} // SimpleDuplicateImportRsaSample TssObject ImportExternalRsaKey(Tpm2 tpm, TpmHandle hParent, int keySizeInBits, IAsymSchemeUnion scheme, byte[] publicPart, byte[] privatePart, ObjectAttr keyAttrs, byte[] authVal = null, byte[] policyDigest = null) { TpmAlgId sigHashAlg = TpmHelper.GetSchemeHash(scheme), nameAlg = sigHashAlg; // TPM signing key template with the actual public key bits var inPub = new TpmPublic(nameAlg, keyAttrs, policyDigest, new RsaParms(new SymDefObject(), scheme as IAsymSchemeUnion, (ushort)keySizeInBits, 0), new Tpm2bPublicKeyRsa(publicPart)); // Wrap the key in a TSS helper class TssObject swKey = TssObject.Create(inPub, authVal, privatePart); // Get a key duplication blob in TPM 2.0 compatibale format TpmPrivate dupBlob = swKey.GetPlaintextDuplicationBlob(); // Importing a duplication blob creates a new TPM private key blob protected // with its new parent key. swKey.Private = tpm.Import(hParent, null, swKey.Public, dupBlob, null, new SymDefObject()); return(swKey); } // ImportExternalRsaKey
void DuplicateImportRsaSample(Tpm2 tpm, TestContext testCtx) { TpmAlgId nameAlg = Substrate.Random(TpmCfg.HashAlgs); var policy = new PolicyTree(nameAlg); policy.SetPolicyRoot(new TpmPolicyCommand(TpmCc.Duplicate)); var inPub = new TpmPublic(nameAlg, ObjectAttr.Sign | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin, policy.GetPolicyDigest(), new RsaParms(new SymDefObject(), new SchemeRsassa(Substrate.Random(TpmCfg.HashAlgs)), Substrate.Random(TpmCfg.RsaKeySizes), 0), new Tpm2bPublicKeyRsa()); TpmHandle hKey = Substrate.CreateAndLoad(tpm, inPub, out TpmPublic pub); // Duplicate TpmPrivate priv = TpmHelper.GetPlaintextPrivate(tpm, hKey, policy); tpm.FlushContext(hKey); // Import TpmPrivate privImp = tpm.Import(Substrate.LoadRsaPrimary(tpm), null, pub, priv, null, new SymDefObject()); } // SimpleDuplicateImportRsaSample
internal static TpmHandle CreateEncryptionDecryptionKey(Tpm2 tpm, TpmHandle parent) { var sensCreate = new SensitiveCreate(null, null); var sym = new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb); var pub = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Decrypt | ObjectAttr.UserWithAuth, null, sym, new Tpm2bDigestSymcipher()); TssObject swKey = TssObject.Create(pub); var innerWrapKey = sym == null ? null : SymCipher.Create(sym); byte[] name, qname; TpmPublic pubParent = tpm.ReadPublic(parent, out name, out qname); byte[] encSecret; TpmPrivate dupBlob = swKey.GetDuplicationBlob(pubParent, innerWrapKey, out encSecret); TpmPrivate privImp = tpm.Import(parent, innerWrapKey, swKey.Public, dupBlob, encSecret, sym ?? new SymDefObject()); TpmHandle hKey = tpm.Load(parent, privImp, swKey.Public) .SetAuth(swKey.Sensitive.authValue); return(hKey); }
/// <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)); } }
/// <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); } }
/// <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