コード例 #1
0
        // 'pbNonce' must point to a 96-bit buffer.
        // 'pbTag' must point to a 128-bit buffer.
        // 'pbEncryptedData' must point to a buffer the same length as 'pbPlaintextData'.
        private void DoGcmEncrypt(byte *pbKey, uint cbKey, byte *pbNonce, byte *pbPlaintextData, uint cbPlaintextData, byte *pbEncryptedData, byte *pbTag)
        {
            BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authCipherInfo;

            BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Init(out authCipherInfo);
            authCipherInfo.pbNonce = pbNonce;
            authCipherInfo.cbNonce = NONCE_SIZE_IN_BYTES;
            authCipherInfo.pbTag   = pbTag;
            authCipherInfo.cbTag   = TAG_SIZE_IN_BYTES;

            using (var keyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbKey, cbKey))
            {
                uint cbResult;
                int  ntstatus = UnsafeNativeMethods.BCryptEncrypt(
                    hKey: keyHandle,
                    pbInput: pbPlaintextData,
                    cbInput: cbPlaintextData,
                    pPaddingInfo: &authCipherInfo,
                    pbIV: null,
                    cbIV: 0,
                    pbOutput: pbEncryptedData,
                    cbOutput: cbPlaintextData,
                    pcbResult: out cbResult,
                    dwFlags: 0);
                UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);
                CryptoUtil.Assert(cbResult == cbPlaintextData, "cbResult == cbPlaintextData");
            }
        }
コード例 #2
0
        // corresponds to the BCRYPT_INIT_AUTH_MODE_INFO macro in bcrypt.h
        public static void Init(out BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info)
        {
            const uint BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1;

            info = new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
            {
                cbSize        = (uint)sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO),
                dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION
            };
        }
コード例 #3
0
        protected override byte[] DecryptImpl(byte *pbCiphertext, uint cbCiphertext, byte *pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData)
        {
            // Argument checking: input must at the absolute minimum contain a key modifier, nonce, and tag
            if (cbCiphertext < KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES)
            {
                throw Error.CryptCommon_PayloadInvalid();
            }

            // Assumption: pbCipherText := { keyModifier || nonce || encryptedData || authenticationTag }

            uint cbPlaintext = checked (cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES));

            byte[] retVal = new byte[cbPlaintext];
            fixed(byte *pbRetVal = retVal)
            {
                // Calculate offsets
                byte *pbKeyModifier   = pbCiphertext;
                byte *pbNonce         = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES];
                byte *pbEncryptedData = &pbNonce[NONCE_SIZE_IN_BYTES];
                byte *pbAuthTag       = &pbEncryptedData[cbPlaintext];

                // Use the KDF to recreate the symmetric block cipher key
                // We'll need a temporary buffer to hold the symmetric encryption subkey
                byte *pbSymmetricDecryptionSubkey = stackalloc byte[checked ((int)_symmetricAlgorithmSubkeyLengthInBytes)];

                try
                {
                    _sp800_108_ctr_hmac_provider.DeriveKeyWithContextHeader(
                        pbLabel: pbAdditionalAuthenticatedData,
                        cbLabel: cbAdditionalAuthenticatedData,
                        contextHeader: _contextHeader,
                        pbContext: pbKeyModifier,
                        cbContext: KEY_MODIFIER_SIZE_IN_BYTES,
                        pbDerivedKey: pbSymmetricDecryptionSubkey,
                        cbDerivedKey: _symmetricAlgorithmSubkeyLengthInBytes);

                    // Perform the decryption operation

                    using (var decryptionSubkeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricDecryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes))
                    {
                        byte  dummy;
                        byte *pbPlaintext = (pbRetVal != null) ? pbRetVal : &dummy; // CLR doesn't like pinning empty buffers

                        BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo;
                        BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.Init(out authInfo);
                        authInfo.pbNonce = pbNonce;
                        authInfo.cbNonce = NONCE_SIZE_IN_BYTES;
                        authInfo.pbTag   = pbAuthTag;
                        authInfo.cbTag   = TAG_SIZE_IN_BYTES;

                        // The call to BCryptDecrypt will also validate the authentication tag
                        uint cbDecryptedBytesWritten;
                        int  ntstatus = UnsafeNativeMethods.BCryptDecrypt(
                            hKey: decryptionSubkeyHandle,
                            pbInput: pbEncryptedData,
                            cbInput: cbPlaintext,
                            pPaddingInfo: &authInfo,
                            pbIV: null, // IV not used; nonce provided in pPaddingInfo
                            cbIV: 0,
                            pbOutput: pbPlaintext,
                            cbOutput: cbPlaintext,
                            pcbResult: out cbDecryptedBytesWritten,
                            dwFlags: 0);
                        UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);
                        CryptoUtil.Assert(cbDecryptedBytesWritten == cbPlaintext, "cbDecryptedBytesWritten == cbPlaintext");

                        // At this point, retVal := { decryptedPayload }
                        // And we're done!
                        return(retVal);
                    }
                }
                finally
                {
                    // The buffer contains key material, so delete it.
                    UnsafeBufferUtil.SecureZeroMemory(pbSymmetricDecryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes);
                }
            }
        }