Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert our CryptoKit bindings to use Swift structs at the boundary #102583

Merged
merged 9 commits into from
Jun 4, 2024
Original file line number Diff line number Diff line change
@@ -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
{
// <summary>
// Represents Swift UnsafeBufferPointer in C#.
// </summary>
internal readonly unsafe struct UnsafeBufferPointer<T> where T : unmanaged
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
{
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;
}

// <summary>
// Represents Swift UnsafeMutableBufferPointer in C#.
// </summary>
internal readonly unsafe struct UnsafeMutableBufferPointer<T> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -29,18 +31,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),
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand All @@ -63,27 +64,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),
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
out SwiftError error);

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();
}
}
Expand All @@ -105,18 +104,17 @@ 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)
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();
Expand All @@ -139,27 +137,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_AesGcmDecrypt(
keyPtr, key.Length,
noncePtr, nonce.Length,
ciphertextPtr, ciphertext.Length,
tagPtr, tag.Length,
plaintextPtr, plaintext.Length,
aadPtr, aad.Length);

if (result != Success)
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))
{
throw new AuthenticationTagMismatchException();
}
else
{
Debug.Assert(result == 0);
throw new CryptographicException();
}
}
Expand All @@ -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<byte> key,
UnsafeBufferPointer<byte> nonce,
UnsafeBufferPointer<byte> plaintext,
UnsafeMutableBufferPointer<byte> ciphertext,
UnsafeMutableBufferPointer<byte> tag,
UnsafeBufferPointer<byte> aad,
out SwiftError error
);
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved

[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<byte> key,
UnsafeBufferPointer<byte> nonce,
UnsafeBufferPointer<byte> ciphertext,
UnsafeBufferPointer<byte> tag,
UnsafeMutableBufferPointer<byte> plaintext,
UnsafeBufferPointer<byte> 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<byte> key,
UnsafeBufferPointer<byte> nonce,
UnsafeBufferPointer<byte> plaintext,
UnsafeMutableBufferPointer<byte> ciphertext,
UnsafeMutableBufferPointer<byte> tag,
UnsafeBufferPointer<byte> 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<byte> key,
UnsafeBufferPointer<byte> nonce,
UnsafeBufferPointer<byte> ciphertext,
UnsafeBufferPointer<byte> tag,
UnsafeMutableBufferPointer<byte> plaintext,
UnsafeBufferPointer<byte> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,8 @@
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EvpPkey.Rsa.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Security.Cryptography.Native\Interop.OpenSslVersion.cs"
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.OpenSslVersion.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Swift.Runtime\UnsafeBufferPointer.cs"
Link="Common\Interop\OSX\Swift.Runtime\UnsafeBufferPointer.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.Keychain.macOS.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ static const Entry s_cryptoAppleNative[] =
DllImportEntry(AppleCryptoNative_AesGcmDecrypt)
DllImportEntry(AppleCryptoNative_ChaCha20Poly1305Encrypt)
DllImportEntry(AppleCryptoNative_ChaCha20Poly1305Decrypt)
DllImportEntry(AppleCryptoNative_IsAuthenticationFailure)
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
DllImportEntry(AppleCryptoNative_DigestFree)
DllImportEntry(AppleCryptoNative_DigestCreate)
DllImportEntry(AppleCryptoNative_DigestUpdate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;