in TPM Parser/Tpm2Lib/CryptoLib.cs [422:496]
public static bool PssVerify(byte[] m, byte[] em, int sLen, int emBits, TpmAlgId hashAlg)
{
var emLen = (int)Math.Ceiling(1.0 * emBits / 8);
int hLen = CryptoLib.DigestSize(hashAlg);
// 1 - Skip
// 2
byte[] mHash = TpmHash.FromData(hashAlg, m);
// 3
if (emLen < hLen + sLen + 2)
{
return false;
}
// 4
if (em[em.Length - 1] != 0xbc)
{
return false;
}
// 5
byte[] maskedDB = Globs.CopyData(em, 0, emLen - hLen - 1);
byte[] h = Globs.CopyData(em, emLen - hLen - 1, hLen);
// 6
int numZeroBits = 8 * emLen - emBits;
// First numZero bits is zero in mask
byte mask = GetByteMask(numZeroBits);
if ((maskedDB[0] & mask) != maskedDB[0])
{
return false;
}
// 7
byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg);
// 8
byte[] db = XorEngine.Xor(maskedDB, dbMask);
// 9
int numZeroBits2 = 8 * emLen - emBits;
byte mask2 = GetByteMask(numZeroBits2);
db[0] &= mask2;
// 10
for (int j = 0; j < emLen - hLen - sLen - 2; j++)
{
if (db[j] != 0)
{
return false;
}
}
if (db[emLen - hLen - sLen - 1 - 1] != 1)
{
return false;
}
// 11
byte[] salt = Globs.CopyData(db, db.Length - sLen);
// 12
byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt});
// 13
byte[] hPrime = TpmHash.FromData(hashAlg, mPrime);
// 14
bool match = Globs.ArraysAreEqual(h, hPrime);
if (match == false)
{
return false;
}
return true;
}