public TpmHandle GenerateRSASigningKeyPair(AuthValue ownerAuth, out TpmPublic keyPublic, byte[] keyAuth, TpmHandle persistantHandle) { 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(), // not a restricted decryption key new SchemeRsassa(TpmAlgId.Sha1), // an unrestricted signing key 2048, 0), new Tpm2bPublicKeyRsa()); var sensCreate = new SensitiveCreate(keyAuth, new byte[0]); //TpmPublic keyPublic; byte[] outsideInfo = Globs.GetRandomBytes(8); var creationPcrArray = new PcrSelection[0]; TpmHandle h = tpm[ownerAuth].CreatePrimary( TpmHandle.RhOwner, // In the owner-hierarchy sensCreate, // With this auth-value keyTemplate, // Describes key outsideInfo, // For creation ticket creationPcrArray, // For creation ticket out keyPublic, // Out pubKey and attributes out CreationData creationData, // Not used here out byte[] creationHash, // Not used here out TkCreation creationTicket); tpm.EvictControl(TpmHandle.RhOwner, h, persistantHandle); return(h); }
static TpmHandle CreateRsaPrimaryKey(Tpm2 tpm, bool isSimulator) { if (isSimulator) { tpm.DictionaryAttackParameters(TpmHandle.RhLockout, 1000, 10, 1); tpm.DictionaryAttackLockReset(TpmHandle.RhLockout); } // // First member of SensitiveCreate contains auth value of the key // var sensCreate = new SensitiveCreate(new byte[] { 0xa, 0xb, 0xc }, null); TpmPublic parms = new TpmPublic( TpmAlgId.Sha1, ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, null, new RsaParms( new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); var creationPcr = new PcrSelection(TpmAlgId.Sha1, new uint[] { 0, 1, 2 }); TpmPublic pubCreated; CreationData creationData; TkCreation creationTicket; byte[] creationHash; Console.WriteLine("Automatic authorization of TpmRh.Owner."); // // An auth session is added automatically to authorize access to the permanent // handle TpmHandle.RhOwner. // // Note that if the TPM is not a simulator and not cleared, you need to // assign the corresponding auth value to the tpm.OwnerAuth property of // the given Tpm2 object. // TpmHandle h = tpm.CreatePrimary(TpmRh.Owner, sensCreate, parms, outsideInfo, new PcrSelection[] { creationPcr }, out pubCreated, out creationData, out creationHash, out creationTicket); Console.WriteLine("Primary RSA storage key created."); return(h); }
public TpmHandle GenerateRsaEncryptionKeyPair(AuthValue ownerAuth, out TpmPublic keyPublic, byte[] keyAuth, TpmHandle persistantHandle) { var sensCreate = new SensitiveCreate(keyAuth, new byte[0]); TpmPublic keyTemplate = new TpmPublic( TpmAlgId.Sha1, ObjectAttr.UserWithAuth | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.SensitiveDataOrigin, new byte[0], new RsaParms( new SymDefObject(), //a unrestricted decryption key new NullAsymScheme(), //not a signing key 2048, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); var creationPcrArray = new PcrSelection[0]; TpmHandle h = tpm[ownerAuth].CreatePrimary( TpmRh.Owner, sensCreate, keyTemplate, outsideInfo, creationPcrArray, out keyPublic, out CreationData creationData, out byte[] creationHash, out TkCreation creationTicket); tpm.EvictControl(TpmHandle.RhOwner, h, persistantHandle); return(h); }
/// <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."); }
/// <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