summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2016-12-06 13:17:52 +0000
committerjsing <jsing@openbsd.org>2016-12-06 13:17:52 +0000
commit16cbd6ee376ed1b3a3bb32a8b4453eea8d610f30 (patch)
tree470bff66790f85a9dc3c335734d416270f10b510
parentMake sure iwm(4) only calls ieee80211_mira_choose() while in RUN state. (diff)
downloadwireguard-openbsd-16cbd6ee376ed1b3a3bb32a8b4453eea8d610f30.tar.xz
wireguard-openbsd-16cbd6ee376ed1b3a3bb32a8b4453eea8d610f30.zip
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@
-rw-r--r--lib/libssl/s3_both.c90
-rw-r--r--lib/libssl/s3_clnt.c31
-rw-r--r--lib/libssl/s3_lib.c73
-rw-r--r--lib/libssl/s3_srvr.c29
-rw-r--r--lib/libssl/ssl_locl.h9
5 files changed, 168 insertions, 64 deletions
diff --git a/lib/libssl/s3_both.c b/lib/libssl/s3_both.c
index cfd0fb9b4bd..52af34a8097 100644
--- a/lib/libssl/s3_both.c
+++ b/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/lib/libssl/s3_clnt.c b/lib/libssl/s3_clnt.c
index f39ae7fab3f..772bb703dda 100644
--- a/lib/libssl/s3_clnt.c
+++ b/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/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c
index e66394a491b..db9292172d9 100644
--- a/lib/libssl/s3_lib.c
+++ b/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 <limits.h>
#include <stdio.h>
#include <openssl/dh.h>
@@ -1725,6 +1726,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)
{
if (SSL_IS_DTLS(s))
diff --git a/lib/libssl/s3_srvr.c b/lib/libssl/s3_srvr.c
index cbdc7bc6bc1..c9790319331 100644
--- a/lib/libssl/s3_srvr.c
+++ b/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/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h
index c7ae289a3ad..89fb83eb9ab 100644
--- a/lib/libssl/ssl_locl.h
+++ b/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 <openssl/ssl.h>
#include <openssl/stack.h>
+#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);