Inheritance: TpmStructureBase
Example #1
0
        GetEccAlg(TpmPublic pub)
        {
            if (pub.unique.GetUnionSelector() != TpmAlgId.Ecc)
            {
                return(null);
            }

            var eccParms = (EccParms)pub.parameters;

            bool signing    = pub.objectAttributes.HasFlag(ObjectAttr.Sign);
            bool encrypting = pub.objectAttributes.HasFlag(ObjectAttr.Decrypt);

            if (!(signing ^ encrypting))
            {
                Globs.Throw <ArgumentException>("ECC Key must either sign or decrypt");
                return(null);
            }
            var scheme = eccParms.scheme.GetUnionSelector();

            if (signing && scheme != TpmAlgId.Ecdsa && scheme != TpmAlgId.Null)
            {
                Globs.Throw <ArgumentException>("Unsupported ECC signing scheme");
                return(null);
            }

            if (!IsCurveSupported(eccParms.curveID))
            {
                Globs.Throw <ArgumentException>("Unsupported ECC curve");
                return(null);
            }
            int curveIndex = (int)eccParms.curveID;

            return(signing ? EcdsaCurveIDs[curveIndex] : EcdhCurveIDs[curveIndex]);
        }
Example #2
0
 public TpmPolicyTicket(TpmPublic authorizingKey, byte[] policyRef, TpmSt ticketType)
     : base("")
 {
     AuthorizingKey = authorizingKey;
     PolicyRef      = Globs.CopyData(policyRef);
     TicketType     = ticketType;
 }
Example #3
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);
        }
Example #4
0
 /// <summary>
 /// This command allows policies to change. If a policy were static,
 /// then it would be difficult to add users to a policy. This command lets a
 /// policy authority sign a new policy so that it may be used in an existing policy.
 /// </summary>
 public TpmPolicyAuthorize(
     byte[] policyToReplace,
     byte[] policyRef,
     TpmPublic signingKey,
     TpmAlgId signingHash,
     ISignatureUnion signature,
     string branchName = "") : base(branchName)
 {
     PolicyToReplace = Globs.CopyData(policyToReplace);
     PolicyRef       = Globs.CopyData(policyRef);
     SigningKey      = signingKey;
     SigningHash     = signingHash;
     // todo - this should really be an ISigntatureUnion but the stock serializer
     // can't serialize interfaces
     //Signature = (SignatureRsassa)signature;
     // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull
     if (signature is SignatureRsapss)
     {
         Sig1 = (SignatureRsapss)signature;
     }
     // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull
     if (signature is SignatureRsassa)
     {
         Sig2 = (SignatureRsassa)signature;
     }
 }
Example #5
0
 public TpmPolicySigned(AsymCryptoSystem authorityKey,
                        bool useNonceTpm, int expirationTime,
                        byte[] cpHash, byte[] policyRef = null,
                        string branchName = "", string nodeId = null)
     : base(useNonceTpm, expirationTime, cpHash, policyRef, branchName, nodeId)
 {
     SwSigningKey   = authorityKey;
     SigningKeyPub  = SwSigningKey.GetPublicParms();
     AuthObjectName = authorityKey.GetPublicParms().GetName();
 }
Example #6
0
        /// <summary>
        /// Instantiates the object using a TPM generated key pair
        /// </summary>
        /// <param name="pub"></param>
        /// <param name="priv"></param>
        public RawRsa(TpmPublic pub, TpmPrivate priv)
        {
            var m        = new Marshaller(priv.buffer);
            var privSize = m.Get <UInt16>();

            // Assert that the private key blob is in plain text
            Debug.Assert(priv.buffer.Length == privSize + 2);
            var sens = m.Get <Sensitive>();

            Init(pub, sens.sensitive as Tpm2bPrivateKeyRsa);
        }
Example #7
0
        /// <summary>
        /// This is called from TpmPolicySigned when an external caller must sign the session data.
        /// </summary>
        /// <returns></returns>
        internal ISignatureUnion ExecuteSignerCallback(TpmPolicySigned ace, byte[] nonceTpm,
                                                       out TpmPublic verificationKey)
        {
            if (SignerCallback == null)
            {
                Globs.Throw("No policy signer callback installed.");
                verificationKey = new TpmPublic();
                return(null);
            }

            return(SignerCallback(this, ace, nonceTpm, out verificationKey));
        }
Example #8
0
        public async Task <Tpm2CreateResponse> CreateAsync(
            TpmHandle parentHandle,
            SensitiveCreate inSensitive,
            TpmPublic inPublic,
            byte[] outsideInfo,
            PcrSelection[] creationPCR)
        {
            var inS  = new Tpm2CreateRequest(parentHandle, inSensitive, inPublic, outsideInfo, creationPCR);
            var resp = new Tpm2CreateResponse();
            await Task.Run(() => DispatchMethod(TpmCc.Create, inS, resp, 1, 0));

            return(resp);
        }
Example #9
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));
        }
Example #10
0
        public async Task <Tpm2CreateResponse> CreateAsync(
            TpmHandle parentHandle,
            SensitiveCreate inSensitive,
            TpmPublic inPublic,
            byte[] outsideInfo,
            PcrSelection[] creationPCR)
        {
            var inS = new Tpm2CreateRequest(parentHandle, inSensitive, inPublic, outsideInfo, creationPCR);
            TpmStructureBase outSBase = null;
            await Task.Run(() => DispatchMethod(TpmCc.Create, inS, typeof(Tpm2CreateResponse), out outSBase, 1, 0));

            var outS = (Tpm2CreateResponse)outSBase;

            return(outS);
        }
Example #11
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);
        }
Example #12
0
        /// <summary>
        /// Create a non-migratable RSA primary with the specified use-auth value and key size.
        /// </summary>
        /// <param name="parentAuth"></param>
        /// <param name="keyLen"></param>
        /// <param name="restricted"></param>
        /// <param name="useAuth"></param>
        /// <param name="parentHandle"></param>
        /// <param name="policy"></param>
        /// <returns></returns>
        public async Task <Tpm2CreateResponse> CreateRsaSigningAsync(
            TpmHandle parentHandle,
            AuthValue parentAuth,
            int keyLen,
            bool restricted,
            AuthValue useAuth,
            TpmHash policy = null)
        {
            ObjectAttr attr = ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicatable
                              ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth;        // Authorize with auth-data

            if (restricted)
            {
                attr |= ObjectAttr.Restricted;
            }

            var thePolicy = new byte[0];

            if ((Object)policy != null)
            {
                thePolicy = policy;
                attr     |= ObjectAttr.AdminWithPolicy;
            }

            var signKeyPubTemplate = new TpmPublic(H.NameHash,
                                                   attr,
                                                   thePolicy,
                                                   new RsaParms(new SymDefObject(),
                                                                // Key type and sig scheme
                                                                H.RsaSigScheme,
                                                                (ushort)keyLen,
                                                                0),
                                                   new Tpm2bPublicKeyRsa());

            // Auth-data for new key
            var sensCreate = new SensitiveCreate(useAuth, new byte[0]);

            // Create the key
            var newKey = await H.Tpm[parentAuth].CreateAsync(parentHandle,
                                                             sensCreate,
                                                             signKeyPubTemplate,
                                                             new byte[0],
                                                             new PcrSelection[0]);

            return(newKey);
        }
Example #13
0
        internal async Task <Tpm2CreatePrimaryResponse> CreatePrimaryRsaAsyncInternal(
            int keyLen,
            byte[] useAuth,
            byte[] policyAuth,
            PcrSelection[] pcrSel)
        {
            ObjectAttr attr = ObjectAttr.Restricted | ObjectAttr.Decrypt
                              | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                              | ObjectAttr.SensitiveDataOrigin;

            var theUseAuth = new byte[0];

            if (useAuth != null)
            {
                theUseAuth = useAuth;
                attr      |= ObjectAttr.UserWithAuth;
            }
            var thePolicyAuth = new byte[0];

            if (policyAuth != null)
            {
                thePolicyAuth = policyAuth;
                attr         |= ObjectAttr.AdminWithPolicy;
            }
            var theSelection = new PcrSelection[0];

            if (pcrSel != null)
            {
                theSelection = pcrSel;
            }

            var sensCreate = new SensitiveCreate(theUseAuth, new byte[0]);
            var parms      = new TpmPublic(H.NameHash,
                                           attr,
                                           thePolicyAuth,
                                           new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                        new NullAsymScheme(),
                                                        (ushort)keyLen,
                                                        0),
                                           new Tpm2bPublicKeyRsa());

            byte[] outsideInfo = Globs.GetRandomBytes(8);
            return(await H.Tpm.CreatePrimaryAsync(TpmRh.Owner, sensCreate,
                                                  parms, outsideInfo, theSelection));
        }
