Dans TLSv1.2 et TLSv1.3, le serveur et le client considèrent que la poignée de main est terminée lorsqu'ils ont tous deux écrit un message "Finished" et reçu un message du pair. Voici à quoi ressemble la poignée de main dans TLSv1.2 (extrait de RFC5246) :
Client Server
ClientHello -------->
ServerHello
Certificate*
ServerKeyExchange*
CertificateRequest*
<-------- ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished -------->
[ChangeCipherSpec]
<-------- Finished
Application Data <-------> Application Data
Vous pouvez donc voir ici que le client envoie ses messages Certificate et Finished lors de son deuxième vol de communication avec le serveur. Il attend ensuite de recevoir les messages ChangeCipherSpec et Finished en retour du serveur avant de considérer la poignée de main comme "complète" et de pouvoir commencer à envoyer des données d'application.
Voici le flux équivalent pour TLSv1.3 tiré de la RFC8446 :
Client Server
Key ^ ClientHello
Exch | + key_share*
| + signature_algorithms*
| + psk_key_exchange_modes*
v + pre_shared_key* -------->
ServerHello ^ Key
+ key_share* | Exch
+ pre_shared_key* v
{EncryptedExtensions} ^ Server
{CertificateRequest*} v Params
{Certificate*} ^
{CertificateVerify*} | Auth
{Finished} v
<-------- [Application Data*]
^ {Certificate*}
Auth | {CertificateVerify*}
v {Finished} -------->
[Application Data] <-------> [Application Data]
L'un des avantages de TLSv1.3 est qu'il accélère le temps nécessaire à la réalisation d'une poignée de main. Dans TLSv1.3, le client reçoit du serveur le message "Finished". antes de il renvoie ses messages de Certificat et de Fini. Au moment où le client envoie son message "Finished", il a déjà reçu le message "Finished" et donc la poignée de main est terminée et il peut immédiatement commencer à envoyer des données d'application.
Cela signifie bien sûr que le client ne saura pas si le serveur a accepté ou non le certificat avant de lire les données du serveur. Si le certificat a été rejeté, la prochaine chose que le client lira sera une alerte d'échec (sinon, ce seront des données d'application normales).
Je suis conscient que le protocole de poignée de main a été complètement réécrit dans le cadre de TLS 1.3, mais il me semble qu'avec tous les différents rappels disponibles, je devrais être en mesure, d'une manière ou d'une autre, côté client, de déterminer que l'authentification a échoué sans avoir à tenter d'écrire des données au serveur.
Ce n'est pas l'écriture de données sur le serveur qui est importante - c'est lecture données. Ce n'est qu'à ce moment-là que vous saurez si le serveur a envoyé une alerte ou simplement des données d'application normales. Tant que ces données n'ont pas été lues, aucun rappel n'est disponible dans OpenSSL pour vous le dire, car OpenSSL lui-même ne le sait pas en raison du protocole sous-jacent.