Greetings folks, 

With moz-bz#1561637 having landed upstream (and subsequently v3.52 being
shipped downstream in Fedora), I've been testing JSS's SSLEngine with
TLSv1.3 again.

One of the issues I've had is there's no good indicator for either
key-exchange or post-handshake auth being started or completed by either
party (client or server).

SSLEngine (in Java) for those unaware has (roughly) the following semantics:

 - After beginHandshake() has been called, handshake status stays in
   NEED_WRAP, NEED_UNWRAP, or NEED_TASK until the handshake is
   complete. Then it moves to FINISHED and finally to
   NOT_HANDSHAKING.
 - beginHandshake() is called implicitly the first time from wrap()
   and unwrap().
 - If certs are required after the initial handshake (such as via PHA in
   TLSv1.3 or a full re-handshake when available in TLSv1.2 and earlier),
   beginHandshake() semantics apply again.


The last requirement is the "hard" one under TLSv1.3.

I've set a SSL_HandshakeCallback() that informs me when the initial
handshake is completed. This works fine for both client and
server-initiated re-handshakes under TLSv1.2. However, this callback
is never executed under TLSv1.3 (in part) because PHA and re-key requests
aren't strictly a new handshake.

So what I ask are:

 - Is there a reliable way to tell (as both a client and server) when
   PHA/rekey requests have started?

 - Is there a reliable way to tell (as both a client and server) when
   PHA/rekey requests have completed?

 - Is there a reliable way to tell (as both a client and server) when
   a handshake has been initiated by the other party (on TLS < 1.2)?


I'm fine living without 1 and 3, but 2 is the more of an issue for me.

I'd be happy to submit the code changes to trigger SSL_HandshakeCallback
via TLSv1.3 PHA/re-key requests -- but I'm not sure if that'd technically
conform to the function's documentation:

> /*
> ** Set the callback that gets called when a TLS handshake is complete. The
> ** handshake callback is called after verifying the peer's Finished message 
> and
> ** before processing incoming application data.
> **
> ** For the initial handshake: If the handshake false started (see
> ** SSL_ENABLE_FALSE_START), then application data may already have been sent
> ** before the handshake callback is called. If we did not false start then the
> ** callback will get called before any application data is sent.
> */
> typedef void(PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
>                                                 void *client_data);
> SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
>                                            SSLHandshakeCallback cb, void 
> *client_data);

It might be surprising behavior? But on the other hand, these two do
kinda replace the (insecure) second handshake. Perhaps gating it behind
an option flag would suffice though (SSL_HANDSHAKE_CALLBACK_FOR_PHA or
some such)?

When looking at the other SSL_SendCertificateRequest experimental API
docs, it does say AuthCertificateComplete is called on the server side:

> /* This function allows a server application to trigger
>  * re-authentication (TLS 1.3 only) after handshake.
>  *
>  * This function will cause a CertificateRequest message to be sent by
>  * a server.  This can be called once at a time, and is not allowed
>  * until an answer is received.
>  *
>  * This function is not allowed for use with DTLS or when external
>  * PSK authentication has been negotiated. SECFailure is returned
>  * in both cases.
>  *
>  * The AuthCertificateCallback is called when the answer is received.
>  * If the answer is accepted by the server, the value returned by
>  * SSL_PeerCertificate() is replaced.  If you need to remember all the
>  * certificates, you will need to call SSL_PeerCertificate() and save
>  * what you get before calling this.
>  *
>  * If the AuthCertificateCallback returns SECFailure, the connection
>  * is aborted.
>  */
> #define SSL_SendCertificateRequest(fd)                 \
>     SSL_EXPERIMENTAL_API("SSL_SendCertificateRequest", \
>                          (PRFileDesc * _fd),           \
>                          (fd))


But this doesn't help on the client side. Additionally, my situation with
AuthCertificateCallback is... complicated (it is either not explicitly set
to use the default NSS value, set to something with no knowledge of my
SSLEngine, or something with knowledge of the SSLEngine) -- so I'm not
sure I like that design.



Thoughts? I feel like I might be missing something.

- Alex

-- 
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to