Inheritance: TpmStructureBase
Exemple #1
0
        /// <summary>
        /// Creates a *software* root 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.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion           publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart        = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key -
            SymDefObject symDef = GetSymDef(keyParameters);

            byte[] symmKey;
            if (symDef.Algorithm != TpmAlgId.Null)
            {
                using (var symmCipher = SymmCipher.Create(symDef))
                {
                    symmKey = symmCipher.KeyData;
                }
            }
            else
            {
                symmKey = new byte[0];
            }
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);

            newKey.sensitivePart = sens;

            // And return the new key
            return(newKey);
        }
Exemple #2
0
        /// <summary>
        /// Creates a Private area for this key so that it can be loaded into a TPM by
        /// TPM2_Load() if the target TPM already has the storage key 'parent' loaded.
        /// This function lets an application to create key hierarchies in software
        /// that can be loaded into a TPM once the parent has been TPM2_Import'ed.
        /// TPM2_Import() supports plaintext import. To get this sort of import blob,
        /// set 'parent' to null.
        /// </summary>
        /// <param name="parent"></param>
        /// <returns></returns>
        public TpmPrivate GetPrivate(TssObject parent)
        {
            SymDefObject symDef = GetSymDef(parent.Public);

            // Figure out how many bits we will need from the KDF
            byte[] parentSymSeed = parent.Sensitive.seedValue;
            Transform(parentSymSeed);
            byte[] iv = (symDef.Mode == TpmAlgId.Ecb) ? new byte[0]
                                : Globs.GetRandomBytes(SymCipher.GetBlockSize(symDef));

            // The encryption key is calculated with a KDF
            byte[] symKey = KDF.KDFa(parent.Public.nameAlg,
                                     parentSymSeed,
                                     "STORAGE",
                                     GetName(),
                                     new byte[0],
                                     symDef.KeyBits);

            Transform(symKey);

            byte[] newPrivate = KeyWrapper.CreatePrivateFromSensitive(
                symDef,
                symKey,
                iv,
                Sensitive,
                Public.nameAlg,
                Public.GetName(),
                parent.Public.nameAlg,
                parent.Sensitive.seedValue,
                TransformerCallback);
            Transform(newPrivate);
            return(new TpmPrivate(newPrivate));
        }
Exemple #3
0
        /// <summary>
        /// Creates a Private area for this key that will be loadable on a TPM though TPM2_Load() if the target TPM already has the parent
        /// storage key "parent" loaded.  This function lets applications create key-hierarchies in software that can be loaded into
        /// a TPM once the parent has been "TPM2_Import'ed."
        /// TPM2_Import() supports plaintext import.  To get this sort of import blob set intendedParent
        /// to null
        /// </summary>
        /// <param name="intendedParent"></param>
        /// <returns></returns>
        public TpmPrivate GetPrivate(TssObject intendedParent)
        {
            SymDefObject symDef = GetSymDef(intendedParent.publicPart);

            // Figure out how many bits we will need from the KDF
            byte[] parentSymValue = intendedParent.sensitivePart.seedValue;
            byte[] iv             = Globs.GetRandomBytes(SymmCipher.GetBlockSize(symDef));

            // The encryption key is calculated with a KDF
            byte[] symKey = KDF.KDFa(intendedParent.publicPart.nameAlg,
                                     parentSymValue,
                                     "STORAGE",
                                     GetName(),
                                     new byte[0],
                                     symDef.KeyBits);

            byte[] newPrivate = KeyWrapper.CreatePrivateFromSensitive(symDef,
                                                                      symKey,
                                                                      iv,
                                                                      sensitivePart,
                                                                      publicPart.nameAlg,
                                                                      publicPart.GetName(),
                                                                      intendedParent.publicPart.nameAlg,
                                                                      intendedParent.sensitivePart.seedValue);

            return(new TpmPrivate(newPrivate));
        }
Exemple #4
0
 private static void Transform(byte[] x, TssObject.Transformer f)
 {
     if (f == null)
     {
         return;
     }
     f(x);
 }
Exemple #5
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);
        }
Exemple #6
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);
        }
