/// <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 SensitiveFromDuplicateBlob(TpmPrivate exportedPrivate, SymDefObject encAlg, byte[] encKey, TpmAlgId nameAlg, byte[] name) { byte[] dupBlob = exportedPrivate.buffer; byte[] sensNoLen; using (SymmCipher c = Create(encAlg, encKey)) { byte[] 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("SensitiveFromDuplicateBlob: Bad inner integrity"); } sensNoLen = Marshaller.Tpm2BToBuffer(sensitive); } var sens = Marshaller.FromTpmRepresentation <Sensitive>(sensNoLen); return(sens); }
public static byte[] PssEncode(byte[] m, TpmAlgId hashAlg, int sLen, int emBits) { var emLen = (int)Math.Ceiling(1.0 * emBits / 8); int hLen = CryptoLib.DigestSize(hashAlg); // 1 - Ignore // 2 byte[] mHash = TpmHash.FromData(hashAlg, m); // 3 if (emLen < hLen + sLen + 2) { if (Tpm2._TssBehavior.Passthrough) { return(new byte[0]); } else { throw new Exception("Encoding error"); } } // 4 byte[] salt = Globs.GetRandomBytes(sLen); // 5 byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt }); // 6 byte[] h = CryptoLib.HashData(hashAlg, mPrime); // 7 byte[] ps = Globs.GetZeroBytes(emLen - sLen - hLen - 2); // 8 byte[] db = Globs.Concatenate(new[] { ps, new byte[] { 0x01 }, salt }); // 9 byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg); // 10 byte[] maskedDb = XorEngine.Xor(db, dbMask); // 11 int numZeroBits = 8 * emLen - emBits; byte mask = GetByteMask(numZeroBits); maskedDb[0] &= mask; // 12 byte[] em = Globs.Concatenate(new[] { maskedDb, h, new byte[] { 0xbc } }); // 13 return(em); }
/// <summary> /// Return a new TpmHash set to the hash of the supplied data /// </summary> /// <param name="hashAlg"></param> /// <param name="dataToHash"></param> /// <returns></returns> public static TpmHash FromData(TpmAlgId hashAlg, byte[] dataToHash) { if (!CryptoLib.IsHashAlgorithm(hashAlg)) { Globs.Throw <ArgumentException>("TpmHash.FromData: Not a hash algorithm"); } return(new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, dataToHash))); }
/// <summary> /// Return a TpmHash that is the hash of Encoding.Unicode.GetBytes(password) /// </summary> /// <param name="hashAlg"></param> /// <param name="password"></param> /// <returns></returns> public static TpmHash FromString(TpmAlgId hashAlg, string password) { if (!CryptoLib.IsHashAlgorithm(hashAlg)) { Globs.Throw <ArgumentException>("TpmHash.FromString: Not a hash algorithm"); } return(new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, Encoding.Unicode.GetBytes(password)))); }
/// <summary> /// Make a new TpmHash from the hash of the TPM representation of data /// </summary> /// <param name="hashAlg"></param> /// <param name="data"></param> /// <returns></returns> public static TpmHash FromObject(TpmAlgId hashAlg, Object data) { var newHash = new TpmHash(hashAlg); byte[] temp = Marshaller.GetTpmRepresentation(data); newHash.HashData = CryptoLib.HashData(hashAlg, temp); return(newHash); }
/// <summary> /// Return a new TpmHash that is the hash of random data /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public static TpmHash FromRandom(TpmAlgId hashAlg) { if (!CryptoLib.IsHashAlgorithm(hashAlg)) { Globs.Throw <ArgumentException>("TpmHash.FromRandom: Not a hash algorithm"); } return(new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, Globs.GetRandomBytes((int)DigestSize(hashAlg))))); }
/// <summary> /// Sign using a non-default hash algorithm. /// </summary> /// <param name="data"></param> /// <param name="sigHash"></param> /// <returns></returns> public ISignatureUnion SignData(byte[] data, TpmAlgId sigHash) { var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { TpmAlgId sigScheme = rsaParams.scheme.GetUnionSelector(); switch (sigScheme) { case TpmAlgId.Rsassa: { if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsassa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); IBuffer sigBuffer = CryptographicEngine.SignHashedData(Key, CryptographicBuffer.CreateFromByteArray(digest)); byte[] sig; CryptographicBuffer.CopyToByteArray(sigBuffer, out sig); return(new SignatureRsassa(sigHash, sig)); } case TpmAlgId.Rsapss: { Globs.Throw <ArgumentException>("SignData(): PSS scheme is not supported"); return(null); } } Globs.Throw <ArgumentException>("Unsupported signature scheme"); return(null); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(null); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); IBuffer buf = CryptographicEngine.SignHashedData(Key, CryptographicBuffer.CreateFromByteArray(digest)); byte[] sig; CryptographicBuffer.CopyToByteArray(buf, out sig); int len = sig.Length / 2; return(new SignatureEcdsa(sigHash, Globs.CopyData(sig, 0, len), Globs.CopyData(sig, len, len))); } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(null); } // SignData()
/// <summary> /// Set the PRNG seed used by the tester. If this routine is not called then the seed is /// extracted from the system RNG. Note that there is on RNG shared by all threads using /// TPM library services, so non-determinism is to be expected in multi-threaded programs /// even when the RNG is seeded. /// </summary> /// <param name="seed"></param> public static void SetRngSeed(string seed) { lock (RandLock) { _randSeed = seed == null ? new byte[0] : CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(seed)); _randRound = 0; _randBuf = null; } }
/// <summary> /// Set the PRNG seed. If this routine is not called then the seed is generated /// by the system RNG. Note that there is one RNG shared by all threads using /// TPM library services, so non-determinism is to be expected in multi-threaded /// programs even when the RNG is seeded. /// </summary> public void SetRngSeed(string seed) { lock (this) { Seed = seed == null ? new byte[0] : CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(seed)); Round = 0; FillRandBuf(); } }
TkVerified SignApproval(Tpm2 tpm, byte[] approvedPolicy, byte[] policyRef, TpmHandle hSigKey, ISigSchemeUnion scheme = null) { byte[] name, qname; TpmPublic pub = tpm.ReadPublic(hSigKey, out name, out qname); byte[] dataToSign = Globs.Concatenate(approvedPolicy, policyRef); byte[] aHash = CryptoLib.HashData(pub.nameAlg, dataToSign); // Create an authorization certificate for the "approvedPolicy" var sig = tpm.Sign(hSigKey, aHash, scheme, new TkHashcheck()); return(tpm.VerifySignature(hSigKey, aHash, sig)); }
/// <summary> /// Calculate the qualified name of an object presumed loaded under the provided ancestral chain /// in a given hierarchy. /// </summary> /// <param name="hierarchyHandle"></param> /// <param name="children"></param> /// <returns></returns> public static byte[] GetQualifiedName(TpmHandle hierarchyHandle, TpmPublic[] children) { byte[] runningName = Marshaller.GetTpmRepresentation(hierarchyHandle); foreach (TpmPublic pub in children) { byte[] thisName = pub.GetName(); runningName = Globs.Concatenate ( Marshaller.GetTpmRepresentation(pub.nameAlg), CryptoLib.HashData(pub.nameAlg, new[] { runningName, thisName }) ); } return(runningName); }
/// <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); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { var m = new Marshaller(); m.Put(OperandB, "operandB"); m.Put(Offset, "offset"); m.Put(Operation, "operation"); byte[] toHash = m.GetBytes(); byte[] args = CryptoLib.HashData(hashAlg, toHash); m = new Marshaller(); m.Put(TpmCc.PolicyCounterTimer, "cc"); m.Put(args, "args"); return(GetNextAcePolicyDigest(hashAlg).Extend(m.GetBytes())); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { var m = new Marshaller(); m.Put(OperandB, "operandB"); m.Put(Offset, "offset"); m.Put(Operation, "operation"); byte[] args = CryptoLib.HashData(hashAlg, m.GetBytes()); m = new Marshaller(); m.Put(TpmCc.PolicyNV, "ord"); m.Put(args, "args"); m.Put(IndexName, "name"); return(GetNextAcePolicyDigest(hashAlg).Extend(m.GetBytes())); }
/// <summary> /// Get the hash of the concatenation of the values in the array order defined by the PcrSelection[] /// returned from GetPcrSelectionArray. /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public TpmHash GetSelectionHash(TpmAlgId hashAlg) { var m = new Marshaller(); PcrSelection[] selections = GetPcrSelectionArray(); foreach (PcrSelection sel in selections) { uint[] pcrIndices = sel.GetSelectedPcrs(); foreach (uint index in pcrIndices) { PcrValue v = GetSpecificValue(sel.hash, index); m.Put(v.value.HashData, "hash"); } } var valueHash = new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, m.GetBytes())); return(valueHash); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { int numBranches = PolicyBranches.Count; if (numBranches < 2 || numBranches > 8) { Globs.Throw("GetPolicyDigest: Must have between 2 and 8 branches in a PolicyOr"); } var m = new Marshaller(); m.Put(TpmHash.ZeroHash(hashAlg).HashData, "zero"); m.Put(TpmCc.PolicyOR, "ordinal"); foreach (PolicyAce branch in PolicyBranches) { TpmHash branchPolicyHash = branch.GetPolicyDigest(hashAlg); m.Put(branchPolicyHash.HashData, "h"); } byte[] polVal = CryptoLib.HashData(hashAlg, m.GetBytes()); return(new TpmHash(hashAlg, polVal)); }
/// <summary> /// Replace the hash value with the hash of the concatenation of the current value and the TPM representation /// of objectToExtend /// </summary> /// <param name="objectToExtend"></param> /// <returns></returns> public TpmHash Extend(Object objectToExtend) { byte[] temp = Marshaller.GetTpmRepresentation(objectToExtend); HashData = CryptoLib.HashData(HashAlg, HashData, temp); return(this); }
/// <summary> /// EME-OAEP PKCS1.2, section 9.1.1.1. /// </summary> /// <param name="message"></param> /// <param name="encodingParameters"></param> /// <param name="hashAlg"></param> /// <param name="modulusNumBytes"></param> /// <returns></returns> public static byte[] OaepEncode(byte[] message, byte[] encodingParameters, TpmAlgId hashAlg, int modulusNumBytes) { int encodedMessageLength = modulusNumBytes - 1; int messageLength = message.Length; int hashLength = CryptoLib.DigestSize(hashAlg); // 1 (Step numbers from RSA labs spec.) // Ignore the ParametersLength limitation // 2 if (messageLength > encodedMessageLength - 2 * hashLength - 1) { if (Tpm2._TssBehavior.Passthrough) { return(new byte[0]); } else { throw new ArgumentException("input message too long"); } } int psLen = encodedMessageLength - messageLength - 2 * hashLength - 1; var ps = new byte[psLen]; // 3 (Not needed.) for (int j = 0; j < psLen; j++) { ps[j] = 0; } // 4 byte[] pHash = CryptoLib.HashData(hashAlg, encodingParameters); // 5 var db = new byte[hashLength + psLen + 1 + messageLength]; var one = new byte[1]; one[0] = 1; pHash.CopyTo(db, 0); ps.CopyTo(db, pHash.Length); one.CopyTo(db, pHash.Length + ps.Length); message.CopyTo(db, pHash.Length + ps.Length + 1); // 6 byte[] seed = Globs.GetRandomBytes(hashLength); // 7 byte[] dbMask = CryptoLib.MGF(seed, encodedMessageLength - hashLength, hashAlg); // 8 byte[] maskedDb = XorEngine.Xor(db, dbMask); // 9 byte[] seedMask = CryptoLib.MGF(maskedDb, hashLength, hashAlg); // 10 byte[] maskedSeed = XorEngine.Xor(seed, seedMask); //11 var encodedMessage = new byte[maskedSeed.Length + maskedDb.Length]; maskedSeed.CopyTo(encodedMessage, 0); maskedDb.CopyTo(encodedMessage, maskedSeed.Length); // 12 return(encodedMessage); }
public static bool OaepDecode(byte[] eMx, byte[] encodingParms, TpmAlgId hashAlg, out byte[] decoded) { decoded = new byte[0]; var em = new byte[eMx.Length + 1]; Array.Copy(eMx, 0, em, 1, eMx.Length); int hLen = CryptoLib.DigestSize(hashAlg); int k = em.Length; // a. byte[] lHash = CryptoLib.HashData(hashAlg, encodingParms); // b. byte y = em[0]; byte[] maskedSeed = Globs.CopyData(em, 1, hLen); byte[] maskedDB = Globs.CopyData(em, 1 + hLen); // c. byte[] seedMask = CryptoLib.MGF(maskedDB, hLen, hashAlg); // d. byte[] seed = XorEngine.Xor(maskedSeed, seedMask); // e. byte[] dbMask = CryptoLib.MGF(seed, k - hLen - 1, hashAlg); // f. byte[] db = XorEngine.Xor(maskedDB, dbMask); // g. byte[] lHashPrime = Globs.CopyData(db, 0, hLen); // Look for the zero.. int j; for (j = hLen; j < db.Length; j++) { if (db[j] == 0) { continue; } if (db[j] == 1) { break; } return(false); } if (j == db.Length - 1) { return(false); } byte[] m = Globs.CopyData(db, j + 1); if (y != 0) { return(false); } if (!Globs.ArraysAreEqual(lHash, lHashPrime)) { return(false); } decoded = m; return(true); }
/// <summary> /// Sign using a non-default hash algorithm. /// </summary> /// <param name="data"></param> /// <param name="sigHash"></param> /// <returns></returns> public ISignatureUnion SignData(byte[] data, TpmAlgId sigHash) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif TpmAlgId sigScheme = rsaParams.scheme.GetUnionSelector(); switch (sigScheme) { case TpmAlgId.Rsassa: { if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsassa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT byte[] sig = Key.SignHash(digest, BcryptScheme.Rsassa, sigHash); #else byte[] sig = RsaProvider.SignData(data, CryptoLib.GetHashName(sigHash)); #endif return(new SignatureRsassa(sigHash, sig)); } case TpmAlgId.Rsapss: { #if true Globs.Throw <ArgumentException>("SignData(): PSS scheme is not supported"); return(null); #else if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsapss).hashAlg; } #if TSS_USE_BCRYPT byte[] sig = BCryptInterface.SignHash(KeyHandle, digest, sigHash, false); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); byte[] sig = rr.PssSign(digest, sigHash); #endif return(new SignatureRsapss(sigHash, sig)); #endif // false } } Globs.Throw <ArgumentException>("Unsupported signature scheme"); return(null); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(null); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT //throw new NotImplementedException("ECC signing with BCrypt is not implemented"); byte[] sig = Key.SignHash(digest, BcryptScheme.Ecdsa, sigHash); int len = sig.Length / 2; return(new SignatureEcdsa(sigHash, Globs.CopyData(sig, 0, len), Globs.CopyData(sig, len, len))); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); byte[] sig = EcdsaProvider.SignData(data); int fragLen = sig.Length / 2; var r = Globs.CopyData(sig, 0, fragLen); var s = Globs.CopyData(sig, fragLen, fragLen); return(new SignatureEcdsa(sigHash, r, s)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(null); } // SignData()
public override int GetHashCode() { byte[] objectData = GetTpmRepresentation(); return(BitConverter.ToInt32(objectData.Length <= sizeof(int) ? objectData : CryptoLib.HashData(TpmAlgId.Sha1, objectData), 0)); }
/// <summary> /// Verifies the signature over data or a digest. /// The data will be hashed internall by the method using hash algorithm from /// the signing scheme digest computed from the specified data buffer. /// The signing scheme is retrieved from the signature. The verification key /// shall have either compatible or null scheme. /// </summary> /// <param name="data">Byte buffer containing either digest or data to check against the signature</param> /// <param name="dataIsDigest">Specifies the type of 'data' parameter contents</param> /// <param name="signature">The signature</param> /// <returns>True if the verification succeeds.</returns> private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion sig) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif TpmAlgId sigScheme = sig.GetUnionSelector(); TpmAlgId sigHash = CryptoLib.SchemeHash(sig); var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif var s = sig as SignatureRsa; TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); if (sigScheme == TpmAlgId.Rsassa) { #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, s.sig, sigHash, true)); #else return(RsaProvider.VerifyHash(digest, CryptoLib.GetHashName(sigHash), s.sig)); #endif } if (sigScheme == TpmAlgId.Rsapss) { #if true Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported"); return(false); #else #if TSS_USE_BCRYPT return(BCryptInterface.VerifySignature(KeyHandle, digest, sig.sig, sigHash, false)); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); return(rr.PssVerify(digest, sig.sig, sigHash)); #endif #endif // false } Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme"); return(false); } var eccParams = PublicParms.parameters as EccParms; if (eccParams != null) { if (eccParams.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(false); } TpmAlgId keyScheme = eccParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } var s = sig as SignatureEcdsa; byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); byte[] sigBlob = Globs.Concatenate(s.signatureR, s.signatureS); #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, sigBlob)); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); return(EcdsaProvider.VerifyHash(digest, sigBlob)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(false); } // VerifySignature()
int IEqualityComparer <byte[]> .GetHashCode(byte[] obj) { return(BitConverter.ToInt32(CryptoLib.HashData(TpmAlgId.Sha1, obj as byte[]), 0)); }
/// <summary> /// The TPM always signs hash-sized data. This version of the VerifySignature /// performs the necessary hashing operation over arbitrarily-length data and /// verifies that the hash is properly signed. /// </summary> /// <param name="data"></param> /// <param name="sig"></param> /// <returns></returns> public bool VerifySignatureOverData(byte[] data, ISignatureUnion sig) { byte[] digest = CryptoLib.HashData(CryptoLib.SchemeHash(sig), data); return(VerifySignatureOverHash(digest, sig)); }
/// <summary> /// Creates a duplication blob for the current key that can be Imported as a child /// of newParent. Three forms are possible. GetPlaintextDuplicationBlob() allows /// plaintext-import. This function enables duplication with and without an /// inner wrapper (depending on whether innerWrapper is null) /// </summary> /// <param name="newParent"></param> /// <param name="innerWrapper"></param> /// <param name="encSecret"></param> /// <returns></returns> public TpmPrivate GetDuplicationBlob( TpmPublic pubNewParent, SymCipher innerWrapper, out byte[] encSecret) { byte[] encSensitive; if (innerWrapper == null) { // No inner wrapper encSensitive = Marshaller.ToTpm2B(Sensitive.GetTpmRepresentation()); Transform(encSensitive); } else { byte[] sens = Marshaller.ToTpm2B(Sensitive.GetTpmRepresentation()); byte[] toHash = Globs.Concatenate(sens, GetName()); Transform(toHash); byte[] innerIntegrity = Marshaller.ToTpm2B(CryptoLib.HashData( Public.nameAlg, toHash)); byte[] innerData = Globs.Concatenate(innerIntegrity, sens); Transform(innerData); encSensitive = innerWrapper.Encrypt(innerData); Transform(encSensitive); } byte[] seed; SymDefObject symDef = GetSymDef(pubNewParent).Copy(); // TPM duplication procedures always use CFB mode symDef.Mode = TpmAlgId.Cfb; using (var swNewParent = AsymCryptoSystem.CreateFrom(pubNewParent)) { switch (pubNewParent.type) { case TpmAlgId.Rsa: // The seed should be the same size as the scheme hash LastSeed = seed = Globs.GetRandomBytes( CryptoLib.DigestSize(swNewParent.OaepHash)); encSecret = swNewParent.EncryptOaep(seed, DuplicateEncodingParms); break; case TpmAlgId.Ecc: EccPoint pubEphem; seed = swNewParent.EcdhGetKeyExchangeKey(DuplicateEncodingParms, pubNewParent.nameAlg, out pubEphem); encSecret = Marshaller.GetTpmRepresentation(pubEphem); break; default: Globs.Throw <NotImplementedException>( "GetDuplicationBlob: Unsupported algorithm"); encSecret = new byte[0]; return(new TpmPrivate()); } } Transform(seed); Transform(encSecret); byte[] symKey = KDF.KDFa(pubNewParent.nameAlg, seed, "STORAGE", Public.GetName(), new byte[0], symDef.KeyBits); Transform(symKey); byte[] dupSensitive; using (SymCipher enc2 = SymCipher.Create(symDef, symKey)) { if (enc2 == null) { return(null); } dupSensitive = enc2.Encrypt(encSensitive); } Transform(dupSensitive); var npNameNumBits = CryptoLib.DigestSize(pubNewParent.nameAlg) * 8; byte[] hmacKey = KDF.KDFa(pubNewParent.nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], npNameNumBits); byte[] outerDataToHmac = Globs.Concatenate(dupSensitive, Public.GetName()); Transform(outerDataToHmac); byte[] outerHmac = Marshaller.ToTpm2B(CryptoLib.Hmac(pubNewParent.nameAlg, hmacKey, outerDataToHmac)); Transform(outerHmac); byte[] dupBlob = Globs.Concatenate(outerHmac, dupSensitive); Transform(dupBlob); return(new TpmPrivate(dupBlob)); }
/// <summary> /// Replace the hash value with the hash of the concatenation of the current hash value and DataToExtend /// </summary> /// <param name="dataToExtend"></param> /// <returns></returns> public TpmHash Event(byte[] dataToExtend) { HashData = CryptoLib.HashData(HashAlg, HashData, CryptoLib.HashData(HashAlg, dataToExtend)); return(this); }
/// <summary> /// Creates a duplication blob for the current key that can be Imported as a child /// of newParent. Three forms are possible. GetPlaintextDuplicationBlob() allows /// plaintext-import. This function enables duplication with and without an /// inner wrapper (depending on whether innerWrapper is null) /// </summary> /// <param name="newParent"></param> /// <param name="innerWrapper"></param> /// <param name="encryptedWrappingKey"></param> /// <returns></returns> 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)); }
private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion signature, TpmAlgId sigHash) { var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { var sig = signature as SignatureRsa; TpmAlgId sigScheme = sig.GetUnionSelector(); TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SchemeHash).hashAlg; } if (sigHash != sig.hash) { Globs.Throw <ArgumentException>("Key scheme hash and signature scheme hash do not match"); return(false); } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); if (sigScheme == TpmAlgId.Rsassa) { return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sig.sig))); } if (sigScheme == TpmAlgId.Rsapss) { Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported"); return(false); } Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme"); return(false); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(false); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); var sig = signature as SignatureEcdsa; byte[] sigBlob = Globs.Concatenate(sig.signatureR, sig.signatureS); return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sigBlob))); } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(false); } // VerifySignature()