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 void Provision(string encodedHmacKey, string hostName, string deviceId = "") { TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId); TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId); TpmHandle srkHandle = new TpmHandle(SRK_HANDLE); UTF8Encoding utf8 = new UTF8Encoding(); byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId); byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey); // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); // Define the store tpm.NvDefineSpace(ownerHandle, new byte[0], new NvPublic(nvHandle, TpmAlgId.Sha256, NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa, new byte[0], (ushort)nvData.Length)); // Write the store tpm.NvWrite(nvHandle, nvHandle, nvData, 0); // Import the HMAC key under the SRK TpmPublic hmacPub; CreationData creationData; byte[] creationhash; TkCreation ticket; TpmPrivate hmacPrv = tpm.Create(srkHandle, new SensitiveCreate(new byte[0], hmacKey), new TpmPublic(TpmAlgId.Sha256, ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign, new byte[0], new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)), new Tpm2bDigestKeyedhash()), new byte[0], new PcrSelection[0], out hmacPub, out creationData, out creationhash, out ticket); // 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> /// 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); }
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(); }
/// <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> /// 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()
/// <summary> /// Funzione per il salvataggio della chiave privata da utilizzare per firmare con HMAC tramite TPM /// </summary> /// <param name="encodedHmacKey"></param> public static void SaveHmacKey(string encodedHmacKey) { // Definizione area di memoria non volatile nel TPM TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId); // Definizione dell'handle contenente l'Owner nel TPM TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner); // Definizione dell'handle per la memorizzazione dell'oggetto HMAC TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId); // Definizione dell'handle della Storage Root Key, si tratta della chiave // principale utilizzata per il salvataggio di altre chiavi. Ogni chiave salvata // nel TPM infatti viene cifrata utilizzando la sua chiave "padre". // La SRK è la chiave più alta dell'albero TpmHandle srkHandle = new TpmHandle(SRK_HANDLE); UTF8Encoding utf8 = new UTF8Encoding(); // dati descrittivi dell'host e del device id byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId); // chiave privata che intendiamo memorizzare nel TPM byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey); // Apertura del TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); var tpm = new Tpm2(tpmDevice); // Definizione dello store Non volatile // Il primo parametro è l'Owner TPM // il terzo parametro è la funzione HMAC che intendiamo salvare // (NvPublic sta per Non volatile public area) tpm.NvDefineSpace(ownerHandle, new byte[0], new NvPublic( nvHandle, TpmAlgId.Sha256, NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa, new byte[0], (ushort)nvData.Length)); // Scrittura nello store non volatile della funzione HMAC tpm.NvWrite(nvHandle, nvHandle, nvData, 0); // Importazione della chiave HMAC sotto la Storage Root Key TpmPublic hmacPub; CreationData creationData; byte[] creationhash; TkCreation ticket; // Passaggio della chiave privata var sensitiveCreate = new SensitiveCreate(new byte[0], hmacKey); // Definizione dell'uso che si farà della chiave var tpmPublic = new TpmPublic( TpmAlgId.Sha256, ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign, new byte[0], new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)), new Tpm2bDigestKeyedhash()); // Salvataggio della chiave privata nel tpm TpmPrivate hmacPrv = tpm.Create( srkHandle, sensitiveCreate, tpmPublic, new byte[0], new PcrSelection[0], out hmacPub, out creationData, out creationhash, out ticket); // Caricamento della chiave HMAC nel TPM TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub); // Salvataggio della chiave nella memoria Non Volatile tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle); // Flush degli oggetti transienti dal tpm tpm.FlushContext(loadedHmacKey); }
/// <summary> /// Get the endorsement key from the TPM. If the key has not yet been set, a new one is generated /// </summary> /// <returns></returns> /// <remarks> /// Picked from https://github.com/Azure/azure-iot-sdk-csharp/blob/e1dd08eacd1caf58f3b318d8ad5ad94dde961d78/security/tpm/src/SecurityProviderTpmHsm.cs#L258-L324 /// </remarks> public static byte[] GetEndorsementKey() { TpmHandle ekHandle = new TpmHandle(TPM_20_EK_HANDLE); byte[] result = Array.Empty <byte>(); try { // Open the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); using (var tpm = new Tpm2(tpmDevice)) { // Read EK from the TPM, temporarily allowing errors TpmPublic ekPub = tpm. _AllowErrors() .ReadPublic(ekHandle, out byte[] name, out byte[] qualifiedName); // if the last command did not succeed, we do not have an endorsement key yet, so create it if (!tpm._LastCommandSucceeded()) { // Get the real EK ready. TpmPublic ekTemplate = new TpmPublic( TpmAlgId.Sha256, ObjectAttr.FixedTPM | ObjectAttr.FixedParent | ObjectAttr.SensitiveDataOrigin | ObjectAttr.AdminWithPolicy | ObjectAttr.Restricted | ObjectAttr.Decrypt, new byte[] { 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa }, new RsaParms( new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0), new Tpm2bPublicKeyRsa(new byte[2048 / 8])); TpmHandle keyHandle = tpm.CreatePrimary( new TpmHandle(TpmHandle.RhEndorsement), new SensitiveCreate(), ekTemplate, Array.Empty <byte>(), Array.Empty <PcrSelection>(), out ekPub, out CreationData creationData, out byte[] creationHash, out TkCreation creationTicket); tpm.EvictControl(TpmHandle.RhOwner, keyHandle, ekHandle); tpm.FlushContext(keyHandle); } // Get the EK representation result = ekPub.GetTpm2BRepresentation(); } } catch { } return(result); }
/// <summary> /// Activates a symmetric identity within the Hardware Security Module. /// </summary> /// <param name="activation">The authentication challenge key supplied by the service.</param> public override void ActivateSymmetricIdentity(byte[] activation) { Destroy(); // Take the pieces out of the container var m = new Marshaller(activation, DataRepresentation.Tpm); byte[] credentialBlob = new byte[m.Get <ushort>()]; credentialBlob = m.GetArray <byte>(credentialBlob.Length, "credentialBlob"); 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>(encryptedSecret.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, _ekAuth ?? Array.Empty <byte>(), new AuthValue(), 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), credentialBlob, 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; // Unwrap the URI byte[] clearText = SymmCipher.Decrypt( new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), _activationSecret, new byte[16], cipherText); UnicodeEncoding unicode = new UnicodeEncoding(); string uriData = unicode.GetString(clearText); int idx = uriData.IndexOf('/'); if (idx > 0) { string hostName = uriData.Substring(0, idx); string deviceId = uriData.Substring(idx + 1); // Persist the URI ProvisionUri(hostName, deviceId); } }