Exemplo n.º 1
0
        public static byte[] PssEncode(byte[] m, TpmAlgId hashAlg, int sLen, int emBits)
        {
            var emLen = (int)Math.Ceiling(1.0 * emBits / 8);
            int hLen  = CryptoLib.DigestSize(hashAlg);

            // 1 - Ignore
            // 2
            byte[] mHash = TpmHash.FromData(hashAlg, m);

            // 3
            if (emLen < hLen + sLen + 2)
            {
                if (Tpm2._TssBehavior.Passthrough)
                {
                    return(new byte[0]);
                }
                else
                {
                    throw new Exception("Encoding error");
                }
            }

            // 4
            byte[] salt = Globs.GetRandomBytes(sLen);

            // 5
            byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0),
                                                      mHash,
                                                      salt });

            // 6
            byte[] h = CryptoLib.HashData(hashAlg, mPrime);

            // 7
            byte[] ps = Globs.GetZeroBytes(emLen - sLen - hLen - 2);

            // 8
            byte[] db = Globs.Concatenate(new[] { ps,
                                                  new byte[] { 0x01 },
                                                  salt });

            // 9
            byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg);

            // 10
            byte[] maskedDb = XorEngine.Xor(db, dbMask);

            // 11
            int  numZeroBits = 8 * emLen - emBits;
            byte mask        = GetByteMask(numZeroBits);

            maskedDb[0] &= mask;

            // 12
            byte[] em = Globs.Concatenate(new[] { maskedDb,
                                                  h,
                                                  new byte[] { 0xbc } });
            // 13
            return(em);
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Create activation blobs that can be passed to ActivateCredential.  Two blobs are returned -
        /// (a) - encryptedSecret - is the symmetric key cfb-symmetrically encrypted with an enveloping key
        /// (b) credentialBlob (the return value of this function) - is the enveloping key OEAP (RSA) encrypted
        ///         by the public part of this key.
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="nameAlgId"></param>
        /// <param name="nameOfKeyToBeActivated"></param>
        /// <param name="encryptedSecret"></param>
        /// <returns>CredentialBlob (</returns>
        public byte[] CreateActivationCredentials(
            byte[] secret,
            TpmAlgId nameAlgId,
            byte[] nameOfKeyToBeActivated,
            out byte[] encryptedSecret)
        {
            byte[] seed, encSecret;

            switch (type)
            {
            case TpmAlgId.Rsa:
                // The seed should be the same size as the symmKey
                seed      = Globs.GetRandomBytes((CryptoLib.DigestSize(nameAlg) + 7) / 8);
                encSecret = EncryptOaep(seed, ActivateEncodingParms);
                break;

            case TpmAlgId.Ecc:
                EccPoint pubEphem;
                seed      = EcdhGetKeyExchangeKey(ActivateEncodingParms, nameAlg, out pubEphem);
                encSecret = Marshaller.GetTpmRepresentation(pubEphem);
                break;

            default:
                Globs.Throw <NotImplementedException>("CreateActivationCredentials: Unsupported algorithm");
                encryptedSecret = new byte[0];
                return(new byte[0]);
            }

            var cvx = new Tpm2bDigest(secret);

            byte[] cvTpm2B = Marshaller.GetTpmRepresentation(cvx);

            SymDefObject symDef = TssObject.GetSymDef(this);

            byte[] symKey = KDF.KDFa(nameAlg, seed, "STORAGE", nameOfKeyToBeActivated, new byte[0], symDef.KeyBits);

            byte[] encIdentity;
            using (SymmCipher symm2 = SymmCipher.Create(symDef, symKey))
            {
                encIdentity = symm2.Encrypt(cvTpm2B);
            }

            var hmacKeyBits = CryptoLib.DigestSize(nameAlg);

            byte[] hmacKey   = KDF.KDFa(nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], hmacKeyBits * 8);
            byte[] outerHmac = CryptoLib.HmacData(nameAlg,
                                                  hmacKey,
                                                  Globs.Concatenate(encIdentity, nameOfKeyToBeActivated));

            byte[] activationBlob = Globs.Concatenate(
                Marshaller.ToTpm2B(outerHmac),
                encIdentity);
            encryptedSecret = encSecret;

            return(activationBlob);
        }
