diff options
author | 2017-03-05 14:39:53 +0000 | |
---|---|---|
committer | 2017-03-05 14:39:53 +0000 | |
commit | 366dc2a2e9ef223ce3418b3d76bba648547d45ef (patch) | |
tree | d9fd995f7169f30e2e7cdc7ee6ee0edc127c064f | |
parent | Convert various handshake message generation functions to CBB. (diff) | |
download | wireguard-openbsd-366dc2a2e9ef223ce3418b3d76bba648547d45ef.tar.xz wireguard-openbsd-366dc2a2e9ef223ce3418b3d76bba648547d45ef.zip |
Provide a rolling handshake hash that commences as soon as the cipher
suite has been selected, and convert the final finish MAC to use this
handshake hash.
This is a first step towards cleaning up the current handshake
buffer/digest code.
ok beck@ inoguchi@
-rw-r--r-- | lib/libssl/Makefile | 4 | ||||
-rw-r--r-- | lib/libssl/s3_lib.c | 7 | ||||
-rw-r--r-- | lib/libssl/ssl_ciph.c | 30 | ||||
-rw-r--r-- | lib/libssl/ssl_clnt.c | 5 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 26 | ||||
-rw-r--r-- | lib/libssl/ssl_srvr.c | 5 | ||||
-rw-r--r-- | lib/libssl/t1_enc.c | 60 | ||||
-rw-r--r-- | lib/libssl/t1_hash.c | 110 |
8 files changed, 193 insertions, 54 deletions
diff --git a/lib/libssl/Makefile b/lib/libssl/Makefile index 1fa49e86dff..b1e67ed9acf 100644 --- a/lib/libssl/Makefile +++ b/lib/libssl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.31 2017/01/26 09:16:01 jsing Exp $ +# $OpenBSD: Makefile,v 1.32 2017/03/05 14:39:53 jsing Exp $ .include <bsd.own.mk> .ifndef NOMAN @@ -25,7 +25,7 @@ SYMBOL_LIST= ${.CURDIR}/Symbols.list SRCS= \ ssl_srvr.c ssl_clnt.c s3_lib.c ssl_pkt.c ssl_both.c \ - t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ + t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_hash.c \ d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ d1_both.c d1_enc.c d1_srtp.c \ ssl_lib.c ssl_cert.c ssl_sess.c \ diff --git a/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c index 3f09834ab11..d6bf6a45746 100644 --- a/lib/libssl/s3_lib.c +++ b/lib/libssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.136 2017/03/04 16:32:00 jsing Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.137 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1839,8 +1839,12 @@ ssl3_free(SSL *s) free(S3I(s)->tmp.x25519); sk_X509_NAME_pop_free(S3I(s)->tmp.ca_names, X509_NAME_free); + BIO_free(S3I(s)->handshake_buffer); + tls1_free_digest_list(s); + tls1_handshake_hash_free(s); + free(S3I(s)->alpn_selected); explicit_bzero(S3I(s), sizeof(*S3I(s))); @@ -1881,6 +1885,7 @@ ssl3_clear(SSL *s) S3I(s)->handshake_buffer = NULL; tls1_free_digest_list(s); + tls1_handshake_hash_free(s); free(S3I(s)->alpn_selected); S3I(s)->alpn_selected = NULL; diff --git a/lib/libssl/ssl_ciph.c b/lib/libssl/ssl_ciph.c index 3e991fa5772..da48765aba2 100644 --- a/lib/libssl/ssl_ciph.c +++ b/lib/libssl/ssl_ciph.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_ciph.c,v 1.94 2017/02/21 15:28:27 jsing Exp $ */ +/* $OpenBSD: ssl_ciph.c,v 1.95 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -719,6 +719,34 @@ ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) return 1; } +int +ssl_get_handshake_evp_md(SSL *s, const EVP_MD **md) +{ + *md = NULL; + + switch (ssl_get_algorithm2(s) & SSL_HANDSHAKE_MAC_MASK) { + case SSL_HANDSHAKE_MAC_DEFAULT: + *md = EVP_md5_sha1(); + return 1; + case SSL_HANDSHAKE_MAC_GOST94: + *md = EVP_gostr341194(); + return 1; + case SSL_HANDSHAKE_MAC_SHA256: + *md = EVP_sha256(); + return 1; + case SSL_HANDSHAKE_MAC_SHA384: + *md = EVP_sha384(); + return 1; + case SSL_HANDSHAKE_MAC_STREEBOG256: + *md = EVP_streebog256(); + return 1; + default: + break; + } + + return 0; +} + #define ITEM_SEP(a) \ (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) diff --git a/lib/libssl/ssl_clnt.c b/lib/libssl/ssl_clnt.c index f46b66c3721..8dd30e87fba 100644 --- a/lib/libssl/ssl_clnt.c +++ b/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.9 2017/03/05 14:24:12 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.10 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -901,6 +901,9 @@ ssl3_get_server_hello(SSL *s) } S3I(s)->tmp.new_cipher = cipher; + if (!tls1_handshake_hash_init(s)) + goto err; + /* * Don't digest cached records if no sigalgs: we may need them for * client authentication. diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index deabb58894d..3f5d6fad202 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.176 2017/03/04 16:32:00 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.177 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -259,12 +259,13 @@ __BEGIN_HIDDEN_DECLS /* Bits for algorithm2 (handshake digests and other extra flags) */ -#define SSL_HANDSHAKE_MAC_MD5 0x10 -#define SSL_HANDSHAKE_MAC_SHA 0x20 -#define SSL_HANDSHAKE_MAC_GOST94 0x40 -#define SSL_HANDSHAKE_MAC_SHA256 0x80 -#define SSL_HANDSHAKE_MAC_SHA384 0x100 -#define SSL_HANDSHAKE_MAC_STREEBOG256 0x200 +#define SSL_HANDSHAKE_MAC_MASK 0xff0 +#define SSL_HANDSHAKE_MAC_MD5 0x010 +#define SSL_HANDSHAKE_MAC_SHA 0x020 +#define SSL_HANDSHAKE_MAC_GOST94 0x040 +#define SSL_HANDSHAKE_MAC_SHA256 0x080 +#define SSL_HANDSHAKE_MAC_SHA384 0x100 +#define SSL_HANDSHAKE_MAC_STREEBOG256 0x200 #define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) /* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX @@ -808,6 +809,10 @@ typedef struct ssl3_state_internal_st { * and freed and MD_CTX-es for all required digests are stored in * this array */ EVP_MD_CTX **handshake_dgst; + + /* Rolling hash of handshake messages. */ + EVP_MD_CTX *handshake_hash; + /* this is set whenerver we see a change_cipher_spec message * come in when we are not looking for one */ int change_cipher_spec; @@ -1099,6 +1104,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); int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead); int ssl_get_handshake_digest(int i, long *mask, const EVP_MD **md); +int ssl_get_handshake_evp_md(SSL *s, const EVP_MD **md); int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk); int ssl_undefined_function(SSL *s); @@ -1272,6 +1278,12 @@ int dtls1_enc(SSL *s, int snd); int ssl_init_wbio_buffer(SSL *s, int push); void ssl_free_wbio_buffer(SSL *s); +int tls1_handshake_hash_init(SSL *s); +int tls1_handshake_hash_update(SSL *s, const unsigned char *buf, size_t len); +int tls1_handshake_hash_value(SSL *s, const unsigned char *out, size_t len, + size_t *outlen); +void tls1_handshake_hash_free(SSL *s); + int tls1_init_finished_mac(SSL *s); int tls1_finish_mac(SSL *s, const unsigned char *buf, int len); void tls1_free_digest_list(SSL *s); diff --git a/lib/libssl/ssl_srvr.c b/lib/libssl/ssl_srvr.c index 09ea6571748..a48cf246da5 100644 --- a/lib/libssl/ssl_srvr.c +++ b/lib/libssl/ssl_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_srvr.c,v 1.9 2017/03/05 14:24:12 jsing Exp $ */ +/* $OpenBSD: ssl_srvr.c,v 1.10 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1045,6 +1045,9 @@ ssl3_get_client_hello(SSL *s) S3I(s)->tmp.new_cipher = s->session->cipher; } + if (!tls1_handshake_hash_init(s)) + goto err; + alg_k = S3I(s)->tmp.new_cipher->algorithm_mkey; if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) || !(s->verify_mode & SSL_VERIFY_PEER)) { diff --git a/lib/libssl/t1_enc.c b/lib/libssl/t1_enc.c index 85d28298bfc..62578beeea3 100644 --- a/lib/libssl/t1_enc.c +++ b/lib/libssl/t1_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_enc.c,v 1.96 2017/02/07 02:08:38 beck Exp $ */ +/* $OpenBSD: t1_enc.c,v 1.97 2017/03/05 14:39:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -135,6 +135,7 @@ * OTHERWISE. */ +#include <limits.h> #include <stdio.h> #include "ssl_locl.h" @@ -193,6 +194,12 @@ tls1_finish_mac(SSL *s, const unsigned char *buf, int len) { int i; + if (len < 0) + return 0; + + if (!tls1_handshake_hash_update(s, buf, len)) + return 0; + if (S3I(s)->handshake_buffer && !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { BIO_write(S3I(s)->handshake_buffer, (void *)buf, len); @@ -1121,52 +1128,23 @@ tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *out) { - unsigned int i; - EVP_MD_CTX ctx; - unsigned char buf[2*EVP_MAX_MD_SIZE]; - unsigned char *q, buf2[12]; - int idx; - long mask; - int err = 0; - const EVP_MD *md; - - q = buf; + unsigned char buf1[EVP_MAX_MD_SIZE]; + unsigned char buf2[12]; + size_t hlen; - if (S3I(s)->handshake_buffer) - if (!tls1_digest_cached_records(s)) - return 0; - - EVP_MD_CTX_init(&ctx); + if (!tls1_handshake_hash_value(s, buf1, sizeof(buf1), &hlen)) + return 0; - for (idx = 0; ssl_get_handshake_digest(idx, &mask, &md); idx++) { - if (ssl_get_algorithm2(s) & mask) { - int hashsize = EVP_MD_size(md); - EVP_MD_CTX *hdgst = S3I(s)->handshake_dgst[idx]; - if (!hdgst || hashsize < 0 || - hashsize > (int)(sizeof buf - (size_t)(q - buf))) { - /* internal error: 'buf' is too small for this cipersuite! */ - err = 1; - } else { - if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) || - !EVP_DigestFinal_ex(&ctx, q, &i) || - (i != (unsigned int)hashsize)) - err = 1; - q += hashsize; - } - } - } + if (hlen > INT_MAX) + return 0; - if (!tls1_PRF(ssl_get_algorithm2(s), str, slen, buf, (int)(q - buf), + if (!tls1_PRF(ssl_get_algorithm2(s), str, slen, buf1, hlen, NULL, 0, NULL, 0, NULL, 0, s->session->master_key, s->session->master_key_length, - out, buf2, sizeof buf2)) - err = 1; - EVP_MD_CTX_cleanup(&ctx); - - if (err) + out, buf2, sizeof(buf2))) return 0; - else - return sizeof buf2; + + return sizeof(buf2); } int diff --git a/lib/libssl/t1_hash.c b/lib/libssl/t1_hash.c new file mode 100644 index 00000000000..94410e4127b --- /dev/null +++ b/lib/libssl/t1_hash.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ssl_locl.h" + +#include <openssl/ssl.h> + +int +tls1_handshake_hash_init(SSL *s) +{ + const EVP_MD *md; + long dlen; + void *data; + + tls1_handshake_hash_free(s); + + if (!ssl_get_handshake_evp_md(s, &md)) { + SSLerrorx(ERR_R_INTERNAL_ERROR); + goto err; + } + + if ((S3I(s)->handshake_hash = EVP_MD_CTX_create()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestInit_ex(S3I(s)->handshake_hash, md, NULL)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + dlen = BIO_get_mem_data(S3I(s)->handshake_buffer, &data); + if (dlen <= 0) { + SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH); + goto err; + } + if (!tls1_handshake_hash_update(s, data, dlen)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + return 1; + + err: + tls1_handshake_hash_free(s); + + return 0; +} + +int +tls1_handshake_hash_update(SSL *s, const unsigned char *buf, size_t len) +{ + if (S3I(s)->handshake_hash == NULL) + return 1; + + return EVP_DigestUpdate(S3I(s)->handshake_hash, buf, len); +} + +int +tls1_handshake_hash_value(SSL *s, const unsigned char *out, size_t len, + size_t *outlen) +{ + EVP_MD_CTX *mdctx = NULL; + unsigned int mdlen; + int ret = 0; + + if (EVP_MD_CTX_size(S3I(s)->handshake_hash) > len) + goto err; + + if ((mdctx = EVP_MD_CTX_create()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_MD_CTX_copy_ex(mdctx, S3I(s)->handshake_hash)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (!EVP_DigestFinal_ex(mdctx, (unsigned char *)out, &mdlen)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (outlen != NULL) + *outlen = mdlen; + + ret = 1; + + err: + EVP_MD_CTX_destroy(mdctx); + + return (ret); +} + +void +tls1_handshake_hash_free(SSL *s) +{ + EVP_MD_CTX_destroy(S3I(s)->handshake_hash); + S3I(s)->handshake_hash = NULL; +} |