Example #14
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);
        }
Example #15
0
        /// <summary>
        /// Extract and return the SymDefObject that describes the associated symmetric algorithm that is used for key protection
        /// in storage keys.
        /// </summary>
        /// <param name="keyParms"></param>
        /// <returns></returns>
        internal static SymDefObject GetSymDef(TpmPublic keyParms)
        {
            TpmAlgId keyAlgId = keyParms.type;

            switch (keyAlgId)
            {
            case TpmAlgId.Rsa:
                var rsaParms = (RsaParms)keyParms.parameters;
                return(rsaParms.symmetric);

            case TpmAlgId.Ecc:
                var eccParms = (EccParms)keyParms.parameters;
                return(eccParms.symmetric);

            default:
                throw new Exception("Unsupported algorithm");
            }
        }
        /// <summary>
        /// Create a new random software key (public and private) matching the parameters in keyParams.
        /// </summary>
        /// <param name="keyParams"></param>
        /// <returns></returns>
        public AsymCryptoSystem(TpmPublic keyParams)
        {
            TpmAlgId keyAlgId = keyParams.type;

            PublicParms = keyParams.Copy();

            switch (keyAlgId)
            {
            case TpmAlgId.Rsa:
            {
                var rsaParams = keyParams.parameters as RsaParms;
                AsymmetricKeyAlgorithmProvider RsaProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha256);
                Key = RsaProvider.CreateKeyPair(rsaParams.keyBits);
                IBuffer keyBlobBuffer = Key.ExportPublicKey(CryptographicPublicKeyBlobType.BCryptPublicKey);
                byte[]  blob;
                CryptographicBuffer.CopyToByteArray(keyBlobBuffer, out blob);
                var m       = new Marshaller(blob, DataRepresentation.LittleEndian);
                var header  = m.Get <BCryptRsaKeyBlob>();
                var modulus = m.GetArray <byte>((int)header.cbModulus);
                var pubId   = new Tpm2bPublicKeyRsa(modulus);
                PublicParms.unique = pubId;
                break;
            }

            case TpmAlgId.Ecc:
            {
                var eccParms = keyParams.parameters as EccParms;
                var alg      = RawEccKey.GetEccAlg(keyParams);
                if (alg == null)
                {
                    Globs.Throw <ArgumentException>("Unknown ECC curve");
                    return;
                }
                AsymmetricKeyAlgorithmProvider EccProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(alg);
                Key = EccProvider.CreateKeyPair((uint)RawEccKey.GetKeyLength(eccParms.curveID));
                break;
            }

            default:
                Globs.Throw <ArgumentException>("Algorithm not supported");
                break;
            }
        }
Example #17
0
        void Init(TpmPublic pub, Tpm2bPrivateKeyRsa priv)
        {
            var parms = pub.parameters as RsaParms;

            NumBits = parms.keyBits;

            E = new BigInteger(parms.exponent == 0 ? RsaParms.DefaultExponent
                                                   : BitConverter.GetBytes(parms.exponent));
            N = FromBigEndian((pub.unique as Tpm2bPublicKeyRsa).buffer);
            P = FromBigEndian(priv.buffer);
            Q = N / P;
            Debug.Assert(N % P == BigInteger.Zero);

            BigInteger PHI = N - (P + Q - BigInteger.One);

            D        = ModInverse(E, PHI);
            InverseQ = ModInverse(Q, P);
            DP       = D % (P - BigInteger.One);
            DQ       = D % (Q - BigInteger.One);
        }
Example #18
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);
        }
Example #19
0
        public async Task <Tpm2CreatePrimaryResponse> CreatePrimaryAsync(
            TpmHandle primaryHandle,
            SensitiveCreate inSensitive,
            TpmPublic inPublic,
            byte[] outsideInfo,
            PcrSelection[] creationPCR)
        {
            var inS = new Tpm2CreatePrimaryRequest {
                primaryHandle = primaryHandle,
                inSensitive   = inSensitive,
                inPublic      = inPublic,
                outsideInfo   = outsideInfo,
                creationPCR   = creationPCR
            };
            TpmStructureBase outSBase = null;
            await Task.Run(() =>
                           DispatchMethod(TpmCc.CreatePrimary, inS, typeof(Tpm2CreatePrimaryResponse), out outSBase, 1, 1));

            var outS = (Tpm2CreatePrimaryResponse)outSBase;

            return(outS);
        }
            } // class PrivateKeyBlob


            // Trailing parameters are used to populate TpmPublic generated for the key from the blob.
            public static TpmPrivate CspToTpm(byte[] cspPrivateBlob, out TpmPublic tpmPub,
                                              TpmAlgId nameAlg        = TpmAlgId.Sha1,
                                              ObjectAttr keyAttrs     = ObjectAttr.Decrypt | ObjectAttr.UserWithAuth,
                                              IAsymSchemeUnion scheme = null,
                                              SymDefObject symDef     = null)
            {
                if (scheme == null)
                {
                    scheme = new NullAsymScheme();
                }
                if (symDef == null)
                {
                    symDef = new SymDefObject();
                }

                var m          = new Marshaller(cspPrivateBlob, DataRepresentation.LittleEndian);
                var cspPrivate = m.Get <Csp.PrivateKeyBlob>();
                var keyAlg     = cspPrivate.publicKeyStruc.aiKeyAlg;

                if (keyAlg != Csp.AlgId.CAlgRsaKeyX && keyAlg != Csp.AlgId.CAlgRsaSign)
                {
                    Globs.Throw <NotSupportedException>("CSP blobs for keys of type " + keyAlg.ToString("X") + " are not supported");
                    tpmPub = new TpmPublic();
                    return(new TpmPrivate());
                }

                var rsaPriv = new Tpm2bPrivateKeyRsa(Globs.ReverseByteOrder(cspPrivate.prime1));
                var sens    = new Sensitive(new byte[0], new byte[0], rsaPriv);

                tpmPub = new TpmPublic(nameAlg, keyAttrs, new byte[0],
                                       new RsaParms(symDef,
                                                    scheme,
                                                    (ushort)cspPrivate.rsaPubKey.bitlen,
                                                    cspPrivate.rsaPubKey.pubexp),
                                       new Tpm2bPublicKeyRsa(Globs.ReverseByteOrder(cspPrivate.modulus)));

                return(new TpmPrivate(sens.GetTpm2BRepresentation()));
            }
Example #21
0
        /// <summary>
        /// Extract and return the SymDefObject that describes the associated symmetric
        /// algorithm that is used for key protection in storage keys.
        /// </summary>
        /// <param name="keyParms"></param>
        /// <returns></returns>
        internal static SymDefObject GetSymDef(TpmPublic keyParms)
        {
            TpmAlgId keyAlgId = keyParms.type;

            switch (keyAlgId)
            {
            case TpmAlgId.Rsa:
                var rsaParms = (RsaParms)keyParms.parameters;
                return(rsaParms.symmetric);

            case TpmAlgId.Ecc:
                var eccParms = (EccParms)keyParms.parameters;
                return(eccParms.symmetric);

            case TpmAlgId.Symcipher:
                return(keyParms.parameters is SymcipherParms
                                        ? (keyParms.parameters as SymcipherParms).sym
                                        : keyParms.parameters as SymDefObject);

            default:
                Globs.Throw("Unsupported key type");
                return(new SymDefObject());
            }
        }
Example #22
0
 ///<param name = "the_publicPart">Public part of key</param>
 ///<param name = "the_sensitivePart">Sensitive part of key</param>
 ///<param name = "the_privatePart">Private part is the encrypted sensitive part of key</param>
 public TssObject(
 TpmPublic the_publicPart,
 Sensitive the_sensitivePart,
 TpmPrivate the_privatePart
 )
 {
     this.publicPart = the_publicPart;
     this.sensitivePart = the_sensitivePart;
     this.privatePart = the_privatePart;
 }