Exemplo n.º 4
0
        public static byte[] Pkcs15Encode(byte[] m, int emLen, TpmAlgId hashAlg)
        {
            byte[] prefix;
            switch (hashAlg)
            {
            case TpmAlgId.Sha1:
                prefix = new byte[]
                { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
                  0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
                break;

            case TpmAlgId.Sha256:
                prefix = new byte[] {
                    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
                    0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
                };
                break;

            case TpmAlgId.Sha384:
                prefix = new byte[] {
                    0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
                    0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
                };
                break;

            case TpmAlgId.Sha512:
                prefix = new byte[] {
                    0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
                    0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
                };
                break;

            default:
                Globs.Throw <ArgumentException>("Pkcs15Encode: Unsupported hashAlg");
                return(new byte[0]);
            }
            byte[] messageHash = TpmHash.FromData(hashAlg, m);
            byte[] T           = Globs.Concatenate(prefix, messageHash);
            int    tLen        = T.Length;

            if (emLen < tLen + 11)
            {
                Globs.Throw <ArgumentException>("Pkcs15Encode: Encoded message is too short");
                return(new byte[0]);
            }

            byte[] ps = Globs.ByteArray(emLen - tLen - 3, 0xff);
            byte[] em = Globs.Concatenate(new[] { new byte[] { 0x00, 0x01 }, ps,
                                                  new byte[] { 0x00 }, T });
            return(em);
        }
Exemplo n.º 5
0
        TkVerified SignApproval(Tpm2 tpm, byte[] approvedPolicy, byte[] policyRef,
                                TpmHandle hSigKey, ISigSchemeUnion scheme = null)
        {
            byte[]    name, qname;
            TpmPublic pub = tpm.ReadPublic(hSigKey, out name, out qname);

            byte[] dataToSign = Globs.Concatenate(approvedPolicy, policyRef);
            byte[] aHash      = CryptoLib.HashData(pub.nameAlg, dataToSign);

            // Create an authorization certificate for the "approvedPolicy"
            var sig = tpm.Sign(hSigKey, aHash, scheme, new TkHashcheck());

            return(tpm.VerifySignature(hSigKey, aHash, sig));
        }
Exemplo n.º 6
0
 /// <summary>
 /// Calculate the qualified name of an object presumed loaded under the provided ancestral chain
 /// in a given hierarchy.
 /// </summary>
 /// <param name="hierarchyHandle"></param>
 /// <param name="children"></param>
 /// <returns></returns>
 public static byte[] GetQualifiedName(TpmHandle hierarchyHandle, TpmPublic[] children)
 {
     byte[] runningName = Marshaller.GetTpmRepresentation(hierarchyHandle);
     foreach (TpmPublic pub in children)
     {
         byte[] thisName = pub.GetName();
         runningName = Globs.Concatenate
                       (
             Marshaller.GetTpmRepresentation(pub.nameAlg),
             CryptoLib.HashData(pub.nameAlg, new[] { runningName, thisName })
                       );
     }
     return(runningName);
 }
Exemplo n.º 7
0
        /// <summary>
        /// Calculate and return the auth-hmac (or plaintext auth if it is a policy session with PlaintextAuth set)
        /// based on the current session parms.
        /// </summary>
        /// <param name="parmHash"></param>
        /// <param name="direction"></param>
        /// <param name="nonceDec"></param>
        /// <param name="nonceEnc"></param>
        /// <returns></returns>
        internal byte[] GetAuthHmac(byte[] parmHash, Direction direction, byte[] nonceDec = null, byte[] nonceEnc = null)
        {
            // special case.  If this is a policy session and the session includes PolicyPassword the
            // TPM expects and assumes that the HMAC field will have the plaintext entity field as in
            // a PWAP session (the related PolicyAuthValue demands an HMAC as usual)
            if (PlaintextAuth)
            {
                return(Handle.Auth ?? AuthHandle.Auth);
            }

            byte[] nonceNewer, nonceOlder;
            if (direction == Direction.Command)
            {
                nonceNewer = NonceCaller;
                nonceOlder = NonceTpm;
            }
            else
            {
                nonceNewer = NonceTpm;
                nonceOlder = NonceCaller;
            }
            byte[] sessionAttrs = Marshaller.GetTpmRepresentation(Attrs);

            byte[] auth = Handle.Auth;
            if (AuthHandle != null && Handle != TpmRh.TpmRsPw && auth == null &&
                ((SessionType != TpmSe.Policy && BindObject != AuthHandle) ||
                 (SessionType == TpmSe.Policy && SessIncludesAuth)))
            {
                auth = Globs.TrimTrailingZeros(AuthHandle.Auth);
            }
            byte[] hmacKey   = Globs.Concatenate(SessionKey, auth);
            byte[] bufToHmac = Globs.Concatenate(new[] { parmHash, nonceNewer, nonceOlder,
                                                         nonceDec, nonceEnc, sessionAttrs });

            byte[] hmac = CryptoLib.Hmac(AuthHash, hmacKey, bufToHmac);
#if false
            Console.WriteLine(Globs.FormatBytesCompact("hmacKey: ", hmacKey));
            Console.WriteLine(Globs.FormatBytesCompact("nonceNewer: ", nonceNewer));
            Console.WriteLine(Globs.FormatBytesCompact("nonceOlder: ", nonceOlder));
            Console.WriteLine(Globs.FormatBytesCompact("nonceDec: ", nonceDec));
            Console.WriteLine(Globs.FormatBytesCompact("nonceEnc: ", nonceEnc));
            Console.WriteLine(Globs.FormatBytesCompact("attrs: ", sessionAttrs));
            Console.WriteLine(Globs.FormatBytesCompact("HMAC: ", hmac));
#endif
            return(hmac);
        }
Exemplo n.º 8
0
        // ReSharper disable once InconsistentNaming
        public static byte[] KDFa(TpmAlgId hmacHash, byte[] hmacKey, string label, byte[] contextU, byte[] contextV, uint numBitsRequired)
        {
            int  bitsPerLoop = CryptoLib.DigestSize(hmacHash) * 8;
            long numLoops    = (numBitsRequired + bitsPerLoop - 1) / bitsPerLoop;
            var  kdfStream   = new byte[numLoops * bitsPerLoop / 8];

            for (int j = 0; j < numLoops; j++)
            {
                byte[] toHmac = Globs.Concatenate(new[] {
                    Globs.HostToNet(j + 1),
                    Encoding.UTF8.GetBytes(label), Globs.HostToNet((byte)0),
                    contextU,
                    contextV,
                    Globs.HostToNet(numBitsRequired)
                });
                byte[] fragment = CryptoLib.HmacData(hmacHash, hmacKey, toHmac);
                Array.Copy(fragment, 0, kdfStream, j * bitsPerLoop / 8, fragment.Length);
            }
            return(Globs.ShiftRight(kdfStream, (int)(bitsPerLoop * numLoops - numBitsRequired)));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Calculate the session-key from the nonces and salt/bound values (if present)
        /// </summary>
        public void CalcSessionKey()
        {
            if (Salt == SaltNeeded)
            {
                Globs.Throw("Unencrypted salt value must be provided for the session" +
                            Handle.handle.ToString("X8"));
            }

            // Compute Handle.Auth in accordance with Part 1, 19.6.8.
            if (Salt == null && BindObject == TpmRh.Null)
            {
                SessionKey = new byte[0];
                return;
            }

            byte[] auth    = Globs.TrimTrailingZeros(BindObject.Auth);
            byte[] hmacKey = Globs.Concatenate(auth, Salt);
            SessionKey = KDF.KDFa(AuthHash, hmacKey, "ATH", NonceTpm, NonceCaller,
                                  TpmHash.DigestSize(AuthHash) * 8);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Calculate the session-key from the nonces and salt/bound values (if present)
        /// </summary>
        internal void CalcSessionKey()
        {
            Debug.Assert(SessionKey == null, "Attempt to repeatedly calculate session key");

            if (Salt == SaltNeeded)
            {
                Globs.Throw(string.Format("Unencrypted salt value must be provided for the session {0:x}", Handle.handle));
            }

            // Compute Handle.Auth in accordance with Part 1, 19.6.8.
            if (Salt == null && BindObject == TpmRh.Null)
            {
                SessionKey = new byte[0];
                return;
            }

            byte[] auth    = Globs.TrimTrailingZeros(BindObject.Auth);
            byte[] hmacKey = Globs.Concatenate(auth, Salt);
            SessionKey = KDF.KDFa(AuthHash, hmacKey, "ATH", NonceTpm, NonceCaller,
                                  TpmHash.DigestSize(AuthHash) * 8);
        }
Exemplo n.º 11
0
 public static byte[] HashData(TpmAlgId alg, byte[][] dataToHash)
 {
     byte[] temp = Globs.Concatenate(dataToHash);
     return(HashData(alg, temp));
 }
Exemplo n.º 12
0
        /// <summary>
        /// PSS verify.  Note: we expect the caller to do the hash.
        /// </summary>
        /// <param name="m"></param>
        /// <param name="em"></param>
        /// <param name="sLen"></param>
        /// <param name="emBits"></param>
        /// <param name="hashAlg"></param>
        /// <returns></returns>
        public static bool PssVerify(byte[] m, byte[] em, int sLen, int emBits, TpmAlgId hashAlg)
        {
            var emLen = (int)Math.Ceiling(1.0 * emBits / 8);
            int hLen  = CryptoLib.DigestSize(hashAlg);

            // 1 - Skip
            // 2
            byte[] mHash = TpmHash.FromData(hashAlg, m);

            // 3
            if (emLen < hLen + sLen + 2)
            {
                return(false);
            }

            // 4
            if (em[em.Length - 1] != 0xbc)
            {
                return(false);
            }

            // 5
            byte[] maskedDB = Globs.CopyData(em, 0, emLen - hLen - 1);
            byte[] h        = Globs.CopyData(em, emLen - hLen - 1, hLen);

            // 6
            int numZeroBits = 8 * emLen - emBits;
            // First numZero bits is zero in mask
            byte mask = GetByteMask(numZeroBits);

            if ((maskedDB[0] & mask) != maskedDB[0])
            {
                return(false);
            }

            // 7
            byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg);

            // 8
            byte[] db = XorEngine.Xor(maskedDB, dbMask);

            // 9
            int  numZeroBits2 = 8 * emLen - emBits;
            byte mask2        = GetByteMask(numZeroBits2);

            db[0] &= mask2;

            // 10
            for (int j = 0; j < emLen - hLen - sLen - 2; j++)
            {
                if (db[j] != 0)
                {
                    return(false);
                }
            }
            if (db[emLen - hLen - sLen - 1 - 1] != 1)
            {
                return(false);
            }

            // 11
            byte[] salt = Globs.CopyData(db, db.Length - sLen);

            // 12
            byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt });

            // 13
            byte[] hPrime = TpmHash.FromData(hashAlg, mPrime);

            // 14
            bool match = Globs.ArraysAreEqual(h, hPrime);

            if (match == false)
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 13
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)
        {
            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);
        }
