コード例 #1
0
        internal static TpmHandle CreateEncryptionDecryptionKey(Tpm2 tpm, TpmHandle parent)
        {
            var sensCreate = new SensitiveCreate(null, null);

            var sym = new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb);

            var pub = new TpmPublic(TpmAlgId.Sha256,
                                    ObjectAttr.Decrypt | ObjectAttr.UserWithAuth,
                                    null,
                                    sym,
                                    new Tpm2bDigestSymcipher());

            TssObject swKey = TssObject.Create(pub);


            var innerWrapKey = sym == null ? null : SymCipher.Create(sym);



            byte[]    name, qname;
            TpmPublic pubParent = tpm.ReadPublic(parent, out name, out qname);

            byte[]     encSecret;
            TpmPrivate dupBlob = swKey.GetDuplicationBlob(pubParent, innerWrapKey, out encSecret);

            TpmPrivate privImp = tpm.Import(parent, innerWrapKey, swKey.Public, dupBlob,
                                            encSecret, sym ?? new SymDefObject());

            TpmHandle hKey = tpm.Load(parent, privImp, swKey.Public)
                             .SetAuth(swKey.Sensitive.authValue);

            return(hKey);
        }
コード例 #2
0
        /// <summary>
        /// De-envelope inner-wrapped duplication blob.
        /// TODO: Move this to TpmPublic and make it fully general
        /// </summary>
        /// <param name="exportedPrivate"></param>
        /// <param name="encAlg"></param>
        /// <param name="encKey"></param>
        /// <param name="nameAlg"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Sensitive SensitiveFromDuplicateBlob(TpmPrivate exportedPrivate, SymDefObject encAlg, byte[] encKey, TpmAlgId nameAlg, byte[] name)
        {
            byte[] dupBlob = exportedPrivate.buffer;
            byte[] sensNoLen;
            using (SymmCipher c = Create(encAlg, encKey))
            {
                byte[] innerObject = c.Decrypt(dupBlob);
                byte[] innerIntegrity, sensitive;

                KDF.Split(innerObject,
                          16 + CryptoLib.DigestSize(nameAlg) * 8,
                          out innerIntegrity,
                          8 * (innerObject.Length - CryptoLib.DigestSize(nameAlg) - 2),
                          out sensitive);

                byte[] expectedInnerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData(nameAlg, sensitive, name));

                if (!Globs.ArraysAreEqual(expectedInnerIntegrity, innerIntegrity))
                {
                    Globs.Throw("SensitiveFromDuplicateBlob: Bad inner integrity");
                }

                sensNoLen = Marshaller.Tpm2BToBuffer(sensitive);
            }
            var sens = Marshaller.FromTpmRepresentation <Sensitive>(sensNoLen);

            return(sens);
        }
コード例 #3
0
ファイル: Sample-KeyImport.cs プロジェクト: rgl/TSS.MSR
        } // SimpleDuplicateImportRsaSample

        TssObject ImportExternalRsaKey(Tpm2 tpm, TpmHandle hParent,
                                       int keySizeInBits, IAsymSchemeUnion scheme,
                                       byte[] publicPart, byte[] privatePart,
                                       ObjectAttr keyAttrs,
                                       byte[] authVal = null, byte[] policyDigest = null)
        {
            TpmAlgId sigHashAlg = TpmHelper.GetSchemeHash(scheme),
                     nameAlg    = sigHashAlg;

            // TPM signing key template with the actual public key bits
            var inPub = new TpmPublic(nameAlg,
                                      keyAttrs,
                                      policyDigest,
                                      new RsaParms(new SymDefObject(), scheme as IAsymSchemeUnion,
                                                   (ushort)keySizeInBits, 0),
                                      new Tpm2bPublicKeyRsa(publicPart));

            // Wrap the key in a TSS helper class
            TssObject swKey = TssObject.Create(inPub, authVal, privatePart);

            // Get a key duplication blob in TPM 2.0 compatibale format
            TpmPrivate dupBlob = swKey.GetPlaintextDuplicationBlob();

            // Importing a duplication blob creates a new TPM private key blob protected
            // with its new parent key.
            swKey.Private = tpm.Import(hParent, null, swKey.Public, dupBlob, null, new SymDefObject());

            return(swKey);
        } // ImportExternalRsaKey
コード例 #4
0
ファイル: Sample-KeyImport.cs プロジェクト: rgl/TSS.MSR
        void DuplicateImportRsaSample(Tpm2 tpm, TestContext testCtx)
        {
            TpmAlgId nameAlg = Substrate.Random(TpmCfg.HashAlgs);
            var      policy  = new PolicyTree(nameAlg);

            policy.SetPolicyRoot(new TpmPolicyCommand(TpmCc.Duplicate));

            var inPub = new TpmPublic(nameAlg,
                                      ObjectAttr.Sign | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin,
                                      policy.GetPolicyDigest(),
                                      new RsaParms(new SymDefObject(),
                                                   new SchemeRsassa(Substrate.Random(TpmCfg.HashAlgs)),
                                                   Substrate.Random(TpmCfg.RsaKeySizes), 0),
                                      new Tpm2bPublicKeyRsa());

            TpmHandle hKey = Substrate.CreateAndLoad(tpm, inPub, out TpmPublic pub);

            // Duplicate
            TpmPrivate priv = TpmHelper.GetPlaintextPrivate(tpm, hKey, policy);

            tpm.FlushContext(hKey);

            // Import
            TpmPrivate privImp = tpm.Import(Substrate.LoadRsaPrimary(tpm), null, pub, priv, null, new SymDefObject());
        } // SimpleDuplicateImportRsaSample
