in TPM Parser/Tpm2Lib/TpmKey.cs [385:451]
public TpmPrivate GetDuplicationBlob(
TpmPublic newParent,
SymmCipher innerWrapper,
out byte[] encryptedWrappingKey)
{
byte[] encSensitive;
if (innerWrapper == null)
{
// No inner wrapper
encSensitive = Marshaller.ToTpm2B(sensitivePart.GetTpmRepresentation());
}
else
{
byte[] sens = Marshaller.ToTpm2B(sensitivePart.GetTpmRepresentation());
byte[] toHash = Globs.Concatenate(sens, GetName());
byte[] innerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData(publicPart.nameAlg, toHash));
byte[] innerData = Globs.Concatenate(innerIntegrity, sens);
encSensitive = innerWrapper.Encrypt(innerData);
}
byte[] seed, encSecret;
SymDefObject symDef = GetSymDef(newParent);
using (AsymCryptoSystem newParentPubKey = AsymCryptoSystem.CreateFrom(newParent))
{
switch (newParent.type)
{
case TpmAlgId.Rsa:
// The seed should be the same size as the symmKey
seed = Globs.GetRandomBytes((symDef.KeyBits + 7) / 8);
encSecret = newParentPubKey.EncryptOaep(seed, DuplicateEncodingParms);
break;
case TpmAlgId.Ecc:
EccPoint pubEphem;
seed = newParentPubKey.EcdhGetKeyExchangeKey(DuplicateEncodingParms,
newParent.nameAlg,
out pubEphem);
encSecret = Marshaller.GetTpmRepresentation(pubEphem);
break;
default:
Globs.Throw<NotImplementedException>("GetDuplicationBlob: Unsupported algorithm");
encryptedWrappingKey = new byte[0];
return new TpmPrivate();
}
}
encryptedWrappingKey = encSecret;
byte[] symKey = KDF.KDFa(newParent.nameAlg, seed, "STORAGE", publicPart.GetName(), new byte[0], symDef.KeyBits);
byte[] dupSensitive;
using (SymmCipher enc2 = SymmCipher.Create(symDef, symKey))
{
dupSensitive = enc2.Encrypt(encSensitive);
}
var npNameNumBits = CryptoLib.DigestSize(newParent.nameAlg) * 8;
byte[] hmacKey = KDF.KDFa(newParent.nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], npNameNumBits);
byte[] outerDataToHmac = Globs.Concatenate(dupSensitive, publicPart.GetName());
byte[] outerHmac = Marshaller.ToTpm2B(CryptoLib.HmacData(newParent.nameAlg, hmacKey, outerDataToHmac));
byte[] dupBlob = Globs.Concatenate(outerHmac, dupSensitive);
return new TpmPrivate(dupBlob);
}