Beispiel #1
0
        private byte[] CreateContextHeader()
        {
            var retVal = new byte[checked (
                                      1                                     /* KDF alg */
                                      + 1                                   /* chaining mode */
                                      + sizeof(uint)                        /* sym alg key size */
                                      + sizeof(uint)                        /* sym alg block size */
                                      + sizeof(uint)                        /* hmac alg key size */
                                      + sizeof(uint)                        /* hmac alg digest size */
                                      + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */
                                      + _hmacAlgorithmDigestLengthInBytes /* digest of HMACed empty string */)];

            fixed(byte *pbRetVal = retVal)
            {
                byte *ptr = pbRetVal;

                // First is the two-byte header
                *(ptr++) = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF
                *(ptr++) = 0; // 0x00 = CBC encryption + HMAC authentication

                // Next is information about the symmetric algorithm (key size followed by block size)
                BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmSubkeyLengthInBytes);
                BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmBlockSizeInBytes);

                // Next is information about the HMAC algorithm (key size followed by digest size)
                BitHelpers.WriteTo(ref ptr, _hmacAlgorithmSubkeyLengthInBytes);
                BitHelpers.WriteTo(ref ptr, _hmacAlgorithmDigestLengthInBytes);

                // See the design document for an explanation of the following code.
                var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes];

                fixed(byte *pbTempKeys = tempKeys)
                {
                    byte dummy;

                    // Derive temporary keys for encryption + HMAC.
                    using (var provider = SP800_108_CTR_HMACSHA512Util.CreateEmptyProvider())
                    {
                        provider.DeriveKey(
                            pbLabel: &dummy,
                            cbLabel: 0,
                            pbContext: &dummy,
                            cbContext: 0,
                            pbDerivedKey: pbTempKeys,
                            cbDerivedKey: (uint)tempKeys.Length);
                    }

                    // At this point, tempKeys := { K_E || K_H }.
                    byte *pbSymmetricEncryptionSubkey = pbTempKeys;
                    byte *pbHmacSubkey = &pbTempKeys[_symmetricAlgorithmSubkeyLengthInBytes];

                    // Encrypt a zero-length input string with an all-zero IV and copy the ciphertext to the return buffer.
                    using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes))
                    {
                        fixed(byte *pbIV = new byte[_symmetricAlgorithmBlockSizeInBytes] /* will be zero-initialized */)
                        {
                            DoCbcEncrypt(
                                symmetricKeyHandle: symmetricKeyHandle,
                                pbIV: pbIV,
                                pbInput: &dummy,
                                cbInput: 0,
                                pbOutput: ptr,
                                cbOutput: _symmetricAlgorithmBlockSizeInBytes);
                        }
                    }
                    ptr += _symmetricAlgorithmBlockSizeInBytes;

                    // MAC a zero-length input string and copy the digest to the return buffer.
                    using (var hashHandle = _hmacAlgorithmHandle.CreateHmac(pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes))
                    {
                        hashHandle.HashData(
                            pbInput: &dummy,
                            cbInput: 0,
                            pbHashDigest: ptr,
                            cbHashDigest: _hmacAlgorithmDigestLengthInBytes);
                    }

                    ptr += _hmacAlgorithmDigestLengthInBytes;
                    CryptoUtil.Assert(ptr - pbRetVal == retVal.Length, "ptr - pbRetVal == retVal.Length");
                }
            }

            // retVal := { version || chainingMode || symAlgKeySize || symAlgBlockSize || hmacAlgKeySize || hmacAlgDigestSize || E("") || MAC("") }.
            return(retVal);
        }