Example #1
0
        } // VerifySignature()

        /// <summary>
        /// Generates the key exchange key and the public part of the ephemeral key
        /// using specified encoding parameters in the KDF (ECC only).
        /// </summary>
        /// <param name="encodingParms"></param>
        /// <param name="decryptKeyNameAlg"></param>
        /// <param name="ephemPub"></param>
        /// <returns>key exchange key blob</returns>
        public byte[] EcdhGetKeyExchangeKey(byte[] encodingParms, TpmAlgId decryptKeyNameAlg, out EccPoint ephemPub)
        {
            byte[] keyExchangeKey = null;
            ephemPub = null;

#if !__MonoCS__
            var eccParms = (EccParms)PublicParms.parameters;
            int keyBits  = RawEccKey.GetKeyLength(eccParms.curveID);

            // Make a new ephemeral key
#if TSS_USE_BCRYPT
            var    ephKey   = Generate(RawEccKey.GetEccAlg(PublicParms), (uint)keyBits);
            byte[] ephPub   = ephKey.Export(Native.BCRYPT_ECCPUBLIC_BLOB);
            byte[] otherPub = Key.Export(Native.BCRYPT_ECCPUBLIC_BLOB);
#else
            using (var eph = new ECDiffieHellmanCng(keyBits))
            {
                byte[] otherPub = EcDhProvider.PublicKey.ToByteArray();
                byte[] ephPub   = eph.PublicKey.ToByteArray();

                eph.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                eph.HashAlgorithm         = GetCngAlgorithm(decryptKeyNameAlg);
#endif // !TSS_USE_BCRYPT

            byte[] herPubX, herPubY;
            RawEccKey.KeyInfoFromPublicBlob(otherPub, out herPubX, out herPubY);

            byte[] myPubX, myPubY;
            RawEccKey.KeyInfoFromPublicBlob(ephPub, out myPubX, out myPubY);

            byte[] otherInfo = Globs.Concatenate(new[] { encodingParms, myPubX, herPubX });

            // The TPM uses the following number of bytes from the KDF
            int bytesNeeded = CryptoLib.DigestSize(decryptKeyNameAlg);
            keyExchangeKey = new byte[bytesNeeded];

            for (int pos = 0, count = 1, bytesToCopy = 0;
                 pos < bytesNeeded;
                 ++count, pos += bytesToCopy)
            {
                byte[] secretPrepend = Marshaller.GetTpmRepresentation((UInt32)count);
#if TSS_USE_BCRYPT
                byte[] fragment = ephKey.DeriveKey(Key, decryptKeyNameAlg, secretPrepend, otherInfo);
#else
                eph.SecretAppend  = otherInfo;
                eph.SecretPrepend = secretPrepend;
                byte[] fragment = eph.DeriveKeyMaterial(EcDhProvider.Key);
#endif // !TSS_USE_BCRYPT
                bytesToCopy = Math.Min(bytesNeeded - pos, fragment.Length);
                Array.Copy(fragment, 0, keyExchangeKey, pos, bytesToCopy);
            }
            ephemPub = new EccPoint(myPubX, myPubY);
#if !TSS_USE_BCRYPT
        }
#endif
#endif // !__MonoCS__
            return(keyExchangeKey);
        }
        } // VerifySignature()

        /// <summary>
        /// Generates the key exchange key and the public part of the ephemeral key
        /// using specified encoding parameters in the KDF (ECC only).
        /// </summary>
        /// <param name="encodingParms"></param>
        /// <param name="decryptKeyNameAlg"></param>
        /// <param name="ephemPub"></param>
        /// <returns>key exchange key blob</returns>
        public byte[] EcdhGetKeyExchangeKey(byte[] encodingParms, TpmAlgId decryptKeyNameAlg, out EccPoint ephemPub)
        {
            var eccParms = (EccParms)PublicParms.parameters;
            int keyBits  = RawEccKey.GetKeyLength(eccParms.curveID);

            byte[] keyExchangeKey = null;
            ephemPub = new EccPoint();

            // Make a new ephemeral key
            var     prov      = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(RawEccKey.GetEccAlg(PublicParms));
            var     ephKey    = prov.CreateKeyPair((uint)keyBits);
            IBuffer ephPubBuf = ephKey.ExportPublicKey(CryptographicPublicKeyBlobType.BCryptEccFullPublicKey);

            byte[] ephPub;
            CryptographicBuffer.CopyToByteArray(ephPubBuf, out ephPub);

            IBuffer otherPubBuf = Key.ExportPublicKey(CryptographicPublicKeyBlobType.BCryptEccFullPublicKey);

            byte[] otherPub;
            CryptographicBuffer.CopyToByteArray(otherPubBuf, out otherPub);

            byte[] herPubX, herPubY;
            RawEccKey.KeyInfoFromPublicBlob(otherPub, out herPubX, out herPubY);

            byte[] myPubX, myPubY;
            RawEccKey.KeyInfoFromPublicBlob(ephPub, out myPubX, out myPubY);

            byte[] otherInfo = Globs.Concatenate(new[] { encodingParms, myPubX, herPubX });

            // The TPM uses the following number of bytes from the KDF
            int bytesNeeded = CryptoLib.DigestSize(decryptKeyNameAlg);

            keyExchangeKey = new byte[bytesNeeded];

            for (int pos = 0, count = 1, bytesToCopy = 0;
                 pos < bytesNeeded;
                 ++count, pos += bytesToCopy)
            {
                byte[] secretPrepend = Marshaller.GetTpmRepresentation((UInt32)count);
                string algName;
                KeyDerivationParameters deriveParams;
                switch (decryptKeyNameAlg)
                {
                case TpmAlgId.Kdf1Sp800108:
                    algName      = KeyDerivationAlgorithmNames.Sp800108CtrHmacSha256;
                    deriveParams = KeyDerivationParameters.BuildForSP800108(CryptographicBuffer.CreateFromByteArray(secretPrepend), CryptographicBuffer.CreateFromByteArray(otherInfo));
                    break;

                case TpmAlgId.Kdf1Sp80056a:
                    algName      = KeyDerivationAlgorithmNames.Sp80056aConcatSha256;
                    deriveParams = KeyDerivationParameters.BuildForSP80056a(CryptographicBuffer.ConvertStringToBinary(algName, BinaryStringEncoding.Utf8),
                                                                            CryptographicBuffer.ConvertStringToBinary("TPM", BinaryStringEncoding.Utf8),
                                                                            CryptographicBuffer.CreateFromByteArray(secretPrepend),
                                                                            CryptographicBuffer.ConvertStringToBinary("", BinaryStringEncoding.Utf8),
                                                                            CryptographicBuffer.CreateFromByteArray(otherInfo));
                    break;

                case TpmAlgId.Kdf2:
                    algName      = KeyDerivationAlgorithmNames.Pbkdf2Sha256;
                    deriveParams = KeyDerivationParameters.BuildForPbkdf2(CryptographicBuffer.CreateFromByteArray(secretPrepend), 1000);
                    break;

                default:
                    Globs.Throw <ArgumentException>("wrong KDF name");
                    return(null);
                }
                KeyDerivationAlgorithmProvider deriveProv = KeyDerivationAlgorithmProvider.OpenAlgorithm(algName);
                IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(Key, deriveParams, (uint)keyBits);
                byte[]  fragment;
                CryptographicBuffer.CopyToByteArray(keyMaterial, out fragment);
                bytesToCopy = Math.Min(bytesNeeded - pos, fragment.Length);
                Array.Copy(fragment, 0, keyExchangeKey, pos, bytesToCopy);
            }
            ephemPub = new EccPoint(myPubX, myPubY);
            return(keyExchangeKey);
        }