@@ -260,18 +260,66 @@ bool tlshd_config_get_crl(int peer_type, char **result)
260260 return true;
261261}
262262
263+ #ifdef HAVE_GNUTLS_MLDSA
264+ static bool tlshd_cert_check_pk_alg (gnutls_datum_t * data ,
265+ gnutls_pk_algorithm_t * pkalg )
266+ {
267+ gnutls_x509_crt_t cert ;
268+ gnutls_pk_algorithm_t pk_alg ;
269+ int ret ;
270+
271+ ret = gnutls_x509_crt_init (& cert );
272+ if (ret < 0 )
273+ return false;
274+
275+ ret = gnutls_x509_crt_import (cert , data , GNUTLS_X509_FMT_PEM );
276+ if (ret < 0 ) {
277+ gnutls_x509_crt_deinit (cert );
278+ return false;
279+ }
280+
281+ pk_alg = gnutls_x509_crt_get_pk_algorithm (cert , NULL );
282+ tlshd_log_debug ("%s: certificate pk algorithm %s" , __func__ ,
283+ gnutls_pk_algorithm_get_name (pk_alg ));
284+ switch (pk_alg ) {
285+ case GNUTLS_PK_MLDSA44 :
286+ case GNUTLS_PK_MLDSA65 :
287+ case GNUTLS_PK_MLDSA87 :
288+ * pkalg = pk_alg ;
289+ break ;
290+ default :
291+ gnutls_x509_crt_deinit (cert );
292+ return false;
293+ }
294+
295+ gnutls_x509_crt_deinit (cert );
296+ return true;
297+ }
298+ #else
299+ static bool tlshd_cert_check_pk_alg (__attribute__ ((unused )) gnutls_datum_t * data ,
300+ __attribute__ ((unused )) gnutls_pk_algorithm_t * pkalg )
301+ {
302+ tlshd_log_debug ("%s: gnutls version does not have ML-DSA support" ,
303+ __func__ );
304+ return false;
305+ }
306+ #endif /* HAVE_GNUTLS_MLDSA */
307+
263308/**
264- * tlshd_config_get_certs - Get certs for {Client,Server} Hello from .conf
309+ * __tlshd_config_get_certs - Helper for tlshd_config_get_certs()
265310 * @peer_type: IN: peer type
266311 * @certs: OUT: in-memory certificates
267312 * @certs_len: IN: maximum number of certs to get, OUT: number of certs found
313+ * @pkgalg: IN: if non-NULL, indicates we want to retrieve the PQ cert,
314+ * OUT: if non-NULL, store the PQ public-key alg that was used in the PQ cert
268315 *
269316 * Return values:
270317 * %true: certificate retrieved successfully
271318 * %false: certificate not retrieved
272319 */
273- bool tlshd_config_get_certs (int peer_type , gnutls_pcert_st * certs ,
274- unsigned int * certs_len )
320+ static bool __tlshd_config_get_certs (int peer_type , gnutls_pcert_st * certs ,
321+ unsigned int * certs_len ,
322+ gnutls_pk_algorithm_t * pkalg )
275323{
276324 gnutls_datum_t data ;
277325 gchar * pathname ;
@@ -281,7 +329,10 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
281329 peer_type == PEER_TYPE_CLIENT ?
282330 "authenticate.client" :
283331 "authenticate.server" ,
284- "x509.certificate" , NULL );
332+ pkalg != NULL ?
333+ "x509.pq.certificate" :
334+ "x509.certificate" ,
335+ NULL );
285336 if (!pathname )
286337 return false;
287338
@@ -291,6 +342,15 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
291342 return false;
292343 }
293344
345+ if (pkalg && !tlshd_cert_check_pk_alg (& data , pkalg )) {
346+ tlshd_log_debug ("%s: %s not using a PQ public-key algorithm" ,
347+ __func__ , pathname );
348+ free (data .data );
349+ g_free (pathname );
350+ * certs_len = 0 ;
351+ return false;
352+ }
353+
294354 /* Config file supports only PEM-encoded certificates */
295355 ret = gnutls_pcert_list_import_x509_raw (certs , certs_len , & data ,
296356 GNUTLS_X509_FMT_PEM , 0 );
@@ -310,15 +370,51 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
310370}
311371
312372/**
313- * tlshd_config_get_privkey - Get private key for {Client,Server}Hello from .conf
373+ * tlshd_config_get_certs - Get certs for {Client,Server} Hello from .conf
374+ * @peer_type: IN: peer type
375+ * @certs: OUT: in-memory certificates
376+ * @pq_certs_len: IN: maximum number of PQ certs to get, OUT: number of PQ certs found
377+ * @certs_len: IN: maximum number of certs to get, OUT: number of certs found
378+ * @pkgalg: OUT: the PQ public-key alg that was used in the PQ cert
379+ *
380+ * Retrieve the PQ cert(s) first, then the RSA cert(s). Both are stored in the
381+ * same list. Note that @pq_certs_len is deducted from the available @certs_len
382+ * and is also used to determine the offset to store the RSA cert(s) in the
383+ * @certs array.
384+ *
385+ * Return values:
386+ * %true: certificate retrieved successfully
387+ * %false: certificate not retrieved
388+ */
389+ bool tlshd_config_get_certs (int peer_type , gnutls_pcert_st * certs ,
390+ unsigned int * pq_certs_len ,
391+ unsigned int * certs_len ,
392+ gnutls_pk_algorithm_t * pkalg )
393+ {
394+ bool ret ;
395+
396+ ret = __tlshd_config_get_certs (peer_type , certs , pq_certs_len , pkalg );
397+
398+ if (ret == true)
399+ * certs_len -= * pq_certs_len ;
400+ else
401+ * pq_certs_len = 0 ;
402+
403+ return __tlshd_config_get_certs (peer_type , certs + * pq_certs_len ,
404+ certs_len , NULL );
405+ }
406+
407+ /**
408+ * __tlshd_config_get_privkey - Helper for tlshd_config_get_privkey()
314409 * @peer_type: IN: peer type
315410 * @privkey: OUT: in-memory private key
411+ * @pq: IN: if true, retrieve the PQ private key
316412 *
317413 * Return values:
318414 * %true: private key retrieved successfully
319415 * %false: private key not retrieved
320416 */
321- bool tlshd_config_get_privkey (int peer_type , gnutls_privkey_t * privkey )
417+ static bool __tlshd_config_get_privkey (int peer_type , gnutls_privkey_t * privkey , bool pq )
322418{
323419 gnutls_datum_t data ;
324420 gchar * pathname ;
@@ -328,7 +424,10 @@ bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
328424 peer_type == PEER_TYPE_CLIENT ?
329425 "authenticate.client" :
330426 "authenticate.server" ,
331- "x509.private_key" , NULL );
427+ pq == true ?
428+ "x509.pq.private_key" :
429+ "x509.private_key" ,
430+ NULL );
332431 if (!pathname )
333432 return false;
334433
@@ -360,3 +459,22 @@ bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
360459 g_free (pathname );
361460 return true;
362461}
462+
463+ /**
464+ * tlshd_config_get_privkey - Get private key for {Client,Server}Hello from .conf
465+ * @peer_type: IN: peer type
466+ * @pq_privkey: OUT: in-memory PQ private key
467+ * @privkey: OUT: in-memory private key
468+ *
469+ * Retrieve the PQ private key first, then the RSA private key.
470+ *
471+ * Return values:
472+ * %true: private key retrieved successfully
473+ * %false: private key not retrieved
474+ */
475+ bool tlshd_config_get_privkey (int peer_type , gnutls_privkey_t * pq_privkey ,
476+ gnutls_privkey_t * privkey )
477+ {
478+ __tlshd_config_get_privkey (peer_type , pq_privkey , true);
479+ return __tlshd_config_get_privkey (peer_type , privkey , false);
480+ }
0 commit comments