diff options
-rw-r--r-- | tls.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/tls.c b/tls.c index 2a42510..9e5a58d 100644 --- a/tls.c +++ b/tls.c @@ -327,6 +327,66 @@ tls_cert_pubkey_hash(X509 *cert, char **hash) return (rv); } +static int +use_certificate_chain_bio(SSL_CTX *ctx, BIO *in) +{ + X509 *ca, *x = NULL; + unsigned long err; + int ret = 0; + + if ((x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL)) == NULL) { + SSLerr(0xfff, ERR_R_PEM_LIB); + goto err; + } + + if (!SSL_CTX_use_certificate(ctx, x)) + goto err; + + if (!SSL_CTX_clear_chain_certs(ctx)) + goto err; + + /* Process any additional CA certificates. */ + while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL) { + if (!SSL_CTX_add0_chain_cert(ctx, ca)) { + X509_free(ca); + goto err; + } + } + + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + ret = 1; + } + + err: + X509_free(x); + + return (ret); +} + +static int +use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len) +{ + BIO *in; + int ret = 0; + + in = BIO_new_mem_buf(buf, len); + if (in == NULL) { + SSLerr(0xfff, ERR_R_BUF_LIB); + goto end; + } + + ret = use_certificate_chain_bio(ctx, in); + + end: + BIO_free(in); + + return (ret); +} + int tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, struct tls_keypair *keypair, int required) @@ -345,7 +405,7 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, goto err; } - if (SSL_CTX_use_certificate_chain_mem(ssl_ctx, + if (use_certificate_chain_mem(ssl_ctx, keypair->cert_mem, keypair->cert_len) != 1) { tls_set_errorx(ctx, "failed to load certificate"); goto err; |