From 5be85615f2c82c4ea9fe6ebec6b38b12a2256717 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 22 May 2024 11:15:13 -0700 Subject: [PATCH 1/9] Try converting our CryptoKit bindings to use more Swift types. Also refactor our cryptokit bindings to reduce duplication. --- .../OSX/Swift.Runtime/UnsafeBufferPointer.cs | 39 +++ .../Interop.Aead.cs | 185 ++++++------ .../src/System.Security.Cryptography.csproj | 2 + .../entrypoints.c | 1 + .../pal_swiftbindings.h | 1 + .../pal_swiftbindings.swift | 274 +++++++++--------- 6 files changed, 259 insertions(+), 243 deletions(-) create mode 100644 src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs new file mode 100644 index 0000000000000..70b86da713135 --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs @@ -0,0 +1,39 @@ +// 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#. + // + public unsafe readonly struct UnsafeBufferPointer where T : unmanaged + { + private readonly T* _baseAddress; + private readonly nint _count; + public UnsafeBufferPointer(T* baseAddress, nint count) + { + _baseAddress = baseAddress; + _count = count; + } + + public T* BaseAddress => _baseAddress; + public nint Count => _count; + } + + // + // Represents Swift UnsafeMutableBufferPointer in C#. + // + public unsafe readonly 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 2f405e0bfd0da..47722b567abde 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 @@ -29,18 +29,17 @@ internal static partial class AppleCrypto fixed (byte* tagPtr = tag) fixed (byte* aadPtr = aad) { - const int Success = 1; - int result = AppleCryptoNative_ChaCha20Poly1305Encrypt( - keyPtr, key.Length, - noncePtr, nonce.Length, - plaintextPtr, plaintext.Length, - ciphertextPtr, ciphertext.Length, - tagPtr, tag.Length, - aadPtr, aad.Length); - - if (result != Success) + AppleCryptoNative_ChaCha20Poly1305Encrypt( + new(keyPtr, key.Length), + new(noncePtr, nonce.Length), + new(plaintextPtr, plaintext.Length), + new(ciphertextPtr, ciphertext.Length), + new(tagPtr, tag.Length), + new(aadPtr, aad.Length), + out SwiftError error); + + if (error.Value != null) { - Debug.Assert(result == 0); CryptographicOperations.ZeroMemory(ciphertext); CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); @@ -63,27 +62,25 @@ internal static partial class AppleCrypto fixed (byte* plaintextPtr = plaintext) fixed (byte* aadPtr = aad) { - const int Success = 1; - const int AuthTagMismatch = -1; - int result = AppleCryptoNative_ChaCha20Poly1305Decrypt( - keyPtr, key.Length, - noncePtr, nonce.Length, - ciphertextPtr, ciphertext.Length, - tagPtr, tag.Length, - plaintextPtr, plaintext.Length, - aadPtr, aad.Length); - - if (result != Success) + AppleCryptoNative_ChaCha20Poly1305Decrypt( + new(keyPtr, key.Length), + new(noncePtr, nonce.Length), + new(ciphertextPtr, ciphertext.Length), + new(tagPtr, tag.Length), + new(plaintextPtr, plaintext.Length), + new(aadPtr, aad.Length), + out SwiftError error); + + if (error.Value != null) { CryptographicOperations.ZeroMemory(plaintext); - if (result == AuthTagMismatch) + if (AppleCryptoNative_IsAuthenticationFailure(error.Value) == AuthTagMismatch) { throw new AuthenticationTagMismatchException(); } else { - Debug.Assert(result == 0); throw new CryptographicException(); } } @@ -105,18 +102,18 @@ internal static partial class AppleCrypto fixed (byte* tagPtr = tag) fixed (byte* aadPtr = aad) { - const int Success = 1; - int result = AppleCryptoNative_AesGcmEncrypt( - keyPtr, key.Length, - noncePtr, nonce.Length, - plaintextPtr, plaintext.Length, - ciphertextPtr, ciphertext.Length, - tagPtr, tag.Length, - aadPtr, aad.Length); - - if (result != Success) + SwiftError error; + AppleCryptoNative_AesGcmEncrypt( + new(keyPtr, key.Length), + new(noncePtr, nonce.Length), + new(plaintextPtr, plaintext.Length), + new(ciphertextPtr, ciphertext.Length), + new(tagPtr, tag.Length), + new(aadPtr, aad.Length), + out SwiftError error); + + if (error.Value != null) { - Debug.Assert(result == 0); CryptographicOperations.ZeroMemory(ciphertext); CryptographicOperations.ZeroMemory(tag); throw new CryptographicException(); @@ -139,27 +136,26 @@ internal static partial class AppleCrypto fixed (byte* plaintextPtr = plaintext) fixed (byte* aadPtr = aad) { - const int Success = 1; - const int AuthTagMismatch = -1; - int result = AppleCryptoNative_AesGcmDecrypt( - keyPtr, key.Length, - noncePtr, nonce.Length, - ciphertextPtr, ciphertext.Length, - tagPtr, tag.Length, - plaintextPtr, plaintext.Length, - aadPtr, aad.Length); - - if (result != Success) + SwiftError error; + AppleCryptoNative_AesGcmDecrypt( + new(keyPtr, key.Length), + new(noncePtr, nonce.Length), + new(ciphertextPtr, ciphertext.Length), + new(tagPtr, tag.Length), + new(plaintextPtr, plaintext.Length), + new(aadPtr, aad.Length), + out SwiftError error); + + if (error.Value != null) { CryptographicOperations.ZeroMemory(plaintext); - if (result == AuthTagMismatch) + if (AppleCryptoNative_IsAuthenticationFailure(error.Value) == AuthTagMismatch) { throw new AuthenticationTagMismatchException(); } else { - Debug.Assert(result == 0); throw new CryptographicException(); } } @@ -168,66 +164,55 @@ internal static partial class AppleCrypto [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] - private static unsafe partial int AppleCryptoNative_ChaCha20Poly1305Encrypt( - byte* keyPtr, - int keyLength, - byte* noncePtr, - int nonceLength, - byte* plaintextPtr, - int plaintextLength, - byte* ciphertextPtr, - int ciphertextLength, - byte* tagPtr, - int tagLength, - byte* aadPtr, - int aadLength); + private static unsafe partial void AppleCryptoNative_ChaCha20Poly1305Encrypt( + 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 int AppleCryptoNative_ChaCha20Poly1305Decrypt( - byte* keyPtr, - int keyLength, - byte* noncePtr, - int nonceLength, - byte* ciphertextPtr, - int ciphertextLength, - byte* tagPtr, - int tagLength, - byte* plaintextPtr, - int plaintextLength, - byte* aadPtr, - int aadLength); + 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 int AppleCryptoNative_AesGcmEncrypt( - byte* keyPtr, - int keyLength, - byte* noncePtr, - int nonceLength, - byte* plaintextPtr, - int plaintextLength, - byte* ciphertextPtr, - int ciphertextLength, - byte* tagPtr, - int tagLength, - byte* aadPtr, - int aadLength); + 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 int AppleCryptoNative_AesGcmDecrypt( - byte* keyPtr, - int keyLength, - byte* noncePtr, - int nonceLength, - byte* ciphertextPtr, - int ciphertextLength, - byte* tagPtr, - int tagLength, - byte* plaintextPtr, - int plaintextLength, - byte* aadPtr, - int aadLength); + private static unsafe partial void AppleCryptoNative_AesGcmDecrypt( + UnsafeBufferPointer key, + UnsafeBufferPointer nonce, + UnsafeBufferPointer ciphertext, + UnsafeBufferPointer tag, + UnsafeMutableBufferPointer plaintext, + UnsafeBufferPointer aad, + out SwiftError error + ); + + [LibraryImport(Libraries.AppleCryptoNative)] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvSwift) })] + [return: MarshalAs(UnmanagedType.U1)] + private static unsafe partial bool AppleCryptoNative_IsAuthenticationFailure(void* error); } } 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 ae5affcbb971a..4a7bd04e14eec 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1210,6 +1210,8 @@ Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EvpPkey.Rsa.cs" /> + , - ciphertextBufferLength: Int32, - tagBuffer: UnsafeMutablePointer, - tagBufferLength: Int32, - aadPtr: UnsafeMutableRawPointer, - aadLength: Int32 - ) -> Int32 { - let nonceData = Data(bytesNoCopy: noncePtr, count: Int(nonceLength), deallocator: Data.Deallocator.none) - let key = Data(bytesNoCopy: keyPtr, count: Int(keyLength), deallocator: Data.Deallocator.none) - let plaintext = Data(bytesNoCopy: plaintextPtr, count: Int(plaintextLength), deallocator: Data.Deallocator.none) - let aad = Data(bytesNoCopy: aadPtr, count: Int(aadLength), deallocator: Data.Deallocator.none) - let symmetricKey = SymmetricKey(data: key) +protocol NonceProtocol { + init(data: D) throws where D : DataProtocol +} - guard let nonce = try? ChaChaPoly.Nonce(data: nonceData) else { - return 0 - } +protocol SealedBoxProtocol where N: NonceProtocol { + var ciphertext: Data { get } + var tag: Data { get } - guard let result = try? ChaChaPoly.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) else { - return 0 - } + init( + nonce: N, + ciphertext: C, + tag: T + ) throws where C : DataProtocol, T : DataProtocol +} - assert(ciphertextBufferLength >= result.ciphertext.count) - assert(tagBufferLength >= result.tag.count) +protocol AEADSymmetricAlgorithm +{ + associatedtype Nonce : NonceProtocol + associatedtype SealedBox : SealedBoxProtocol - result.ciphertext.copyBytes(to: ciphertextBuffer, count: result.ciphertext.count) - result.tag.copyBytes(to: tagBuffer, count: result.tag.count) - return 1 - } + static func seal(_ plaintext: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil, authenticating additionalData: AuthenticatedData) throws -> SealedBox where Plaintext: DataProtocol, AuthenticatedData: DataProtocol + static func open(_ sealedBox: SealedBox, using key: SymmetricKey, authenticating additionalData: AuthenticatedData) throws -> Data where AuthenticatedData: DataProtocol +} + +extension AES.GCM.SealedBox: SealedBoxProtocol {} +extension AES.GCM.Nonce: NonceProtocol {} +extension AES.GCM: AEADSymmetricAlgorithm {} + +extension ChaChaPoly.SealedBox: SealedBoxProtocol {} +extension ChaChaPoly.Nonce: NonceProtocol {} +extension ChaChaPoly: AEADSymmetricAlgorithm {} + +func encrypt( + _ algorithm: Algorithm.Type, + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + plaintext: UnsafeBufferPointer, + cipherText: UnsafeMutableBufferPointer, + tag: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer) throws where Algorithm: AEADSymmetricAlgorithm { -@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Decrypt") -public func AppleCryptoNative_ChaCha20Poly1305Decrypt( - keyPtr: UnsafeMutableRawPointer, - keyLength: Int32, - noncePtr: UnsafeMutableRawPointer, - nonceLength: Int32, - ciphertextPtr: UnsafeMutableRawPointer, - ciphertextLength: Int32, - tagPtr: UnsafeMutableRawPointer, - tagLength: Int32, - plaintextBuffer: UnsafeMutablePointer, - plaintextBufferLength: Int32, - aadPtr: UnsafeMutableRawPointer, - aadLength: Int32 -) -> Int32 { - let nonceData = Data(bytesNoCopy: noncePtr, count: Int(nonceLength), deallocator: Data.Deallocator.none) - let key = Data(bytesNoCopy: keyPtr, count: Int(keyLength), deallocator: Data.Deallocator.none) - let ciphertext = Data(bytesNoCopy: ciphertextPtr, count: Int(ciphertextLength), deallocator: Data.Deallocator.none) - let aad = Data(bytesNoCopy: aadPtr, count: Int(aadLength), deallocator: Data.Deallocator.none) - let tag = Data(bytesNoCopy: tagPtr, count: Int(tagLength), deallocator: Data.Deallocator.none) let symmetricKey = SymmetricKey(data: key) - guard let nonce = try? ChaChaPoly.Nonce(data: nonceData) else { - return 0 - } - - guard let sealedBox = try? ChaChaPoly.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) else { - return 0 - } - - do { - let result = try ChaChaPoly.open(sealedBox, using: symmetricKey, authenticating: aad) - - assert(plaintextBufferLength >= result.count) - result.copyBytes(to: plaintextBuffer, count: result.count) - return 1 - } - catch CryptoKitError.authenticationFailure { - return -1 - } - catch { - return 0 - } + let nonce = try Algorithm.Nonce(data: nonceData) + + let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) + + result.ciphertext.copyBytes(to: cipherText) + result.tag.copyBytes(to: tag) } -@_silgen_name("AppleCryptoNative_AesGcmEncrypt") -public func AppleCryptoNative_AesGcmEncrypt( - keyPtr: UnsafeMutableRawPointer, - keyLength: Int32, - noncePtr: UnsafeMutableRawPointer, - nonceLength: Int32, - plaintextPtr: UnsafeMutableRawPointer, - plaintextLength: Int32, - ciphertextBuffer: UnsafeMutablePointer, - ciphertextBufferLength: Int32, - tagBuffer: UnsafeMutablePointer, - tagBufferLength: Int32, - aadPtr: UnsafeMutableRawPointer, - aadLength: Int32 - ) -> Int32 { - let nonceData = Data(bytesNoCopy: noncePtr, count: Int(nonceLength), deallocator: Data.Deallocator.none) - let key = Data(bytesNoCopy: keyPtr, count: Int(keyLength), deallocator: Data.Deallocator.none) - let plaintext = Data(bytesNoCopy: plaintextPtr, count: Int(plaintextLength), deallocator: Data.Deallocator.none) - let aad = Data(bytesNoCopy: aadPtr, count: Int(aadLength), deallocator: Data.Deallocator.none) +func decrypt( + _ algorithm: Algorithm.Type, + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + cipherText: UnsafeBufferPointer, + tag: UnsafeBufferPointer, + plaintext: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer) throws where Algorithm: AEADSymmetricAlgorithm { + let symmetricKey = SymmetricKey(data: key) - guard let nonce = try? AES.GCM.Nonce(data: nonceData) else { - return 0 - } + let nonce = try Algorithm.Nonce(data: nonceData) + + let sealedBox = try Algorithm.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) - guard let result = try? AES.GCM.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) else { - return 0 - } + let result = try Algorithm.open(sealedBox, using: symmetricKey, authenticating: aad) - assert(ciphertextBufferLength >= result.ciphertext.count) - assert(tagBufferLength >= result.tag.count) + result.copyBytes(to: plaintext) +} - result.ciphertext.copyBytes(to: ciphertextBuffer, count: result.ciphertext.count) - result.tag.copyBytes(to: tagBuffer, count: result.tag.count) - return 1 +@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt") +public func AppleCryptoNative_ChaCha20Poly1305Encrypt( + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + plaintext: UnsafeBufferPointer, + cipherText: UnsafeMutableBufferPointer, + tag: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer +) throws { + return try encrypt( + algorithm: ChaChaPoly.self, + key: key, + nonceData: nonceData, + plaintext: plaintext, + cipherText: cipherText, + tag: tag, + aad: aad) + } + +@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Decrypt") +public func AppleCryptoNative_ChaCha20Poly1305Decrypt( + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + cipherText: UnsafeBufferPointer, + tag: UnsafeBufferPointer, + plaintext: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer +) throws { + return try decrypt( + algorithm: ChaChaPoly.self, + key: key, + nonceData: nonceData, + cipherText: cipherText, + tag: tag, + plaintext: plaintext, + aad: aad); +} + +@_silgen_name("AppleCryptoNative_AesGcmEncrypt") +public func AppleCryptoNative_AesGcmEncrypt( + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + plaintext: UnsafeBufferPointer, + cipherText: UnsafeMutableBufferPointer, + tag: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer +) throws { + return try encrypt( + algorithm: AES.GCM.self, + key: key, + nonceData: nonceData, + plaintext: plaintext, + cipherText: cipherText, + tag: tag, + aad: aad) } @_silgen_name("AppleCryptoNative_AesGcmDecrypt") public func AppleCryptoNative_AesGcmDecrypt( - keyPtr: UnsafeMutableRawPointer, - keyLength: Int32, - noncePtr: UnsafeMutableRawPointer, - nonceLength: Int32, - ciphertextPtr: UnsafeMutableRawPointer, - ciphertextLength: Int32, - tagPtr: UnsafeMutableRawPointer, - tagLength: Int32, - plaintextBuffer: UnsafeMutablePointer, - plaintextBufferLength: Int32, - aadPtr: UnsafeMutableRawPointer, - aadLength: Int32 -) -> Int32 { - let nonceData = Data(bytesNoCopy: noncePtr, count: Int(nonceLength), deallocator: Data.Deallocator.none) - let key = Data(bytesNoCopy: keyPtr, count: Int(keyLength), deallocator: Data.Deallocator.none) - let ciphertext = Data(bytesNoCopy: ciphertextPtr, count: Int(ciphertextLength), deallocator: Data.Deallocator.none) - let aad = Data(bytesNoCopy: aadPtr, count: Int(aadLength), deallocator: Data.Deallocator.none) - let tag = Data(bytesNoCopy: tagPtr, count: Int(tagLength), deallocator: Data.Deallocator.none) - let symmetricKey = SymmetricKey(data: key) + key: UnsafeBufferPointer, + nonceData: UnsafeBufferPointer, + cipherText: UnsafeBufferPointer, + tag: UnsafeBufferPointer, + plaintext: UnsafeMutableBufferPointer, + aad: UnsafeBufferPointer +) throws { + return try decrypt( + algorithm: AES.GCM.self, + key: key, + nonceData: nonceData, + cipherText: cipherText, + tag: tag, + plaintext: plaintext, + aad: aad); +} - guard let nonce = try? AES.GCM.Nonce(data: nonceData) else { - return 0 - } - - guard let sealedBox = try? AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) else { - return 0 - } - - do { - let result = try AES.GCM.open(sealedBox, using: symmetricKey, authenticating: aad) - - assert(plaintextBufferLength >= result.count) - result.copyBytes(to: plaintextBuffer, count: result.count) - return 1 - } - catch CryptoKitError.authenticationFailure { - return -1 - } - catch { - return 0 - } +@_silgen_name("AppleCryptoNative_IsAuthenticationFailure") +public func AppleCryptoNative_IsAuthenticationFailure(error: Error) -> Bool { + return error is CryptoKitError && error as! CryptoKitError == CryptoKitError.authenticationFailure } From bad0a95359d1c3cdfdce74552862536549535cd9 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 22 May 2024 13:04:36 -0700 Subject: [PATCH 2/9] Fix build on macos --- .../OSX/Swift.Runtime/UnsafeBufferPointer.cs | 4 +- .../Interop.Aead.cs | 8 +-- .../pal_swiftbindings.swift | 50 ++++++++++++------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs index 70b86da713135..ec54fb705a836 100644 --- a/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs +++ b/src/libraries/Common/src/Interop/OSX/Swift.Runtime/UnsafeBufferPointer.cs @@ -6,7 +6,7 @@ namespace Swift.Runtime // // Represents Swift UnsafeBufferPointer in C#. // - public unsafe readonly struct UnsafeBufferPointer where T : unmanaged + internal readonly unsafe struct UnsafeBufferPointer where T : unmanaged { private readonly T* _baseAddress; private readonly nint _count; @@ -23,7 +23,7 @@ public UnsafeBufferPointer(T* baseAddress, nint count) // // Represents Swift UnsafeMutableBufferPointer in C#. // - public unsafe readonly struct UnsafeMutableBufferPointer where T : unmanaged + internal readonly unsafe struct UnsafeMutableBufferPointer where T : unmanaged { private readonly T* _baseAddress; private readonly nint _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 47722b567abde..19c0d9314b80a 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 @@ -5,8 +5,10 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Swift; using System.Security.Cryptography; using System.Security.Cryptography.Apple; +using Swift.Runtime; #pragma warning disable CS3016 // Arrays as attribute arguments are not CLS Compliant @@ -75,7 +77,7 @@ internal static partial class AppleCrypto { CryptographicOperations.ZeroMemory(plaintext); - if (AppleCryptoNative_IsAuthenticationFailure(error.Value) == AuthTagMismatch) + if (AppleCryptoNative_IsAuthenticationFailure(error.Value)) { throw new AuthenticationTagMismatchException(); } @@ -102,7 +104,6 @@ internal static partial class AppleCrypto fixed (byte* tagPtr = tag) fixed (byte* aadPtr = aad) { - SwiftError error; AppleCryptoNative_AesGcmEncrypt( new(keyPtr, key.Length), new(noncePtr, nonce.Length), @@ -136,7 +137,6 @@ internal static partial class AppleCrypto fixed (byte* plaintextPtr = plaintext) fixed (byte* aadPtr = aad) { - SwiftError error; AppleCryptoNative_AesGcmDecrypt( new(keyPtr, key.Length), new(noncePtr, nonce.Length), @@ -150,7 +150,7 @@ internal static partial class AppleCrypto { CryptographicOperations.ZeroMemory(plaintext); - if (AppleCryptoNative_IsAuthenticationFailure(error.Value) == AuthTagMismatch) + if (AppleCryptoNative_IsAuthenticationFailure(error.Value)) { throw new AuthenticationTagMismatchException(); } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift index 16d4630de5861..4f46cac4c59be 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift @@ -8,32 +8,36 @@ protocol NonceProtocol { init(data: D) throws where D : DataProtocol } -protocol SealedBoxProtocol where N: NonceProtocol { +protocol SealedBoxProtocol { + associatedtype Nonce : NonceProtocol + var ciphertext: Data { get } var tag: Data { get } init( - nonce: N, + nonce: Nonce, ciphertext: C, tag: T ) throws where C : DataProtocol, T : DataProtocol } -protocol AEADSymmetricAlgorithm -{ - associatedtype Nonce : NonceProtocol +protocol AEADSymmetricAlgorithm { associatedtype SealedBox : SealedBoxProtocol - static func seal(_ plaintext: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil, authenticating additionalData: AuthenticatedData) throws -> SealedBox where Plaintext: DataProtocol, AuthenticatedData: DataProtocol + static func seal(_ plaintext: Plaintext, using key: SymmetricKey, nonce: SealedBox.Nonce?, authenticating additionalData: AuthenticatedData) throws -> SealedBox where Plaintext: DataProtocol, AuthenticatedData: DataProtocol static func open(_ sealedBox: SealedBox, using key: SymmetricKey, authenticating additionalData: AuthenticatedData) throws -> Data where AuthenticatedData: DataProtocol } -extension AES.GCM.SealedBox: SealedBoxProtocol {} extension AES.GCM.Nonce: NonceProtocol {} +extension AES.GCM.SealedBox: SealedBoxProtocol { + typealias Nonce = AES.GCM.Nonce +} extension AES.GCM: AEADSymmetricAlgorithm {} -extension ChaChaPoly.SealedBox: SealedBoxProtocol {} extension ChaChaPoly.Nonce: NonceProtocol {} +extension ChaChaPoly.SealedBox: SealedBoxProtocol { + typealias Nonce = ChaChaPoly.Nonce +} extension ChaChaPoly: AEADSymmetricAlgorithm {} func encrypt( @@ -47,12 +51,12 @@ func encrypt( let symmetricKey = SymmetricKey(data: key) - let nonce = try Algorithm.Nonce(data: nonceData) + let nonce = try Algorithm.SealedBox.Nonce(data: nonceData) let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) - result.ciphertext.copyBytes(to: cipherText) - result.tag.copyBytes(to: tag) + _ = result.ciphertext.copyBytes(to: cipherText) + _ = result.tag.copyBytes(to: tag) } func decrypt( @@ -66,13 +70,13 @@ func decrypt( let symmetricKey = SymmetricKey(data: key) - let nonce = try Algorithm.Nonce(data: nonceData) + let nonce = try Algorithm.SealedBox.Nonce(data: nonceData) - let sealedBox = try Algorithm.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) + 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) + _ = result.copyBytes(to: plaintext) } @_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt") @@ -85,7 +89,7 @@ public func AppleCryptoNative_ChaCha20Poly1305Encrypt( aad: UnsafeBufferPointer ) throws { return try encrypt( - algorithm: ChaChaPoly.self, + ChaChaPoly.self, key: key, nonceData: nonceData, plaintext: plaintext, @@ -104,7 +108,7 @@ public func AppleCryptoNative_ChaCha20Poly1305Decrypt( aad: UnsafeBufferPointer ) throws { return try decrypt( - algorithm: ChaChaPoly.self, + ChaChaPoly.self, key: key, nonceData: nonceData, cipherText: cipherText, @@ -123,7 +127,7 @@ public func AppleCryptoNative_AesGcmEncrypt( aad: UnsafeBufferPointer ) throws { return try encrypt( - algorithm: AES.GCM.self, + AES.GCM.self, key: key, nonceData: nonceData, plaintext: plaintext, @@ -142,7 +146,7 @@ public func AppleCryptoNative_AesGcmDecrypt( aad: UnsafeBufferPointer ) throws { return try decrypt( - algorithm: AES.GCM.self, + AES.GCM.self, key: key, nonceData: nonceData, cipherText: cipherText, @@ -153,5 +157,13 @@ public func AppleCryptoNative_AesGcmDecrypt( @_silgen_name("AppleCryptoNative_IsAuthenticationFailure") public func AppleCryptoNative_IsAuthenticationFailure(error: Error) -> Bool { - return error is CryptoKitError && error as! CryptoKitError == CryptoKitError.authenticationFailure + if let error = error as? CryptoKitError { + switch error { + case .authenticationFailure: + return true + default: + return false + } + } + return false } From d9705c2f3a7346d5e60d8c1b600e74c5f929e7f0 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 22 May 2024 15:39:15 -0700 Subject: [PATCH 3/9] Remove target-typed new and other style changes --- .../Interop.Aead.cs | 60 +++++++++---------- .../entrypoints.c | 2 +- 2 files changed, 29 insertions(+), 33 deletions(-) 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 19c0d9314b80a..79650f2750033 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 @@ -32,12 +32,12 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = aad) { AppleCryptoNative_ChaCha20Poly1305Encrypt( - new(keyPtr, key.Length), - new(noncePtr, nonce.Length), - new(plaintextPtr, plaintext.Length), - new(ciphertextPtr, ciphertext.Length), - new(tagPtr, tag.Length), - new(aadPtr, aad.Length), + 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), out SwiftError error); if (error.Value != null) @@ -65,12 +65,12 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = aad) { AppleCryptoNative_ChaCha20Poly1305Decrypt( - new(keyPtr, key.Length), - new(noncePtr, nonce.Length), - new(ciphertextPtr, ciphertext.Length), - new(tagPtr, tag.Length), - new(plaintextPtr, plaintext.Length), - new(aadPtr, aad.Length), + 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), out SwiftError error); if (error.Value != null) @@ -105,12 +105,12 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = aad) { AppleCryptoNative_AesGcmEncrypt( - new(keyPtr, key.Length), - new(noncePtr, nonce.Length), - new(plaintextPtr, plaintext.Length), - new(ciphertextPtr, ciphertext.Length), - new(tagPtr, tag.Length), - new(aadPtr, aad.Length), + 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), out SwiftError error); if (error.Value != null) @@ -138,12 +138,12 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = aad) { AppleCryptoNative_AesGcmDecrypt( - new(keyPtr, key.Length), - new(noncePtr, nonce.Length), - new(ciphertextPtr, ciphertext.Length), - new(tagPtr, tag.Length), - new(plaintextPtr, plaintext.Length), - new(aadPtr, aad.Length), + 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), out SwiftError error); if (error.Value != null) @@ -171,8 +171,7 @@ internal static partial class AppleCrypto UnsafeMutableBufferPointer ciphertext, UnsafeMutableBufferPointer tag, UnsafeBufferPointer aad, - out SwiftError error - ); + out SwiftError error); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] @@ -183,8 +182,7 @@ internal static partial class AppleCrypto UnsafeBufferPointer tag, UnsafeMutableBufferPointer plaintext, UnsafeBufferPointer aad, - out SwiftError error - ); + out SwiftError error); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] @@ -195,8 +193,7 @@ internal static partial class AppleCrypto UnsafeMutableBufferPointer ciphertext, UnsafeMutableBufferPointer tag, UnsafeBufferPointer aad, - out SwiftError error - ); + out SwiftError error); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] @@ -207,8 +204,7 @@ internal static partial class AppleCrypto UnsafeBufferPointer tag, UnsafeMutableBufferPointer plaintext, UnsafeBufferPointer aad, - out SwiftError error - ); + out SwiftError error); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvSwift) })] diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c index 1df74317c43db..41395f63b201f 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c @@ -30,7 +30,6 @@ static const Entry s_cryptoAppleNative[] = DllImportEntry(AppleCryptoNative_AesGcmDecrypt) DllImportEntry(AppleCryptoNative_ChaCha20Poly1305Encrypt) DllImportEntry(AppleCryptoNative_ChaCha20Poly1305Decrypt) - DllImportEntry(AppleCryptoNative_IsAuthenticationFailure) DllImportEntry(AppleCryptoNative_DigestFree) DllImportEntry(AppleCryptoNative_DigestCreate) DllImportEntry(AppleCryptoNative_DigestUpdate) @@ -49,6 +48,7 @@ static const Entry s_cryptoAppleNative[] = DllImportEntry(AppleCryptoNative_HmacFinal) DllImportEntry(AppleCryptoNative_HmacCurrent) DllImportEntry(AppleCryptoNative_HmacOneShot) + DllImportEntry(AppleCryptoNative_IsAuthenticationFailure) DllImportEntry(AppleCryptoNative_SecKeychainItemCopyKeychain) DllImportEntry(AppleCryptoNative_SecKeychainCopyDefault) DllImportEntry(AppleCryptoNative_SecKeychainCreate) From e1852378d68a3921edc34b490da7c3299e85381c Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 23 May 2024 17:26:17 -0700 Subject: [PATCH 4/9] Don't pass down null with UnsafeBufferPointer --- .../Interop.Aead.cs | 35 ++++++++++++------- .../CMakeLists.txt | 2 +- .../pal_swiftbindings.swift | 2 ++ 3 files changed, 26 insertions(+), 13 deletions(-) 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 79650f2750033..c833b71c8eade 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 @@ -16,6 +16,17 @@ internal static partial class Interop { internal static partial class AppleCrypto { + private static byte NullSentinel; + + // CryptoKit doesn't do well with a null pointer for the buffer data, + // so provide a sentinel pointer instead. + private static ref readonly byte GetSwiftRef(ReadOnlySpan b) + { + return ref (b.Length == 0 + ? ref NullSentinel + : ref MemoryMarshal.GetReference(b)); + } + internal static unsafe void ChaCha20Poly1305Encrypt( ReadOnlySpan key, ReadOnlySpan nonce, @@ -26,10 +37,10 @@ internal static partial class AppleCrypto { fixed (byte* keyPtr = key) fixed (byte* noncePtr = nonce) - fixed (byte* plaintextPtr = plaintext) - fixed (byte* ciphertextPtr = ciphertext) + fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) + fixed (byte* ciphertextPtr = &GetSwiftRef(ciphertext)) fixed (byte* tagPtr = tag) - fixed (byte* aadPtr = aad) + fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_ChaCha20Poly1305Encrypt( new UnsafeBufferPointer(keyPtr, key.Length), @@ -59,10 +70,10 @@ internal static partial class AppleCrypto { fixed (byte* keyPtr = key) fixed (byte* noncePtr = nonce) - fixed (byte* ciphertextPtr = ciphertext) + fixed (byte* ciphertextPtr = &GetSwiftRef(ciphertext)) fixed (byte* tagPtr = tag) - fixed (byte* plaintextPtr = plaintext) - fixed (byte* aadPtr = aad) + fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) + fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_ChaCha20Poly1305Decrypt( new UnsafeBufferPointer(keyPtr, key.Length), @@ -99,10 +110,10 @@ internal static partial class AppleCrypto { fixed (byte* keyPtr = key) fixed (byte* noncePtr = nonce) - fixed (byte* plaintextPtr = plaintext) - fixed (byte* ciphertextPtr = ciphertext) + fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) + fixed (byte* ciphertextPtr = &GetSwiftRef(ciphertext)) fixed (byte* tagPtr = tag) - fixed (byte* aadPtr = aad) + fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_AesGcmEncrypt( new UnsafeBufferPointer(keyPtr, key.Length), @@ -132,10 +143,10 @@ internal static partial class AppleCrypto { fixed (byte* keyPtr = key) fixed (byte* noncePtr = nonce) - fixed (byte* ciphertextPtr = ciphertext) + fixed (byte* ciphertextPtr = &GetSwiftRef(ciphertext)) fixed (byte* tagPtr = tag) - fixed (byte* plaintextPtr = plaintext) - fixed (byte* aadPtr = aad) + fixed (byte* plaintextPtr = &GetSwiftRef(plaintext)) + fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_AesGcmDecrypt( new UnsafeBufferPointer(keyPtr, key.Length), diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/CMakeLists.txt b/src/native/libs/System.Security.Cryptography.Native.Apple/CMakeLists.txt index b847f5c3cd68b..a50ade7e86317 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/CMakeLists.txt +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/CMakeLists.txt @@ -51,7 +51,7 @@ endif() add_custom_command( OUTPUT pal_swiftbindings.o - COMMAND xcrun swiftc -emit-object -static -parse-as-library -runtime-compatibility-version none -sdk ${CMAKE_OSX_SYSROOT} -target ${SWIFT_COMPILER_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/pal_swiftbindings.swift -o pal_swiftbindings.o + COMMAND xcrun swiftc -emit-object -static -parse-as-library -enable-library-evolution -g -runtime-compatibility-version none -sdk ${CMAKE_OSX_SYSROOT} -target ${SWIFT_COMPILER_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/pal_swiftbindings.swift -o pal_swiftbindings.o MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/pal_swiftbindings.swift COMMENT "Compiling Swift file pal_swiftbindings.swift" ) diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift index 4f46cac4c59be..6b4cead0769a4 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift @@ -24,8 +24,10 @@ protocol SealedBoxProtocol { 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 } extension AES.GCM.Nonce: NonceProtocol {} From 3220d06e22904b957ba91d2fb833671129c20d6e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky <jekoritz@microsoft.com> Date: Fri, 24 May 2024 14:01:17 -0700 Subject: [PATCH 5/9] Call copyBytes with a pointer because everything else seems to fail some assert for some reason I can't figure out. --- .../pal_swiftbindings.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift index 6b4cead0769a4..932eb8baa472b 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift @@ -57,8 +57,8 @@ func encrypt<Algorithm>( let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) - _ = result.ciphertext.copyBytes(to: cipherText) - _ = result.tag.copyBytes(to: tag) + _ = result.ciphertext.copyBytes(to: cipherText.baseAddress!, count: cipherText.count) + _ = result.tag.copyBytes(to: tag.baseAddress!, count: tag.count) } func decrypt<Algorithm>( @@ -78,7 +78,7 @@ func decrypt<Algorithm>( let result = try Algorithm.open(sealedBox, using: symmetricKey, authenticating: aad) - _ = result.copyBytes(to: plaintext) + _ = result.copyBytes(to: plaintext.baseAddress!, count: plaintext.count) } @_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt") From a64218463b29c77f6e6ff89be42867ffe3399eb8 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky <jekoritz@microsoft.com> Date: Tue, 28 May 2024 13:29:11 -0700 Subject: [PATCH 6/9] Make copies and use copyBytes(to: buffer) again. --- .../pal_swiftbindings.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift index 932eb8baa472b..92d461886730b 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift @@ -57,8 +57,14 @@ func encrypt<Algorithm>( let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) - _ = result.ciphertext.copyBytes(to: cipherText.baseAddress!, count: cipherText.count) - _ = result.tag.copyBytes(to: tag.baseAddress!, count: tag.count) + // 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) } func decrypt<Algorithm>( @@ -78,7 +84,7 @@ func decrypt<Algorithm>( let result = try Algorithm.open(sealedBox, using: symmetricKey, authenticating: aad) - _ = result.copyBytes(to: plaintext.baseAddress!, count: plaintext.count) + _ = result.copyBytes(to: plaintext) } @_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt") From f22ddae33903c9265286377ab0a06d0077481212 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky <jkoritzinsky@gmail.com> Date: Fri, 31 May 2024 10:19:13 -0700 Subject: [PATCH 7/9] Fix generic value types condition --- src/mono/mono/metadata/marshal.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 90076ba1994ef..3369d3ee8173c 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -6818,9 +6818,11 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } // Non-value types are illegal at the interop boundary. - if (type->type == MONO_TYPE_GENERICINST && !mono_type_generic_inst_is_valuetype (type)) { - lowering.by_reference = TRUE; - return lowering; + if (type->type == MONO_TYPE_GENERICINST) { + if (!mono_type_generic_inst_is_valuetype (type)) { + lowering.by_reference = TRUE; + return lowering; + } } else if (type->type != MONO_TYPE_VALUETYPE && !mono_type_is_primitive(type)) { lowering.by_reference = TRUE; return lowering; From b13139b36a117cda7481e2395151858ff16e1e35 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky <jkoritzinsky@gmail.com> Date: Mon, 3 Jun 2024 13:43:06 -0700 Subject: [PATCH 8/9] Put SwiftError parameter first to try working around Mono register allocation bug --- .../Interop.Aead.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) 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 c833b71c8eade..27df7309b90a8 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 @@ -43,13 +43,13 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_ChaCha20Poly1305Encrypt( + out SwiftError error, new UnsafeBufferPointer<byte>(keyPtr, key.Length), new UnsafeBufferPointer<byte>(noncePtr, nonce.Length), new UnsafeBufferPointer<byte>(plaintextPtr, plaintext.Length), new UnsafeMutableBufferPointer<byte>(ciphertextPtr, ciphertext.Length), new UnsafeMutableBufferPointer<byte>(tagPtr, tag.Length), - new UnsafeBufferPointer<byte>(aadPtr, aad.Length), - out SwiftError error); + new UnsafeBufferPointer<byte>(aadPtr, aad.Length)); if (error.Value != null) { @@ -76,13 +76,13 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_ChaCha20Poly1305Decrypt( + out SwiftError error, new UnsafeBufferPointer<byte>(keyPtr, key.Length), new UnsafeBufferPointer<byte>(noncePtr, nonce.Length), new UnsafeBufferPointer<byte>(ciphertextPtr, ciphertext.Length), new UnsafeBufferPointer<byte>(tagPtr, tag.Length), new UnsafeMutableBufferPointer<byte>(plaintextPtr, plaintext.Length), - new UnsafeBufferPointer<byte>(aadPtr, aad.Length), - out SwiftError error); + new UnsafeBufferPointer<byte>(aadPtr, aad.Length)); if (error.Value != null) { @@ -116,13 +116,13 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_AesGcmEncrypt( + out SwiftError error, new UnsafeBufferPointer<byte>(keyPtr, key.Length), new UnsafeBufferPointer<byte>(noncePtr, nonce.Length), new UnsafeBufferPointer<byte>(plaintextPtr, plaintext.Length), new UnsafeMutableBufferPointer<byte>(ciphertextPtr, ciphertext.Length), new UnsafeMutableBufferPointer<byte>(tagPtr, tag.Length), - new UnsafeBufferPointer<byte>(aadPtr, aad.Length), - out SwiftError error); + new UnsafeBufferPointer<byte>(aadPtr, aad.Length)); if (error.Value != null) { @@ -149,13 +149,13 @@ internal static partial class AppleCrypto fixed (byte* aadPtr = &GetSwiftRef(aad)) { AppleCryptoNative_AesGcmDecrypt( + out SwiftError error, new UnsafeBufferPointer<byte>(keyPtr, key.Length), new UnsafeBufferPointer<byte>(noncePtr, nonce.Length), new UnsafeBufferPointer<byte>(ciphertextPtr, ciphertext.Length), new UnsafeBufferPointer<byte>(tagPtr, tag.Length), new UnsafeMutableBufferPointer<byte>(plaintextPtr, plaintext.Length), - new UnsafeBufferPointer<byte>(aadPtr, aad.Length), - out SwiftError error); + new UnsafeBufferPointer<byte>(aadPtr, aad.Length)); if (error.Value != null) { @@ -176,46 +176,46 @@ internal static partial class AppleCrypto [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] private static unsafe partial void AppleCryptoNative_ChaCha20Poly1305Encrypt( + out SwiftError error, UnsafeBufferPointer<byte> key, UnsafeBufferPointer<byte> nonce, UnsafeBufferPointer<byte> plaintext, UnsafeMutableBufferPointer<byte> ciphertext, UnsafeMutableBufferPointer<byte> tag, - UnsafeBufferPointer<byte> aad, - out SwiftError error); + UnsafeBufferPointer<byte> aad); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] private static unsafe partial void AppleCryptoNative_ChaCha20Poly1305Decrypt( + out SwiftError error, UnsafeBufferPointer<byte> key, UnsafeBufferPointer<byte> nonce, UnsafeBufferPointer<byte> ciphertext, UnsafeBufferPointer<byte> tag, UnsafeMutableBufferPointer<byte> plaintext, - UnsafeBufferPointer<byte> aad, - out SwiftError error); + UnsafeBufferPointer<byte> aad); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] private static unsafe partial void AppleCryptoNative_AesGcmEncrypt( + out SwiftError error. UnsafeBufferPointer<byte> key, UnsafeBufferPointer<byte> nonce, UnsafeBufferPointer<byte> plaintext, UnsafeMutableBufferPointer<byte> ciphertext, UnsafeMutableBufferPointer<byte> tag, - UnsafeBufferPointer<byte> aad, - out SwiftError error); + UnsafeBufferPointer<byte> aad); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] private static unsafe partial void AppleCryptoNative_AesGcmDecrypt( + out SwiftError error, UnsafeBufferPointer<byte> key, UnsafeBufferPointer<byte> nonce, UnsafeBufferPointer<byte> ciphertext, UnsafeBufferPointer<byte> tag, UnsafeMutableBufferPointer<byte> plaintext, - UnsafeBufferPointer<byte> aad, - out SwiftError error); + UnsafeBufferPointer<byte> aad); [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvSwift) })] From 9fda4d65c919874fe93f2bd2450d3555f5a06000 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky <jkoritzinsky@gmail.com> Date: Mon, 3 Jun 2024 14:26:07 -0700 Subject: [PATCH 9/9] Comma --- .../System.Security.Cryptography.Native.Apple/Interop.Aead.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 27df7309b90a8..3e7583694b1ca 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 @@ -198,7 +198,7 @@ internal static partial class AppleCrypto [LibraryImport(Libraries.AppleCryptoNative)] [UnmanagedCallConv(CallConvs = [ typeof(CallConvSwift) ])] private static unsafe partial void AppleCryptoNative_AesGcmEncrypt( - out SwiftError error. + out SwiftError error, UnsafeBufferPointer<byte> key, UnsafeBufferPointer<byte> nonce, UnsafeBufferPointer<byte> plaintext,