From: Dr. Stephen Henson Date: Thu, 26 Jan 2012 15:47:32 +0000 (+0000) Subject: Tidy/enhance certificate chain output code. X-Git-Tag: master-post-reformat~1967 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=4379d0e457ebd404f248d2e2c265ff11d25bfab4;ds=sidebyside Tidy/enhance certificate chain output code. New function ssl_add_cert_chain which adds a certificate chain to SSL internal BUF_MEM. Use this function in ssl3_output_cert_chain and dtls1_output_cert_chain instead of partly duplicating code. --- diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 0a84f95711..ad2d1fcc98 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -992,70 +992,14 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } -static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) - { - int n; - unsigned char *p; - - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) - { - SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); - return 0; - } - p=(unsigned char *)&(buf->data[*l]); - l2n3(n,p); - i2d_X509(x,&p); - *l+=n+3; - - return 1; - } unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; - int i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; - BUF_MEM *buf; + BUF_MEM *buf=s->init_buf; - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - buf=s->init_buf; - if (!BUF_MEM_grow_clean(buf,10)) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - if (x != NULL) - { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i=0; i < sk_X509_num(xs_ctx.chain); i++) - { - x = sk_X509_value(xs_ctx.chain, i); - - if (!dtls1_add_cert_to_buf(buf, &l, x)) - { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - /* Thawte special :-) */ - for (i=0; ictx->extra_certs); i++) - { - x=sk_X509_value(s->ctx->extra_certs,i); - if (!dtls1_add_cert_to_buf(buf, &l, x)) - return 0; - } + if (!ssl_add_cert_chain(s, x, &l)) + return 0; l-= (3 + DTLS1_HM_HEADER_LENGTH); diff --git a/ssl/s3_both.c b/ssl/s3_both.c index c58713ffb8..153b2bfc78 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -321,84 +321,14 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b) return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } -static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) - { - int n; - unsigned char *p; - - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) - { - SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); - return(-1); - } - p=(unsigned char *)&(buf->data[*l]); - l2n3(n,p); - i2d_X509(x,&p); - *l+=n+3; - - return(0); - } - unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; - int i; unsigned long l=7; - BUF_MEM *buf; - int no_chain; - - if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) - no_chain = 1; - else - no_chain = 0; + BUF_MEM *buf = s->init_buf; - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - buf=s->init_buf; - if (!BUF_MEM_grow_clean(buf,10)) - { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - if (x != NULL) - { - if (no_chain) - { - if (ssl3_add_cert_to_buf(buf, &l, x)) - return(0); - } - else - { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) - { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i=0; i < sk_X509_num(xs_ctx.chain); i++) - { - x = sk_X509_value(xs_ctx.chain, i); - - if (ssl3_add_cert_to_buf(buf, &l, x)) - { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - } - /* Thawte special :-) */ - for (i=0; ictx->extra_certs); i++) - { - x=sk_X509_value(s->ctx->extra_certs,i); - if (ssl3_add_cert_to_buf(buf, &l, x)) - return(0); - } + if (!ssl_add_cert_chain(s, x, &l)) + return 0; l-=7; p=(unsigned char *)&(buf->data[4]); diff --git a/ssl/ssl.h b/ssl/ssl.h index 4b7397f4bf..b9325feb41 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -2175,6 +2175,8 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_CERT_CHAIN 316 +#define SSL_F_SSL_ADD_CERT_TO_BUF 317 #define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 #define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 917be31876..c1e7ec1b7e 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -851,3 +851,85 @@ err: return ret; } +/* Add a certificate to a BUF_MEM structure */ + +static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) + { + int n; + unsigned char *p; + + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) + { + SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); + return 0; + } + p=(unsigned char *)&(buf->data[*l]); + l2n3(n,p); + i2d_X509(x,&p); + *l+=n+3; + + return 1; + } + +/* Add certificate chain to internal SSL BUF_MEM strcuture */ +int ssl_add_cert_chain(SSL *s, X509 *x, unsigned long *l) + { + BUF_MEM *buf = s->init_buf; + int no_chain; + int i; + + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) + no_chain = 1; + else + no_chain = 0; + + /* TLSv1 sends a chain with nothing in it, instead of an alert */ + if (!BUF_MEM_grow_clean(buf,10)) + { + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB); + return 0; + } + if (x != NULL) + { + if (no_chain) + { + if (!ssl_add_cert_to_buf(buf, l, x)) + return 0; + } + else + { + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) + { + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } + X509_verify_cert(&xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + for (i=0; i < sk_X509_num(xs_ctx.chain); i++) + { + x = sk_X509_value(xs_ctx.chain, i); + + if (ssl_add_cert_to_buf(buf, l, x)) + { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } + } + /* Thawte special :-) */ + for (i=0; ictx->extra_certs); i++) + { + x=sk_X509_value(s->ctx->extra_certs,i); + if (!ssl_add_cert_to_buf(buf, l, x)) + return 0; + } + + return 1; + } + diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 4eb2e44f5d..e94ffe0141 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -180,6 +180,8 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "SSL3_SETUP_WRITE_BUFFER"}, {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "SSL3_WRITE_BYTES"}, {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "SSL3_WRITE_PENDING"}, +{ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "SSL_ADD_CERT_CHAIN"}, +{ERR_FUNC(SSL_F_SSL_ADD_CERT_TO_BUF), "SSL_ADD_CERT_TO_BUF"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT), "SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT), "SSL_ADD_CLIENTHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT), "SSL_ADD_CLIENTHELLO_USE_SRTP_EXT"}, diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 8cbaaab44f..25f5fd49fb 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -825,6 +825,7 @@ int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc, const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp); int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md); int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); +int ssl_add_cert_chain(SSL *s, X509 *x, unsigned long *l); int ssl_undefined_function(SSL *s); int ssl_undefined_void_function(void); int ssl_undefined_const_function(const SSL *s);