コード例 #5
0
ファイル: Limpet.cs プロジェクト: blinds52/security-1
        public void Provision(string encodedHmacKey, string hostName, string deviceId = "")
        {
            TpmHandle    nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle    ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle    hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);
            TpmHandle    srkHandle     = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8          = new UTF8Encoding();

            byte[] nvData  = utf8.GetBytes(hostName + "/" + deviceId);
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Define the store
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(nvHandle,
                                           TpmAlgId.Sha256,
                                           NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                           new byte[0],
                                           (ushort)nvData.Length));

            // Write the store
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Import the HMAC key under the SRK
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(new byte[0],
                                                                hmacKey),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          new byte[0],
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            new byte[0],
                                            new PcrSelection[0],
                                            out hmacPub,
                                            out creationData,
                                            out creationhash,
                                            out ticket);

            // Load the HMAC key into the TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Persist the key in NV
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }
コード例 #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);
        }
コード例 #7
0
        public Sensitive GetSensitive()
        {
            TpmPublic  fromCspPublic;
            TpmPrivate fromCspPrivate = Csp.CspToTpm(ExportCspBlob(), out fromCspPublic);
            var        m        = new Marshaller(fromCspPrivate.buffer);
            ushort     privSize = m.Get <UInt16>();

            if (fromCspPrivate.buffer.Length != privSize + 2)
            {
                Globs.Throw("Invalid key blob");
            }
            return(m.Get <Sensitive>());
        }
コード例 #8
0
        public static TpmPrivate GetPlaintextPrivate(Tpm2 tpm, TpmHandle key, PolicyTree policy)
        {
            AuthSession sess = tpm.StartAuthSessionEx(TpmSe.Policy, policy.HashAlg);

            sess.RunPolicy(tpm, policy);
            TpmPrivate privPlain = null;

            byte[] symSeed;
            tpm[sess]._ExpectResponses(TpmRc.Success, TpmRc.Attributes)
            .Duplicate(key, TpmRh.Null, null, new SymDefObject(),
                       out privPlain, out symSeed);
            Debug.Assert(!tpm._LastCommandSucceeded() || symSeed.Length == 0);
            tpm.FlushContext(sess);
            return(Globs.IsEmpty(privPlain.buffer) ? null : privPlain);
        }
コード例 #9
0
    /// <summary>
    /// Provision the key in the TPM
    /// </summary>
    /// <param name="key">the access key</param>
    public void Provision(byte[] key)
    {
        TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
        TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId);
        TpmHandle srkHandle     = new TpmHandle(TPM_20_SRK_HANDLE);

        // Open the TPM
        Tpm2Device tpmDevice = new TbsDevice();

        tpmDevice.Connect();
        using (var tpm = new Tpm2(tpmDevice))
        {
#pragma warning disable IDE0059 // Value assigned to symbol is never used
            // Import the HMAC key under the SRK
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(Array.Empty <byte>(),
                                                                key),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          Array.Empty <byte>(),
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            Array.Empty <byte>(),
                                            Array.Empty <PcrSelection>(),
                                            out TpmPublic hmacPub,
                                            out CreationData creationData,
                                            out byte[] creationhash,
                                            out TkCreation ticket);
#pragma warning restore IDE0059 // Value assigned to symbol is never used

            // Load the HMAC key into the TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Persist the key in NV
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }
    }
コード例 #10
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);
        }
コード例 #11
0
ファイル: TpmKey.cs プロジェクト: jimsdog/TSS.MSR
 public TssObject(TpmPublic thePublicPart, TpmPrivate thePrivatePart)
 {
     Public  = thePublicPart;
     Private = thePrivatePart;
 }
