/// <summary> /// Encrypt dataToEncrypt using the specified encodingParams (RSA only). /// </summary> /// <param name="plainText"></param> /// <param name="label"></param> /// <returns></returns> public byte[] EncryptOaep(byte[] plainText, byte[] label) { if (plainText == null) { plainText = new byte[0]; } if (label == null) { label = new byte[0]; } #if TSS_USE_BCRYPT var paddingInfo = new BCryptOaepPaddingInfo(OaepHash, label); byte[] cipherText = Key.Encrypt(plainText, paddingInfo); #elif false var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); byte[] cipherText = rr.OaepEncrypt(plainText, OaepHash, label); #else RSAParameters parms = RsaProvider.ExportParameters(false); var alg = new BCryptAlgorithm(Native.BCRYPT_RSA_ALGORITHM); var key = alg.LoadRSAKey(parms.Exponent, parms.Modulus); var paddingInfo = new BCryptOaepPaddingInfo(OaepHash, label); byte[] cipherText = key.Encrypt(plainText, paddingInfo); key.Destroy(); alg.Close(); #endif return(cipherText); }
public byte[] DecryptOaep(byte[] cipherText, byte[] label) { var rr = new RawRsa(Key); byte[] plainText = rr.OaepDecrypt(cipherText, OaepHash, label); return(plainText); }
/// <summary> /// Encrypt dataToEncrypt using the specified encodingParams (RSA only). /// </summary> /// <param name="dataToEncrypt"></param> /// <param name="label"></param> /// <returns></returns> public byte[] EncryptOaep(byte[] plainText, byte[] label) { if (plainText == null) { plainText = new byte[0]; } if (label == null) { label = new byte[0]; } var rr = new RawRsa(Key); byte[] cipherText = rr.OaepEncrypt(plainText, OaepHash, label);; return(cipherText); }
/// <summary> /// Create a new asymmetric key based on the parameters in keyParms. The resulting key data is returned in structures /// suitable for incorporation in a TPMT_PUBLIC and TPMS_SENSITIVE /// </summary> /// <param name="keyParms"></param> /// <param name="publicParms"></param> /// <returns></returns> internal static ISensitiveCompositeUnion CreateSensitiveComposite(TpmPublic keyParms, out IPublicIdUnion publicParms) { TpmAlgId keyAlgId = keyParms.type; ISensitiveCompositeUnion newSens; // Create the asymmetric key if (keyAlgId != TpmAlgId.Rsa) { Globs.Throw <ArgumentException>("Algorithm not supported"); } var newKeyPair = new RawRsa((keyParms.parameters as RsaParms).keyBits); // Put the key bits into the required structure envelopes newSens = new Tpm2bPrivateKeyRsa(newKeyPair.Private); publicParms = new Tpm2bPublicKeyRsa(newKeyPair.Public); return(newSens); }
public byte[] DecryptOaep(byte[] cipherText, byte[] label) { #if TSS_USE_BCRYPT var paddingInfo = new BCryptOaepPaddingInfo(OaepHash, label); byte[] plainText = Key.Decrypt(cipherText, paddingInfo); #elif true var rr = new RawRsa(RsaProvider.ExportParameters(true), RsaProvider.KeySize); byte[] plainText = rr.OaepDecrypt(cipherText, OaepHash, label); #else RSAParameters parms = RsaProvider.ExportParameters(true); var alg = new BCryptAlgorithm(Native.BCRYPT_RSA_ALGORITHM); var key = alg.LoadRSAKey(parms.Exponent, parms.Modulus, parms.P, parms.Q); var paddingInfo = new BCryptOaepPaddingInfo(OaepHash, label); byte[] plainText = key.Decrypt(cipherText, paddingInfo); key.Destroy(); alg.Close(); #endif return(plainText); }
CreateSensitiveComposite(TpmPublic pub, ref byte[] keyData, out IPublicIdUnion publicId) { ISensitiveCompositeUnion newSens = null; publicId = null; if (pub.type == TpmAlgId.Rsa) { if (keyData != null) { Globs.Throw <ArgumentException>("Cannot specify key data for an RSA key"); return(null); } var newKeyPair = new RawRsa((pub.parameters as RsaParms).keyBits); // Put the key bits into the required structure envelopes newSens = new Tpm2bPrivateKeyRsa(newKeyPair.Private); publicId = new Tpm2bPublicKeyRsa(newKeyPair.Public); } else if (pub.type == TpmAlgId.Symcipher) { var symDef = (SymDefObject)pub.parameters; if (symDef.Algorithm != TpmAlgId.Aes) { Globs.Throw <ArgumentException>("Unsupported symmetric algorithm"); return(null); } int keySize = (symDef.KeyBits + 7) / 8; if (keyData == null) { keyData = Globs.GetRandomBytes(keySize); } else if (keyData.Length != keySize) { keyData = Globs.CopyData(keyData); } else { Globs.Throw <ArgumentException>("Wrong symmetric key length"); return(null); } newSens = new Tpm2bSymKey(keyData); } else if (pub.type == TpmAlgId.Keyedhash) { var scheme = (pub.parameters as KeyedhashParms).scheme; TpmAlgId hashAlg = scheme is SchemeHash ? (scheme as SchemeHash).hashAlg : scheme is SchemeXor ? (scheme as SchemeXor).hashAlg : pub.nameAlg; var digestSize = CryptoLib.DigestSize(hashAlg); if (keyData == null) { keyData = Globs.GetRandomBytes(digestSize); } else if (keyData.Length <= CryptoLib.BlockSize(hashAlg)) { keyData = Globs.CopyData(keyData); } else { Globs.Throw <ArgumentException>("HMAC key is too big"); return(null); } newSens = new Tpm2bSensitiveData(keyData); } else { Globs.Throw <ArgumentException>("Unsupported key type"); } return(newSens); }
/// <summary> /// Verifies the signature over data or a digest. /// The data will be hashed internall by the method using hash algorithm from /// the signing scheme digest computed from the specified data buffer. /// The signing scheme is retrieved from the signature. The verification key /// shall have either compatible or null scheme. /// </summary> /// <param name="data">Byte buffer containing either digest or data to check against the signature</param> /// <param name="dataIsDigest">Specifies the type of 'data' parameter contents</param> /// <param name="signature">The signature</param> /// <returns>True if the verification succeeds.</returns> private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion sig) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif TpmAlgId sigScheme = sig.GetUnionSelector(); TpmAlgId sigHash = CryptoLib.SchemeHash(sig); var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif var s = sig as SignatureRsa; TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); if (sigScheme == TpmAlgId.Rsassa) { #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, s.sig, sigHash, true)); #else return(RsaProvider.VerifyHash(digest, CryptoLib.GetHashName(sigHash), s.sig)); #endif } if (sigScheme == TpmAlgId.Rsapss) { #if true Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported"); return(false); #else #if TSS_USE_BCRYPT return(BCryptInterface.VerifySignature(KeyHandle, digest, sig.sig, sigHash, false)); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); return(rr.PssVerify(digest, sig.sig, sigHash)); #endif #endif // false } Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme"); return(false); } var eccParams = PublicParms.parameters as EccParms; if (eccParams != null) { if (eccParams.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(false); } TpmAlgId keyScheme = eccParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } var s = sig as SignatureEcdsa; byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); byte[] sigBlob = Globs.Concatenate(s.signatureR, s.signatureS); #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, sigBlob)); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); return(EcdsaProvider.VerifyHash(digest, sigBlob)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(false); } // VerifySignature()
/// <summary> /// Sign using a non-default hash algorithm. /// </summary> /// <param name="data"></param> /// <param name="sigHash"></param> /// <returns></returns> public ISignatureUnion SignData(byte[] data, TpmAlgId sigHash) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif TpmAlgId sigScheme = rsaParams.scheme.GetUnionSelector(); switch (sigScheme) { case TpmAlgId.Rsassa: { if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsassa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT byte[] sig = Key.SignHash(digest, BcryptScheme.Rsassa, sigHash); #else byte[] sig = RsaProvider.SignData(data, CryptoLib.GetHashName(sigHash)); #endif return(new SignatureRsassa(sigHash, sig)); } case TpmAlgId.Rsapss: { #if true Globs.Throw <ArgumentException>("SignData(): PSS scheme is not supported"); return(null); #else if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsapss).hashAlg; } #if TSS_USE_BCRYPT byte[] sig = BCryptInterface.SignHash(KeyHandle, digest, sigHash, false); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); byte[] sig = rr.PssSign(digest, sigHash); #endif return(new SignatureRsapss(sigHash, sig)); #endif // false } } Globs.Throw <ArgumentException>("Unsupported signature scheme"); return(null); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(null); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT //throw new NotImplementedException("ECC signing with BCrypt is not implemented"); byte[] sig = Key.SignHash(digest, BcryptScheme.Ecdsa, sigHash); int len = sig.Length / 2; return(new SignatureEcdsa(sigHash, Globs.CopyData(sig, 0, len), Globs.CopyData(sig, len, len))); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); byte[] sig = EcdsaProvider.SignData(data); int fragLen = sig.Length / 2; var r = Globs.CopyData(sig, 0, fragLen); var s = Globs.CopyData(sig, fragLen, fragLen); return(new SignatureEcdsa(sigHash, r, s)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(null); } // SignData()
/// <summary> /// Create a new AsymCryptoSystem from TPM public parameter. This can then /// be used to validate TPM signatures or encrypt data destined for a TPM. /// </summary> /// <param name="pubKey"></param> /// <param name="privKey"></param> /// <returns></returns> public static AsymCryptoSystem CreateFrom(TpmPublic pubKey, TpmPrivate privKey = null) { var cs = new AsymCryptoSystem(); TpmAlgId keyAlgId = pubKey.type; cs.PublicParms = pubKey.Copy(); // Create an algorithm provider from the provided PubKey switch (keyAlgId) { case TpmAlgId.Rsa: { RawRsa rr = null; byte[] prime1 = null, prime2 = null; if (privKey != null) { rr = new RawRsa(pubKey, privKey); prime1 = RawRsa.ToBigEndian(rr.P); prime2 = RawRsa.ToBigEndian(rr.Q); } var rsaParams = (RsaParms)pubKey.parameters; var exponent = rsaParams.exponent != 0 ? Globs.HostToNet(rsaParams.exponent) : RsaParms.DefaultExponent; var modulus = (pubKey.unique as Tpm2bPublicKeyRsa).buffer; #if TSS_USE_BCRYPT var alg = new BCryptAlgorithm(Native.BCRYPT_RSA_ALGORITHM); cs.Key = alg.LoadRSAKey(exponent, modulus, prime1, prime2); alg.Close(); #else var dotNetPubParms = new RSAParameters() { Exponent = exponent, Modulus = modulus }; if (privKey != null) { dotNetPubParms.P = prime1; dotNetPubParms.Q = prime2; dotNetPubParms.D = RawRsa.ToBigEndian(rr.D); dotNetPubParms.InverseQ = RawRsa.ToBigEndian(rr.InverseQ); dotNetPubParms.DP = RawRsa.ToBigEndian(rr.DP); dotNetPubParms.DQ = RawRsa.ToBigEndian(rr.DQ); } cs.RsaProvider = new RSACryptoServiceProvider(); cs.RsaProvider.ImportParameters(dotNetPubParms); #endif break; } #if !__MonoCS__ case TpmAlgId.Ecc: { var eccParms = (EccParms)pubKey.parameters; var eccPub = (EccPoint)pubKey.unique; var algId = RawEccKey.GetEccAlg(pubKey); if (algId == null) { return(null); } bool isEcdsa = eccParms.scheme.GetUnionSelector() == TpmAlgId.Ecdsa; byte[] keyBlob = RawEccKey.GetKeyBlob(eccPub.x, eccPub.y, keyAlgId, !isEcdsa, eccParms.curveID); #if TSS_USE_BCRYPT var alg = new BCryptAlgorithm(algId); cs.Key = alg.ImportKeyPair(Native.BCRYPT_ECCPUBLIC_BLOB, keyBlob); alg.Close(); if (cs.Key == UIntPtr.Zero) { Globs.Throw("Failed to create new RSA key"); return(null); } #else CngKey eccKey = CngKey.Import(keyBlob, CngKeyBlobFormat.EccPublicBlob); if (pubKey.objectAttributes.HasFlag(ObjectAttr.Sign)) { cs.EcdsaProvider = new ECDsaCng(eccKey); } else { cs.EcDhProvider = new ECDiffieHellmanCng(eccKey); } #endif // !TSS_USE_BCRYPT break; } #endif // !__MonoCS__ default: Globs.Throw <ArgumentException>("Algorithm not supported"); cs = null; break; } return(cs); }
/// <summary> /// Create a new AsymCryptoSystem from TPM public parameter. This can then /// be used to validate TPM signatures or encrypt data destined for a TPM. /// </summary> /// <param name="pubKey"></param> /// <returns></returns> public static AsymCryptoSystem CreateFrom(TpmPublic pubKey, TpmPrivate privKey = null) { var cs = new AsymCryptoSystem(); TpmAlgId keyAlgId = pubKey.type; cs.PublicParms = pubKey.Copy(); // Create an algorithm provider from the provided PubKey switch (keyAlgId) { case TpmAlgId.Rsa: { RawRsa rr = null; byte[] prime1 = null, prime2 = null; if (privKey != null) { rr = new RawRsa(pubKey, privKey); prime1 = RawRsa.ToBigEndian(rr.P); prime2 = RawRsa.ToBigEndian(rr.Q); } var rsaParams = (RsaParms)pubKey.parameters; var exponent = rsaParams.exponent != 0 ? Globs.HostToNet(rsaParams.exponent) : RsaParms.DefaultExponent; var modulus = (pubKey.unique as Tpm2bPublicKeyRsa).buffer; AsymmetricKeyAlgorithmProvider rsaProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha256); uint primeLen1 = 0, primeLen2 = 0; // Compute the size of BCRYPT_RSAKEY_BLOB int rsaKeySize = exponent.Length + modulus.Length + 24; if (prime1 != null && prime1.Length > 0) { if (prime2 == null || prime2.Length == 0) { Globs.Throw <ArgumentException>("LoadRSAKey(): The second prime is missing"); return(null); } primeLen1 = (uint)prime1.Length; primeLen2 = (uint)prime2.Length; rsaKeySize += prime1.Length + prime2.Length; } else if (prime2 != null && prime2.Length > 0) { Globs.Throw <ArgumentException>("LoadRSAKey(): The first prime is missing"); return(null); } var rsaKey = new byte[rsaKeySize]; // Initialize BCRYPT_RSAKEY_BLOB int offset = 0; WriteToBuffer(ref rsaKey, ref offset, primeLen1 == 0 ? BCRYPT_RSAPUBLIC_MAGIC : BCRYPT_RSAPRIVATE_MAGIC); WriteToBuffer(ref rsaKey, ref offset, (uint)modulus.Length * 8); WriteToBuffer(ref rsaKey, ref offset, (uint)exponent.Length); WriteToBuffer(ref rsaKey, ref offset, (uint)modulus.Length); WriteToBuffer(ref rsaKey, ref offset, primeLen1); WriteToBuffer(ref rsaKey, ref offset, primeLen1); WriteToBuffer(ref rsaKey, ref offset, exponent); WriteToBuffer(ref rsaKey, ref offset, modulus); if (primeLen1 != 0) { WriteToBuffer(ref rsaKey, ref offset, prime1); WriteToBuffer(ref rsaKey, ref offset, prime2); } IBuffer rsaBuffer = CryptographicBuffer.CreateFromByteArray(rsaKey); if (primeLen1 == 0) { cs.Key = rsaProvider.ImportPublicKey(rsaBuffer, CryptographicPublicKeyBlobType.BCryptPublicKey); } else { cs.Key = rsaProvider.ImportKeyPair(rsaBuffer, CryptographicPrivateKeyBlobType.BCryptPrivateKey); } break; } case TpmAlgId.Ecc: { var eccParms = (EccParms)pubKey.parameters; var eccPub = (EccPoint)pubKey.unique; var algId = RawEccKey.GetEccAlg(pubKey); if (algId == null) { return(null); } bool isEcdsa = eccParms.scheme.GetUnionSelector() == TpmAlgId.Ecdsa; byte[] keyBlob = RawEccKey.GetKeyBlob(eccPub.x, eccPub.y, keyAlgId, !isEcdsa, eccParms.curveID); AsymmetricKeyAlgorithmProvider eccProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algId); cs.Key = eccProvider.ImportKeyPair(CryptographicBuffer.CreateFromByteArray(keyBlob)); break; } default: Globs.Throw <ArgumentException>("Algorithm not supported"); cs = null; break; } return(cs); }