public static byte[] GetPcrProperty(Tpm2 tpm, PtPcr prop) { ICapabilitiesUnion caps; tpm.GetCapability(Cap.PcrProperties, (uint)prop, 1, out caps); TaggedPcrSelect[] props = (caps as TaggedPcrPropertyArray).pcrProperty; if (props.Length == 0) { return(new byte[0]); } if (props.Length != 1) { Globs.Throw("Unexpected return from GetCapability"); } return(props[0].pcrSelect); }
virtual internal void ToStringInternal(TpmStructPrinter p) { bool enabled = dbg.Enabled; dbg.Enabled = false; var members = GetFieldsToMarshal(); dbg.Enabled = enabled; foreach (var mem in members) { MemberInfo memInfo = mem; object memVal = Globs.GetMember(memInfo, this); Type memType = Globs.GetMemberType(memInfo); p.Print(memInfo.Name, Globs.ToCSharpStyle(memType.Name), memVal); } }
void Init(RSAParameters rsaParams, int numBits) { NumBits = numBits; E = FromBigEndian(rsaParams.Exponent); N = FromBigEndian(rsaParams.Modulus); Debug.Assert(Globs.ArraysAreEqual(ToBigEndian(N.ToByteArray()), rsaParams.Modulus)); if (rsaParams.P != null) { D = FromBigEndian(rsaParams.D); P = FromBigEndian(rsaParams.P); Q = FromBigEndian(rsaParams.Q); InverseQ = FromBigEndian(rsaParams.InverseQ); DP = FromBigEndian(rsaParams.DP); DQ = FromBigEndian(rsaParams.DQ); } }
internal static int GetKeyLength(EccCurve curve) { switch (curve) { case EccCurve.TpmEccNistP256: return(256); case EccCurve.TpmEccNistP384: return(384); case EccCurve.TpmEccNistP521: return(521); } Globs.Throw <ArgumentException>("GetKeyLength(): Invalid ECC curve"); return(-1); }
public byte[] OaepEncrypt(byte[] data, TpmAlgId hashAlg, byte[] encodingParms) { int encLen = NumBits / 8; byte[] zeroTermEncoding = GetLabel(encodingParms); byte[] encoded = CryptoEncoders.OaepEncode(data, zeroTermEncoding, hashAlg, encLen); BigInteger message = FromBigEndian(encoded); BigInteger cipher = BigInteger.ModPow(message, E, N); byte[] encMessageBigEnd = ToBigEndian(cipher, KeySize); if (encMessageBigEnd.Length < encLen) { encMessageBigEnd = Globs.AddZeroToBeginning(encMessageBigEnd, encLen - encMessageBigEnd.Length); } return(encMessageBigEnd); }
private byte[] GetTpmAuth(TBS_AUTH_TYPE authType) { #if false return(new byte[0]); #else if (TbsHandle == UIntPtr.Zero) { throw new Exception("TBS context not created."); } //Console.WriteLine("GetTpmAuth: Retrieving auth value {0}", authType); var resultBuf = new byte[256]; uint resultByteCount = (uint)resultBuf.Length; TbsWrapper.TBS_RESULT result = TbsWrapper.NativeMethods. Tbsi_Get_OwnerAuth(TbsHandle, (uint)authType, resultBuf, ref resultByteCount); if (result != TbsWrapper.TBS_RESULT.SUCCESS) { #if !__NETCOREAPP2__ && false Console.WriteLine($"Trying to read LockoutAuth from the registry..."); try { string lockoutAuthBase64 = (string)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TPM\WMI\Admin", "LockoutHash", null); if (lockoutAuthBase64 != null) { resultBuf = Convert.FromBase64String(lockoutAuthBase64); Console.WriteLine($"LockoutAuth: {lockoutAuthBase64} | len {resultBuf.Length} bytes | {Globs.HexFromByteArray(resultBuf)}"); return(resultBuf); } } catch (Exception e) { Console.WriteLine($"Exception: {e}"); } #endif #if !WINDOWS_UWP Console.WriteLine("GetTpmAuth({0}): Windows TBS returned 0x{1:X} {2}", authType, result, result == TbsWrapper.TBS_RESULT.OWNERAUTH_NOT_FOUND ? " (OWNERAUTH_NOT_FOUND)" : result == TbsWrapper.TBS_RESULT.BAD_PARAMETER ? " (BAD_PARAMETER)" : ""); #endif return(new byte[0]); } return(Globs.CopyData(resultBuf, 0, (int)resultByteCount)); #endif }
/// <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; // 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); }
public static byte[] HmacData(TpmAlgId hashAlgId, byte[] key, byte[] dataToHash) { #if TSS_USE_BCRYPT string algName = Native.BCryptHashAlgName(hashAlgId); if (string.IsNullOrEmpty(algName)) { Globs.Throw <ArgumentException>("HmacData(): Unsupported hash algorithm " + hashAlgId); return(null); } var alg = new BCryptAlgorithm(algName, Native.BCRYPT_ALG_HANDLE_HMAC); var digest = alg.HmacData(key, dataToHash); alg.Close(); return(digest); #else switch (hashAlgId) { case TpmAlgId.Sha1: using (var h = new HMACSHA1(key)) { return(h.ComputeHash(dataToHash)); } case TpmAlgId.Sha256: using (var h2 = new HMACSHA256(key)) { return(h2.ComputeHash(dataToHash)); } case TpmAlgId.Sha384: using (var h3 = new HMACSHA384(key)) { return(h3.ComputeHash(dataToHash)); } case TpmAlgId.Sha512: using (var h4 = new HMACSHA512(key)) { return(h4.ComputeHash(dataToHash)); } default: Globs.Throw <ArgumentException>("HmacData(): Unsupported hash algorithm " + hashAlgId); return(null); } #endif // !TSS_USE_BCRYPT }
/// <summary> /// Create an enveloped (encrypted and integrity protected) private area from a provided sensitive. /// </summary> /// <param name="iv"></param> /// <param name="sens"></param> /// <param name="nameHash"></param> /// <param name="publicName"></param> /// <param name="symWrappingAlg"></param> /// <param name="symKey"></param> /// <param name="parentNameAlg"></param> /// <param name="parentSeed"></param> /// <param name="f"></param> /// <returns></returns> public static byte[] CreatePrivateFromSensitive( SymDefObject symWrappingAlg, byte[] symKey, byte[] iv, Sensitive sens, TpmAlgId nameHash, byte[] publicName, TpmAlgId parentNameAlg, byte[] parentSeed, TssObject.Transformer f = null) { // ReSharper disable once InconsistentNaming byte[] tpm2bIv = Marshaller.ToTpm2B(iv); Transform(tpm2bIv, f); byte[] sensitive = sens.GetTpmRepresentation(); Transform(sensitive, f); // ReSharper disable once InconsistentNaming byte[] tpm2bSensitive = Marshaller.ToTpm2B(sensitive); Transform(tpm2bSensitive, f); byte[] encSensitive = SymCipher.Encrypt(symWrappingAlg, symKey, iv, tpm2bSensitive); Transform(encSensitive, f); byte[] decSensitive = SymCipher.Decrypt(symWrappingAlg, symKey, iv, encSensitive); Debug.Assert(f != null || Globs.ArraysAreEqual(decSensitive, tpm2bSensitive)); var hmacKeyBits = CryptoLib.DigestSize(parentNameAlg) * 8; byte[] hmacKey = KDF.KDFa(parentNameAlg, parentSeed, "INTEGRITY", new byte[0], new byte[0], hmacKeyBits); Transform(hmacKey, f); byte[] dataToHmac = Marshaller.GetTpmRepresentation(tpm2bIv, encSensitive, publicName); Transform(dataToHmac, f); byte[] outerHmac = CryptoLib.Hmac(parentNameAlg, hmacKey, dataToHmac); Transform(outerHmac, f); byte[] priv = Marshaller.GetTpmRepresentation(Marshaller.ToTpm2B(outerHmac), tpm2bIv, encSensitive); Transform(priv, f); return(priv); }
/// <summary> /// Calculate and return the auth-hmac (or plaintext auth if it is a policy session with PlaintextAuth set) /// based on the current session parms. /// </summary> /// <param name="parmHash"></param> /// <param name="direction"></param> /// <param name="nonceDec"></param> /// <param name="nonceEnc"></param> /// <returns></returns> internal byte[] GetAuthHmac(byte[] parmHash, Direction direction, byte[] nonceDec = null, byte[] nonceEnc = null) { // special case. If this is a policy session and the session includes PolicyPassword the // TPM expects and assumes that the HMAC field will have the plaintext entity field as in // a PWAP session (the related PolicyAuthValue demands an HMAC as usual) if (PlaintextAuth) { return(Handle.Auth ?? AuthHandle.Auth); } byte[] nonceNewer, nonceOlder; if (direction == Direction.Command) { nonceNewer = NonceCaller; nonceOlder = NonceTpm; } else { nonceNewer = NonceTpm; nonceOlder = NonceCaller; } byte[] sessionAttrs = Marshaller.GetTpmRepresentation(Attrs); byte[] auth = Handle.Auth; if (AuthHandle != null && Handle != TpmRh.TpmRsPw && auth == null && ((SessionType != TpmSe.Policy && BindObject != AuthHandle) || (SessionType == TpmSe.Policy && SessIncludesAuth))) { auth = Globs.TrimTrailingZeros(AuthHandle.Auth); } byte[] hmacKey = Globs.Concatenate(SessionKey, auth); byte[] bufToHmac = Globs.Concatenate(new[] { parmHash, nonceNewer, nonceOlder, nonceDec, nonceEnc, sessionAttrs }); byte[] hmac = CryptoLib.Hmac(AuthHash, hmacKey, bufToHmac); #if false Console.WriteLine(Globs.FormatBytesCompact("hmacKey: ", hmacKey)); Console.WriteLine(Globs.FormatBytesCompact("nonceNewer: ", nonceNewer)); Console.WriteLine(Globs.FormatBytesCompact("nonceOlder: ", nonceOlder)); Console.WriteLine(Globs.FormatBytesCompact("nonceDec: ", nonceDec)); Console.WriteLine(Globs.FormatBytesCompact("nonceEnc: ", nonceEnc)); Console.WriteLine(Globs.FormatBytesCompact("attrs: ", sessionAttrs)); Console.WriteLine(Globs.FormatBytesCompact("HMAC: ", hmac)); #endif return(hmac); }
public static byte[] HashData(TpmAlgId algId, byte[] dataToHash) { if (dataToHash == null) { dataToHash = new byte[0]; } #if TSS_USE_BCRYPT string algName = Native.BCryptHashAlgName(algId); if (string.IsNullOrEmpty(algName)) { Globs.Throw <ArgumentException>("HashData(): Unsupported hash algorithm " + algId); return(null); } var alg = new BCryptAlgorithm(algName); var digest = alg.HashData(dataToHash); alg.Close(); return(digest); #else HashAlgorithm hashAlg = null; switch (algId) { case TpmAlgId.Sha1: hashAlg = new SHA1Managed(); break; case TpmAlgId.Sha256: hashAlg = new SHA256Managed(); break; case TpmAlgId.Sha384: hashAlg = new SHA384Managed(); break; case TpmAlgId.Sha512: hashAlg = new SHA512Managed(); break; default: Globs.Throw <ArgumentException>("AlgId is not a supported hash algorithm"); return(null); } return(hashAlg.ComputeHash(dataToHash)); #endif }
public static byte[] TrimTrailingZeros(byte[] buf) { if (buf == null || buf.Length == 0) { return(buf); } int i = buf.Length; while (buf[i - 1] == 0 && --i > 0) { continue; } Debug.Assert(i >= 0); return(Globs.CopyData(buf, 0, i)); }
public byte[] OaepEncrypt(byte[] data, TpmAlgId hashAlg, byte[] encodingParms) { if (data.Length == 0) { Globs.Throw <ArgumentException>("OaepEncrypt: Empty data buffer"); return(new byte[0]); } int encLen = NumBits / 8; byte[] zeroTermEncoding = GetLabel(encodingParms); byte[] encoded = CryptoEncoders.OaepEncode(data, zeroTermEncoding, hashAlg, encLen); BigInteger message = FromBigEndian(encoded); BigInteger cipher = BigInteger.ModPow(message, E, N); byte[] encMessageBigEnd = ToBigEndian(cipher, KeySize); return(encMessageBigEnd); }
internal async Task <Tpm2CreatePrimaryResponse> CreatePrimaryRsaAsyncInternal( int keyLen, byte[] useAuth, byte[] policyAuth, PcrSelection[] pcrSel) { ObjectAttr attr = ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.SensitiveDataOrigin; var theUseAuth = new byte[0]; if (useAuth != null) { theUseAuth = useAuth; attr |= ObjectAttr.UserWithAuth; } var thePolicyAuth = new byte[0]; if (policyAuth != null) { thePolicyAuth = policyAuth; attr |= ObjectAttr.AdminWithPolicy; } var theSelection = new PcrSelection[0]; if (pcrSel != null) { theSelection = pcrSel; } var sensCreate = new SensitiveCreate(theUseAuth, new byte[0]); var parms = new TpmPublic(H.NameHash, attr, thePolicyAuth, new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), (ushort)keyLen, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); return(await H.Tpm.CreatePrimaryAsync(TpmRh.Owner, sensCreate, parms, outsideInfo, theSelection)); }
private void DebugStateSave() { if (Globs.GetRandomDouble() < StateSaveProbability) { bool s3 = NumStateSaves % 4 < 2; bool doPowerCycle = (NumStateSaves % 2 == 0); string message = s3 ? "{S3}" : "{S4}"; if (!doPowerCycle) { message = "{S3-abort}"; } Console.ForegroundColor = ConsoleColor.Magenta; Console.Error.Write(message); Console.ResetColor(); StateSaveAndReload(s3, (NumStateSaves % 2 == 0)); NumStateSaves++; } }
/// <summary> /// This command is used to cause conditional gating of a policy based on the contents of an NV Index. /// </summary> public TpmPolicyNV( TpmHandle authorizationHandle, byte[] nvAccessAuth, TpmHandle nvIndex, byte[] indexName, byte[] operandB, ushort offset, Eo operation, string branchName = "") : base(branchName) { AuthorizationHandle = authorizationHandle; NvAccessAuth = Globs.CopyData(nvAccessAuth); NvIndex = nvIndex; OperandB = Globs.CopyData(operandB); Offset = offset; Operation = operation; IndexName = Globs.CopyData(indexName); }
/// <summary> /// Create a new asymmetric key based on the parameters in keyParms. The resulting key data is returned in structures /// suitable for incorporation in a TPMT_PUBLIC and TPMS_SENSITIVE /// </summary> /// <param name="keyParms"></param> /// <param name="publicParms"></param> /// <returns></returns> internal static ISensitiveCompositeUnion CreateSensitiveComposite(TpmPublic keyParms, out IPublicIdUnion publicParms) { TpmAlgId keyAlgId = keyParms.type; ISensitiveCompositeUnion newSens; // Create the asymmetric key if (keyAlgId != TpmAlgId.Rsa) { Globs.Throw <ArgumentException>("Algorithm not supported"); } var newKeyPair = new RawRsa((keyParms.parameters as RsaParms).keyBits); // Put the key bits into the required structure envelopes newSens = new Tpm2bPrivateKeyRsa(newKeyPair.Private); publicParms = new Tpm2bPublicKeyRsa(newKeyPair.Public); return(newSens); }
internal static void KeyInfoFromPublicBlob(byte[] blob, out byte[] x, out byte[] y) { x = null; y = null; var m = new Marshaller(blob); uint magic = BitConverter.ToUInt32(m.GetNBytes(4), 0); bool magicOk = AlgInfo.Any(xx => xx.Magic == magic); if (!magicOk) { Globs.Throw <ArgumentException>("KeyInfoFromPublicBlob: Public key blob magic not recognized"); } uint cbKey = BitConverter.ToUInt32(m.GetNBytes(4), 0); x = m.GetNBytes((int)cbKey); y = m.GetNBytes((int)cbKey); }
/// <summary> /// Create a new random software key (public and private) matching the parameters in keyParams. /// </summary> /// <param name="keyParams"></param> /// <returns></returns> public AsymCryptoSystem(TpmPublic keyParams) { TpmAlgId keyAlgId = keyParams.type; PublicParms = keyParams.Copy(); switch (keyAlgId) { case TpmAlgId.Rsa: { var rsaParams = keyParams.parameters as RsaParms; AsymmetricKeyAlgorithmProvider RsaProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha256); Key = RsaProvider.CreateKeyPair(rsaParams.keyBits); IBuffer keyBlobBuffer = Key.ExportPublicKey(CryptographicPublicKeyBlobType.BCryptPublicKey); byte[] blob; CryptographicBuffer.CopyToByteArray(keyBlobBuffer, out blob); var m = new Marshaller(blob, DataRepresentation.LittleEndian); var header = m.Get <BCryptRsaKeyBlob>(); var modulus = m.GetArray <byte>((int)header.cbModulus); var pubId = new Tpm2bPublicKeyRsa(modulus); PublicParms.unique = pubId; break; } case TpmAlgId.Ecc: { var eccParms = keyParams.parameters as EccParms; var alg = RawEccKey.GetEccAlg(keyParams); if (alg == null) { Globs.Throw <ArgumentException>("Unknown ECC curve"); return; } AsymmetricKeyAlgorithmProvider EccProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(alg); Key = EccProvider.CreateKeyPair((uint)RawEccKey.GetKeyLength(eccParms.curveID)); break; } default: Globs.Throw <ArgumentException>("Algorithm not supported"); break; } }
/// <summary> /// Calculates and returns the policy-hashes of the attached branches. /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public Tpm2bDigest[] GetPolicyHashArray(TpmAlgId hashAlg) { int numBranches = PolicyBranches.Count; if (numBranches < 2 || numBranches > 8) { Globs.Throw("GetPolicyHashArray: Must have between 2 and 8 branches in a PolicyOr"); } int i = 0; var childHashes = new Tpm2bDigest[numBranches]; foreach (PolicyAce branch in PolicyBranches) { childHashes[i++] = branch.GetPolicyDigest(hashAlg); } return(childHashes); }
/// <summary> /// Extract and return the SymDefObject that describes the associated symmetric algorithm that is used for key protection /// in storage keys. /// </summary> /// <param name="keyParms"></param> /// <returns></returns> internal static SymDefObject GetSymDef(TpmPublic keyParms) { TpmAlgId keyAlgId = keyParms.type; switch (keyAlgId) { case TpmAlgId.Rsa: var rsaParms = (RsaParms)keyParms.parameters; return(rsaParms.symmetric); case TpmAlgId.Ecc: var eccParms = (EccParms)keyParms.parameters; return(eccParms.symmetric); default: Globs.Throw("Unsupported algorithm"); return(new SymDefObject()); } }
/// <summary> /// De-envelope inner-wrapped duplication blob. /// TODO: Move this to TpmPublic and make it fully general /// </summary> /// <param name="exportedPrivate"></param> /// <param name="encAlg"></param> /// <param name="encKey"></param> /// <param name="nameAlg"></param> /// <param name="name"></param> /// <returns></returns> public static Sensitive SensitiveFromDupBlob(TpmPrivate exportedPrivate, SymDefObject encAlg, byte[] encKey, TpmAlgId nameAlg, byte[] name) { byte[] dupBlob = exportedPrivate.buffer; byte[] sensNoLen = null; using (SymCipher c = Create(encAlg, encKey)) { byte[] innerObject = null; if (c == null) { if (encAlg.Algorithm != TpmAlgId.Null) { return(null); } else { return(Marshaller.FromTpmRepresentation <Sensitive>(Marshaller.Tpm2BToBuffer(dupBlob))); } } innerObject = c.Decrypt(dupBlob); byte[] innerIntegrity, sensitive; KDF.Split(innerObject, 16 + CryptoLib.DigestSize(nameAlg) * 8, out innerIntegrity, 8 * (innerObject.Length - CryptoLib.DigestSize(nameAlg) - 2), out sensitive); byte[] expectedInnerIntegrity = Marshaller.ToTpm2B( CryptoLib.HashData(nameAlg, sensitive, name)); if (!Globs.ArraysAreEqual(expectedInnerIntegrity, innerIntegrity)) { Globs.Throw("SensitiveFromDupBlob: Bad inner integrity"); } sensNoLen = Marshaller.Tpm2BToBuffer(sensitive); } var sens = Marshaller.FromTpmRepresentation <Sensitive>(sensNoLen); return(sens); }
/// <summary> /// Assuming a ushort-prepended array, return the payload (if properly formed). /// </summary> /// <param name="x"></param> /// <returns></returns> static public byte[] Tpm2BToBuffer(byte[] x) { var m = new Marshaller(x); var len = m.Get <ushort>(); if (len != x.Length - 2) { Globs.Throw <ArgumentException>("Tpm2BToBuffer: Ill formed TPM2B"); if (x.Length < 2) { return(new byte[0]); } len = (ushort)(x.Length - 2); } var ret = new byte[len]; Array.Copy(x, 2, ret, 0, len); return(ret); }
public bool PkcsVerify(byte[] m, byte[] s, TpmAlgId hashAlg) { if (s.Length != KeySize) { throw new Exception("Invalid signature"); } int k = KeySize; BigInteger sig = FromBigEndian(s); BigInteger emx = BigInteger.ModPow(sig, E, N); byte[] emDecrypted = ToBigEndian(emx, KeySize); byte[] emPrime = CryptoEncoders.Pkcs15Encode(m, k, hashAlg); if (!Globs.ArraysAreEqual(emPrime, emDecrypted)) { return(false); } return(true); }
private Object FromNetValueType(Type tp) { byte[] data = Buffer.Extract(Globs.SizeOf(tp)); if (data == null) { return(null); } if (Repr == DataRepresentation.Tpm) { return(Globs.NetToHostValue(tp, data)); } if (Repr == DataRepresentation.LittleEndian) { return(Globs.FromBytes(tp, data)); } // Unsupported type Debug.Assert(false); return(null); }
// Returns the PcrSelection[] for the current PcrValueCollection public PcrSelection[] GetPcrSelectionArray() { // find all referenced algorithms var referencedAlgs = new List <TpmAlgId>(); foreach (PcrValue v in Values) { // todo reference or value contains? if (!referencedAlgs.Contains(v.value.HashAlg)) { referencedAlgs.Add(v.value.HashAlg); } } var selection = new PcrSelection[referencedAlgs.Count]; int count = 0; foreach (TpmAlgId algId in referencedAlgs) { selection[count++] = new PcrSelection(algId, new uint[0]); } uint bankNum = 0; foreach (TpmAlgId algId in referencedAlgs) { foreach (PcrValue val in Values) { if (val.value.HashAlg != algId) { continue; } // Do we already have a PcrValue with the same {alg, pcrNum?} if (selection[bankNum].IsPcrSelected(val.index)) { Globs.Throw("PcrValueCollection.GetPcrSelectionArray: PCR is referenced more than once"); } // Else select it selection[bankNum].SelectPcr(val.index); } bankNum++; } return(selection); }
public override void Connect() { TbsWrapper.TBS_CONTEXT_PARAMS contextParams; UIntPtr tbsContext = UIntPtr.Zero; contextParams.Version = TbsWrapper.TBS_CONTEXT_VERSION.TWO; contextParams.Flags = TbsWrapper.TBS_CONTEXT_CREATE_FLAGS.IncludeTpm20; TbsWrapper.TBS_RESULT result = TbsWrapper.NativeMethods .Tbsi_Context_Create(ref contextParams, ref tbsContext); Debug.WriteLine(Globs.GetResourceString("TbsHandle:") + tbsContext.ToUInt32()); if (result != TbsWrapper.TBS_RESULT.SUCCESS) { throw new Exception("Failed to create TBS context: Error {" + result + "}"); } TbsHandle = tbsContext; OriginalHandle = tbsContext; }
// ReSharper disable once InconsistentNaming public static byte[] KDFa(TpmAlgId hmacHash, byte[] hmacKey, string label, byte[] contextU, byte[] contextV, uint numBitsRequired) { int bitsPerLoop = CryptoLib.DigestSize(hmacHash) * 8; long numLoops = (numBitsRequired + bitsPerLoop - 1) / bitsPerLoop; var kdfStream = new byte[numLoops * bitsPerLoop / 8]; for (int j = 0; j < numLoops; j++) { byte[] toHmac = Globs.Concatenate(new[] { Globs.HostToNet(j + 1), Encoding.UTF8.GetBytes(label), Globs.HostToNet((byte)0), contextU, contextV, Globs.HostToNet(numBitsRequired) }); byte[] fragment = CryptoLib.HmacData(hmacHash, hmacKey, toHmac); Array.Copy(fragment, 0, kdfStream, j * bitsPerLoop / 8, fragment.Length); } return(Globs.ShiftRight(kdfStream, (int)(bitsPerLoop * numLoops - numBitsRequired))); }
/// <summary> /// Calculate the session-key from the nonces and salt/bound values (if present) /// </summary> public void CalcSessionKey() { if (Salt == SaltNeeded) { Globs.Throw("Unencrypted salt value must be provided for the session" + Handle.handle.ToString("X8")); } // Compute Handle.Auth in accordance with Part 1, 19.6.8. if (Salt == null && BindObject == TpmRh.Null) { SessionKey = new byte[0]; return; } byte[] auth = Globs.TrimTrailingZeros(BindObject.Auth); byte[] hmacKey = Globs.Concatenate(auth, Salt); SessionKey = KDF.KDFa(AuthHash, hmacKey, "ATH", NonceTpm, NonceCaller, TpmHash.DigestSize(AuthHash) * 8); }
private static byte[] ShiftRightInternal(byte[] x, int numBits) { if (numBits > 7) { Globs.Throw <ArgumentException>("ShiftRightInternal: Can only shift up to 7 bits"); numBits = 0; } int numCarryBits = 8 - numBits; var y = new byte[x.Length]; for (int j = x.Length - 1; j >= 0; j--) { y[j] = (byte)(x[j] >> numBits); if (j != 0) { y[j] |= (byte)(x[j - 1] << numCarryBits); } } return(y); }