コード例 #12
0
ファイル: Program.cs プロジェクト: rgl/TSS.MSR
        } // CreateRsaPrimaryStorageKey()

        /// <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)
        {
            Console.WriteLine("\nPCR Quote sample started.");

            //
            // First use a library routine to create an RSA/AES primary storage key
            // with null user-auth.
            //
            TpmHandle primHandle = CreateRsaPrimaryStorageKey(tpm);

            //
            // Template for a signing key.  We will make the key restricted so that we
            // can quote with it too.
            //
            var signKeyPubTemplate = new TpmPublic(TpmAlgId.Sha256,
                                                   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
                                                   null,
                                                   new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0),
                                                   new Tpm2bPublicKeyRsa());
            //
            // Auth-data for new key
            //
            var userAuth   = new byte[] { 1, 2, 3, 4 };
            var sensCreate = new SensitiveCreate(userAuth, null);

            //
            // Creation data (not used in this sample)
            //
            CreationData childCreationData;
            TkCreation   creationTicket;

            byte[] creationHash;

            //
            // Create the key
            //
            TpmPublic  keyPub;
            TpmPrivate keyPriv = tpm.Create(primHandle,          // Child of primary key created above
                                            sensCreate,          // Auth-data
                                            signKeyPubTemplate,  // Template created above
                                            null,                // Other parms are not used here
                                            new PcrSelection[0], // Not bound to any PCRs
                                            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 hSigKey = tpm.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(hSigKey.Name));

            //
            // A nonce (or qualifying data)
            //
            TpmHash nonce = TpmHash.FromData(TpmAlgId.Sha256, new byte[] { 4, 3, 2, 1 });

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

            //
            // Ask the TPM to quote the PCR (with the given nonce).  The TPM
            // returns both the signature and the quote data that were signed.
            //
            ISignatureUnion quoteSig;
            Attest          quotedInfo = tpm.Quote(hSigKey,
                                                   nonce,
                                                   new SchemeRsassa(TpmAlgId.Sha256),
                                                   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.Sha256, new uint[] { 1, 2, 3 })
            },
                        out outSelection,
                        out outValues);

            //
            // Use the TSS.Net library to validate the quote against the
            // values just read.
            //
            bool quoteOk = keyPub.VerifyQuote(TpmAlgId.Sha256, outSelection, outValues,
                                              nonce, 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, null);

            tpm._ExpectError(TpmRc.Ticket)
            .Sign(hSigKey, nonce, new SchemeRsassa(TpmAlgId.Sha256), 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 tkSafeHash;
            TpmHandle   hashHandle = tpm.HashSequenceStart(null, TpmAlgId.Sha256);

            //
            // The ticket is only generated if the data is "safe."
            //
            tpm.SequenceComplete(hashHandle, new byte[] { 4, 3, 2, 1 },
                                 TpmRh.Owner, out tkSafeHash);
            //
            // 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.Sign(hSigKey, nonce,
                                           new SchemeRsassa(TpmAlgId.Sha256), tkSafeHash);
            //
            // 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(hSigKey);

            Console.WriteLine("PCR Quote sample finished.");
        } // QuotePcrs()
コード例 #13
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>
        /// <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);
        }
コード例 #14
0
 public TssObject(TpmPublic thePublicPart, TpmPrivate thePrivatePart)
 {
     publicPart  = thePublicPart;
     privatePart = thePrivatePart;
 }
コード例 #15
0
        /// <summary>
        /// Activates a symmetric identity within the Hardware Security Module.
        /// </summary>
        /// <param name="activation">The authentication challenge key supplied by the service.</param>
        public override void ActivateSymmetricIdentity(byte[] activation)
        {
            Destroy();

            // Take the pieces out of the container
            var m = new Marshaller(activation, DataRepresentation.Tpm);

            byte[] credentialBlob = new byte[m.Get <ushort>()];
            credentialBlob = m.GetArray <byte>(credentialBlob.Length, "credentialBlob");
            byte[] encryptedSecret = new byte[m.Get <ushort>()];
            encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret");
            TpmPrivate dupBlob = m.Get <TpmPrivate>();

            byte[] encWrapKey = new byte[m.Get <ushort>()];
            encWrapKey = m.GetArray <byte>(encryptedSecret.Length, "encWrapKey");
            UInt16 pubSize = m.Get <UInt16>();

            _idKeyPub = m.Get <TpmPublic>();
            byte[] cipherText = new byte[m.Get <ushort>()];
            cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo");

            // Setup the authorization session for the EK
            var policyNode = new TpmPolicySecret(
                TpmHandle.RhEndorsement, _ekAuth ?? Array.Empty <byte>(),
                new AuthValue(),
                false,
                0,
                Array.Empty <byte>(),
                Array.Empty <byte>());

            var policy = new PolicyTree(_ekPub.nameAlg);

            policy.SetPolicyRoot(policyNode);
            AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg);

            ekSession.RunPolicy(_tpm2, policy);

            // Perform the activation
            ekSession.Attrs  &= ~SessionAttr.ContinueSession;
            _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential(
                new TpmHandle(TPM_20_SRK_HANDLE),
                new TpmHandle(TPM_20_EK_HANDLE),
                credentialBlob,
                encryptedSecret);

            TpmPrivate importedKeyBlob = _tpm2.Import(
                new TpmHandle(TPM_20_SRK_HANDLE),
                _activationSecret,
                _idKeyPub,
                dupBlob,
                encWrapKey,
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));

            _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub);

            // Persist the key in NV
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);

            _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle);

            // Unload the transient copy from the TPM
            _tpm2.FlushContext(_idKeyHandle);
            _idKeyHandle = hmacKeyHandle;

            // Unwrap the URI
            byte[] clearText = SymmCipher.Decrypt(
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                _activationSecret,
                new byte[16],
                cipherText);

            UnicodeEncoding unicode = new UnicodeEncoding();
            string          uriData = unicode.GetString(clearText);
            int             idx     = uriData.IndexOf('/');

            if (idx > 0)
            {
                string hostName = uriData.Substring(0, idx);
                string deviceId = uriData.Substring(idx + 1);

                // Persist the URI
                ProvisionUri(hostName, deviceId);
            }
        }
