Exemple #1
0
        /// <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);
        }
Exemple #4
0
        /// <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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        /// <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()
Exemple #8
0
        /// <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()
Exemple #9
0
        /// <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);
        }