Exemple #7
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 = SymmCipher.Encrypt(symWrappingAlg, symKey, iv, tpm2bSensitive);
            Transform(encSensitive, f);
            byte[] decSensitive = SymmCipher.Decrypt(symWrappingAlg, symKey, iv, encSensitive);
            Debug.Assert(f != null || Globs.ArraysAreEqual(decSensitive, tpm2bSensitive));

            uint hmacKeyBits = (uint)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.HmacData(parentNameAlg, hmacKey, dataToHmac);
            Transform(outerHmac, f);

            byte[] priv = Marshaller.GetTpmRepresentation(Marshaller.ToTpm2B(outerHmac),
                                                          tpm2bIv,
                                                          encSensitive);
            Transform(priv, f);
            return priv;
        }
Exemple #8
0
        /// <summary>
        /// Creates a *software* root 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.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion           publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart        = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key
            byte[] symmKey = Globs.GetRandomBytes(CryptoLib.DigestSize(keyParameters.nameAlg));
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);

            newKey.sensitivePart = sens;

            // And return the new key
            return(newKey);
        }
Exemple #9
0
 /// <summary>
 /// Extract and return the SymDefObject that describes the symmetric
 /// algorithm used for key protection in storage keys.
 /// </summary>
 /// <returns></returns>
 public SymDefObject GetSymDef()
 {
     return(TssObject.GetSymDef(Public));
 }
Exemple #10
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));
        }
Exemple #11
0
        /// <summary>
        /// Creates a Private area for this key that will be loadable on a TPM though TPM2_Load() if the target TPM already has the parent
        /// storage key "parent" loaded.  This function lets applications create key-hierarchies in software that can be loaded into
        /// a TPM once the parent has been "TPM2_Import'ed."
        /// TPM2_Import() supports plaintext import.  To get this sort of import blob set intendedParent
        /// to null
        /// </summary>
        /// <param name="intendedParent"></param>
        /// <returns></returns>
        public TpmPrivate GetPrivate(TssObject intendedParent)
        {
            SymDefObject symDef = GetSymDef(intendedParent.publicPart);

            // Figure out how many bits we will need from the KDF
            byte[] parentSymValue = intendedParent.sensitivePart.seedValue;
            Transform(parentSymValue);
            byte[] iv = Globs.GetRandomBytes(SymmCipher.GetBlockSize(symDef));

            // The encryption key is calculated with a KDF
            byte[] symKey = KDF.KDFa(intendedParent.publicPart.nameAlg,
                                     parentSymValue,
                                     "STORAGE",
                                     GetName(),
                                     new byte[0],
                                     symDef.KeyBits);

            Transform(symKey);

            byte[] newPrivate = KeyWrapper.CreatePrivateFromSensitive(symDef,
                                                                      symKey,
                                                                      iv,
                                                                      sensitivePart,
                                                                      publicPart.nameAlg,
                                                                      publicPart.GetName(),
                                                                      intendedParent.publicPart.nameAlg,
                                                                      intendedParent.sensitivePart.seedValue,
                                                                      TransformerCallback);
            Transform(newPrivate);
            return new TpmPrivate(newPrivate);
        }
Exemple #12
0
        /// <summary>
        /// Creates a *software* root 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.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key -
            SymDefObject symDef = GetSymDef(keyParameters);
            byte[] symmKey;
            if (symDef.Algorithm != TpmAlgId.Null)
            {
                using (var symmCipher = SymmCipher.Create(symDef))
                {
                    symmKey = symmCipher.KeyData;
                }
            }
            else
            {
                symmKey = new byte[0];
            }
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);
            newKey.sensitivePart = sens;

            // And return the new key
            return newKey;
        }
Exemple #13
0
 public TssObject(TssObject the_TssObject)
 {
     if((Object) the_TssObject == null ) throw new ArgumentException(Globs.GetResourceString("parmError"));
     publicPart = the_TssObject.publicPart;
     sensitivePart = the_TssObject.sensitivePart;
     privatePart = the_TssObject.privatePart;
 }
Exemple #14
0
        /// <summary>
        /// Creates a *software* root 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.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key 
            byte[] symmKey = Globs.GetRandomBytes(CryptoLib.DigestSize(keyParameters.nameAlg));
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);
            newKey.sensitivePart = sens;

            // And return the new key
            return newKey;
        }