internal static TpmHandle CreatePrimary(Tpm2 tpm, out TpmPublic newKeyPub, byte[] auth = null, byte[] seed = null) { var sensCreate = new SensitiveCreate(auth, null); var parms = new TpmPublic(TpmAlgId.Sha256, // Name algorithm ObjectAttr.Restricted | ObjectAttr.Decrypt | // Storage key ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, null, // No policy // No signing or decryption scheme, and non-empty symmetric // specification (even when it is an asymmetric key) new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), null, 2048, 0), new Tpm2bPublicKeyRsa(seed) // Additional entropy for key derivation ); CreationData creationData; TkCreation creationTicket; byte[] creationHash; var handle = tpm.CreatePrimary(TpmRh.Owner, // In storage hierarchy sensCreate, // Auth value CreateDecryptionKey(), // Key template // // The following parameters influence the creation of the // creation-ticket. They are not used in this sample // null, // Null outsideInfo new PcrSelection[0], // Not PCR-bound out newKeyPub, // Our outs out creationData, out creationHash, out creationTicket); return(handle); }
private TpmPublic ReadOrCreatePersistedKey(TpmHandle persHandle, TpmHandle hierarchy, TpmPublic template) { byte[] name; byte[] qualifiedName; // Let's see if the key was already created and installed. TpmPublic keyPub = _tpm2._AllowErrors().ReadPublic(persHandle, out name, out qualifiedName); // If not create and install it. if (!_tpm2._LastCommandSucceeded()) { CreationData creationData; byte[] creationHash; TkCreation creationTicket; TpmHandle keyHandle = _tpm2.CreatePrimary(hierarchy, new SensitiveCreate(), template, Array.Empty <byte>(), Array.Empty <PcrSelection>(), out keyPub, out creationData, out creationHash, out creationTicket); _tpm2.EvictControl(TpmHandle.RhOwner, keyHandle, persHandle); _tpm2.FlushContext(keyHandle); } return(keyPub); }
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); }
void EcdhSample(Tpm2 tpm, TestContext testCtx) { // // Peer A (e.g. local machine): // // Template for an ECC key with the ECDH scheme: var inPub = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Decrypt | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, null, new EccParms(new SymDefObject(), new SchemeEcdh(TpmAlgId.Sha256), EccCurve.NistP256, new NullKdfScheme()), new EccPoint()); // Boilerplate stuff var pcrSel = new PcrSelection[0]; CreationData crData; byte[] crHash; TkCreation crTk; // Create a key for ECDH TpmPublic pubA; TpmHandle hKeyA = tpm.CreatePrimary(TpmRh.Owner, new SensitiveCreate(), inPub, null, new PcrSelection[0], out pubA, out crData, out crHash, out crTk); // // Peer B (e.g. remote machine): // // Receives 'pubA' from peer A // Load public key TpmHandle hPubKeyA = tpm.LoadExternal(null, pubA, TpmRh.Owner); // Create shared secret 'zB', and a public ECC point for exchange EccPoint ephPubPt; EccPoint zB = tpm.EcdhKeyGen(hPubKeyA, out ephPubPt); tpm.FlushContext(hPubKeyA); // // Peer A again: // // Receives 'ephPubPt' from peer B // A full key is required here EccPoint zA = tpm.EcdhZGen(hKeyA, ephPubPt); testCtx.AssertEqual("SharedSecret", zA, zB); tpm.FlushContext(hKeyA); } // EcdhSample
internal static void EncryptDecrypt(Tpm2 tpm) { var keyParams = KeyHelpers.CreateDecryptionKey2(); TpmPublic pubCreated; CreationData creationData; TkCreation creationTicket; byte[] creationHash; TpmHandle h = tpm.CreatePrimary(TpmRh.Owner, null, keyParams, null, //outsideInfo, null, //new PcrSelection[] { creationPcr }, out pubCreated, out creationData, out creationHash, out creationTicket); }
internal static TpmHandle CreatePrimaryRsaKey(Tpm2 tpm, TpmHandle primHandle, byte[] auth, byte[] seed, out TpmPublic keyPublic) { if (primHandle == null) { primHandle = TpmRh.Endorsement; } 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(seed)); SensitiveCreate sensCreate = new SensitiveCreate(auth, null); CreationData keyCreationData; TkCreation creationTicket; byte[] creationHash; TpmHandle keyPrivate = tpm.CreatePrimary(primHandle, sensCreate, keyInPublic, auth, new PcrSelection[0], out keyPublic, out keyCreationData, out creationHash, out creationTicket); return(keyPrivate); }
void ActivateAikSample(Tpm2 tpm, TestContext testCtx) { // Use an RSA primary key in the Endorsement hierarchy (EK) to 'activate' // another primary in the Endorsement hierarchy (AIK). // Note: this procedure can be used to activate a key in the Storage hierarchy, too. // "Activation" means secure passing sensitive data generated by a CA (e.g. // a symmetric key protecting a freshly generated certificate), so that only // a device with the TPM owning the target AIK and EK can access these data. // Create a primary key that we will certify. ////////////////////////////////////////////////////////////////////////////// // Device side code ////////////////////////////////////////////////////////////////////////////// // Name algorithm of the new AIK TpmAlgId nameAlg = TpmAlgId.Sha256; // The key to be certified needs a policy. It can be ANY policy, but here // it is configured to allow AIK usage only with the following commands var policyAIK = new PolicyTree(nameAlg); var policyOR = new TpmPolicyOr(); policyAIK.SetPolicyRoot(policyOR); policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.ActivateCredential, "Activate")); policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.Certify, "Certify")); policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.CertifyCreation, "CertifyCreation")); policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.Quote, "Quote")); var inAIKPub = new TpmPublic(nameAlg, ObjectAttr.Restricted | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin, policyAIK.GetPolicyDigest(), new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa()); TpmPublic AIKpub; var inSens = new SensitiveCreate(Substrate.RandomAuth(nameAlg), null); CreationData creationData; byte[] creationHash; TkCreation creationTk; TpmHandle hAIK = tpm.CreatePrimary(TpmRh.Endorsement, inSens, inAIKPub, null, null, out AIKpub, out creationData, out creationHash, out creationTk); // An alternative using test substrate helper //TpmHandle hAIK = Substrate.CreatePrimary(tpm, inAIKPub, TpmRh.Endorsement); // Normally a device would have a pre-provisioned persistent EK with the above handle TpmHandle hEK = new TpmHandle(0x81010001); // Get its public part TpmPublic EKpub = null; // In a test environment the real EK may be absent. In this case use // a primary key temporarily created in the Endorsement hierarchy. byte[] name, qname; tpm._AllowErrors() .ReadPublic(hEK, out name, out qname); if (!tpm._LastCommandSucceeded()) { var inEKpub = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin, new byte[] { 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa }, new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), null, 2048, 0), new Tpm2bPublicKeyRsa()); inSens = new SensitiveCreate(null, null); hEK = tpm.CreatePrimary(TpmRh.Endorsement, inSens, inEKpub, null, null, out EKpub, out creationData, out creationHash, out creationTk); } // Marshal public parts of AIK and EK byte[] AIKpubBytes = AIKpub.GetTpmRepresentation(); byte[] EKpubBytes = EKpub.GetTpmRepresentation(); // Here the device uses network to pass AIKpubBytes and EKpubBytes (as well as // the EK certificate) to CA service. ////////////////////////////////////////////////////////////////////////////// // Service (CA) side code ////////////////////////////////////////////////////////////////////////////// // Unmarshal AIKpub and EKpub (and EK certificate) var m = new Marshaller(AIKpubBytes); AIKpub = m.Get <TpmPublic>(); m = new Marshaller(EKpubBytes); EKpub = m.Get <TpmPublic>(); // Symmetric key to be used by CA to encrypt the new certificate it creates for AIK byte[] secretKey = Substrate.RandomBytes(32); // Here CA does the following (the sample does not show this code): // - Validates EK certificate // - Generates a new certificate for AIK (AIKcert) // - Encrypts AIKcert with secretKey // Create an activation blob // Internal wrapper key encrypted with EKpub to be used by TPM2_ActivateCredential() command. byte[] encSecret; // An encrypted and HMACed object tied to the destination TPM. It contains // 'secret' to be extracted by the successful TPM2_ActivateCredential() command // (that can only succeeed on the TPM that originated both EK and AIK). IdObject certInfo; // Run TSS.Net equivalent of TPM2_MakeCredential() command (convenient for the server side, // as it will likely be faster than the TPM transaction and allows concurrent execution). certInfo = EKpub.CreateActivationCredentials(secretKey, AIKpub.GetName(), out encSecret); // Marshal certInfo // IdObject data type requires customized marshaling m = new Marshaller(); m.Put(certInfo.integrityHMAC.Length, "integrityHMAC.Length"); m.Put(certInfo.integrityHMAC, "integrityHMAC"); m.Put(certInfo.encIdentity.Length, "encIdentity"); m.Put(certInfo.encIdentity, "encIdentity.Length"); byte[] certInfoBytes = m.GetBytes(); // Here the CA passes certInfoBytes and encSecret (as well as the encrypted // AIK certificate) back to the device via network. ////////////////////////////////////////////////////////////////////////////// // Device side code again ////////////////////////////////////////////////////////////////////////////// // Unmarshal certInfo and encSecret (and encrypted AIK certificate) m = new Marshaller(certInfoBytes); int len = m.Get <int>(); certInfo.integrityHMAC = m.GetArray <byte>(len); len = m.Get <int>(); certInfo.encIdentity = m.GetArray <byte>(len); // encSecret is a byte array, so, normally, no special unmarshalling is required // Create policy session to authorize AIK usage AuthSession sessAIK = tpm.StartAuthSessionEx(TpmSe.Policy, nameAlg); sessAIK.RunPolicy(tpm, policyAIK, "Activate"); // Create policy description and corresponding policy session to authorize EK usage var policyEK = new PolicyTree(EKpub.nameAlg); policyEK.SetPolicyRoot(new TpmPolicySecret(TpmRh.Endorsement, false, 0, null, null)); AuthSession sessEK = tpm.StartAuthSessionEx(TpmSe.Policy, EKpub.nameAlg); sessEK.RunPolicy(tpm, policyEK); byte[] recoveredSecretKey = tpm[sessAIK, sessEK].ActivateCredential(hAIK, hEK, certInfo, encSecret); testCtx.AssertEqual("Secret.1", recoveredSecretKey, secretKey); // Here the device can use recoveredSecretKey to decrypt the AIK certificate ////////////////////////////////////////////////////////////////////////////// // End of activation sequence ////////////////////////////////////////////////////////////////////////////// // // Now prepare activation using the TPM built-in command // byte[] encSecret2 = null; IdObject certInfo2 = tpm.MakeCredential(hEK, secretKey, AIKpub.GetName(), out encSecret2); // Reinitialize policy sessions tpm.PolicyRestart(sessAIK); sessAIK.RunPolicy(tpm, policyAIK, "Activate"); tpm.PolicyRestart(sessEK); sessEK.RunPolicy(tpm, policyEK); recoveredSecretKey = tpm[sessAIK, sessEK].ActivateCredential(hAIK, hEK, certInfo2, encSecret2); testCtx.AssertEqual("Secret.2", recoveredSecretKey, secretKey); // Cleanup tpm.FlushContext(sessAIK); tpm.FlushContext(sessEK); tpm.FlushContext(hAIK); if (hEK.handle != 0x81010001) { tpm.FlushContext(hEK); } } // ActivateAikSample
} // QuotePcrs() /// <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) { Console.WriteLine("\nStorageRootKey sample started."); // // This template asks the TPM to create an 2048 bit RSA storage key // with an associated AES key for symmetric protection of its child keys. // NOTE - The term SRK is not used in TPM 2.0 spec, but is widely used // in other documents. // var srkTemplate = new TpmPublic(TpmAlgId.Sha256, // 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, null, // No policy new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), // No signing or decryption scheme 2048, 0), // 2048-bit RSA new Tpm2bPublicKeyRsa()); AuthValue childAuthVal = AuthValue.FromRandom(8); TssObject swKey = TssObject.Create(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.CreatePrimary(TpmRh.Owner, // In the owner-hierarchy new SensitiveCreate(null, null), // Empty auth-value srkTemplate, // Key template (params) null, // 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._AllowErrors() .EvictControl(TpmRh.Owner, srkHandle, srkHandle); if (tpm._LastCommandSucceeded()) { Console.WriteLine("Removed previous persistent SRK."); } // // Make the SRK NV-resident // tpm.EvictControl(TpmRh.Owner, keyHandle, srkHandle); Console.WriteLine("SRK is persistent now."); Console.WriteLine("\nStorageRootKey sample finished."); } // StorageRootKey()
/// <summary> /// Get the endorsement key from the TPM. If the key has not yet been set, a new one is generated /// </summary> /// <returns></returns> /// <remarks> /// Picked from https://github.com/Azure/azure-iot-sdk-csharp/blob/e1dd08eacd1caf58f3b318d8ad5ad94dde961d78/security/tpm/src/SecurityProviderTpmHsm.cs#L258-L324 /// </remarks> public static byte[] GetEndorsementKey() { TpmHandle ekHandle = new TpmHandle(TPM_20_EK_HANDLE); byte[] result = Array.Empty <byte>(); try { // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); using (var tpm = new Tpm2(tpmDevice)) { // Read EK from the TPM, temporarily allowing errors TpmPublic ekPub = tpm. _AllowErrors() .ReadPublic(ekHandle, out byte[] name, out byte[] qualifiedName); // if the last command did not succeed, we do not have an endorsement key yet, so create it if (!tpm._LastCommandSucceeded()) { // Get the real EK ready. TpmPublic ekTemplate = new TpmPublic( TpmAlgId.Sha256, ObjectAttr.FixedTPM | ObjectAttr.FixedParent | ObjectAttr.SensitiveDataOrigin | ObjectAttr.AdminWithPolicy | ObjectAttr.Restricted | ObjectAttr.Decrypt, new byte[] { 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa }, new RsaParms( new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0), new Tpm2bPublicKeyRsa(new byte[2048 / 8])); TpmHandle keyHandle = tpm.CreatePrimary( new TpmHandle(TpmHandle.RhEndorsement), new SensitiveCreate(), ekTemplate, Array.Empty <byte>(), Array.Empty <PcrSelection>(), out ekPub, out CreationData creationData, out byte[] creationHash, out TkCreation creationTicket); tpm.EvictControl(TpmHandle.RhOwner, keyHandle, ekHandle); tpm.FlushContext(keyHandle); } // Get the EK representation result = ekPub.GetTpm2BRepresentation(); } } catch { } return(result); }