Example #23
0
 public TssObject()
 {
     publicPart = new TpmPublic();
     sensitivePart = new Sensitive();
     privatePart = new TpmPrivate();
 }
Example #24
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);
        }
Example #25
0
 public TssKey(TssKey the_TssKey)
 {
     if((Object) the_TssKey == null ) throw new ArgumentException(Globs.GetResourceString("parmError"));
     publicPart = the_TssKey.publicPart;
     privatePart = the_TssKey.privatePart;
 }
Example #26
0
 public Tpm2bPublic(Tpm2bPublic the_Tpm2bPublic)
 {
     if((Object) the_Tpm2bPublic == null ) throw new ArgumentException(Globs.GetResourceString("parmError"));
     publicArea = the_Tpm2bPublic.publicArea;
 }
Example #27
0
 public TpmHandle Load(
     TpmHandle parentHandle,
     TpmPrivate inPrivate,
     TpmPublic inPublic
 )
 {
     Tpm2LoadRequest inS = new Tpm2LoadRequest();
     inS.parentHandle = parentHandle;
     inS.inPrivate = inPrivate;
     inS.inPublic = inPublic;
     TpmStructureBase outSBase;
     DispatchMethod(TpmCc.Load, (TpmStructureBase) inS, typeof(Tpm2LoadResponse), out outSBase, 1, 1);
     Tpm2LoadResponse outS = (Tpm2LoadResponse) outSBase;
     return outS.objectHandle;
 }
