/// <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);
}