diff --git a/eng/Versions.props b/eng/Versions.props
index f3fcd5453467..a4294df9556e 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -16,6 +16,6 @@
2.4.1
2.4.3
- 9.0.0-preview.3.24172.9
+ 9.0.0-rc.1.24431.7
diff --git a/global.json b/global.json
index 2257ba0c98e0..4c1d8ee8cc0e 100644
--- a/global.json
+++ b/global.json
@@ -1,11 +1,11 @@
{
"sdk": {
- "version": "9.0.100-preview.4.24267.66",
+ "version": "9.0.100-rc.1.24452.12",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
- "dotnet": "9.0.100-preview.4.24267.66",
+ "dotnet": "9.0.100-rc.1.24452.12",
"runtimes": {
"dotnet": [
"$(MicrosoftNETCoreAppVersion)"
@@ -13,6 +13,6 @@
}
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24281.1"
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.24474.1"
}
}
diff --git a/src/Swift.Bindings/tests/CryptoKit/CryptoKit.Source.cs b/src/Swift.Bindings/tests/CryptoKit/CryptoKit.Source.cs
new file mode 100644
index 000000000000..264fcdad91c7
--- /dev/null
+++ b/src/Swift.Bindings/tests/CryptoKit/CryptoKit.Source.cs
@@ -0,0 +1,490 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Swift;
+using System.Security.Cryptography;
+
+namespace Test
+{
+ ///
+ /// Represents ChaChaPoly in C#.
+ ///
+ public unsafe struct ChaChaPoly
+ {
+ ///
+ /// Represents Nonce in C#.
+ ///
+ public sealed unsafe class Nonce : IDisposable, ISwiftObject
+ {
+ private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Test.Runtime.GetValueWitnessTable(Metadata))->Size;
+
+ private readonly void* _payload;
+
+ private bool _disposed = false;
+
+ public Nonce()
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+ CryptoKit.PInvoke_ChaChaPoly_Nonce_Init(swiftIndirectResult);
+ }
+
+ public Nonce(Data data)
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+
+ void* metadata = Test.Runtime.GetMetadata(data);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null);
+
+ CryptoKit.PInvoke_ChaChaPoly_Nonce_Init2(swiftIndirectResult, &data, metadata, witnessTable, out SwiftError error);
+
+ if (error.Value != null)
+ {
+ NativeMemory.Free(_payload);
+ throw new CryptographicException();
+ }
+ }
+
+ public void* Payload => _payload;
+
+ public static void* Metadata => CryptoKit.PInvoke_ChaChaPoly_Nonce_GetMetadata();
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ NativeMemory.Free(_payload);
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ ~Nonce()
+ {
+ NativeMemory.Free(_payload);
+ }
+ }
+
+ ///
+ /// Represents SealedBox in C#.
+ ///
+ [StructLayout(LayoutKind.Sequential, Size = 16)]
+ public unsafe struct SealedBox
+ {
+ private readonly Data _combined;
+
+ public SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag)
+ {
+ void* ciphertextMetadata = Test.Runtime.GetMetadata(ciphertext);
+ void* tagMetadata = Test.Runtime.GetMetadata(tag);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* ciphertextWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, ciphertextMetadata, null);
+ void* tagWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, tagMetadata, null);
+
+ this = CryptoKit.PInvoke_ChaChaPoly_SealedBox_Init(
+ nonce.Payload,
+ &ciphertext,
+ &tag,
+ ciphertextMetadata,
+ tagMetadata,
+ ciphertextWitnessTable,
+ tagWitnessTable,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ throw new CryptographicException();
+ }
+ }
+
+ public Data Ciphertext => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetCiphertext(this);
+
+ public Data Tag => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetTag(this);
+ }
+
+ ///
+ /// Encrypts the plaintext using the key, nonce, and authenticated data.
+ ///
+ public static unsafe SealedBox seal(Plaintext plaintext, SymmetricKey key, Nonce nonce, AuthenticateData aad, out SwiftError error) where Plaintext : unmanaged, ISwiftObject where AuthenticateData : unmanaged, ISwiftObject {
+ void* plaintextMetadata = Test.Runtime.GetMetadata(plaintext);
+ void* aadMetadata = Test.Runtime.GetMetadata(aad);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* plaintextWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, plaintextMetadata, null);
+ void* aadWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, aadMetadata, null);
+
+ SealedBox sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal(
+ &plaintext,
+ key.Payload,
+ nonce.Payload,
+ &aad,
+ plaintextMetadata,
+ aadMetadata,
+ plaintextWitnessTable,
+ aadWitnessTable,
+ out error);
+
+ return sealedBox;
+ }
+
+ ///
+ /// Decrypts the sealed box using the key and authenticated data.
+ ///
+ public static unsafe Data open(SealedBox sealedBox, SymmetricKey key, AuthenticateData aad, out SwiftError error) where AuthenticateData : unmanaged, ISwiftObject {
+ void* metadata = Test.Runtime.GetMetadata(aad);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null);
+
+ Data data = CryptoKit.PInvoke_ChaChaPoly_Open(
+ sealedBox,
+ key.Payload,
+ &aad,
+ metadata,
+ witnessTable,
+ out error);
+
+ return data;
+ }
+ }
+
+ ///
+ /// Represents AesGcm in C#.
+ ///
+ public unsafe struct AesGcm
+ {
+ ///
+ /// Represents Nonce in C#.
+ ///
+ public sealed unsafe class Nonce : IDisposable, ISwiftObject
+ {
+ private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Test.Runtime.GetValueWitnessTable(Metadata))->Size;
+
+ private readonly void* _payload;
+
+ private bool _disposed = false;
+
+ public Nonce()
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+ CryptoKit.PInvoke_AesGcm_Nonce_Init(swiftIndirectResult);
+ }
+
+ public Nonce(Data data)
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+
+ void* metadata = Test.Runtime.GetMetadata(data);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null);
+
+ CryptoKit.PInvoke_AesGcm_Nonce_Init2(swiftIndirectResult, &data, metadata, witnessTable, out SwiftError error);
+
+ if (error.Value != null)
+ {
+ NativeMemory.Free(_payload);
+ throw new CryptographicException();
+ }
+ }
+
+ public void* Payload => _payload;
+
+ public static void* Metadata => CryptoKit.PInvoke_AesGcm_Nonce_GetMetadata();
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ NativeMemory.Free(_payload);
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ ~Nonce()
+ {
+ NativeMemory.Free(_payload);
+ }
+ }
+
+ ///
+ /// Represents SealedBox in C#.
+ ///
+ public sealed unsafe class SealedBox : IDisposable, ISwiftObject
+ {
+ private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Test.Runtime.GetValueWitnessTable(Metadata))->Size;
+
+ private readonly void* _payload;
+
+ private bool _disposed = false;
+
+ public SealedBox()
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ }
+
+ public SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag)
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+
+ void* ciphertextMetadata = Test.Runtime.GetMetadata(ciphertext);
+ void* tagMetadata = Test.Runtime.GetMetadata(tag);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* ciphertextWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, ciphertextMetadata, null);
+ void* tagWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, tagMetadata, null);
+
+ CryptoKit.PInvoke_AesGcm_SealedBox_Init(
+ swiftIndirectResult,
+ nonce.Payload,
+ &ciphertext,
+ &tag,
+ ciphertextMetadata,
+ tagMetadata,
+ ciphertextWitnessTable,
+ tagWitnessTable,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ NativeMemory.Free(_payload);
+ throw new CryptographicException();
+ }
+ }
+
+ public void* Payload => _payload;
+
+ public static void* Metadata => CryptoKit.PInvoke_AesGcm_SealedBox_GetMetadata();
+
+ public Data Ciphertext => CryptoKit.PInvoke_AesGcm_SealedBox_GetCiphertext(new SwiftSelf(_payload));
+
+ public Data Tag => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(_payload));
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ NativeMemory.Free(_payload);
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ ~SealedBox()
+ {
+ NativeMemory.Free(_payload);
+ }
+ }
+
+ ///
+ /// Encrypts the plaintext using the key, nonce, and authenticated data.
+ ///
+ public static unsafe SealedBox seal(Plaintext plaintext, SymmetricKey key, Nonce nonce, AuthenticateData aad, out SwiftError error) where Plaintext : unmanaged, ISwiftObject where AuthenticateData : unmanaged, ISwiftObject {
+ AesGcm.SealedBox sealedBox = new AesGcm.SealedBox();
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.Payload);
+
+ void* plaintextMetadata = Test.Runtime.GetMetadata(plaintext);
+ void* aadMetadata = Test.Runtime.GetMetadata(aad);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* plaintextWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, plaintextMetadata, null);
+ void* aadWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, aadMetadata, null);
+
+ CryptoKit.PInvoke_AesGcm_Seal(
+ swiftIndirectResult,
+ &plaintext,
+ key.Payload,
+ nonce.Payload,
+ &aad,
+ plaintextMetadata,
+ aadMetadata,
+ plaintextWitnessTable,
+ aadWitnessTable,
+ out error);
+
+ return sealedBox;
+ }
+
+ ///
+ /// Decrypts the sealed box using the key and authenticated data.
+ ///
+ public static unsafe Data open(SealedBox sealedBox, SymmetricKey key, AuthenticateData aad, out SwiftError error) where AuthenticateData : unmanaged, ISwiftObject {
+ void* metadata = Test.Runtime.GetMetadata(aad);
+ void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor;
+ void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null);
+
+ Data data = CryptoKit.PInvoke_AesGcm_Open(
+ sealedBox.Payload,
+ key.Payload,
+ &aad,
+ metadata,
+ witnessTable,
+ out error);
+
+ return data;
+ }
+ }
+
+ ///
+ /// Represents SymmetricKey in C#.
+ ///
+ public sealed unsafe class SymmetricKey : IDisposable, ISwiftObject
+ {
+ private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Test.Runtime.GetValueWitnessTable(Metadata))->Size;
+
+ public readonly void* _payload;
+
+ private bool _disposed = false;
+
+ public SymmetricKey(SymmetricKeySize symmetricKeySize)
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+ CryptoKit.PInvoke_SymmetricKey_Init(swiftIndirectResult, &symmetricKeySize);
+ }
+
+ public SymmetricKey(Data data)
+ {
+ _payload = NativeMemory.Alloc(PayloadSize);
+ SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload);
+
+ void* metadata = Test.Runtime.GetMetadata(data);
+ void* conformanceDescriptor = IContiguousBytes.GetConformanceDescriptor;
+ void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null);
+
+ CryptoKit.PInvoke_SymmetricKey_Init2(swiftIndirectResult, &data, metadata, witnessTable);
+ }
+
+ public void* Payload => _payload;
+
+ public static void* Metadata => CryptoKit.PInvoke_SymmetricKey_GetMetadata();
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ NativeMemory.Free(_payload);
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ ~SymmetricKey()
+ {
+ NativeMemory.Free(_payload);
+ }
+ }
+
+ ///
+ /// Represents SymmetricKeySize in C#.
+ ///
+ [StructLayout(LayoutKind.Sequential, Size = 8)]
+ public unsafe struct SymmetricKeySize
+ {
+ private readonly nint _bitCount;
+
+ public SymmetricKeySize(nint bitCount)
+ {
+ SymmetricKeySize instance;
+ CryptoKit.PInvoke_init(new SwiftIndirectResult(&instance), bitCount);
+ this = instance;
+ }
+ }
+
+ ///
+ /// Swift CryptoKit PInvoke methods in C#.
+ ///
+ public static class CryptoKit
+ {
+ public const string Path = "/System/Library/Frameworks/CryptoKit.framework/CryptoKit";
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO5NonceVAEycfC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_ChaChaPoly_Nonce_Init(SwiftIndirectResult result);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO5NonceV4dataAEx_tKc10Foundation12DataProtocolRzlufC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_ChaChaPoly_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVMa")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_ChaChaPoly_Nonce_GetMetadata();
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV10ciphertext10Foundation4DataVvg")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_ChaChaPoly_SealedBox_GetCiphertext(ChaChaPoly.SealedBox sealedBox);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV3tag10Foundation4DataVvg")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_ChaChaPoly_SealedBox_GetTag(ChaChaPoly.SealedBox sealedBox);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV5nonce10ciphertext3tagAeC5NonceV_xq_tKc10Foundation12DataProtocolRzAkLR_r0_lufC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern ChaChaPoly.SealedBox PInvoke_ChaChaPoly_SealedBox_Init(void* nonce, void* ciphertext, void* tag, void* ciphertextMetadata, void* tagMetadata, void* ciphertextWitnessTable, void* tagWitnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVAGycfC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_AesGcm_Nonce_Init(SwiftIndirectResult result);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceV4dataAGx_tKc10Foundation12DataProtocolRzlufC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_AesGcm_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVMa")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_AesGcm_Nonce_GetMetadata();
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxVMa")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_AesGcm_SealedBox_GetMetadata();
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV10ciphertext10Foundation4DataVvg")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_AesGcm_SealedBox_GetCiphertext(SwiftSelf sealedBox);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV3tag10Foundation4DataVvg")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_AesGcm_SealedBox_GetTag(SwiftSelf sealedBox);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV5nonce10ciphertext3tagAgE5NonceV_xq_tKc10Foundation12DataProtocolRzAmNR_r0_lufC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_AesGcm_SealedBox_Init(SwiftIndirectResult result, void* nonce, void* ciphertext, void* tag, void* ciphertextMetadata, void* tagMetadata, void* ciphertextWitnessTable, void* tagWitnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4sizeAcA0cD4SizeV_tcfC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_SymmetricKey_Init(SwiftIndirectResult result, SymmetricKeySize* symmetricKeySize);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4dataACx_tc10Foundation15ContiguousBytesRzlufC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_SymmetricKey_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyVMa")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_SymmetricKey_GetMetadata();
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit16SymmetricKeySizeV8bitCountACSi_tcfC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_init(SwiftIndirectResult result, nint bitCount);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4seal_5using5nonce14authenticatingAC9SealedBoxVx_AA12SymmetricKeyVAC5NonceVSgq_tK10Foundation12DataProtocolRzAoPR_r0_lFZ")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern ChaChaPoly.SealedBox PInvoke_ChaChaPoly_Seal(void* plaintext, void* key, void* nonce, void* aad, void* plaintextMetadata, void* aadMetadata, void* plaintextWitnessTable, void* aadWitnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4open_5using14authenticating10Foundation4DataVAC9SealedBoxV_AA12SymmetricKeyVxtKAG0I8ProtocolRzlFZ")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_ChaChaPoly_Open(ChaChaPoly.SealedBox sealedBox, void* key, void* aad, void* metadata, void* witnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4seal_5using5nonce14authenticatingAE9SealedBoxVx_AA12SymmetricKeyVAE5NonceVSgq_tK10Foundation12DataProtocolRzAqRR_r0_lFZ")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_AesGcm_Seal(SwiftIndirectResult result, void* plaintext, void* key, void* nonce, void* aad, void* plaintextMetadata, void* aadMetadata, void* plaintextWitnessTable, void* aadWitnessTable, out SwiftError error);
+
+ [DllImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4open_5using14authenticating10Foundation4DataVAE9SealedBoxV_AA12SymmetricKeyVxtKAI0I8ProtocolRzlFZ")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_AesGcm_Open(void* sealedBox, void* key, void* aad, void* metadata, void* witnessTable, out SwiftError error);
+ }
+}
diff --git a/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.Source.cs b/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.Source.cs
new file mode 100644
index 000000000000..e8ae308ecb65
--- /dev/null
+++ b/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.Source.cs
@@ -0,0 +1,247 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Swift;
+using System.Security.Cryptography;
+using System.Diagnostics;
+using AesGcm = Test.AesGcm;
+
+namespace Test
+{
+ public class MainClass
+ {
+ public static unsafe void AesGcmEncrypt(
+ ReadOnlySpan key,
+ ReadOnlySpan nonce,
+ ReadOnlySpan plaintext,
+ Span ciphertext,
+ Span tag,
+ ReadOnlySpan aad)
+ {
+ fixed (void* keyPtr = key)
+ fixed (void* noncePtr = nonce)
+ fixed (void* plaintextPtr = plaintext)
+ fixed (byte* ciphertextPtr = ciphertext)
+ fixed (byte* tagPtr = tag)
+ fixed (void* aadPtr = aad)
+ {
+ Data symmetricKeyData = new Data(keyPtr, key.Length);
+ SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData);
+
+ Data nonceData = new Data(noncePtr, nonce.Length);
+ AesGcm.Nonce aesGcmNonce = new AesGcm.Nonce(nonceData);
+
+ Data plaintextData = new Data(plaintextPtr, plaintext.Length);
+ Data aadData = new Data(aadPtr, aad.Length);
+
+ AesGcm.SealedBox sealedBox = AesGcm.seal(
+ plaintextData,
+ symmetricKey,
+ aesGcmNonce,
+ aadData,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ sealedBox.Dispose();
+ aesGcmNonce.Dispose();
+ symmetricKey.Dispose();
+
+ throw new CryptographicException();
+ }
+
+ Data resultCiphertext = sealedBox.Ciphertext;
+ Data resultTag = sealedBox.Tag;
+
+ resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count);
+ resultTag.CopyBytes(tagPtr, resultTag.Count);
+ }
+ }
+
+ public static unsafe void AesGcmDecrypt(
+ ReadOnlySpan key,
+ ReadOnlySpan nonce,
+ ReadOnlySpan ciphertext,
+ ReadOnlySpan tag,
+ Span plaintext,
+ ReadOnlySpan aad)
+ {
+ fixed (void* keyPtr = key)
+ fixed (void* noncePtr = nonce)
+ fixed (byte* ciphertextPtr = ciphertext)
+ fixed (byte* tagPtr = tag)
+ fixed (byte* plaintextPtr = plaintext)
+ fixed (void* aadPtr = aad)
+ {
+ Data symmetricKeyData = new Data(keyPtr, key.Length);
+ SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData);
+
+ Data nonceData = new Data(noncePtr, nonce.Length);
+ AesGcm.Nonce aesGcmNonce = new AesGcm.Nonce(nonceData);
+
+ Data ciphertextData = new Data(ciphertextPtr, ciphertext.Length);
+ Data tagData = new Data(tagPtr, tag.Length);
+ Data aadData = new Data(aadPtr, aad.Length);
+
+ AesGcm.SealedBox sealedBox = new AesGcm.SealedBox(aesGcmNonce, ciphertextData, tagData);
+
+ Data data = AesGcm.open(
+ sealedBox,
+ symmetricKey,
+ aadData,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ sealedBox.Dispose();
+ aesGcmNonce.Dispose();
+ symmetricKey.Dispose();
+
+ throw new CryptographicException();
+ }
+
+ data.CopyBytes(plaintextPtr, data.Count);
+ }
+ }
+
+ public static unsafe void ChaCha20Poly1305Encrypt(
+ ReadOnlySpan key,
+ ReadOnlySpan nonce,
+ ReadOnlySpan plaintext,
+ Span ciphertext,
+ Span tag,
+ ReadOnlySpan aad)
+ {
+ fixed (void* keyPtr = key)
+ fixed (void* noncePtr = nonce)
+ fixed (byte* ciphertextPtr = ciphertext)
+ fixed (byte* tagPtr = tag)
+ fixed (byte* plaintextPtr = plaintext)
+ fixed (void* aadPtr = aad)
+ {
+ Data symmetricKeyData = new Data(keyPtr, key.Length);
+ SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData);
+
+ Data nonceData = new Data(noncePtr, nonce.Length);
+ ChaChaPoly.Nonce chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData);
+
+ Data plaintextData = new Data(plaintextPtr, plaintext.Length);
+ Data aadData = new Data(aadPtr, aad.Length);
+
+ ChaChaPoly.SealedBox sealedBox = ChaChaPoly.seal(
+ plaintextData,
+ symmetricKey,
+ chaChaPolyNonce,
+ aadData,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ chaChaPolyNonce.Dispose();
+ symmetricKey.Dispose();
+
+ throw new CryptographicException();
+ }
+
+ Data resultCiphertext = sealedBox.Ciphertext;
+ Data resultTag = sealedBox.Tag;
+
+ resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count);
+ resultTag.CopyBytes(tagPtr, resultTag.Count);
+ }
+ }
+
+ public static unsafe void ChaCha20Poly1305Decrypt(
+ ReadOnlySpan key,
+ ReadOnlySpan nonce,
+ ReadOnlySpan ciphertext,
+ ReadOnlySpan tag,
+ Span plaintext,
+ ReadOnlySpan aad)
+ {
+ fixed (void* keyPtr = key)
+ fixed (void* noncePtr = nonce)
+ fixed (byte* ciphertextPtr = ciphertext)
+ fixed (byte* tagPtr = tag)
+ fixed (byte* plaintextPtr = plaintext)
+ fixed (void* aadPtr = aad)
+ {
+ Data symmetricKeyData = new Data(keyPtr, key.Length);
+ SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData);
+
+ Data nonceData = new Data(noncePtr, nonce.Length);
+ ChaChaPoly.Nonce chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData);
+
+ Data ciphertextData = new Data(ciphertextPtr, ciphertext.Length);
+ Data tagData = new Data(tagPtr, tag.Length);
+ Data aadData = new Data(aadPtr, aad.Length);
+
+ ChaChaPoly.SealedBox sealedBox = new ChaChaPoly.SealedBox(chaChaPolyNonce, ciphertextData, tagData);
+
+ Data data = ChaChaPoly.open(
+ sealedBox,
+ symmetricKey,
+ aadData,
+ out SwiftError error);
+
+ if (error.Value != null)
+ {
+ chaChaPolyNonce.Dispose();
+ symmetricKey.Dispose();
+
+ CryptographicOperations.ZeroMemory(plaintext);
+ throw new CryptographicException();
+ }
+
+ data.CopyBytes(plaintextPtr, data.Count);
+ }
+ }
+
+ private const int KeySizeInBytes = 256 / 8;
+ private const int NonceSizeInBytes = 96 / 8;
+ private const int TagSizeInBytes = 128 / 8;
+ public static int Main(string[] args)
+ {
+ const int dataLength = 35;
+ byte[] plaintext = Enumerable.Range(1, dataLength).Select(x => (byte)x).ToArray();
+ byte[] ciphertext = new byte[dataLength];
+ byte[] key = RandomNumberGenerator.GetBytes(KeySizeInBytes);
+ byte[] nonce = RandomNumberGenerator.GetBytes(NonceSizeInBytes);
+ byte[] tag = new byte[TagSizeInBytes];
+ byte[] decrypted = new byte[dataLength];
+
+ ChaCha20Poly1305Encrypt(key, nonce, plaintext, ciphertext, tag, default);
+ ChaCha20Poly1305Decrypt(key, nonce, ciphertext, tag, decrypted, default);
+
+ if (!plaintext.SequenceEqual(decrypted))
+ {
+ Console.WriteLine("ChaChaPoly decryption failed");
+ return 1;
+ }
+ else
+ {
+ Console.WriteLine("ChaChaPoly decryption succeeded");
+ }
+
+ decrypted = new byte[dataLength];
+ AesGcmEncrypt(key, nonce, plaintext, ciphertext, tag, default);
+
+ AesGcmDecrypt(key, nonce, ciphertext, tag, decrypted, default);
+
+ if (!plaintext.SequenceEqual(decrypted))
+ {
+ Console.WriteLine("AES-GCM decryption failed");
+ return 1;
+ }
+ else
+ {
+ Console.WriteLine("AES-GCM decryption succeeded");
+ }
+
+ return 0;
+ }
+ }
+}
diff --git a/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.cs b/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.cs
new file mode 100644
index 000000000000..48dfcf164e47
--- /dev/null
+++ b/src/Swift.Bindings/tests/CryptoKit/CryptoKitTests.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Xunit;
+
+namespace BindingsGeneration.Tests
+{
+ public class CryptoKitTests: IClassFixture
+ {
+ private readonly TestFixture _fixture;
+ private static string _assemblyPath;
+
+ public CryptoKitTests(TestFixture fixture)
+ {
+ _fixture = fixture;
+ }
+
+ public class TestFixture
+ {
+ static TestFixture()
+ {
+ InitializeResources();
+ }
+
+ private static void InitializeResources()
+ {
+ _assemblyPath = TestsHelper.Compile(
+ new string [] { "CryptoKit/*.cs" },
+ new string [] { },
+ new string [] { "System.Security.Cryptography" });
+ }
+ }
+
+ [Fact]
+ public static void TestUnsafePointerCryptoKit()
+ {
+ int result = (int)TestsHelper.Execute(_assemblyPath, "Test.MainClass", "Main", new object [] { new string[0] });
+ Assert.Equal(0, result);
+ }
+ }
+}
diff --git a/src/Swift.Bindings/tests/CryptoKit/Foundation.Source.cs b/src/Swift.Bindings/tests/CryptoKit/Foundation.Source.cs
new file mode 100644
index 000000000000..b8048aee29a2
--- /dev/null
+++ b/src/Swift.Bindings/tests/CryptoKit/Foundation.Source.cs
@@ -0,0 +1,274 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+namespace Test
+{
+ ///
+ /// Represents a Swift type in C#.
+ ///
+ public unsafe interface ISwiftObject
+ {
+ public static abstract void* Metadata { get; }
+ }
+
+ //
+ // Represents Swift UnsafePointer in C#.
+ //
+ public readonly unsafe struct UnsafePointer where T : unmanaged
+ {
+ private readonly T* _pointee;
+ public UnsafePointer(T* pointee)
+ {
+ this._pointee = pointee;
+ }
+
+ public T* Pointee => _pointee;
+
+ public static implicit operator T*(UnsafePointer pointer) => pointer.Pointee;
+
+ public static implicit operator UnsafePointer(T* pointee) => new(pointee);
+ }
+
+ //
+ // Represents Swift UnsafeMutablePointer in C#.
+ //
+ public readonly unsafe struct UnsafeMutablePointer where T : unmanaged
+ {
+ private readonly T* _pointee;
+ public UnsafeMutablePointer(T* pointee)
+ {
+ _pointee = pointee;
+ }
+
+ public T* Pointee => _pointee;
+
+ public static implicit operator T*(UnsafeMutablePointer pointer) => pointer.Pointee;
+
+ public static implicit operator UnsafeMutablePointer(T* pointee) => new(pointee);
+ }
+
+ //
+ // Represents Swift UnsafeRawPointer in C#.
+ //
+ public readonly unsafe struct UnsafeRawPointer
+ {
+ private readonly void* _pointee;
+ public UnsafeRawPointer(void* pointee)
+ {
+ _pointee = pointee;
+ }
+
+ public void* Pointee => _pointee;
+
+ public static implicit operator void*(UnsafeRawPointer pointer) => pointer.Pointee;
+
+ public static implicit operator UnsafeRawPointer(void* pointee) => new(pointee);
+ }
+
+ //
+ // Represents Swift UnsafeMutableRawPointer in C#.
+ //
+ public readonly unsafe struct UnsafeMutableRawPointer
+ {
+ private readonly void* _pointee;
+ public UnsafeMutableRawPointer(void* pointee)
+ {
+ _pointee = pointee;
+ }
+
+ public void* Pointee => _pointee;
+
+ public static implicit operator void*(UnsafeMutableRawPointer pointer) => pointer.Pointee;
+
+ public static implicit operator UnsafeMutableRawPointer(void* pointee) => new(pointee);
+ }
+
+ //
+ // Represents Swift UnsafeBufferPointer in C#.
+ //
+ public readonly unsafe struct UnsafeBufferPointer where T : unmanaged
+ {
+ private readonly T* _baseAddress;
+ private readonly nint _count;
+ public UnsafeBufferPointer(T* baseAddress, nint count)
+ {
+ _baseAddress = baseAddress;
+ _count = count;
+ }
+
+ public T* BaseAddress => _baseAddress;
+ public nint Count => _count;
+ }
+
+ //
+ // Represents Swift UnsafeMutableBufferPointer in C#.
+ //
+ public readonly unsafe struct UnsafeMutableBufferPointer where T : unmanaged
+ {
+ private readonly T* _baseAddress;
+ private readonly nint _count;
+ public UnsafeMutableBufferPointer(T* baseAddress, nint count)
+ {
+ _baseAddress = baseAddress;
+ _count = count;
+ }
+
+ public T* BaseAddress => _baseAddress;
+ public nint Count => _count;
+ }
+
+ //
+ // Represents Swift Foundation.Data in C#.
+ //
+ [StructLayout(LayoutKind.Sequential, Size = 16)]
+ [InlineArray(16)]
+ public unsafe struct Data : ISwiftObject
+ {
+ private byte _payload;
+
+ public unsafe Data(UnsafeRawPointer pointer, nint count)
+ {
+ this = Foundation.PInvoke_Data_InitWithBytes(pointer, count);
+ }
+
+ public byte Payload => _payload;
+
+ public readonly nint Count => Foundation.PInvoke_Data_GetCount(this);
+
+ public unsafe void CopyBytes(UnsafeMutablePointer buffer, nint count)
+ {
+ Foundation.PInvoke_Data_CopyBytes(buffer, count, this);
+ }
+
+ public static void* Metadata => Foundation.PInvoke_Data_GetMetadata();
+ }
+
+ ///
+ /// Represents Swift Foundation.DataProtocol in C#.
+ ///
+ public unsafe interface IDataProtocol
+ {
+ public static void* GetConformanceDescriptor => Runtime.GetConformanceDescriptor("$s10Foundation4DataVAA0B8ProtocolAAMc");
+ }
+
+ ///
+ /// Represents Swift Foundation.ContiguousBytes in C#.
+ ///
+ public unsafe interface IContiguousBytes
+ {
+ public static void* GetConformanceDescriptor => Runtime.GetConformanceDescriptor("$s10Foundation4DataVAA15ContiguousBytesAAMc");
+ }
+
+ ///
+ /// Swift Foundation PInvoke methods in C#.
+ ///
+ public static class Foundation
+ {
+ public const string Path = "/System/Library/Frameworks/Foundation.framework/Foundation";
+
+ [DllImport(Path, EntryPoint = "$s10Foundation4DataV5bytes5countACSV_SitcfC")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern Data PInvoke_Data_InitWithBytes(UnsafeRawPointer pointer, nint count);
+
+ [DllImport(Path, EntryPoint = "$s10Foundation4DataV5countSivg")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern nint PInvoke_Data_GetCount(Data data);
+
+ [DllImport(Path, EntryPoint = "$s10Foundation4DataV9copyBytes2to5countySpys5UInt8VG_SitF")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void PInvoke_Data_CopyBytes(UnsafeMutablePointer buffer, nint count, Data data);
+
+ [DllImport(Path, EntryPoint = "swift_getWitnessTable")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_Swift_GetWitnessTable(void* conformanceDescriptor, void* typeMetadata, void* instantiationArgs);
+
+ [DllImport(Path, EntryPoint = "$s10Foundation4DataVMa")]
+ [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])]
+ public static unsafe extern void* PInvoke_Data_GetMetadata();
+ }
+
+ ///
+ /// Swift runtime helper methods in C#.
+ ///
+ public static class Runtime
+ {
+ ///
+ /// https://github.com/apple/swift/blob/main/include/swift/ABI/MetadataValues.h#L117
+ ///
+ [Flags]
+ public enum ValueWitnessFlags
+ {
+ AlignmentMask = 0x0000FFFF,
+ IsNonPOD = 0x00010000,
+ IsNonInline = 0x00020000,
+ HasSpareBits = 0x00080000,
+ IsNonBitwiseTakable = 0x00100000,
+ HasEnumWitnesses = 0x00200000,
+ Incomplete = 0x00400000,
+ }
+
+ ///
+ /// See https://github.com/apple/swift/blob/main/include/swift/ABI/ValueWitness.def
+ ///
+ [StructLayout (LayoutKind.Sequential)]
+ public ref struct ValueWitnessTable
+ {
+ public IntPtr InitializeBufferWithCopyOfBuffer;
+ public IntPtr Destroy;
+ public IntPtr InitWithCopy;
+ public IntPtr AssignWithCopy;
+ public IntPtr InitWithTake;
+ public IntPtr AssignWithTake;
+ public IntPtr GetEnumTagSinglePayload;
+ public IntPtr StoreEnumTagSinglePayload;
+ private IntPtr _Size;
+ private IntPtr _Stride;
+ public ValueWitnessFlags Flags;
+ public uint ExtraInhabitantCount;
+ public int Size => _Size.ToInt32();
+ public int Stride => _Stride.ToInt32();
+ public int Alignment => (int)((Flags & ValueWitnessFlags.AlignmentMask) + 1);
+ public bool IsNonPOD => Flags.HasFlag (ValueWitnessFlags.IsNonPOD);
+ public bool IsNonBitwiseTakable => Flags.HasFlag (ValueWitnessFlags.IsNonBitwiseTakable);
+ public bool HasExtraInhabitants => ExtraInhabitantCount != 0;
+ }
+
+ public static unsafe void* GetMetadata(T type) where T: ISwiftObject
+ {
+ return T.Metadata;
+ }
+
+ public static unsafe void* GetValueWitnessTable(void* metadata)
+ {
+ void* valueWitnessTable = (void*)Marshal.ReadIntPtr((IntPtr)metadata, -IntPtr.Size);
+ return valueWitnessTable;
+ }
+
+ public static unsafe void* GetConformanceDescriptor(string symbol)
+ {
+ IntPtr handle = IntPtr.Zero;
+ try
+ {
+ handle = NativeLibrary.Load(Foundation.Path);
+ void* conformanceDescriptor = NativeLibrary.GetExport(handle, symbol).ToPointer();
+ return conformanceDescriptor;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"Failed to get conformance descriptor for symbol: {symbol}", ex);
+ }
+ finally
+ {
+ if (handle != IntPtr.Zero)
+ {
+ NativeLibrary.Free(handle);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Swift.Bindings/tests/TestsHelper.cs b/src/Swift.Bindings/tests/TestsHelper.cs
index 2896a5b00e27..50899b4781a1 100644
--- a/src/Swift.Bindings/tests/TestsHelper.cs
+++ b/src/Swift.Bindings/tests/TestsHelper.cs
@@ -26,6 +26,7 @@ public static string Compile(string[] filePaths, string[] sourceCodes, string[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location),
MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
MetadataReference.CreateFromFile(Assembly.Load("System.Runtime.InteropServices").Location),
};