Example #28
0
        /// <summary>
        /// Some policies can be evaluated solely from public parts of the policy.
        /// Others need a private keyholder to sign some data. Tpm2Lib provides a
        /// callback facility for these cases. In this sample the callback 
        /// signs some data using a software key. But the callback might also 
        /// ask for a smartcard to sign a challenge, etc.
        /// </summary>
        /// <param name="tpm">reference to the TPM2 object to use.</param>
        static void PolicyEvaluationWithCallback(Tpm2 tpm)
        {
            Console.WriteLine("Policy evaluation with callback sample.");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            // 
            var usedCommands = new[] {
                                        TpmCc.PolicySigned,
                                        TpmCc.PolicyGetDigest
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy evaluation callback sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // Template for a software signing key
            // 
            var signKeyPublicTemplate = new TpmPublic(TpmAlgId.Sha256,
                                                      ObjectAttr.Sign | ObjectAttr.Restricted,
                                                      new byte[0],
                                                      new RsaParms(SymDefObject.NullObject(),
                                                                   new SchemeRsassa(TpmAlgId.Sha1),
                                                                   2048, 0),
                                                      new Tpm2bPublicKeyRsa());
            //
            // Create a new random key
            // 
            _publicSigningKey = new AsymCryptoSystem(signKeyPublicTemplate);

            //
            // Create a policy containing a TpmPolicySigned referring to the new 
            // software signing key.
            // 
            _expectedExpirationTime = 60;
            var policy = new PolicyTree(TpmAlgId.Sha256);

            policy.Create(
                new PolicyAce[]
                {
                    new TpmPolicySigned(_publicSigningKey.GetPublicParms().GetName(), 
                                                                            // Newly created PubKey
                                        true,                               // nonceTpm required, expiration time is given
                                        _expectedExpirationTime,            // expirationTime for policy
                                        new byte[0],                        // cpHash
                                        new byte[] {1, 2, 3, 4})            // policyRef
                                        {NodeId = "Signing Key 1"},         // Distinguishing name
                                        new TpmPolicyChainId("leaf")        // Signed data
                });

            //
            // Compute the expected hash for the policy session. This hash would be
            // used in the object associated with the policy to confirm that the 
            // policy is actually fulfilled.
            // 
            TpmHash expectedHash = policy.GetPolicyDigest();

            //
            // The use of the object associated with the policy has to evaluate the
            // policy. In order to process TpmPolicySigned the caller will have to 
            // sign a data structure challenge from the TPM. Here we install a 
            // callback that will sign the challenge from the TPM. 
            // 
            policy.SetSignerCallback(SignerCallback);

            //
            // Evaluate the policy. Tpm2Lib will traverse the policy tree from leaf to 
            // root (in this case just TpmPolicySigned) and will call the signer callback
            // to get a properly-formed challenge signed.
            // 
            AuthSession authSession = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            authSession.RunPolicy(tpm, policy, "leaf");

            //
            // And check that the TPM policy hash is what we expect
            // 
            byte[] actualHash = tpm.PolicyGetDigest(authSession.Handle);

            if (expectedHash != actualHash)
            {
                throw new Exception("Policy evaluation error");
            }

            Console.WriteLine("TpmPolicySignature evaluated.");

            //
            // Clean up
            // 
            tpm.FlushContext(authSession.Handle);
        }
Example #29
0
 public TssObject(TpmPublic thePublicPart, TpmPrivate thePrivatePart)
 {
     Public  = thePublicPart;
     Private = thePrivatePart;
 }
Example #30
0
 public TpmPublic(TpmPublic the_TpmPublic)
 {
     if((Object) the_TpmPublic == null ) throw new ArgumentException(Globs.GetResourceString("parmError"));
     nameAlg = the_TpmPublic.nameAlg;
     objectAttributes = the_TpmPublic.objectAttributes;
     authPolicy = the_TpmPublic.authPolicy;
 }
Example #31
0
        /// <summary>
        /// The callback to sign the TpmPolicySignature challenge from the TPM.
        /// </summary>
        /// <param name="policyTree">The policy tree to check.</param>
        /// <param name="ace">The policy element (TpmPolicySignature) to evaluate.</param>
        /// <param name="nonceTpm">The nonce from the TPM.</param>
        /// <returns>Signature of the nonce.</returns>
        public static ISignatureUnion SignerCallback(PolicyTree policyTree, TpmPolicySigned ace, 
            byte[] nonceTpm, out TpmPublic verificationKey)
        {
            //
            // This function checks the parameters of the associated TpmPolicySigned
            // ACE, and if they are those expected the TPM challenge is signed.
            // Note that policy expressions are often obtained from untrustworthy
            // sources, so it is important for key-holders to check what they 
            // are bing asked to do before signing anything.
            //

            // 
            // The policy just contains the name of the signature verification key, however the
            // TPM needs the actual public key to verify the signature.  Check that the name
            // matches, and if it does return the public key.
            //
            byte[] expectedName = _publicSigningKey.GetPublicParms().GetName();
            if (!expectedName.SequenceEqual(ace.AuthObjectName))
            {
                throw new Exception("Unexpected name in policy.");
            }
            verificationKey = _publicSigningKey.GetPublicParms();
            
            // 
            // Check that the key is the one that we expect
            // 
            if (ace.NodeId != "Signing Key 1")
            {
                throw new Exception("Unrecognized key");
            }


            //
            // Check that nonceTom is not null (otherwise anything we sign can
            // be used for any session).
            // 
            if (nonceTpm.Length == 0)
            {
                throw new Exception("Sign challenges with expiration time need nonce.");
            }

            //
            // Check PolicyRef and cpHash are what we want to sign
            // 
            if (ace.CpHash.Length != 0)
            {
                throw new Exception("I only sign null-cpHash");
            }

            if (!ace.PolicyRef.SequenceEqual(new byte[] { 1, 2, 3, 4 }))
            {
                throw new Exception("Incorrect PolicyRef");
            }

            //
            // And finally check that the expiration is set correctly. Check for
            // positive values (simple signing policy) and negative values (sining 
            // policy with ticket).
            // 
            if (ace.ExpirationTime != _expectedExpirationTime)
            {
                throw new Exception("Unexpected expiration time");
            }

            //
            // Everything is OK, so get a formatted bloc containing the challenge 
            // data and then sign it.
            // 
            byte[] dataStructureToSign = PolicyTree.GetDataStructureToSign(ace.ExpirationTime,
                                                                                 nonceTpm,
                                                                                 ace.CpHash,
                                                                                 ace.PolicyRef);
            ISignatureUnion signature = _publicSigningKey.Sign(dataStructureToSign);
            return signature;
        }
Example #32
0
        /// <summary>
        /// This is called from TpmPolicySigned when an external caller must sign the session data.  
        /// </summary>
        /// <returns></returns>
        internal ISignatureUnion ExecuteSignerCallback(TpmPolicySigned ace, byte[] nonceTpm, out TpmPublic verificationKey)
        {
            if (SignerCallback == null)
            {
                Globs.Throw("No policy signer callback installed.");
                verificationKey = new TpmPublic();
                return null;
            }

            ISignatureUnion signature = SignerCallback(this, ace, nonceTpm, out verificationKey);
            return signature;
        }
Example #33
0
 public async Task<Tpm2CreateResponse> CreateAsync(
     TpmHandle parentHandle,
     SensitiveCreate inSensitive,
     TpmPublic inPublic,
     byte[] outsideInfo,
     PcrSelection[] creationPCR)
 {
     var inS = new Tpm2CreateRequest {
         parentHandle = parentHandle,
         inSensitive = inSensitive,
         inPublic = inPublic,
         outsideInfo = outsideInfo,
         creationPCR = creationPCR
     };
     TpmStructureBase outSBase = null;
     await Task.Run(() => DispatchMethod(TpmCc.Create, inS, typeof (Tpm2CreateResponse), out outSBase, 1, 0));
     var outS = (Tpm2CreateResponse)outSBase;
     return outS;
 }
Example #34
0
 ///<param name = "the_publicArea">the public area NOTE	The + indicates that the caller may specify that use of TPM_ALG_NULL is allowed for nameAlg.</param>
 public Tpm2bPublic(
 TpmPublic the_publicArea
 )
 {
     this.publicArea = the_publicArea;
 }
Example #35
0
 ///<param name = "the_objectHandle">handle of type TPM_HT_TRANSIENT for created Primary Object</param>
 ///<param name = "the_outPublic">the public portion of the created object</param>
 ///<param name = "the_creationData">contains a TPMT_CREATION_DATA</param>
 ///<param name = "the_creationHash">digest of creationData using nameAlg of outPublic</param>
 ///<param name = "the_creationTicket">ticket used by TPM2_CertifyCreation() to validate that the creation data was produced by the TPM</param>
 ///<param name = "the_name">the name of the created object</param>
 public Tpm2CreatePrimaryResponse(
 TpmHandle the_objectHandle,
 TpmPublic the_outPublic,
 CreationData the_creationData,
 byte[] the_creationHash,
 TkCreation the_creationTicket,
 byte[] the_name
 )
 {
     this.objectHandle = the_objectHandle;
     this.outPublic = the_outPublic;
     this.creationData = the_creationData;
     this.creationHash = the_creationHash;
     this.creationTicket = the_creationTicket;
     this.name = the_name;
 }
Example #36
0
        /// <summary>
        /// This sample demonstrates a policy containing ALL policy commands.  
        /// It also demonstrates serialization of the policy, and the use
        /// of callbacks to satisfy the conditions in a policy (e.g. knowledge
        /// of a private key, or the NV-index associated with a name.
        /// </summary>
        /// <param name="tpm">Reference to the TPM used.</param>
        static void SamplePolicySerializationAndCallbacks(Tpm2 tpm)
        {
            Console.WriteLine("Policy sample that serializes all policy commands.");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            // 
            var usedCommands = new[] {
                                       TpmCc.PolicyPhysicalPresence,
                                       TpmCc.PolicySigned,
                                       TpmCc.PolicySecret,
                                       TpmCc.PolicyPCR,
                                       TpmCc.PolicyLocality,
                                       TpmCc.PolicyNV,
                                       TpmCc.PolicyCounterTimer,
                                       TpmCc.PolicyCommandCode,
                                       TpmCc.PolicyPassword,
                                       TpmCc.PolicyAuthorize,
                                       TpmCc.PolicyPhysicalPresence,
                                       TpmCc.PolicyCpHash,
                                       TpmCc.PolicyTicket,
                                       TpmCc.PolicyNameHash,
                                       TpmCc.PolicyCpHash,
                                       TpmCc.PolicyDuplicationSelect,
                                       TpmCc.PolicyAuthValue,
                                       TpmCc.PolicyNvWritten
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy serialization and callback sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // AuthValue encapsulates an authorization value: essentially a byte-array.
            // OwnerAuth is the owner authorization value of the TPM-under-test. We
            // assume that it (and other) auths are set to the default (null) value.
            // If running on a real TPM, which has been provisioned by Windows, this
            // value will be different. An administrator can retrieve the owner
            // authorization value from the registry.
            //
            var ownerAuth = new AuthValue();

            var pInit = new PolicyTree(TpmAlgId.Sha256);
            var p = new PolicyTree(TpmAlgId.Sha256);

            //
            // In the first part of this sample we establish keys, NV-slots, 
            // etc. that will be used in the policy.
            // 

            //
            // create a new RSA software signing key. We will use this for both 
            // TpmPolicySigned AND TpmPolicyAuthorize.
            // 
            var signKeyPublicTemplate = new TpmPublic(TpmAlgId.Sha256,
                                                      ObjectAttr.Sign | ObjectAttr.Restricted | ObjectAttr.FixedTPM,
                                                      new byte[0],
                                                      new RsaParms(new SymDefObject(),
                                                                   new SchemeRsassa(TpmAlgId.Sha256), 
                                                                   2048, 0),
                                                      new Tpm2bPublicKeyRsa());
            _publicSigningKey = new AsymCryptoSystem(signKeyPublicTemplate);

            //
            // Get an authorization ticket for TpmPolicyAuthorize. We will authorize
            // a policy-digest consisting of policyPhysPresense.
            // 
            var tempPolicy = new PolicyTree(TpmAlgId.Sha256);
            tempPolicy.Create(
                new PolicyAce[]
                {
                    new TpmPolicyPhysicalPresence(), 
                    "leaf"
                });

            TpmHash initPolicyHash = tempPolicy.GetPolicyDigest();
            var policyAuthRef = new byte[0];
            byte[] dataToSign = Globs.Concatenate(initPolicyHash.HashData, policyAuthRef);
            byte[] aHash = CryptoLib.HashData(TpmAlgId.Sha256, 
                                              Globs.Concatenate(initPolicyHash.HashData, policyAuthRef));

            //
            // Sign the simple policy just containing PolicyPhysPres so that 
            // we can change it to a new value with PolicyAuthorize.
            // 
            ISignatureUnion policyAuthSig = _publicSigningKey.Sign(dataToSign);

            //
            // Get a ticket verifying the signature.
            // 
            TpmHandle verifierHandle = tpm.LoadExternal(null, _publicSigningKey.GetPublicParms(), TpmHandle.RhOwner);
            tpm.VerifySignature(verifierHandle, aHash, policyAuthSig);
            tpm.FlushContext(verifierHandle);

            //
            // Get the value of PCR[1]
            // 
            var pcrs = new uint[] { 1 };
            var sel = new PcrSelection(TpmAlgId.Sha, pcrs);
            PcrSelection[] selOut;
            Tpm2bDigest[] pcrValues;
            tpm.PcrRead(new[] { sel }, out selOut, out pcrValues);

            //
            // Save the current PCR values in a convenient data structure
            // 
            var expectedPcrVals = new PcrValueCollection(selOut, pcrValues);

            //
            // Set up an NV slot
            // 
            TpmHandle nvHandle = TpmHandle.NV(3001);

            //
            // Clean anything that might have been there before
            // 
            tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);

            AuthValue nvAuth = AuthValue.FromRandom(8);

            tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1,
                                         NvAttr.TpmaNvAuthread | NvAttr.TpmaNvAuthwrite, new byte[0], 32));
            //
            // write some data
            // 
            var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
            tpm[nvAuth].NvWrite(nvHandle, nvHandle, nvData, 0);
            byte[] nvName;
            tpm.NvReadPublic(nvHandle, out nvName);

            //
            // Install evaluation callback
            // Note: generally the callback will check that the parameters are
            // actions that it is willing to authorize. Those checks are omitted here.
            // 
            p.SetNvCallback((PolicyTree policyTree,
                             TpmPolicyNV ace,
                             out SessionBase authorizingSession,
                             out TpmHandle authorizedEntityHandle,
                             out TpmHandle nvHandleIs) =>
            {
                authorizedEntityHandle = nvHandle;
                nvHandleIs = nvHandle;
                authorizingSession = nvAuth;
            });

            //
            // counter-timer:  The policy will check that the reset-count
            // is the current value.
            // 
            int start, end;
            TimeInfo now = tpm.ReadClock();            
            Marshaller.GetFragmentInfo(now, "resetCount", out start, out end);
            byte[] operandB = Marshaller.GetTpmRepresentation(now.clockInfo.resetCount);

            //
            // Get a cpHash for the command we want to execute
            // 
            var cpHash = new TpmHash(TpmAlgId.Sha256);
            tpm._GetCpHash(cpHash).HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);

            p.SetSignerCallback(SignerCallback);

            //
            // PolicySecret tests knowledge of ownerAuth. Note that the callback 
            // will generally check that it is prepared to authorize what it is 
            // being asked to authorize. Those checks are omitted here (we just
            // provide a PWAP session containing ownerAuth.
            // 
            p.SetPolicySecretCallback((PolicyTree policyTree,
                                       TpmPolicySecret ace,
                                       out SessionBase authorizingSession,
                                       out TpmHandle authorizedEntityHandle,
                                       out bool flushAuthEntity) =>
            {
                authorizingSession = ownerAuth;
                authorizedEntityHandle = TpmHandle.RhOwner;
                flushAuthEntity = false;
            });

            //
            // If the policy contains a TpmPolicyAction then print out the 
            // action string on the console.  
            // 
            p.SetPolicyActionCallback((PolicyTree policy, TpmPolicyAction ace)
                                      => Console.WriteLine(ace.Action));

            var policyRef = new byte[] { 1, 2, 3, 4 };

            //
            // Ticket expiration times have to be negative.
            // Positive expiration times do not generate a ticket.
            // 
            _expectedExpirationTime = -60;

            //
            // A normalized policy is an array of policy-chains written as 
            // arrays. Here "most" of the policy-ACEs are in the first chain, but some 
            // ACEs cannot co-exist, and some need a ticket from a prior evaluation.
            // 
            pInit.CreateNormalizedPolicy(
                new[] 
                {
                    new PolicyAce[]
                    {
                        new TpmPolicySigned(_publicSigningKey.GetPublicParms().GetName(),
                                                                                // Newly created PubKey
                                            true,                               // Nonce in signed data
                                            _expectedExpirationTime,            // expirationTime
                                            new byte[0],                        // cpHash
                                            policyRef)                          // policyRef
                        {NodeId = "Signing Key 1"},                             // Distinguishing name

                        //
                        // Include owner-auth
                        // 
                        new TpmPolicySecret(TpmHandle.RhOwner.GetName(), true,
                                            new byte[0], new byte[] {1, 2, 3}, 0),

                        //
                        // Include PCR-values read earlier
                        // 
                        new TpmPolicyPcr(expectedPcrVals), 

                        //
                        // Command must be issued at locality two
                        // 
                        new TpmPolicyLocality(LocalityAttr.TpmLocTwo), 

                        //
                        // NV-data we set earlier must be present
                        // 
                        new TpmPolicyNV(nvName, nvData, 0, Eo.Eq), 

                        //
                        // This is a "dummy ACE" that is not executed on the TPM but
                        // a callback will be invoked at when the policy is executed.
                        // One use case for this is to increment a counter between two
                        // PolicyNV counter-checks.
                        // 
                        new TpmPolicyAction("Output of TpmPolicyAction when executed."),

                        //
                        // Boot-count must be what we read earlier
                        // 
                        new TpmPolicyCounterTimer(operandB, (ushort) start, Eo.Eq),

                        //
                        // Only authorize HierarchyChangeAuth
                        // 
                        new TpmPolicyCommand(TpmCc.HierarchyChangeAuth),

                        //
                        // Include password
                        // 
                        new TpmPolicyPassword(), 

                        //
                        // Authorize a change from PolicyPP (last ACE below)
                        // 
                        new TpmPolicyAuthorize(initPolicyHash.HashData, 
                                               policyAuthRef, 
                                               _publicSigningKey.GetPublicParms(), 
                                               TpmAlgId.Sha256, 
                                               policyAuthSig),
                        //
                        // Demand that the command be executed with PP asserted
                        // 
                        new TpmPolicyPhysicalPresence(), 

                        //
                        // Name for this branch
                        //
                        "branch_1"
                    },

                    new PolicyAce[]
                    {
                        //
                        // Bind to command/parameters
                        //
                        new TpmPolicyCpHash(cpHash),   

                        //
                        // Name for this branch
                        //
                        "branch_2"
                    },

                    new PolicyAce[]
                    {
                        new TpmPolicyTicket(_publicSigningKey.GetPublicParms(),
                                            policyRef,
                                            TpmSt.AuthSigned)
                        //
                        // Distinguishing name for this node
                        //
                        {NodeId = "PolicyTicket"},     

                        //
                        // Name for this branch
                        //
                        "branch_3"
                    },

                    //
                    // TODO: These ACEs are not evaluated yet in this sample
                    //
                    new PolicyAce[]
                    {
                        new TpmPolicyNameHash(),
                        new TpmPolicyCpHash(cpHash),
                        new TpmPolicyDuplicationSelect(new byte[0], new byte[0], true), 
                        new TpmPolicyAuthValue(), // Include entity authValue in HMAC
                        new TpmPolicyNvWritten(),
                        "branch_4"
                    }
                }
            );

            TpmHash policyHash = pInit.GetPolicyDigest();

            //
            // Check that we can serialize and deserialize the policy
            // 
            const string fileName = @".\test1.xml";
            pInit.SerializeToFile("Sample Policy",PolicySerializationFormat.Xml, fileName);
            p.DeserializeFromFile(PolicySerializationFormat.Xml, fileName);
            
            //
            // And check that the policy hash is the same
            // 
            TpmHash deserializedHash = p.GetPolicyDigest();
            if (policyHash != deserializedHash)
            {
                throw new Exception("Serialization error");
            }

            //
            // Execute the policy on the TPM. Start with "branch_1".
            // 
            AuthSession s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_1");

            //
            // Check that the executed policy has the correct digest
            // 
            byte[] actualPolicyDigest = tpm.PolicyGetDigest(s0.Handle);
            if (policyHash != actualPolicyDigest)
            {
                throw new Exception("Policy Evaluation error");
            }

            //
            // Set a command to use the policy
            // 
            tpm[ownerAuth].SetPrimaryPolicy(TpmHandle.RhOwner, policyHash.HashData, TpmAlgId.Sha256);

            //
            // And then execute the command
            // 
            tpm._AssertPhysicalPresence(true);
            tpm._SetLocality(LocalityAttr.TpmLocTwo);
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm._SetLocality(LocalityAttr.TpmLocZero);
            tpm._AssertPhysicalPresence(false);
            tpm.FlushContext(s0.Handle);

            //
            // Next, "branch_2".
            // 
            s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_2");
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm.FlushContext(s0.Handle);

            //
            // Now "branch_3" - ticket. Copy parms out of the ticket/ACE returned
            // from TpmPolicySinged above.
            // 
            var sigAce = p.GetAce<TpmPolicySigned>("Signing Key 1");
            TkAuth signedTicket = p.GetTicket("Signing Key 1");

            var tickAce = p.GetAce<TpmPolicyTicket>("PolicyTicket");
            tickAce.CpHash = sigAce.CpHash;
            tickAce.PolicyRef = sigAce.PolicyRef;
            tickAce.ExpirationTime = sigAce.GetTimeout();
            tickAce.SetTicket(signedTicket);

            s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_3");
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm.FlushContext(s0.Handle);

            Console.WriteLine("Finished SamplePolicySerializationAndCallbacks.");
        }
        /// <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);
        }