Exemplo n.º 14
0
 public static byte[] HmacData(TpmAlgId underlyingHash, byte[] key, byte[][] dataToHash)
 {
     byte[] temp = Globs.Concatenate(dataToHash);
     return(HmacData(underlyingHash, key, temp));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Creates a duplication blob for the current key that can be Imported as a child
        /// of newParent. Three forms are possible. GetPlaintextDuplicationBlob() allows
        /// plaintext-import. This function enables duplication with and without an
        /// inner wrapper (depending on whether innerWrapper is null)
        /// </summary>
        /// <param name="newParent"></param>
        /// <param name="innerWrapper"></param>
        /// <param name="encSecret"></param>
        /// <returns></returns>
        public TpmPrivate GetDuplicationBlob(
            TpmPublic pubNewParent,
            SymCipher innerWrapper,
            out byte[] encSecret)
        {
            byte[] encSensitive;
            if (innerWrapper == null)
            {
                // No inner wrapper
                encSensitive = Marshaller.ToTpm2B(Sensitive.GetTpmRepresentation());
                Transform(encSensitive);
            }
            else
            {
                byte[] sens   = Marshaller.ToTpm2B(Sensitive.GetTpmRepresentation());
                byte[] toHash = Globs.Concatenate(sens, GetName());
                Transform(toHash);
                byte[] innerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData(
                                                               Public.nameAlg, toHash));
                byte[] innerData = Globs.Concatenate(innerIntegrity, sens);
                Transform(innerData);
                encSensitive = innerWrapper.Encrypt(innerData);
                Transform(encSensitive);
            }

            byte[]       seed;
            SymDefObject symDef = GetSymDef(pubNewParent).Copy();

            // TPM duplication procedures always use CFB mode
            symDef.Mode = TpmAlgId.Cfb;

            using (var swNewParent = AsymCryptoSystem.CreateFrom(pubNewParent))
            {
                switch (pubNewParent.type)
                {
                case TpmAlgId.Rsa:
                    // The seed should be the same size as the scheme hash
                    LastSeed =
                        seed = Globs.GetRandomBytes(
                            CryptoLib.DigestSize(swNewParent.OaepHash));
                    encSecret = swNewParent.EncryptOaep(seed, DuplicateEncodingParms);
                    break;

                case TpmAlgId.Ecc:
                    EccPoint pubEphem;
                    seed = swNewParent.EcdhGetKeyExchangeKey(DuplicateEncodingParms,
                                                             pubNewParent.nameAlg,
                                                             out pubEphem);
                    encSecret = Marshaller.GetTpmRepresentation(pubEphem);
                    break;

                default:
                    Globs.Throw <NotImplementedException>(
                        "GetDuplicationBlob: Unsupported algorithm");
                    encSecret = new byte[0];
                    return(new TpmPrivate());
                }
            }
            Transform(seed);
            Transform(encSecret);

            byte[] symKey = KDF.KDFa(pubNewParent.nameAlg, seed, "STORAGE",
                                     Public.GetName(), new byte[0], symDef.KeyBits);
            Transform(symKey);

            byte[] dupSensitive;
            using (SymCipher enc2 = SymCipher.Create(symDef, symKey))
            {
                if (enc2 == null)
                {
                    return(null);
                }

                dupSensitive = enc2.Encrypt(encSensitive);
            }
            Transform(dupSensitive);

            var npNameNumBits = CryptoLib.DigestSize(pubNewParent.nameAlg) * 8;

            byte[] hmacKey = KDF.KDFa(pubNewParent.nameAlg, seed, "INTEGRITY",
                                      new byte[0], new byte[0], npNameNumBits);

            byte[] outerDataToHmac = Globs.Concatenate(dupSensitive, Public.GetName());
            Transform(outerDataToHmac);

            byte[] outerHmac = Marshaller.ToTpm2B(CryptoLib.Hmac(pubNewParent.nameAlg,
                                                                 hmacKey, outerDataToHmac));
            Transform(outerHmac);

            byte[] dupBlob = Globs.Concatenate(outerHmac, dupSensitive);
            Transform(dupBlob);

            return(new TpmPrivate(dupBlob));
        }
