示例#1
0
        /// <summary>
        /// Creates a *software* key.  The key will be random (not created from
        /// a seed).  The key can be used as the root of a software hierarchy that
        /// can be translated into a duplication blob ready for import into a TPM.
        /// Depending on the type of key, the software root key can be a parent for
        /// other root keys that can comprise a migration group.  The caller should
        /// specify necessary key parameters in Public.
        ///
        /// Parameter keyData is used only with symmetric or HMAC keys. If non-null
        /// on entry, it contains the key bytes supplied by the caller, otherwise the
        /// key will be randomly generated. For asymmetric keys keyData must be null.
        ///
        /// Parameter authVal specifies the authorization value associated with the key.
        /// If it is null, then an random value will be used.
        /// </summary>
        /// <param name="pub"></param>
        /// <param name="authVal"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        public static TssObject Create(TpmPublic pub,
                                       AuthValue authVal = null,
                                       byte[] keyData    = null)
        {
            var newKey = new TssObject();

            // Create a new key from the supplied parameters
            IPublicIdUnion publicId;
            var            sensData = CreateSensitiveComposite(pub, ref keyData, out publicId);

            var nameSize = CryptoLib.DigestSize(pub.nameAlg);

            // Create the associated seed value
            byte[] seed = Globs.GetRandomBytes(nameSize);

            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal ?? AuthValue.FromRandom(nameSize),
                                     seed, sensData);

            newKey.Sensitive = sens;
            newKey.Private   = new TpmPrivate(sens.GetTpm2BRepresentation());

            // fill in the public data
            newKey.Public = pub.Copy();

            if (pub.type == TpmAlgId.Keyedhash || pub.type == TpmAlgId.Symcipher)
            {
                byte[] unique = null;
                if (pub.objectAttributes.HasFlag(ObjectAttr.Restricted | ObjectAttr.Decrypt))
                {
                    unique = CryptoLib.Hmac(pub.nameAlg, seed, keyData);
                }
                else
                {
                    unique = CryptoLib.HashData(pub.nameAlg, seed, keyData);
                }
                newKey.Public.unique = pub.type == TpmAlgId.Keyedhash
                                     ? new Tpm2bDigestKeyedhash(unique) as IPublicIdUnion
                                     : new Tpm2bDigestSymcipher(unique);
            }
            else
            {
                newKey.Public.unique = publicId;
            }

            // And return the new key
            return(newKey);
        }
示例#2
0
        /// <summary>
        /// Create an enveloped (encrypted and integrity protected) private area from a provided sensitive.
        /// </summary>
        /// <param name="iv"></param>
        /// <param name="sens"></param>
        /// <param name="nameHash"></param>
        /// <param name="publicName"></param>
        /// <param name="symWrappingAlg"></param>
        /// <param name="symKey"></param>
        /// <param name="parentNameAlg"></param>
        /// <param name="parentSeed"></param>
        /// <param name="f"></param>
        /// <returns></returns>
        public static byte[] CreatePrivateFromSensitive(
            SymDefObject symWrappingAlg,
            byte[] symKey,
            byte[] iv,
            Sensitive sens,
            TpmAlgId nameHash,
            byte[] publicName,
            TpmAlgId parentNameAlg,
            byte[] parentSeed,
            TssObject.Transformer f = null)
        {
            // ReSharper disable once InconsistentNaming
            byte[] tpm2bIv = Marshaller.ToTpm2B(iv);
            Transform(tpm2bIv, f);

            byte[] sensitive = sens.GetTpmRepresentation();
            Transform(sensitive, f);

            // ReSharper disable once InconsistentNaming
            byte[] tpm2bSensitive = Marshaller.ToTpm2B(sensitive);
            Transform(tpm2bSensitive, f);

            byte[] encSensitive = SymCipher.Encrypt(symWrappingAlg, symKey, iv, tpm2bSensitive);
            Transform(encSensitive, f);
            byte[] decSensitive = SymCipher.Decrypt(symWrappingAlg, symKey, iv, encSensitive);
            Debug.Assert(f != null || Globs.ArraysAreEqual(decSensitive, tpm2bSensitive));

            var hmacKeyBits = CryptoLib.DigestSize(parentNameAlg) * 8;

            byte[] hmacKey = KDF.KDFa(parentNameAlg, parentSeed, "INTEGRITY", new byte[0], new byte[0], hmacKeyBits);
            Transform(hmacKey, f);

            byte[] dataToHmac = Marshaller.GetTpmRepresentation(tpm2bIv,
                                                                encSensitive,
                                                                publicName);
            Transform(dataToHmac, f);

            byte[] outerHmac = CryptoLib.Hmac(parentNameAlg, hmacKey, dataToHmac);
            Transform(outerHmac, f);

            byte[] priv = Marshaller.GetTpmRepresentation(Marshaller.ToTpm2B(outerHmac),
                                                          tpm2bIv,
                                                          encSensitive);
            Transform(priv, f);
            return(priv);
        }
示例#3
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);
        }
示例#4
0
        // ReSharper disable once InconsistentNaming
        public static byte[] KDFa(TpmAlgId hmacHash, byte[] hmacKey, string label,
                                  byte[] contextU, byte[] contextV, int 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.Hmac(hmacHash, hmacKey, toHmac);
                Array.Copy(fragment, 0, kdfStream, j * bitsPerLoop / 8, fragment.Length);
            }
            return(Globs.ShiftRight(kdfStream, (int)(bitsPerLoop * numLoops - numBitsRequired)));
        }
示例#5
0
文件: TpmKey.cs 项目: jimsdog/TSS.MSR
        /// <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));
        }
示例#6
0
文件: TpmKey.cs 项目: jimsdog/TSS.MSR
        /// <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));
        }