From 21ff89ebbb4bdd4d2a5dee38cb8d4960c200234c Mon Sep 17 00:00:00 2001 From: jsing <> Date: Tue, 6 Dec 2016 13:17:52 +0000 Subject: Convert certificate handshake message generation to CBB, with some clean up and restructure. This also adds CBB based variants of the ssl3_handshake_msg_{start,finish} functions - for the time being these use a CBB to build the messages, then copy back into the init_buf. ok doug@ --- src/lib/libssl/s3_both.c | 90 +++++++++++++++++++++++------------------------ src/lib/libssl/s3_clnt.c | 31 +++++++++++----- src/lib/libssl/s3_lib.c | 73 +++++++++++++++++++++++++++++++++++++- src/lib/libssl/s3_srvr.c | 29 +++++++++++---- src/lib/libssl/ssl_locl.h | 9 +++-- 5 files changed, 168 insertions(+), 64 deletions(-) diff --git a/src/lib/libssl/s3_both.c b/src/lib/libssl/s3_both.c index cfd0fb9b4b..52af34a809 100644 --- a/src/lib/libssl/s3_both.c +++ b/src/lib/libssl/s3_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_both.c,v 1.48 2015/09/12 15:03:39 jsing Exp $ */ +/* $OpenBSD: s3_both.c,v 1.49 2016/12/06 13:17:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -316,49 +316,50 @@ ssl3_send_change_cipher_spec(SSL *s, int a, int b) } static int -ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) +ssl3_add_cert(CBB *cbb, X509 *x) { - int n; - unsigned char *p; + unsigned char *data; + int cert_len; + int ret = 0; + CBB cert; - n = i2d_X509(x, NULL); - if (!BUF_MEM_grow_clean(buf, n + (*l) + 3)) { - SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF, ERR_R_BUF_LIB); - return (-1); - } - /* XXX */ - p = (unsigned char *)&(buf->data[*l]); - l2n3(n, p); - i2d_X509(x, &p); - *l += n + 3; + if ((cert_len = i2d_X509(x, NULL)) < 0) + goto err; - return (0); + if (!CBB_add_u24_length_prefixed(cbb, &cert)) + goto err; + if (!CBB_add_space(&cert, &data, cert_len)) + goto err; + if (i2d_X509(x, &data) < 0) + goto err; + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + return (ret); } -unsigned long -ssl3_output_cert_chain(SSL *s, X509 *x) +int +ssl3_output_cert_chain(SSL *s, CBB *cbb, X509 *x) { - unsigned char *p; - unsigned long l = ssl3_handshake_msg_hdr_len(s) + 3; - BUF_MEM *buf; - int no_chain; + int no_chain = 0; + CBB cert_list; + int ret = 0; int i; + if (!CBB_add_u24_length_prefixed(cbb, &cert_list)) + goto err; + 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 */ - buf = s->init_buf; - if (!BUF_MEM_grow_clean(buf, ssl3_handshake_msg_hdr_len(s) + 6)) { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB); - return (0); - } + /* TLSv1 sends a chain with nothing in it, instead of an alert. */ if (x != NULL) { if (no_chain) { - if (ssl3_add_cert_to_buf(buf, &l, x)) - return (0); + if (!ssl3_add_cert(&cert_list, x)) + goto err; } else { X509_STORE_CTX xs_ctx; @@ -366,7 +367,7 @@ ssl3_output_cert_chain(SSL *s, X509 *x) x, NULL)) { SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB); - return (0); + goto err; } X509_verify_cert(&xs_ctx); @@ -374,30 +375,29 @@ ssl3_output_cert_chain(SSL *s, X509 *x) 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)) { + if (!ssl3_add_cert(&cert_list, x)) { X509_STORE_CTX_cleanup(&xs_ctx); - return 0; + goto err; } } X509_STORE_CTX_cleanup(&xs_ctx); } } + /* Thawte special :-) */ for (i = 0; i < sk_X509_num(s->ctx->extra_certs); i++) { x = sk_X509_value(s->ctx->extra_certs, i); - if (ssl3_add_cert_to_buf(buf, &l, x)) - return (0); + if (!ssl3_add_cert(&cert_list, x)) + goto err; } - l -= ssl3_handshake_msg_hdr_len(s) + 3; - p = (unsigned char *)&(buf->data[4]); - l2n3(l, p); - l += 3; - p = (unsigned char *)&(buf->data[0]); - *(p++) = SSL3_MT_CERTIFICATE; - l2n3(l, p); - l += 4; /* XXX */ - return (l); + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + return (ret); } /* diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index f39ae7fab3..772bb703dd 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_clnt.c,v 1.149 2016/12/04 14:32:30 jsing Exp $ */ +/* $OpenBSD: s3_clnt.c,v 1.150 2016/12/06 13:17:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -2433,10 +2433,12 @@ err: int ssl3_send_client_certificate(SSL *s) { - X509 *x509 = NULL; - EVP_PKEY *pkey = NULL; - int i; - unsigned long l; + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + CBB cbb, client_cert; + int i; + + memset(&cbb, 0, sizeof(cbb)); if (s->state == SSL3_ST_CW_CERT_A) { if ((s->cert == NULL) || (s->cert->key->x509 == NULL) || @@ -2480,14 +2482,25 @@ ssl3_send_client_certificate(SSL *s) } if (s->state == SSL3_ST_CW_CERT_C) { + if (!ssl3_handshake_msg_start_cbb(s, &cbb, &client_cert, + SSL3_MT_CERTIFICATE)) + goto err; + if (!ssl3_output_cert_chain(s, &client_cert, + (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key->x509)) + goto err; + if (!ssl3_handshake_msg_finish_cbb(s, &cbb)) + goto err; + s->state = SSL3_ST_CW_CERT_D; - l = ssl3_output_cert_chain(s, - (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key->x509); - s->init_num = (int)l; - s->init_off = 0; } + /* SSL3_ST_CW_CERT_D */ return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + + err: + CBB_cleanup(&cbb); + + return (0); } #define has_bits(i,m) (((i)&(m)) == (m)) diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c index e66394a491..db9292172d 100644 --- a/src/lib/libssl/s3_lib.c +++ b/src/lib/libssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.112 2016/11/06 13:11:40 jsing Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.113 2016/12/06 13:17:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -148,6 +148,7 @@ * OTHERWISE. */ +#include #include #include @@ -1724,6 +1725,76 @@ ssl3_handshake_msg_finish(SSL *s, unsigned int len) } } +int +ssl3_handshake_msg_start_cbb(SSL *s, CBB *handshake, CBB *body, + uint8_t msg_type) +{ + int ret = 0; + + if (!CBB_init(handshake, SSL3_RT_MAX_PLAIN_LENGTH)) + goto err; + if (!CBB_add_u8(handshake, msg_type)) + goto err; + if (SSL_IS_DTLS(s)) { + unsigned char *data; + + if (!CBB_add_space(handshake, &data, DTLS1_HM_HEADER_LENGTH - + SSL3_HM_HEADER_LENGTH)) + goto err; + } + if (!CBB_add_u24_length_prefixed(handshake, body)) + goto err; + + ret = 1; + + err: + return (ret); +} + +int +ssl3_handshake_msg_finish_cbb(SSL *s, CBB *handshake) +{ + unsigned char *data = NULL; + size_t outlen; + int ret = 0; + + if (!CBB_finish(handshake, &data, &outlen)) + goto err; + + if (outlen > INT_MAX) + goto err; + + if (!BUF_MEM_grow_clean(s->init_buf, outlen)) + goto err; + + memcpy(s->init_buf->data, data, outlen); + + s->init_num = (int)outlen; + s->init_off = 0; + + if (SSL_IS_DTLS(s)) { + unsigned long len; + uint8_t msg_type; + CBS cbs; + + CBS_init(&cbs, data, outlen); + if (!CBS_get_u8(&cbs, &msg_type)) + goto err; + + len = outlen - ssl3_handshake_msg_hdr_len(s); + + dtls1_set_message_header(s, data, msg_type, len, 0, len); + dtls1_buffer_message(s, 0); + } + + ret = 1; + + err: + free(data); + + return (ret); +} + int ssl3_handshake_write(SSL *s) { diff --git a/src/lib/libssl/s3_srvr.c b/src/lib/libssl/s3_srvr.c index cbdc7bc6bc..c979031933 100644 --- a/src/lib/libssl/s3_srvr.c +++ b/src/lib/libssl/s3_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_srvr.c,v 1.135 2016/12/04 14:20:13 jsing Exp $ */ +/* $OpenBSD: s3_srvr.c,v 1.136 2016/12/06 13:17:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -2524,25 +2524,40 @@ err: int ssl3_send_server_certificate(SSL *s) { - unsigned long l; + CBB cbb, server_cert; X509 *x; + /* + * Server Certificate - RFC 5246, section 7.4.2. + */ + + memset(&cbb, 0, sizeof(cbb)); + if (s->state == SSL3_ST_SW_CERT_A) { - x = ssl_get_server_send_cert(s); - if (x == NULL) { + if ((x = ssl_get_server_send_cert(s)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); return (0); } - l = ssl3_output_cert_chain(s, x); + if (!ssl3_handshake_msg_start_cbb(s, &cbb, &server_cert, + SSL3_MT_CERTIFICATE)) + goto err; + if (!ssl3_output_cert_chain(s, &server_cert, x)) + goto err; + if (!ssl3_handshake_msg_finish_cbb(s, &cbb)) + goto err; + s->state = SSL3_ST_SW_CERT_B; - s->init_num = (int)l; - s->init_off = 0; } /* SSL3_ST_SW_CERT_B */ return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (0); } /* send a new session ticket (not necessarily for a new session) */ diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index c7ae289a3a..89fb83eb9a 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.137 2016/12/04 14:32:30 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.138 2016/12/06 13:17:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -160,6 +160,8 @@ #include #include +#include "bytestring.h" + __BEGIN_HIDDEN_DECLS #define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ @@ -617,7 +619,7 @@ int ssl3_renegotiate_check(SSL *ssl); int ssl3_dispatch_alert(SSL *s); int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); -unsigned long ssl3_output_cert_chain(SSL *s, X509 *x); +int ssl3_output_cert_chain(SSL *s, CBB *cbb, X509 *x); SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, STACK_OF(SSL_CIPHER) *srvr); int ssl3_setup_buffers(SSL *s); @@ -644,6 +646,9 @@ int ssl3_pending(const SSL *s); int ssl3_handshake_msg_hdr_len(SSL *s); unsigned char *ssl3_handshake_msg_start(SSL *s, uint8_t htype); void ssl3_handshake_msg_finish(SSL *s, unsigned int len); +int ssl3_handshake_msg_start_cbb(SSL *s, CBB *handshake, CBB *body, + uint8_t msg_type); +int ssl3_handshake_msg_finish_cbb(SSL *s, CBB *handshake); int ssl3_handshake_write(SSL *s); void tls1_record_sequence_increment(unsigned char *seq); -- cgit v1.2.3-55-g6feb