internal static SafeBCryptKeyHandle ImportKey(SafeBCryptAlgorithmHandle algorithm, byte[] key) { const int BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4d42444b; // Concatenate the BCRYPT_KEY_DATA_BLOB header and the raw key. byte[] keyBlob = new byte[Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)) + key.Length]; unsafe { fixed(byte *pbKeyBlob = keyBlob) { BCRYPT_KEY_DATA_BLOB *pkeyDataBlob = (BCRYPT_KEY_DATA_BLOB *)pbKeyBlob; pkeyDataBlob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; pkeyDataBlob->dwVersion = 1; pkeyDataBlob->cbKeyData = key.Length; } } Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)), key.Length); int cbKeyData = BitConverter.ToInt32(GetProperty(algorithm, "ObjectLength"), 0); var pbKeyData = Marshal.AllocCoTaskMem(cbKeyData); ErrorCode error = UnsafeNativeMethods.BCryptImportKey(algorithm, IntPtr.Zero, "KeyDataBlob", out var keyHandle, pbKeyData, cbKeyData, keyBlob, keyBlob.Length, 0); if (error == ErrorCode.Success) { keyHandle.DataBuffer = pbKeyData; return(keyHandle); } else { Marshal.FreeCoTaskMem(pbKeyData); throw new CryptographicException("Failed to import key: error " + error); } }
public unsafe void SetKey(Span <byte> key) { var keyBlob = stackalloc byte[sizeof(BCRYPT_KEY_DATA_BLOB) + _keyLength]; BCRYPT_KEY_DATA_BLOB *pkeyDataBlob = (BCRYPT_KEY_DATA_BLOB *)keyBlob; pkeyDataBlob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; pkeyDataBlob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; pkeyDataBlob->cbKeyData = _keyLength; var keyBlobSpan = new Span <byte>(keyBlob + sizeof(BCRYPT_KEY_DATA_BLOB), _keyLength); key.CopyTo(keyBlobSpan); Interop.Windows.ExceptionHelper.CheckReturnCode( BCryptImportKey(_algo, IntPtr.Zero, "KeyDataBlob", out _key, IntPtr.Zero, 0, (IntPtr)keyBlob, sizeof(BCRYPT_KEY_DATA_BLOB) + _keyLength, 0)); BCryptPropertiesHelper.SetBlockChainingMode(_key, _chainingMode); _blockLength = BCryptPropertiesHelper.GetBlockLength(_key); _maxTagLength = _blockLength; }
internal static SafeBCryptKeyHandle ImportSymmetricKey(SafeBCryptAlgorithmHandle algorithm, byte[] key) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); Debug.Assert(key != null, "buffer != null"); IntPtr keyDataBuffer = IntPtr.Zero; SafeBCryptKeyHandle keyHandle = null; RuntimeHelpers.PrepareConstrainedRegions(); try { // Build up the key blob structure in memory. BCryptImportKey requries a // BCRYPT_KEY_DATA_BLOB header immediately followed by the raw key data. byte[] keyBlob = new byte[Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)) + key.Length]; unsafe { fixed(byte *pbKeyBlob = keyBlob) { BCRYPT_KEY_DATA_BLOB *pkeyDataBlob = (BCRYPT_KEY_DATA_BLOB *)pbKeyBlob; pkeyDataBlob->dwMagic = KeyBlobMagicNumber.KeyDataBlob; pkeyDataBlob->dwVersion = 1; pkeyDataBlob->cbKeyData = key.Length; } } Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)), key.Length); // Figure out how big of a key data buffer we need and allocate space on the native heap for // it. We cannot use a managed array here because the address needs to stay constant for // the lifetime of the algorithm handle. Pinning for a potentially long lifetime is // undesirable, so we use a native heap allocation instead. int keyDataSize = GetInt32Property(algorithm, ObjectPropertyName.ObjectLength); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { keyDataBuffer = Marshal.AllocCoTaskMem(keyDataSize); } // Import the key ErrorCode error = UnsafeNativeMethods.BCryptImportKey(algorithm, IntPtr.Zero, KeyBlobType.KeyDataBlob, out keyHandle, keyDataBuffer, keyDataSize, keyBlob, keyBlob.Length, 0); if (error != ErrorCode.Success) { throw new CryptographicException((int)error); } // Give the key ownership of the key data buffer keyHandle.DataBuffer = keyDataBuffer; return(keyHandle); } finally { // If we allocated a key data buffer, but never transfered ownership to the key handle, then // we need to free it now otherwise it will leak. if (keyDataBuffer != IntPtr.Zero) { if (keyHandle == null || keyHandle.DataBuffer == IntPtr.Zero) { Marshal.FreeCoTaskMem(keyDataBuffer); } } } }