Example #38
0
 public TpmHandle CreatePrimary(
     TpmHandle primaryHandle,
     SensitiveCreate inSensitive,
     TpmPublic inPublic,
     byte[] outsideInfo,
     PcrSelection[] creationPCR,
     [SuppressMessage("Microsoft.Design", "CA1021")]
     out TpmPublic outPublic,
     [SuppressMessage("Microsoft.Design", "CA1021")]
     out CreationData creationData,
     [SuppressMessage("Microsoft.Design", "CA1021")]
     out byte[] creationHash,
     [SuppressMessage("Microsoft.Design", "CA1021")]
     out TkCreation creationTicket
 )
 {
     Tpm2CreatePrimaryRequest inS = new Tpm2CreatePrimaryRequest();
     inS.primaryHandle = primaryHandle;
     inS.inSensitive = inSensitive;
     inS.inPublic = inPublic;
     inS.outsideInfo = outsideInfo;
     inS.creationPCR = creationPCR;
     TpmStructureBase outSBase;
     DispatchMethod(TpmCc.CreatePrimary, (TpmStructureBase) inS, typeof(Tpm2CreatePrimaryResponse), out outSBase, 1, 1);
     Tpm2CreatePrimaryResponse outS = (Tpm2CreatePrimaryResponse) outSBase;
     outPublic = outS.outPublic;
     creationData = outS.creationData;
     creationHash = outS.creationHash;
     creationTicket = outS.creationTicket;
     return outS.objectHandle;
 }
