/// <summary> /// Creates a *software* key. The key will be random (not created from /// a seed). The key can be used as the root of a software hierarchy that /// can be translated into a duplication blob ready for import into a TPM. /// Depending on the type of key, the software root key can be a parent for /// other root keys that can comprise a migration group. The caller should /// specify necessary key parameters in Public. /// /// Parameter keyData is used only with symmetric or HMAC keys. If non-null /// on entry, it contains the key bytes supplied by the caller, otherwise the /// key will be randomly generated. For asymmetric keys keyData must be null. /// /// Parameter authVal specifies the authorization value associated with the key. /// If it is null, then an random value will be used. /// </summary> /// <param name="pub"></param> /// <param name="authVal"></param> /// <param name="keyData"></param> /// <returns></returns> public static TssObject Create(TpmPublic pub, AuthValue authVal = null, byte[] keyData = null) { var newKey = new TssObject(); // Create a new key from the supplied parameters IPublicIdUnion publicId; var sensData = CreateSensitiveComposite(pub, ref keyData, out publicId); var nameSize = CryptoLib.DigestSize(pub.nameAlg); // Create the associated seed value byte[] seed = Globs.GetRandomBytes(nameSize); // Fill in the fields for the symmetric private-part of the asymmetric key var sens = new Sensitive(authVal ?? AuthValue.FromRandom(nameSize), seed, sensData); newKey.Sensitive = sens; newKey.Private = new TpmPrivate(sens.GetTpm2BRepresentation()); // fill in the public data newKey.Public = pub.Copy(); if (pub.type == TpmAlgId.Keyedhash || pub.type == TpmAlgId.Symcipher) { byte[] unique = null; if (pub.objectAttributes.HasFlag(ObjectAttr.Restricted | ObjectAttr.Decrypt)) { unique = CryptoLib.Hmac(pub.nameAlg, seed, keyData); } else { unique = CryptoLib.HashData(pub.nameAlg, seed, keyData); } newKey.Public.unique = pub.type == TpmAlgId.Keyedhash ? new Tpm2bDigestKeyedhash(unique) as IPublicIdUnion : new Tpm2bDigestSymcipher(unique); } else { newKey.Public.unique = publicId; } // And return the new key return(newKey); }
} // class PrivateKeyBlob // Trailing parameters are used to populate TpmPublic generated for the key from the blob. public static TpmPrivate CspToTpm(byte[] cspPrivateBlob, out TpmPublic tpmPub, TpmAlgId nameAlg = TpmAlgId.Sha1, ObjectAttr keyAttrs = ObjectAttr.Decrypt | ObjectAttr.UserWithAuth, IAsymSchemeUnion scheme = null, SymDefObject symDef = null) { if (scheme == null) { scheme = new NullAsymScheme(); } if (symDef == null) { symDef = new SymDefObject(); } var m = new Marshaller(cspPrivateBlob, DataRepresentation.LittleEndian); var cspPrivate = m.Get <Csp.PrivateKeyBlob>(); var keyAlg = cspPrivate.publicKeyStruc.aiKeyAlg; if (keyAlg != Csp.AlgId.CAlgRsaKeyX && keyAlg != Csp.AlgId.CAlgRsaSign) { Globs.Throw <NotSupportedException>("CSP blobs for keys of type " + keyAlg.ToString("X") + " are not supported"); tpmPub = new TpmPublic(); return(new TpmPrivate()); } var rsaPriv = new Tpm2bPrivateKeyRsa(Globs.ReverseByteOrder(cspPrivate.prime1)); var sens = new Sensitive(new byte[0], new byte[0], rsaPriv); tpmPub = new TpmPublic(nameAlg, keyAttrs, new byte[0], new RsaParms(symDef, scheme, (ushort)cspPrivate.rsaPubKey.bitlen, cspPrivate.rsaPubKey.pubexp), new Tpm2bPublicKeyRsa(Globs.ReverseByteOrder(cspPrivate.modulus))); return(new TpmPrivate(sens.GetTpm2BRepresentation())); }
/// <summary> /// Create a plaintext duplication blob that can be imported into a TPM /// </summary> /// <returns></returns> public TpmPrivate GetPlaintextDuplicationBlob() { return(new TpmPrivate(Sensitive.GetTpm2BRepresentation())); }