1- /*
2- * Perform a TLSv1.3 server-side handshake.
1+ /**
2+ * @file server.c
3+ * @brief Perform a TLSv1.3 server-side handshake
34 *
5+ * @copyright
46 * Copyright (c) 2023 Oracle and/or its affiliates.
57 * Copyright (c) 2024 Red Hat, Inc.
6- *
8+ */
9+
10+ /*
711 * ktls-utils is free software; you can redistribute it and/or
812 * modify it under the terms of the GNU General Public License as
913 * published by the Free Software Foundation; version 2.
4246#include "tlshd.h"
4347#include "netlink.h"
4448
49+ /**
50+ * @var gnutls_privkey_t tlshd_server_pq_privkey
51+ * Server peer's post-quantum private key
52+ */
4553static gnutls_privkey_t tlshd_server_pq_privkey ;
54+
55+ /**
56+ * @var gnutls_privkey_t tlshd_server_privkey
57+ * Server peer's RSA private key
58+ */
4659static gnutls_privkey_t tlshd_server_privkey ;
60+
61+ /**
62+ * @var unsigned int tlshd_server_pq_certs_len
63+ * Count of server peer's PQ certificates
64+ */
4765static unsigned int tlshd_server_pq_certs_len = TLSHD_MAX_CERTS ;
66+
67+ /**
68+ * @var unsigned int tlshd_server_certs_len
69+ * Count of server peer's certificates
70+ */
4871static unsigned int tlshd_server_certs_len = TLSHD_MAX_CERTS ;
72+
73+ /**
74+ * @var gnutls_pcert_st tlshd_server_certs
75+ * Server peer's certificates
76+ */
4977static gnutls_pcert_st tlshd_server_certs [TLSHD_MAX_CERTS ];
78+
79+ /**
80+ * @var gnutls_pk_algorithm_t tlshd_server_pq_pkalg
81+ * Server peer certificate's public key algorithms
82+ */
5083static gnutls_pk_algorithm_t tlshd_server_pq_pkalg = GNUTLS_PK_UNKNOWN ;
5184
85+ /**
86+ * @brief Retrieve server certificates to be used for ServerHello
87+ * @param[in] parms Handshake parameters
88+ *
89+ * @retval true Server certificates were found. Caller must release
90+ * the certificates using tlshd_x509_server_put_certs.
91+ * @retval false No usable server certificates were found
92+ */
5293static bool tlshd_x509_server_get_certs (struct tlshd_handshake_parms * parms )
5394{
5495 if (parms -> x509_cert != TLS_NO_CERT )
@@ -61,6 +102,9 @@ static bool tlshd_x509_server_get_certs(struct tlshd_handshake_parms *parms)
61102 & tlshd_server_pq_pkalg );
62103}
63104
105+ /**
106+ * @brief Release server certificates that were used for ServerHello
107+ */
64108static void tlshd_x509_server_put_certs (void )
65109{
66110 unsigned int i ;
@@ -69,6 +113,14 @@ static void tlshd_x509_server_put_certs(void)
69113 gnutls_pcert_deinit (& tlshd_server_certs [i ]);
70114}
71115
116+ /**
117+ * @brief Retrieve the private key to be used for ServerHello
118+ * @param[in] parms Handshake parameters
119+ *
120+ * @retval true Private key was found. Caller must release the
121+ * private key using tlshd_x509_server_put_privkey.
122+ * @retval false No usable private key was found
123+ */
72124static bool tlshd_x509_server_get_privkey (struct tlshd_handshake_parms * parms )
73125{
74126 if (parms -> x509_privkey != TLS_NO_PRIVKEY )
@@ -79,12 +131,20 @@ static bool tlshd_x509_server_get_privkey(struct tlshd_handshake_parms *parms)
79131 & tlshd_server_privkey );
80132}
81133
134+ /**
135+ * @brief Release the private key that was used for ServerHello
136+ */
82137static void tlshd_x509_server_put_privkey (void )
83138{
84139 gnutls_privkey_deinit (tlshd_server_pq_privkey );
85140 gnutls_privkey_deinit (tlshd_server_privkey );
86141}
87142
143+ /**
144+ * @brief Audit trust chain of incoming client certificate
145+ * @param[in] req_ca_rdn
146+ * @param[in] nreqs
147+ */
88148static void tlshd_x509_log_issuers (const gnutls_datum_t * req_ca_rdn , int nreqs )
89149{
90150 char issuer_dn [256 ];
@@ -107,18 +167,25 @@ static void tlshd_x509_log_issuers(const gnutls_datum_t *req_ca_rdn, int nreqs)
107167}
108168
109169/**
110- * tlshd_x509_retrieve_key_cb - Initialize client's x.509 identity
170+ * @brief Initialize the server peer's x.509 identity
171+ * @param[in] session session in the midst of a handshake
172+ * @param[in] req_ca_rdn
173+ * @param[in] nreqs
174+ * @param[in] pk_algos
175+ * @param[in] pk_algos_length
176+ * @param[out] pcert
177+ * @param[out] pcert_length
178+ * @param[out] privkey
179+ *
180+ * @retval 0 Success; output parameters are set accordingly
181+ * @retval -1 Failure
111182 *
112183 * Callback function is of type gnutls_certificate_retrieve_function2
113184 *
114185 * Initial implementation based on the cert_callback() function in
115186 * gnutls/doc/examples/ex-cert-select.c.
116187 *
117188 * Sketched-in and untested.
118- *
119- * Return values:
120- * %0: Success; output parameters are set accordingly
121- * %-1: Failure
122189 */
123190static int
124191tlshd_x509_retrieve_key_cb (gnutls_session_t session ,
@@ -197,6 +264,13 @@ tlshd_x509_retrieve_key_cb(gnutls_session_t session,
197264 return 0 ;
198265}
199266
267+ /**
268+ * @brief Initialize server-side trust store
269+ * @param[out] cred Trust store to initialize
270+ *
271+ * @returns a GnuTLS error code. Caller must release credentials
272+ * using gnutls_certificate_free_credentials(3).
273+ */
200274static int tlshd_server_get_truststore (gnutls_certificate_credentials_t cred )
201275{
202276 char * pathname ;
@@ -227,9 +301,9 @@ static int tlshd_server_get_truststore(gnutls_certificate_credentials_t cred)
227301}
228302
229303/**
230- * tlshd_server_x509_verify_function - Verify remote's x.509 certificate
231- * @session: session in the midst of a handshake
232- * @parms: handshake parameters
304+ * @brief Verify remote's x.509 certificate
305+ * @param[in] session Session in the midst of a handshake
306+ * @param[in] parms Handshake parameters
233307 *
234308 * A return value of %GNUTLS_E_SUCCESS indicates that the TLS session
235309 * has been allowed to continue. tlshd either sets the peerid array if
@@ -299,13 +373,24 @@ static int tlshd_server_x509_verify_function(gnutls_session_t session,
299373 return GNUTLS_E_CERTIFICATE_ERROR ;
300374}
301375
376+ /**
377+ * @brief Verify a remote peer's x.509 certificate (TLSv1.3)
378+ * @param[in] session session in the midst of a handshake
379+ *
380+ * @retval GNUTLS_E_SUCCESS Certificate has been successfully verified
381+ * @retval GNUTLS_E_CERTIFICATE_ERROR Certificate verification failed
382+ */
302383static int tlshd_tls13_server_x509_verify_function (gnutls_session_t session )
303384{
304385 struct tlshd_handshake_parms * parms = gnutls_session_get_ptr (session );
305386
306387 return tlshd_server_x509_verify_function (session , parms );
307388}
308389
390+ /**
391+ * @brief Process an x.509-based TLS handshake with a server certificate
392+ * @param[in] parms Handshake parameters
393+ */
309394static void tlshd_tls13_server_x509_handshake (struct tlshd_handshake_parms * parms )
310395{
311396 gnutls_certificate_credentials_t xcred ;
@@ -386,17 +471,16 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
386471}
387472
388473/**
389- * tlshd_server_psk_cb - Validate remote's username
390- * @session: session in the midst of a handshake
391- * @username: remote 's username
392- * @key: PSK matching @ username
474+ * @brief Validate the remote peer 's username
475+ * @param[in] session Session in the midst of a handshake
476+ * @param[in] username Remote peer 's username
477+ * @param[in] key PSK matching " username"
393478 *
394- * Searches for a key with description @ username in the session
395- * keyring, and stores the PSK data in @ key if found.
479+ * Searches for a key with description " username" in the session
480+ * keyring, and stores the PSK data in " key" if found.
396481 *
397- * Return values:
398- * %0: Matching key has been stored in @key
399- * %-1: Error during lookup, @key is not updated
482+ * @retval 0 Matching key has been stored in "key"
483+ * @retval -1 Error during lookup, "key" is not updated
400484 */
401485static int tlshd_server_psk_cb (gnutls_session_t session ,
402486 const char * username , gnutls_datum_t * key )
@@ -426,6 +510,10 @@ static int tlshd_server_psk_cb(gnutls_session_t session,
426510 return 0 ;
427511}
428512
513+ /**
514+ * @brief Process an PSK-based TLS handshake (TLSv1.3)
515+ * @param[in] parms Handshake parameters
516+ */
429517static void tlshd_tls13_server_psk_handshake (struct tlshd_handshake_parms * parms )
430518{
431519 gnutls_psk_server_credentials_t psk_cred ;
@@ -471,9 +559,8 @@ static void tlshd_tls13_server_psk_handshake(struct tlshd_handshake_parms *parms
471559}
472560
473561/**
474- * tlshd_tls13_serverhello_handshake - send a TLSv1.3 ServerHello
475- * @parms: handshake parameters
476- *
562+ * @brief Send a TLSv1.3 ServerHello
563+ * @param[in] parms Handshake parameters
477564 */
478565void tlshd_tls13_serverhello_handshake (struct tlshd_handshake_parms * parms )
479566{
@@ -491,6 +578,17 @@ void tlshd_tls13_serverhello_handshake(struct tlshd_handshake_parms *parms)
491578}
492579
493580#ifdef HAVE_GNUTLS_QUIC
581+ /**
582+ * @brief Verify the ALPNs presented by a remote peer
583+ * @param[in] session
584+ * @param[in] htype
585+ * @param[in] when
586+ * @param[in] incoming
587+ * @param[in] msg
588+ *
589+ * @retval 0 ALPN verification was successful
590+ * @retval -1 ALPN verification failed
591+ */
494592static int tlshd_quic_server_alpn_verify (gnutls_session_t session , unsigned int htype ,
495593 unsigned int when , unsigned int incoming ,
496594 const gnutls_datum_t * msg )
@@ -515,6 +613,25 @@ static int tlshd_quic_server_alpn_verify(gnutls_session_t session, unsigned int
515613 return 0 ;
516614}
517615
616+ /**
617+ * @brief Anti-reply protection
618+ * @param[in] dbf
619+ * @param[in] exp_time
620+ * @param[in] key
621+ * @param[in] data
622+ *
623+ * Currently, tlshd handles each handshake request in a new process
624+ * rather than a thread. As a result, it cannot share the
625+ * gnutls_anti_replay_t object across processes. This causes 0-RTT
626+ * data to be automatically disabled, since
627+ * _gnutls_anti_replay_check() fails validation in the absence of a
628+ * shared anti-replay context.
629+ *
630+ * To properly support 0-RTT data, we need to enable sharing of the
631+ * gnutls_anti_replay_t object across processes in some way.
632+ *
633+ * @retval 0 Not a replay
634+ */
518635static int tlshd_quic_server_anti_replay_db_add_func (void * dbf , time_t exp_time ,
519636 const gnutls_datum_t * key ,
520637 const gnutls_datum_t * data )
@@ -523,15 +640,38 @@ static int tlshd_quic_server_anti_replay_db_add_func(void *dbf, time_t exp_time,
523640 return 0 ;
524641}
525642
643+ /**
644+ * @var gnutls_anti_replay_t tlshd_quic_server_anti_replay
645+ * Shared anti-replay context
646+ */
526647static gnutls_anti_replay_t tlshd_quic_server_anti_replay ;
527648
649+ /**
650+ * @brief Verify a remote peer's x.509 certificate (QUIC)
651+ * @param[in] session session in the midst of a handshake
652+ *
653+ * @retval GNUTLS_E_SUCCESS Certificate has been successfully verified
654+ * @retval GNUTLS_E_CERTIFICATE_ERROR Certificate verification failed
655+ */
528656static int tlshd_quic_server_x509_verify_function (gnutls_session_t session )
529657{
530658 struct tlshd_quic_conn * conn = gnutls_session_get_ptr (session );
531659
532660 return tlshd_server_x509_verify_function (session , conn -> parms );
533661}
534662
663+ /**
664+ * @brief Validate the remote peer's username
665+ * @param[in] session Session in the midst of a handshake
666+ * @param[in] username Remote peer's username
667+ * @param[in] key PSK matching "username"
668+ *
669+ * Searches for a key with description "username" in the session
670+ * keyring, and stores the PSK data in "key" if found.
671+ *
672+ * @retval 0 Matching key has been stored in "key"
673+ * @retval -1 Error during lookup, "key" is not updated
674+ */
535675static int tlshd_quic_server_psk_cb (gnutls_session_t session , const char * username ,
536676 gnutls_datum_t * key )
537677{
@@ -562,6 +702,10 @@ static int tlshd_quic_server_psk_cb(gnutls_session_t session, const char *userna
562702 return 0 ;
563703}
564704
705+ /**
706+ * @brief Prepare a session for a QUIC server handshake using an x.509 cert
707+ * @param[in] conn
708+ */
565709static void tlshd_quic_server_set_x509_session (struct tlshd_quic_conn * conn )
566710{
567711 struct tlshd_handshake_parms * parms = conn -> parms ;
@@ -631,6 +775,10 @@ static void tlshd_quic_server_set_x509_session(struct tlshd_quic_conn *conn)
631775 tlshd_log_gnutls_error (ret );
632776}
633777
778+ /**
779+ * @brief Prepare a session for a QUIC client handshake using a pre-shared key
780+ * @param[in] conn
781+ */
634782static void tlshd_quic_server_set_psk_session (struct tlshd_quic_conn * conn )
635783{
636784 gnutls_psk_server_credentials_t cred ;
@@ -665,9 +813,8 @@ static void tlshd_quic_server_set_psk_session(struct tlshd_quic_conn *conn)
665813}
666814
667815/**
668- * tlshd_quic_serverhello_handshake - send a QUIC Server Initial
669- * @parms: handshake parameters
670- *
816+ * @brief Send a QUIC Server Initial
817+ * @param[in] parms Handshake parameters
671818 */
672819void tlshd_quic_serverhello_handshake (struct tlshd_handshake_parms * parms )
673820{
@@ -699,6 +846,10 @@ void tlshd_quic_serverhello_handshake(struct tlshd_handshake_parms *parms)
699846 tlshd_quic_conn_destroy (conn );
700847}
701848#else
849+ /**
850+ * @brief Send a QUIC Server Initial
851+ * @param[in] parms Handshake parameters
852+ */
702853void tlshd_quic_serverhello_handshake (struct tlshd_handshake_parms * parms )
703854{
704855 tlshd_log_debug ("QUIC handshake is not enabled (%d)" , parms -> auth_mode );
0 commit comments