summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2017-03-05 14:39:53 +0000
committerjsing <jsing@openbsd.org>2017-03-05 14:39:53 +0000
commit366dc2a2e9ef223ce3418b3d76bba648547d45ef (patch)
treed9fd995f7169f30e2e7cdc7ee6ee0edc127c064f /lib
parentConvert various handshake message generation functions to CBB. (diff)
downloadwireguard-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@
Diffstat (limited to 'lib')
-rw-r--r--lib/libssl/Makefile4
-rw-r--r--lib/libssl/s3_lib.c7
-rw-r--r--lib/libssl/ssl_ciph.c30
-rw-r--r--lib/libssl/ssl_clnt.c5
-rw-r--r--lib/libssl/ssl_locl.h26
-rw-r--r--lib/libssl/ssl_srvr.c5
-rw-r--r--lib/libssl/t1_enc.c60
-rw-r--r--lib/libssl/t1_hash.c110
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;
+}