[PATCH] OpenSSL: Support PEM encoded chain from ca_cert blob
Beniamino Galvani
bgalvani at redhat.com
Fri Dec 19 03:09:05 PST 2025
Support configuring a chain of certificates through a ca_cert blob.
Since the code to to add the certificate to the store is used in
multiple places in tls_connection_ca_cert(), extract it to a separate
function.
Signed-off-by: Beniamino Galvani <bgalvani at redhat.com>
---
src/crypto/tls_openssl.c | 109 +++++++++++++++++++++++++++------------
1 file changed, 75 insertions(+), 34 deletions(-)
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index f172241b4..24e4360e2 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -2967,6 +2967,29 @@ static int tls_load_ca_der(struct tls_data *data, const char *ca_cert)
}
#endif /* OPENSSL_NO_STDIO */
+static int tls_add_ca_cert(SSL_CTX *ssl_ctx, X509 *cert)
+{
+ unsigned long err;
+
+ if (X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), cert) == 1)
+ return 0;
+
+ err = ERR_peek_error();
+
+ if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
+ ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ ERR_get_error();
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: %s - ignoring cert already in hash table error",
+ __func__);
+ return 0;
+ }
+
+ tls_show_errors(MSG_WARNING, __func__,
+ "Failed to add ca_cert_blob to certificate store");
+
+ return -1;
+}
static int tls_connection_ca_cert(struct tls_data *data,
struct tls_connection *conn,
@@ -3030,49 +3053,67 @@ static int tls_connection_ca_cert(struct tls_data *data,
}
if (ca_cert_blob) {
- X509 *cert = d2i_X509(NULL,
- (const unsigned char **) &ca_cert_blob,
- ca_cert_blob_len);
- if (cert == NULL) {
- BIO *bio = BIO_new_mem_buf(ca_cert_blob,
- ca_cert_blob_len);
-
- if (bio) {
- cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
+ unsigned long err;
+ X509 *cert;
+ int count;
+ BIO *bio;
- if (!cert) {
- tls_show_errors(MSG_WARNING, __func__,
- "Failed to parse ca_cert_blob");
+ cert = d2i_X509(NULL,
+ (const unsigned char **) &ca_cert_blob,
+ ca_cert_blob_len);
+ if (cert) {
+ if (tls_add_ca_cert(ssl_ctx, cert) < 0) {
+ X509_free(cert);
return -1;
}
- while (ERR_get_error()) {
- /* Ignore errors from DER conversion. */
- }
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
+ "to certificate store", __func__);
+ X509_free(cert);
+ return 0;
}
- if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
- cert)) {
- unsigned long err = ERR_peek_error();
- tls_show_errors(MSG_WARNING, __func__,
- "Failed to add ca_cert_blob to "
- "certificate store");
- if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
- ERR_GET_REASON(err) ==
- X509_R_CERT_ALREADY_IN_HASH_TABLE) {
- wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
- "cert already in hash table error",
- __func__);
- } else {
+ count = 0;
+ bio = BIO_new_mem_buf(ca_cert_blob, ca_cert_blob_len);
+ if (bio) {
+ while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL))) {
+ if (count == 0) {
+ /* Ignore errors from DER conversion
+ * if we detect a certificate in PEM
+ * format. */
+ ERR_clear_error();
+ }
+ count++;
+ if (tls_add_ca_cert(ssl_ctx, cert) < 0) {
+ X509_free(cert);
+ BIO_free(bio);
+ return -1;
+ }
X509_free(cert);
- return -1;
}
+ BIO_free(bio);
}
- X509_free(cert);
- wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
- "to certificate store", __func__);
+
+ if (count == 0) {
+ tls_show_errors(MSG_WARNING, __func__,
+ "Failed to parse ca_cert_blob");
+ return -1;
+ }
+
+ /* When the loop ends successfully, it's because of EOF */
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
+ ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
+ tls_show_errors(MSG_WARNING, __func__,
+ "Failed to parse ca_cert_blob bundle");
+ return -1;
+ }
+
+ ERR_clear_error();
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s - added %d ca_cert_blob "
+ "certificates to certificate store",
+ __func__, count);
return 0;
}
--
2.52.0
More information about the Hostap
mailing list