From c7ab93fba64bd92c19a997477d593939fc9daf28 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 27 Sep 2024 12:12:44 +0200 Subject: [PATCH 1/9] Add C# CryptoKit bindings and remove Swift wrapper --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 274 ++++++++++++++++++ .../OSX/Swift.Runtime/DynamicLibraryLoader.cs | 31 ++ .../Interop/OSX/Swift.Runtime/Foundation.cs | 217 ++++++++++++++ .../OSX/Swift.Runtime/UnsafeBufferPointer.cs | 39 --- .../Interop.Aead.cs | 186 +++++++----- .../src/System.Security.Cryptography.csproj | 8 +- .../entrypoints.c | 4 - .../pal_swiftbindings.h | 4 - .../pal_swiftbindings.swift | 176 ----------- 9 files changed, 642 insertions(+), 297 deletions(-) create mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs create mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs create mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs delete mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs new file mode 100644 index 0000000000000..4318d20017394 --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -0,0 +1,274 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Swift; + +#pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant +#pragma warning disable SYSLIB1051 + +namespace Swift.Runtime +{ + /// + /// Represents ChaChaPoly in C#. + /// + internal unsafe partial struct ChaChaPoly + { + /// + /// Represents Nonce in C#. + /// + internal sealed unsafe partial class Nonce + { + private const int _payloadSize = 16; + internal void* payload; + + internal Nonce() + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + CryptoKit.PInvoke_ChaChaPoly_Nonce_Init(swiftIndirectResult); + } + + internal Nonce(Data data) + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + void* dataPtr = &data; + + CryptoKit.PInvoke_ChaChaPoly_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); + + if (error.Value != null) // Should throw when nonce is not 12 bytes + { + throw new Exception(); + } + } + + ~Nonce() + { + Marshal.FreeHGlobal(new IntPtr(payload)); + } + } + + /// + /// Represents SealedBox in C#. + /// + [StructLayout(LayoutKind.Sequential, Size = 16)] + internal unsafe partial struct SealedBox + { + internal Data combined; + internal readonly Data Ciphertext { get => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetCiphertext(this); } + internal readonly Data Tag { get => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetTag(this); } + + internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) + { + void* tagPtr = &tag; + void* ciphertextPtr = &ciphertext; + this = CryptoKit.PInvoke_ChaChaPoly_SealedBox_Init(nonce.payload, ciphertextPtr, tagPtr, ciphertext.Metadata(), tag.Metadata(), default(DataProtocol).WitnessTable(ciphertext), default(DataProtocol).WitnessTable(tag), out SwiftError error); + + if (error.Value != null) + { + throw new Exception(); + } + } + } + } + + /// + /// Represents AesGcm in C#. + /// + internal unsafe partial struct AesGcm + { + /// + /// Represents Nonce in C#. + /// + internal sealed unsafe partial class Nonce + { + private const int _payloadSize = 16; + internal void* payload; + + internal Nonce() + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + CryptoKit.PInvoke_AesGcm_Nonce_Init(swiftIndirectResult); + } + + internal Nonce(Data data) + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + void* dataPtr = &data; + CryptoKit.PInvoke_AesGcm_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); + + if (error.Value != null) // Should throw when nonce is not 12 bytes + { + throw new Exception(); + } + } + + ~Nonce() + { + Marshal.FreeHGlobal(new IntPtr(payload)); + } + } + + /// + /// Represents SealedBox in C#. + /// + internal sealed unsafe partial class SealedBox + { + private const int _payloadSize = 24; + internal void* payload; + public Data Ciphertext { get => CryptoKit.PInvoke_AesGcm_SealedBox_GetCiphertext(new SwiftSelf(payload)); } + public Data Tag { get => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(payload)); } + internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + void* tagPtr = &tag; + void* ciphertextPtr = &ciphertext; + + CryptoKit.PInvoke_AesGcm_SealedBox_Init(swiftIndirectResult, nonce.payload, ciphertextPtr, tagPtr, ciphertext.Metadata(), tag.Metadata(), default(DataProtocol).WitnessTable(ciphertext), default(DataProtocol).WitnessTable(tag), out SwiftError error); + + if (error.Value != null) + { + throw new Exception(); + } + } + + internal SealedBox() + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + } + + ~SealedBox() + { + Marshal.FreeHGlobal(new IntPtr(payload)); + } + } + } + + /// + /// Represents SymmetricKey in C#. + /// + internal sealed unsafe partial class SymmetricKey + { + private const int _payloadSize = 8; + internal void* payload; + + internal SymmetricKey(SymmetricKeySize symmetricKeySize) + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + CryptoKit.PInvoke_SymmetricKey_Init(swiftIndirectResult, &symmetricKeySize); + } + + internal SymmetricKey(Data data) + { + payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + void* dataPtr = &data; + CryptoKit.PInvoke_SymmetricKey_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(ContiguousBytes).WitnessTable(data)); + } + + ~SymmetricKey() + { + Marshal.FreeHGlobal(new IntPtr(payload)); + } + } + + /// + /// Represents SymmetricKeySize in C#. + /// + [StructLayout(LayoutKind.Sequential, Size = 8)] + internal unsafe partial struct SymmetricKeySize + { + internal const string AppleCryptoKit = "/System/Library/Frameworks/CryptoKit.framework/CryptoKit"; + internal nint bitCount; + + [LibraryImport(AppleCryptoKit, EntryPoint = "$s9CryptoKit16SymmetricKeySizeV8bitCountACSi_tcfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_init(SwiftIndirectResult result, nint bitCount); + internal SymmetricKeySize(nint bitCount) + { + SymmetricKeySize instance; + PInvoke_init(new SwiftIndirectResult(&instance), bitCount); + this = instance; + } + } + + /// + /// Swift CryptoKit PInvoke methods in C#. + /// + internal static partial class CryptoKit + { + internal const string Path = "/System/Library/Frameworks/CryptoKit.framework/CryptoKit"; + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO5NonceVAEycfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_ChaChaPoly_Nonce_Init(SwiftIndirectResult result); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO5NonceV4dataAEx_tKc10Foundation12DataProtocolRzlufC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_ChaChaPoly_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV10ciphertext10Foundation4DataVvg")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_ChaChaPoly_SealedBox_GetCiphertext(ChaChaPoly.SealedBox sealedBox); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV3tag10Foundation4DataVvg")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_ChaChaPoly_SealedBox_GetTag(ChaChaPoly.SealedBox sealedBox); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV5nonce10ciphertext3tagAeC5NonceV_xq_tKc10Foundation12DataProtocolRzAkLR_r0_lufC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_SealedBox_Init(void* nonce, void* ciphertext, void* tag, void* metadata1, void* metadata2, void* witnessTable1, void*witnessTable2, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVAGycfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_AesGcm_Nonce_Init(SwiftIndirectResult result); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceV4dataAGx_tKc10Foundation12DataProtocolRzlufC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_AesGcm_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV10ciphertext10Foundation4DataVvg")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_AesGcm_SealedBox_GetCiphertext(SwiftSelf sealedBox); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV3tag10Foundation4DataVvg")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_AesGcm_SealedBox_GetTag(SwiftSelf sealedBox); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV5nonce10ciphertext3tagAgE5NonceV_xq_tKc10Foundation12DataProtocolRzAmNR_r0_lufC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_AesGcm_SealedBox_Init(SwiftIndirectResult result, void* nonce, void* ciphertext, void* tag, void* metadata1, void* metadata2, void* witnessTable1, void*witnessTable2, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4sizeAcA0cD4SizeV_tcfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_SymmetricKey_Init(SwiftIndirectResult result, SymmetricKeySize* symmetricKeySize); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4dataACx_tc10Foundation15ContiguousBytesRzlufC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_SymmetricKey_Init2(SwiftIndirectResult result, void* data, void* md, void* pwt); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4seal_5using5nonce14authenticatingAC9SealedBoxVx_AA12SymmetricKeyVAC5NonceVSgq_tK10Foundation12DataProtocolRzAoPR_r0_lFZ")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_Seal(void* messagePtr, void* key, void* nonce, void* authenticatedData, void* metadata1, void* metadata2, void* witnessTable1, void* witnessTable2, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4open_5using14authenticating10Foundation4DataVAC9SealedBoxV_AA12SymmetricKeyVxtKAG0I8ProtocolRzlFZ")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_ChaChaPoly_Open(ChaChaPoly.SealedBox sealedBox, void* key, void* authenticatedData, void* metadata, void* witnessTable, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4seal_5using5nonce14authenticatingAE9SealedBoxVx_AA12SymmetricKeyVAE5NonceVSgq_tK10Foundation12DataProtocolRzAqRR_r0_lFZ")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_AesGcm_Seal(SwiftIndirectResult result, void* messagePtr, void* key, void* nonce, void* authenticatedData, void* metadata1, void* metadata2, void* witnessTable1, void* witnessTable2, out SwiftError error); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4open_5using14authenticating10Foundation4DataVAE9SealedBoxV_AA12SymmetricKeyVxtKAI0I8ProtocolRzlFZ")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_AesGcm_Open(void* sealedBox, void* key, void* authenticatedData, void* metadata, void* witnessTable, out SwiftError error); + } +} diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs new file mode 100644 index 0000000000000..77f741b7a38bd --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Swift.Runtime +{ + // + // Represents dynamic library loader in C#. + // + internal static partial class DynamicLibraryLoader + { + public const int RTLD_LAZY = 0x1; + public const int RTLD_NOW = 0x2; + + [LibraryImport("libdl.dylib")] + internal static partial IntPtr dlopen([MarshalAs(UnmanagedType.LPStr)] string path, int mode); + + [LibraryImport("libdl.dylib")] + internal static partial IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string symbol); + + [LibraryImport("libdl.dylib")] + internal static partial int dlclose(IntPtr handle); + + [LibraryImport("libdl.dylib")] + internal static partial IntPtr dlerror(); + } +} diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs new file mode 100644 index 0000000000000..5c53ee49a46c0 --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -0,0 +1,217 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant +#pragma warning disable SYSLIB1051 + +namespace Swift.Runtime +{ + /// + /// Represents a Swift type in C#. + /// + internal unsafe interface ISwiftType + { + public abstract void* Metadata(); + } + + /// + /// Represents a Swift protocol in C#. + /// + internal unsafe interface ISwiftProtocol + { + public abstract void* WitnessTable(ISwiftType type); + } + // + // Represents Swift UnsafePointer in C#. + // + internal 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#. + // + internal 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#. + // + internal 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#. + // + internal 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#. + // + internal 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#. + // + internal 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)] + internal unsafe partial struct Data : ISwiftType + { + private static void* metadata = Foundation.PInvoke_Data_GetMetadata(); + internal byte payload; + + internal unsafe Data(UnsafeRawPointer pointer, nint count) + { + this = Foundation.PInvoke_Data_InitWithBytes(pointer, count); + } + + internal readonly nint Count => Foundation.PInvoke_Data_GetCount(this); + + internal unsafe void CopyBytes(UnsafeMutablePointer buffer, nint count) + { + Foundation.PInvoke_Data_CopyBytes(buffer, count, this); + } + + public void* Metadata() => metadata; + } + + /// + /// Represents Swift Foundation.DataProtocol in C#. + /// + internal unsafe partial struct DataProtocol : ISwiftProtocol + { + public void* WitnessTable(ISwiftType type) + { + return Foundation.GetProtocolWitnessTable(type.Metadata(), "$s10Foundation4DataVAA0B8ProtocolAAMc"); + } + } + + /// + /// Represents Swift Foundation.ContiguousBytes in C#. + /// + internal unsafe partial struct ContiguousBytes : ISwiftProtocol + { + public void* WitnessTable(ISwiftType type) + { + return Foundation.GetProtocolWitnessTable(type.Metadata(), "$s10Foundation4DataVAA15ContiguousBytesAAMc"); + } + } + + /// + /// Swift Foundation PInvoke methods in C#. + /// + internal static partial class Foundation + { + internal const string Path = "/System/Library/Frameworks/Foundation.framework/Foundation"; + + [LibraryImport(Path, EntryPoint = "$s10Foundation4DataV5bytes5countACSV_SitcfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial Data PInvoke_Data_InitWithBytes(UnsafeRawPointer pointer, nint count); + + [LibraryImport(Path, EntryPoint = "$s10Foundation4DataV5countSivg")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial nint PInvoke_Data_GetCount(Data data); + + [LibraryImport(Path, EntryPoint = "$s10Foundation4DataV9copyBytes2to5countySpys5UInt8VG_SitF")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_Data_CopyBytes(UnsafeMutablePointer buffer, nint count, Data data); + + [LibraryImport(Path, EntryPoint = "swift_getWitnessTable")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_Swift_GetWitnessTable(void* conformanceDescriptor, void* typeMetadata, void* instantiationArgs); + + [LibraryImport(Path, EntryPoint = "$s10Foundation4DataVMa")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_Data_GetMetadata(); + + internal static unsafe void* GetProtocolWitnessTable(void* metadata, string conformanceDescriptorSymbol) + { + IntPtr handle = DynamicLibraryLoader.dlopen(Path, DynamicLibraryLoader.RTLD_NOW); + void* conformanceDescriptor = DynamicLibraryLoader.dlsym(handle, conformanceDescriptorSymbol).ToPointer(); + void* witnessTable = PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); + DynamicLibraryLoader.dlclose(handle); + return witnessTable; + } + } +} diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs deleted file mode 100644 index ec54fb705a836..0000000000000 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Swift.Runtime -{ - // - // Represents Swift UnsafeBufferPointer in C#. - // - internal 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#. - // - internal 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; - } -} diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs index 8d340797f444a..98042d5212f84 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs @@ -11,6 +11,8 @@ using System.Security.Cryptography.Apple; using Swift.Runtime; +using AesGcm = Swift.Runtime.AesGcm; + #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant internal static partial class Interop @@ -47,13 +49,27 @@ internal static unsafe void ChaCha20Poly1305Encrypt( fixed (byte* tagPtr = tag) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - AppleCryptoNative_ChaCha20Poly1305Encrypt( - new UnsafeBufferPointer(keyPtr, key.Length), - new UnsafeBufferPointer(noncePtr, nonce.Length), - new UnsafeBufferPointer(plaintextPtr, plaintext.Length), - new UnsafeMutableBufferPointer(ciphertextPtr, ciphertext.Length), - new UnsafeMutableBufferPointer(tagPtr, tag.Length), - new UnsafeBufferPointer(aadPtr, aad.Length), + var symmetricKeyData = new Data(keyPtr, key.Length); + var swiftKey = new SymmetricKey(symmetricKeyData); + + var nonceData = new Data(noncePtr, nonce.Length); + var swiftNonce = new ChaChaPoly.Nonce(nonceData); + + var plaintextData = new Data(plaintextPtr, plaintext.Length); + var aadData = new Data(aadPtr, aad.Length); + + void* messagePtr = &plaintextData; + void* authenticatedDataPtr = &aadData; + + var sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal( + messagePtr, + swiftKey.payload, + swiftNonce.payload, + authenticatedDataPtr, + plaintextData.Metadata(), + aadData.Metadata(), + default(DataProtocol).WitnessTable(plaintextData), + default(DataProtocol).WitnessTable(aadData), out SwiftError error); if (error.Value != null) @@ -62,6 +78,15 @@ internal static unsafe void ChaCha20Poly1305Encrypt( CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); } + + GC.KeepAlive(plaintextData); + GC.KeepAlive(aadData); + + var resultCiphertext = sealedBox.Ciphertext; + var resultTag = sealedBox.Tag; + + resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count); + resultTag.CopyBytes(tagPtr, resultTag.Count); } } @@ -84,13 +109,26 @@ internal static unsafe void ChaCha20Poly1305Decrypt( fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - AppleCryptoNative_ChaCha20Poly1305Decrypt( - new UnsafeBufferPointer(keyPtr, key.Length), - new UnsafeBufferPointer(noncePtr, nonce.Length), - new UnsafeBufferPointer(ciphertextPtr, ciphertext.Length), - new UnsafeBufferPointer(tagPtr, tag.Length), - new UnsafeMutableBufferPointer(plaintextPtr, plaintext.Length), - new UnsafeBufferPointer(aadPtr, aad.Length), + var symmetricKeyData = new Data(keyPtr, key.Length); + var swiftKey = new SymmetricKey(symmetricKeyData); + + var nonceData = new Data(noncePtr, nonce.Length); + var swiftNonce = new ChaChaPoly.Nonce(nonceData); + + var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); + var tagData = new Data(tagPtr, tag.Length); + var aadData = new Data(aadPtr, aad.Length); + + var sealedBox = new ChaChaPoly.SealedBox(swiftNonce, ciphertextData, tagData); + + void* authenticatedDataPtr = &aadData; + + var data = CryptoKit.PInvoke_ChaChaPoly_Open( + sealedBox, + swiftKey.payload, + authenticatedDataPtr, + aadData.Metadata(), + default(DataProtocol).WitnessTable(aadData), out SwiftError error); if (error.Value != null) @@ -106,6 +144,10 @@ internal static unsafe void ChaCha20Poly1305Decrypt( throw new CryptographicException(); } } + + GC.KeepAlive(aadData); + + data.CopyBytes(plaintextPtr, data.Count); } } @@ -128,13 +170,31 @@ internal static unsafe void AesGcmEncrypt( fixed (byte* tagPtr = tag) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - AppleCryptoNative_AesGcmEncrypt( - new UnsafeBufferPointer(keyPtr, key.Length), - new UnsafeBufferPointer(noncePtr, nonce.Length), - new UnsafeBufferPointer(plaintextPtr, plaintext.Length), - new UnsafeMutableBufferPointer(ciphertextPtr, ciphertext.Length), - new UnsafeMutableBufferPointer(tagPtr, tag.Length), - new UnsafeBufferPointer(aadPtr, aad.Length), + var symmetricKeyData = new Data(keyPtr, key.Length); + var swiftKey = new SymmetricKey(symmetricKeyData); + + var nonceData = new Data(noncePtr, nonce.Length); + var swiftNonce = new AesGcm.Nonce(nonceData); + + var plaintextData = new Data(plaintextPtr, plaintext.Length); + var aadData = new Data(aadPtr, aad.Length); + + void* messagePtr = &plaintextData; + void* authenticatedDataPtr = &aadData; + + var sealedBox = new AesGcm.SealedBox(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.payload); + + CryptoKit.PInvoke_AesGcm_Seal( + swiftIndirectResult, + messagePtr, + swiftKey.payload, + swiftNonce.payload, + authenticatedDataPtr, + plaintextData.Metadata(), + aadData.Metadata(), + default(DataProtocol).WitnessTable(plaintextData), + default(DataProtocol).WitnessTable(aadData), out SwiftError error); if (error.Value != null) @@ -143,6 +203,15 @@ internal static unsafe void AesGcmEncrypt( CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); } + + GC.KeepAlive(plaintextData); + GC.KeepAlive(aadData); + + var resultCiphertext = sealedBox.Ciphertext; + var resultTag = sealedBox.Tag; + + resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count); + resultTag.CopyBytes(tagPtr, resultTag.Count); } } @@ -165,13 +234,26 @@ internal static unsafe void AesGcmDecrypt( fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - AppleCryptoNative_AesGcmDecrypt( - new UnsafeBufferPointer(keyPtr, key.Length), - new UnsafeBufferPointer(noncePtr, nonce.Length), - new UnsafeBufferPointer(ciphertextPtr, ciphertext.Length), - new UnsafeBufferPointer(tagPtr, tag.Length), - new UnsafeMutableBufferPointer(plaintextPtr, plaintext.Length), - new UnsafeBufferPointer(aadPtr, aad.Length), + var symmetricKeyData = new Data(keyPtr, key.Length); + var swiftKey = new SymmetricKey(symmetricKeyData); + + var nonceData = new Data(noncePtr, nonce.Length); + var swiftNonce = new AesGcm.Nonce(nonceData); + + var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); + var tagData = new Data(tagPtr, tag.Length); + var aadData = new Data(aadPtr, aad.Length); + + var sealedBox = new AesGcm.SealedBox(swiftNonce, ciphertextData, tagData); + + void* authenticatedDataPtr = &aadData; + + var data = CryptoKit.PInvoke_AesGcm_Open( + sealedBox.payload, + swiftKey.payload, + authenticatedDataPtr, + aadData.Metadata(), + default(DataProtocol).WitnessTable(aadData), out SwiftError error); if (error.Value != null) @@ -187,52 +269,12 @@ internal static unsafe void AesGcmDecrypt( throw new CryptographicException(); } } - } - } - [LibraryImport(Libraries.AppleCryptoNative)] - [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - private static unsafe partial void AppleCryptoNative_ChaCha20Poly1305Encrypt( - UnsafeBufferPointer key, - UnsafeBufferPointer nonce, - UnsafeBufferPointer plaintext, - UnsafeMutableBufferPointer ciphertext, - UnsafeMutableBufferPointer tag, - UnsafeBufferPointer aad, - out SwiftError error); + GC.KeepAlive(aadData); - [LibraryImport(Libraries.AppleCryptoNative)] - [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - private static unsafe partial void AppleCryptoNative_ChaCha20Poly1305Decrypt( - UnsafeBufferPointer key, - UnsafeBufferPointer nonce, - UnsafeBufferPointer ciphertext, - UnsafeBufferPointer tag, - UnsafeMutableBufferPointer plaintext, - UnsafeBufferPointer aad, - out SwiftError error); - - [LibraryImport(Libraries.AppleCryptoNative)] - [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - private static unsafe partial void AppleCryptoNative_AesGcmEncrypt( - UnsafeBufferPointer key, - UnsafeBufferPointer nonce, - UnsafeBufferPointer plaintext, - UnsafeMutableBufferPointer ciphertext, - UnsafeMutableBufferPointer tag, - UnsafeBufferPointer aad, - out SwiftError error); - - [LibraryImport(Libraries.AppleCryptoNative)] - [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - private static unsafe partial void AppleCryptoNative_AesGcmDecrypt( - UnsafeBufferPointer key, - UnsafeBufferPointer nonce, - UnsafeBufferPointer ciphertext, - UnsafeBufferPointer tag, - UnsafeMutableBufferPointer plaintext, - UnsafeBufferPointer aad, - out SwiftError error); + data.CopyBytes(plaintextPtr, data.Count); + } + } [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvSwift) })] diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index c609292d4059f..9c8552df9c3e3 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1086,8 +1086,12 @@ Link="Common\Interop\OSX\Interop.CoreFoundation.CFString.cs" /> - + + + (data: D) throws where D : DataProtocol -} - -protocol SealedBoxProtocol { - associatedtype Nonce : NonceProtocol - - var ciphertext: Data { get } - var tag: Data { get } - - init( - nonce: Nonce, - ciphertext: C, - tag: T - ) throws where C : DataProtocol, T : DataProtocol -} - -@available(iOS 13, tvOS 13, *) -protocol AEADSymmetricAlgorithm { - associatedtype SealedBox : SealedBoxProtocol - - static func seal(_ plaintext: Plaintext, using key: SymmetricKey, nonce: SealedBox.Nonce?) throws -> SealedBox where Plaintext: DataProtocol - static func seal<Plaintext, AuthenticatedData>(_ plaintext: Plaintext, using key: SymmetricKey, nonce: SealedBox.Nonce?, authenticating additionalData: AuthenticatedData) throws -> SealedBox where Plaintext: DataProtocol, AuthenticatedData: DataProtocol - static func open<AuthenticatedData>(_ sealedBox: SealedBox, using key: SymmetricKey, authenticating additionalData: AuthenticatedData) throws -> Data where AuthenticatedData: DataProtocol - static func open(_ sealedBox: SealedBox, using key: SymmetricKey) throws -> Data -} - -@available(iOS 13, tvOS 13, *) -extension AES.GCM.Nonce: NonceProtocol {} - -@available(iOS 13, tvOS 13, *) -extension AES.GCM.SealedBox: SealedBoxProtocol { - typealias Nonce = AES.GCM.Nonce -} - -@available(iOS 13, tvOS 13, *) -extension AES.GCM: AEADSymmetricAlgorithm {} - -@available(iOS 13, tvOS 13, *) -extension ChaChaPoly.Nonce: NonceProtocol {} - -@available(iOS 13, tvOS 13, *) -extension ChaChaPoly.SealedBox: SealedBoxProtocol { - typealias Nonce = ChaChaPoly.Nonce -} - -@available(iOS 13, tvOS 13, *) -extension ChaChaPoly: AEADSymmetricAlgorithm {} - -@available(iOS 13, tvOS 13, *) -func encrypt<Algorithm>( - _ algorithm: Algorithm.Type, - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeMutableBufferPointer<UInt8>, - tag: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8>) throws where Algorithm: AEADSymmetricAlgorithm { - - let symmetricKey = SymmetricKey(data: key) - - let nonce = try Algorithm.SealedBox.Nonce(data: nonceData) - - let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) - - // Copy results out of the SealedBox as the Data objects returned here are sometimes slices, - // which don't have a correct implementation of copyBytes. - // See https://github.com/apple/swift-foundation/issues/638 for more information. - let resultCiphertext = Data(result.ciphertext) - let resultTag = Data(result.tag) - - _ = resultCiphertext.copyBytes(to: cipherText) - _ = resultTag.copyBytes(to: tag) -} - -@available(iOS 13, tvOS 13, *) -func decrypt<Algorithm>( - _ algorithm: Algorithm.Type, - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeBufferPointer<UInt8>, - tag: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8>) throws where Algorithm: AEADSymmetricAlgorithm { - - let symmetricKey = SymmetricKey(data: key) - - let nonce = try Algorithm.SealedBox.Nonce(data: nonceData) - - let sealedBox = try Algorithm.SealedBox(nonce: nonce, ciphertext: cipherText, tag: tag) - - let result = try Algorithm.open(sealedBox, using: symmetricKey, authenticating: aad) - - _ = result.copyBytes(to: plaintext) -} - -@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt") -@available(iOS 13, tvOS 13, *) -public func AppleCryptoNative_ChaCha20Poly1305Encrypt( - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeMutableBufferPointer<UInt8>, - tag: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8> -) throws { - return try encrypt( - ChaChaPoly.self, - key: key, - nonceData: nonceData, - plaintext: plaintext, - cipherText: cipherText, - tag: tag, - aad: aad) - } - -@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Decrypt") -@available(iOS 13, tvOS 13, *) -public func AppleCryptoNative_ChaCha20Poly1305Decrypt( - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeBufferPointer<UInt8>, - tag: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8> -) throws { - return try decrypt( - ChaChaPoly.self, - key: key, - nonceData: nonceData, - cipherText: cipherText, - tag: tag, - plaintext: plaintext, - aad: aad); -} - -@_silgen_name("AppleCryptoNative_AesGcmEncrypt") -@available(iOS 13, tvOS 13, *) -public func AppleCryptoNative_AesGcmEncrypt( - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeMutableBufferPointer<UInt8>, - tag: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8> -) throws { - return try encrypt( - AES.GCM.self, - key: key, - nonceData: nonceData, - plaintext: plaintext, - cipherText: cipherText, - tag: tag, - aad: aad) - } - -@_silgen_name("AppleCryptoNative_AesGcmDecrypt") -@available(iOS 13, tvOS 13, *) -public func AppleCryptoNative_AesGcmDecrypt( - key: UnsafeBufferPointer<UInt8>, - nonceData: UnsafeBufferPointer<UInt8>, - cipherText: UnsafeBufferPointer<UInt8>, - tag: UnsafeBufferPointer<UInt8>, - plaintext: UnsafeMutableBufferPointer<UInt8>, - aad: UnsafeBufferPointer<UInt8> -) throws { - return try decrypt( - AES.GCM.self, - key: key, - nonceData: nonceData, - cipherText: cipherText, - tag: tag, - plaintext: plaintext, - aad: aad); -} - @_silgen_name("AppleCryptoNative_IsAuthenticationFailure") @available(iOS 13, tvOS 13, *) public func AppleCryptoNative_IsAuthenticationFailure(error: Error) -> Bool { From acb1756cfe6209f8a6f0dc35b0ac9f3af64172e1 Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Wed, 2 Oct 2024 17:13:47 +0200 Subject: [PATCH 2/9] Use CryptographicException for error handling --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs index 4318d20017394..3489ee4347166 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Swift; +using System.Security.Cryptography; #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant #pragma warning disable SYSLIB1051 @@ -40,9 +41,9 @@ internal Nonce(Data data) CryptoKit.PInvoke_ChaChaPoly_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); - if (error.Value != null) // Should throw when nonce is not 12 bytes + if (error.Value != null) { - throw new Exception(); + throw new CryptographicException(); } } @@ -66,11 +67,19 @@ internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) { void* tagPtr = &tag; void* ciphertextPtr = &ciphertext; - this = CryptoKit.PInvoke_ChaChaPoly_SealedBox_Init(nonce.payload, ciphertextPtr, tagPtr, ciphertext.Metadata(), tag.Metadata(), default(DataProtocol).WitnessTable(ciphertext), default(DataProtocol).WitnessTable(tag), out SwiftError error); + this = CryptoKit.PInvoke_ChaChaPoly_SealedBox_Init( + nonce.payload, + ciphertextPtr, + tagPtr, + ciphertext.Metadata(), + tag.Metadata(), + default(DataProtocol).WitnessTable(ciphertext), + default(DataProtocol).WitnessTable(tag), + out SwiftError error); if (error.Value != null) { - throw new Exception(); + throw new CryptographicException(); } } } @@ -103,9 +112,9 @@ internal Nonce(Data data) void* dataPtr = &data; CryptoKit.PInvoke_AesGcm_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); - if (error.Value != null) // Should throw when nonce is not 12 bytes + if (error.Value != null) { - throw new Exception(); + throw new CryptographicException(); } } @@ -131,11 +140,20 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) void* tagPtr = &tag; void* ciphertextPtr = &ciphertext; - CryptoKit.PInvoke_AesGcm_SealedBox_Init(swiftIndirectResult, nonce.payload, ciphertextPtr, tagPtr, ciphertext.Metadata(), tag.Metadata(), default(DataProtocol).WitnessTable(ciphertext), default(DataProtocol).WitnessTable(tag), out SwiftError error); + CryptoKit.PInvoke_AesGcm_SealedBox_Init( + swiftIndirectResult, + nonce.payload, + ciphertextPtr, + tagPtr, + ciphertext.Metadata(), + tag.Metadata(), + default(DataProtocol).WitnessTable(ciphertext), + default(DataProtocol).WitnessTable(tag), + out SwiftError error); if (error.Value != null) { - throw new Exception(); + throw new CryptographicException(); } } From eed991e466d0d30821a156477010c7dc85b4175d Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Wed, 2 Oct 2024 17:37:34 +0200 Subject: [PATCH 3/9] Remove DynamicLibraryLoader and use NativeLibrary --- .../OSX/Swift.Runtime/DynamicLibraryLoader.cs | 31 ------------------- .../Interop/OSX/Swift.Runtime/Foundation.cs | 6 ++-- .../src/System.Security.Cryptography.csproj | 2 -- 3 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs deleted file mode 100644 index 77f741b7a38bd..0000000000000 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/DynamicLibraryLoader.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Swift.Runtime -{ - // <summary> - // Represents dynamic library loader in C#. - // </summary> - internal static partial class DynamicLibraryLoader - { - public const int RTLD_LAZY = 0x1; - public const int RTLD_NOW = 0x2; - - [LibraryImport("libdl.dylib")] - internal static partial IntPtr dlopen([MarshalAs(UnmanagedType.LPStr)] string path, int mode); - - [LibraryImport("libdl.dylib")] - internal static partial IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string symbol); - - [LibraryImport("libdl.dylib")] - internal static partial int dlclose(IntPtr handle); - - [LibraryImport("libdl.dylib")] - internal static partial IntPtr dlerror(); - } -} diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 5c53ee49a46c0..3fb40e7085334 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -207,10 +207,10 @@ internal static partial class Foundation internal static unsafe void* GetProtocolWitnessTable(void* metadata, string conformanceDescriptorSymbol) { - IntPtr handle = DynamicLibraryLoader.dlopen(Path, DynamicLibraryLoader.RTLD_NOW); - void* conformanceDescriptor = DynamicLibraryLoader.dlsym(handle, conformanceDescriptorSymbol).ToPointer(); + IntPtr handle = NativeLibrary.Load(Path); + void* conformanceDescriptor = NativeLibrary.GetExport(handle, conformanceDescriptorSymbol).ToPointer(); void* witnessTable = PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); - DynamicLibraryLoader.dlclose(handle); + NativeLibrary.Free(handle); return witnessTable; } } diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index 9c8552df9c3e3..2df45c6e3b093 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1090,8 +1090,6 @@ Link="Common\Interop\OSX\Swift.Runtime\Foundation.cs" /> <Compile Include="$(CommonPath)Interop\OSX\Swift.Runtime\CryptoKit.cs" Link="Common\Interop\OSX\Swift.Runtime\CryptoKit.cs" /> - <Compile Include="$(CommonPath)Interop\OSX\Swift.Runtime\DynamicLibraryLoader.cs" - Link="Common\Interop\OSX\Swift.Runtime\DynamicLibraryLoader.cs" /> <Compile Include="$(CommonPath)Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.Aead.cs" Link="Common\Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.Aead.cs" /> <Compile Include="$(CommonPath)Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.Digest.cs" From 55c459ebc5454c6f3a6276196fdffe00b16b3d65 Mon Sep 17 00:00:00 2001 From: Jeremi Kurdek <jkurdek@gmail.com> Date: Thu, 3 Oct 2024 18:43:36 +0200 Subject: [PATCH 4/9] Reorder Data members --- .../Common/src/Interop/OSX/Swift.Runtime/Foundation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 3fb40e7085334..11d62d85c0d40 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -138,8 +138,8 @@ public UnsafeMutableBufferPointer(T* baseAddress, nint count) [InlineArray(16)] internal unsafe partial struct Data : ISwiftType { - private static void* metadata = Foundation.PInvoke_Data_GetMetadata(); internal byte payload; + private static void* metadata = Foundation.PInvoke_Data_GetMetadata(); // Static field after instance field: https://github.com/dotnet/runtime/issues/108522 internal unsafe Data(UnsafeRawPointer pointer, nint count) { From c8d73f7f4c28a6bbe7eaa2b4c1d17927ef80f2a9 Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Fri, 4 Oct 2024 10:17:35 +0200 Subject: [PATCH 5/9] Refactor tests to have C#-like surface and move Swift-specific features to the bindings --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 177 ++++++++++++++---- .../Interop/OSX/Swift.Runtime/Foundation.cs | 56 +++--- .../Interop.Aead.cs | 94 +++------- 3 files changed, 199 insertions(+), 128 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs index 3489ee4347166..b40c59a706cc8 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -11,7 +11,7 @@ #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant #pragma warning disable SYSLIB1051 -namespace Swift.Runtime +namespace Swift { /// <summary> /// Represents ChaChaPoly in C#. @@ -37,9 +37,12 @@ internal Nonce(Data data) { payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); - void* dataPtr = &data; - CryptoKit.PInvoke_ChaChaPoly_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); + void* metadata = Swift.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) { @@ -65,16 +68,20 @@ internal unsafe partial struct SealedBox internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) { - void* tagPtr = &tag; - void* ciphertextPtr = &ciphertext; + void* ciphertextMetadata = Swift.Runtime.GetMetadata(ciphertext); + void* tagMetadata = Swift.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, - ciphertextPtr, - tagPtr, - ciphertext.Metadata(), - tag.Metadata(), - default(DataProtocol).WitnessTable(ciphertext), - default(DataProtocol).WitnessTable(tag), + &ciphertext, + &tag, + ciphertextMetadata, + tagMetadata, + ciphertextWitnessTable, + tagWitnessTable, out SwiftError error); if (error.Value != null) @@ -83,6 +90,49 @@ internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) } } } + + /// <summary> + /// Encrypts the plaintext using the key, nonce, and authenticated data. + /// </summary> + internal static unsafe SealedBox seal<Plaintext, AuthenticateData>(Plaintext plaintext, SymmetricKey key, Nonce nonce, AuthenticateData aad, out SwiftError error) where Plaintext : unmanaged, ISwiftObject where AuthenticateData : unmanaged, ISwiftObject { + void* plaintextMetadata = Swift.Runtime.GetMetadata(plaintext); + void* aadMetadata = Swift.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); + + var sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal( + &plaintext, + key.payload, + nonce.payload, + &aad, + plaintextMetadata, + aadMetadata, + plaintextWitnessTable, + aadWitnessTable, + out error); + + return sealedBox; + } + + /// <summary> + /// Decrypts the sealed box using the key and authenticated data. + /// </summary> + internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, SymmetricKey key, AuthenticateData aad, out SwiftError error) where AuthenticateData : unmanaged, ISwiftObject { + void* metadata = Swift.Runtime.GetMetadata(aad); + void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; + void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); + + var data = CryptoKit.PInvoke_ChaChaPoly_Open( + sealedBox, + key.payload, + &aad, + metadata, + witnessTable, + out error); + + return data; + } } /// <summary> @@ -109,8 +159,12 @@ internal Nonce(Data data) { payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); - void* dataPtr = &data; - CryptoKit.PInvoke_AesGcm_Nonce_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(DataProtocol).WitnessTable(data), out SwiftError error); + + void* metadata = Swift.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) { @@ -137,18 +191,22 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) { payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); - void* tagPtr = &tag; - void* ciphertextPtr = &ciphertext; + + void* ciphertextMetadata = Swift.Runtime.GetMetadata(ciphertext); + void* tagMetadata = Swift.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, - ciphertextPtr, - tagPtr, - ciphertext.Metadata(), - tag.Metadata(), - default(DataProtocol).WitnessTable(ciphertext), - default(DataProtocol).WitnessTable(tag), + &ciphertext, + &tag, + ciphertextMetadata, + tagMetadata, + ciphertextWitnessTable, + tagWitnessTable, out SwiftError error); if (error.Value != null) @@ -167,6 +225,53 @@ internal SealedBox() Marshal.FreeHGlobal(new IntPtr(payload)); } } + + /// <summary> + /// Encrypts the plaintext using the key, nonce, and authenticated data. + /// </summary> + internal static unsafe SealedBox seal<Plaintext, AuthenticateData>(Plaintext plaintext, SymmetricKey key, Nonce nonce, AuthenticateData aad, out SwiftError error) where Plaintext : unmanaged, ISwiftObject where AuthenticateData : unmanaged, ISwiftObject { + var sealedBox = new AesGcm.SealedBox(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.payload); + + void* plaintextMetadata = Swift.Runtime.GetMetadata(plaintext); + void* aadMetadata = Swift.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; + } + + /// <summary> + /// Decrypts the sealed box using the key and authenticated data. + /// </summary> + internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, SymmetricKey key, AuthenticateData aad, out SwiftError error) where AuthenticateData : unmanaged, ISwiftObject { + void* metadata = Swift.Runtime.GetMetadata(aad); + void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; + void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); + + var data = CryptoKit.PInvoke_AesGcm_Open( + sealedBox.payload, + key.payload, + &aad, + metadata, + witnessTable, + out error); + + return data; + } } /// <summary> @@ -188,8 +293,12 @@ internal SymmetricKey(Data data) { payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); - void* dataPtr = &data; - CryptoKit.PInvoke_SymmetricKey_Init2(swiftIndirectResult, dataPtr, data.Metadata(), default(ContiguousBytes).WitnessTable(data)); + + void* metadata = Swift.Runtime.GetMetadata(data); + void* conformanceDescriptor = IContiguousBytes.GetConformanceDescriptor; + void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); + + CryptoKit.PInvoke_SymmetricKey_Init2(swiftIndirectResult, &data, metadata, witnessTable); } ~SymmetricKey() @@ -204,12 +313,8 @@ internal SymmetricKey(Data data) [StructLayout(LayoutKind.Sequential, Size = 8)] internal unsafe partial struct SymmetricKeySize { - internal const string AppleCryptoKit = "/System/Library/Frameworks/CryptoKit.framework/CryptoKit"; internal nint bitCount; - [LibraryImport(AppleCryptoKit, EntryPoint = "$s9CryptoKit16SymmetricKeySizeV8bitCountACSi_tcfC")] - [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial void PInvoke_init(SwiftIndirectResult result, nint bitCount); internal SymmetricKeySize(nint bitCount) { SymmetricKeySize instance; @@ -243,7 +348,7 @@ internal static partial class CryptoKit [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV5nonce10ciphertext3tagAeC5NonceV_xq_tKc10Foundation12DataProtocolRzAkLR_r0_lufC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_SealedBox_Init(void* nonce, void* ciphertext, void* tag, void* metadata1, void* metadata2, void* witnessTable1, void*witnessTable2, out SwiftError error); + internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_SealedBox_Init(void* nonce, void* ciphertext, void* tag, void* ciphertextMetadata, void* tagMetadata, void* ciphertextWitnessTable, void* tagWitnessTable, out SwiftError error); [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVAGycfC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] @@ -263,7 +368,7 @@ internal static partial class CryptoKit [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV5nonce10ciphertext3tagAgE5NonceV_xq_tKc10Foundation12DataProtocolRzAmNR_r0_lufC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial void PInvoke_AesGcm_SealedBox_Init(SwiftIndirectResult result, void* nonce, void* ciphertext, void* tag, void* metadata1, void* metadata2, void* witnessTable1, void*witnessTable2, out SwiftError error); + internal static unsafe partial void PInvoke_AesGcm_SealedBox_Init(SwiftIndirectResult result, void* nonce, void* ciphertext, void* tag, void* ciphertextMetadata, void* tagMetadata, void* ciphertextWitnessTable, void* tagWitnessTable, out SwiftError error); [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4sizeAcA0cD4SizeV_tcfC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] @@ -271,22 +376,26 @@ internal static partial class CryptoKit [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4dataACx_tc10Foundation15ContiguousBytesRzlufC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial void PInvoke_SymmetricKey_Init2(SwiftIndirectResult result, void* data, void* md, void* pwt); + internal static unsafe partial void PInvoke_SymmetricKey_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable); + + [LibraryImport(Path, EntryPoint = "$s9CryptoKit16SymmetricKeySizeV8bitCountACSi_tcfC")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void PInvoke_init(SwiftIndirectResult result, nint bitCount); [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4seal_5using5nonce14authenticatingAC9SealedBoxVx_AA12SymmetricKeyVAC5NonceVSgq_tK10Foundation12DataProtocolRzAoPR_r0_lFZ")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_Seal(void* messagePtr, void* key, void* nonce, void* authenticatedData, void* metadata1, void* metadata2, void* witnessTable1, void* witnessTable2, out SwiftError error); + internal static unsafe partial ChaChaPoly.SealedBox PInvoke_ChaChaPoly_Seal(void* plaintext, void* key, void* nonce, void* aad, void* plaintextMetadata, void* aadMetadata, void* plaintextWitnessTable, void* aadWitnessTable, out SwiftError error); [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO4open_5using14authenticating10Foundation4DataVAC9SealedBoxV_AA12SymmetricKeyVxtKAG0I8ProtocolRzlFZ")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial Data PInvoke_ChaChaPoly_Open(ChaChaPoly.SealedBox sealedBox, void* key, void* authenticatedData, void* metadata, void* witnessTable, out SwiftError error); + internal static unsafe partial Data PInvoke_ChaChaPoly_Open(ChaChaPoly.SealedBox sealedBox, void* key, void* aad, void* metadata, void* witnessTable, out SwiftError error); [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4seal_5using5nonce14authenticatingAE9SealedBoxVx_AA12SymmetricKeyVAE5NonceVSgq_tK10Foundation12DataProtocolRzAqRR_r0_lFZ")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial void PInvoke_AesGcm_Seal(SwiftIndirectResult result, void* messagePtr, void* key, void* nonce, void* authenticatedData, void* metadata1, void* metadata2, void* witnessTable1, void* witnessTable2, out SwiftError error); + internal static unsafe partial 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); [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO4open_5using14authenticating10Foundation4DataVAE9SealedBoxV_AA12SymmetricKeyVxtKAI0I8ProtocolRzlFZ")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - internal static unsafe partial Data PInvoke_AesGcm_Open(void* sealedBox, void* key, void* authenticatedData, void* metadata, void* witnessTable, out SwiftError error); + internal static unsafe partial Data PInvoke_AesGcm_Open(void* sealedBox, void* key, void* aad, void* metadata, void* witnessTable, out SwiftError error); } } diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 11d62d85c0d40..80a4f2a71326e 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -4,27 +4,22 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Reflection; #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant #pragma warning disable SYSLIB1051 +#pragma warning disable IDE0060 -namespace Swift.Runtime +namespace Swift { /// <summary> /// Represents a Swift type in C#. /// </summary> - internal unsafe interface ISwiftType + internal unsafe interface ISwiftObject { - public abstract void* Metadata(); + public static abstract void* Metadata { get; } } - /// <summary> - /// Represents a Swift protocol in C#. - /// </summary> - internal unsafe interface ISwiftProtocol - { - public abstract void* WitnessTable(ISwiftType type); - } // <summary> // Represents Swift UnsafePointer in C#. // </summary> @@ -136,10 +131,9 @@ public UnsafeMutableBufferPointer(T* baseAddress, nint count) // </summary> [StructLayout(LayoutKind.Sequential, Size = 16)] [InlineArray(16)] - internal unsafe partial struct Data : ISwiftType + internal unsafe partial struct Data : ISwiftObject { internal byte payload; - private static void* metadata = Foundation.PInvoke_Data_GetMetadata(); // Static field after instance field: https://github.com/dotnet/runtime/issues/108522 internal unsafe Data(UnsafeRawPointer pointer, nint count) { @@ -153,29 +147,23 @@ internal unsafe void CopyBytes(UnsafeMutablePointer<byte> buffer, nint count) Foundation.PInvoke_Data_CopyBytes(buffer, count, this); } - public void* Metadata() => metadata; + public static void* Metadata => Foundation.PInvoke_Data_GetMetadata(); } /// <summary> /// Represents Swift Foundation.DataProtocol in C#. /// </summary> - internal unsafe partial struct DataProtocol : ISwiftProtocol + internal unsafe interface IDataProtocol { - public void* WitnessTable(ISwiftType type) - { - return Foundation.GetProtocolWitnessTable(type.Metadata(), "$s10Foundation4DataVAA0B8ProtocolAAMc"); - } + public static void* GetConformanceDescriptor => Runtime.GetConformanceDescriptor("$s10Foundation4DataVAA0B8ProtocolAAMc"); } /// <summary> /// Represents Swift Foundation.ContiguousBytes in C#. /// </summary> - internal unsafe partial struct ContiguousBytes : ISwiftProtocol + internal unsafe interface IContiguousBytes { - public void* WitnessTable(ISwiftType type) - { - return Foundation.GetProtocolWitnessTable(type.Metadata(), "$s10Foundation4DataVAA15ContiguousBytesAAMc"); - } + public static void* GetConformanceDescriptor => Runtime.GetConformanceDescriptor("$s10Foundation4DataVAA15ContiguousBytesAAMc"); } /// <summary> @@ -204,14 +192,24 @@ internal static partial class Foundation [LibraryImport(Path, EntryPoint = "$s10Foundation4DataVMa")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void* PInvoke_Data_GetMetadata(); + } + + /// <summary> + /// Swift runtime helper methods in C#. + /// </summary> + internal static partial class Runtime + { + + internal static unsafe void* GetMetadata<T>(T type) where T: ISwiftObject + { + return T.Metadata; + } - internal static unsafe void* GetProtocolWitnessTable(void* metadata, string conformanceDescriptorSymbol) + internal static unsafe void* GetConformanceDescriptor(string symbol) { - IntPtr handle = NativeLibrary.Load(Path); - void* conformanceDescriptor = NativeLibrary.GetExport(handle, conformanceDescriptorSymbol).ToPointer(); - void* witnessTable = PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); - NativeLibrary.Free(handle); - return witnessTable; + IntPtr handle = NativeLibrary.Load(Foundation.Path); + void* conformanceDescriptor = NativeLibrary.GetExport(handle, symbol).ToPointer(); + return conformanceDescriptor; } } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs index 98042d5212f84..9743ba62c948a 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs @@ -9,9 +9,9 @@ using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Cryptography.Apple; -using Swift.Runtime; +using Swift; -using AesGcm = Swift.Runtime.AesGcm; +using AesGcm = Swift.AesGcm; #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant @@ -50,26 +50,19 @@ internal static unsafe void ChaCha20Poly1305Encrypt( fixed (byte* aadPtr = &GetSwiftRef(aad)) { var symmetricKeyData = new Data(keyPtr, key.Length); - var swiftKey = new SymmetricKey(symmetricKeyData); + var symmetricKey = new SymmetricKey(symmetricKeyData); var nonceData = new Data(noncePtr, nonce.Length); - var swiftNonce = new ChaChaPoly.Nonce(nonceData); + var chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); var plaintextData = new Data(plaintextPtr, plaintext.Length); var aadData = new Data(aadPtr, aad.Length); - void* messagePtr = &plaintextData; - void* authenticatedDataPtr = &aadData; - - var sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal( - messagePtr, - swiftKey.payload, - swiftNonce.payload, - authenticatedDataPtr, - plaintextData.Metadata(), - aadData.Metadata(), - default(DataProtocol).WitnessTable(plaintextData), - default(DataProtocol).WitnessTable(aadData), + var sealedBox = ChaChaPoly.seal( + plaintextData, + symmetricKey, + chaChaPolyNonce, + aadData, out SwiftError error); if (error.Value != null) @@ -79,9 +72,6 @@ internal static unsafe void ChaCha20Poly1305Encrypt( throw new CryptographicException(); } - GC.KeepAlive(plaintextData); - GC.KeepAlive(aadData); - var resultCiphertext = sealedBox.Ciphertext; var resultTag = sealedBox.Tag; @@ -110,25 +100,21 @@ internal static unsafe void ChaCha20Poly1305Decrypt( fixed (byte* aadPtr = &GetSwiftRef(aad)) { var symmetricKeyData = new Data(keyPtr, key.Length); - var swiftKey = new SymmetricKey(symmetricKeyData); + var symmetricKey = new SymmetricKey(symmetricKeyData); var nonceData = new Data(noncePtr, nonce.Length); - var swiftNonce = new ChaChaPoly.Nonce(nonceData); + var chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); var tagData = new Data(tagPtr, tag.Length); var aadData = new Data(aadPtr, aad.Length); - var sealedBox = new ChaChaPoly.SealedBox(swiftNonce, ciphertextData, tagData); - - void* authenticatedDataPtr = &aadData; + var sealedBox = new ChaChaPoly.SealedBox(chaChaPolyNonce, ciphertextData, tagData); - var data = CryptoKit.PInvoke_ChaChaPoly_Open( + var data = ChaChaPoly.open( sealedBox, - swiftKey.payload, - authenticatedDataPtr, - aadData.Metadata(), - default(DataProtocol).WitnessTable(aadData), + symmetricKey, + aadData, out SwiftError error); if (error.Value != null) @@ -145,8 +131,6 @@ internal static unsafe void ChaCha20Poly1305Decrypt( } } - GC.KeepAlive(aadData); - data.CopyBytes(plaintextPtr, data.Count); } } @@ -171,30 +155,19 @@ internal static unsafe void AesGcmEncrypt( fixed (byte* aadPtr = &GetSwiftRef(aad)) { var symmetricKeyData = new Data(keyPtr, key.Length); - var swiftKey = new SymmetricKey(symmetricKeyData); + var symmetricKey = new SymmetricKey(symmetricKeyData); var nonceData = new Data(noncePtr, nonce.Length); - var swiftNonce = new AesGcm.Nonce(nonceData); + var aesGcmNonce = new AesGcm.Nonce(nonceData); var plaintextData = new Data(plaintextPtr, plaintext.Length); var aadData = new Data(aadPtr, aad.Length); - void* messagePtr = &plaintextData; - void* authenticatedDataPtr = &aadData; - - var sealedBox = new AesGcm.SealedBox(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.payload); - - CryptoKit.PInvoke_AesGcm_Seal( - swiftIndirectResult, - messagePtr, - swiftKey.payload, - swiftNonce.payload, - authenticatedDataPtr, - plaintextData.Metadata(), - aadData.Metadata(), - default(DataProtocol).WitnessTable(plaintextData), - default(DataProtocol).WitnessTable(aadData), + var sealedBox = AesGcm.seal( + plaintextData, + symmetricKey, + aesGcmNonce, + aadData, out SwiftError error); if (error.Value != null) @@ -204,9 +177,6 @@ internal static unsafe void AesGcmEncrypt( throw new CryptographicException(); } - GC.KeepAlive(plaintextData); - GC.KeepAlive(aadData); - var resultCiphertext = sealedBox.Ciphertext; var resultTag = sealedBox.Tag; @@ -235,25 +205,21 @@ internal static unsafe void AesGcmDecrypt( fixed (byte* aadPtr = &GetSwiftRef(aad)) { var symmetricKeyData = new Data(keyPtr, key.Length); - var swiftKey = new SymmetricKey(symmetricKeyData); + var symmetricKey = new SymmetricKey(symmetricKeyData); var nonceData = new Data(noncePtr, nonce.Length); - var swiftNonce = new AesGcm.Nonce(nonceData); + var aesGcmNonce = new AesGcm.Nonce(nonceData); var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); var tagData = new Data(tagPtr, tag.Length); var aadData = new Data(aadPtr, aad.Length); - var sealedBox = new AesGcm.SealedBox(swiftNonce, ciphertextData, tagData); + var sealedBox = new AesGcm.SealedBox(aesGcmNonce, ciphertextData, tagData); - void* authenticatedDataPtr = &aadData; - - var data = CryptoKit.PInvoke_AesGcm_Open( - sealedBox.payload, - swiftKey.payload, - authenticatedDataPtr, - aadData.Metadata(), - default(DataProtocol).WitnessTable(aadData), + var data = AesGcm.open( + sealedBox, + symmetricKey, + aadData, out SwiftError error); if (error.Value != null) @@ -270,8 +236,6 @@ internal static unsafe void AesGcmDecrypt( } } - GC.KeepAlive(aadData); - data.CopyBytes(plaintextPtr, data.Count); } } From 2e05e175982527a600796643aac29a63baf53474 Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Fri, 4 Oct 2024 10:53:00 +0200 Subject: [PATCH 6/9] Update bindings to follow coding guidelines --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 119 ++++++++++-------- .../Interop/OSX/Swift.Runtime/Foundation.cs | 5 +- .../Interop.Aead.cs | 72 +++++------ 3 files changed, 107 insertions(+), 89 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs index b40c59a706cc8..9854d6f0ef29b 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -23,20 +23,21 @@ internal unsafe partial struct ChaChaPoly /// </summary> internal sealed unsafe partial class Nonce { - private const int _payloadSize = 16; - internal void* payload; + private const int PayloadSize = 16; + + private readonly void* _payload; internal Nonce() { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_ChaChaPoly_Nonce_Init(swiftIndirectResult); } internal Nonce(Data data) { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; @@ -50,9 +51,11 @@ internal Nonce(Data data) } } + internal void* Payload => _payload; + ~Nonce() { - Marshal.FreeHGlobal(new IntPtr(payload)); + Marshal.FreeHGlobal(new IntPtr(_payload)); } } @@ -62,9 +65,7 @@ internal Nonce(Data data) [StructLayout(LayoutKind.Sequential, Size = 16)] internal unsafe partial struct SealedBox { - internal Data combined; - internal readonly Data Ciphertext { get => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetCiphertext(this); } - internal readonly Data Tag { get => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetTag(this); } + private readonly Data _combined; internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) { @@ -75,7 +76,7 @@ internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) void* tagWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, tagMetadata, null); this = CryptoKit.PInvoke_ChaChaPoly_SealedBox_Init( - nonce.payload, + nonce.Payload, &ciphertext, &tag, ciphertextMetadata, @@ -89,6 +90,10 @@ internal SealedBox(ChaChaPoly.Nonce nonce, Data ciphertext, Data tag) throw new CryptographicException(); } } + + internal Data Ciphertext => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetCiphertext(this); + + internal Data Tag => CryptoKit.PInvoke_ChaChaPoly_SealedBox_GetTag(this); } /// <summary> @@ -101,10 +106,10 @@ internal static unsafe SealedBox seal<Plaintext, AuthenticateData>(Plaintext pla void* plaintextWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, plaintextMetadata, null); void* aadWitnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, aadMetadata, null); - var sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal( + SealedBox sealedBox = CryptoKit.PInvoke_ChaChaPoly_Seal( &plaintext, - key.payload, - nonce.payload, + key.Payload, + nonce.Payload, &aad, plaintextMetadata, aadMetadata, @@ -123,9 +128,9 @@ internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, Symmetri void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); - var data = CryptoKit.PInvoke_ChaChaPoly_Open( + Data data = CryptoKit.PInvoke_ChaChaPoly_Open( sealedBox, - key.payload, + key.Payload, &aad, metadata, witnessTable, @@ -145,20 +150,21 @@ internal unsafe partial struct AesGcm /// </summary> internal sealed unsafe partial class Nonce { - private const int _payloadSize = 16; - internal void* payload; + private const int PayloadSize = 16; + + private readonly void* _payload; internal Nonce() { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_AesGcm_Nonce_Init(swiftIndirectResult); } internal Nonce(Data data) { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; @@ -172,9 +178,11 @@ internal Nonce(Data data) } } + internal void* Payload => _payload; + ~Nonce() { - Marshal.FreeHGlobal(new IntPtr(payload)); + Marshal.FreeHGlobal(new IntPtr(_payload)); } } @@ -183,14 +191,19 @@ internal Nonce(Data data) /// </summary> internal sealed unsafe partial class SealedBox { - private const int _payloadSize = 24; - internal void* payload; - public Data Ciphertext { get => CryptoKit.PInvoke_AesGcm_SealedBox_GetCiphertext(new SwiftSelf(payload)); } - public Data Tag { get => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(payload)); } + private const int PayloadSize = 24; + + private readonly void* _payload; + + internal SealedBox() + { + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + } + internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* ciphertextMetadata = Swift.Runtime.GetMetadata(ciphertext); void* tagMetadata = Swift.Runtime.GetMetadata(tag); @@ -200,7 +213,7 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) CryptoKit.PInvoke_AesGcm_SealedBox_Init( swiftIndirectResult, - nonce.payload, + nonce.Payload, &ciphertext, &tag, ciphertextMetadata, @@ -215,14 +228,15 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) } } - internal SealedBox() - { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - } + internal void* Payload => _payload; + + internal Data Ciphertext => CryptoKit.PInvoke_AesGcm_SealedBox_GetCiphertext(new SwiftSelf(_payload)); + + internal Data Tag => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(_payload)); ~SealedBox() { - Marshal.FreeHGlobal(new IntPtr(payload)); + Marshal.FreeHGlobal(new IntPtr(_payload)); } } @@ -230,8 +244,8 @@ internal SealedBox() /// Encrypts the plaintext using the key, nonce, and authenticated data. /// </summary> internal static unsafe SealedBox seal<Plaintext, AuthenticateData>(Plaintext plaintext, SymmetricKey key, Nonce nonce, AuthenticateData aad, out SwiftError error) where Plaintext : unmanaged, ISwiftObject where AuthenticateData : unmanaged, ISwiftObject { - var sealedBox = new AesGcm.SealedBox(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.payload); + AesGcm.SealedBox sealedBox = new AesGcm.SealedBox(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(sealedBox.Payload); void* plaintextMetadata = Swift.Runtime.GetMetadata(plaintext); void* aadMetadata = Swift.Runtime.GetMetadata(aad); @@ -242,8 +256,8 @@ internal static unsafe SealedBox seal<Plaintext, AuthenticateData>(Plaintext pla CryptoKit.PInvoke_AesGcm_Seal( swiftIndirectResult, &plaintext, - key.payload, - nonce.payload, + key.Payload, + nonce.Payload, &aad, plaintextMetadata, aadMetadata, @@ -262,9 +276,9 @@ internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, Symmetri void* conformanceDescriptor = IDataProtocol.GetConformanceDescriptor; void* witnessTable = Foundation.PInvoke_Swift_GetWitnessTable(conformanceDescriptor, metadata, null); - var data = CryptoKit.PInvoke_AesGcm_Open( - sealedBox.payload, - key.payload, + Data data = CryptoKit.PInvoke_AesGcm_Open( + sealedBox.Payload, + key.Payload, &aad, metadata, witnessTable, @@ -279,20 +293,21 @@ internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, Symmetri /// </summary> internal sealed unsafe partial class SymmetricKey { - private const int _payloadSize = 8; - internal void* payload; + private const int PayloadSize = 8; + + internal readonly void* _payload; internal SymmetricKey(SymmetricKeySize symmetricKeySize) { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_SymmetricKey_Init(swiftIndirectResult, &symmetricKeySize); } internal SymmetricKey(Data data) { - payload = Marshal.AllocHGlobal(_payloadSize).ToPointer(); - SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(payload); + _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); void* conformanceDescriptor = IContiguousBytes.GetConformanceDescriptor; @@ -301,9 +316,11 @@ internal SymmetricKey(Data data) CryptoKit.PInvoke_SymmetricKey_Init2(swiftIndirectResult, &data, metadata, witnessTable); } + internal void* Payload => _payload; + ~SymmetricKey() { - Marshal.FreeHGlobal(new IntPtr(payload)); + Marshal.FreeHGlobal(new IntPtr(_payload)); } } @@ -313,12 +330,12 @@ internal SymmetricKey(Data data) [StructLayout(LayoutKind.Sequential, Size = 8)] internal unsafe partial struct SymmetricKeySize { - internal nint bitCount; + private readonly nint _bitCount; internal SymmetricKeySize(nint bitCount) { SymmetricKeySize instance; - PInvoke_init(new SwiftIndirectResult(&instance), bitCount); + CryptoKit.PInvoke_init(new SwiftIndirectResult(&instance), bitCount); this = instance; } } diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 80a4f2a71326e..65956edb11dd3 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -133,13 +133,15 @@ public UnsafeMutableBufferPointer(T* baseAddress, nint count) [InlineArray(16)] internal unsafe partial struct Data : ISwiftObject { - internal byte payload; + private byte _payload; internal unsafe Data(UnsafeRawPointer pointer, nint count) { this = Foundation.PInvoke_Data_InitWithBytes(pointer, count); } + internal byte Payload => _payload; + internal readonly nint Count => Foundation.PInvoke_Data_GetCount(this); internal unsafe void CopyBytes(UnsafeMutablePointer<byte> buffer, nint count) @@ -199,7 +201,6 @@ internal static partial class Foundation /// </summary> internal static partial class Runtime { - internal static unsafe void* GetMetadata<T>(T type) where T: ISwiftObject { return T.Metadata; diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs index 9743ba62c948a..19531b02c789e 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs @@ -49,16 +49,16 @@ internal static unsafe void ChaCha20Poly1305Encrypt( fixed (byte* tagPtr = tag) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - var symmetricKeyData = new Data(keyPtr, key.Length); - var symmetricKey = new SymmetricKey(symmetricKeyData); + Data symmetricKeyData = new Data(keyPtr, key.Length); + SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData); - var nonceData = new Data(noncePtr, nonce.Length); - var chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); + Data nonceData = new Data(noncePtr, nonce.Length); + ChaChaPoly.Nonce chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); - var plaintextData = new Data(plaintextPtr, plaintext.Length); - var aadData = new Data(aadPtr, aad.Length); + Data plaintextData = new Data(plaintextPtr, plaintext.Length); + Data aadData = new Data(aadPtr, aad.Length); - var sealedBox = ChaChaPoly.seal( + ChaChaPoly.SealedBox sealedBox = ChaChaPoly.seal( plaintextData, symmetricKey, chaChaPolyNonce, @@ -72,8 +72,8 @@ internal static unsafe void ChaCha20Poly1305Encrypt( throw new CryptographicException(); } - var resultCiphertext = sealedBox.Ciphertext; - var resultTag = sealedBox.Tag; + Data resultCiphertext = sealedBox.Ciphertext; + Data resultTag = sealedBox.Tag; resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count); resultTag.CopyBytes(tagPtr, resultTag.Count); @@ -99,19 +99,19 @@ internal static unsafe void ChaCha20Poly1305Decrypt( fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - var symmetricKeyData = new Data(keyPtr, key.Length); - var symmetricKey = new SymmetricKey(symmetricKeyData); + Data symmetricKeyData = new Data(keyPtr, key.Length); + SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData); - var nonceData = new Data(noncePtr, nonce.Length); - var chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); + Data nonceData = new Data(noncePtr, nonce.Length); + ChaChaPoly.Nonce chaChaPolyNonce = new ChaChaPoly.Nonce(nonceData); - var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); - var tagData = new Data(tagPtr, tag.Length); - var aadData = new Data(aadPtr, aad.Length); + Data ciphertextData = new Data(ciphertextPtr, ciphertext.Length); + Data tagData = new Data(tagPtr, tag.Length); + Data aadData = new Data(aadPtr, aad.Length); - var sealedBox = new ChaChaPoly.SealedBox(chaChaPolyNonce, ciphertextData, tagData); + ChaChaPoly.SealedBox sealedBox = new ChaChaPoly.SealedBox(chaChaPolyNonce, ciphertextData, tagData); - var data = ChaChaPoly.open( + Data data = ChaChaPoly.open( sealedBox, symmetricKey, aadData, @@ -154,16 +154,16 @@ internal static unsafe void AesGcmEncrypt( fixed (byte* tagPtr = tag) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - var symmetricKeyData = new Data(keyPtr, key.Length); - var symmetricKey = new SymmetricKey(symmetricKeyData); + Data symmetricKeyData = new Data(keyPtr, key.Length); + SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData); - var nonceData = new Data(noncePtr, nonce.Length); - var aesGcmNonce = new AesGcm.Nonce(nonceData); + Data nonceData = new Data(noncePtr, nonce.Length); + AesGcm.Nonce aesGcmNonce = new AesGcm.Nonce(nonceData); - var plaintextData = new Data(plaintextPtr, plaintext.Length); - var aadData = new Data(aadPtr, aad.Length); + Data plaintextData = new Data(plaintextPtr, plaintext.Length); + Data aadData = new Data(aadPtr, aad.Length); - var sealedBox = AesGcm.seal( + AesGcm.SealedBox sealedBox = AesGcm.seal( plaintextData, symmetricKey, aesGcmNonce, @@ -177,8 +177,8 @@ internal static unsafe void AesGcmEncrypt( throw new CryptographicException(); } - var resultCiphertext = sealedBox.Ciphertext; - var resultTag = sealedBox.Tag; + Data resultCiphertext = sealedBox.Ciphertext; + Data resultTag = sealedBox.Tag; resultCiphertext.CopyBytes(ciphertextPtr, resultCiphertext.Count); resultTag.CopyBytes(tagPtr, resultTag.Count); @@ -204,19 +204,19 @@ internal static unsafe void AesGcmDecrypt( fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) fixed (byte* aadPtr = &GetSwiftRef(aad)) { - var symmetricKeyData = new Data(keyPtr, key.Length); - var symmetricKey = new SymmetricKey(symmetricKeyData); + Data symmetricKeyData = new Data(keyPtr, key.Length); + SymmetricKey symmetricKey = new SymmetricKey(symmetricKeyData); - var nonceData = new Data(noncePtr, nonce.Length); - var aesGcmNonce = new AesGcm.Nonce(nonceData); + Data nonceData = new Data(noncePtr, nonce.Length); + AesGcm.Nonce aesGcmNonce = new AesGcm.Nonce(nonceData); - var ciphertextData = new Data(ciphertextPtr, ciphertext.Length); - var tagData = new Data(tagPtr, tag.Length); - var aadData = new Data(aadPtr, aad.Length); + Data ciphertextData = new Data(ciphertextPtr, ciphertext.Length); + Data tagData = new Data(tagPtr, tag.Length); + Data aadData = new Data(aadPtr, aad.Length); - var sealedBox = new AesGcm.SealedBox(aesGcmNonce, ciphertextData, tagData); + AesGcm.SealedBox sealedBox = new AesGcm.SealedBox(aesGcmNonce, ciphertextData, tagData); - var data = AesGcm.open( + Data data = AesGcm.open( sealedBox, symmetricKey, aadData, From 9b1b2a9991036f80d5f01eac8e376356d4d50726 Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Fri, 4 Oct 2024 11:07:19 +0200 Subject: [PATCH 7/9] Check for errors in GetConformanceDescriptor --- .../Interop/OSX/Swift.Runtime/Foundation.cs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 65956edb11dd3..8969fb49da0e9 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -208,9 +208,24 @@ internal static partial class Runtime internal static unsafe void* GetConformanceDescriptor(string symbol) { - IntPtr handle = NativeLibrary.Load(Foundation.Path); - void* conformanceDescriptor = NativeLibrary.GetExport(handle, symbol).ToPointer(); - return conformanceDescriptor; + 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); + } + } } } } From 302fdcf80a1dbd8f909beb5eef424e2841d05a0d Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Fri, 4 Oct 2024 12:10:39 +0200 Subject: [PATCH 8/9] Add IDisposable for non-frozen types in CryptoKit --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 84 +++++++++++++++---- .../Interop.Aead.cs | 14 ++++ 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs index 9854d6f0ef29b..1287ff9835ee9 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -10,6 +10,7 @@ #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant #pragma warning disable SYSLIB1051 +#pragma warning disable CA1805 namespace Swift { @@ -21,22 +22,24 @@ internal unsafe partial struct ChaChaPoly /// <summary> /// Represents Nonce in C#. /// </summary> - internal sealed unsafe partial class Nonce + internal sealed unsafe partial class Nonce : IDisposable { private const int PayloadSize = 16; private readonly void* _payload; + private bool _disposed = false; + internal Nonce() { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_ChaChaPoly_Nonce_Init(swiftIndirectResult); } internal Nonce(Data data) { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); @@ -47,15 +50,26 @@ internal Nonce(Data data) if (error.Value != null) { + NativeMemory.Free(_payload); throw new CryptographicException(); } } internal void* Payload => _payload; + public void Dispose() + { + if (!_disposed) + { + NativeMemory.Free(_payload); + _disposed = true; + GC.SuppressFinalize(this); + } + } + ~Nonce() { - Marshal.FreeHGlobal(new IntPtr(_payload)); + NativeMemory.Free(_payload); } } @@ -148,22 +162,24 @@ internal unsafe partial struct AesGcm /// <summary> /// Represents Nonce in C#. /// </summary> - internal sealed unsafe partial class Nonce + internal sealed unsafe partial class Nonce : IDisposable { private const int PayloadSize = 16; private readonly void* _payload; + private bool _disposed = false; + internal Nonce() { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_AesGcm_Nonce_Init(swiftIndirectResult); } internal Nonce(Data data) { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); @@ -174,35 +190,48 @@ internal Nonce(Data data) if (error.Value != null) { + NativeMemory.Free(_payload); throw new CryptographicException(); } } internal void* Payload => _payload; + public void Dispose() + { + if (!_disposed) + { + NativeMemory.Free(_payload); + _disposed = true; + GC.SuppressFinalize(this); + } + } + ~Nonce() { - Marshal.FreeHGlobal(new IntPtr(_payload)); + NativeMemory.Free(_payload); } } /// <summary> /// Represents SealedBox in C#. /// </summary> - internal sealed unsafe partial class SealedBox + internal sealed unsafe partial class SealedBox : IDisposable { private const int PayloadSize = 24; private readonly void* _payload; + private bool _disposed = false; + internal SealedBox() { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); } internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* ciphertextMetadata = Swift.Runtime.GetMetadata(ciphertext); @@ -224,6 +253,7 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) if (error.Value != null) { + NativeMemory.Free(_payload); throw new CryptographicException(); } } @@ -234,9 +264,19 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) internal Data Tag => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(_payload)); + public void Dispose() + { + if (!_disposed) + { + NativeMemory.Free(_payload); + _disposed = true; + GC.SuppressFinalize(this); + } + } + ~SealedBox() { - Marshal.FreeHGlobal(new IntPtr(_payload)); + NativeMemory.Free(_payload); } } @@ -291,22 +331,24 @@ internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, Symmetri /// <summary> /// Represents SymmetricKey in C#. /// </summary> - internal sealed unsafe partial class SymmetricKey + internal sealed unsafe partial class SymmetricKey : IDisposable { private const int PayloadSize = 8; internal readonly void* _payload; + private bool _disposed = false; + internal SymmetricKey(SymmetricKeySize symmetricKeySize) { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); CryptoKit.PInvoke_SymmetricKey_Init(swiftIndirectResult, &symmetricKeySize); } internal SymmetricKey(Data data) { - _payload = Marshal.AllocHGlobal(PayloadSize).ToPointer(); + _payload = NativeMemory.Alloc(PayloadSize); SwiftIndirectResult swiftIndirectResult = new SwiftIndirectResult(_payload); void* metadata = Swift.Runtime.GetMetadata(data); @@ -318,9 +360,19 @@ internal SymmetricKey(Data data) internal void* Payload => _payload; + public void Dispose() + { + if (!_disposed) + { + NativeMemory.Free(_payload); + _disposed = true; + GC.SuppressFinalize(this); + } + } + ~SymmetricKey() { - Marshal.FreeHGlobal(new IntPtr(_payload)); + NativeMemory.Free(_payload); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs index 19531b02c789e..f8fa1397f666d 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Aead.cs @@ -67,6 +67,9 @@ internal static unsafe void ChaCha20Poly1305Encrypt( if (error.Value != null) { + chaChaPolyNonce.Dispose(); + symmetricKey.Dispose(); + CryptographicOperations.ZeroMemory(ciphertext); CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); @@ -119,6 +122,9 @@ internal static unsafe void ChaCha20Poly1305Decrypt( if (error.Value != null) { + chaChaPolyNonce.Dispose(); + symmetricKey.Dispose(); + CryptographicOperations.ZeroMemory(plaintext); if (AppleCryptoNative_IsAuthenticationFailure(error.Value)) @@ -172,6 +178,10 @@ internal static unsafe void AesGcmEncrypt( if (error.Value != null) { + sealedBox.Dispose(); + aesGcmNonce.Dispose(); + symmetricKey.Dispose(); + CryptographicOperations.ZeroMemory(ciphertext); CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); @@ -224,6 +234,10 @@ internal static unsafe void AesGcmDecrypt( if (error.Value != null) { + sealedBox.Dispose(); + aesGcmNonce.Dispose(); + symmetricKey.Dispose(); + CryptographicOperations.ZeroMemory(plaintext); if (AppleCryptoNative_IsAuthenticationFailure(error.Value)) From ad43d2df2ba1551dd149c19a49359baaee6457f2 Mon Sep 17 00:00:00 2001 From: Milos Kotlar <kotlarmilos@gmail.com> Date: Fri, 4 Oct 2024 13:08:54 +0200 Subject: [PATCH 9/9] Retrieve layout size from value witness table --- .../Interop/OSX/Swift.Runtime/CryptoKit.cs | 40 ++++++++++++---- .../Interop/OSX/Swift.Runtime/Foundation.cs | 47 +++++++++++++++++++ 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs index 1287ff9835ee9..80e4672acdd0e 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/CryptoKit.cs @@ -22,9 +22,9 @@ internal unsafe partial struct ChaChaPoly /// <summary> /// Represents Nonce in C#. /// </summary> - internal sealed unsafe partial class Nonce : IDisposable + internal sealed unsafe partial class Nonce : IDisposable, ISwiftObject { - private const int PayloadSize = 16; + private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Swift.Runtime.GetValueWitnessTable(Metadata))->Size; private readonly void* _payload; @@ -57,6 +57,8 @@ internal Nonce(Data data) internal void* Payload => _payload; + public static void* Metadata => CryptoKit.PInvoke_ChaChaPoly_Nonce_GetMetadata(); + public void Dispose() { if (!_disposed) @@ -162,9 +164,9 @@ internal unsafe partial struct AesGcm /// <summary> /// Represents Nonce in C#. /// </summary> - internal sealed unsafe partial class Nonce : IDisposable + internal sealed unsafe partial class Nonce : IDisposable, ISwiftObject { - private const int PayloadSize = 16; + private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Swift.Runtime.GetValueWitnessTable(Metadata))->Size; private readonly void* _payload; @@ -197,6 +199,8 @@ internal Nonce(Data data) internal void* Payload => _payload; + public static void* Metadata => CryptoKit.PInvoke_AesGcm_Nonce_GetMetadata(); + public void Dispose() { if (!_disposed) @@ -216,9 +220,9 @@ public void Dispose() /// <summary> /// Represents SealedBox in C#. /// </summary> - internal sealed unsafe partial class SealedBox : IDisposable + internal sealed unsafe partial class SealedBox : IDisposable, ISwiftObject { - private const int PayloadSize = 24; + private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Swift.Runtime.GetValueWitnessTable(Metadata))->Size; private readonly void* _payload; @@ -260,6 +264,8 @@ internal SealedBox(AesGcm.Nonce nonce, Data ciphertext, Data tag) internal void* Payload => _payload; + public static void* Metadata => CryptoKit.PInvoke_AesGcm_SealedBox_GetMetadata(); + internal Data Ciphertext => CryptoKit.PInvoke_AesGcm_SealedBox_GetCiphertext(new SwiftSelf(_payload)); internal Data Tag => CryptoKit.PInvoke_AesGcm_SealedBox_GetTag(new SwiftSelf(_payload)); @@ -331,9 +337,9 @@ internal static unsafe Data open<AuthenticateData>(SealedBox sealedBox, Symmetri /// <summary> /// Represents SymmetricKey in C#. /// </summary> - internal sealed unsafe partial class SymmetricKey : IDisposable + internal sealed unsafe partial class SymmetricKey : IDisposable, ISwiftObject { - private const int PayloadSize = 8; + private static nuint PayloadSize = (nuint)((Runtime.ValueWitnessTable*)Swift.Runtime.GetValueWitnessTable(Metadata))->Size; internal readonly void* _payload; @@ -360,6 +366,8 @@ internal SymmetricKey(Data data) internal void* Payload => _payload; + public static void* Metadata => CryptoKit.PInvoke_SymmetricKey_GetMetadata(); + public void Dispose() { if (!_disposed) @@ -407,6 +415,10 @@ internal static partial class CryptoKit [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_ChaChaPoly_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVMa")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_ChaChaPoly_Nonce_GetMetadata(); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit03ChaC4PolyO9SealedBoxV10ciphertext10Foundation4DataVvg")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial Data PInvoke_ChaChaPoly_SealedBox_GetCiphertext(ChaChaPoly.SealedBox sealedBox); @@ -427,6 +439,10 @@ internal static partial class CryptoKit [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_AesGcm_Nonce_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable, out SwiftError error); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO5NonceVMa")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_AesGcm_Nonce_GetMetadata(); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxV10ciphertext10Foundation4DataVvg")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial Data PInvoke_AesGcm_SealedBox_GetCiphertext(SwiftSelf sealedBox); @@ -439,6 +455,10 @@ internal static partial class CryptoKit [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_AesGcm_SealedBox_Init(SwiftIndirectResult result, void* nonce, void* ciphertext, void* tag, void* ciphertextMetadata, void* tagMetadata, void* ciphertextWitnessTable, void* tagWitnessTable, out SwiftError error); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit3AESO3GCMO9SealedBoxVMa")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_AesGcm_SealedBox_GetMetadata(); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyV4sizeAcA0cD4SizeV_tcfC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_SymmetricKey_Init(SwiftIndirectResult result, SymmetricKeySize* symmetricKeySize); @@ -447,6 +467,10 @@ internal static partial class CryptoKit [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_SymmetricKey_Init2(SwiftIndirectResult result, void* data, void* metadata, void* witnessTable); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit12SymmetricKeyVMa")] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] + internal static unsafe partial void* PInvoke_SymmetricKey_GetMetadata(); + [LibraryImport(Path, EntryPoint = "$s9CryptoKit16SymmetricKeySizeV8bitCountACSi_tcfC")] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] internal static unsafe partial void PInvoke_init(SwiftIndirectResult result, nint bitCount); diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs index 8969fb49da0e9..1c5ecec46f365 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/Foundation.cs @@ -201,11 +201,58 @@ internal static partial class Foundation /// </summary> internal static partial class Runtime { + /// <summary> + /// https://github.com/apple/swift/blob/main/include/swift/ABI/MetadataValues.h#L117 + /// </summary> + [Flags] + public enum ValueWitnessFlags + { + AlignmentMask = 0x0000FFFF, + IsNonPOD = 0x00010000, + IsNonInline = 0x00020000, + HasSpareBits = 0x00080000, + IsNonBitwiseTakable = 0x00100000, + HasEnumWitnesses = 0x00200000, + Incomplete = 0x00400000, + } + + /// <summary> + /// See https://github.com/apple/swift/blob/main/include/swift/ABI/ValueWitness.def + /// </summary> + [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; + } + internal static unsafe void* GetMetadata<T>(T type) where T: ISwiftObject { return T.Metadata; } + internal static unsafe void* GetValueWitnessTable(void* metadata) + { + void* valueWitnessTable = (void*)Marshal.ReadIntPtr((IntPtr)metadata, -IntPtr.Size); + return valueWitnessTable; + } + internal static unsafe void* GetConformanceDescriptor(string symbol) { IntPtr handle = IntPtr.Zero;