diff options
author | jsing <> | 2021-11-29 16:00:32 +0000 |
---|---|---|
committer | jsing <> | 2021-11-29 16:00:32 +0000 |
commit | a0d7805041037ed2978f81fb42281572ecf06ba5 (patch) | |
tree | a67c634e81e938a386fd858c39b174adb55c4703 | |
parent | fa78f5478a96728245b0da9e87927ad51540d124 (diff) | |
download | openbsd-a0d7805041037ed2978f81fb42281572ecf06ba5.tar.gz openbsd-a0d7805041037ed2978f81fb42281572ecf06ba5.tar.bz2 openbsd-a0d7805041037ed2978f81fb42281572ecf06ba5.zip |
Factor out/rewrite DHE key exchange.
This follows what was done previously for ECDHE EC point key exchange and
will allow for deduplication and further code improvement.
Convert the TLSv1.2 client to use the new DHE key exchange functions.
ok inoguchi@ tb@
-rw-r--r-- | src/lib/libssl/ssl_clnt.c | 84 | ||||
-rw-r--r-- | src/lib/libssl/ssl_kex.c | 145 | ||||
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 10 |
3 files changed, 173 insertions, 66 deletions
diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c index 6fe15dcf1d..b349f24cb0 100644 --- a/src/lib/libssl/ssl_clnt.c +++ b/src/lib/libssl/ssl_clnt.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_clnt.c,v 1.119 2021/11/26 16:41:42 tb Exp $ */ | 1 | /* $OpenBSD: ssl_clnt.c,v 1.120 2021/11/29 16:00:32 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1223,46 +1223,24 @@ ssl3_get_server_certificate(SSL *s) | |||
1223 | static int | 1223 | static int |
1224 | ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, CBS *cbs) | 1224 | ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, CBS *cbs) |
1225 | { | 1225 | { |
1226 | CBS dhp, dhg, dhpk; | ||
1227 | BN_CTX *bn_ctx = NULL; | ||
1228 | SESS_CERT *sc = NULL; | 1226 | SESS_CERT *sc = NULL; |
1229 | DH *dh = NULL; | 1227 | DH *dh = NULL; |
1230 | long alg_a; | 1228 | long alg_a; |
1231 | int al; | ||
1232 | 1229 | ||
1233 | alg_a = S3I(s)->hs.cipher->algorithm_auth; | 1230 | alg_a = S3I(s)->hs.cipher->algorithm_auth; |
1234 | sc = s->session->sess_cert; | 1231 | sc = s->session->sess_cert; |
1235 | 1232 | ||
1236 | if ((dh = DH_new()) == NULL) { | 1233 | if ((dh = DH_new()) == NULL) |
1237 | SSLerror(s, ERR_R_DH_LIB); | ||
1238 | goto err; | ||
1239 | } | ||
1240 | |||
1241 | if (!CBS_get_u16_length_prefixed(cbs, &dhp)) | ||
1242 | goto decode_err; | ||
1243 | if ((dh->p = BN_bin2bn(CBS_data(&dhp), CBS_len(&dhp), NULL)) == NULL) { | ||
1244 | SSLerror(s, ERR_R_BN_LIB); | ||
1245 | goto err; | 1234 | goto err; |
1246 | } | ||
1247 | 1235 | ||
1248 | if (!CBS_get_u16_length_prefixed(cbs, &dhg)) | 1236 | if (!ssl_kex_peer_params_dhe(dh, cbs)) |
1249 | goto decode_err; | 1237 | goto decode_err; |
1250 | if ((dh->g = BN_bin2bn(CBS_data(&dhg), CBS_len(&dhg), NULL)) == NULL) { | 1238 | if (!ssl_kex_peer_public_dhe(dh, cbs)) |
1251 | SSLerror(s, ERR_R_BN_LIB); | ||
1252 | goto err; | ||
1253 | } | ||
1254 | |||
1255 | if (!CBS_get_u16_length_prefixed(cbs, &dhpk)) | ||
1256 | goto decode_err; | 1239 | goto decode_err; |
1257 | if ((dh->pub_key = BN_bin2bn(CBS_data(&dhpk), CBS_len(&dhpk), | ||
1258 | NULL)) == NULL) { | ||
1259 | SSLerror(s, ERR_R_BN_LIB); | ||
1260 | goto err; | ||
1261 | } | ||
1262 | 1240 | ||
1263 | /* | 1241 | /* |
1264 | * Check the strength of the DH key just constructed. | 1242 | * Check the strength of the DH key just constructed. |
1265 | * Discard keys weaker than 1024 bits. | 1243 | * Reject keys weaker than 1024 bits. |
1266 | */ | 1244 | */ |
1267 | if (DH_size(dh) < 1024 / 8) { | 1245 | if (DH_size(dh) < 1024 / 8) { |
1268 | SSLerror(s, SSL_R_BAD_DH_P_LENGTH); | 1246 | SSLerror(s, SSL_R_BAD_DH_P_LENGTH); |
@@ -1280,13 +1258,11 @@ ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, CBS *cbs) | |||
1280 | return (1); | 1258 | return (1); |
1281 | 1259 | ||
1282 | decode_err: | 1260 | decode_err: |
1283 | al = SSL_AD_DECODE_ERROR; | ||
1284 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); | 1261 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); |
1285 | ssl3_send_alert(s, SSL3_AL_FATAL, al); | 1262 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); |
1286 | 1263 | ||
1287 | err: | 1264 | err: |
1288 | DH_free(dh); | 1265 | DH_free(dh); |
1289 | BN_CTX_free(bn_ctx); | ||
1290 | 1266 | ||
1291 | return (-1); | 1267 | return (-1); |
1292 | } | 1268 | } |
@@ -1988,59 +1964,38 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb) | |||
1988 | static int | 1964 | static int |
1989 | ssl3_send_client_kex_dhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) | 1965 | ssl3_send_client_kex_dhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) |
1990 | { | 1966 | { |
1991 | DH *dh_srvr = NULL, *dh_clnt = NULL; | 1967 | DH *dh_clnt = NULL; |
1992 | unsigned char *key = NULL; | 1968 | DH *dh_srvr; |
1993 | int key_size = 0, key_len; | 1969 | uint8_t *key = NULL; |
1994 | unsigned char *data; | 1970 | size_t key_len = 0; |
1995 | int ret = -1; | 1971 | int ret = -1; |
1996 | CBB dh_Yc; | ||
1997 | 1972 | ||
1998 | /* Ensure that we have an ephemeral key for DHE. */ | 1973 | /* Ensure that we have an ephemeral key from the server for DHE. */ |
1999 | if (sess_cert->peer_dh_tmp == NULL) { | 1974 | if ((dh_srvr = sess_cert->peer_dh_tmp) == NULL) { |
2000 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); | 1975 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); |
2001 | SSLerror(s, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); | 1976 | SSLerror(s, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); |
2002 | goto err; | 1977 | goto err; |
2003 | } | 1978 | } |
2004 | dh_srvr = sess_cert->peer_dh_tmp; | ||
2005 | 1979 | ||
2006 | /* Generate a new random key. */ | 1980 | if ((dh_clnt = DH_new()) == NULL) |
2007 | if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { | ||
2008 | SSLerror(s, ERR_R_DH_LIB); | ||
2009 | goto err; | 1981 | goto err; |
2010 | } | 1982 | |
2011 | if (!DH_generate_key(dh_clnt)) { | 1983 | if (!ssl_kex_generate_dhe(dh_clnt, dh_srvr)) |
2012 | SSLerror(s, ERR_R_DH_LIB); | ||
2013 | goto err; | ||
2014 | } | ||
2015 | if ((key_size = DH_size(dh_clnt)) <= 0) { | ||
2016 | SSLerror(s, ERR_R_DH_LIB); | ||
2017 | goto err; | ||
2018 | } | ||
2019 | if ((key = malloc(key_size)) == NULL) { | ||
2020 | SSLerror(s, ERR_R_MALLOC_FAILURE); | ||
2021 | goto err; | 1984 | goto err; |
2022 | } | 1985 | if (!ssl_kex_public_dhe(dh_clnt, cbb)) |
2023 | if ((key_len = DH_compute_key(key, dh_srvr->pub_key, dh_clnt)) <= 0) { | ||
2024 | SSLerror(s, ERR_R_DH_LIB); | ||
2025 | goto err; | 1986 | goto err; |
2026 | } | ||
2027 | 1987 | ||
2028 | if (!tls12_derive_master_secret(s, key, key_len)) | 1988 | if (!ssl_kex_derive_dhe(dh_clnt, dh_srvr, &key, &key_len)) |
2029 | goto err; | 1989 | goto err; |
2030 | 1990 | ||
2031 | if (!CBB_add_u16_length_prefixed(cbb, &dh_Yc)) | 1991 | if (!tls12_derive_master_secret(s, key, key_len)) |
2032 | goto err; | ||
2033 | if (!CBB_add_space(&dh_Yc, &data, BN_num_bytes(dh_clnt->pub_key))) | ||
2034 | goto err; | ||
2035 | BN_bn2bin(dh_clnt->pub_key, data); | ||
2036 | if (!CBB_flush(cbb)) | ||
2037 | goto err; | 1992 | goto err; |
2038 | 1993 | ||
2039 | ret = 1; | 1994 | ret = 1; |
2040 | 1995 | ||
2041 | err: | 1996 | err: |
2042 | DH_free(dh_clnt); | 1997 | DH_free(dh_clnt); |
2043 | freezero(key, key_size); | 1998 | freezero(key, key_len); |
2044 | 1999 | ||
2045 | return (ret); | 2000 | return (ret); |
2046 | } | 2001 | } |
@@ -2072,6 +2027,7 @@ ssl3_send_client_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, CBB *cbb) | |||
2072 | 2027 | ||
2073 | if (!ssl_kex_derive_ecdhe_ecp(ecdh, sc->peer_ecdh_tmp, &key, &key_len)) | 2028 | if (!ssl_kex_derive_ecdhe_ecp(ecdh, sc->peer_ecdh_tmp, &key, &key_len)) |
2074 | goto err; | 2029 | goto err; |
2030 | |||
2075 | if (!tls12_derive_master_secret(s, key, key_len)) | 2031 | if (!tls12_derive_master_secret(s, key, key_len)) |
2076 | goto err; | 2032 | goto err; |
2077 | 2033 | ||
diff --git a/src/lib/libssl/ssl_kex.c b/src/lib/libssl/ssl_kex.c index 9f05fd60c9..26f991f190 100644 --- a/src/lib/libssl/ssl_kex.c +++ b/src/lib/libssl/ssl_kex.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_kex.c,v 1.2 2020/04/18 14:07:56 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_kex.c,v 1.3 2021/11/29 16:00:32 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <stdlib.h> | 18 | #include <stdlib.h> |
19 | 19 | ||
20 | #include <openssl/dh.h> | ||
20 | #include <openssl/ec.h> | 21 | #include <openssl/ec.h> |
21 | #include <openssl/ecdh.h> | 22 | #include <openssl/ecdh.h> |
22 | #include <openssl/evp.h> | 23 | #include <openssl/evp.h> |
@@ -25,6 +26,148 @@ | |||
25 | #include "bytestring.h" | 26 | #include "bytestring.h" |
26 | 27 | ||
27 | int | 28 | int |
29 | ssl_kex_generate_dhe(DH *dh, DH *dh_params) | ||
30 | { | ||
31 | BN_free(dh->p); | ||
32 | BN_free(dh->g); | ||
33 | dh->p = NULL; | ||
34 | dh->g = NULL; | ||
35 | |||
36 | if ((dh->p = BN_dup(dh_params->p)) == NULL) | ||
37 | return 0; | ||
38 | if ((dh->g = BN_dup(dh_params->g)) == NULL) | ||
39 | return 0; | ||
40 | |||
41 | if (!DH_generate_key(dh)) | ||
42 | return 0; | ||
43 | |||
44 | return 1; | ||
45 | } | ||
46 | |||
47 | int | ||
48 | ssl_kex_params_dhe(DH *dh, CBB *cbb) | ||
49 | { | ||
50 | int dh_p_len, dh_g_len; | ||
51 | CBB dh_p, dh_g; | ||
52 | uint8_t *data; | ||
53 | |||
54 | if ((dh_p_len = BN_num_bytes(dh->p)) <= 0) | ||
55 | return 0; | ||
56 | if ((dh_g_len = BN_num_bytes(dh->g)) <= 0) | ||
57 | return 0; | ||
58 | |||
59 | if (!CBB_add_u16_length_prefixed(cbb, &dh_p)) | ||
60 | return 0; | ||
61 | if (!CBB_add_space(&dh_p, &data, dh_p_len)) | ||
62 | return 0; | ||
63 | if (BN_bn2bin(dh->p, data) != dh_p_len) | ||
64 | return 0; | ||
65 | |||
66 | if (!CBB_add_u16_length_prefixed(cbb, &dh_g)) | ||
67 | return 0; | ||
68 | if (!CBB_add_space(&dh_g, &data, dh_g_len)) | ||
69 | return 0; | ||
70 | if (BN_bn2bin(dh->g, data) != dh_g_len) | ||
71 | return 0; | ||
72 | |||
73 | if (!CBB_flush(cbb)) | ||
74 | return 0; | ||
75 | |||
76 | return 1; | ||
77 | } | ||
78 | |||
79 | int | ||
80 | ssl_kex_public_dhe(DH *dh, CBB *cbb) | ||
81 | { | ||
82 | uint8_t *data; | ||
83 | int dh_y_len; | ||
84 | CBB dh_y; | ||
85 | |||
86 | if ((dh_y_len = BN_num_bytes(dh->pub_key)) <= 0) | ||
87 | return 0; | ||
88 | |||
89 | if (!CBB_add_u16_length_prefixed(cbb, &dh_y)) | ||
90 | return 0; | ||
91 | if (!CBB_add_space(&dh_y, &data, dh_y_len)) | ||
92 | return 0; | ||
93 | if (BN_bn2bin(dh->pub_key, data) != dh_y_len) | ||
94 | return 0; | ||
95 | |||
96 | if (!CBB_flush(cbb)) | ||
97 | return 0; | ||
98 | |||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | int | ||
103 | ssl_kex_peer_params_dhe(DH *dh, CBS *cbs) | ||
104 | { | ||
105 | CBS dh_p, dh_g; | ||
106 | |||
107 | BN_free(dh->p); | ||
108 | BN_free(dh->g); | ||
109 | dh->p = NULL; | ||
110 | dh->g = NULL; | ||
111 | |||
112 | if (!CBS_get_u16_length_prefixed(cbs, &dh_p)) | ||
113 | return 0; | ||
114 | if (!CBS_get_u16_length_prefixed(cbs, &dh_g)) | ||
115 | return 0; | ||
116 | |||
117 | if ((dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL) | ||
118 | return 0; | ||
119 | if ((dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL) | ||
120 | return 0; | ||
121 | |||
122 | return 1; | ||
123 | } | ||
124 | |||
125 | int | ||
126 | ssl_kex_peer_public_dhe(DH *dh, CBS *cbs) | ||
127 | { | ||
128 | CBS dh_y; | ||
129 | |||
130 | BN_free(dh->pub_key); | ||
131 | dh->pub_key = NULL; | ||
132 | |||
133 | if (!CBS_get_u16_length_prefixed(cbs, &dh_y)) | ||
134 | return 0; | ||
135 | if ((dh->pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y), | ||
136 | NULL)) == NULL) | ||
137 | return 0; | ||
138 | |||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | ssl_kex_derive_dhe(DH *dh, DH *dh_peer, | ||
144 | uint8_t **shared_key, size_t *shared_key_len) | ||
145 | { | ||
146 | uint8_t *key = NULL; | ||
147 | int key_len = 0; | ||
148 | int ret = 0; | ||
149 | |||
150 | if ((key_len = DH_size(dh)) <= 0) | ||
151 | goto err; | ||
152 | if ((key = calloc(1, key_len)) == NULL) | ||
153 | goto err; | ||
154 | |||
155 | if ((key_len = DH_compute_key(key, dh_peer->pub_key, dh)) <= 0) | ||
156 | goto err; | ||
157 | |||
158 | *shared_key = key; | ||
159 | *shared_key_len = key_len; | ||
160 | key = NULL; | ||
161 | |||
162 | ret = 1; | ||
163 | |||
164 | err: | ||
165 | freezero(key, key_len); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | int | ||
28 | ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) | 171 | ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) |
29 | { | 172 | { |
30 | EC_GROUP *group = NULL; | 173 | EC_GROUP *group = NULL; |
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 27bf5ec41f..7810bcd05e 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_locl.h,v 1.368 2021/10/25 10:09:28 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.369 2021/11/29 16:00:32 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1447,6 +1447,14 @@ int ssl3_get_client_certificate(SSL *s); | |||
1447 | int ssl3_get_client_key_exchange(SSL *s); | 1447 | int ssl3_get_client_key_exchange(SSL *s); |
1448 | int ssl3_get_cert_verify(SSL *s); | 1448 | int ssl3_get_cert_verify(SSL *s); |
1449 | 1449 | ||
1450 | int ssl_kex_generate_dhe(DH *dh, DH *dh_params); | ||
1451 | int ssl_kex_params_dhe(DH *dh, CBB *cbb); | ||
1452 | int ssl_kex_public_dhe(DH *dh, CBB *cbb); | ||
1453 | int ssl_kex_peer_params_dhe(DH *dh, CBS *cbs); | ||
1454 | int ssl_kex_peer_public_dhe(DH *dh, CBS *cbs); | ||
1455 | int ssl_kex_derive_dhe(DH *dh, DH *dh_peer, | ||
1456 | uint8_t **shared_key, size_t *shared_key_len); | ||
1457 | |||
1450 | int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey); | 1458 | int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey); |
1451 | int ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid); | 1459 | int ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid); |
1452 | int ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb); | 1460 | int ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb); |