コード例 #1
0
        private static void TestCngKeyDerivation(ProviderFactory factory, byte[] kdk, byte[] label, byte[] contextHeader, byte[] context, int numDerivedBytes, string expectedDerivedSubkeyAsBase64)
        {
            byte[] derivedSubkey = new byte[numDerivedBytes];

            fixed(byte *pbKdk = kdk)
            fixed(byte *pbLabel         = label)
            fixed(byte *pbContext       = context)
            fixed(byte *pbDerivedSubkey = derivedSubkey)
            {
                ISP800_108_CTR_HMACSHA512Provider provider = factory(pbKdk, (uint)kdk.Length);

                provider.DeriveKeyWithContextHeader(pbLabel, (uint)label.Length, contextHeader, pbContext, (uint)context.Length, pbDerivedSubkey, (uint)derivedSubkey.Length);
            }

            Assert.Equal(expectedDerivedSubkeyAsBase64, Convert.ToBase64String(derivedSubkey));
        }
コード例 #2
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, IV, and MAC
            if (cbCiphertext < checked (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes))
            {
                throw Error.CryptCommon_PayloadInvalid();
            }

            // Assumption: pbCipherText := { keyModifier | IV | encryptedData | MAC(IV | encryptedPayload) }

            var cbEncryptedData = checked (cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes));

            // Calculate offsets
            byte *pbKeyModifier   = pbCiphertext;
            byte *pbIV            = &pbKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES];
            byte *pbEncryptedData = &pbIV[_symmetricAlgorithmBlockSizeInBytes];
            byte *pbActualHmac    = &pbEncryptedData[cbEncryptedData];

            // Use the KDF to recreate the symmetric encryption and HMAC subkeys
            // We'll need a temporary buffer to hold them
            var   cbTempSubkeys = checked (_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes);
            byte *pbTempSubkeys = stackalloc byte[checked ((int)cbTempSubkeys)];

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

                // Calculate offsets
                byte *pbSymmetricEncryptionSubkey = pbTempSubkeys;
                byte *pbHmacSubkey = &pbTempSubkeys[_symmetricAlgorithmSubkeyLengthInBytes];

                // First, perform an explicit integrity check over (iv | encryptedPayload) to ensure the
                // data hasn't been tampered with. The integrity check is also implicitly performed over
                // keyModifier since that value was provided to the KDF earlier.
                using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes))
                {
                    if (!ValidateHash(hashHandle, pbIV, _symmetricAlgorithmBlockSizeInBytes + cbEncryptedData, pbActualHmac))
                    {
                        throw Error.CryptCommon_PayloadInvalid();
                    }
                }

                // If the integrity check succeeded, decrypt the payload.
                using (var decryptionSubkeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes))
                {
                    return(DoCbcDecrypt(decryptionSubkeyHandle, pbIV, pbEncryptedData, cbEncryptedData));
                }
            }
            finally
            {
                // Buffer contains sensitive key material; delete.
                UnsafeBufferUtil.SecureZeroMemory(pbTempSubkeys, cbTempSubkeys);
            }
        }
コード例 #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 }

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

        var 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;
                    var  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);
            }
        }
    }