From 86dd9a4f816c164cfa45e157991a16f15badb4a3 Mon Sep 17 00:00:00 2001 From: reyk <> Date: Sun, 28 Sep 2014 14:45:48 +0000 Subject: Add a new API function SSL_CTX_use_certificate_chain() that allows to read the PEM-encoded certificate chain from memory instead of a file. This idea is derived from an older implementation in relayd that was needed to use the function with a privep'ed process in a chroot. Now it is time to get it into LibreSSL to make the API more privsep- friendly and to make it available for other programs and the ressl library. ok jsing@ miod@ --- src/lib/libressl/ressl.c | 21 ++----- .../libssl/src/doc/ssl/SSL_CTX_use_certificate.pod | 10 ++-- src/lib/libssl/src/ssl/ssl.h | 3 +- src/lib/libssl/src/ssl/ssl_rsa.c | 64 ++++++++++++++++------ src/lib/libssl/ssl.h | 3 +- src/lib/libssl/ssl_rsa.c | 64 ++++++++++++++++------ 6 files changed, 111 insertions(+), 54 deletions(-) diff --git a/src/lib/libressl/ressl.c b/src/lib/libressl/ressl.c index 1bf971419b..f01448b8f4 100644 --- a/src/lib/libressl/ressl.c +++ b/src/lib/libressl/ressl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ressl.c,v 1.13 2014/09/28 06:24:00 tedu Exp $ */ +/* $OpenBSD: ressl.c,v 1.14 2014/09/28 14:45:48 reyk Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -110,22 +110,11 @@ ressl_configure_keypair(struct ressl *ctx) BIO *bio = NULL; if (ctx->config->cert_mem != NULL) { - if ((bio = BIO_new_mem_buf(ctx->config->cert_mem, - ctx->config->cert_len)) == NULL) { - ressl_set_error(ctx, "failed to create buffer"); - goto err; - } - if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { - ressl_set_error(ctx, "failed to read certificate"); - goto err; - } - if (SSL_CTX_use_certificate(ctx->ssl_ctx, cert) != 1) { + if (SSL_CTX_use_certificate_chain(ctx->ssl_ctx, + ctx->config->cert_mem, ctx->config->cert_len) != 1) { ressl_set_error(ctx, "failed to load certificate"); goto err; } - BIO_free(bio); - bio = NULL; - X509_free(cert); cert = NULL; } if (ctx->config->key_mem != NULL) { @@ -150,8 +139,8 @@ ressl_configure_keypair(struct ressl *ctx) } if (ctx->config->cert_file != NULL) { - if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, - ctx->config->cert_file, SSL_FILETYPE_PEM) != 1) { + if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, + ctx->config->cert_file) != 1) { ressl_set_error(ctx, "failed to load certificate file"); goto err; } diff --git a/src/lib/libssl/src/doc/ssl/SSL_CTX_use_certificate.pod b/src/lib/libssl/src/doc/ssl/SSL_CTX_use_certificate.pod index 8e0d609d05..560e00937f 100644 --- a/src/lib/libssl/src/doc/ssl/SSL_CTX_use_certificate.pod +++ b/src/lib/libssl/src/doc/ssl/SSL_CTX_use_certificate.pod @@ -3,8 +3,9 @@ =head1 NAME SSL_CTX_use_certificate, SSL_CTX_use_certificate_ASN1, -SSL_CTX_use_certificate_file, SSL_use_certificate, SSL_use_certificate_ASN1, -SSL_use_certificate_file, SSL_CTX_use_certificate_chain_file, +SSL_CTX_use_certificate_file, SSL_use_certificate, +SSL_use_certificate_ASN1, SSL_use_certificate_file, +SSL_CTX_use_certificate_chain, SSL_CTX_use_certificate_chain_file, SSL_CTX_use_PrivateKey, SSL_CTX_use_PrivateKey_ASN1, SSL_CTX_use_PrivateKey_file, SSL_CTX_use_RSAPrivateKey, SSL_CTX_use_RSAPrivateKey_ASN1, SSL_CTX_use_RSAPrivateKey_file, @@ -24,6 +25,7 @@ data int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len); int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, void *buf, int len); int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); @@ -75,8 +77,8 @@ SSL_use_certificate_file() loads the certificate from B into B. See the NOTES section on why SSL_CTX_use_certificate_chain_file() should be preferred. -SSL_CTX_use_certificate_chain_file() loads a certificate chain from -B into B. The certificates must be in PEM format and must +The SSL_CTX_use_certificate_chain*() functions load a certificate chain +into B. The certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA. diff --git a/src/lib/libssl/src/ssl/ssl.h b/src/lib/libssl/src/ssl/ssl.h index 3b948245f2..c7dd4259cc 100644 --- a/src/lib/libssl/src/ssl/ssl.h +++ b/src/lib/libssl/src/ssl/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.65 2014/09/27 11:01:06 jsing Exp $ */ +/* $OpenBSD: ssl.h,v 1.66 2014/09/28 14:45:48 reyk Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1530,6 +1530,7 @@ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, void *buf, int len); STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, const char *file); diff --git a/src/lib/libssl/src/ssl/ssl_rsa.c b/src/lib/libssl/src/ssl/ssl_rsa.c index d4d14bad35..e8b72f016e 100644 --- a/src/lib/libssl/src/ssl/ssl_rsa.c +++ b/src/lib/libssl/src/ssl/ssl_rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_rsa.c,v 1.16 2014/07/12 16:03:37 miod Exp $ */ +/* $OpenBSD: ssl_rsa.c,v 1.17 2014/09/28 14:45:48 reyk Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,8 @@ static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); +static int ssl_ctx_use_certificate_chain_bio(SSL_CTX *, BIO *); + int SSL_use_certificate(SSL *ssl, X509 *x) { @@ -637,30 +639,18 @@ SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, /* - * Read a file that contains our certificate in "PEM" format, + * Read a bio that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. */ -int -SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +static int +ssl_ctx_use_certificate_chain_bio(SSL_CTX *ctx, BIO *in) { - BIO *in; int ret = 0; X509 *x = NULL; ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ - in = BIO_new(BIO_s_file_internal()); - if (in == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in, file) <= 0) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); - goto end; - } - x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata); if (x == NULL) { @@ -716,6 +706,48 @@ SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) end: if (x != NULL) X509_free(x); + return (ret); +} + +int +SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + BIO *in; + int ret = 0; + + in = BIO_new(BIO_s_file_internal()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); + goto end; + } + + ret = ssl_ctx_use_certificate_chain_bio(ctx, in); + +end: + BIO_free(in); + return (ret); +} + +int +SSL_CTX_use_certificate_chain(SSL_CTX *ctx, void *buf, int len) +{ + BIO *in; + int ret = 0; + + in = BIO_new_mem_buf(buf, len); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + goto end; + } + + ret = ssl_ctx_use_certificate_chain_bio(ctx, in); + +end: BIO_free(in); return (ret); } diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h index 3b948245f2..c7dd4259cc 100644 --- a/src/lib/libssl/ssl.h +++ b/src/lib/libssl/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.65 2014/09/27 11:01:06 jsing Exp $ */ +/* $OpenBSD: ssl.h,v 1.66 2014/09/28 14:45:48 reyk Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1530,6 +1530,7 @@ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, void *buf, int len); STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, const char *file); diff --git a/src/lib/libssl/ssl_rsa.c b/src/lib/libssl/ssl_rsa.c index d4d14bad35..e8b72f016e 100644 --- a/src/lib/libssl/ssl_rsa.c +++ b/src/lib/libssl/ssl_rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_rsa.c,v 1.16 2014/07/12 16:03:37 miod Exp $ */ +/* $OpenBSD: ssl_rsa.c,v 1.17 2014/09/28 14:45:48 reyk Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,8 @@ static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); +static int ssl_ctx_use_certificate_chain_bio(SSL_CTX *, BIO *); + int SSL_use_certificate(SSL *ssl, X509 *x) { @@ -637,30 +639,18 @@ SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, /* - * Read a file that contains our certificate in "PEM" format, + * Read a bio that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. */ -int -SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +static int +ssl_ctx_use_certificate_chain_bio(SSL_CTX *ctx, BIO *in) { - BIO *in; int ret = 0; X509 *x = NULL; ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ - in = BIO_new(BIO_s_file_internal()); - if (in == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in, file) <= 0) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); - goto end; - } - x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata); if (x == NULL) { @@ -716,6 +706,48 @@ SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) end: if (x != NULL) X509_free(x); + return (ret); +} + +int +SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + BIO *in; + int ret = 0; + + in = BIO_new(BIO_s_file_internal()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); + goto end; + } + + ret = ssl_ctx_use_certificate_chain_bio(ctx, in); + +end: + BIO_free(in); + return (ret); +} + +int +SSL_CTX_use_certificate_chain(SSL_CTX *ctx, void *buf, int len) +{ + BIO *in; + int ret = 0; + + in = BIO_new_mem_buf(buf, len); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + goto end; + } + + ret = ssl_ctx_use_certificate_chain_bio(ctx, in); + +end: BIO_free(in); return (ret); } -- cgit v1.2.3-55-g6feb