public static byte[] SafeNvRead(Tpm2 tpm, ushort maxNvOpSize, TpmHandle nvHandle, ushort size, ushort nvOffset = 0) { byte[] contents = new byte[size]; for (ushort offset = 0; offset < size; offset += maxNvOpSize, nvOffset += maxNvOpSize) { var chunkSize = size - offset < maxNvOpSize ? size - offset : maxNvOpSize; var chunk = tpm.NvRead(nvHandle, nvHandle, (ushort)chunkSize, nvOffset); Array.Copy(chunk, 0, contents, offset, chunkSize); } return(contents); }
/// <summary> /// Signs the data using the previously activated identity key. /// </summary> /// <remarks> /// Calls to the TPM library can potentially return a <see cref="TssException"/> or a <see cref="TpmException"/> /// if your TPM hardware does not support the relevant API call. /// </remarks> /// <param name="data">The data to be signed.</param> /// <returns>The signed data.</returns> public override byte[] Sign(byte[] data) { if (Logging.IsEnabled) { Logging.Enter(this, null, nameof(Sign)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } byte[] result = Array.Empty <byte>(); var hmacKeyHandle = new TpmHandle(AiothPersistedKeyHandle); int dataIndex = 0; byte[] iterationBuffer; const int maxBufferLength = 1024; if (data.Length <= maxBufferLength) { result = _tpm2.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256); } else { // Start the HMAC sequence. TpmHandle hmacHandle = _tpm2.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256); while (data.Length > dataIndex + maxBufferLength) { // Repeat to update the HMAC until we only have <=1024 bytes left. iterationBuffer = new byte[maxBufferLength]; Array.Copy(data, dataIndex, iterationBuffer, 0, maxBufferLength); _tpm2.SequenceUpdate(hmacHandle, iterationBuffer); dataIndex += maxBufferLength; } // Finalize the HMAC with the remainder of the data. iterationBuffer = new byte[data.Length - dataIndex]; Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex); result = _tpm2.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk); } if (Logging.IsEnabled) { Logging.Exit(this, null, nameof(Sign)); } return(result); }
} // CreateRsaPrimaryStorageKey() /// <summary> /// Main logic of the Import sample. /// The sample demonstrates how to create in software (using TSS.net helpers) /// keys of different kinds, then import them into TPM and make sure they work. /// </summary> static void ImportSample(Tpm2 tpm) { // Templates of the keys to be generated and imported var inPubs = new TpmPublic[] { new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Decrypt | ObjectAttr.UserWithAuth, null, new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new Tpm2bDigestSymcipher()), new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Sign | ObjectAttr.UserWithAuth, null, new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa()), new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Sign | ObjectAttr.UserWithAuth, null, new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)), new Tpm2bDigestKeyedhash()) }; // Create a TPM based key that will serve as a parent for the imported keys. // This should be a storage key, i.e. it must have Restricted and Decrypt // attributes, no signing or decryption scheme, and non-empty symmetric // specification (even if it is an asymmetric key) as part of its parameters. // NOTE 1 - We use an empty auth value for the parent key. If you want one, // uncomment the optional second parameter. // NOTE 2 - The size of the auth value shall not exceed the size of the digest // produced by the name algorithm of the key. In this case name algorithm is // hardcoded inside the helper, so that we do not have control over it at // this point, and therefore we use the maximal number that is safe for any // modern hash algorithm (SHA-1 or larger), though for the given implementation // of CreateRsaPrimaryStorageKey() we could use 32 (for SHA-256). TpmHandle hPrim = CreateRsaPrimaryStorageKey(tpm /*, AuthValue.FromRandom(20)*/); foreach (var inPub in inPubs) { GenerateAndImport(tpm, inPub, hPrim); // Now do the same using an inner wrapper (additional layer of cryptographic // protection in the form of symmetric encryption for the duplication blob). GenerateAndImport(tpm, inPub, hPrim, new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb)); } tpm.FlushContext(hPrim); } // ImportSample()
public static TpmPrivate GetPlaintextPrivate(Tpm2 tpm, TpmHandle key, PolicyTree policy) { AuthSession sess = tpm.StartAuthSessionEx(TpmSe.Policy, policy.HashAlg); sess.RunPolicy(tpm, policy); TpmPrivate privPlain = null; byte[] symSeed; tpm[sess]._ExpectResponses(TpmRc.Success, TpmRc.Attributes) .Duplicate(key, TpmRh.Null, null, new SymDefObject(), out privPlain, out symSeed); Debug.Assert(!tpm._LastCommandSucceeded() || symSeed.Length == 0); tpm.FlushContext(sess); return(Globs.IsEmpty(privPlain.buffer) ? null : privPlain); }
/// <summary> /// Funzione per la pulizia di una chiave e funzione HMAC precedentementi salvati nel TPM /// </summary> public static void CleanOldHmacKey() { // Apertura del TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId); TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId); // Undefine dello spazio utilizzato per la chiave HMAC tpm.NvUndefineSpace(ownerHandle, nvHandle); // Rimozione della funzione HMAC tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle); }
void TestVendorSpecific(Tpm2 tpm, TestContext testCtx) { if (!TpmCfg.IsImplemented(TpmCc.VendorTcgTest)) { Substrate.WriteToLog("TestVendorSpecific skipped", ConsoleColor.DarkCyan); return; } TpmHandle h = Substrate.CreateDataObject(tpm); byte[] inData = Substrate.RandomBytes(24); testCtx.ReportParams("Input data size: " + inData.Length); byte[] outData = tpm.VendorTcgTest(inData); testCtx.Assert("CertDataReceived", outData.Length > 0, outData.Length); tpm.FlushContext(h); } // TestVendorSpecific
/// <summary> /// Sign data using the key stored in the TPM. The signing is done inside the TPM to avoid exposing the key. /// This is similar to using <see cref="System.Security.Cryptography.SHA256CryptoServiceProvider"/> which /// uses <see cref="System.Security.Cryptography.HMACSHA256"/> inside. /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] Sign(byte[] data) { TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId); int dataIndex = 0; byte[] iterationBuffer, result = Array.Empty <byte>(); try { // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); using (var tpm = new Tpm2(tpmDevice)) { if (data.Length <= 1024) { // Calculate the HMAC in one shot result = tpm.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256); } else { // Start the HMAC sequence TpmHandle hmacHandle = tpm.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256); while (data.Length > dataIndex + 1024) { // Repeat to update the hmac until we only hace <=1024 bytes left iterationBuffer = new byte[1024]; Array.Copy(data, dataIndex, iterationBuffer, 0, 1024); tpm.SequenceUpdate(hmacHandle, iterationBuffer); dataIndex += 1024; } // Finalize the hmac with the remainder of the data iterationBuffer = new byte[data.Length - dataIndex]; Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex); result = tpm.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk); } } } catch { } return(result); }
public static SchemeEcdaa PrepareEcdaaScheme(Tpm2 tpm, TpmHandle signKey, ISigSchemeUnion scheme) { var schemeEcdaa = scheme as SchemeEcdaa; if (schemeEcdaa != null) { byte[] name, qualName; var keyPub = tpm.ReadPublic(signKey, out name, out qualName); ushort counter = 0; EccPoint l, E; EccPoint PP = keyPub.unique as EccPoint; tpm.Commit(signKey, PP, null, null, out l, out E, out counter); schemeEcdaa.count = counter; } return(schemeEcdaa); }
/// <summary> /// Signs the data using the previously activated identity key. /// </summary> /// <param name="data">The data to be signed.</param> /// <returns>The signed data.</returns> public override byte[] Sign(byte[] data) { if (Logging.IsEnabled) { Logging.Enter(this, $"{Convert.ToBase64String(data)}", nameof(Sign)); } byte[] result = Array.Empty <byte>(); TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE); int dataIndex = 0; byte[] iterationBuffer; if (data.Length <= 1024) { result = _tpm2.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256); } else { // Start the HMAC sequence. TpmHandle hmacHandle = _tpm2.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256); while (data.Length > dataIndex + 1024) { // Repeat to update the HMAC until we only have <=1024 bytes left. iterationBuffer = new Byte[1024]; Array.Copy(data, dataIndex, iterationBuffer, 0, 1024); _tpm2.SequenceUpdate(hmacHandle, iterationBuffer); dataIndex += 1024; } // Finalize the HMAC with the remainder of the data. iterationBuffer = new Byte[data.Length - dataIndex]; Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex); result = _tpm2.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk); } if (Logging.IsEnabled) { Logging.Exit(this, $"{Convert.ToBase64String(result)}", nameof(Sign)); } return(result); }
private void ProvisionUri(string hostName, string deviceId = "") { TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX); TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); UTF8Encoding utf8 = new UTF8Encoding(); byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId); // Define the store _tpm2.NvDefineSpace(ownerHandle, Array.Empty <byte>(), new NvPublic(nvHandle, TpmAlgId.Sha256, NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa, Array.Empty <byte>(), (ushort)nvData.Length)); // Write the store _tpm2.NvWrite(nvHandle, nvHandle, nvData, 0); }
internal static void EncryptDecrypt(Tpm2 tpm) { var keyParams = KeyHelpers.CreateDecryptionKey2(); TpmPublic pubCreated; CreationData creationData; TkCreation creationTicket; byte[] creationHash; TpmHandle h = tpm.CreatePrimary(TpmRh.Owner, null, keyParams, null, //outsideInfo, null, //new PcrSelection[] { creationPcr }, out pubCreated, out creationData, out creationHash, out creationTicket); }
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); }
public void Destroy() { TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId); TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId); // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); // Destyroy the URI tpm.NvUndefineSpace(ownerHandle, nvHandle); // Destroy the HMAC key tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle); // Dispose of the TPM tpm.Dispose(); }
public override Task <bool> Delete(string thumbprint) { lock (m_lock) { try { // Create a handle based on the hash of the cert thumbprint ushort slotIndex = BitConverter.ToUInt16(CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(thumbprint)), 0); TpmHandle nvHandle = TpmHandle.NV(slotIndex); // Delete hash of thumbprint from NV storage m_tpm[m_ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); } catch (Exception e) { Utils.Trace(e, "Could not delete application certificate thumprint from TPM NV storage!"); } } return(base.Delete(thumbprint)); }
/// <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); }
/// <summary> /// Provision the key in the TPM /// </summary> /// <param name="key">the access key</param> public void Provision(byte[] key) { TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId); TpmHandle srkHandle = new TpmHandle(TPM_20_SRK_HANDLE); // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); using (var tpm = new Tpm2(tpmDevice)) { #pragma warning disable IDE0059 // Value assigned to symbol is never used // Import the HMAC key under the SRK TpmPrivate hmacPrv = tpm.Create(srkHandle, new SensitiveCreate(Array.Empty <byte>(), key), new TpmPublic(TpmAlgId.Sha256, ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign, Array.Empty <byte>(), new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)), new Tpm2bDigestKeyedhash()), Array.Empty <byte>(), Array.Empty <PcrSelection>(), out TpmPublic hmacPub, out CreationData creationData, out byte[] creationhash, out TkCreation ticket); #pragma warning restore IDE0059 // Value assigned to symbol is never used // Load the HMAC key into the TPM TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub); // Persist the key in NV tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle); // Unload the transient copy from the TPM tpm.FlushContext(loadedHmacKey); } }
/// <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)); }
private TpmPublic ReadOrCreatePersistedKey(TpmHandle persHandle, TpmHandle hierarchy, TpmPublic template) { // Let's see if the key was already created and installed. TpmPublic keyPub = _tpm2._AllowErrors().ReadPublic(persHandle, out _, out _); // If not create and install it. if (!_tpm2._LastCommandSucceeded()) { TpmHandle keyHandle = _tpm2.CreatePrimary(hierarchy, new SensitiveCreate(), template, Array.Empty <byte>(), Array.Empty <PcrSelection>(), out keyPub, out _, out _, creationTicket: out _); _tpm2.EvictControl(TpmHandle.RhOwner, keyHandle, persHandle); _tpm2.FlushContext(keyHandle); } return(keyPub); }
void LoadExternalFullRsaKeySample(Tpm2 tpm, TestContext testCtx) { var hashAlg = TpmAlgId.Sha256; var inPub = new TpmPublic(hashAlg, ObjectAttr.Decrypt | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, null, new RsaParms(new SymDefObject(), new SchemeOaep(hashAlg), 2048, 0), new Tpm2bPublicKeyRsa()); // Create a software RSA key var swKey = new AsymCryptoSystem(inPub); // The crucial point in loading a software key is preparing the TPM-formatted private part of the key Sensitive sens = swKey.GetSensitive(); TpmHandle extKey = tpm.LoadExternal(sens, swKey.GetPublicParms(), TpmRh.Null); // // Make sure that the key was loaded correctly // // This particular label is used by the TPM while doing OAEP for its internal protocols // (though in n general any label can be used). byte[] label = RawRsa.GetLabel("OaepLabel"); byte[] origMsg = Substrate.RandomBytes(64); // Encrypt using software key (the paublic part is used) byte[] encMsg = swKey.EncryptOaep(origMsg, label); testCtx.AssertNotEqual("SwEnc", origMsg, encMsg); // Decrypt using the TPM (the private part is used) byte[] decMsg = tpm.RsaDecrypt(extKey, encMsg, null, label); testCtx.AssertEqual("CrossEncDec", origMsg, decMsg); tpm.FlushContext(extKey); }
private TpmPublic ReadOrCreatePersistedKey(TpmHandle persHandle, TpmHandle hierarchy, TpmPublic template) { // Let's see if the key was already created and installed (aka. the TPM has been provisioned by Windows). TpmPublic keyPub = _tpm2._AllowErrors().ReadPublic(persHandle, out byte[] name, out byte[] qualifiedName); // If not create and install it if (!_tpm2._LastCommandSucceeded()) { TpmHandle keyHandle = _tpm2.CreatePrimary(hierarchy, new SensitiveCreate(), template, Array.Empty <byte>(), Array.Empty <PcrSelection>(), out keyPub, out CreationData creationData, out byte[] creationHash, out TkCreation creationTicket); _tpm2.EvictControl(TpmHandle.RhOwner, keyHandle, persHandle); _tpm2.FlushContext(keyHandle); } return(keyPub); }
/// <summary> /// This sample demonstrates how the caller can control simulated power, locality /// and physical-presence against the simulated TPM /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static void PowerAndLocality(Tpm2 tpm) { // // Do a complete simulated clean power-down // tpm.Shutdown(Su.Clear); tpm._GetUnderlyingDevice().PowerCycle(); tpm.Startup(Su.Clear); Console.WriteLine("Power cycle with TPM2_Startup(CLEAR) completed."); // // Now do a simulated hibernate // tpm.Shutdown(Su.State); tpm._GetUnderlyingDevice().PowerCycle(); tpm.Startup(Su.State); Console.WriteLine("Power cycle with TPM2_Startup(STATE) completed."); // // Execute a command at locality 2 // tpm._SetLocality(LocalityAttr.TpmLocTwo); tpm.PcrReset(TpmHandle.Pcr(21)); tpm._SetLocality(LocalityAttr.TpmLocZero); Console.WriteLine("PCR[21] for locality 2 reset."); // // Execute a command that needs physical-presence // tpm._AssertPhysicalPresence() .PpCommands(TpmHandle.RhPlatform, new TpmCc[0], new TpmCc[0]); Console.WriteLine("Physical presence commands tested."); }
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); }
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); }
public string GetHardwareDeviceId() { TpmHandle srkHandle = new TpmHandle(SRK_HANDLE); string hardwareDeviceId = ""; Byte[] name; Byte[] qualifiedName; try { // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); // Read the URI from the TPM TpmPublic srk = tpm.ReadPublic(srkHandle, out name, out qualifiedName); // Dispose of the TPM tpm.Dispose(); } catch { return(hardwareDeviceId); } // Calculate the hardware device id for this logical device byte[] deviceId = CryptoLib.HashData(TpmAlgId.Sha256, BitConverter.GetBytes(logicalDeviceId), name); // Produce the output string foreach (byte n in deviceId) { hardwareDeviceId += n.ToString("x2"); } return(hardwareDeviceId); }
public void TestTpmCollector() { var PcrAlgorithm = TpmAlgId.Sha256; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var process = TpmSim.GetTpmSimulator(); process.Start(); var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; uint nvIndex = 3001; var tpmc = new TpmCollector(new CollectorOptions() { Verbose = true }, null, TestMode: true); // Prepare to write to NV 3001 TpmHandle nvHandle = TpmHandle.NV(nvIndex); TcpTpmDevice tcpTpmDevice = new TcpTpmDevice("127.0.0.1", 2321, stopTpm: false); tcpTpmDevice.Connect(); using var tpm = new Tpm2(tcpTpmDevice); tcpTpmDevice.PowerCycle(); tpm.Startup(Su.Clear); try { tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); tpm.NvDefineSpace(TpmRh.Owner, null, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.NoDa | NvAttr.Ownerread | NvAttr.Ownerwrite, null, 32)); // Write to NV 3001 tpm.NvWrite(TpmRh.Owner, nvHandle, nvData, 0); var nvOut = tpm.NvRead(TpmRh.Owner, nvHandle, (ushort)nvData.Length, 0); Assert.IsTrue(nvOut.SequenceEqual(nvData)); } catch (TpmException e) { Log.Debug(e, "Failed to Write to NV."); Assert.Fail(); } // Verify that all the PCRs are blank to start with var pcrs = TpmCollector.DumpPCRs(tpm, PcrAlgorithm, new PcrSelection[] { new PcrSelection(PcrAlgorithm, new uint[] { 15, 16 }) }); Assert.IsTrue(pcrs.All(x => x.Value.SequenceEqual(new byte[x.Value.Length]))); // Measure to PCR 16 try { tpm.PcrExtend(TpmHandle.Pcr(16), tpm.PcrEvent(TpmHandle.Pcr(16), nvData)); } catch (TpmException e) { Log.Debug(e, "Failed to Write PCR."); } // Verify that we extended the PCR var pcrs2 = TpmCollector.DumpPCRs(tpm, PcrAlgorithm, new PcrSelection[] { new PcrSelection(PcrAlgorithm, new uint[] { 15, 16 }, 24) }); Assert.IsTrue(pcrs2[(PcrAlgorithm, 15)].SequenceEqual(pcrs[(PcrAlgorithm, 15)]));
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
/// <summary> /// Demonstrate use of NV counters. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static 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. // var ownerAuth = new AuthValue(); TpmHandle nvHandle = TpmHandle.NV(3001); // // Clean up any slot that was left over from an earlier run // tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // // Scenario 2 - A NV-counter // AuthValue nvAuth = AuthValue.FromRandom(8); tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.TpmaNvCounter | NvAttr.TpmaNvAuthread | NvAttr.TpmaNvAuthwrite, new byte[0], 8)); // // Must write before we can read // tpm[nvAuth].NvIncrement(nvHandle, nvHandle); // // Read the current value // byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, 8, 0); var initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); // // Increment // tpm[nvAuth].NvIncrement(nvHandle, nvHandle); // // Read again and see if the answer is what we expect // nvRead = tpm[nvAuth].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); // // Clean up // tpm[ownerAuth].NvUndefineSpace(TpmHandle.RhOwner, nvHandle); }
/// <summary> /// Activates an identity key within the TPM device. /// </summary> /// <param name="encryptedKey">The encrypted identity key.</param> public override void ActivateIdentityKey(byte[] encryptedKey) { if (Logging.IsEnabled) { Logging.Enter(this, $"{encryptedKey}", nameof(ActivateIdentityKey)); } Destroy(); // Take the pieces out of the container var m = new Marshaller(encryptedKey, DataRepresentation.Tpm); Tpm2bIdObject cred2b = m.Get <Tpm2bIdObject>(); byte[] encryptedSecret = new byte[m.Get <ushort>()]; encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret"); TpmPrivate dupBlob = m.Get <TpmPrivate>(); byte[] encWrapKey = new byte[m.Get <ushort>()]; encWrapKey = m.GetArray <byte>(encWrapKey.Length, "encWrapKey"); UInt16 pubSize = m.Get <UInt16>(); _idKeyPub = m.Get <TpmPublic>(); byte[] cipherText = new byte[m.Get <ushort>()]; cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo"); // Setup the authorization session for the EK var policyNode = new TpmPolicySecret(TpmHandle.RhEndorsement, false, 0, Array.Empty <byte>(), Array.Empty <byte>()); var policy = new PolicyTree(_ekPub.nameAlg); policy.SetPolicyRoot(policyNode); AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg); ekSession.RunPolicy(_tpm2, policy); // Perform the activation ekSession.Attrs &= ~SessionAttr.ContinueSession; _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential( new TpmHandle(TPM_20_SRK_HANDLE), new TpmHandle(TPM_20_EK_HANDLE), cred2b.credential, encryptedSecret); TpmPrivate importedKeyBlob = _tpm2.Import( new TpmHandle(TPM_20_SRK_HANDLE), _activationSecret, _idKeyPub, dupBlob, encWrapKey, new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb)); _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub); // Persist the key in NV TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE); _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle); // Unload the transient copy from the TPM _tpm2.FlushContext(_idKeyHandle); _idKeyHandle = hmacKeyHandle; if (Logging.IsEnabled) { Logging.Exit(this, $"{encryptedKey}", nameof(ActivateIdentityKey)); } }
} // 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()