Example #1
0
        internal static unsafe void Decrypt(
            Interop.BCrypt.SafeKeyHandle keyHandle,
            ReadOnlySpan <byte> nonce,
            ReadOnlySpan <byte> associatedData,
            ReadOnlySpan <byte> ciphertext,
            ReadOnlySpan <byte> tag,
            Span <byte> plaintext,
            bool clearPlaintextOnFailure)
        {
            // bcrypt sometimes misbehaves when given nullptr buffers; ensure non-nullptr
            fixed(byte *plaintextBytes = &GetNonNullPinnableReference(plaintext))
            fixed(byte *nonceBytes          = &GetNonNullPinnableReference(nonce))
            fixed(byte *ciphertextBytes     = &GetNonNullPinnableReference(ciphertext))
            fixed(byte *tagBytes            = &GetNonNullPinnableReference(tag))
            fixed(byte *associatedDataBytes = &GetNonNullPinnableReference(associatedData))
            {
                var authInfo = Interop.BCrypt.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;

                Interop.BCrypt.NTSTATUS ntStatus = Interop.BCrypt.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 Interop.BCrypt.NTSTATUS.STATUS_SUCCESS:
                    return;

                case Interop.BCrypt.NTSTATUS.STATUS_AUTH_TAG_MISMATCH:
                    if (clearPlaintextOnFailure)
                    {
                        plaintext.Clear();
                        //CryptographicOperations.ZeroMemory(plaintext);
                    }
                    Errors.CryptographyAuthTagMismatch();
                    return;

                default:
                    //throw CreateCryptographicException(ntStatus);
                    throw new CryptographicException($"Error: 0x{(int)ntStatus:X8}");
                }
            }
        }
Example #2
0
        internal static unsafe void Encrypt(
            Interop.BCrypt.SafeKeyHandle keyHandle,
            ReadOnlySpan <byte> nonce,
            ReadOnlySpan <byte> associatedData,
            ReadOnlySpan <byte> plaintext,
            Span <byte> ciphertext,
            Span <byte> tag)
        {
            // bcrypt sometimes misbehaves when given nullptr buffers; ensure non-nullptr
            fixed(byte *plaintextBytes = &GetNonNullPinnableReference(plaintext))
            fixed(byte *nonceBytes          = &GetNonNullPinnableReference(nonce))
            fixed(byte *ciphertextBytes     = &GetNonNullPinnableReference(ciphertext))
            fixed(byte *tagBytes            = &GetNonNullPinnableReference(tag))
            fixed(byte *associatedDataBytes = &GetNonNullPinnableReference(associatedData))
            {
                var authInfo = Interop.BCrypt.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;

                Interop.BCrypt.NTSTATUS ntStatus = Interop.BCrypt.BCryptEncrypt(
                    keyHandle,
                    plaintextBytes,
                    plaintext.Length,
                    new IntPtr(&authInfo),
                    null,
                    0,
                    ciphertextBytes,
                    ciphertext.Length,
                    out int ciphertextBytesWritten,
                    0);

                Debug.Assert(plaintext.Length == ciphertextBytesWritten);

                if (ntStatus != Interop.BCrypt.NTSTATUS.STATUS_SUCCESS)
                {
                    throw Interop.BCrypt.CreateCryptographicException(ntStatus);
                }
            }
        }