internal static void NVCounter(Tpm2 tpm) { TpmHandle nvHandle = TpmHandle.NV(3001); tpm._AllowErrors().NvUndefineSpace(TpmRh.Owner, nvHandle); tpm.NvDefineSpace(TpmRh.Owner, AuthValue.FromRandom(8), new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Counter | NvAttr.Authread | NvAttr.Authwrite, null, 8)); tpm.NvIncrement(nvHandle, nvHandle); byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); tpm.NvIncrement(nvHandle, nvHandle); nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var finalVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); if (finalVal != initVal + 1) { throw new Exception("NV-counter fail"); } Console.WriteLine("Incremented counter from {0} to {1}.", initVal, finalVal); tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); } //NVCounter
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); }
public static void SaveValueIntoTpm(int address, byte[] data, int length) { Tpm2Device tpmDevice; if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { tpmDevice = new TbsDevice(); } else { tpmDevice = new LinuxTpmDevice(); } tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); var ownerAuth = new AuthValue(); TpmHandle nvHandle = TpmHandle.NV(address); tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); AuthValue nvAuth = authValue; var nvPublic = new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authwrite | NvAttr.Authread, new byte[0], (ushort)length); tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth, nvPublic); tpm[nvAuth].NvWrite(nvHandle, nvHandle, data, 0); tpm.Dispose(); }
/// <summary> /// This sample shows the use of HMAC sessions to authorize TPM actions. /// HMAC sessions may be bound/unbound and seeded/unseeded. This sample /// illustrates an unseeded and unbound session. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static void HmacUnboundUnseeded(Tpm2 tpm) { // // Create a hash-sequence with a random authorization value // TpmHandle hashHandle = tpm.HashSequenceStart(AuthValue.FromRandom(8), TpmAlgId.Sha256); // // Commands with the Ex modifier are library-provided wrappers // around TPM functions to make programming easier. This version // of StartAuthSessionEx calls StartAuthSession configured to // create an unbound and unseeded auth session with the auth-value // provided here. // AuthSession s0 = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256); // // The following calls show the use of the HMAC session in authorization. // The session to use is communicated as a parameter in the [] overloaded // function and the auth-value is that set during HMAC session creation. // It picks up the appropriate auth value from the handle used in the command // (hashHandle in this case). // TkHashcheck validate; tpm[s0].SequenceUpdate(hashHandle, new byte[] { 0, 2, 1 }); byte[] hashedData = tpm[s0].SequenceComplete(hashHandle, new byte[] { 2, 3, 4 }, TpmRh.Owner, out validate); Console.WriteLine("Hashed data (HMAC authorized sequence): " + BitConverter.ToString(hashedData)); tpm.FlushContext(s0); }
/// <summary> /// Demonstrate use of NV counters. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> void NVCounter(Tpm2 tpm) { // // 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. // TpmHandle nvHandle = TpmHandle.NV(3001); // // Clean up any slot that was left over from an earlier run // tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); // // Scenario 2 - A NV-counter // tpm.NvDefineSpace(TpmRh.Owner, AuthValue.FromRandom(8), new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Counter | NvAttr.Authread | NvAttr.Authwrite, null, 8)); // // Must write before we can read // tpm.NvIncrement(nvHandle, nvHandle); // // Read the current value // byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); // // Increment // tpm.NvIncrement(nvHandle, nvHandle); // // Read again and see if the answer is what we expect // nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var finalVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); if (finalVal != initVal + 1) { throw new Exception("NV-counter fail"); } this.textBlock.Text += "Incremented counter from " + initVal.ToString() + " to " + finalVal.ToString() + ". "; // // Clean up // tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); }
internal static void NVReadWrite(Tpm2 tpm) { // // 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(); TpmHandle nvHandle = TpmHandle.NV(3001); // // Clean up any slot that was left over from an earlier run // tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); // // Scenario 1 - write and read a 32-byte NV-slot // AuthValue nvAuth = AuthValue.FromRandom(8); tpm.NvDefineSpace(TpmRh.Owner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authread | NvAttr.Authwrite, null, 32)); // // Write some data // var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; tpm.NvWrite(nvHandle, nvHandle, nvData, 0); // // And read it back // byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, (ushort)nvData.Length, 0); // // Is it correct? // bool correct = nvData.SequenceEqual(nvRead); if (!correct) { throw new Exception("NV data was incorrect."); } Console.WriteLine("NV data written and read."); // // And clean up // tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); }
public string GetUserName(string username, string password, string service) { AuthValue authValue = _auths[new AuthKey(username, password, service)] as AuthValue; if (authValue != null && !string.IsNullOrEmpty(authValue.ReturnedUsername)) { return(authValue.ReturnedUsername); } return(username); }
/// <summary> /// Use a hash sequence to concatenate and hash data that is bigger then /// the communication buffer to the TPM. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static void HashSequence(Tpm2 tpm) { // // Create a hash sequence-object based on SHA-1 and with a 10 byte auth-value // randomly generated by TSS.Net. // This command returns a uint handle value encapsulated in TpmHandle class. // TpmHandle hashHandle = tpm.HashSequenceStart(AuthValue.FromRandom(10), TpmAlgId.Sha1); // // Hash some data using the hash sequence object just created. // It is normally the case that the use of TPM internal objects // must be "authorized" by proof-of-knowledge of the authorization // value that was set when the object was created. Authorization // is communicated using a TPM construct called a "session." // Every handle that requires authorization requires a session // that conveys knowledge of the auth-value (or other authorization). // // The specific style of session used here is a "password authorization // session, or PWAP session, where the password is communicated // in plain text. // // Three styles of session creation are demonstrated. // Style 1 (not preferred). The method _SetSessions() tells TSS.Net // to use the authorization value authVal in a PWAP session // tpm.SequenceUpdate(hashHandle, new byte[] { 0, 1 }); // // Style 2 (not preferred). The method _SetSessions() returns "this" // so the two lines above can be condensed. tpm._SetSessions(authVal); // tpm.SequenceUpdate(hashHandle, new byte[] { 2, 3 }); // // Style 3 - RECOMMENDED // In the command sequence below the [authValue] construct is // NOT an array-accessor. Instead it is shorthand to associate // a list of authorization sessions with the command (one session // in this case. // tpm.SequenceUpdate(hashHandle, new byte[] { 4, 5 }); tpm.SequenceUpdate(hashHandle, new byte[] { 6, 7 }); // // Add the final data block // TkHashcheck validation; byte[] hashedData = tpm.SequenceComplete(hashHandle, new byte[] { 4, 5 }, TpmRh.Owner, out validation); Console.WriteLine("Hashed data (Sequence): " + BitConverter.ToString(hashedData)); }
/// <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 string GetCredentialsIfValid(string username, string password, string service) { if (IsValid(username, password, service)) { AuthValue authValue = _auths[new AuthKey(username, password, service)] as AuthValue; if (authValue != null) { string auth = authValue.AuthString; if (auth != null) { return("GoogleLogin auth=" + auth); } } } return(null); }
public bool IsValid(string username, string password, string service) { AuthValue authValue = _auths[new AuthKey(username, password, service)] as AuthValue; if (authValue == null) { return(false); } TimeSpan age = DateTimeHelper.UtcNow - authValue.DateCreatedUtc; if (age < TimeSpan.Zero || age > TimeSpan.FromHours(23)) { return(false); } return(true); }
public static byte[] ReadValueFromTpm(int address, int length) { Tpm2Device tpmDevice; if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { tpmDevice = new TbsDevice(); } else { tpmDevice = new LinuxTpmDevice(); } tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); TpmHandle nvHandle = TpmHandle.NV(address); AuthValue nvAuth = authValue; byte[] newData = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)length, 0); tpm.Dispose(); return(newData); }
/// <summary> /// This sample demonstrates the creation and use of TPM NV memory storage. /// NOTE: Only reads from the TPM NV Memory are supported on the EFLOW VM. /// In order to properly run through this sample, you must have previously /// setup and written to NV Index 3001 on the Windows Host. See README.md /// for details. /// </summary> /// <param name="tpm">Reference to TPM object.</param> static void NVReadOnly(Tpm2 tpm) { // // 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. // int nvIndex = 3001; // Arbitrarily Chosen ushort dataLength = 8; // Length from the data stored into the TPM TpmHandle nvHandle = TpmHandle.NV(nvIndex); AuthValue nvAuth = new AuthValue(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); Console.WriteLine("Reading NVIndex {0}.", nvIndex); byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, dataLength, 0); Console.WriteLine("Read Bytes: {0}", BitConverter.ToString(nvRead)); }
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); }
public static byte[] ReadData(int tailleData) { Tpm2Device tpmDevice; if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { tpmDevice = new TbsDevice(); } else { tpmDevice = new LinuxTpmDevice(); } tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); TpmHandle nvHandle = TpmHandle.NV(indexTMPSlot); AuthValue nvAuth = nvAuthValue; byte[] newData = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)tailleData, 0); tpm.Dispose(); return(newData); }
/// <summary> /// This sample illustrates the use of a simple TPM policy session. The policy demands /// PCR 1, 2, 3 set to current values, and the command be issued at locality zero. /// </summary> static void SimplePolicy(Tpm2 tpm) { Console.WriteLine("Simple Policy sample:"); // // Check if policy commands are implemented by TPM. This list // could include all the other used commands as well. // This check here makes sense for policy commands, because // usually a policy has to be executed in full. If a command // out of the chain of policy commands is not implemented in the // TPM, the policy cannot be satisfied. // var usedCommands = new[] { TpmCc.PolicyPCR }; foreach (var commandCode in usedCommands) { if (!tpm.Helpers.IsImplemented(commandCode)) { Console.WriteLine("Cancel Simple Policy sample, because command {0} is not implemented by TPM.", commandCode); return; } } // // First read the PCR values // var pcrs = new uint[] { 1, 2, 3 }; var sel = new PcrSelection(TpmAlgId.Sha, pcrs); PcrSelection[] selOut; Tpm2bDigest[] pcrValues; tpm.PcrRead(new[] { sel }, out selOut, out pcrValues); Console.WriteLine("PCR Selections:\n"); foreach (PcrSelection s in selOut) { Console.WriteLine(s.ToString()); } Console.WriteLine("PCR Values:\n"); foreach (var v in pcrValues) { Console.WriteLine(v.ToString()); } // // Save the current PCR values in a convenient data structure // var expectedPcrVals = new PcrValueCollection(selOut, pcrValues); // // Tpm2Lib encapsulates a set of policy assertions as the PolicyTree class. // var policy = new PolicyTree(TpmAlgId.Sha256); // // Set the policy: Locality AND PolicyPcr. This form of CreatePOlicy // only creates a single chain. Note that all well-formed policy chains // must have leaf identifiers. Leaf identifiers are just strings that // are unique in a policy so that the framework can be told what // chain to evaluate. // policy.Create( new PolicyAce[] { new TpmPolicyPcr(expectedPcrVals), "leaf" } ); // // Ask Tpm2Lib for the expected policy-hash for this policy // TpmHash expectedPolicyHash = policy.GetPolicyDigest(); // // Create a sealed primary object with the policy-hash we just calculated // var dataToSeal = new byte[] { 1, 2, 3, 4, 5, 4, 3, 2, 1 }; TpmHandle primHandle = CreateSealedPrimaryObject(tpm, dataToSeal, null, expectedPolicyHash.HashData); // // Create an actual TPM policy session to evaluate the policy // AuthSession session = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256); // // Run the policy on the TPM // session.RunPolicy(tpm, policy, "leaf"); // // Unseal the object // byte[] unsealedData = tpm[session].Unseal(primHandle); Console.WriteLine("Unsealed data: " + BitConverter.ToString(unsealedData)); // // Change a PCR and make sure that the policy no longer works // var nullAuth = new AuthValue(); tpm[nullAuth].PcrEvent(TpmHandle.Pcr(3), new byte[] { 1, 2, 3 }); tpm.PolicyRestart(session.Handle); // // Run the policy again - an error will be returned // TpmRc policyError = session.RunPolicy(tpm, policy, null, true); // // And the session will be unusable // unsealedData = tpm[session]._ExpectError(TpmRc.PolicyFail).Unseal(primHandle); // // Clean up // tpm.FlushContext(session.Handle); tpm.FlushContext(primHandle); }
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
public void EnsureLoggedIn(string username, string password, string service, bool showUi, string uri) { try { if (IsValid(username, password, service)) { return; } string captchaToken = null; string captchaValue = null; string source = string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", ApplicationEnvironment.CompanyName, ApplicationEnvironment.ProductName, ApplicationEnvironment.ProductVersion); while (true) { GoogleLoginRequestFactory glrf = new GoogleLoginRequestFactory(username, password, service, source, captchaToken, captchaValue); if (captchaToken != null && captchaValue != null) { captchaToken = null; captchaValue = null; } HttpWebResponse response; try { response = RedirectHelper.GetResponse(uri, new RedirectHelper.RequestFactory(glrf.Create)); } catch (WebException we) { response = (HttpWebResponse)we.Response; if (response == null) { Trace.Fail(we.ToString()); if (showUi) { showUi = false; ShowError(MessageId.WeblogConnectionError, we.Message); } throw; } } if (response.StatusCode == HttpStatusCode.OK) { Hashtable ht = ParseAuthResponse(response.GetResponseStream()); if (ht.ContainsKey("Auth")) { _auths[new AuthKey(username, password, service)] = new AuthValue((string)ht["Auth"], ht["YouTubeUser"] as string); return; } else { if (showUi) { showUi = false; ShowError(MessageId.GoogleAuthTokenNotFound); } throw new BlogClientInvalidServerResponseException(uri, "No Auth token was present in the response.", string.Empty); } } else if (response.StatusCode == HttpStatusCode.Forbidden) { // login failed Hashtable ht = ParseAuthResponse(response.GetResponseStream()); string error = ht["Error"] as string; if (error != null && error == "CaptchaRequired") { captchaToken = (string)ht["CaptchaToken"]; string captchaUrl = (string)ht["CaptchaUrl"]; GDataCaptchaHelper helper = new GDataCaptchaHelper( new Win32WindowImpl(BlogClientUIContext.ContextForCurrentThread.Handle), captchaUrl); BlogClientUIContext.ContextForCurrentThread.Invoke(new ThreadStart(helper.ShowCaptcha), null); if (helper.DialogResult == DialogResult.OK) { captchaValue = helper.Reply; continue; } else { throw new BlogClientOperationCancelledException(); } } if (showUi) { if (error == "NoLinkedYouTubeAccount") { if (DisplayMessage.Show(MessageId.YouTubeSignup, username) == DialogResult.Yes) { ShellHelper.LaunchUrl(GLink.Instance.YouTubeRegister); } return; } showUi = false; if (error == "BadAuthentication") { ShowError(MessageId.LoginFailed, ApplicationEnvironment.ProductNameQualified); } else { ShowError(MessageId.BloggerError, TranslateError(error)); } } throw new BlogClientAuthenticationException(error, TranslateError(error)); } else { if (showUi) { showUi = false; ShowError(MessageId.BloggerError, response.StatusCode + ": " + response.StatusDescription); } throw new BlogClientAuthenticationException(response.StatusCode + "", response.StatusDescription); } } } catch (BlogClientOperationCancelledException) { throw; } catch (Exception e) { Trace.WriteLine(e.ToString()); if (showUi) { ShowError(MessageId.UnexpectedErrorLogin, e.Message); } throw; } }
/// <summary> /// This sample demonstrates the creation and use of TPM NV-storage /// </summary> /// <param name="tpm">Reference to TPM object.</param> static void NvReadWriteWithOwnerAuth(Tpm2 tpm) { if (tpm._GetUnderlyingDevice().GetType() != typeof(TbsDevice)) { return; } int nvIndex = 3001; // arbitrarely chosen TpmHandle nvHandle = TpmHandle.NV(nvIndex); // // The NV auth value is required to read and write the NV slot after it has been // created. Because this test is supposed to be used in different conditions: // first as Administrator to create the NV slot, and then as Standard User to read // it, the test uses a well defined authorization value. // // In a real world scenario, tha authorization value should be bigger and random, // or include a policy with better policy. For example, the next line could be // substitued with: // AuthValue nvAuth = AuthValue.FromRandom(32); // which requires storage of the authorization value for reads. // AuthValue nvAuth = new AuthValue(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { Console.WriteLine("Running as Administrator. Deleting and re-creating NV entry."); // // 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. // byte[] ownerAuth; if (GetOwnerAuthFromOS(out ownerAuth)) { tpm.OwnerAuth = ownerAuth; } else { Console.WriteLine("Could not retrieve owner auth from registry. Trying empty auth."); } bool failed; do { failed = false; // // Clean up any slot that was left over from an earlier run. // Only clean up the nvIndex if data from a possible previous invocation // should be deleted. // // Another approach could be to invoke NvDefineSpace, check if the call // returns TpmRc.NvDefined, then try a read with the known/stored // NV authorization value. If that succeeds, the likelyhood that this // NV index already contains valid data is high. // tpm._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // // Define the NV slot. The authorization passed in as nvAuth will be // needed for future NvRead and NvWrite access. (Attribute Authread // specifies that authorization is required to read. Attribute Authwrite // specifies that authorization is required to write.) // try { tpm.NvDefineSpace(TpmHandle.RhOwner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authread | NvAttr.Authwrite, new byte[0], 32)); } catch (TpmException e) { if (e.RawResponse == TpmRc.NvDefined) { nvIndex++; nvHandle = TpmHandle.NV(nvIndex); Console.WriteLine("NV index already taken, trying next."); failed = true; } else { Console.WriteLine("Exception {0}\n{1}", e.Message, e.StackTrace); return; } } // // Store successful nvIndex and nvAuth, so next invocation as client // knows which index to read. For instance in registry. Storage of // nvAuth is only required if attributes of NvDefineSpace include // NvAttr.Authread. // } while (failed); // // Now that NvDefineSpace succeeded, write some random data (nvData) to // nvIndex. Note that NvDefineSpace defined the NV slot to be 32 bytes, // so a NvWrite (nor NvRead) should try to write more than that. // If more data has to be written to the NV slot, NvDefineSpace should // be adjusted accordingly. // Console.WriteLine("Writing NVIndex {0}.", nvIndex); tpm[nvAuth].NvWrite(nvHandle, nvHandle, nvData, 0); Console.WriteLine("Written: {0}", BitConverter.ToString(nvData)); } // // Read the data back. // Console.WriteLine("Reading NVIndex {0}.", nvIndex); byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)nvData.Length, 0); Console.WriteLine("Read: {0}", BitConverter.ToString(nvRead)); // // Optional: compare if data read from NV slot is the same as data // written to it. // We can only compare if running as admin, because the data has been // generated with admin account. // if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { bool correct = nvData.SequenceEqual(nvRead); if (!correct) { throw new Exception("NV data was incorrect."); } } Console.WriteLine("NV access complete."); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { // // Optional: clean up. // If NvIndex should stick around, skip this code. // //tpm.NvUndefineSpace(TpmHandle.RhOwner, nvHandle); } }
/// <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."); }
static void Sign() { using (Tpm2Device tpmDevice = Examples.GetSimulator()) { tpmDevice.Connect(); using (var tpm = new Tpm2(tpmDevice)) { if (tpmDevice is TcpTpmDevice) { tpmDevice.PowerCycle(); } CreateRsaPrimaryKey(tpm, tpmDevice is TcpTpmDevice); var keyTemplate = new TpmPublic(TpmAlgId.Sha1, // Name algorithm ObjectAttr.UserWithAuth | ObjectAttr.Sign | // Signing key ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-migratable ObjectAttr.SensitiveDataOrigin, null, // No policy new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha1), 2048, 0), new Tpm2bPublicKeyRsa()); var ownerAuth = new AuthValue(); var keyAuth = new byte[] { 1, 2, 3 }; TpmPublic keyPublic; CreationData creationData; TkCreation creationTicket; byte[] creationHash; TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary( TpmRh.Owner, // In the owner-hierarchy new SensitiveCreate(keyAuth, null), // With this auth-value keyTemplate, // Describes key null, // Extra data for creation ticket new PcrSelection[0], // Non-PCR-bound out keyPublic, // PubKey and attributes out creationData, out creationHash, out creationTicket); // Not used here // // Print out text-versions of the public key just created // Console.WriteLine("New public key\n" + keyPublic.ToString()); byte[] message = Encoding.Unicode.GetBytes("ABC"); TpmHash digestToSign = TpmHash.FromData(TpmAlgId.Sha1, message); var signature = tpm[keyAuth].Sign(keyHandle, // Handle of signing key digestToSign, // Data to sign null, // Use key's scheme TpmHashCheck.Null()) as SignatureRsassa; // // Print the signature. // Console.WriteLine("Signature: " + BitConverter.ToString(signature.sig)); bool sigOk = keyPublic.VerifySignatureOverData(message, signature); if (!sigOk) { throw new Exception("Signature did not validate."); } Console.WriteLine("Verified signature with TPM2lib (software implementation)."); TpmHandle pubHandle = tpm.LoadExternal(null, keyPublic, TpmRh.Owner); tpm.VerifySignature(pubHandle, digestToSign, signature); Console.WriteLine("Verified signature with TPM."); } } }
} // 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()
public static void Main(string[] args) { try { // Keypair Generator RsaKeyPairGenerator kpGenerator = new RsaKeyPairGenerator(); kpGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); // Create a keypair AsymmetricCipherKeyPair keys = kpGenerator.GenerateKeyPair(); // Connect to the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); Tpm2 tpm = new Tpm2(tpmDevice); AuthValue ownerAuth = new AuthValue(); // Create a handle based on the hash of the cert thumbprint ushort hashcode = (ushort)keys.GetHashCode(); TpmHandle nvHandle = TpmHandle.NV(hashcode); // Clean up the slot tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // Export serial number, the "valid from" date (the cert will be valid for 1 year, so no need to store that date, too!), the size of the keys blob and the keys themselves TextWriter textWriter = new StringWriter(); PemWriter pemWriter = new PemWriter(textWriter); pemWriter.WriteObject(keys); pemWriter.Writer.Flush(); byte[] rawData = Encoding.ASCII.GetBytes(textWriter.ToString().ToCharArray()); ushort size = (ushort)(sizeof(long) + sizeof(long) + rawData.Length + sizeof(int) + 64); ushort offset = 0; // Define a slot for the keys, which is 64 bytes bigger than we need as we write in 64-byte chunks tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, ownerAuth, new NvPublic(nvHandle, TpmAlgId.Sha256, NvAttr.Authread | NvAttr.Authwrite, new byte[0], size)); // Write the serial number tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(BigInteger.ProbablePrime(120, new Random()).LongValue), offset); offset += sizeof(long); // Write the "valid from" date (today) in FileTime format tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(DateTime.Today.ToFileTime()), offset); offset += sizeof(long); // Write the size of the keys tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(rawData.Length), offset); offset += sizeof(int); // Write the keys themselves (in 64-byte chunks) byte[] dataToWrite = new byte[64]; int index = 0; while (index < rawData.Length) { for (int i = 0; i < 64; i++) { if (index < rawData.Length) { dataToWrite[i] = rawData[index]; index++; } else { // fill the rest of the buffer with zeros dataToWrite[i] = 0; } } tpm[ownerAuth].NvWrite(nvHandle, nvHandle, dataToWrite, offset); offset += 64; } tpm.Dispose(); Console.WriteLine("Keys successfully generated and copied to TPM. Hashcode=" + hashcode.ToString()); } catch (Exception e) { Console.WriteLine("Could not generate or copy keys to TPM: " + e.Message); } }
/// <summary> /// Some policies can be evaluated solely from public parts of the policy. /// Others needs a private keyholder to sign some data. Tpm2Lib provides /// a callback facility for these cases. /// /// This second sample illustrates the use of callbacks to provide authData. /// </summary> /// <param name="tpm">Reference to the TPM object to use.</param> static void PolicyEvaluationWithCallback2(Tpm2 tpm) { Console.WriteLine("Policy evaluation with callback sample 2."); // // Check if policy commands are implemented by TPM. This list // could include all the other used commands as well. // This check here makes sense for policy commands, because // usually a policy has to be executed in full. If a command // out of the chain of policy commands is not implemented in the // TPM, the policy cannot be satisfied. // var usedCommands = new[] { TpmCc.PolicySecret, TpmCc.PolicyGetDigest, TpmCc.PolicyRestart }; foreach (var commandCode in usedCommands) { if (!tpm.Helpers.IsImplemented(commandCode)) { Console.WriteLine("Cancel Policy evaluation callback 2 sample, because command {0} is not implemented by TPM.", commandCode); return; } } // // Create an object with an AuthValue. The type of object is immaterial // (it can even be the owner). In order to construct the policy we will // need the name and to prove that we know the AuthVal. // _publicAuthorizationValue = AuthValue.FromRandom(10); var dataToSeal = new byte[] { 1, 2, 3, 4 }; _publicSealedObjectHandle = CreateSealedPrimaryObject(tpm, dataToSeal, _publicAuthorizationValue, null); byte[] objectName = _publicSealedObjectHandle.Name; var policy = new PolicyTree(TpmAlgId.Sha256); policy.Create( new PolicyAce[] { new TpmPolicySecret(objectName, // Name of the obj that we will prove authData true, // Include nonceTpm new byte[0], // Not bound to a cpHash new byte[0], // Null policyRef 0), // Never expires (in this session) "leaf" // Name for this ACE }); TpmHash expectedHash = policy.GetPolicyDigest(); // // We are about to ask for the session to be evaluated, but in order // to process TpmPolicySecret the caller will have to prove knowledge of // the authValue associated with objectName. In this first version we // do this with PWAP. // policy.SetPolicySecretCallback(PolicySecretCallback); AuthSession authSession = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256); authSession.RunPolicy(tpm, policy, "leaf"); // // The policy evaluated. But is the digest what we expect? // byte[] digestIs = tpm.PolicyGetDigest(authSession.Handle); if (expectedHash != digestIs) { throw new Exception("Incorrect PolicyDigest"); } // // And now do the same thing but with an HMAC session. // _sharedTpm = tpm; tpm.PolicyRestart(authSession.Handle); policy.SetPolicySecretCallback(PolicySecretCallback2); authSession.RunPolicy(tpm, policy, "leaf"); _sharedTpm = null; // // The policy evaluated. But is the digest what we expect? // digestIs = tpm.PolicyGetDigest(authSession.Handle); if (expectedHash != digestIs) { throw new Exception("Incorrect PolicyDigest"); } Console.WriteLine("TpmPolicySignature evaluated."); tpm.FlushContext(authSession.Handle); }
/// <summary> /// This sample demonstrates the creation of a signing "primary" key and use of this /// key to sign data, and use of the TPM and TSS.Net to validate the signature. /// </summary> /// <param name="args">Arguments to this program.</param> static void Main(string[] args) { // // Parse the program arguments. If the wrong arguments are given or // are malformed, then instructions for usage are displayed and // the program terminates. // string tpmDeviceName; if (!ParseArguments(args, out tpmDeviceName)) { WriteUsage(); return; } try { // // Create the device according to the selected connection. // Tpm2Device tpmDevice; switch (tpmDeviceName) { case DeviceSimulator: tpmDevice = new TcpTpmDevice(DefaultSimulatorName, DefaultSimulatorPort); break; case DeviceWinTbs: tpmDevice = new TbsDevice(); break; default: throw new Exception("Unknown device selected."); } // // Connect to the TPM device. This function actually establishes the // connection. // tpmDevice.Connect(); // // Pass the device object used for communication to the TPM 2.0 object // which provides the command interface. // var tpm = new Tpm2(tpmDevice); if (tpmDevice is TcpTpmDevice) { // // If we are using the simulator, we have to do a few things the // firmware would usually do. These actions have to occur after // the connection has been established. // tpmDevice.PowerCycle(); tpm.Startup(Su.Clear); } // // 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(); // // The TPM needs a template that describes the parameters of the key // or other object to be created. The template below instructs the TPM // to create a new 2048-bit non-migratable signing key. // var keyTemplate = new TpmPublic(TpmAlgId.Sha1, // Name algorithm ObjectAttr.UserWithAuth | ObjectAttr.Sign | // Signing key ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-migratable ObjectAttr.SensitiveDataOrigin, null, // No policy new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha1), 2048, 0), new Tpm2bPublicKeyRsa()); // // Authorization for the key we are about to create. // var keyAuth = new byte[] { 1, 2, 3 }; TpmPublic keyPublic; CreationData creationData; TkCreation creationTicket; byte[] creationHash; // // Ask the TPM to create a new primary RSA signing key. // TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary( TpmRh.Owner, // In the owner-hierarchy new SensitiveCreate(keyAuth, null), // With this auth-value keyTemplate, // Describes key null, // Extra data for creation ticket new PcrSelection[0], // Non-PCR-bound out keyPublic, // PubKey and attributes out creationData, out creationHash, out creationTicket); // Not used here // // Print out text-versions of the public key just created // Console.WriteLine("New public key\n" + keyPublic.ToString()); // // Use the key to sign some data // byte[] message = Encoding.Unicode.GetBytes("ABC"); TpmHash digestToSign = TpmHash.FromData(TpmAlgId.Sha1, message); // // A different structure is returned for each signing scheme, // so cast the interface to our signature type (see third argument). // // As an alternative, 'signature' can be of type ISignatureUnion and // cast to SignatureRssa whenever a signature specific type is needed. // var signature = tpm[keyAuth].Sign(keyHandle, // Handle of signing key digestToSign, // Data to sign null, // Use key's scheme TpmHashCheck.Null()) as SignatureRsassa; // // Print the signature. // Console.WriteLine("Signature: " + BitConverter.ToString(signature.sig)); // // Use the TPM library to validate the signature // bool sigOk = keyPublic.VerifySignatureOverData(message, signature); if (!sigOk) { throw new Exception("Signature did not validate."); } Console.WriteLine("Verified signature with TPM2lib (software implementation)."); // // Load the public key into another slot in the TPM and then // use the TPM to validate the signature // TpmHandle pubHandle = tpm.LoadExternal(null, keyPublic, TpmRh.Owner); tpm.VerifySignature(pubHandle, digestToSign, signature); Console.WriteLine("Verified signature with TPM."); // // The default behavior of Tpm2Lib is to create an exception if the // signature does not validate. If an error is expected the library can // be notified of this, or the exception can be turned into a value that // can be later queried. The following are examples of this. // signature.sig[0] ^= 1; tpm._ExpectError(TpmRc.Signature) .VerifySignature(pubHandle, digestToSign, signature); if (tpm._GetLastResponseCode() != TpmRc.Signature) { throw new Exception("TPM returned unexpected return code."); } Console.WriteLine("Verified that invalid signature causes TPM_RC_SIGNATURE return code."); // // Clean up of used handles. // tpm.FlushContext(keyHandle); tpm.FlushContext(pubHandle); // // (Note that serialization is not supported on WinRT) // // Demonstrate the use of XML persistence by saving keyPublic to // a file and making a copy by reading it back into a new object // // NOTE: 12-JAN-2016: May be removing support for policy // serialization. We'd like to get feedback on whether // this is a desirable feature and should be retained. // // { // const string fileName = "sample.xml"; // string xmlVersionOfObject = keyPublic.GetXml(); // keyPublic.XmlSerializeToFile(fileName); // var copyOfPublic = TpmStructureBase.XmlDeserializeFromFile<TpmPublic>(fileName); // // // // // Demonstrate Tpm2Lib support of TPM-structure equality operators // // // if (copyOfPublic != keyPublic) // { // Console.WriteLine("Library bug persisting data."); // } // } // // // Clean up. // tpm.Dispose(); } catch (Exception e) { Console.WriteLine("Exception occurred: {0}", e.Message); } Console.WriteLine("Press Any Key to continue."); Console.ReadLine(); }
/// <summary> /// This sample demonstrates the creation and use of a storage root key that /// behaves like the Storage Root Key (SRK) defined in TPM1.2. /// To do this we need to create a new primary, and then use EvictControl /// to make it NV-resident. /// </summary> /// <param name="tpm">Reference to TPM object</param> static void StorageRootKey(Tpm2 tpm) { // // This template asks the TPM to create an 2048 bit RSA storage key // with an associated AES key for symmetric data protection. The term // "SRKs" is not used in TPM2.0, but we use it here to // not // var srkTemplate = new TpmPublic(TpmAlgId.Sha1, // Name algorithm ObjectAttr.Restricted | // Storage keys must be restricted ObjectAttr.Decrypt | // Storage keys are Decrypt keys ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable (like 1.2) ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, new byte[0], // No policy new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), // No signature 2048, 0), // 2048-bit RSA new Tpm2bPublicKeyRsa()); // // Authorization for the key we are about to create // var srkAuth = new byte[0]; AuthValue childAuthVal = AuthValue.FromRandom(8); TssObject swKey = TssObject.CreateStorageParent(srkTemplate, childAuthVal); TpmPublic srkPublic; CreationData srkCreationData; TkCreation srkCreationTicket; byte[] srkCreationHash; // // Ask the TPM to create a new primary RSA/AES primary storage key // TpmHandle keyHandle = tpm[_ownerAuth].CreatePrimary( TpmHandle.RhOwner, // In the owner-hierarchy new SensitiveCreate(srkAuth, new byte[0]), // With this auth-value srkTemplate, // Describes key new byte[0], // For creation ticket new PcrSelection[0], // For creation ticket out srkPublic, // Out pubKey and attrs out srkCreationData, // Not used here out srkCreationHash, // Ibid out srkCreationTicket); // Ibid // // print out text-versions of the public key just created // Console.WriteLine("New SRK public key\n" + srkPublic.ToString()); // // The caller provides the handle for persistent keys // TpmHandle srkHandle = TpmHandle.Persistent(0x5000); // // Ae will make the "SRK" persistent in an NV-slot, so clean up anything // that is already there // tpm[_ownerAuth]._AllowErrors().EvictControl(TpmHandle.RhOwner, srkHandle, srkHandle); TpmRc lastError = tpm._GetLastResponseCode(); // // Make the SRK NV-resident // tpm[_ownerAuth].EvictControl(TpmHandle.RhOwner, keyHandle, srkHandle); Console.WriteLine("SRK is persistent now."); }
public void EnsureLoggedIn(string username, string password, string service, bool showUi, string uri) { try { if (IsValid(username, password, service)) return; string captchaToken = null; string captchaValue = null; string source = string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", ApplicationEnvironment.CompanyName, ApplicationEnvironment.ProductName, ApplicationEnvironment.ProductVersion); while (true) { GoogleLoginRequestFactory glrf = new GoogleLoginRequestFactory(username, password, service, source, captchaToken, captchaValue); if (captchaToken != null && captchaValue != null) { captchaToken = null; captchaValue = null; } HttpWebResponse response; try { response = RedirectHelper.GetResponse(uri, new RedirectHelper.RequestFactory(glrf.Create)); } catch (WebException we) { response = (HttpWebResponse)we.Response; if (response == null) { Trace.Fail(we.ToString()); if (showUi) { showUi = false; ShowError(MessageId.WeblogConnectionError, we.Message); } throw; } } if (response.StatusCode == HttpStatusCode.OK) { Hashtable ht = ParseAuthResponse(response.GetResponseStream()); if (ht.ContainsKey("Auth")) { _auths[new AuthKey(username, password, service)] = new AuthValue((string)ht["Auth"], ht["YouTubeUser"] as string); return; } else { if (showUi) { showUi = false; ShowError(MessageId.GoogleAuthTokenNotFound); } throw new BlogClientInvalidServerResponseException(uri, "No Auth token was present in the response.", string.Empty); } } else if (response.StatusCode == HttpStatusCode.Forbidden) { // login failed Hashtable ht = ParseAuthResponse(response.GetResponseStream()); string error = ht["Error"] as string; if (error != null && error == "CaptchaRequired") { captchaToken = (string)ht["CaptchaToken"]; string captchaUrl = (string)ht["CaptchaUrl"]; GDataCaptchaHelper helper = new GDataCaptchaHelper( new Win32WindowImpl(BlogClientUIContext.ContextForCurrentThread.Handle), captchaUrl); BlogClientUIContext.ContextForCurrentThread.Invoke(new ThreadStart(helper.ShowCaptcha), null); if (helper.DialogResult == DialogResult.OK) { captchaValue = helper.Reply; continue; } else { throw new BlogClientOperationCancelledException(); } } if (showUi) { if (error == "NoLinkedYouTubeAccount") { if (DisplayMessage.Show(MessageId.YouTubeSignup, username) == DialogResult.Yes) { ShellHelper.LaunchUrl(GLink.Instance.YouTubeRegister); } return; } showUi = false; if (error == "BadAuthentication") { ShowError(MessageId.LoginFailed, ApplicationEnvironment.ProductNameQualified); } else { ShowError(MessageId.BloggerError, TranslateError(error)); } } throw new BlogClientAuthenticationException(error, TranslateError(error)); } else { if (showUi) { showUi = false; ShowError(MessageId.BloggerError, response.StatusCode + ": " + response.StatusDescription); } throw new BlogClientAuthenticationException(response.StatusCode + "", response.StatusDescription); } } } catch (BlogClientOperationCancelledException) { throw; } catch (Exception e) { Trace.WriteLine(e.ToString()); if (showUi) { ShowError(MessageId.UnexpectedErrorLogin, e.Message); } throw; } }
/// <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