diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2016-12-21 16:44:32 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2016-12-21 16:44:32 +0000 |
commit | eddce5bd7db41e4fad671b4dafb7ea75781328b1 (patch) | |
tree | 0802607a4bcee6e1b81ceb80bad82e9d74e626a7 /lib | |
parent | 2ea2fedf3e342d5bb7236940e1b8267a12dca9f3 (diff) |
Add support for ECDHE with X25519.
Testing of an earlier revision by naddy@.
ok beck@
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libssl/s3_clnt.c | 260 | ||||
-rw-r--r-- | lib/libssl/s3_lib.c | 12 | ||||
-rw-r--r-- | lib/libssl/s3_srvr.c | 117 | ||||
-rw-r--r-- | lib/libssl/ssl3.h | 4 | ||||
-rw-r--r-- | lib/libssl/ssl_cert.c | 3 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 3 | ||||
-rw-r--r-- | lib/libssl/t1_lib.c | 8 |
7 files changed, 316 insertions, 91 deletions
diff --git a/lib/libssl/s3_clnt.c b/lib/libssl/s3_clnt.c index be6e461a1e0..07457e95a7a 100644 --- a/lib/libssl/s3_clnt.c +++ b/lib/libssl/s3_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_clnt.c,v 1.156 2016/12/18 13:52:53 jsing Exp $ */ +/* $OpenBSD: s3_clnt.c,v 1.157 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -156,6 +156,7 @@ #include <openssl/bn.h> #include <openssl/buffer.h> +#include <openssl/curve25519.h> #include <openssl/dh.h> #include <openssl/evp.h> #include <openssl/md5.h> @@ -1184,19 +1185,99 @@ ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) } static int +ssl3_get_server_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, int nid, CBS *public) +{ + const EC_GROUP *group; + EC_GROUP *ngroup = NULL; + EC_POINT *point = NULL; + BN_CTX *bn_ctx = NULL; + EC_KEY *ecdh = NULL; + int ret = -1; + + /* + * Extract the server's ephemeral ECDH public key. + */ + + if ((ecdh = EC_KEY_new()) == NULL) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((ngroup = EC_GROUP_new_by_curve_name(nid)) == NULL) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); + goto err; + } + if (EC_KEY_set_group(ecdh, ngroup) == 0) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); + goto err; + } + + group = EC_KEY_get0_group(ecdh); + + if ((point = EC_POINT_new(group)) == NULL || + (bn_ctx = BN_CTX_new()) == NULL) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EC_POINT_oct2point(group, point, CBS_data(public), + CBS_len(public), bn_ctx) == 0) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + goto err; + } + + EC_KEY_set_public_key(ecdh, point); + sc->peer_ecdh_tmp = ecdh; + ecdh = NULL; + + ret = 1; + + err: + BN_CTX_free(bn_ctx); + EC_GROUP_free(ngroup); + EC_POINT_free(point); + EC_KEY_free(ecdh); + + return (ret); +} + +static int +ssl3_get_server_kex_ecdhe_ecx(SSL *s, SESS_CERT *sc, int nid, CBS *public) +{ + size_t outlen; + + if (nid != NID_X25519) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (CBS_len(public) != X25519_KEY_LENGTH) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + goto err; + } + + if (!CBS_stow(public, &sc->peer_x25519_tmp, &outlen)) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + + return (1); + + err: + return (-1); +} + +static int ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) { - CBS cbs, ecpoint; + CBS cbs, public; uint8_t curve_type; uint16_t curve_id; - EC_POINT *srvr_ecpoint = NULL; - EC_KEY *ecdh = NULL; - BN_CTX *bn_ctx = NULL; - const EC_GROUP *group; - EC_GROUP *ngroup = NULL; SESS_CERT *sc; - int curve_nid; long alg_a; + int nid; int al; alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -1207,15 +1288,6 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) CBS_init(&cbs, *pp, *nn); - /* - * Extract EC parameters and the server's ephemeral ECDH public key. - */ - - if ((ecdh = EC_KEY_new()) == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto err; - } - /* Only named curves are supported. */ if (!CBS_get_u8(&cbs, &curve_type) || curve_type != NAMED_CURVE_TYPE || @@ -1235,39 +1307,22 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) goto f_err; } - if ((curve_nid = tls1_ec_curve_id2nid(curve_id)) == 0) { + if ((nid = tls1_ec_curve_id2nid(curve_id)) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); goto f_err; } - if ((ngroup = EC_GROUP_new_by_curve_name(curve_nid)) == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); - goto err; - } - if (EC_KEY_set_group(ecdh, ngroup) == 0) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); - goto err; - } - - group = EC_KEY_get0_group(ecdh); - - /* Next, get the encoded ECPoint */ - if ((srvr_ecpoint = EC_POINT_new(group)) == NULL || - (bn_ctx = BN_CTX_new()) == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!CBS_get_u8_length_prefixed(&cbs, &ecpoint)) + if (!CBS_get_u8_length_prefixed(&cbs, &public)) goto truncated; - if (EC_POINT_oct2point(group, srvr_ecpoint, CBS_data(&ecpoint), - CBS_len(&ecpoint), bn_ctx) == 0) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT); - goto f_err; + if (nid == NID_X25519) { + if (ssl3_get_server_kex_ecdhe_ecx(s, sc, nid, &public) != 1) + goto err; + } else { + if (ssl3_get_server_kex_ecdhe_ecp(s, sc, nid, &public) != 1) + goto err; } /* @@ -1283,13 +1338,6 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) /* XXX - Anonymous ECDH, so no certificate or pkey. */ *pkey = NULL; - EC_KEY_set_public_key(ecdh, srvr_ecpoint); - sc->peer_ecdh_tmp = ecdh; - - BN_CTX_free(bn_ctx); - EC_GROUP_free(ngroup); - EC_POINT_free(srvr_ecpoint); - *nn = CBS_len(&cbs); *pp = (unsigned char *)CBS_data(&cbs); @@ -1303,11 +1351,6 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - BN_CTX_free(bn_ctx); - EC_GROUP_free(ngroup); - EC_POINT_free(srvr_ecpoint); - EC_KEY_free(ecdh); - return (-1); } @@ -1360,6 +1403,9 @@ ssl3_get_server_key_exchange(SSL *s) EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); s->session->sess_cert->peer_ecdh_tmp = NULL; + + free(s->session->sess_cert->peer_x25519_tmp); + s->session->sess_cert->peer_x25519_tmp = NULL; } else { s->session->sess_cert = ssl_sess_cert_new(); if (s->session->sess_cert == NULL) @@ -2010,11 +2056,11 @@ err: } static int -ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) +ssl3_send_client_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, CBB *cbb) { - EC_KEY *clnt_ecdh = NULL; - const EC_GROUP *srvr_group = NULL; - const EC_POINT *srvr_ecpoint = NULL; + const EC_GROUP *group = NULL; + const EC_POINT *point = NULL; + EC_KEY *ecdh = NULL; BN_CTX *bn_ctx = NULL; unsigned char *key = NULL; unsigned char *data; @@ -2023,40 +2069,30 @@ ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) int ret = -1; CBB ecpoint; - if (sess_cert->peer_ecdh_tmp == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + if ((group = EC_KEY_get0_group(sc->peer_ecdh_tmp)) == NULL || + (point = EC_KEY_get0_public_key(sc->peer_ecdh_tmp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - srvr_group = EC_KEY_get0_group(sess_cert->peer_ecdh_tmp); - srvr_ecpoint = EC_KEY_get0_public_key(sess_cert->peer_ecdh_tmp); - - if (srvr_group == NULL || srvr_ecpoint == NULL) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((clnt_ecdh = EC_KEY_new()) == NULL) { + if ((ecdh = EC_KEY_new()) == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto err; } - if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { + if (!EC_KEY_set_group(ecdh, group)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } /* Generate a new ECDH key pair. */ - if (!(EC_KEY_generate_key(clnt_ecdh))) { + if (!(EC_KEY_generate_key(ecdh))) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - key_size = ECDH_size(clnt_ecdh); - if (key_size <= 0) { + if ((key_size = ECDH_size(ecdh)) <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } @@ -2064,7 +2100,7 @@ ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); } - key_len = ECDH_compute_key(key, key_size, srvr_ecpoint, clnt_ecdh, NULL); + key_len = ECDH_compute_key(key, key_size, point, ecdh, NULL); if (key_len <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; @@ -2075,8 +2111,7 @@ ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, key, key_len); - encoded_len = EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), + encoded_len = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); if (encoded_len == 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); @@ -2094,7 +2129,7 @@ ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) goto err; if (!CBB_add_space(&ecpoint, &data, encoded_len)) goto err; - if (EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh), + if (EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, data, encoded_len, bn_ctx) == 0) goto err; @@ -2108,13 +2143,78 @@ ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) explicit_bzero(key, key_size); free(key); - BN_CTX_free(bn_ctx); - EC_KEY_free(clnt_ecdh); + return (ret); +} + +static int +ssl3_send_client_kex_ecdhe_ecx(SSL *s, SESS_CERT *sc, CBB *cbb) +{ + uint8_t *public_key = NULL, *private_key = NULL, *shared_key = NULL; + int ret = -1; + CBB ecpoint; + + /* Generate X25519 key pair and derive shared key. */ + if ((public_key = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + if ((private_key = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + if ((shared_key = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + X25519_keypair(public_key, private_key); + if (!X25519(shared_key, private_key, sc->peer_x25519_tmp)) + goto err; + + /* Serialize the public key. */ + if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) + goto err; + if (!CBB_add_bytes(&ecpoint, public_key, X25519_KEY_LENGTH)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + /* Generate master key from the result. */ + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, shared_key, X25519_KEY_LENGTH); + + ret = 1; + + err: + if (private_key != NULL) + explicit_bzero(private_key, X25519_KEY_LENGTH); + if (shared_key != NULL) + explicit_bzero(shared_key, X25519_KEY_LENGTH); + + free(public_key); + free(private_key); + free(shared_key); return (ret); } static int +ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sc, CBB *cbb) +{ + if (sc->peer_x25519_tmp != NULL) { + if (ssl3_send_client_kex_ecdhe_ecx(s, sc, cbb) != 1) + goto err; + } else if (sc->peer_ecdh_tmp != NULL) { + if (ssl3_send_client_kex_ecdhe_ecp(s, sc, cbb) != 1) + goto err; + } else { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + return (1); + + err: + return (-1); +} + +static int ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) { unsigned char premaster_secret[32], shared_ukm[32], tmp[256]; diff --git a/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c index db9292172d9..212de5f7a44 100644 --- a/lib/libssl/s3_lib.c +++ b/lib/libssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.113 2016/12/06 13:17:52 jsing Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.114 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -151,6 +151,7 @@ #include <limits.h> #include <stdio.h> +#include <openssl/curve25519.h> #include <openssl/dh.h> #include <openssl/md5.h> #include <openssl/objects.h> @@ -1835,6 +1836,10 @@ ssl3_free(SSL *s) DH_free(s->s3->tmp.dh); EC_KEY_free(s->s3->tmp.ecdh); + if (s->s3->tmp.x25519 != NULL) + explicit_bzero(s->s3->tmp.x25519, X25519_KEY_LENGTH); + free(s->s3->tmp.x25519); + if (s->s3->tmp.ca_names != NULL) sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); BIO_free(s->s3->handshake_buffer); @@ -1861,6 +1866,11 @@ ssl3_clear(SSL *s) EC_KEY_free(s->s3->tmp.ecdh); s->s3->tmp.ecdh = NULL; + if (s->s3->tmp.x25519 != NULL) + explicit_bzero(s->s3->tmp.x25519, X25519_KEY_LENGTH); + free(s->s3->tmp.x25519); + s->s3->tmp.x25519 = NULL; + rp = s->s3->rbuf.buf; wp = s->s3->wbuf.buf; rlen = s->s3->rbuf.len; diff --git a/lib/libssl/s3_srvr.c b/lib/libssl/s3_srvr.c index 3dd085115da..8e3dc11fc1d 100644 --- a/lib/libssl/s3_srvr.c +++ b/lib/libssl/s3_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_srvr.c,v 1.137 2016/12/07 13:18:38 jsing Exp $ */ +/* $OpenBSD: s3_srvr.c,v 1.138 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -154,6 +154,7 @@ #include <openssl/bn.h> #include <openssl/buffer.h> +#include <openssl/curve25519.h> #include <openssl/evp.h> #include <openssl/dh.h> #ifndef OPENSSL_NO_GOST @@ -1268,8 +1269,8 @@ ssl3_send_server_kex_dhe(SSL *s, CBB *cbb) return (-1); } -int -ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) +static int +ssl3_send_server_kex_ecdhe_ecp(SSL *s, int nid, CBB *cbb) { CBB ecpoint; unsigned char *data; @@ -1283,7 +1284,6 @@ ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) ecdhp = s->cert->ecdh_tmp; if (s->cert->ecdh_tmp_auto != 0) { - int nid = tls1_get_shared_curve(s); if (nid != NID_undef) ecdhp = EC_KEY_new_by_curve_name(nid); } else if (ecdhp == NULL && s->cert->ecdh_tmp_cb != NULL) { @@ -1404,6 +1404,65 @@ ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) return (-1); } +static int +ssl3_send_server_kex_ecdhe_ecx(SSL *s, int nid, CBB *cbb) +{ + uint8_t *public_key = NULL; + int curve_id; + CBB ecpoint; + int ret = -1; + + /* Generate an X25519 key pair. */ + if (s->s3->tmp.x25519 != NULL) { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + if ((s->s3->tmp.x25519 = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + if ((public_key = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + X25519_keypair(public_key, s->s3->tmp.x25519); + + /* Serialize public key. */ + if ((curve_id = tls1_ec_nid2curve_id(nid)) == 0) { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, + SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + goto err; + } + + if (!CBB_add_u8(cbb, NAMED_CURVE_TYPE)) + goto err; + if (!CBB_add_u16(cbb, curve_id)) + goto err; + if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) + goto err; + if (!CBB_add_bytes(&ecpoint, public_key, X25519_KEY_LENGTH)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + free(public_key); + + return (ret); +} + +static int +ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) +{ + int nid; + + nid = tls1_get_shared_curve(s); + + if (s->cert->ecdh_tmp_auto != 0 && nid == NID_X25519) + return ssl3_send_server_kex_ecdhe_ecx(s, nid, cbb); + + return ssl3_send_server_kex_ecdhe_ecp(s, nid, cbb); +} + int ssl3_send_server_key_exchange(SSL *s) { @@ -1822,7 +1881,7 @@ ssl3_get_client_kex_dhe(SSL *s, unsigned char *p, long n) } static int -ssl3_get_client_kex_ecdhe(SSL *s, unsigned char *p, long n) +ssl3_get_client_kex_ecdhe_ecp(SSL *s, unsigned char *p, long n) { EC_KEY *srvr_ecdh = NULL; EVP_PKEY *clnt_pub_pkey = NULL; @@ -1971,6 +2030,54 @@ ssl3_get_client_kex_ecdhe(SSL *s, unsigned char *p, long n) } static int +ssl3_get_client_kex_ecdhe_ecx(SSL *s, unsigned char *p, long n) +{ + uint8_t *shared_key = NULL; + CBS cbs, ecpoint; + int ret = -1; + + if (n < 0) + goto err; + + CBS_init(&cbs, p, n); + if (!CBS_get_u8_length_prefixed(&cbs, &ecpoint)) + goto err; + if (CBS_len(&ecpoint) != X25519_KEY_LENGTH) + goto err; + + if ((shared_key = malloc(X25519_KEY_LENGTH)) == NULL) + goto err; + if (!X25519(shared_key, s->s3->tmp.x25519, CBS_data(&ecpoint))) + goto err; + + explicit_bzero(s->s3->tmp.x25519, X25519_KEY_LENGTH); + free(s->s3->tmp.x25519); + s->s3->tmp.x25519 = NULL; + + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret( + s, s->session->master_key, shared_key, X25519_KEY_LENGTH); + + ret = 1; + + err: + if (shared_key != NULL) + explicit_bzero(shared_key, X25519_KEY_LENGTH); + free(shared_key); + + return (ret); +} + +static int +ssl3_get_client_kex_ecdhe(SSL *s, unsigned char *p, long n) +{ + if (s->s3->tmp.x25519 != NULL) + return ssl3_get_client_kex_ecdhe_ecx(s, p, n); + + return ssl3_get_client_kex_ecdhe_ecp(s, p, n); +} + +static int ssl3_get_client_kex_gost(SSL *s, unsigned char *p, long n) { diff --git a/lib/libssl/ssl3.h b/lib/libssl/ssl3.h index 5ec2fe6f884..90fcae7914e 100644 --- a/lib/libssl/ssl3.h +++ b/lib/libssl/ssl3.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl3.h,v 1.41 2015/07/19 06:23:51 doug Exp $ */ +/* $OpenBSD: ssl3.h,v 1.42 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -440,6 +440,8 @@ typedef struct ssl3_state_st { EC_KEY *ecdh; /* holds short lived ECDH key */ + uint8_t *x25519; + /* used when SSL_ST_FLUSH_DATA is entered */ int next_state; diff --git a/lib/libssl/ssl_cert.c b/lib/libssl/ssl_cert.c index 7e92812e56a..294745c9f93 100644 --- a/lib/libssl/ssl_cert.c +++ b/lib/libssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_cert.c,v 1.52 2016/03/11 07:08:45 mmcc Exp $ */ +/* $OpenBSD: ssl_cert.c,v 1.53 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -403,6 +403,7 @@ ssl_sess_cert_free(SESS_CERT *sc) DH_free(sc->peer_dh_tmp); EC_KEY_free(sc->peer_ecdh_tmp); + free(sc->peer_x25519_tmp); free(sc); } diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index d7484dd7a0c..858be716272 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.140 2016/12/18 13:52:53 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.141 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -468,6 +468,7 @@ typedef struct sess_cert_st { DH *peer_dh_tmp; EC_KEY *peer_ecdh_tmp; + uint8_t *peer_x25519_tmp; int references; /* actually always 1 at the moment */ } SESS_CERT; diff --git a/lib/libssl/t1_lib.c b/lib/libssl/t1_lib.c index 0a5958341b7..4e4fa216875 100644 --- a/lib/libssl/t1_lib.c +++ b/lib/libssl/t1_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_lib.c,v 1.95 2016/12/18 13:52:53 jsing Exp $ */ +/* $OpenBSD: t1_lib.c,v 1.96 2016/12/21 16:44:31 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -241,7 +241,8 @@ static int nid_list[] = { NID_secp521r1, /* secp521r1 (25) */ NID_brainpoolP256r1, /* brainpoolP256r1 (26) */ NID_brainpoolP384r1, /* brainpoolP384r1 (27) */ - NID_brainpoolP512r1 /* brainpoolP512r1 (28) */ + NID_brainpoolP512r1, /* brainpoolP512r1 (28) */ + NID_X25519, /* X25519 (29) */ }; static const uint8_t ecformats_default[] = { @@ -251,6 +252,7 @@ static const uint8_t ecformats_default[] = { }; static const uint16_t eccurves_default[] = { + 29, /* X25519 (29) */ 14, /* sect571r1 (14) */ 13, /* sect571k1 (13) */ 25, /* secp521r1 (25) */ @@ -352,6 +354,8 @@ tls1_ec_nid2curve_id(int nid) return 27; case NID_brainpoolP512r1: /* brainpoolP512r1 (28) */ return 28; + case NID_X25519: /* X25519 (29) */ + return 29; default: return 0; } |