Example #39
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);
        }
Example #40
0
 public TpmPrivate Import(
     TpmHandle parentHandle,
     byte[] encryptionKey,
     TpmPublic objectPublic,
     TpmPrivate duplicate,
     byte[] inSymSeed,
     SymDefObject symmetricAlg
 )
 {
     Tpm2ImportRequest inS = new Tpm2ImportRequest();
     inS.parentHandle = parentHandle;
     inS.encryptionKey = encryptionKey;
     inS.objectPublic = objectPublic;
     inS.duplicate = duplicate;
     inS.inSymSeed = inSymSeed;
     inS.symmetricAlg = symmetricAlg;
     TpmStructureBase outSBase;
     DispatchMethod(TpmCc.Import, (TpmStructureBase) inS, typeof(Tpm2ImportResponse), out outSBase, 1, 0);
     Tpm2ImportResponse outS = (Tpm2ImportResponse) outSBase;
     return outS.outPrivate;
 }
Example #41
0
 public TpmHandle LoadExternal(
     Sensitive inPrivate,
     TpmPublic inPublic,
     TpmHandle hierarchy
 )
 {
     Tpm2LoadExternalRequest inS = new Tpm2LoadExternalRequest();
     inS.inPrivate = inPrivate;
     inS.inPublic = inPublic;
     inS.hierarchy = hierarchy;
     TpmStructureBase outSBase;
     DispatchMethod(TpmCc.LoadExternal, (TpmStructureBase) inS, typeof(Tpm2LoadExternalResponse), out outSBase, 0, 1);
     Tpm2LoadExternalResponse outS = (Tpm2LoadExternalResponse) outSBase;
     return outS.objectHandle;
 }
Example #42
0
        /// <summary>
        /// Create an RSA primary storage key in the storage hierarchy and return the key-handle 
        /// to the caller.  The key will be RSA2048 with a SHA256-name algorithm.  The caller can 
        /// provide user-auth. The caller is responsible for disposing of this key.
        /// </summary>
        /// <returns></returns>
        static TpmHandle CreateRsaPrimaryStorageKey(Tpm2 tpm, byte[] auth, out TpmPublic newKeyPub)
        {
            //
            // Creation parameters (no external data for TPM-created objects)
            // 
            var sensCreate = new SensitiveCreate(auth,         // Auth-data provided by the caller
                                                 new byte[0]); // No external data (the TPM will create the new key).

            var parms = new TpmPublic(TpmAlgId.Sha256, 
                                      ObjectAttr.Restricted   | ObjectAttr.Decrypt  |  // Storage key
                                      ObjectAttr.FixedParent  | ObjectAttr.FixedTPM |  // Non-duplicable
                                      ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                      new byte[0], // No policy, and Storage key should be RSA + AES128
                                      new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                   new NullAsymScheme(), 2048, 0),
                                      new Tpm2bPublicKeyRsa());

            //
            // The following are returned by the TPM in CreatePrimary (and Create)
            // they are not used in this sample.
            // 
            CreationData creationData;
            TkCreation creationTicket;
            byte[] creationHash;

            TpmHandle primHandle = tpm[_ownerAuth].CreatePrimary(TpmHandle.RhOwner,    // In storage hierarchy
                                                                 sensCreate,           // UserAuth
                                                                 parms,                // Creation parms set above
                                                                 //
                                                                 // The following parameters influence the creation of the 
                                                                 // creation-ticket. They are not used in this sample
                                                                 //
                                                                 new byte[0],          // Null outsideInfo
                                                                 new PcrSelection[0],  // Do not record PCR-state
                                                                 out newKeyPub,        // Our outs
                                                                 out creationData, out creationHash, out creationTicket);
            return primHandle;
        }
Example #43
0
 ///<param name = "the_publicPart">Public part of key</param>
 ///<param name = "the_privatePart">Private part is the encrypted sensitive part of key</param>
 public TssKey(
 TpmPublic the_publicPart,
 byte[] the_privatePart
 )
 {
     this.publicPart = the_publicPart;
     this.privatePart = the_privatePart;
 }
Example #44
0
        /// <summary>
        /// This sample illustrates the creation and use of an RSA signing key to 
        /// "quote" PCR state
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static void QuotePcrs(Tpm2 tpm)
        {
            //
            // First use a library routine to create an RSA/AES primary storage key
            // with null user-auth.
            // 
            TpmPublic rsaPrimaryPublic;
            var primaryAuth = new byte[0];
            TpmHandle primHandle = CreateRsaPrimaryStorageKey(tpm, primaryAuth, out rsaPrimaryPublic);

            //
            // Template for a signing key.  We will make the key restricted so that we 
            // can quote with it too.
            // 
            var signKeyPubTemplate = new TpmPublic(TpmAlgId.Sha1,
                                                   ObjectAttr.Sign | ObjectAttr.Restricted |      // A "quoting" key
                                                   ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable
                                                   ObjectAttr.UserWithAuth |                      // Authorize with auth-data
                                                   ObjectAttr.SensitiveDataOrigin,                // TPM will create a new key
                                                   new byte[0],
                                                   new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                                   new Tpm2bPublicKeyRsa());
            //
            // Auth-data for new key
            // 
            var userAuth = new byte[] { 1, 2, 3, 4 };
            var sensCreate = new SensitiveCreate(userAuth, new byte[0]);

            //
            // Creation data (not used in this sample)
            // 
            CreationData childCreationData;
            TkCreation creationTicket;
            byte[] creationHash;

            //
            // Create the key
            // 
            TpmPublic keyPub;
            TpmPrivate keyPriv = tpm[primaryAuth].Create(primHandle,          // Child of primary key created above
                                                         sensCreate,          // Auth-data
                                                         signKeyPubTemplate,  // Template created above
                                                         new byte[0],         // Other parms are not used here
                                                         new PcrSelection[0],
                                                         out keyPub,
                                                         out childCreationData, out creationHash, out creationTicket);

            Console.WriteLine("New public key\n" + keyPub.ToString());

            //
            // Load the key as a child of the primary that it 
            // was created under.
            // 
            TpmHandle signHandle = tpm[primaryAuth].Load(primHandle, keyPriv, keyPub);

            //
            // Note that Load returns the "name" of the key and this is automatically
            // associated with the handle.
            // 
            Console.WriteLine("Name of key:" + BitConverter.ToString(signHandle.Name));

            //
            // Aome data to quote
            // 
            TpmHash hashToSign = TpmHash.FromData(TpmAlgId.Sha1, new byte[] { 4, 3, 2, 1 });

            //
            // PCRs to quote.  SHA-1 bank, PCR-indices 1, 2, and 3
            // 
            var pcrsToQuote = new PcrSelection[] 
            {
                new PcrSelection(TpmAlgId.Sha, new uint[] { 1, 2, 3 })
            };

            //
            // Ask the TPM to quote the PCR (and the nonce).  The TPM
            // returns the quote-signature and the data that was signed
            // 
            ISignatureUnion quoteSig;
            Attest quotedInfo = tpm[userAuth].Quote(signHandle,
                                                    hashToSign.HashData,
                                                    new SchemeRsassa(TpmAlgId.Sha1),
                                                    pcrsToQuote,
                                                    out quoteSig);
            //
            // Print out what was quoted
            // 
            var info = (QuoteInfo)quotedInfo.attested;
            Console.WriteLine("PCRs that were quoted: "    +
                              info.pcrSelect[0].ToString() +
                              "\nHash of PCR-array: "      +
                              BitConverter.ToString(info.pcrDigest));

            //
            // Read the PCR to check the quoted value
            // 
            PcrSelection[] outSelection;
            Tpm2bDigest[] outValues;
            tpm.PcrRead(new PcrSelection[] {
                            new PcrSelection(TpmAlgId.Sha, new uint[] { 1, 2, 3 }) 
                        },
                        out outSelection,
                        out outValues);

            //
            // Use the Tpm2Lib library to validate the quote against the
            // values just read.
            // 
            bool quoteOk = keyPub.VerifyQuote(TpmAlgId.Sha1,
                                              outSelection,
                                              outValues,
                                              hashToSign.HashData,
                                              quotedInfo,
                                              quoteSig);
            if (!quoteOk)
            {
                throw new Exception("Quote did not validate");
            }

            Console.WriteLine("Quote correctly validated.");

            //
            // Test other uses of the signing key.  A restricted key can only
            // sign data that the TPM knows does not start with a magic
            // number (that identifies TPM internal data).  So this does not 
            // work
            //
            var nullProof = new TkHashcheck(TpmHandle.RhNull, new byte[0]);
            tpm[userAuth]._ExpectError(TpmRc.Ticket).Sign(signHandle,
                                                          hashToSign.HashData,
                                                          new SchemeRsassa(TpmAlgId.Sha1),
                                                          nullProof);
            //
            // But if we ask the TPM to hash the same data and then sign it 
            // then the TPM can be sure that the data is safe, so it will 
            // sign it.
            // 
            TkHashcheck safeHashTicket;
            TpmHandle hashHandle = tpm.HashSequenceStart(_nullAuth, TpmAlgId.Sha1);

            //
            // The ticket is only generated if the data is "safe."
            // 
            tpm[_nullAuth].SequenceComplete(hashHandle,
                                            new byte[] { 4, 3, 2, 1 },
                                            TpmHandle.RhOwner,
                                            out safeHashTicket);
            //
            // This will now work because the ticket proves to the 
            // TPM that the data that it is about to sign does not 
            // start with TPM_GENERATED
            // 
            ISignatureUnion sig = tpm[userAuth].Sign(signHandle,
                                                     hashToSign.HashData,
                                                     new SchemeRsassa(TpmAlgId.Sha1),
                                                     safeHashTicket);
            //
            // And we can verify the signature
            // 
            bool sigOk = keyPub.VerifySignatureOverData(new byte[] { 4, 3, 2, 1 }, sig);
            if (!sigOk)
            {
                throw new Exception("Signature did not verify");
            }

            Console.WriteLine("Signature verified.");

            //
            // Clean up
            // 
            tpm.FlushContext(primHandle);
            tpm.FlushContext(signHandle);
        }