コード例 #16
0
        /// <summary>
        /// Creates a child of the given storage key, which can be used both for signing and decryption.
        /// Illustrates strict mode effect on automatic authorization handling.
        /// </summary>
        /// <returns>Handle of the created key.</returns>
        static TpmHandle CreateSigningDecryptionKey(Tpm2 tpm, TpmHandle primHandle, out TpmPublic keyPublic)
        {
            TpmPublic keyInPublic = new TpmPublic(
                TpmAlgId.Sha1,
                ObjectAttr.Decrypt | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                null,
                new RsaParms(
                    new SymDefObject(),
                    new NullAsymScheme(),
                    2048, 0),
                new Tpm2bPublicKeyRsa());

            SensitiveCreate sensCreate = new SensitiveCreate(new byte[] { 1, 2, 3 }, null);
            CreationData    keyCreationData;
            TkCreation      creationTicket;

            byte[] creationHash;

            Console.WriteLine("Automatic authorization of a primary storage key.");

            //
            // An auth session is added automatically to authorize access to primHandle.
            //
            TpmPrivate keyPrivate = tpm.Create(primHandle,
                                               sensCreate,
                                               keyInPublic,
                                               null,
                                               new PcrSelection[0],
                                               out keyPublic,
                                               out keyCreationData,
                                               out creationHash,
                                               out creationTicket);

            TpmHandle keyHandle = null;

            Console.WriteLine("Strict mode.");

            //
            // Switch TPM object to the strict mode. (Note that this is a TSS.Net
            // specific piece of functionality, not a part of TPM 2.0 specification).
            //
            tpm._Behavior.Strict = true;

            //
            // No auth session is added automatically when TPM object is in strict mode.
            //
            tpm._ExpectError(TpmRc.AuthMissing)
            .Load(primHandle, keyPrivate, keyPublic);

            //
            // Now explicitly request an auth session of a desired type.
            // The actual auth value will be supplied by TSS.Net implicitly.
            //
            keyHandle = tpm[Auth.Default].Load(primHandle, keyPrivate, keyPublic);

            Console.WriteLine("Signing decryption key created.");

            //
            // Switch TPM object back to the normal mode.
            //
            tpm._Behavior.Strict = false;

            return(keyHandle);
        }
