Hi On Thu, Oct 30, 2025 at 6:50 PM Daniel P. Berrangé <[email protected]> wrote:
> Currently only a single set of certificates can be loaded for a > server / client. Certificates are created using a particular > key algorithm and in some scenarios it can be useful to support > multiple algorithms in parallel. This requires the ability to > load multiple sets of certificates. > > Signed-off-by: Daniel P. Berrangé <[email protected]> > Reviewed-by: Marc-André Lureau <[email protected]> > --- > crypto/tlscredsx509.c | 164 ++++++++++++++++++++++++++++-------------- > 1 file changed, 112 insertions(+), 52 deletions(-) > > diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c > index 3cb0a6c31f..d7d1f594c0 100644 > --- a/crypto/tlscredsx509.c > +++ b/crypto/tlscredsx509.c > @@ -39,6 +39,14 @@ struct QCryptoTLSCredsX509 { > char *passwordid; > }; > > +typedef struct QCryptoTLSCredsX509IdentFiles > QCryptoTLSCredsX509IdentFiles; > +struct QCryptoTLSCredsX509IdentFiles { > + char *certpath; > + char *keypath; > + gnutls_x509_crt_t *certs; > + unsigned int ncerts; > + gnutls_x509_privkey_t key; > +}; > > typedef struct QCryptoTLSCredsX509Files QCryptoTLSCredsX509Files; > struct QCryptoTLSCredsX509Files { > @@ -46,11 +54,8 @@ struct QCryptoTLSCredsX509Files { > gnutls_x509_crt_t *cacerts; > unsigned int ncacerts; > > - char *certpath; > - char *keypath; > - gnutls_x509_crt_t *certs; > - unsigned int ncerts; > - gnutls_x509_privkey_t key; > + QCryptoTLSCredsX509IdentFiles **identities; > + size_t nidentities; > }; > > static QCryptoTLSCredsX509Files * > @@ -61,14 +66,9 @@ qcrypto_tls_creds_x509_files_new(void) > > > static void > -qcrypto_tls_creds_x509_files_free(QCryptoTLSCredsX509Files *files) > +qcrypto_tls_creds_x509_ident_files_free(QCryptoTLSCredsX509IdentFiles > *files) > { > size_t i; > - for (i = 0; i < files->ncacerts; i++) { > - gnutls_x509_crt_deinit(files->cacerts[i]); > - } > - g_free(files->cacerts); > - g_free(files->cacertpath); > for (i = 0; i < files->ncerts; i++) { > gnutls_x509_crt_deinit(files->certs[i]); > } > @@ -79,6 +79,26 @@ > qcrypto_tls_creds_x509_files_free(QCryptoTLSCredsX509Files *files) > g_free(files); > } > > +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSCredsX509IdentFiles, > + qcrypto_tls_creds_x509_ident_files_free); > + > + > +static void > +qcrypto_tls_creds_x509_files_free(QCryptoTLSCredsX509Files *files) > +{ > + size_t i; > + for (i = 0; i < files->ncacerts; i++) { > + gnutls_x509_crt_deinit(files->cacerts[i]); > + } > + g_free(files->cacerts); > + g_free(files->cacertpath); > + for (i = 0; i < files->nidentities; i++) { > + qcrypto_tls_creds_x509_ident_files_free(files->identities[i]); > + } > + g_free(files->identities); > + g_free(files); > +} > + > G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSCredsX509Files, > qcrypto_tls_creds_x509_files_free); > > @@ -573,33 +593,32 @@ qcrypto_tls_creds_load_privkey(QCryptoTLSCredsX509 > *creds, > > > static int > -qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds, > - QCryptoTLSCredsX509Files *files, > - bool isServer, > - Error **errp) > +qcrypto_tls_creds_x509_sanity_check_identity(QCryptoTLSCredsX509 *creds, > + QCryptoTLSCredsX509Files > *files, > + > QCryptoTLSCredsX509IdentFiles *ifiles, > + bool isServer, > + Error **errp) > { > size_t i; > > - for (i = 0; i < files->ncerts; i++) { > + for (i = 0; i < ifiles->ncerts; i++) { > if (qcrypto_tls_creds_check_cert(creds, > - files->certs[i], files->certpath, > + ifiles->certs[i], > ifiles->certpath, > isServer, i != 0, errp) < 0) { > return -1; > } > } > > - if (files->ncerts && > + if (ifiles->ncerts && > qcrypto_tls_creds_check_authority_chain(creds, files, > - files->certs, > files->ncerts, > + ifiles->certs, > ifiles->ncerts, > isServer, errp) < 0) { > return -1; > } > > - if (files->ncerts && > - qcrypto_tls_creds_check_cert_pair(files, > - files->certs, files->ncerts, > - files->certpath, isServer, > - errp) < 0) { > + if (ifiles->ncerts && > + qcrypto_tls_creds_check_cert_pair(files, ifiles->certs, > ifiles->ncerts, > + ifiles->certpath, isServer, > errp) < 0) { > return -1; > } > > @@ -607,6 +626,26 @@ > qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds, > } > > > +static int > +qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds, > + QCryptoTLSCredsX509Files *files, > + bool isServer, > + Error **errp) > +{ > + size_t i; > + for (i = 0; i < files->nidentities; i++) { > + if (qcrypto_tls_creds_x509_sanity_check_identity(creds, > + files, > + > files->identities[i], > + isServer, > + errp) < 0) { > + return -1; > + } > + } > + return 0; > +} > + > + > static int > qcrypto_tls_creds_x509_load_ca(QCryptoTLSCredsX509 *creds, > QCryptoTLSCredsBox *box, > @@ -642,48 +681,38 @@ qcrypto_tls_creds_x509_load_ca(QCryptoTLSCredsX509 > *creds, > } > > > -static int > +static QCryptoTLSCredsX509IdentFiles * > qcrypto_tls_creds_x509_load_identity(QCryptoTLSCredsX509 *creds, > QCryptoTLSCredsBox *box, > - QCryptoTLSCredsX509Files *files, > - bool isServer, > + const char *certbase, > + const char *keybase, > + bool isOptional, > Error **errp) > { > + g_autoptr(QCryptoTLSCredsX509IdentFiles) files = > + g_new0(QCryptoTLSCredsX509IdentFiles, 1); > int ret; > > - if (isServer) { > - if (qcrypto_tls_creds_get_path(&creds->parent_obj, > - QCRYPTO_TLS_CREDS_X509_SERVER_CERT, > - true, &files->certpath, errp) < 0 > || > - qcrypto_tls_creds_get_path(&creds->parent_obj, > - QCRYPTO_TLS_CREDS_X509_SERVER_KEY, > - true, &files->keypath, errp) < 0) { > - return -1; > - } > - } else { > - if (qcrypto_tls_creds_get_path(&creds->parent_obj, > - QCRYPTO_TLS_CREDS_X509_CLIENT_CERT, > - false, &files->certpath, errp) < 0 > || > - qcrypto_tls_creds_get_path(&creds->parent_obj, > - QCRYPTO_TLS_CREDS_X509_CLIENT_KEY, > - false, &files->keypath, errp) < 0) > { > - return -1; > - } > + if (qcrypto_tls_creds_get_path(&creds->parent_obj, certbase, > + !isOptional, &files->certpath, errp) < > 0 || > + qcrypto_tls_creds_get_path(&creds->parent_obj, keybase, > + !isOptional, &files->keypath, errp) < > 0) { > + return NULL; > } > > if (!files->certpath && > !files->keypath) { > - return 0; > + return NULL; > } > if (files->certpath && !files->keypath) { > error_setg(errp, "Cert '%s' without corresponding key", > files->certpath); > - return -1; > + return NULL; > } > if (!files->certpath && files->keypath) { > error_setg(errp, "Key '%s' without corresponding cert", > files->keypath); > - return -1; > + return NULL; > } > > if (qcrypto_tls_creds_load_cert_list(creds, > @@ -691,14 +720,14 @@ > qcrypto_tls_creds_x509_load_identity(QCryptoTLSCredsX509 *creds, > &files->certs, > &files->ncerts, > errp) < 0) { > - return -1; > + return NULL; > } > > if (qcrypto_tls_creds_load_privkey(creds, > files->keypath, > &files->key, > errp) < 0) { > - return -1; > + return NULL; > } > > ret = gnutls_certificate_set_x509_key(box->data.cert, > @@ -708,8 +737,39 @@ > qcrypto_tls_creds_x509_load_identity(QCryptoTLSCredsX509 *creds, > if (ret < 0) { > error_setg(errp, "Cannot set certificate '%s' & key '%s': %s", > files->certpath, files->keypath, gnutls_strerror(ret)); > + return NULL; > + } > + return g_steal_pointer(&files); > +} > + > + > +static int > +qcrypto_tls_creds_x509_load_identities(QCryptoTLSCredsX509 *creds, > + QCryptoTLSCredsBox *box, > + QCryptoTLSCredsX509Files *files, > + bool isServer, > + Error **errp) > +{ > + QCryptoTLSCredsX509IdentFiles *ifiles; > + > + ifiles = qcrypto_tls_creds_x509_load_identity( > + creds, box, > + isServer ? > + QCRYPTO_TLS_CREDS_X509_SERVER_CERT : > + QCRYPTO_TLS_CREDS_X509_CLIENT_CERT, > + isServer ? > + QCRYPTO_TLS_CREDS_X509_SERVER_KEY : > + QCRYPTO_TLS_CREDS_X509_CLIENT_KEY, > + !isServer, errp); > + if (!ifiles) { > return -1; > } > + > + files->identities = g_renew(QCryptoTLSCredsX509IdentFiles *, > + files->identities, > + files->nidentities + 1); > + files->identities[files->nidentities++] = ifiles; > + > return 0; > } > > @@ -752,8 +812,8 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds, > return -1; > } > > - if (qcrypto_tls_creds_x509_load_identity(creds, box, files, > - isServer, errp) < 0) { > + if (qcrypto_tls_creds_x509_load_identities(creds, box, files, > + isServer, errp) < 0) { > return -1; > } > > -- > 2.51.1 > >
