FERcsI
FERcsI

Reputation: 458

TLS1.3 Certificate Verification complete algorithm

I would like to implement TLS1.3 Certificate Verify functionality (without external library, openssl etc.).

I am a bit confused about the documentation. According to it I am believing, that the algorithm, using RSA-PSS-RSAE-SHA256 is the following:

  1. Parsing and checking certificates received in the Certificate handshake is Ok. From here I can also get the public key (RSA n and e) for the Cerificate Verify

  2. According to RFC8446/4.4.3, the content to sign consists of: 64 * 0x20 + "TLS 1.3, server CertificateVerify" + 0x00 + transcript-hash of messages (in our case, sha256 hash of concatenating all handshakes ClientHello...Certificate). I consider content to be message M in the followings.

  3. RSASSA-PPS with EMSA-PSS (for the selected signature algorithm) is described in RFC8017/8.1.2, 9.1.2. There are two main steps: The signature has to be RSA-decrypted (8.1.2); EMSA-PSS verification has to be done (9.1.2):

    1. The firts one is rather trivial, resulting in Encoded Messaget EM
    2. hash (H), and salt can be extracted from that one. Details are in the RFC document
    3. Hash of M must be calculated: mHash = sha256(M)
    4. H' can be calculated by sha256 hash of (8 * 0x00 + mHash + salt)
  4. If H == H', then verification is successful.

At least this is how I interpret this. But it does not work:

  1. I am almost sure, that my transcript-hash is good, I use the handshake concatenation in multiple positions in TLS communcation successfully, and calculating the hash of it is also not a big deal
  2. So I am almost sure, that the content (prefixing the content hash with elements as seen above) is also Ok.
  3. There might be a gap between RFC8446 and RFC8017, but I did not find any info on that. Maybe M of RSASSA-PPS is not the same as the content of TLS Certificate Verify content.
  4. I could evaluate H and salt using the signature and the public key (there are good checking opportunities for this, so this is surely Ok in my case)

But as a result H != H'.

So I probably misunderstand something with this algorithm. Maybe the message M should be something different, or something else is missing. Is there any good description somewhere, which leads through this process step by step? Or a source which can be run part by part, so that I can check where my implementation deviates? (Pyhton or perl is preferred, but any major languages can be good)

Upvotes: 0

Views: 280

Answers (1)

srabutdotcom
srabutdotcom

Reputation: 57

I think the problem is that you use publicKey instead of privateKey. Signature is created using privateKey which is paired with publicKey inside certificate.

revised:

  1. First at all, the intention of TLS1.3 Certificate Verify is to create signature using PrivateKey that corresponded to PublicKey in certificate being verified. So the client can verify using publicKey delivered inside Certificate delivered in TLS handshake.
  2. The message (M) to be signed in your no.2 is correct and should be complied with RFC8446.
  3. The signature is then created using RSASSA_PSS with argument supplied M. Inside this function, there are several step: (1). encode M using EM = EMSA_PSS(M), (2). Convert it to integer using m = OS2IP(EM), (3). apply signature primitive, s = RSASP1(m, privateKey:{n,d})., and (4). convert to Signature, S = I2OSP(s, modulus.length).

Inside EMSA_PSS there are several step including salting, concatenate, hashing, merging, and masking using MGF1 function.

The formula above descripted in RFC8017. Hope the made you clear.

Upvotes: 0

Related Questions