Interop
From
https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptEncryptDecrypt.cs
SHOULD NOT BE CHANGED WITHOUT COORDINATING WITH BCL TEAM
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace Azure.Storage.Shared.AesGcm
{
internal static class Interop
{
internal static class BCrypt
{
internal struct BCRYPT_KEY_DATA_BLOB_HEADER
{
public uint ;
public uint ;
public uint ;
public const uint = 1296188491;
public const uint = 1;
}
internal struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
{
private int ;
private uint ;
internal unsafe byte* ;
internal int ;
internal unsafe byte* ;
internal int ;
internal unsafe byte* ;
internal int ;
internal unsafe byte* ;
internal int ;
internal int ;
internal ulong ;
internal uint ;
public unsafe static BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO ()
{
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO result = default(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO);
result.cbSize = sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO);
result.dwInfoVersion = 1;
return result;
}
}
internal static class BCryptAeadHandleCache
{
internal static SafeAlgorithmHandle { get; } = OpenAlgorithm("AES", "ChainingModeGCM");
private static SafeAlgorithmHandle (string algId, string chainingMode = null)
{
SafeAlgorithmHandle safeAlgorithmHandle = BCryptOpenAlgorithmProvider(algId, null, 0);
if (chainingMode != null)
SetCipherMode(safeAlgorithmHandle, chainingMode);
return safeAlgorithmHandle;
}
}
internal enum NTSTATUS : uint
{
STATUS_SUCCESS = 0,
STATUS_NOT_FOUND = 3221226021,
STATUS_INVALID_PARAMETER = 3221225485,
STATUS_NO_MEMORY = 3221225495,
STATUS_AUTH_TAG_MISMATCH = 3221266434
}
internal sealed class SafeAlgorithmHandle : SafeBCryptHandle
{
protected sealed override bool ()
{
return BCryptCloseAlgorithmProvider(handle, 0) == 0;
}
[DllImport("BCrypt.dll")]
private static extern uint (IntPtr , int );
}
internal sealed class SafeKeyHandle : SafeBCryptHandle
{
private SafeAlgorithmHandle ;
public void (SafeAlgorithmHandle parentHandle)
{
bool success = false;
parentHandle.DangerousAddRef(ref success);
_parentHandle = parentHandle;
}
protected sealed override bool ()
{
if (_parentHandle != null) {
_parentHandle.DangerousRelease();
_parentHandle = null;
}
return BCryptDestroyKey(handle) == 0;
}
[DllImport("BCrypt.dll")]
private static extern uint (IntPtr );
}
internal unsafe static int (SafeKeyHandle hKey, ReadOnlySpan<byte> input, byte[] iv, Span<byte> output)
{
fixed (byte* pbInput = &input.GetPinnableReference()) {
fixed (byte* pbOutput = &output.GetPinnableReference()) {
int cbResult;
NTSTATUS nTSTATUS = BCryptEncrypt(hKey, pbInput, input.Length, IntPtr.Zero, iv, (iv != null) ? iv.Length : 0, pbOutput, output.Length, out cbResult, 0);
if (nTSTATUS != 0)
throw CreateCryptographicException(nTSTATUS);
return cbResult;
}
}
}
internal unsafe static int (SafeKeyHandle hKey, ReadOnlySpan<byte> input, byte[] iv, Span<byte> output)
{
fixed (byte* pbInput = &input.GetPinnableReference()) {
fixed (byte* pbOutput = &output.GetPinnableReference()) {
int cbResult;
NTSTATUS nTSTATUS = BCryptDecrypt(hKey, pbInput, input.Length, IntPtr.Zero, iv, (iv != null) ? iv.Length : 0, pbOutput, output.Length, out cbResult, 0);
if (nTSTATUS != 0)
throw CreateCryptographicException(nTSTATUS);
return cbResult;
}
}
}
[DllImport("BCrypt.dll")]
internal unsafe static extern NTSTATUS (SafeKeyHandle , byte* , int , IntPtr , byte[] , int , byte* , int , out int , int );
[DllImport("BCrypt.dll")]
internal unsafe static extern NTSTATUS (SafeKeyHandle , byte* , int , IntPtr , byte[] , int , byte* , int , out int , int );
internal unsafe static SafeKeyHandle (SafeAlgorithmHandle hAlg, ReadOnlySpan<byte> key)
{
int length = key.Length;
int num = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + length;
int num2 = 64;
int num3 = num2;
Span<byte> span = new Span<byte>(stackalloc byte[(int)(uint)num3], num3);
if (num > num2)
span = new byte[num];
else
span.Clear();
fixed (byte* ptr = &span.GetPinnableReference()) {
BCRYPT_KEY_DATA_BLOB_HEADER* ptr2 = (BCRYPT_KEY_DATA_BLOB_HEADER*)ptr;
ptr2->dwMagic = 1296188491;
ptr2->dwVersion = 1;
ptr2->cbKeyData = (uint)length;
key.CopyTo(span.Slice(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)));
SafeKeyHandle hKey;
NTSTATUS nTSTATUS = BCryptImportKey(hAlg, IntPtr.Zero, "KeyDataBlob", out hKey, IntPtr.Zero, 0, ptr, num, 0);
if (nTSTATUS != 0)
throw CreateCryptographicException(nTSTATUS);
return hKey;
}
}
[DllImport("BCrypt.dll", CharSet = CharSet.Unicode)]
private unsafe static extern NTSTATUS (SafeAlgorithmHandle , IntPtr , string , out SafeKeyHandle , IntPtr , int , byte* , int , int );
internal static CryptographicException (NTSTATUS ntstatus)
{
return CreateCryptographicException((int)ntstatus);
}
internal static CryptographicException (int hr)
{
return new CryptographicException(hr);
}
private static void (SafeAlgorithmHandle hAlg, string cipherMode)
{
NTSTATUS nTSTATUS = BCryptSetProperty(hAlg, "ChainingMode", cipherMode, (cipherMode.Length + 1) * 2, 0);
if (nTSTATUS != 0)
throw CreateCryptographicException(nTSTATUS);
}
private static SafeAlgorithmHandle (string pszAlgId, string pszImplementation, int dwFlags)
{
SafeAlgorithmHandle phAlgorithm;
NTSTATUS nTSTATUS = BCryptOpenAlgorithmProvider(out phAlgorithm, pszAlgId, pszImplementation, dwFlags);
if (nTSTATUS != 0)
throw CreateCryptographicException(nTSTATUS);
return phAlgorithm;
}
[DllImport("BCrypt.dll", CharSet = CharSet.Unicode)]
private static extern NTSTATUS (out SafeAlgorithmHandle , string , string , int );
[DllImport("BCrypt.dll", CharSet = CharSet.Unicode)]
private static extern NTSTATUS (SafeAlgorithmHandle , string , string , int , int );
}
}
}