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); }
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); }
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); }
/// <summary> /// Create a sealed-object primary that can be accessed with the given policy. SHA256 is assumed. /// </summary> /// <param name="tpm"></param> /// <param name="dataToSeal"></param> /// <param name="authValue"></param> /// <param name="policy"></param> /// <returns></returns> private static TpmHandle CreateSealedPrimaryObject(Tpm2 tpm, byte[] dataToSeal, byte[] authValue, byte[] policy) { ObjectAttr attrs = ObjectAttr.FixedTPM | ObjectAttr.FixedParent; if (authValue != null) { attrs |= ObjectAttr.UserWithAuth; } byte[] policyVal = policy ?? new byte[0]; var sealedInPublic = new TpmPublic(TpmAlgId.Sha256, attrs, policyVal, new KeyedhashParms(new NullSchemeKeyedhash()), new Tpm2bDigestKeyedhash()); // // Envelope for sealed data and auth // byte[] authVal = authValue ?? new byte[0]; var sealedInSensitive = new SensitiveCreate(authVal, dataToSeal); TkCreation creationTicket; byte[] creationHashSealed; TpmPublic sealedPublic; CreationData sealedCreationData; // // AuthValue encapsulates an authorization value: essentially a byte-array. // OwnerAuth is the owner authorization value of the TPM-under-test. We // assume that it (and other) auths are set to the default (null) value. // If running on a real TPM, which has been provisioned by Windows, this // value will be different. An administrator can retrieve the owner // authorization value from the registry. // var ownerAuth = new AuthValue(); // // Ask the TPM to create a primary containing the "sealed" data // TpmHandle primHandle = tpm[ownerAuth].CreatePrimary(TpmHandle.RhOwner, sealedInSensitive, sealedInPublic, new byte[0], new PcrSelection[0], out sealedPublic, out sealedCreationData, out creationHashSealed, out creationTicket); return(primHandle); }
public async Task <Tpm2CreateResponse> CreateAsync( TpmHandle parentHandle, SensitiveCreate inSensitive, TpmPublic inPublic, byte[] outsideInfo, PcrSelection[] creationPCR) { var inS = new Tpm2CreateRequest(parentHandle, inSensitive, inPublic, outsideInfo, creationPCR); var resp = new Tpm2CreateResponse(); await Task.Run(() => DispatchMethod(TpmCc.Create, inS, resp, 1, 0)); return(resp); }
public async Task <Tpm2CreateResponse> CreateAsync( TpmHandle parentHandle, SensitiveCreate inSensitive, TpmPublic inPublic, byte[] outsideInfo, PcrSelection[] creationPCR) { var inS = new Tpm2CreateRequest(parentHandle, inSensitive, inPublic, outsideInfo, creationPCR); TpmStructureBase outSBase = null; await Task.Run(() => DispatchMethod(TpmCc.Create, inS, typeof(Tpm2CreateResponse), out outSBase, 1, 0)); var outS = (Tpm2CreateResponse)outSBase; return(outS); }
/// <summary> /// Create a non-migratable RSA primary with the specified use-auth value and key size. /// </summary> /// <param name="parentAuth"></param> /// <param name="keyLen"></param> /// <param name="restricted"></param> /// <param name="useAuth"></param> /// <param name="parentHandle"></param> /// <param name="policy"></param> /// <returns></returns> public async Task <Tpm2CreateResponse> CreateRsaSigningAsync( TpmHandle parentHandle, AuthValue parentAuth, int keyLen, bool restricted, AuthValue useAuth, TpmHash policy = null) { ObjectAttr attr = ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicatable ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth; // Authorize with auth-data if (restricted) { attr |= ObjectAttr.Restricted; } var thePolicy = new byte[0]; if ((Object)policy != null) { thePolicy = policy; attr |= ObjectAttr.AdminWithPolicy; } var signKeyPubTemplate = new TpmPublic(H.NameHash, attr, thePolicy, new RsaParms(new SymDefObject(), // Key type and sig scheme H.RsaSigScheme, (ushort)keyLen, 0), new Tpm2bPublicKeyRsa()); // Auth-data for new key var sensCreate = new SensitiveCreate(useAuth, new byte[0]); // Create the key var newKey = await H.Tpm[parentAuth].CreateAsync(parentHandle, sensCreate, signKeyPubTemplate, new byte[0], new PcrSelection[0]); return(newKey); }
internal async Task <Tpm2CreatePrimaryResponse> CreatePrimaryRsaAsyncInternal( int keyLen, byte[] useAuth, byte[] policyAuth, PcrSelection[] pcrSel) { ObjectAttr attr = ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.SensitiveDataOrigin; var theUseAuth = new byte[0]; if (useAuth != null) { theUseAuth = useAuth; attr |= ObjectAttr.UserWithAuth; } var thePolicyAuth = new byte[0]; if (policyAuth != null) { thePolicyAuth = policyAuth; attr |= ObjectAttr.AdminWithPolicy; } var theSelection = new PcrSelection[0]; if (pcrSel != null) { theSelection = pcrSel; } var sensCreate = new SensitiveCreate(theUseAuth, new byte[0]); var parms = new TpmPublic(H.NameHash, attr, thePolicyAuth, new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), (ushort)keyLen, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); return(await H.Tpm.CreatePrimaryAsync(TpmRh.Owner, sensCreate, parms, outsideInfo, theSelection)); }
/// <summary> /// Create an RSA primary storage key in the storage hierarchy and return the key-handle /// to the caller. The key will be RSA2048 with a SHA256-name algorithm. The caller can /// provide user-auth. The caller is responsible for disposing of this key. /// </summary> /// <returns></returns> static TpmHandle CreateRsaPrimaryStorageKey(Tpm2 tpm, byte[] auth, out TpmPublic newKeyPub) { // // Creation parameters (no external data for TPM-created objects) // var sensCreate = new SensitiveCreate(auth, // Auth-data provided by the caller new byte[0]); // No external data (the TPM will create the new key). var parms = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Restricted | ObjectAttr.Decrypt | // Storage key ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, new byte[0], // No policy, and Storage key should be RSA + AES128 new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0), new Tpm2bPublicKeyRsa()); // // The following are returned by the TPM in CreatePrimary (and Create) // they are not used in this sample. // CreationData creationData; TkCreation creationTicket; byte[] creationHash; TpmHandle primHandle = tpm[_ownerAuth].CreatePrimary(TpmHandle.RhOwner, // In storage hierarchy sensCreate, // UserAuth parms, // Creation parms set above // // The following parameters influence the creation of the // creation-ticket. They are not used in this sample // new byte[0], // Null outsideInfo new PcrSelection[0], // Do not record PCR-state out newKeyPub, // Our outs out creationData, out creationHash, out creationTicket); return(primHandle); }
public async Task <Tpm2CreatePrimaryResponse> CreatePrimaryAsync( TpmHandle primaryHandle, SensitiveCreate inSensitive, TpmPublic inPublic, byte[] outsideInfo, PcrSelection[] creationPCR) { var inS = new Tpm2CreatePrimaryRequest { primaryHandle = primaryHandle, inSensitive = inSensitive, inPublic = inPublic, outsideInfo = outsideInfo, creationPCR = creationPCR }; TpmStructureBase outSBase = null; await Task.Run(() => DispatchMethod(TpmCc.CreatePrimary, inS, typeof(Tpm2CreatePrimaryResponse), out outSBase, 1, 1)); var outS = (Tpm2CreatePrimaryResponse)outSBase; return(outS); }
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); }
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
} // 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()
/// <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); }
/// <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); }