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..ec54fb705a836
--- /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#.
+ //
+ 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 2f405e0bfd0da..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
@@ -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
@@ -14,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,
@@ -24,23 +37,22 @@ internal static unsafe void ChaCha20Poly1305Encrypt(
{
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))
{
- 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(
+ out SwiftError error,
+ 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));
+
+ if (error.Value != null)
{
- Debug.Assert(result == 0);
CryptographicOperations.ZeroMemory(ciphertext);
CryptographicOperations.ZeroMemory(tag);
throw new CryptographicException();
@@ -58,32 +70,30 @@ internal static unsafe void ChaCha20Poly1305Decrypt(
{
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))
{
- 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(
+ out SwiftError error,
+ 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));
+
+ if (error.Value != null)
{
CryptographicOperations.ZeroMemory(plaintext);
- if (result == AuthTagMismatch)
+ if (AppleCryptoNative_IsAuthenticationFailure(error.Value))
{
throw new AuthenticationTagMismatchException();
}
else
{
- Debug.Assert(result == 0);
throw new CryptographicException();
}
}
@@ -100,23 +110,22 @@ internal static unsafe void AesGcmEncrypt(
{
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))
{
- 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)
+ AppleCryptoNative_AesGcmEncrypt(
+ out SwiftError error,
+ 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));
+
+ if (error.Value != null)
{
- Debug.Assert(result == 0);
CryptographicOperations.ZeroMemory(ciphertext);
CryptographicOperations.ZeroMemory(tag);
throw new CryptographicException();
@@ -134,32 +143,30 @@ internal static unsafe void AesGcmDecrypt(
{
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))
{
- 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)
+ AppleCryptoNative_AesGcmDecrypt(
+ out SwiftError error,
+ 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));
+
+ if (error.Value != null)
{
CryptographicOperations.ZeroMemory(plaintext);
- if (result == AuthTagMismatch)
+ if (AppleCryptoNative_IsAuthenticationFailure(error.Value))
{
throw new AuthenticationTagMismatchException();
}
else
{
- Debug.Assert(result == 0);
throw new CryptographicException();
}
}
@@ -168,66 +175,51 @@ internal static unsafe void AesGcmDecrypt(
[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(
+ out SwiftError error,
+ UnsafeBufferPointer key,
+ UnsafeBufferPointer nonce,
+ UnsafeBufferPointer plaintext,
+ UnsafeMutableBufferPointer ciphertext,
+ UnsafeMutableBufferPointer tag,
+ UnsafeBufferPointer aad);
[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(
+ out SwiftError error,
+ UnsafeBufferPointer key,
+ UnsafeBufferPointer nonce,
+ UnsafeBufferPointer ciphertext,
+ UnsafeBufferPointer tag,
+ UnsafeMutableBufferPointer plaintext,
+ UnsafeBufferPointer aad);
[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(
+ out SwiftError error,
+ UnsafeBufferPointer key,
+ UnsafeBufferPointer nonce,
+ UnsafeBufferPointer plaintext,
+ UnsafeMutableBufferPointer ciphertext,
+ UnsafeMutableBufferPointer tag,
+ UnsafeBufferPointer aad);
[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(
+ out SwiftError error,
+ UnsafeBufferPointer key,
+ UnsafeBufferPointer nonce,
+ UnsafeBufferPointer ciphertext,
+ UnsafeBufferPointer tag,
+ UnsafeMutableBufferPointer plaintext,
+ UnsafeBufferPointer aad);
+
+ [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" />
+
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;
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/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c
index 099fb34394711..41395f63b201f 100644
--- a/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c
+++ b/src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c
@@ -48,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)
diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.h b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.h
index fd90fd0ad8216..058c94869b57d 100644
--- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.h
+++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.h
@@ -10,3 +10,4 @@ EXTERN_C void* AppleCryptoNative_ChaCha20Poly1305Encrypt;
EXTERN_C void* AppleCryptoNative_ChaCha20Poly1305Decrypt;
EXTERN_C void* AppleCryptoNative_AesGcmEncrypt;
EXTERN_C void* AppleCryptoNative_AesGcmDecrypt;
+EXTERN_C void* AppleCryptoNative_IsAuthenticationFailure;
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 2a50deefb52bc..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
@@ -4,166 +4,174 @@
import CryptoKit
import Foundation
-@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt")
-public func AppleCryptoNative_ChaCha20Poly1305Encrypt(
- 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)
- 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 {
+ associatedtype Nonce : NonceProtocol
- guard let result = try? ChaChaPoly.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) else {
- return 0
- }
+ var ciphertext: Data { get }
+ var tag: Data { get }
- assert(ciphertextBufferLength >= result.ciphertext.count)
- assert(tagBufferLength >= result.tag.count)
+ init(
+ nonce: Nonce,
+ ciphertext: C,
+ tag: T
+ ) throws where C : DataProtocol, T : DataProtocol
+}
- result.ciphertext.copyBytes(to: ciphertextBuffer, count: result.ciphertext.count)
- result.tag.copyBytes(to: tagBuffer, count: result.tag.count)
- return 1
- }
+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: 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
+ static func open(_ sealedBox: SealedBox, using key: SymmetricKey) throws -> Data
+}
+
+extension AES.GCM.Nonce: NonceProtocol {}
+extension AES.GCM.SealedBox: SealedBoxProtocol {
+ typealias Nonce = AES.GCM.Nonce
+}
+extension AES.GCM: AEADSymmetricAlgorithm {}
+
+extension ChaChaPoly.Nonce: NonceProtocol {}
+extension ChaChaPoly.SealedBox: SealedBoxProtocol {
+ typealias Nonce = ChaChaPoly.Nonce
+}
+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
- }
+ let nonce = try Algorithm.SealedBox.Nonce(data: nonceData)
- guard let sealedBox = try? ChaChaPoly.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) else {
- return 0
- }
+ let result = try Algorithm.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad)
- do {
- let result = try ChaChaPoly.open(sealedBox, using: symmetricKey, 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)
- assert(plaintextBufferLength >= result.count)
- result.copyBytes(to: plaintextBuffer, count: result.count)
- return 1
- }
- catch CryptoKitError.authenticationFailure {
- return -1
- }
- catch {
- return 0
- }
+ _ = resultCiphertext.copyBytes(to: cipherText)
+ _ = resultTag.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.SealedBox.Nonce(data: nonceData)
- guard let result = try? AES.GCM.seal(plaintext, using: symmetricKey, nonce: nonce, authenticating: aad) else {
- return 0
- }
+ let sealedBox = try Algorithm.SealedBox(nonce: nonce, ciphertext: cipherText, tag: tag)
- assert(ciphertextBufferLength >= result.ciphertext.count)
- assert(tagBufferLength >= result.tag.count)
+ let result = try Algorithm.open(sealedBox, using: symmetricKey, authenticating: aad)
- result.ciphertext.copyBytes(to: ciphertextBuffer, count: result.ciphertext.count)
- result.tag.copyBytes(to: tagBuffer, count: result.tag.count)
- return 1
- }
+ _ = result.copyBytes(to: plaintext)
+}
-@_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)
+@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Encrypt")
+public func AppleCryptoNative_ChaCha20Poly1305Encrypt(
+ key: UnsafeBufferPointer,
+ nonceData: UnsafeBufferPointer,
+ plaintext: UnsafeBufferPointer,
+ cipherText: UnsafeMutableBufferPointer,
+ tag: UnsafeMutableBufferPointer,
+ aad: UnsafeBufferPointer
+) throws {
+ return try encrypt(
+ ChaChaPoly.self,
+ key: key,
+ nonceData: nonceData,
+ plaintext: plaintext,
+ cipherText: cipherText,
+ tag: tag,
+ aad: aad)
+ }
- guard let nonce = try? AES.GCM.Nonce(data: nonceData) else {
- return 0
- }
+@_silgen_name("AppleCryptoNative_ChaCha20Poly1305Decrypt")
+public func AppleCryptoNative_ChaCha20Poly1305Decrypt(
+ key: UnsafeBufferPointer,
+ nonceData: UnsafeBufferPointer,
+ cipherText: UnsafeBufferPointer,
+ tag: UnsafeBufferPointer,
+ plaintext: UnsafeMutableBufferPointer,
+ aad: UnsafeBufferPointer
+) throws {
+ return try decrypt(
+ ChaChaPoly.self,
+ key: key,
+ nonceData: nonceData,
+ cipherText: cipherText,
+ tag: tag,
+ plaintext: plaintext,
+ aad: aad);
+}
- guard let sealedBox = try? AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag) else {
- return 0
- }
+@_silgen_name("AppleCryptoNative_AesGcmEncrypt")
+public func AppleCryptoNative_AesGcmEncrypt(
+ key: UnsafeBufferPointer,
+ nonceData: UnsafeBufferPointer,
+ plaintext: UnsafeBufferPointer,
+ cipherText: UnsafeMutableBufferPointer,
+ tag: UnsafeMutableBufferPointer,
+ aad: UnsafeBufferPointer
+) throws {
+ return try encrypt(
+ AES.GCM.self,
+ key: key,
+ nonceData: nonceData,
+ plaintext: plaintext,
+ cipherText: cipherText,
+ tag: tag,
+ aad: aad)
+ }
- do {
- let result = try AES.GCM.open(sealedBox, using: symmetricKey, authenticating: aad)
+@_silgen_name("AppleCryptoNative_AesGcmDecrypt")
+public func AppleCryptoNative_AesGcmDecrypt(
+ key: UnsafeBufferPointer,
+ nonceData: UnsafeBufferPointer,
+ cipherText: UnsafeBufferPointer,
+ tag: UnsafeBufferPointer,
+ plaintext: UnsafeMutableBufferPointer,
+ aad: UnsafeBufferPointer
+) throws {
+ return try decrypt(
+ AES.GCM.self,
+ key: key,
+ nonceData: nonceData,
+ cipherText: cipherText,
+ tag: tag,
+ plaintext: plaintext,
+ aad: 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 {
+ if let error = error as? CryptoKitError {
+ switch error {
+ case .authenticationFailure:
+ return true
+ default:
+ return false
+ }
}
+ return false
}