Example #45
0
        /// <summary>
        /// Create a new random software key (public and private) matching the parameters in keyParams.
        /// </summary>
        /// <param name="keyParams"></param>
        /// <returns></returns>
        public AsymCryptoSystem(TpmPublic keyParams)
        {
            TpmAlgId keyAlgId = keyParams.type;

            PublicParms = keyParams.Copy();

            switch (keyAlgId)
            {
            case TpmAlgId.Rsa:
            {
                var rsaParams = keyParams.parameters as RsaParms;
#if TSS_USE_BCRYPT
                Key = Generate(Native.BCRYPT_RSA_ALGORITHM, rsaParams.keyBits);
                if (Key == UIntPtr.Zero)
                {
                    Globs.Throw("Failed to generate RSA key");
                    return;
                }
                byte[] blob   = Export(Native.BCRYPT_RSAPUBLIC_BLOB);
                var    m      = new Marshaller(blob, DataRepresentation.LittleEndian);
                var    header = m.Get <BCryptRsaKeyBlob>();
                /*var exponent = */ m.GetArray <byte>((int)header.cbPublicExp);
                var modulus = m.GetArray <byte>((int)header.cbModulus);
#else
                RsaProvider = new RSACryptoServiceProvider(rsaParams.keyBits);
                var modulus = RsaProvider.ExportParameters(true).Modulus;
#endif
                var pubId = new Tpm2bPublicKeyRsa(modulus);
                PublicParms.unique = pubId;
                break;
            }

#if !__MonoCS__
            case TpmAlgId.Ecc:
            {
                var eccParms = keyParams.parameters as EccParms;
                var alg      = RawEccKey.GetEccAlg(keyParams);
                if (alg == null)
                {
                    Globs.Throw <ArgumentException>("Unknown ECC curve");
                    return;
                }
#if TSS_USE_BCRYPT
                Key = Generate(alg, (uint)RawEccKey.GetKeyLength(eccParms.curveID));
#else
                var keyParmsX = new CngKeyCreationParameters {
                    ExportPolicy = CngExportPolicies.AllowPlaintextExport
                };
                using (CngKey key = CngKey.Create(alg, null, keyParmsX))
                {
                    byte[] keyIs = key.Export(CngKeyBlobFormat.EccPublicBlob);
                    CngKey.Import(keyIs, CngKeyBlobFormat.EccPublicBlob);

                    if (keyParams.objectAttributes.HasFlag(ObjectAttr.Sign))
                    {
                        EcdsaProvider = new ECDsaCng(key);
                    }
                    else
                    {
                        EcDhProvider = new ECDiffieHellmanCng(key);
                    }
                }
#endif // !TSS_USE_BCRYPT && !__MonoCS__
                break;
            }
#endif // !__MonoCS__
            default:
                Globs.Throw <ArgumentException>("Algorithm not supported");
                break;
            }
        }
Example #46
0
        /// <summary>
        /// This sample demonstrates the creation and use of a storage root key that 
        /// behaves like the Storage Root Key (SRK) defined in TPM1.2.
        /// To do this we need to create a new primary, and then use EvictControl
        /// to make it NV-resident.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        static void StorageRootKey(Tpm2 tpm)
        {
            //
            // This template asks the TPM to create an 2048 bit RSA storage key 
            // with an associated AES key for symmetric data protection.  The term 
            // "SRKs" is not used in TPM2.0, but we use it here to 
            // not 
            // 
            var srkTemplate = new TpmPublic(TpmAlgId.Sha1,                      // Name algorithm
                                            ObjectAttr.Restricted   |           // Storage keys must be restricted
                                            ObjectAttr.Decrypt      |           // Storage keys are Decrypt keys
                                            ObjectAttr.FixedParent  | ObjectAttr.FixedTPM | // Non-duplicable (like 1.2)
                                            ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                            new byte[0],                        // No policy
                                            new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                         new NullAsymScheme(),  // No signature
                                                         2048, 0),              // 2048-bit RSA
                                            new Tpm2bPublicKeyRsa());
            //
            // Authorization for the key we are about to create
            // 
            var srkAuth = new byte[0];

            AuthValue childAuthVal = AuthValue.FromRandom(8);
            TssObject swKey = TssObject.CreateStorageParent(srkTemplate, childAuthVal);

            TpmPublic srkPublic;
            CreationData srkCreationData;
            TkCreation srkCreationTicket;
            byte[] srkCreationHash;

            //
            // Ask the TPM to create a new primary RSA/AES primary storage key
            // 
            TpmHandle keyHandle = tpm[_ownerAuth].CreatePrimary(
                TpmHandle.RhOwner,                          // In the owner-hierarchy
                new SensitiveCreate(srkAuth, new byte[0]),  // With this auth-value
                srkTemplate,                                // Describes key
                new byte[0],                                // For creation ticket
                new PcrSelection[0],                        // For creation ticket
                out srkPublic,                              // Out pubKey and attrs
                out srkCreationData,                        // Not used here
                out srkCreationHash,                        //      Ibid
                out srkCreationTicket);                     //      Ibid
                                                                
            //
            // print out text-versions of the public key just created
            // 
            Console.WriteLine("New SRK public key\n" + srkPublic.ToString());

            //
            // The caller provides the handle for persistent keys
            // 
            TpmHandle srkHandle = TpmHandle.Persistent(0x5000);

            //
            // Ae will make the "SRK" persistent in an NV-slot, so clean up anything
            // that is already there
            // 
            tpm[_ownerAuth]._AllowErrors().EvictControl(TpmHandle.RhOwner, srkHandle, srkHandle);
            TpmRc lastError = tpm._GetLastResponseCode();

            //
            // Make the SRK NV-resident
            // 
            tpm[_ownerAuth].EvictControl(TpmHandle.RhOwner, keyHandle, srkHandle);

            Console.WriteLine("SRK is persistent now.");
        }