コード例 #17
0
        void TestAutomaticAuth(Tpm2 tpm, TestContext testCtx)
        {
            TpmHandle hPrim = Substrate.LoadRsaPrimary(tpm);

            // Make an RSA encryption key.
            var    decScheme = new SchemeOaep(Substrate.Random(TpmCfg.HashAlgs));
            var    sigScheme = new SchemeRsassa(Substrate.Random(TpmCfg.HashAlgs));
            ushort keyLength = Substrate.RandomRsaKeySize(decScheme.hashAlg);
            var    inPub     = new TpmPublic(Substrate.Random(TpmCfg.HashAlgs),
                                             ObjectAttr.Decrypt | ObjectAttr.Sign
                                             | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                                             | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                             null,
                                             new RsaParms(new SymDefObject(), null, keyLength, 0),
                                             new Tpm2bPublicKeyRsa());

            TpmPublic  keyPublic;
            TpmPrivate keyPrivate = Substrate.Create(tpm, hPrim, inPub, out keyPublic);

            TpmHandle keyHandle = null;

            tpm._Behavior.Strict = true;
            try
            {
                // No auth session is added automatically when TPM object is in strict mode.
                tpm._ExpectError(TpmRc.AuthMissing)
                .Load(hPrim, keyPrivate, keyPublic);

                // Now explicitly request an auth session of appropriate type
                keyHandle = tpm[Auth.Default].Load(hPrim, keyPrivate, keyPublic);
            }
            finally
            {
                tpm._Behavior.Strict = false;
            }

            byte[] message = Substrate.RandBytes(1, TpmHelper.MaxOaepMsgSize(keyLength, decScheme.hashAlg));

            byte[] encrypted = tpm.RsaEncrypt(keyHandle, message, decScheme, null);

            // An auth session is added automatically when TPM object is not in strict mode.
            byte[] decrypted1 = tpm.RsaDecrypt(keyHandle, encrypted, decScheme, null);

            TpmAlgId auditHashAlg = Substrate.Random(TpmCfg.HashAlgs);

            byte[] nonceTpm;

            // AuthSession object can be built from session handle concatenated, if necessary,
            // with session flags and unencrypted salt value (not used in this example).
            AuthSession auditSess = tpm.StartAuthSession(
                TpmRh.Null,                              // no salt
                TpmRh.Null,                              // no bind object
                Substrate.RandomNonce(auditHashAlg),     // nonceCaller
                null,                                    // no salt
                TpmSe.Hmac,                              // session type
                new SymDef(),                            // no encryption/decryption
                auditHashAlg,                            // authHash
                out nonceTpm)
                                    + (SessionAttr.ContinueSession | SessionAttr.Audit);

            /*
             * Alternatively one of the StartAuthSessionEx helpers can be used)
             * AuthSession auditSess = tpm.StartAuthSessionEx(TpmSe.Hmac, auditHashAlg, null,
             *                                                SessionAttr.ContinueSession | SessionAttr.Audit);
             */

            // TSS-specific call to verify TPM auditing correctness.
            tpm._SetCommandAuditAlgorithm(auditHashAlg);

            // Appropriate auth value is added automatically into the provided session
            byte[] decrypted2 = tpm[auditSess]._Audit()
                                .RsaDecrypt(keyHandle, encrypted, decScheme, null);

            ISignatureUnion sig;
            Attest          attest;

            // A session is added automatically to authorize TpmRh.Endorsement usage.
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                               null, new NullSigScheme(), out sig);

            // But if the corresponding auth value stored in the Tpm2 object is invalid, ...
            AuthValue endorsementAuth = tpm.EndorsementAuth;

            tpm.EndorsementAuth = Globs.ByteArray(16, 0xde);
            // ... the command will fail
            tpm._ExpectError(TpmRc.BadAuth)
            .GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                   null, new NullSigScheme(), out sig);
            // Restore correct auth value.
            tpm.EndorsementAuth = endorsementAuth;

            // Verify that both decryption and auditing worked correctly.
            SessionAuditInfo info = (SessionAuditInfo)attest.attested;

            byte[] auditDigest = tpm._GetAuditHash();
            testCtx.AssertEqual("AuditSessionDigest", info.sessionDigest, auditDigest);
            testCtx.AssertEqual("Decryption", decrypted1, decrypted2);

            // Change auth value of the decryption key.
            TpmPrivate newKeyPrivate = tpm.ObjectChangeAuth(keyHandle, hPrim,
                                                            Substrate.RandomAuth(keyPublic.nameAlg));
            TpmHandle newKeyHandle = tpm.Load(hPrim, newKeyPrivate, keyPublic);

            auditSess.Attrs &= ~SessionAttr.AuditExclusive;
            // Correct auth value (corresponding to newKeyHandle, and different from
            // the one used for keyHandle) will be added to auditSess.
            decrypted1 = tpm[auditSess]._Audit().RsaDecrypt(newKeyHandle, encrypted, decScheme, null);

            // And now two sessions are auto-generated (for TpmRh.Endorsement and keyHandle).
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess,
                                               null, sigScheme, out sig);
            bool sigOk = keyPublic.VerifySignatureOverData(
                Marshaller.GetTpmRepresentation(attest), sig);

            testCtx.Assert("AuditSessionSignatute.1", sigOk);

            // Here the first session is generated based on session type indicator
            // (Auth.Pw), and the second one is added automatically.
            attest = tpm[Auth.Pw].GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess,
                                                        null, sigScheme, out sig);

            // Verify that auditing worked correctly.
            sigOk = keyPublic.VerifySignatureOverData(
                Marshaller.GetTpmRepresentation(attest), sig);
            testCtx.Assert("AuditSessionSignatute.2", sigOk);

            tpm.FlushContext(newKeyHandle);
            tpm.FlushContext(auditSess);

            if (!TestCfg.HasTRM)
            {
                // Deplete TPM's active session storage
                List <AuthSession> landfill = new List <AuthSession>();

                for (;;)
                {
                    tpm._AllowErrors();
                    AuthSession s = tpm.StartAuthSessionEx(TpmSe.Hmac, Substrate.Random(TpmCfg.HashAlgs),
                                                           SessionAttr.ContinueSession);
                    if (!tpm._LastCommandSucceeded())
                    {
                        break;
                    }
                    landfill.Add(s);
                }

                // Check if session type indicators are processed correctly
                tpm[Auth.Hmac]._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, null, null);
                tpm[Auth.Pw].RsaDecrypt(keyHandle, encrypted, null, null);

                // Check if default session type defined by the TPM device is processed correctly
                bool needHmac = tpm._GetUnderlyingDevice().NeedsHMAC;

                tpm._GetUnderlyingDevice().NeedsHMAC = true;
                tpm._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, null, null);
                tpm[Auth.Default]._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, null, null);

                tpm._GetUnderlyingDevice().NeedsHMAC = false;
                tpm.RsaDecrypt(keyHandle, encrypted, null, null);
                tpm[Auth.Default].RsaDecrypt(keyHandle, encrypted, null, null);

                tpm._GetUnderlyingDevice().NeedsHMAC = needHmac;

                landfill.ForEach(s => tpm.FlushContext(s));
            }
            tpm.FlushContext(keyHandle);
        } // TestAutomaticAuth