Exemplo n.º 16
0
        /// <summary>
        /// Create activation blobs that can be passed to ActivateCredential. Two
        /// blobs are returned:
        /// 1) encryptedSecret - symmetric key cfb-symmetrically encrypted with the
        ///                      enveloping key;
        /// 2) credentialBlob -  the enveloping key OEAP (RSA) encrypted by the public
        ///                      part of this key. This is the return value of this
        ///                      function
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="nameOfKeyToBeActivated"></param>
        /// <param name="encryptedSecret"></param>
        /// <returns>CredentialBlob (</returns>
        public IdObject CreateActivationCredentials(byte[] secret,
                                                    byte[] nameOfKeyToBeActivated,
                                                    out byte[] encryptedSecret)
        {
            byte[] seed, encSecret;

            switch (type)
            {
            case TpmAlgId.Rsa:
                // The seed should be the same size as the name algorithmdigest
                seed      = Globs.GetRandomBytes(CryptoLib.DigestSize(nameAlg));
                encSecret = EncryptOaep(seed, ActivateEncodingParms);
                break;

            case TpmAlgId.Ecc:
                EccPoint ephemPubPt;
                seed      = EcdhGetKeyExchangeKey(ActivateEncodingParms, out ephemPubPt);
                encSecret = Marshaller.GetTpmRepresentation(ephemPubPt);
                break;

            default:
                Globs.Throw <NotImplementedException>(
                    "CreateActivationCredentials: Unsupported algorithm");
                encryptedSecret = new byte[0];
                return(null);
            }

            Transform(seed);
            Transform(encSecret);

            var cvx = new Tpm2bDigest(secret);

            byte[] cvTpm2B = Marshaller.GetTpmRepresentation(cvx);
            Transform(cvTpm2B);

            SymDefObject symDef = TssObject.GetSymDef(this);

            byte[] symKey = KDF.KDFa(nameAlg, seed, "STORAGE",
                                     nameOfKeyToBeActivated, new byte[0], symDef.KeyBits);
            Transform(symKey);

            byte[] encIdentity;
            // TPM only uses CFB mode in its command implementations
            var sd = symDef.Copy();

            sd.Mode = TpmAlgId.Cfb;
            using (var sym = SymCipher.Create(sd, symKey))
            {
                // Not all keys specs are supported by SW crypto
                if (sym == null)
                {
                    encryptedSecret = null;
                    return(null);
                }
                encIdentity = sym.Encrypt(cvTpm2B);
            }
            Transform(encIdentity);

            var hmacKeyBits = CryptoLib.DigestSize(nameAlg);

            byte[] hmacKey = KDF.KDFa(nameAlg, seed, "INTEGRITY",
                                      new byte[0], new byte[0], hmacKeyBits * 8);
            Transform(hmacKey);
            byte[] outerHmac = CryptoLib.Hmac(nameAlg, hmacKey,
                                              Globs.Concatenate(encIdentity, nameOfKeyToBeActivated));
            Transform(outerHmac);


            encryptedSecret = encSecret;
            return(new IdObject(outerHmac, encIdentity));
        }