Example #47
0
 public TssKey()
 {
     publicPart = new TpmPublic();
     privatePart = new byte[0];
 }
Example #48
0
        /// <summary>
        /// This sample demonstrates the async interface to the TPM for selected slow operations.
        /// await-async is preferred when calling slow TPM functions on a UI-thread.  Only a few TPM
        /// functions have an async-form.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        /// <param name="Event">Synchronization object to signal calling function when we're done.</param>
        static async void PrimarySigningKeyAsync(Tpm2 tpm, AutoResetEvent Event)
        {
            //
            // The TPM needs a template that describes the parameters of the key
            // or other object to be created.  The template below instructs the TPM 
            // to create a new 2048-bit non-migratable signing key.
            // 
            var keyTemplate = new TpmPublic(TpmAlgId.Sha1,                                  // Name algorithm
                                            ObjectAttr.UserWithAuth | ObjectAttr.Sign     | // Signing key
                                            ObjectAttr.FixedParent  | ObjectAttr.FixedTPM | // Non-migratable 
                                            ObjectAttr.SensitiveDataOrigin,
                                            new byte[0],                                    // No policy
                                            new RsaParms(new SymDefObject(), 
                                                         new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                            new Tpm2bPublicKeyRsa());
            //
            // Authorization for the key we are about to create
            // 
            var keyAuth = new byte[] { 1, 2, 3 };

            //
            // Ask the TPM to create a new primary RSA signing key
            // 
            var newPrimary = await tpm[_ownerAuth].CreatePrimaryAsync(
                TpmHandle.RhOwner,                          // In the owner-hierarchy
                new SensitiveCreate(keyAuth, new byte[0]),  // With this auth-value
                keyTemplate,                                // Describes key
                new byte[0],                                // For creation ticket
                new PcrSelection[0]);                       // For creation ticket

            //
            // Print out text-versions of the public key just created
            // 
            Console.WriteLine("New public key\n" + newPrimary.outPublic.ToString());

            //
            // Use the key to sign some data
            // 
            byte[] message = Encoding.Unicode.GetBytes("ABC");
            TpmHash dataToSign = TpmHash.FromData(TpmAlgId.Sha1, message);
            var sig = await tpm[keyAuth].SignAsync(newPrimary.objectHandle,            // Handle of signing key
                                                   dataToSign.HashData,                // Data to sign
                                                   new SchemeRsassa(TpmAlgId.Sha1),    // Default scheme
                                                   TpmHashCheck.NullHashCheck());
            //
            // Print the signature. A different structure is returned for each 
            // signing scheme, so cast the interface to our signature type.
            // 
            var actualSig = (SignatureRsassa)sig;
            Console.WriteLine("Signature: " + BitConverter.ToString(actualSig.sig));

            //
            // Clean up
            // 
            tpm.FlushContext(newPrimary.objectHandle);

            //
            // Tell caller, we're done.
            // 
            Event.Set();
        }
Example #49
0
 public TssObject(TpmPublic thePublicPart, TpmPrivate thePrivatePart)
 {
     publicPart  = thePublicPart;
     privatePart = thePrivatePart;
 }
Example #50
0
 public TssObject(TpmPublic thePublicPart, TpmPrivate thePrivatePart)
 {
     publicPart = thePublicPart;
     privatePart = thePrivatePart;
 }
Example #51
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));
        }
Example #52
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;
        }
Example #53
0
 public Tpm2CreatePrimaryResponse()
 {
     objectHandle = new TpmHandle();
     outPublic = new TpmPublic();
     creationData = new CreationData();
     creationHash = new byte[0];
     creationTicket = new TkCreation();
     name = new byte[0];
 }
Example #54
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());
                Transform(encSensitive);
            }
            else
            {
                byte[] sens = Marshaller.ToTpm2B(sensitivePart.GetTpmRepresentation());
                byte[] toHash = Globs.Concatenate(sens, GetName());
                Transform(toHash);
                byte[] innerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData(publicPart.nameAlg, toHash));
                byte[] innerData = Globs.Concatenate(innerIntegrity, sens);
                Transform(innerData);
                encSensitive = innerWrapper.CFBEncrypt(innerData);
                Transform(encSensitive);
            }

            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:
                        throw new NotImplementedException("activate crypto scheme not implemented");
                }
            }
            Transform(seed);
            Transform(encSecret);

            encryptedWrappingKey = encSecret;

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

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

            int npNameNumBits = CryptoLib.DigestSize(newParent.nameAlg) * 8;
            byte[] hmacKey = KDF.KDFa(newParent.nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], (uint)npNameNumBits);

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

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

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

            return new TpmPrivate(dupBlob);
        }
Example #55
0
        /// <summary>
        /// This is called from TpmPolicySigned when an external caller must sign the session data.
        /// </summary>
        /// <returns></returns>
        internal ISignatureUnion ExecuteSignerCallback(TpmPolicySigned ace, byte[] nonceTpm, out TpmPublic verificationKey)
        {
            if (SignerCallback == null)
            {
                throw new Exception("No policy signer callback installed.");
            }

            ISignatureUnion signature = SignerCallback(this, ace, nonceTpm, out verificationKey);

            return(signature);
        }
Example #56
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)
            {
                throw new Exception("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;
        }
Example #57
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));
        }
Example #58
0
        /// <summary>
        /// Extract and return the SymDefObject that describes the associated symmetric algorithm that is used for key protection
        /// in storage keys.
        /// </summary>
        /// <param name="keyParms"></param>
        /// <returns></returns>
        internal static SymDefObject GetSymDef(TpmPublic keyParms)
        {
            TpmAlgId keyAlgId = keyParms.type;
            switch (keyAlgId)
            {
                case TpmAlgId.Rsa:
                    var rsaParms = (RsaParms)keyParms.parameters;
                    return rsaParms.symmetric;
                case TpmAlgId.Ecc:
                    var eccParms = (EccParms)keyParms.parameters;
                    return eccParms.symmetric;
                default:
                    throw new Exception("Unsupported algorithm");

            }
        }
Example #59
0
        /// <summary>
        /// Create a sealed-object primary that can be accessed with the given policy. SHA256 is assumed.
        /// </summary>
        /// <param name="tpm"></param>
        /// <param name="dataToSeal"></param>
        /// <param name="authValue"></param>
        /// <param name="policy"></param>
        /// <returns></returns>
        private static TpmHandle CreateSealedPrimaryObject(Tpm2 tpm, byte[] dataToSeal, byte[] authValue, byte[] policy)
        {
            ObjectAttr attrs = ObjectAttr.FixedTPM | ObjectAttr.FixedParent;

            if (authValue != null)
            {
                attrs |= ObjectAttr.UserWithAuth;
            }

            byte[] policyVal = policy ?? new byte[0];
            var sealedInPublic = new TpmPublic(TpmAlgId.Sha256,
                                               attrs,
                                               policyVal,
                                               new KeyedhashParms(new NullSchemeKeyedhash()),
                                               new Tpm2bDigestKeyedhash());

            //
            // Envelope for sealed data and auth
            // 
            byte[] authVal = authValue ?? new byte[0];
            var sealedInSensitive = new SensitiveCreate(authVal, dataToSeal);

            TkCreation creationTicket;
            byte[] creationHashSealed;
            TpmPublic sealedPublic;
            CreationData sealedCreationData;

            //
            // AuthValue encapsulates an authorization value: essentially a byte-array.
            // OwnerAuth is the owner authorization value of the TPM-under-test.  We
            // assume that it (and other) auths are set to the default (null) value.
            // If running on a real TPM, which has been provisioned by Windows, this
            // value will be different. An administrator can retrieve the owner
            // authorization value from the registry.
            //
            var ownerAuth = new AuthValue();

            //
            // Ask the TPM to create a primary containing the "sealed" data
            // 
            TpmHandle primHandle = tpm[ownerAuth].CreatePrimary(TpmHandle.RhOwner,
                                                                sealedInSensitive,
                                                                sealedInPublic,
                                                                new byte[0],
                                                                new PcrSelection[0],
                                                                out sealedPublic,
                                                                out sealedCreationData,
                                                                out creationHashSealed,
                                                                out creationTicket);
            return primHandle;
        }
Example #60
0
 public Tpm2bPublic()
 {
     publicArea = new TpmPublic();
 }