コード例 #18
0
        /// <summary>
        /// Illustrates various cases of automatic authorization handling.
        /// </summary>
        static void AutomaticAuth(Tpm2 tpm)
        {
            TpmHandle primHandle = CreateRsaPrimaryKey(tpm);

            TpmPublic keyPublic;
            TpmHandle keyHandle = CreateSigningDecryptionKey(tpm, primHandle, out keyPublic);

            byte[] message = Globs.GetRandomBytes(32);

            IAsymSchemeUnion decScheme = new SchemeOaep(TpmAlgId.Sha1);
            ISigSchemeUnion  sigScheme = new SchemeRsassa(TpmAlgId.Sha1);

            //
            // TSS.Net implicitly creates an auth session to authorize keyHandle.
            // It uses the auth value cached in the TpmHandle object.
            //
            byte[] encrypted = tpm.RsaEncrypt(keyHandle, message, decScheme, null);

            Console.WriteLine("Automatic authorization of a decryption key.");

            //
            // An auth session is added automatically when TPM object is not in strict mode.
            //
            byte[] decrypted1 = tpm.RsaDecrypt(keyHandle, encrypted, decScheme, null);

            byte[] nonceTpm;

            Console.WriteLine("Session object construction.");

            //
            // If a session with specific properties is required, an AuthSession object
            // can be built from the session handle returned by the TPM2_StartAuthSession
            // command concatenated, if necessary, with session flags and unencrypted salt
            // value (not used in this example).
            //
            AuthSession auditSess = tpm.StartAuthSession(
                TpmRh.Null,                             // no salt
                TpmRh.Null,                             // no bind object
                Globs.GetRandomBytes(16),               // nonceCaller
                null,                                   // no salt
                TpmSe.Hmac,                             // session type
                new SymDef(),                           // no encryption/decryption
                TpmAlgId.Sha256,                        // authHash
                out nonceTpm)
                                    + (SessionAttr.ContinueSession | SessionAttr.Audit);

            /*
             * Alternatively one of the StartAuthSessionEx helpers can be used). E.g.
             *
             * AuthSession auditSess = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256,
             *                                  SessionAttr.ContinueSession | SessionAttr.Audit);
             */

            //
            // TSS.Net specific call to verify TPM auditing correctness.
            //
            tpm._SetCommandAuditAlgorithm(TpmAlgId.Sha256);

            Console.WriteLine("Automatic authorization using explicitly created session object.");

            //
            // Appropriate auth value is added automatically into the provided session.
            //
            // Note that the call to _Audit() is optional and is only used when one
            // needs the TSS.Net framework to compute the audit digest on its own (e.g.
            // when simulating the TPM functionality without access to an actual TPM).
            //
            byte[] decrypted2 = tpm[auditSess]._Audit()
                                .RsaDecrypt(keyHandle, encrypted, decScheme, null);

            ISignatureUnion signature;
            Attest          attest;

            //
            // A session is added automatically to authorize usage of the permanent
            // handle TpmRh.Endorsement.
            //
            // Note that if auth value of TpmRh.Endorsement is not empty, you need to
            // explicitly assign it to the tpm.EndorsementAuth property of the given
            // Tpm2 object.
            //
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                               null, new NullSigScheme(), out signature);

            //
            // But if the corresponding auth value stored in the Tpm2 object is invalid, ...
            //
            AuthValue endorsementAuth = tpm.EndorsementAuth;

            tpm.EndorsementAuth = Globs.ByteArray(16, 0xde);

            //
            // ... the command will fail.
            //
            tpm._ExpectError(TpmRc.BadAuth)
            .GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                   null, new NullSigScheme(), out signature);
            //
            // Restore correct auth value.
            //
            tpm.EndorsementAuth = endorsementAuth;

            //
            // Verify that decryption worked correctly.
            //
            Debug.Assert(Globs.ArraysAreEqual(decrypted1, decrypted2));

            //
            // Verify that auditing worked correctly.
            //
            SessionAuditInfo info = (SessionAuditInfo)attest.attested;

            Debug.Assert(Globs.ArraysAreEqual(info.sessionDigest, tpm._GetAuditHash().HashData));

            Console.WriteLine("Auth value tracking by TSS.Net.");

            //
            // Change auth value of the decryption key.
            //
            TpmPrivate newKeyPrivate = tpm.ObjectChangeAuth(keyHandle, primHandle, AuthValue.FromRandom(16));
            TpmHandle  newKeyHandle  = tpm.Load(primHandle, newKeyPrivate, keyPublic);

            //
            // Allow non-exclusive usage of the audit session.
            //
            auditSess.Attrs &= ~SessionAttr.AuditExclusive;

            //
            // Correct auth value (corresponding to newKeyHandle, and different from
            // the one used for keyHandle) will be added to auditSess.
            //
            decrypted1 = tpm[auditSess]._Audit()
                         .RsaDecrypt(newKeyHandle, encrypted, decScheme, null);

            Console.WriteLine("Automatic authorization with multiple sessions.");

            //
            // Now two sessions are auto-generated (for TpmRh.Endorsement and keyHandle).
            //
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess,
                                               null, sigScheme, out signature);

            //
            // Verify that the previous command worked correctly.
            //
            bool sigOk = keyPublic.VerifySignatureOverData(Marshaller.GetTpmRepresentation(attest),
                                                           signature);

            Debug.Assert(sigOk);

            //
            // In the following example the first session is generated based on session
            // type indicator (Auth.Pw), and the second one is added automatically.
            //
            attest = tpm[Auth.Pw].GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess,
                                                        null, sigScheme, out signature);

            //
            // Verify that the previous command worked correctly.
            //
            sigOk = keyPublic.VerifySignatureOverData(Marshaller.GetTpmRepresentation(attest),
                                                      signature);
            Debug.Assert(sigOk);

            //
            // Release TPM resources that we do not need anymore.
            //
            tpm.FlushContext(newKeyHandle);
            tpm.FlushContext(auditSess);

            //
            // The following example works correctly only when TPM resource management
            // is not enabled (e.g. with TPM simulator, or when actual TPM is in raw mode).
            //
            if (!tpm._GetUnderlyingDevice().HasRM())
            {
                Console.WriteLine("Using session type indicators.");

                //
                // Deplete TPM's active session storage
                //
                List <AuthSession> landfill = new List <AuthSession>();

                for (;;)
                {
                    tpm._AllowErrors();
                    AuthSession s = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256,
                                                           SessionAttr.ContinueSession);
                    if (!tpm._LastCommandSucceeded())
                    {
                        break;
                    }
                    landfill.Add(s);
                }

                //
                // Check if session type indicators are processed correctly
                //
                tpm[Auth.Hmac]._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);
                //
                // Password authorization protocol session uses a predefined handle value,
                // so it must work even when there are no free session slots in the TPM.
                //
                tpm[Auth.Pw].RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);

                //
                // Check if default session type defined by the TPM device is processed correctly.
                //
                bool needHmac = tpm._GetUnderlyingDevice().NeedsHMAC;

                tpm._GetUnderlyingDevice().NeedsHMAC = true;

                tpm._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);

                tpm[Auth.Default]._ExpectError(TpmRc.SessionMemory)
                .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);

                tpm._GetUnderlyingDevice().NeedsHMAC = false;

                tpm.RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);
                tpm[Auth.Default].RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), null);

                tpm._GetUnderlyingDevice().NeedsHMAC = needHmac;

                landfill.ForEach(s => tpm.FlushContext(s));
            }

            //
            // Release TPM resources.
            //
            tpm.FlushContext(keyHandle);
            tpm.FlushContext(primHandle);

            Console.WriteLine("Done.");
        }
