public static unsafe void Decrypt( SafeAlgorithmHandle algorithm, SafeKeyHandleBCrypt keyHandle, ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> associatedData, ReadOnlySpan <byte> ciphertext, ReadOnlySpan <byte> tag, Span <byte> plaintext, bool clearPlaintextOnFailure) { fixed(byte *plaintextBytes = plaintext) fixed(byte *nonceBytes = nonce) fixed(byte *ciphertextBytes = ciphertext) fixed(byte *tagBytes = tag) fixed(byte *associatedDataBytes = associatedData) { BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Create(); authInfo.pbNonce = nonceBytes; authInfo.cbNonce = nonce.Length; authInfo.pbTag = tagBytes; authInfo.cbTag = tag.Length; authInfo.pbAuthData = associatedDataBytes; authInfo.cbAuthData = associatedData.Length; NTSTATUS ntStatus = Cng.Interop.BCryptDecrypt( keyHandle, ciphertextBytes, ciphertext.Length, new IntPtr(&authInfo), null, 0, plaintextBytes, plaintext.Length, out int plaintextBytesWritten, 0); Debug.Assert(ciphertext.Length == plaintextBytesWritten); switch (ntStatus) { case NTSTATUS.STATUS_SUCCESS: return; case NTSTATUS.STATUS_AUTH_TAG_MISMATCH: if (clearPlaintextOnFailure) { CryptographicOperations.ZeroMemory(plaintext); } throw new CryptographicException(SR.Cryptography_AuthTagMismatch); default: throw CreateCryptographicException(ntStatus); } } }
public static unsafe void Encrypt( SafeAlgorithmHandle algorithm, SafeKeyHandleBCrypt keyHandle, ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> associatedData, ReadOnlySpan <byte> plaintext, Span <byte> ciphertext, Span <byte> tag) { fixed(byte *plaintextBytes = plaintext) fixed(byte *nonceBytes = nonce) fixed(byte *ciphertextBytes = ciphertext) fixed(byte *tagBytes = tag) fixed(byte *associatedDataBytes = associatedData) { BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Create(); authInfo.pbNonce = nonceBytes; authInfo.cbNonce = nonce.Length; authInfo.pbTag = tagBytes; authInfo.cbTag = tag.Length; authInfo.pbAuthData = associatedDataBytes; authInfo.cbAuthData = associatedData.Length; NTSTATUS ntStatus = Cng.Interop.BCryptEncrypt( keyHandle, plaintextBytes, plaintext.Length, new IntPtr(&authInfo), null, 0, ciphertextBytes, ciphertext.Length, out int ciphertextBytesWritten, 0); Debug.Assert(plaintext.Length == ciphertextBytesWritten); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { throw CreateCryptographicException(ntStatus); } } }
protected override void Dispose(bool disposing) { if (disposing) { SafeKeyHandleBCrypt hKey = _hKey; _hKey = null; if (hKey != null) { hKey.Dispose(); } byte[] currentIv = _currentIv; _currentIv = null; if (currentIv != null) { Array.Clear(currentIv, 0, currentIv.Length); } } base.Dispose(disposing); }
private byte[] _currentIv; // CNG mutates this with the updated IV for the next stage on each Encrypt/Decrypt call. // The base IV holds a copy of the original IV for Reset(), until it is cleared by Dispose(). public BasicSymmetricCipherBCrypt(SafeAlgorithmHandle algorithm, CipherMode cipherMode, int blockSizeInBytes, byte[] key, bool ownsParentHandle, byte[] iv, bool encrypting) : base(cipherMode.GetCipherIv(iv), blockSizeInBytes) { Debug.Assert(algorithm != null); _encrypting = encrypting; if (IV != null) { _currentIv = new byte[IV.Length]; } _hKey = algorithm.BCryptImportKey(key); if (ownsParentHandle) { _hKey.SetParentHandle(algorithm); } Reset(); }
private void ImportKey(ReadOnlySpan <byte> key) { _keyHandle = s_aesCcm.BCryptImportKey(key); }