示例#1
0
    protected override byte[] EncryptImpl(byte *pbPlaintext, uint cbPlaintext, byte *pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer)
    {
        // Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag.
        // In GCM, the encrypted output will be the same length as the plaintext input.
        var retVal = new byte[checked (cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + cbPlaintext + TAG_SIZE_IN_BYTES + cbPostBuffer)];

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

            // Randomly generate the key modifier and nonce
            _genRandom.GenRandom(pbKeyModifier, KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES);

            // At this point, retVal := { preBuffer | keyModifier | nonce | _____ | _____ | postBuffer }

            // Use the KDF to generate a new symmetric block cipher key
            // We'll need a temporary buffer to hold the symmetric encryption subkey
            byte *pbSymmetricEncryptionSubkey = 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: pbSymmetricEncryptionSubkey,
                    cbDerivedKey: _symmetricAlgorithmSubkeyLengthInBytes);

                // Perform the encryption operation
                DoGcmEncrypt(
                    pbKey: pbSymmetricEncryptionSubkey,
                    cbKey: _symmetricAlgorithmSubkeyLengthInBytes,
                    pbNonce: pbNonce,
                    pbPlaintextData: pbPlaintext,
                    cbPlaintextData: cbPlaintext,
                    pbEncryptedData: pbEncryptedData,
                    pbTag: pbAuthTag);

                // At this point, retVal := { preBuffer | keyModifier | nonce | encryptedData | authenticationTag | postBuffer }
                // And we're done!
                return(retVal);
            }
            finally
            {
                // The buffer contains key material, so delete it.
                UnsafeBufferUtil.SecureZeroMemory(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes);
            }
        }
    }
示例#2
0
        protected override byte[] EncryptImpl(byte *pbPlaintext, uint cbPlaintext, byte *pbAdditionalAuthenticatedData, uint cbAdditionalAuthenticatedData, uint cbPreBuffer, uint cbPostBuffer)
        {
            // This buffer will be used to hold the symmetric encryption and HMAC subkeys
            // used in the generation of this payload.
            var   cbTempSubkeys = checked (_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes);
            byte *pbTempSubkeys = stackalloc byte[checked ((int)cbTempSubkeys)];

            try
            {
                // Randomly generate the key modifier and IV.
                var   cbKeyModifierAndIV = checked (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes);
                byte *pbKeyModifierAndIV = stackalloc byte[checked ((int)cbKeyModifierAndIV)];
                _genRandom.GenRandom(pbKeyModifierAndIV, cbKeyModifierAndIV);

                // Calculate offsets
                byte *pbKeyModifier = pbKeyModifierAndIV;
                byte *pbIV          = &pbKeyModifierAndIV[KEY_MODIFIER_SIZE_IN_BYTES];

                // Use the KDF to generate a new symmetric encryption and HMAC subkey
                _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];

                using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes))
                {
                    // We can't assume PKCS#7 padding (maybe the underlying provider is really using CTS),
                    // so we need to query the padded output size before we can allocate the return value array.
                    var cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, cbPlaintext);

                    // Allocate return value array and start copying some data
                    var retVal = new byte[checked (cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext + _hmacAlgorithmDigestLengthInBytes + cbPostBuffer)];
                    fixed(byte *pbRetVal = retVal)
                    {
                        // Calculate offsets
                        byte *pbOutputKeyModifier = &pbRetVal[cbPreBuffer];
                        byte *pbOutputIV          = &pbOutputKeyModifier[KEY_MODIFIER_SIZE_IN_BYTES];
                        byte *pbOutputCiphertext  = &pbOutputIV[_symmetricAlgorithmBlockSizeInBytes];
                        byte *pbOutputHmac        = &pbOutputCiphertext[cbOutputCiphertext];

                        UnsafeBufferUtil.BlockCopy(from: pbKeyModifierAndIV, to: pbOutputKeyModifier, byteCount: cbKeyModifierAndIV);

                        // retVal will eventually contain { preBuffer | keyModifier | iv | encryptedData | HMAC(iv | encryptedData) | postBuffer }
                        // At this point, retVal := { preBuffer | keyModifier | iv | _____ | _____ | postBuffer }

                        DoCbcEncrypt(
                            symmetricKeyHandle: symmetricKeyHandle,
                            pbIV: pbIV,
                            pbInput: pbPlaintext,
                            cbInput: cbPlaintext,
                            pbOutput: pbOutputCiphertext,
                            cbOutput: cbOutputCiphertext);

                        // At this point, retVal := { preBuffer | keyModifier | iv | encryptedData | _____ | postBuffer }

                        // Compute the HMAC over the IV and the ciphertext (prevents IV tampering).
                        // The HMAC is already implicitly computed over the key modifier since the key
                        // modifier is used as input to the KDF.
                        using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes))
                        {
                            hashHandle.HashData(
                                pbInput: pbOutputIV,
                                cbInput: checked (_symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext),
                                pbHashDigest: pbOutputHmac,
                                cbHashDigest: _hmacAlgorithmDigestLengthInBytes);
                        }

                        // At this point, retVal := { preBuffer | keyModifier | iv | encryptedData | HMAC(iv | encryptedData) | postBuffer }
                        // And we're done!
                        return(retVal);
                    }
                }
            }
            finally
            {
                // Buffer contains sensitive material; delete it.
                UnsafeBufferUtil.SecureZeroMemory(pbTempSubkeys, cbTempSubkeys);
            }
        }