コード例 #19
0
ファイル: TpmHelper.cs プロジェクト: catan85/SshOnDemand
        /// <summary>
        /// Funzione per il salvataggio della chiave privata da utilizzare per firmare con HMAC tramite TPM
        /// </summary>
        /// <param name="encodedHmacKey"></param>
        public static void SaveHmacKey(string encodedHmacKey)
        {
            // Definizione area di memoria non volatile nel TPM
            TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);

            // Definizione dell'handle contenente l'Owner nel TPM
            TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner);

            // Definizione dell'handle per la memorizzazione dell'oggetto HMAC
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Definizione dell'handle della Storage Root Key, si tratta della chiave
            // principale utilizzata per il salvataggio di altre chiavi. Ogni chiave salvata
            // nel TPM infatti viene cifrata utilizzando la sua chiave "padre".
            // La SRK è la chiave più alta dell'albero
            TpmHandle    srkHandle = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8      = new UTF8Encoding();

            // dati descrittivi dell'host e del device id
            byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId);

            // chiave privata che intendiamo memorizzare nel TPM
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Apertura del TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Definizione dello store Non volatile
            // Il primo parametro è l'Owner TPM
            // il terzo parametro è la funzione HMAC che intendiamo salvare
            // (NvPublic sta per Non volatile public area)
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(
                                  nvHandle,
                                  TpmAlgId.Sha256,
                                  NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                  new byte[0],
                                  (ushort)nvData.Length));

            // Scrittura nello store non volatile della funzione HMAC
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Importazione della chiave HMAC sotto la Storage Root Key
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;

            // Passaggio della chiave privata
            var sensitiveCreate = new SensitiveCreate(new byte[0], hmacKey);

            // Definizione dell'uso che si farà della chiave
            var tpmPublic = new TpmPublic(
                TpmAlgId.Sha256,
                ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                new byte[0],
                new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                new Tpm2bDigestKeyedhash());

            // Salvataggio della chiave privata nel tpm
            TpmPrivate hmacPrv = tpm.Create(
                srkHandle,
                sensitiveCreate,
                tpmPublic,
                new byte[0],
                new PcrSelection[0],
                out hmacPub,
                out creationData,
                out creationhash,
                out ticket);

            // Caricamento della chiave HMAC nel TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Salvataggio della chiave nella memoria Non Volatile
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Flush degli oggetti transienti dal tpm
            tpm.FlushContext(loadedHmacKey);
        }
コード例 #20
0
        /// <summary>
        /// Activates an identity key within the TPM device.
        /// </summary>
        /// <param name="encryptedKey">The encrypted identity key.</param>
        public override void ActivateIdentityKey(byte[] encryptedKey)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
            Destroy();

            // Take the pieces out of the container
            var           m      = new Marshaller(encryptedKey, DataRepresentation.Tpm);
            Tpm2bIdObject cred2b = m.Get <Tpm2bIdObject>();

            byte[] encryptedSecret = new byte[m.Get <ushort>()];
            encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret");
            TpmPrivate dupBlob = m.Get <TpmPrivate>();

            byte[] encWrapKey = new byte[m.Get <ushort>()];
            encWrapKey = m.GetArray <byte>(encWrapKey.Length, "encWrapKey");
            UInt16 pubSize = m.Get <UInt16>();

            _idKeyPub = m.Get <TpmPublic>();
            byte[] cipherText = new byte[m.Get <ushort>()];
            cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo");

            // Setup the authorization session for the EK
            var policyNode = new TpmPolicySecret(TpmHandle.RhEndorsement, false, 0, Array.Empty <byte>(), Array.Empty <byte>());
            var policy     = new PolicyTree(_ekPub.nameAlg);

            policy.SetPolicyRoot(policyNode);
            AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg);

            ekSession.RunPolicy(_tpm2, policy);

            // Perform the activation
            ekSession.Attrs  &= ~SessionAttr.ContinueSession;
            _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential(
                new TpmHandle(TPM_20_SRK_HANDLE),
                new TpmHandle(TPM_20_EK_HANDLE),
                cred2b.credential,
                encryptedSecret);

            TpmPrivate importedKeyBlob = _tpm2.Import(
                new TpmHandle(TPM_20_SRK_HANDLE),
                _activationSecret,
                _idKeyPub,
                dupBlob,
                encWrapKey,
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));

            _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub);

            // Persist the key in NV
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);

            _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle);

            // Unload the transient copy from the TPM
            _tpm2.FlushContext(_idKeyHandle);
            _idKeyHandle = hmacKeyHandle;

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
        }
