AeadCommon
Taken from
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AeadCommon.Windows.cs
SHOULD NOT BE CHANGED WITHOUT COORDINATING WITH BCL TEAM
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace Azure.Storage.Shared.AesGcm
{
internal static class AeadCommon
{
internal unsafe static void (Interop.BCrypt.SafeKeyHandle keyHandle, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> associatedData, ReadOnlySpan<byte> plaintext, Span<byte> ciphertext, Span<byte> tag)
{
fixed (byte* pbInput = &GetNonNullPinnableReference(plaintext)) {
fixed (byte* pbNonce = &GetNonNullPinnableReference(nonce)) {
fixed (byte* pbOutput = &GetNonNullPinnableReference(ciphertext)) {
fixed (byte* pbTag = &GetNonNullPinnableReference(tag)) {
fixed (byte* pbAuthData = &GetNonNullPinnableReference(associatedData)) {
Interop.BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO = Interop.BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Create();
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbNonce = pbNonce;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbNonce = nonce.Length;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbTag = pbTag;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbTag = tag.Length;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbAuthData = pbAuthData;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbAuthData = associatedData.Length;
int cbResult;
Interop.BCrypt.NTSTATUS nTSTATUS = Interop.BCrypt.BCryptEncrypt(keyHandle, pbInput, plaintext.Length, new IntPtr(&bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO), null, 0, pbOutput, ciphertext.Length, out cbResult, 0);
if (nTSTATUS != 0)
throw Interop.BCrypt.CreateCryptographicException(nTSTATUS);
}
}
}
}
}
}
internal unsafe static void (Interop.BCrypt.SafeKeyHandle keyHandle, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> associatedData, ReadOnlySpan<byte> ciphertext, ReadOnlySpan<byte> tag, Span<byte> plaintext, bool clearPlaintextOnFailure)
{
fixed (byte* pbOutput = &GetNonNullPinnableReference(plaintext)) {
fixed (byte* pbNonce = &GetNonNullPinnableReference(nonce)) {
fixed (byte* pbInput = &GetNonNullPinnableReference(ciphertext)) {
fixed (byte* pbTag = &GetNonNullPinnableReference(tag)) {
fixed (byte* pbAuthData = &GetNonNullPinnableReference(associatedData)) {
Interop.BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO = Interop.BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Create();
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbNonce = pbNonce;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbNonce = nonce.Length;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbTag = pbTag;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbTag = tag.Length;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.pbAuthData = pbAuthData;
bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.cbAuthData = associatedData.Length;
int cbResult;
Interop.BCrypt.NTSTATUS nTSTATUS = Interop.BCrypt.BCryptDecrypt(keyHandle, pbInput, ciphertext.Length, new IntPtr(&bCRYPT_AUTHENTICATED_CIPHER_MODE_INFO), null, 0, pbOutput, plaintext.Length, out cbResult, 0);
switch (nTSTATUS) {
case Interop.BCrypt.NTSTATUS.STATUS_SUCCESS:
break;
case Interop.BCrypt.NTSTATUS.STATUS_AUTH_TAG_MISMATCH:
if (clearPlaintextOnFailure)
plaintext.Clear();
Errors.CryptographyAuthTagMismatch();
break;
default:
throw new CryptographicException($"""{(int)nTSTATUS:""}");
}
}
}
}
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: System.Runtime.CompilerServices.IsReadOnly]
private unsafe static ref byte (ReadOnlySpan<byte> buffer)
{
if (buffer.Length == 0)
return ref Unsafe.AsRef<byte>((void*)1);
return ref MemoryMarshal.GetReference(buffer);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static ref byte (Span<byte> buffer)
{
if (buffer.Length == 0)
return ref Unsafe.AsRef<byte>((void*)1);
return ref MemoryMarshal.GetReference(buffer);
}
}
}