diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2014-10-03 13:58:19 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2014-10-03 13:58:19 +0000 |
commit | b9a87bb6890852e78fbfda2d3561b11194e0db8e (patch) | |
tree | ac83e1a191a91403af20b5a78ad6e443d6b730d4 | |
parent | 64ec975e1e324d7dcbf99caef225607f20a95702 (diff) |
Add support for automatic ephemeral EC keys.
This allows an SSL server to enable ECDHE ciphers with a single setting,
which results in an EC key being generated using the first preference
shared curve.
Based on OpenSSL with inspiration from boringssl.
ok miod@
-rw-r--r-- | lib/libssl/src/ssl/s3_lib.c | 10 | ||||
-rw-r--r-- | lib/libssl/src/ssl/s3_srvr.c | 14 | ||||
-rw-r--r-- | lib/libssl/src/ssl/ssl.h | 8 | ||||
-rw-r--r-- | lib/libssl/src/ssl/ssl_cert.c | 3 | ||||
-rw-r--r-- | lib/libssl/src/ssl/ssl_lib.c | 5 | ||||
-rw-r--r-- | lib/libssl/src/ssl/ssl_locl.h | 8 | ||||
-rw-r--r-- | lib/libssl/src/ssl/t1_lib.c | 41 |
7 files changed, 76 insertions, 13 deletions
diff --git a/lib/libssl/src/ssl/s3_lib.c b/lib/libssl/src/ssl/s3_lib.c index 246aa6f23df..42f8074f8c3 100644 --- a/lib/libssl/src/ssl/s3_lib.c +++ b/lib/libssl/src/ssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.81 2014/09/30 15:40:09 jsing Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.82 2014/10/03 13:58:17 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -2128,6 +2128,11 @@ ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) ret = 1; break; + case SSL_CTRL_SET_ECDH_AUTO: + s->cert->ecdh_tmp_auto = larg; + ret = 1; + break; + default: break; } @@ -2322,6 +2327,9 @@ ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) return 1; break; + case SSL_CTRL_SET_ECDH_AUTO: + ctx->cert->ecdh_tmp_auto = larg; + return 1; /* A Thawte special :-) */ case SSL_CTRL_EXTRA_CHAIN_CERT: diff --git a/lib/libssl/src/ssl/s3_srvr.c b/lib/libssl/src/ssl/s3_srvr.c index cba875a3e69..c4a8442a3e0 100644 --- a/lib/libssl/src/ssl/s3_srvr.c +++ b/lib/libssl/src/ssl/s3_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_srvr.c,v 1.85 2014/09/27 11:03:43 jsing Exp $ */ +/* $OpenBSD: s3_srvr.c,v 1.86 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1465,9 +1465,15 @@ ssl3_send_server_key_exchange(SSL *s) const EC_GROUP *group; ecdhp = cert->ecdh_tmp; - if (ecdhp == NULL && s->cert->ecdh_tmp_cb != NULL) + 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) { ecdhp = s->cert->ecdh_tmp_cb(s, 0, SSL_C_PKEYLENGTH(s->s3->tmp.new_cipher)); + } if (ecdhp == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, @@ -1482,7 +1488,9 @@ ssl3_send_server_key_exchange(SSL *s) } /* Duplicate the ECDH structure. */ - if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { + if (s->cert->ecdh_tmp_auto != 0) { + ecdh = ecdhp; + } else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; diff --git a/lib/libssl/src/ssl/ssl.h b/lib/libssl/src/ssl/ssl.h index c7dd4259ccb..1e9e8461955 100644 --- a/lib/libssl/src/ssl/ssl.h +++ b/lib/libssl/src/ssl/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.66 2014/09/28 14:45:48 reyk Exp $ */ +/* $OpenBSD: ssl.h,v 1.67 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1425,6 +1425,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) #define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 +#define SSL_CTRL_SET_ECDH_AUTO 94 + #define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) #define DTLSv1_handle_timeout(ssl) \ @@ -1449,6 +1451,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) #define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) #define SSL_need_tmp_RSA(ssl) \ SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) @@ -1458,6 +1462,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) #define SSL_set_tmp_ecdh(ssl,ecdh) \ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +#define SSL_set_ecdh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) #define SSL_CTX_add_extra_chain_cert(ctx,x509) \ SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) diff --git a/lib/libssl/src/ssl/ssl_cert.c b/lib/libssl/src/ssl/ssl_cert.c index 6aae59e3106..6f1815067b9 100644 --- a/lib/libssl/src/ssl/ssl_cert.c +++ b/lib/libssl/src/ssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_cert.c,v 1.41 2014/07/10 08:25:00 guenther Exp $ */ +/* $OpenBSD: ssl_cert.c,v 1.42 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -244,6 +244,7 @@ ssl_cert_dup(CERT *cert) } } ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; + ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; for (i = 0; i < SSL_PKEY_NUM; i++) { if (cert->pkeys[i].x509 != NULL) { diff --git a/lib/libssl/src/ssl/ssl_lib.c b/lib/libssl/src/ssl/ssl_lib.c index bd5f9f6da14..f6a21d43514 100644 --- a/lib/libssl/src/ssl/ssl_lib.c +++ b/lib/libssl/src/ssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.84 2014/09/07 12:16:23 jsing Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.85 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1943,7 +1943,8 @@ ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) rsa_tmp = (c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL); dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL); - have_ecdh_tmp = (c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL); + have_ecdh_tmp = (c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL || + c->ecdh_tmp_auto != 0); cpk = &(c->pkeys[SSL_PKEY_RSA_ENC]); rsa_enc = (cpk->x509 != NULL && cpk->privatekey != NULL); cpk = &(c->pkeys[SSL_PKEY_RSA_SIGN]); diff --git a/lib/libssl/src/ssl/ssl_locl.h b/lib/libssl/src/ssl/ssl_locl.h index 8ec4c69d5be..976f835c923 100644 --- a/lib/libssl/src/ssl/ssl_locl.h +++ b/lib/libssl/src/ssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.70 2014/09/30 15:40:09 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.71 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -439,13 +439,16 @@ typedef struct cert_st { int valid; unsigned long mask_k; unsigned long mask_a; + RSA *rsa_tmp; RSA *(*rsa_tmp_cb)(SSL *ssl, int is_export, int keysize); + DH *dh_tmp; DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize); + EC_KEY *ecdh_tmp; - /* Callback for generating ephemeral ECDH keys */ EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize); + int ecdh_tmp_auto; CERT_PKEY pkeys[SSL_PKEY_NUM]; @@ -799,6 +802,7 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); int tls1_ec_curve_id2nid(int curve_id); int tls1_ec_nid2curve_id(int nid); int tls1_check_curve(SSL *s, const unsigned char *p, size_t len); +int tls1_get_shared_curve(SSL *s); unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); diff --git a/lib/libssl/src/ssl/t1_lib.c b/lib/libssl/src/ssl/t1_lib.c index d40768560cb..678818d51b2 100644 --- a/lib/libssl/src/ssl/t1_lib.c +++ b/lib/libssl/src/ssl/t1_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_lib.c,v 1.59 2014/09/30 15:40:09 jsing Exp $ */ +/* $OpenBSD: t1_lib.c,v 1.60 2014/10/03 13:58:18 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -408,6 +408,35 @@ tls1_check_curve(SSL *s, const unsigned char *p, size_t len) return (0); } +int +tls1_get_shared_curve(SSL *s) +{ + const unsigned char *pref, *supp, *tsupp; + size_t preflen, supplen, i, j; + unsigned long server_pref; + int id; + + /* Cannot do anything on the client side. */ + if (s->server == 0) + return (NID_undef); + + /* Return first preference shared curve. */ + server_pref = (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE); + tls1_get_curvelist(s, (server_pref == 0), &pref, &preflen); + tls1_get_curvelist(s, (server_pref != 0), &supp, &supplen); + + for (i = 0; i < preflen; i += 2, pref += 2) { + tsupp = supp; + for (j = 0; j < supplen; j += 2, tsupp += 2) { + if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) { + id = (pref[0] << 8) | pref[1]; + return (tls1_ec_curve_id2nid(id)); + } + } + } + return (NID_undef); +} + /* For an EC key set TLS ID and required compression based on parameters. */ static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, EC_KEY *ec) @@ -524,11 +553,17 @@ tls1_check_ec_tmp_key(SSL *s) EC_KEY *ec = s->cert->ecdh_tmp; unsigned char curve_id[2]; + if (s->cert->ecdh_tmp_auto != 0) { + /* Need a shared curve. */ + if (tls1_get_shared_curve(s) != NID_undef) + return (1); + return (0); + } + if (ec == NULL) { if (s->cert->ecdh_tmp_cb != NULL) return (1); - else - return (0); + return (0); } if (tls1_set_ec_id(curve_id, NULL, ec) != 1) return (0); |