Add support for ML-DSA certificates (RHEL-105441)
Resolves: RHEL-105441
This commit is contained in:
parent
3bd22847d2
commit
b7d9966184
@ -0,0 +1,135 @@
|
||||
From facd084e43fc493ae8fbaca00cb65925ae30d0e9 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Mayhew <smayhew@redhat.com>
|
||||
Date: Wed, 10 Sep 2025 21:00:09 -0400
|
||||
Subject: [PATCH 4/4] tlshd: Client-side dual certificate support
|
||||
|
||||
Add two new config options "x509.pq.certificate" and
|
||||
"x509.pq.private_key", this time to the "[authenticate.client]" stanza
|
||||
of tlshd.conf. This is for client-side handling of the server's
|
||||
certificate request when the client is mounting with "xprtsec=mtls".
|
||||
|
||||
This commit also makes sure the client-side x509.pq.certificate is using
|
||||
a post-quantum public-key algorithm, and we make sure that the server
|
||||
supports that algorithm before returning that cert in the cert callback
|
||||
(unlike the server-side cert callback, the pk_algos list is populated,
|
||||
so this check is more straightforward than on the server-side).
|
||||
|
||||
Link: https://github.com/oracle/ktls-utils/issues/113
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
src/tlshd/client.c | 45 ++++++++++++++++++++++++++++++++++++--------
|
||||
src/tlshd/tlshd.conf | 2 ++
|
||||
2 files changed, 39 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/tlshd/client.c b/src/tlshd/client.c
|
||||
index 257e835..ad9a793 100644
|
||||
--- a/src/tlshd/client.c
|
||||
+++ b/src/tlshd/client.c
|
||||
@@ -134,17 +134,21 @@ out_free_creds:
|
||||
gnutls_certificate_free_credentials(xcred);
|
||||
}
|
||||
|
||||
+static gnutls_privkey_t tlshd_pq_privkey;
|
||||
static gnutls_privkey_t tlshd_privkey;
|
||||
+static unsigned int tlshd_pq_certs_len = TLSHD_MAX_CERTS;
|
||||
static unsigned int tlshd_certs_len = TLSHD_MAX_CERTS;
|
||||
static gnutls_pcert_st tlshd_certs[TLSHD_MAX_CERTS];
|
||||
+static gnutls_pk_algorithm_t tlshd_pq_pkalg = GNUTLS_PK_UNKNOWN;
|
||||
|
||||
static bool tlshd_x509_client_get_certs(struct tlshd_handshake_parms *parms)
|
||||
{
|
||||
if (parms->x509_cert != TLS_NO_CERT)
|
||||
return tlshd_keyring_get_certs(parms->x509_cert, tlshd_certs,
|
||||
&tlshd_certs_len);
|
||||
- return tlshd_config_get_certs(PEER_TYPE_CLIENT, tlshd_certs, NULL,
|
||||
- &tlshd_certs_len, NULL);
|
||||
+ return tlshd_config_get_certs(PEER_TYPE_CLIENT, tlshd_certs,
|
||||
+ &tlshd_pq_certs_len, &tlshd_certs_len,
|
||||
+ &tlshd_pq_pkalg);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_certs(void)
|
||||
@@ -160,12 +164,14 @@ static bool tlshd_x509_client_get_privkey(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_privkey != TLS_NO_PRIVKEY)
|
||||
return tlshd_keyring_get_privkey(parms->x509_privkey,
|
||||
&tlshd_privkey);
|
||||
- return tlshd_config_get_privkey(PEER_TYPE_CLIENT, NULL, &tlshd_privkey);
|
||||
+ return tlshd_config_get_privkey(PEER_TYPE_CLIENT, &tlshd_pq_privkey,
|
||||
+ &tlshd_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_privkey(void)
|
||||
{
|
||||
gnutls_privkey_deinit(tlshd_privkey);
|
||||
+ gnutls_privkey_deinit(tlshd_pq_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_log_issuers(const gnutls_datum_t *req_ca_rdn, int nreqs)
|
||||
@@ -206,13 +212,15 @@ static void tlshd_x509_log_issuers(const gnutls_datum_t *req_ca_rdn, int nreqs)
|
||||
static int
|
||||
tlshd_x509_retrieve_key_cb(gnutls_session_t session,
|
||||
const gnutls_datum_t *req_ca_rdn, int nreqs,
|
||||
- __attribute__ ((unused)) const gnutls_pk_algorithm_t *pk_algos,
|
||||
- __attribute__ ((unused)) int pk_algos_length,
|
||||
+ const gnutls_pk_algorithm_t *pk_algos,
|
||||
+ int pk_algos_length,
|
||||
gnutls_pcert_st **pcert,
|
||||
unsigned int *pcert_length,
|
||||
gnutls_privkey_t *privkey)
|
||||
{
|
||||
gnutls_certificate_type_t type;
|
||||
+ bool use_pq_cert = false;
|
||||
+ int i;
|
||||
|
||||
tlshd_x509_log_issuers(req_ca_rdn, nreqs);
|
||||
|
||||
@@ -220,9 +228,30 @@ tlshd_x509_retrieve_key_cb(gnutls_session_t session,
|
||||
if (type != GNUTLS_CRT_X509)
|
||||
return -1;
|
||||
|
||||
- *pcert_length = tlshd_certs_len;
|
||||
- *pcert = tlshd_certs;
|
||||
- *privkey = tlshd_privkey;
|
||||
+ if (tlshd_pq_pkalg != GNUTLS_PK_UNKNOWN) {
|
||||
+ for (i = 0; i < pk_algos_length; i++) {
|
||||
+ if (pk_algos[i] == tlshd_pq_pkalg) {
|
||||
+ use_pq_cert = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (use_pq_cert == true) {
|
||||
+ tlshd_log_debug("%s: Server supports %s", __func__,
|
||||
+ gnutls_pk_algorithm_get_name(pk_algos[i]));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (use_pq_cert == true) {
|
||||
+ tlshd_log_debug("%s: Selecting x509.pq.certificate from conf file", __func__);
|
||||
+ *pcert_length = tlshd_pq_certs_len;
|
||||
+ *pcert = tlshd_certs;
|
||||
+ *privkey = tlshd_pq_privkey;
|
||||
+ } else {
|
||||
+ tlshd_log_debug("%s: Selecting x509.certificate from conf file", __func__);
|
||||
+ *pcert_length = tlshd_certs_len;
|
||||
+ *pcert = tlshd_certs + tlshd_pq_certs_len;
|
||||
+ *privkey = tlshd_privkey;
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/tlshd/tlshd.conf b/src/tlshd/tlshd.conf
|
||||
index 5419146..1d4220e 100644
|
||||
--- a/src/tlshd/tlshd.conf
|
||||
+++ b/src/tlshd/tlshd.conf
|
||||
@@ -33,6 +33,8 @@ nl=0
|
||||
#x509.crl= <pathname>
|
||||
#x509.certificate= <pathname>
|
||||
#x509.private_key= <pathname>
|
||||
+#x509.pq.certificate= <pathname>
|
||||
+#x509.pq.private_key= <pathname>
|
||||
|
||||
[authenticate.server]
|
||||
#x509.truststore= <pathname>
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 9253f9df5ff986bddba38b8146ba6e650e7ebdd9 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Mayhew <smayhew@redhat.com>
|
||||
Date: Wed, 10 Sep 2025 17:02:16 -0400
|
||||
Subject: [PATCH 2/4] tlshd: Fix priority string to allow PQC
|
||||
|
||||
Specifying either of the SECURE256 or SECURE128 keywords in the priority
|
||||
string results in the ML-DSA algorithms being disabled because the
|
||||
post-quantum algorithms do not map nicely to the security
|
||||
classifications based on "bits of security" used for traditional
|
||||
algorithms [1].
|
||||
|
||||
Use @SYSTEM instead, which will allow PQC on systems with newer versions
|
||||
of GnuTLS. It will also allow users to disable PQC via a policy module
|
||||
(on systems with the crypto-policies package).
|
||||
|
||||
[1] https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/call-for-proposals-final-dec-2016.pdf#page=15
|
||||
|
||||
Link: https://github.com/oracle/ktls-utils/issues/113
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
src/tlshd/ktls.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/tlshd/ktls.c b/src/tlshd/ktls.c
|
||||
index 883256a..50381bf 100644
|
||||
--- a/src/tlshd/ktls.c
|
||||
+++ b/src/tlshd/ktls.c
|
||||
@@ -357,7 +357,7 @@ static int tlshd_gnutls_priority_init_list(const unsigned int *ciphers,
|
||||
const char *errpos;
|
||||
int ret, i;
|
||||
|
||||
- pstring = strdup("SECURE256:+SECURE128:-COMP-ALL");
|
||||
+ pstring = strdup("@SYSTEM:-COMP-ALL");
|
||||
if (!pstring)
|
||||
return -ENOMEM;
|
||||
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,445 @@
|
||||
From 14f53496509eea9cbe14eb244161b0e26699d165 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Mayhew <smayhew@redhat.com>
|
||||
Date: Wed, 10 Sep 2025 20:45:41 -0400
|
||||
Subject: [PATCH 3/4] tlshd: Server-side dual certificate support
|
||||
|
||||
Add two new config options, "x509.pq.certificate" and
|
||||
"x509.pq.private_key" to configure tlshd to use an ML-DSA certificate.
|
||||
If the cert callback determines that the client supports ML-DSA, it will
|
||||
select this certificate. Otherwise, it will fall back to the
|
||||
traditional certficate (i.e. the certificate configured via
|
||||
"x509.certificate" and "x509.private_key").
|
||||
|
||||
Note that we check to ensure that the PQ certificate is using a
|
||||
post-quantum public-key algorithm (ML-DSA-44, ML-DSA-65, or ML-DSA-87),
|
||||
and we store the algorithm value so we can later compare it to the list
|
||||
of signing algorithms supported by the client in the cert callback.
|
||||
|
||||
Link: https://github.com/oracle/ktls-utils/issues/113
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
configure.ac | 12 ++++
|
||||
src/tlshd/client.c | 6 +-
|
||||
src/tlshd/config.c | 132 ++++++++++++++++++++++++++++++++++++---
|
||||
src/tlshd/server.c | 65 ++++++++++++++++++-
|
||||
src/tlshd/tlshd.conf | 2 +
|
||||
src/tlshd/tlshd.conf.man | 15 +++++
|
||||
src/tlshd/tlshd.h | 7 ++-
|
||||
7 files changed, 225 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index a6d9d09..0dd23f2 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -79,6 +79,18 @@ AC_CHECK_LIB([gnutls], [gnutls_get_system_config_file],
|
||||
AC_CHECK_LIB([gnutls], [gnutls_psk_allocate_client_credentials2],
|
||||
[AC_DEFINE([HAVE_GNUTLS_PSK_ALLOCATE_CREDENTIALS2], [1],
|
||||
[Define to 1 if you have the gnutls_psk_allocate_client_credentials2 function.])])
|
||||
+
|
||||
+AC_MSG_CHECKING(for ML-DSA support in gnutls)
|
||||
+AC_COMPILE_IFELSE(
|
||||
+ [AC_LANG_PROGRAM([[ #include <gnutls/gnutls.h> ]],
|
||||
+ [[ (void) GNUTLS_SIGN_MLDSA65; ]])],
|
||||
+ [ have_mldsa=yes ],
|
||||
+ [ have_mldsa=no ])
|
||||
+AC_MSG_RESULT([$have_mldsa])
|
||||
+if test "x$have_mldsa" = xyes ; then
|
||||
+ AC_DEFINE([HAVE_GNUTLS_MLDSA], [1], [Define to 1 if gnutls supports ML-DSA])
|
||||
+fi
|
||||
+
|
||||
AC_SUBST([AM_CPPFLAGS])
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile src/tlshd/Makefile systemd/Makefile])
|
||||
diff --git a/src/tlshd/client.c b/src/tlshd/client.c
|
||||
index c07ae29..257e835 100644
|
||||
--- a/src/tlshd/client.c
|
||||
+++ b/src/tlshd/client.c
|
||||
@@ -143,8 +143,8 @@ static bool tlshd_x509_client_get_certs(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_cert != TLS_NO_CERT)
|
||||
return tlshd_keyring_get_certs(parms->x509_cert, tlshd_certs,
|
||||
&tlshd_certs_len);
|
||||
- return tlshd_config_get_certs(PEER_TYPE_CLIENT, tlshd_certs,
|
||||
- &tlshd_certs_len);
|
||||
+ return tlshd_config_get_certs(PEER_TYPE_CLIENT, tlshd_certs, NULL,
|
||||
+ &tlshd_certs_len, NULL);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_certs(void)
|
||||
@@ -160,7 +160,7 @@ static bool tlshd_x509_client_get_privkey(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_privkey != TLS_NO_PRIVKEY)
|
||||
return tlshd_keyring_get_privkey(parms->x509_privkey,
|
||||
&tlshd_privkey);
|
||||
- return tlshd_config_get_privkey(PEER_TYPE_CLIENT, &tlshd_privkey);
|
||||
+ return tlshd_config_get_privkey(PEER_TYPE_CLIENT, NULL, &tlshd_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_privkey(void)
|
||||
diff --git a/src/tlshd/config.c b/src/tlshd/config.c
|
||||
index ff1f2a5..9a3b6b2 100644
|
||||
--- a/src/tlshd/config.c
|
||||
+++ b/src/tlshd/config.c
|
||||
@@ -260,18 +260,66 @@ bool tlshd_config_get_crl(int peer_type, char **result)
|
||||
return true;
|
||||
}
|
||||
|
||||
+#ifdef HAVE_GNUTLS_MLDSA
|
||||
+static bool tlshd_cert_check_pk_alg(gnutls_datum_t *data,
|
||||
+ gnutls_pk_algorithm_t *pkalg)
|
||||
+{
|
||||
+ gnutls_x509_crt_t cert;
|
||||
+ gnutls_pk_algorithm_t pk_alg;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = gnutls_x509_crt_init(&cert);
|
||||
+ if (ret < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ ret = gnutls_x509_crt_import(cert, data, GNUTLS_X509_FMT_PEM);
|
||||
+ if (ret < 0) {
|
||||
+ gnutls_x509_crt_deinit(cert);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ pk_alg = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
|
||||
+ tlshd_log_debug("%s: certificate pk algorithm %s", __func__,
|
||||
+ gnutls_pk_algorithm_get_name(pk_alg));
|
||||
+ switch (pk_alg) {
|
||||
+ case GNUTLS_PK_MLDSA44:
|
||||
+ case GNUTLS_PK_MLDSA65:
|
||||
+ case GNUTLS_PK_MLDSA87:
|
||||
+ *pkalg = pk_alg;
|
||||
+ break;
|
||||
+ default:
|
||||
+ gnutls_x509_crt_deinit(cert);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ gnutls_x509_crt_deinit(cert);
|
||||
+ return true;
|
||||
+}
|
||||
+#else
|
||||
+static bool tlshd_cert_check_pk_alg(__attribute__ ((unused)) gnutls_datum_t *data,
|
||||
+ __attribute__ ((unused)) gnutls_pk_algorithm_t *pkalg)
|
||||
+{
|
||||
+ tlshd_log_debug("%s: gnutls version does not have ML-DSA support",
|
||||
+ __func__);
|
||||
+ return false;
|
||||
+}
|
||||
+#endif /* HAVE_GNUTLS_MLDSA */
|
||||
+
|
||||
/**
|
||||
- * tlshd_config_get_certs - Get certs for {Client,Server} Hello from .conf
|
||||
+ * __tlshd_config_get_certs - Helper for tlshd_config_get_certs()
|
||||
* @peer_type: IN: peer type
|
||||
* @certs: OUT: in-memory certificates
|
||||
* @certs_len: IN: maximum number of certs to get, OUT: number of certs found
|
||||
+ * @pkgalg: IN: if non-NULL, indicates we want to retrieve the PQ cert,
|
||||
+ * OUT: if non-NULL, store the PQ public-key alg that was used in the PQ cert
|
||||
*
|
||||
* Return values:
|
||||
* %true: certificate retrieved successfully
|
||||
* %false: certificate not retrieved
|
||||
*/
|
||||
-bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len)
|
||||
+static bool __tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
+ unsigned int *certs_len,
|
||||
+ gnutls_pk_algorithm_t *pkalg)
|
||||
{
|
||||
gnutls_datum_t data;
|
||||
gchar *pathname;
|
||||
@@ -281,7 +329,10 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
peer_type == PEER_TYPE_CLIENT ?
|
||||
"authenticate.client" :
|
||||
"authenticate.server",
|
||||
- "x509.certificate", NULL);
|
||||
+ pkalg != NULL ?
|
||||
+ "x509.pq.certificate" :
|
||||
+ "x509.certificate",
|
||||
+ NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
|
||||
@@ -291,6 +342,15 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (pkalg && !tlshd_cert_check_pk_alg(&data, pkalg)) {
|
||||
+ tlshd_log_debug("%s: %s not using a PQ public-key algorithm",
|
||||
+ __func__, pathname);
|
||||
+ free(data.data);
|
||||
+ g_free(pathname);
|
||||
+ *certs_len = 0;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/* Config file supports only PEM-encoded certificates */
|
||||
ret = gnutls_pcert_list_import_x509_raw(certs, certs_len, &data,
|
||||
GNUTLS_X509_FMT_PEM, 0);
|
||||
@@ -310,15 +370,51 @@ bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
}
|
||||
|
||||
/**
|
||||
- * tlshd_config_get_privkey - Get private key for {Client,Server}Hello from .conf
|
||||
+ * tlshd_config_get_certs - Get certs for {Client,Server} Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
+ * @certs: OUT: in-memory certificates
|
||||
+ * @pq_certs_len: IN: maximum number of PQ certs to get, OUT: number of PQ certs found
|
||||
+ * @certs_len: IN: maximum number of certs to get, OUT: number of certs found
|
||||
+ * @pkgalg: OUT: the PQ public-key alg that was used in the PQ cert
|
||||
+ *
|
||||
+ * Retrieve the PQ cert(s) first, then the RSA cert(s). Both are stored in the
|
||||
+ * same list. Note that @pq_certs_len is deducted from the available @certs_len
|
||||
+ * and is also used to determine the offset to store the RSA cert(s) in the
|
||||
+ * @certs array.
|
||||
+ *
|
||||
+ * Return values:
|
||||
+ * %true: certificate retrieved successfully
|
||||
+ * %false: certificate not retrieved
|
||||
+ */
|
||||
+bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
+ unsigned int *pq_certs_len,
|
||||
+ unsigned int *certs_len,
|
||||
+ gnutls_pk_algorithm_t *pkalg)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ ret = __tlshd_config_get_certs(peer_type, certs, pq_certs_len, pkalg);
|
||||
+
|
||||
+ if (ret == true)
|
||||
+ *certs_len -= *pq_certs_len;
|
||||
+ else
|
||||
+ *pq_certs_len = 0;
|
||||
+
|
||||
+ return __tlshd_config_get_certs(peer_type, certs + *pq_certs_len,
|
||||
+ certs_len, NULL);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __tlshd_config_get_privkey - Helper for tlshd_config_get_privkey()
|
||||
* @peer_type: IN: peer type
|
||||
* @privkey: OUT: in-memory private key
|
||||
+ * @pq: IN: if true, retrieve the PQ private key
|
||||
*
|
||||
* Return values:
|
||||
* %true: private key retrieved successfully
|
||||
* %false: private key not retrieved
|
||||
*/
|
||||
-bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
|
||||
+static bool __tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey, bool pq)
|
||||
{
|
||||
gnutls_datum_t data;
|
||||
gchar *pathname;
|
||||
@@ -328,7 +424,10 @@ bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
|
||||
peer_type == PEER_TYPE_CLIENT ?
|
||||
"authenticate.client" :
|
||||
"authenticate.server",
|
||||
- "x509.private_key", NULL);
|
||||
+ pq == true ?
|
||||
+ "x509.pq.private_key" :
|
||||
+ "x509.private_key",
|
||||
+ NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
|
||||
@@ -360,3 +459,22 @@ bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
|
||||
g_free(pathname);
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * tlshd_config_get_privkey - Get private key for {Client,Server}Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
+ * @pq_privkey: OUT: in-memory PQ private key
|
||||
+ * @privkey: OUT: in-memory private key
|
||||
+ *
|
||||
+ * Retrieve the PQ private key first, then the RSA private key.
|
||||
+ *
|
||||
+ * Return values:
|
||||
+ * %true: private key retrieved successfully
|
||||
+ * %false: private key not retrieved
|
||||
+ */
|
||||
+bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *pq_privkey,
|
||||
+ gnutls_privkey_t *privkey)
|
||||
+{
|
||||
+ __tlshd_config_get_privkey(peer_type, pq_privkey, true);
|
||||
+ return __tlshd_config_get_privkey(peer_type, privkey, false);
|
||||
+}
|
||||
diff --git a/src/tlshd/server.c b/src/tlshd/server.c
|
||||
index efea387..13b805c 100644
|
||||
--- a/src/tlshd/server.c
|
||||
+++ b/src/tlshd/server.c
|
||||
@@ -42,9 +42,12 @@
|
||||
#include "tlshd.h"
|
||||
#include "netlink.h"
|
||||
|
||||
+static gnutls_privkey_t tlshd_server_pq_privkey;
|
||||
static gnutls_privkey_t tlshd_server_privkey;
|
||||
+static unsigned int tlshd_server_pq_certs_len = TLSHD_MAX_CERTS;
|
||||
static unsigned int tlshd_server_certs_len = TLSHD_MAX_CERTS;
|
||||
static gnutls_pcert_st tlshd_server_certs[TLSHD_MAX_CERTS];
|
||||
+static gnutls_pk_algorithm_t tlshd_server_pq_pkalg = GNUTLS_PK_UNKNOWN;
|
||||
|
||||
static bool tlshd_x509_server_get_certs(struct tlshd_handshake_parms *parms)
|
||||
{
|
||||
@@ -53,14 +56,16 @@ static bool tlshd_x509_server_get_certs(struct tlshd_handshake_parms *parms)
|
||||
tlshd_server_certs,
|
||||
&tlshd_server_certs_len);
|
||||
return tlshd_config_get_certs(PEER_TYPE_SERVER, tlshd_server_certs,
|
||||
- &tlshd_server_certs_len);
|
||||
+ &tlshd_server_pq_certs_len,
|
||||
+ &tlshd_server_certs_len,
|
||||
+ &tlshd_server_pq_pkalg);
|
||||
}
|
||||
|
||||
static void tlshd_x509_server_put_certs(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
- for (i = 0; i < tlshd_server_certs_len; i++)
|
||||
+ for (i = 0; i < TLSHD_MAX_CERTS; i++)
|
||||
gnutls_pcert_deinit(&tlshd_server_certs[i]);
|
||||
}
|
||||
|
||||
@@ -70,11 +75,13 @@ static bool tlshd_x509_server_get_privkey(struct tlshd_handshake_parms *parms)
|
||||
return tlshd_keyring_get_privkey(parms->x509_privkey,
|
||||
&tlshd_server_privkey);
|
||||
return tlshd_config_get_privkey(PEER_TYPE_SERVER,
|
||||
+ &tlshd_server_pq_privkey,
|
||||
&tlshd_server_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_server_put_privkey(void)
|
||||
{
|
||||
+ gnutls_privkey_deinit(tlshd_server_pq_privkey);
|
||||
gnutls_privkey_deinit(tlshd_server_privkey);
|
||||
}
|
||||
|
||||
@@ -123,6 +130,11 @@ tlshd_x509_retrieve_key_cb(gnutls_session_t session,
|
||||
gnutls_privkey_t *privkey)
|
||||
{
|
||||
gnutls_certificate_type_t type;
|
||||
+#ifdef HAVE_GNUTLS_MLDSA
|
||||
+ gnutls_sign_algorithm_t client_alg;
|
||||
+ bool use_pq_cert = false;
|
||||
+ int i, ret;
|
||||
+#endif /* HAVE_GNUTLS_MLDSA */
|
||||
|
||||
tlshd_x509_log_issuers(req_ca_rdn, nreqs);
|
||||
|
||||
@@ -130,9 +142,58 @@ tlshd_x509_retrieve_key_cb(gnutls_session_t session,
|
||||
if (type != GNUTLS_CRT_X509)
|
||||
return -1;
|
||||
|
||||
+#ifdef HAVE_GNUTLS_MLDSA
|
||||
+ /*
|
||||
+ * NB: Unfortunately when the callback function is invoked server-side,
|
||||
+ * pk_algos is NULL and pk_algos_length is 0. So we check the signature
|
||||
+ * algorithms the client supports and try to match one of them to the
|
||||
+ * public-key algorithm used by the server cert.
|
||||
+ */
|
||||
+ if (tlshd_server_pq_pkalg != GNUTLS_PK_UNKNOWN) {
|
||||
+ for (i = 0; ; i++) {
|
||||
+ ret = gnutls_sign_algorithm_get_requested(session, i, &client_alg);
|
||||
+ if (ret != GNUTLS_E_SUCCESS)
|
||||
+ break;
|
||||
+ switch (client_alg) {
|
||||
+ case GNUTLS_SIGN_MLDSA44:
|
||||
+ if (tlshd_server_pq_pkalg == GNUTLS_PK_MLDSA44)
|
||||
+ use_pq_cert = true;
|
||||
+ break;
|
||||
+ case GNUTLS_SIGN_MLDSA65:
|
||||
+ if (tlshd_server_pq_pkalg == GNUTLS_PK_MLDSA65)
|
||||
+ use_pq_cert = true;
|
||||
+ break;
|
||||
+ case GNUTLS_SIGN_MLDSA87:
|
||||
+ if (tlshd_server_pq_pkalg == GNUTLS_PK_MLDSA87)
|
||||
+ use_pq_cert = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ if (use_pq_cert == true) {
|
||||
+ tlshd_log_debug("%s: Client supports %s", __func__,
|
||||
+ gnutls_sign_get_name(client_alg));
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (use_pq_cert == true) {
|
||||
+ tlshd_log_debug("%s: Selecting x509.pq.certificate from conf file", __func__);
|
||||
+ *pcert_length = tlshd_server_pq_certs_len;
|
||||
+ *pcert = tlshd_server_certs;
|
||||
+ *privkey = tlshd_server_pq_privkey;
|
||||
+ } else {
|
||||
+ tlshd_log_debug("%s: Selecting x509.certificate from conf file", __func__);
|
||||
+ *pcert_length = tlshd_server_certs_len;
|
||||
+ *pcert = tlshd_server_certs + tlshd_server_pq_certs_len;
|
||||
+ *privkey = tlshd_server_privkey;
|
||||
+ }
|
||||
+#else
|
||||
*pcert_length = tlshd_server_certs_len;
|
||||
*pcert = tlshd_server_certs;
|
||||
*privkey = tlshd_server_privkey;
|
||||
+#endif /* HAVE_GNUTLS_MLDSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/tlshd/tlshd.conf b/src/tlshd/tlshd.conf
|
||||
index 620bd17..5419146 100644
|
||||
--- a/src/tlshd/tlshd.conf
|
||||
+++ b/src/tlshd/tlshd.conf
|
||||
@@ -39,3 +39,5 @@ nl=0
|
||||
#x509.crl= <pathname>
|
||||
#x509.certificate= <pathname>
|
||||
#x509.private_key= <pathname>
|
||||
+#x509.pq.certificate= <pathname>
|
||||
+#x509.pq.private_key= <pathname>
|
||||
diff --git a/src/tlshd/tlshd.conf.man b/src/tlshd/tlshd.conf.man
|
||||
index 914261e..575d88b 100644
|
||||
--- a/src/tlshd/tlshd.conf.man
|
||||
+++ b/src/tlshd/tlshd.conf.man
|
||||
@@ -125,6 +125,21 @@ a handshake request when no other certificate is available.
|
||||
.B x509.private_key
|
||||
This option specifies the pathname of a file containing
|
||||
a PEM-encoded private key associated with the above certificate.
|
||||
+.TP
|
||||
+.B x509.pq.certificate
|
||||
+This option specifies the pathname of a file containing
|
||||
+a PEM-encoded x.509 certificate that is to be presented during
|
||||
+a handshake request if the peer supports post-quantum cryptography.
|
||||
+This certificate must be using a post-quantum public-key algorithm
|
||||
+(ML-DSA-44, ML-DSA-65, or ML-DSA-87).
|
||||
+If the peer does not support post-quantum cryptography, the
|
||||
+certificate configured in the
|
||||
+.I x509.certificate
|
||||
+option will be presented instead.
|
||||
+.TP
|
||||
+.B x509.pq.private_key
|
||||
+This option specifies the pathname of a file containing
|
||||
+a PEM-encoded private key associated with the above certificate.
|
||||
.SH SEE ALSO
|
||||
.BR tlshd (8)
|
||||
.SH AUTHOR
|
||||
diff --git a/src/tlshd/tlshd.h b/src/tlshd/tlshd.h
|
||||
index 6ba45ac..664de67 100644
|
||||
--- a/src/tlshd/tlshd.h
|
||||
+++ b/src/tlshd/tlshd.h
|
||||
@@ -60,8 +60,11 @@ void tlshd_config_shutdown(void);
|
||||
bool tlshd_config_get_truststore(int peer_type, char **bundle);
|
||||
bool tlshd_config_get_crl(int peer_type, char **result);
|
||||
bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len);
|
||||
-bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey);
|
||||
+ unsigned int *pq_certs_len,
|
||||
+ unsigned int *certs_len,
|
||||
+ gnutls_pk_algorithm_t *pkalg);
|
||||
+bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *pq_privkey,
|
||||
+ gnutls_privkey_t *privkey);
|
||||
|
||||
/* handshake.c */
|
||||
extern void tlshd_start_tls_handshake(gnutls_session_t session,
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -0,0 +1,445 @@
|
||||
From 6cea3a0e8a10aa893f42576059dcf5c74f092283 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Mayhew <smayhew@redhat.com>
|
||||
Date: Wed, 10 Sep 2025 16:17:43 -0400
|
||||
Subject: [PATCH 1/4] tlshd: deduplicate client and server config functions
|
||||
|
||||
The client and server variants of tlshd_config_get_* are identical
|
||||
except for
|
||||
1) the stanza they're looking at in the config file, and
|
||||
2) whether the word "client" or "server" gets written in a log message
|
||||
|
||||
Add new parameter 'peer_type' to each of these functions so we can use
|
||||
the same function for both the client and server code.
|
||||
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
---
|
||||
src/tlshd/client.c | 9 +-
|
||||
src/tlshd/config.c | 213 +++++++++------------------------------------
|
||||
src/tlshd/server.c | 11 +--
|
||||
src/tlshd/tlshd.h | 20 ++---
|
||||
4 files changed, 62 insertions(+), 191 deletions(-)
|
||||
|
||||
diff --git a/src/tlshd/client.c b/src/tlshd/client.c
|
||||
index 8acb0aa..c07ae29 100644
|
||||
--- a/src/tlshd/client.c
|
||||
+++ b/src/tlshd/client.c
|
||||
@@ -48,7 +48,7 @@ static int tlshd_client_get_truststore(gnutls_certificate_credentials_t cred)
|
||||
char *pathname;
|
||||
int ret;
|
||||
|
||||
- if (tlshd_config_get_client_truststore(&pathname)) {
|
||||
+ if (tlshd_config_get_truststore(PEER_TYPE_CLIENT, &pathname)) {
|
||||
ret = gnutls_certificate_set_x509_trust_file(cred, pathname,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
free(pathname);
|
||||
@@ -60,7 +60,7 @@ static int tlshd_client_get_truststore(gnutls_certificate_credentials_t cred)
|
||||
}
|
||||
tlshd_log_debug("System trust: Loaded %d certificate(s).", ret);
|
||||
|
||||
- if (tlshd_config_get_client_crl(&pathname)) {
|
||||
+ if (tlshd_config_get_crl(PEER_TYPE_CLIENT, &pathname)) {
|
||||
ret = gnutls_certificate_set_x509_crl_file(cred, pathname,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
free(pathname);
|
||||
@@ -143,7 +143,8 @@ static bool tlshd_x509_client_get_certs(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_cert != TLS_NO_CERT)
|
||||
return tlshd_keyring_get_certs(parms->x509_cert, tlshd_certs,
|
||||
&tlshd_certs_len);
|
||||
- return tlshd_config_get_client_certs(tlshd_certs, &tlshd_certs_len);
|
||||
+ return tlshd_config_get_certs(PEER_TYPE_CLIENT, tlshd_certs,
|
||||
+ &tlshd_certs_len);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_certs(void)
|
||||
@@ -159,7 +160,7 @@ static bool tlshd_x509_client_get_privkey(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_privkey != TLS_NO_PRIVKEY)
|
||||
return tlshd_keyring_get_privkey(parms->x509_privkey,
|
||||
&tlshd_privkey);
|
||||
- return tlshd_config_get_client_privkey(&tlshd_privkey);
|
||||
+ return tlshd_config_get_privkey(PEER_TYPE_CLIENT, &tlshd_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_client_put_privkey(void)
|
||||
diff --git a/src/tlshd/config.c b/src/tlshd/config.c
|
||||
index 029dbcc..ff1f2a5 100644
|
||||
--- a/src/tlshd/config.c
|
||||
+++ b/src/tlshd/config.c
|
||||
@@ -187,18 +187,22 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
- * tlshd_config_get_client_truststore - Get truststore for ClientHello from .conf
|
||||
+ * tlshd_config_get_truststore - Get truststore for {Client,Server}Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
* @bundle: OUT: pathname to truststore
|
||||
*
|
||||
* Return values:
|
||||
* %false: pathname not retrieved
|
||||
* %true: pathname retrieved successfully; caller must free @bundle using free(3)
|
||||
*/
|
||||
-bool tlshd_config_get_client_truststore(char **bundle)
|
||||
+bool tlshd_config_get_truststore(int peer_type, char **bundle)
|
||||
{
|
||||
gchar *pathname;
|
||||
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.client",
|
||||
+ pathname = g_key_file_get_string(tlshd_configuration,
|
||||
+ peer_type == PEER_TYPE_CLIENT ?
|
||||
+ "authenticate.client" :
|
||||
+ "authenticate.server",
|
||||
"x509.truststore", NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
@@ -213,23 +217,29 @@ bool tlshd_config_get_client_truststore(char **bundle)
|
||||
if (!*bundle)
|
||||
return false;
|
||||
|
||||
- tlshd_log_debug("Client x.509 truststore is %s", *bundle);
|
||||
+ tlshd_log_debug("%s x.509 truststore is %s",
|
||||
+ peer_type == PEER_TYPE_CLIENT ? "Client" : "Server",
|
||||
+ *bundle);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
- * tlshd_config_get_client_crl - Get CRL for ClientHello from .conf
|
||||
+ * tlshd_config_get_crl - Get CRL for {Client,Server}Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
* @result: OUT: pathname to CRL
|
||||
*
|
||||
* Return values:
|
||||
* %false: pathname not retrieved
|
||||
* %true: pathname retrieved successfully; caller must free @result using free(3)
|
||||
*/
|
||||
-bool tlshd_config_get_client_crl(char **result)
|
||||
+bool tlshd_config_get_crl(int peer_type, char **result)
|
||||
{
|
||||
gchar *pathname;
|
||||
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.client",
|
||||
+ pathname = g_key_file_get_string(tlshd_configuration,
|
||||
+ peer_type == PEER_TYPE_CLIENT ?
|
||||
+ "authenticate.client" :
|
||||
+ "authenticate.server",
|
||||
"x509.crl", NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
@@ -244,12 +254,15 @@ bool tlshd_config_get_client_crl(char **result)
|
||||
if (!*result)
|
||||
return false;
|
||||
|
||||
- tlshd_log_debug("Client x.509 crl is %s", *result);
|
||||
+ tlshd_log_debug("%s x.509 crl is %s",
|
||||
+ peer_type == PEER_TYPE_CLIENT ? "Client" : "Server",
|
||||
+ *result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
- * tlshd_config_get_client_certs - Get certs for ClientHello from .conf
|
||||
+ * tlshd_config_get_certs - Get certs for {Client,Server} Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
* @certs: OUT: in-memory certificates
|
||||
* @certs_len: IN: maximum number of certs to get, OUT: number of certs found
|
||||
*
|
||||
@@ -257,15 +270,18 @@ bool tlshd_config_get_client_crl(char **result)
|
||||
* %true: certificate retrieved successfully
|
||||
* %false: certificate not retrieved
|
||||
*/
|
||||
-bool tlshd_config_get_client_certs(gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len)
|
||||
+bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
+ unsigned int *certs_len)
|
||||
{
|
||||
gnutls_datum_t data;
|
||||
gchar *pathname;
|
||||
int ret;
|
||||
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.client",
|
||||
- "x509.certificate", NULL);
|
||||
+ pathname = g_key_file_get_string(tlshd_configuration,
|
||||
+ peer_type == PEER_TYPE_CLIENT ?
|
||||
+ "authenticate.client" :
|
||||
+ "authenticate.server",
|
||||
+ "x509.certificate", NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
|
||||
@@ -285,181 +301,34 @@ bool tlshd_config_get_client_certs(gnutls_pcert_st *certs,
|
||||
return false;
|
||||
}
|
||||
|
||||
- tlshd_log_debug("Retrieved %u x.509 client certificate(s) from %s",
|
||||
- *certs_len, pathname);
|
||||
+ tlshd_log_debug("Retrieved %u x.509 %s certificate(s) from %s",
|
||||
+ *certs_len,
|
||||
+ peer_type == PEER_TYPE_CLIENT ? "client" : "server",
|
||||
+ pathname);
|
||||
g_free(pathname);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
- * tlshd_config_get_client_privkey - Get private key for ClientHello from .conf
|
||||
+ * tlshd_config_get_privkey - Get private key for {Client,Server}Hello from .conf
|
||||
+ * @peer_type: IN: peer type
|
||||
* @privkey: OUT: in-memory private key
|
||||
*
|
||||
* Return values:
|
||||
* %true: private key retrieved successfully
|
||||
* %false: private key not retrieved
|
||||
*/
|
||||
-bool tlshd_config_get_client_privkey(gnutls_privkey_t *privkey)
|
||||
+bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey)
|
||||
{
|
||||
gnutls_datum_t data;
|
||||
gchar *pathname;
|
||||
int ret;
|
||||
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.client",
|
||||
- "x509.private_key", NULL);
|
||||
- if (!pathname)
|
||||
- return false;
|
||||
-
|
||||
- if (!tlshd_config_read_datum(pathname, &data, TLSHD_OWNER,
|
||||
- TLSHD_PRIVKEY_MODE)) {
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- ret = gnutls_privkey_init(privkey);
|
||||
- if (ret != GNUTLS_E_SUCCESS) {
|
||||
- tlshd_log_gnutls_error(ret);
|
||||
- free(data.data);
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- /* Config file supports only PEM-encoded keys */
|
||||
- ret = gnutls_privkey_import_x509_raw(*privkey, &data,
|
||||
- GNUTLS_X509_FMT_PEM, NULL, 0);
|
||||
- free(data.data);
|
||||
- if (ret != GNUTLS_E_SUCCESS) {
|
||||
- tlshd_log_gnutls_error(ret);
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- tlshd_log_debug("Retrieved private key from %s", pathname);
|
||||
- g_free(pathname);
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * tlshd_config_get_server_truststore - Get truststore for ServerHello from .conf
|
||||
- * @bundle: OUT: pathname to truststore
|
||||
- *
|
||||
- * Return values:
|
||||
- * %false: pathname not retrieved
|
||||
- * %true: pathname retrieved successfully; caller must free @bundle using free(3)
|
||||
- */
|
||||
-bool tlshd_config_get_server_truststore(char **bundle)
|
||||
-{
|
||||
- gchar *pathname;
|
||||
-
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.server",
|
||||
- "x509.truststore", NULL);
|
||||
- if (!pathname)
|
||||
- return false;
|
||||
- if (access(pathname, F_OK)) {
|
||||
- tlshd_log_debug("tlshd cannot access \"%s\"", pathname);
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- *bundle = strdup(pathname);
|
||||
- g_free(pathname);
|
||||
- if (!*bundle)
|
||||
- return false;
|
||||
-
|
||||
- tlshd_log_debug("Server x.509 truststore is %s", *bundle);
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * tlshd_config_get_server_crl - Get CRL for ServerHello from .conf
|
||||
- * @result: OUT: pathname to CRL
|
||||
- *
|
||||
- * Return values:
|
||||
- * %false: pathname not retrieved
|
||||
- * %true: pathname retrieved successfully; caller must free @result using free(3)
|
||||
- */
|
||||
-bool tlshd_config_get_server_crl(char **result)
|
||||
-{
|
||||
- gchar *pathname;
|
||||
-
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.server",
|
||||
- "x509.crl", NULL);
|
||||
- if (!pathname)
|
||||
- return false;
|
||||
- if (access(pathname, F_OK)) {
|
||||
- tlshd_log_debug("tlshd cannot access \"%s\"", pathname);
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- *result = strdup(pathname);
|
||||
- g_free(pathname);
|
||||
- if (!*result)
|
||||
- return false;
|
||||
-
|
||||
- tlshd_log_debug("Server x.509 crl is %s", *result);
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * tlshd_config_get_server_certs - Get certs for ServerHello from .conf
|
||||
- * @certs: OUT: in-memory certificates
|
||||
- * @certs_len: IN: maximum number of certs to get, OUT: number of certs found
|
||||
- *
|
||||
- * Return values:
|
||||
- * %true: certificate retrieved successfully
|
||||
- * %false: certificate not retrieved
|
||||
- */
|
||||
-bool tlshd_config_get_server_certs(gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len)
|
||||
-{
|
||||
- gnutls_datum_t data;
|
||||
- gchar *pathname;
|
||||
- int ret;
|
||||
-
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.server",
|
||||
- "x509.certificate", NULL);
|
||||
- if (!pathname)
|
||||
- return false;
|
||||
-
|
||||
- if (!tlshd_config_read_datum(pathname, &data, TLSHD_OWNER,
|
||||
- TLSHD_CERT_MODE)) {
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- /* Config file supports only PEM-encoded certificates */
|
||||
- ret = gnutls_pcert_list_import_x509_raw(certs, certs_len, &data,
|
||||
- GNUTLS_X509_FMT_PEM, 0);
|
||||
- free(data.data);
|
||||
- if (ret != GNUTLS_E_SUCCESS) {
|
||||
- tlshd_log_gnutls_error(ret);
|
||||
- g_free(pathname);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- tlshd_log_debug("Retrieved %u x.509 server certificate(s) from %s",
|
||||
- *certs_len, pathname);
|
||||
- g_free(pathname);
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * tlshd_config_get_server_privkey - Get private key for ServerHello from .conf
|
||||
- * @privkey: OUT: in-memory private key
|
||||
- *
|
||||
- * Return values:
|
||||
- * %true: private key retrieved successfully
|
||||
- * %false: private key not retrieved
|
||||
- */
|
||||
-bool tlshd_config_get_server_privkey(gnutls_privkey_t *privkey)
|
||||
-{
|
||||
- gnutls_datum_t data;
|
||||
- gchar *pathname;
|
||||
- int ret;
|
||||
-
|
||||
- pathname = g_key_file_get_string(tlshd_configuration, "authenticate.server",
|
||||
- "x509.private_key", NULL);
|
||||
+ pathname = g_key_file_get_string(tlshd_configuration,
|
||||
+ peer_type == PEER_TYPE_CLIENT ?
|
||||
+ "authenticate.client" :
|
||||
+ "authenticate.server",
|
||||
+ "x509.private_key", NULL);
|
||||
if (!pathname)
|
||||
return false;
|
||||
|
||||
diff --git a/src/tlshd/server.c b/src/tlshd/server.c
|
||||
index 44a91c4..efea387 100644
|
||||
--- a/src/tlshd/server.c
|
||||
+++ b/src/tlshd/server.c
|
||||
@@ -52,8 +52,8 @@ static bool tlshd_x509_server_get_certs(struct tlshd_handshake_parms *parms)
|
||||
return tlshd_keyring_get_certs(parms->x509_cert,
|
||||
tlshd_server_certs,
|
||||
&tlshd_server_certs_len);
|
||||
- return tlshd_config_get_server_certs(tlshd_server_certs,
|
||||
- &tlshd_server_certs_len);
|
||||
+ return tlshd_config_get_certs(PEER_TYPE_SERVER, tlshd_server_certs,
|
||||
+ &tlshd_server_certs_len);
|
||||
}
|
||||
|
||||
static void tlshd_x509_server_put_certs(void)
|
||||
@@ -69,7 +69,8 @@ static bool tlshd_x509_server_get_privkey(struct tlshd_handshake_parms *parms)
|
||||
if (parms->x509_privkey != TLS_NO_PRIVKEY)
|
||||
return tlshd_keyring_get_privkey(parms->x509_privkey,
|
||||
&tlshd_server_privkey);
|
||||
- return tlshd_config_get_server_privkey(&tlshd_server_privkey);
|
||||
+ return tlshd_config_get_privkey(PEER_TYPE_SERVER,
|
||||
+ &tlshd_server_privkey);
|
||||
}
|
||||
|
||||
static void tlshd_x509_server_put_privkey(void)
|
||||
@@ -140,7 +141,7 @@ static int tlshd_server_get_truststore(gnutls_certificate_credentials_t cred)
|
||||
char *pathname;
|
||||
int ret;
|
||||
|
||||
- if (tlshd_config_get_server_truststore(&pathname)) {
|
||||
+ if (tlshd_config_get_truststore(PEER_TYPE_SERVER, &pathname)) {
|
||||
ret = gnutls_certificate_set_x509_trust_file(cred, pathname,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
free(pathname);
|
||||
@@ -150,7 +151,7 @@ static int tlshd_server_get_truststore(gnutls_certificate_credentials_t cred)
|
||||
return ret;
|
||||
tlshd_log_debug("System trust: Loaded %d certificate(s).", ret);
|
||||
|
||||
- if (tlshd_config_get_server_crl(&pathname)) {
|
||||
+ if (tlshd_config_get_crl(PEER_TYPE_SERVER, &pathname)) {
|
||||
ret = gnutls_certificate_set_x509_crl_file(cred, pathname,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
free(pathname);
|
||||
diff --git a/src/tlshd/tlshd.h b/src/tlshd/tlshd.h
|
||||
index 2857804..6ba45ac 100644
|
||||
--- a/src/tlshd/tlshd.h
|
||||
+++ b/src/tlshd/tlshd.h
|
||||
@@ -45,6 +45,11 @@ struct tlshd_handshake_parms {
|
||||
unsigned int session_status;
|
||||
};
|
||||
|
||||
+enum peer_type {
|
||||
+ PEER_TYPE_CLIENT,
|
||||
+ PEER_TYPE_SERVER,
|
||||
+};
|
||||
+
|
||||
/* client.c */
|
||||
extern void tlshd_tls13_clienthello_handshake(struct tlshd_handshake_parms *parms);
|
||||
extern void tlshd_quic_clienthello_handshake(struct tlshd_handshake_parms *parms);
|
||||
@@ -52,16 +57,11 @@ extern void tlshd_quic_clienthello_handshake(struct tlshd_handshake_parms *parms
|
||||
/* config.c */
|
||||
bool tlshd_config_init(const gchar *pathname);
|
||||
void tlshd_config_shutdown(void);
|
||||
-bool tlshd_config_get_client_truststore(char **bundle);
|
||||
-bool tlshd_config_get_client_crl(char **result);
|
||||
-bool tlshd_config_get_client_certs(gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len);
|
||||
-bool tlshd_config_get_client_privkey(gnutls_privkey_t *privkey);
|
||||
-bool tlshd_config_get_server_truststore(char **bundle);
|
||||
-bool tlshd_config_get_server_crl(char **result);
|
||||
-bool tlshd_config_get_server_certs(gnutls_pcert_st *certs,
|
||||
- unsigned int *certs_len);
|
||||
-bool tlshd_config_get_server_privkey(gnutls_privkey_t *privkey);
|
||||
+bool tlshd_config_get_truststore(int peer_type, char **bundle);
|
||||
+bool tlshd_config_get_crl(int peer_type, char **result);
|
||||
+bool tlshd_config_get_certs(int peer_type, gnutls_pcert_st *certs,
|
||||
+ unsigned int *certs_len);
|
||||
+bool tlshd_config_get_privkey(int peer_type, gnutls_privkey_t *privkey);
|
||||
|
||||
/* handshake.c */
|
||||
extern void tlshd_start_tls_handshake(gnutls_session_t session,
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -16,6 +16,11 @@ URL: %{forgeurl}
|
||||
# FIXME: is this a bug in the tagging scheme or forgesource macro?
|
||||
Source0: %{forgeurl}/releases/download/%{name}-%{baseversion}/%{name}-%{baseversion}.tar.gz
|
||||
|
||||
Patch0: ktls-utils-1.2.1-tlshd-deduplicate-client-and-server-config-functions.patch
|
||||
Patch1: ktls-utils-1.2.1-tlshd-Fix-priority-string-to-allow-PQC.patch
|
||||
Patch2: ktls-utils-1.2.1-tlshd-Server-side-dual-certificate-support.patch
|
||||
Patch3: ktls-utils-1.2.1-tlshd-Client-side-dual-certificate-support.patch
|
||||
|
||||
BuildRequires: bash systemd-rpm-macros
|
||||
BuildRequires: gcc make coreutils
|
||||
BuildRequires: pkgconfig(gnutls) >= 3.3.0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user