Exemplo n.º 17
0
        /// <summary>
        /// Creates a duplication blob for the current key that can be Imported as a child
        /// of newParent. Three forms are possible. GetPlaintextDuplicationBlob() allows
        /// plaintext-import. This function enables duplication with and without an
        /// inner wrapper (depending on whether innerWrapper is null)
        /// </summary>
        /// <param name="newParent"></param>
        /// <param name="innerWrapper"></param>
        /// <param name="encryptedWrappingKey"></param>
        /// <returns></returns>
        public TpmPrivate GetDuplicationBlob(
            TpmPublic newParent,
            SymmCipher innerWrapper,
            out byte[] encryptedWrappingKey)
        {
            byte[] encSensitive;
            if (innerWrapper == null)
            {
                // No inner wrapper
                encSensitive = Marshaller.ToTpm2B(sensitivePart.GetTpmRepresentation());
            }
            else
            {
                byte[] sens           = Marshaller.ToTpm2B(sensitivePart.GetTpmRepresentation());
                byte[] toHash         = Globs.Concatenate(sens, GetName());
                byte[] innerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData(publicPart.nameAlg, toHash));
                byte[] innerData      = Globs.Concatenate(innerIntegrity, sens);
                encSensitive = innerWrapper.Encrypt(innerData);
            }

            byte[]       seed, encSecret;
            SymDefObject symDef = GetSymDef(newParent);

            using (AsymCryptoSystem newParentPubKey = AsymCryptoSystem.CreateFrom(newParent))
            {
                switch (newParent.type)
                {
                case TpmAlgId.Rsa:
                    // The seed should be the same size as the symmKey
                    seed      = Globs.GetRandomBytes((symDef.KeyBits + 7) / 8);
                    encSecret = newParentPubKey.EncryptOaep(seed, DuplicateEncodingParms);
                    break;

                case TpmAlgId.Ecc:
                    EccPoint pubEphem;
                    seed = newParentPubKey.EcdhGetKeyExchangeKey(DuplicateEncodingParms,
                                                                 newParent.nameAlg,
                                                                 out pubEphem);
                    encSecret = Marshaller.GetTpmRepresentation(pubEphem);
                    break;

                default:
                    Globs.Throw <NotImplementedException>("GetDuplicationBlob: Unsupported algorithm");
                    encryptedWrappingKey = new byte[0];
                    return(new TpmPrivate());
                }
            }

            encryptedWrappingKey = encSecret;

            byte[] symKey = KDF.KDFa(newParent.nameAlg, seed, "STORAGE", publicPart.GetName(), new byte[0], symDef.KeyBits);

            byte[] dupSensitive;
            using (SymmCipher enc2 = SymmCipher.Create(symDef, symKey))
            {
                dupSensitive = enc2.Encrypt(encSensitive);
            }

            var npNameNumBits = CryptoLib.DigestSize(newParent.nameAlg) * 8;

            byte[] hmacKey = KDF.KDFa(newParent.nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], npNameNumBits);

            byte[] outerDataToHmac = Globs.Concatenate(dupSensitive, publicPart.GetName());

            byte[] outerHmac = Marshaller.ToTpm2B(CryptoLib.HmacData(newParent.nameAlg, hmacKey, outerDataToHmac));

            byte[] dupBlob = Globs.Concatenate(outerHmac, dupSensitive);

            return(new TpmPrivate(dupBlob));
        }
