public byte[] Export(string bcryptBlobType) { #if !TSS_USE_BCRYPT return(null); #else //RSAParameters parms = RsaProvider.ExportParameters(bcryptBlobType == Native.BCRYPT_RSAPRIVATE_BLOB); //var alg = new BCryptAlgorithm(Native.BCRYPT_RSA_ALGORITHM); //var Key = alg.LoadRSAKey(parms.Exponent, parms.Modulus, parms.P, parms.Q); byte[] keyBlob = Key.Export(bcryptBlobType); //Key.Destroy(); //alg.Close(); return(keyBlob); #endif }
} // 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); }
/// <summary> /// Create a new random software key (public and private) matching the parameters in keyParams. /// </summary> /// <param name="keyParams"></param> /// <returns></returns> public AsymCryptoSystem(TpmPublic keyParams) { TpmAlgId keyAlgId = keyParams.type; PublicParms = keyParams.Copy(); switch (keyAlgId) { case TpmAlgId.Rsa: { var rsaParams = keyParams.parameters as RsaParms; #if TSS_USE_BCRYPT Key = Generate(Native.BCRYPT_RSA_ALGORITHM, rsaParams.keyBits); if (Key == UIntPtr.Zero) { Globs.Throw("Failed to generate RSA key"); return; } byte[] blob = Export(Native.BCRYPT_RSAPUBLIC_BLOB); var m = new Marshaller(blob, DataRepresentation.LittleEndian); var header = m.Get <BCryptRsaKeyBlob>(); /*var exponent = */ m.GetArray <byte>((int)header.cbPublicExp); var modulus = m.GetArray <byte>((int)header.cbModulus); #else RsaProvider = new RSACryptoServiceProvider(rsaParams.keyBits); var modulus = RsaProvider.ExportParameters(true).Modulus; #endif var pubId = new Tpm2bPublicKeyRsa(modulus); PublicParms.unique = pubId; break; } #if !__MonoCS__ case TpmAlgId.Ecc: { var eccParms = keyParams.parameters as EccParms; var alg = RawEccKey.GetEccAlg(keyParams); if (alg == null) { Globs.Throw <ArgumentException>("Unknown ECC curve"); return; } byte[] keyIs; #if TSS_USE_BCRYPT Key = Generate(alg, (uint)RawEccKey.GetKeyLength(eccParms.curveID)); //BCRYPT_ECCPRIVATE_BLOB; keyIs = Key.Export(Native.BCRYPT_ECCPUBLIC_BLOB); #else var keyParmsX = new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextExport }; using (CngKey key = CngKey.Create(alg, null, keyParmsX)) { keyIs = key.Export(CngKeyBlobFormat.EccPublicBlob); CngKey.Import(keyIs, CngKeyBlobFormat.EccPublicBlob); if (keyParams.objectAttributes.HasFlag(ObjectAttr.Sign)) { EcdsaProvider = new ECDsaCng(key); } else { EcDhProvider = new ECDiffieHellmanCng(key); } } #endif // !TSS_USE_BCRYPT // Store the public key const int offset = 8; int keySize = 0; switch (eccParms.curveID) { case EccCurve.NistP256: case EccCurve.BnP256: case EccCurve.Sm2P256: keySize = 32; break; case EccCurve.NistP384: keySize = 48; break; case EccCurve.NistP521: keySize = 66; break; default: throw new NotImplementedException(); } var pubId = new EccPoint( Globs.CopyData(keyIs, offset, keySize), Globs.CopyData(keyIs, offset + keySize, keySize)); PublicParms.unique = pubId; break; } #endif // !__MonoCS__ default: Globs.Throw <ArgumentException>("Algorithm not supported"); break; } }