コード例 #21
0
ファイル: Program.cs プロジェクト: tes001/TSS.MSR
        /// <summary>
        /// Performs the following operations:
        /// - Generates in software (using TSS.net helpers) a key with the given template,
        /// - Creates TPM-compatible dupliction blob for the given TPM based parent key,
        /// - Import the duplication blob into TPM
        /// - Loads the imported key into the TPM
        /// - Makes sure that the imported key works.
        /// </summary>
        /// <param name="tpm">TPM instance to use</param>
        /// <param name="keyPub">Template for the software generated key.</param>
        /// <param name="hParent">Intended TPM based parent key for the software generated key.</param>
        /// <param name="innerSymDef">Specification of the optional inner wrapper for the duplication blob.</param>
        static void GenerateAndImport(Tpm2 tpm, TpmPublic keyPub, TpmHandle hParent,
                                      SymDefObject innerSymDef = null)
        {
            //
            // Create a software key with the given template
            //

            // Generate a random auth value for the key to be created (though we could
            // use an empty buffer, too).
            var keyAuth = AuthValue.FromRandom(CryptoLib.DigestSize(keyPub.nameAlg));

            // Generate the key
            TssObject swKey = TssObject.Create(keyPub, keyAuth);

            //
            // Create duplication blob for the new key with the SRK as the new parent
            //

            // Create a symmetric software key if an inner wrapper is requested.
            var innerWrapKey = innerSymDef == null ? null : SymCipher.Create(innerSymDef);

            // Retrieve the public area of the intended parent key from the TPM
            // We do not need the name (and qualified name) of the key here, but
            // the TPM command returns them anyway.
            // NOTE - Alternatively we could get the public area from the overloaded
            // form of the CreateRsaPrimaryStorageKey() helper used to create the parent
            // key, as all TPM key creation commands (TPM2_CreatePrimary(), TPM2_Create()
            // and TPM2_CreateLoaded()) return it.
            byte[]    name, qname;
            TpmPublic pubParent = tpm.ReadPublic(hParent, out name, out qname);

            byte[]     encSecret;
            TpmPrivate dupBlob = swKey.GetDuplicationBlob(pubParent, innerWrapKey, out encSecret);

            // Import the duplication blob into the TPM
            TpmPrivate privImp = tpm.Import(hParent, innerWrapKey, swKey.Public, dupBlob,
                                            encSecret, innerSymDef ?? new SymDefObject());

            // Load the imported key ...
            TpmHandle hKey = tpm.Load(hParent, privImp, swKey.Public)
                             .SetAuth(swKey.Sensitive.authValue);

            // ... and validate that it works
            byte[] message = Globs.GetRandomBytes(32);

            if (keyPub.objectAttributes.HasFlag(ObjectAttr.Decrypt))
            {
                // Encrypt something
                if (keyPub.type == TpmAlgId.Symcipher)
                {
                    // Only need software symcypher here to query IV size.
                    // Normally, when you use a fixed algorithm, you can hardcode it.
                    var    swSym = SymCipher.Create(keyPub.parameters as SymDefObject);
                    byte[] ivIn  = Globs.GetRandomBytes(swSym.IVSize),
                    ivOut = null;
                    byte[] cipher = swKey.Encrypt(message, ref ivIn, out ivOut);

                    // Not all TPMs implement TPM2_EncryptDecrypt() command
                    tpm._ExpectResponses(TpmRc.Success, TpmRc.TbsCommandBlocked);
                    byte[] decrypted = tpm.EncryptDecrypt(hKey, 1, TpmAlgId.Null, ivIn,
                                                          cipher, out ivOut);
                    if (tpm._LastCommandSucceeded())
                    {
                        bool decOk = Globs.ArraysAreEqual(message, decrypted);
                        Console.WriteLine("Imported symmetric key validation {0}",
                                          decOk ? "SUCCEEDED" : "FAILED");
                    }
                }
            }
            else
            {
                // Sign something (works for both asymmetric and MAC keys)
                string keyType = keyPub.type == TpmAlgId.Rsa ? "RSA"
                               : keyPub.type == TpmAlgId.Keyedhash ? "HMAC"
                               : "UNKNOWN"; // Should not happen in this sample
                TpmAlgId        sigHashAlg = GetSchemeHash(keyPub);
                TpmHash         toSign     = TpmHash.FromData(sigHashAlg, message);
                var             proofx     = new TkHashcheck(TpmRh.Null, null);
                ISignatureUnion sig        = tpm.Sign(hKey, toSign, null, proofx);
                bool            sigOk      = swKey.VerifySignatureOverHash(toSign, sig);
                Console.WriteLine("Imported {0} key validation {1}", keyType,
                                  sigOk ? "SUCCEEDED" : "FAILED");
            }

            // Free TPM resources taken by the loaded imported key
            tpm.FlushContext(hKey);
        } // GenerateAndImport