Exemplo n.º 18
0
        private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion signature, TpmAlgId sigHash)
        {
            var rsaParams = PublicParms.parameters as RsaParms;

            if (rsaParams != null)
            {
                var      sig       = signature as SignatureRsa;
                TpmAlgId sigScheme = sig.GetUnionSelector();
                TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector();

                if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme)
                {
                    Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match");
                    return(false);
                }
                if (sigHash == TpmAlgId.Null)
                {
                    sigHash = (rsaParams.scheme as SchemeHash).hashAlg;
                }
                if (sigHash != sig.hash)
                {
                    Globs.Throw <ArgumentException>("Key scheme hash and signature scheme hash do not match");
                    return(false);
                }

                byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data);

                if (sigScheme == TpmAlgId.Rsassa)
                {
                    return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sig.sig)));
                }
                if (sigScheme == TpmAlgId.Rsapss)
                {
                    Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported");
                    return(false);
                }
                Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme");
                return(false);
            }

            var eccParms = PublicParms.parameters as EccParms;

            if (eccParms != null)
            {
                if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa)
                {
                    Globs.Throw <ArgumentException>("Unsupported ECC sig scheme");
                    return(false);
                }
                if (sigHash == TpmAlgId.Null)
                {
                    sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg;
                }

                byte[] digest  = dataIsDigest ? data : CryptoLib.HashData(sigHash, data);
                var    sig     = signature as SignatureEcdsa;
                byte[] sigBlob = Globs.Concatenate(sig.signatureR, sig.signatureS);
                return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sigBlob)));
            }

            // Should never be here
            Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm");
            return(false);
        } // VerifySignature()
Exemplo n.º 19
0
 public static byte[] HashData(TpmAlgId alg, byte[] data1, byte[] data2)
 {
     return(HashData(alg, Globs.Concatenate(data1, data2)));
 }
Exemplo n.º 20
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()