diff options
author | jsing <> | 2016-11-05 08:26:37 +0000 |
---|---|---|
committer | jsing <> | 2016-11-05 08:26:37 +0000 |
commit | 9fa2112db3b5977fa473ce68fa02199114a3b870 (patch) | |
tree | f18e5a0a899b59b54269ba0efb72acd8d5566f6f /src/lib | |
parent | 8e601af590fe4daecd1a7d96cddb851fc0118296 (diff) | |
download | openbsd-9fa2112db3b5977fa473ce68fa02199114a3b870.tar.gz openbsd-9fa2112db3b5977fa473ce68fa02199114a3b870.tar.bz2 openbsd-9fa2112db3b5977fa473ce68fa02199114a3b870.zip |
Convert ssl3_get_server_kex_ecdhe() to CBS, simplifying tls1_check_curve()
in the process. This also fixes a long standing bug where
tls1_ec_curve_id2nid() is called with only one byte of the curve ID.
ok beck@ miod@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libssl/s3_clnt.c | 75 | ||||
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 8 | ||||
-rw-r--r-- | src/lib/libssl/t1_lib.c | 20 |
3 files changed, 41 insertions, 62 deletions
diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index dd5121366d..ff015568e4 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: s3_clnt.c,v 1.143 2016/11/04 19:11:43 jsing Exp $ */ | 1 | /* $OpenBSD: s3_clnt.c,v 1.144 2016/11/05 08:26:36 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 | * |
@@ -1175,64 +1175,63 @@ ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) | |||
1175 | static int | 1175 | static int |
1176 | ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) | 1176 | ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) |
1177 | { | 1177 | { |
1178 | CBS cbs, ecpoint; | ||
1179 | uint8_t curve_type; | ||
1180 | uint16_t curve_id; | ||
1178 | EC_POINT *srvr_ecpoint = NULL; | 1181 | EC_POINT *srvr_ecpoint = NULL; |
1179 | EC_KEY *ecdh = NULL; | 1182 | EC_KEY *ecdh = NULL; |
1180 | BN_CTX *bn_ctx = NULL; | 1183 | BN_CTX *bn_ctx = NULL; |
1181 | const EC_GROUP *group; | 1184 | const EC_GROUP *group; |
1182 | EC_GROUP *ngroup; | 1185 | EC_GROUP *ngroup; |
1183 | SESS_CERT *sc; | 1186 | SESS_CERT *sc; |
1184 | unsigned char *p; | 1187 | int curve_nid; |
1185 | int al, param_len; | 1188 | long alg_a; |
1186 | long alg_a, n; | 1189 | int al; |
1187 | int curve_nid = 0; | ||
1188 | int encoded_pt_len = 0; | ||
1189 | 1190 | ||
1190 | alg_a = s->s3->tmp.new_cipher->algorithm_auth; | 1191 | alg_a = s->s3->tmp.new_cipher->algorithm_auth; |
1191 | n = *nn; | ||
1192 | p = *pp; | ||
1193 | sc = s->session->sess_cert; | 1192 | sc = s->session->sess_cert; |
1194 | 1193 | ||
1195 | if ((ecdh = EC_KEY_new()) == NULL) { | 1194 | if (*nn < 0) |
1196 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); | ||
1197 | goto err; | 1195 | goto err; |
1198 | } | ||
1199 | 1196 | ||
1200 | /* | 1197 | CBS_init(&cbs, *pp, *nn); |
1201 | * Extract elliptic curve parameters and the server's ephemeral ECDH | ||
1202 | * public key. Keep accumulating lengths of various components in | ||
1203 | * param_len and make sure it never exceeds n. | ||
1204 | */ | ||
1205 | 1198 | ||
1206 | /* | 1199 | /* |
1207 | * XXX: For now we only support named (not generic) curves | 1200 | * Extract EC parameters and the server's ephemeral ECDH public key. |
1208 | * and the ECParameters in this case is just three bytes. | ||
1209 | */ | 1201 | */ |
1210 | param_len = 3; | 1202 | |
1211 | if (param_len > n) { | 1203 | if ((ecdh = EC_KEY_new()) == NULL) { |
1204 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); | ||
1205 | goto err; | ||
1206 | } | ||
1207 | |||
1208 | /* Only named curves are supported. */ | ||
1209 | if (!CBS_get_u8(&cbs, &curve_type) || | ||
1210 | curve_type != NAMED_CURVE_TYPE || | ||
1211 | !CBS_get_u16(&cbs, &curve_id)) { | ||
1212 | al = SSL_AD_DECODE_ERROR; | 1212 | al = SSL_AD_DECODE_ERROR; |
1213 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); | 1213 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); |
1214 | goto f_err; | 1214 | goto f_err; |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | /* | 1217 | /* |
1218 | * Check curve is one of our preferences, if not server has | 1218 | * Check that the curve is one of our preferences - if it is not, |
1219 | * sent an invalid curve. | 1219 | * the server has sent us an invalid curve. |
1220 | */ | 1220 | */ |
1221 | if (tls1_check_curve(s, p, param_len) != 1) { | 1221 | if (tls1_check_curve(s, curve_id) != 1) { |
1222 | al = SSL_AD_DECODE_ERROR; | 1222 | al = SSL_AD_DECODE_ERROR; |
1223 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE); | 1223 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE); |
1224 | goto f_err; | 1224 | goto f_err; |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) { | 1227 | if ((curve_nid = tls1_ec_curve_id2nid(curve_id)) == 0) { |
1228 | al = SSL_AD_INTERNAL_ERROR; | 1228 | al = SSL_AD_INTERNAL_ERROR; |
1229 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, | 1229 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, |
1230 | SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); | 1230 | SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); |
1231 | goto f_err; | 1231 | goto f_err; |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | ngroup = EC_GROUP_new_by_curve_name(curve_nid); | 1234 | if ((ngroup = EC_GROUP_new_by_curve_name(curve_nid)) == NULL) { |
1235 | if (ngroup == NULL) { | ||
1236 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); | 1235 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EC_LIB); |
1237 | goto err; | 1236 | goto err; |
1238 | } | 1237 | } |
@@ -1244,31 +1243,23 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) | |||
1244 | 1243 | ||
1245 | group = EC_KEY_get0_group(ecdh); | 1244 | group = EC_KEY_get0_group(ecdh); |
1246 | 1245 | ||
1247 | p += 3; | ||
1248 | |||
1249 | /* Next, get the encoded ECPoint */ | 1246 | /* Next, get the encoded ECPoint */ |
1250 | if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) || | 1247 | if ((srvr_ecpoint = EC_POINT_new(group)) == NULL || |
1251 | ((bn_ctx = BN_CTX_new()) == NULL)) { | 1248 | (bn_ctx = BN_CTX_new()) == NULL) { |
1252 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); | 1249 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); |
1253 | goto err; | 1250 | goto err; |
1254 | } | 1251 | } |
1255 | 1252 | ||
1256 | if (param_len + 1 > n) | 1253 | if (!CBS_get_u8_length_prefixed(&cbs, &ecpoint)) |
1257 | goto truncated; | 1254 | goto truncated; |
1258 | encoded_pt_len = *p; | 1255 | |
1259 | /* length of encoded point */ | 1256 | if (EC_POINT_oct2point(group, srvr_ecpoint, CBS_data(&ecpoint), |
1260 | p += 1; | 1257 | CBS_len(&ecpoint), bn_ctx) == 0) { |
1261 | param_len += (1 + encoded_pt_len); | ||
1262 | if ((param_len > n) || (EC_POINT_oct2point(group, srvr_ecpoint, | ||
1263 | p, encoded_pt_len, bn_ctx) == 0)) { | ||
1264 | al = SSL_AD_DECODE_ERROR; | 1258 | al = SSL_AD_DECODE_ERROR; |
1265 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT); | 1259 | SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT); |
1266 | goto f_err; | 1260 | goto f_err; |
1267 | } | 1261 | } |
1268 | 1262 | ||
1269 | n -= param_len; | ||
1270 | p += encoded_pt_len; | ||
1271 | |||
1272 | /* | 1263 | /* |
1273 | * The ECC/TLS specification does not mention the use of DSA to sign | 1264 | * The ECC/TLS specification does not mention the use of DSA to sign |
1274 | * ECParameters in the server key exchange message. We do support RSA | 1265 | * ECParameters in the server key exchange message. We do support RSA |
@@ -1288,8 +1279,8 @@ ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, unsigned char **pp, long *nn) | |||
1288 | BN_CTX_free(bn_ctx); | 1279 | BN_CTX_free(bn_ctx); |
1289 | EC_POINT_free(srvr_ecpoint); | 1280 | EC_POINT_free(srvr_ecpoint); |
1290 | 1281 | ||
1291 | *nn = n; | 1282 | *nn = CBS_len(&cbs); |
1292 | *pp = p; | 1283 | *pp = (unsigned char *)CBS_data(&cbs); |
1293 | 1284 | ||
1294 | return (1); | 1285 | return (1); |
1295 | 1286 | ||
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 1b3838a33f..4386f0f7e5 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.134 2016/11/04 19:11:43 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.135 2016/11/05 08:26:36 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 | * |
@@ -772,9 +772,9 @@ int ssl_ok(SSL *s); | |||
772 | 772 | ||
773 | int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); | 773 | int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); |
774 | 774 | ||
775 | int tls1_ec_curve_id2nid(uint16_t curve_id); | 775 | int tls1_ec_curve_id2nid(const uint16_t curve_id); |
776 | uint16_t tls1_ec_nid2curve_id(int nid); | 776 | uint16_t tls1_ec_nid2curve_id(const int nid); |
777 | int tls1_check_curve(SSL *s, const unsigned char *p, size_t len); | 777 | int tls1_check_curve(SSL *s, const uint16_t curve_id); |
778 | int tls1_get_shared_curve(SSL *s); | 778 | int tls1_get_shared_curve(SSL *s); |
779 | 779 | ||
780 | unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, | 780 | unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, |
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index e7dbe9cd99..090259cf1f 100644 --- a/src/lib/libssl/t1_lib.c +++ b/src/lib/libssl/t1_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: t1_lib.c,v 1.93 2016/10/19 16:38:40 jsing Exp $ */ | 1 | /* $OpenBSD: t1_lib.c,v 1.94 2016/11/05 08:26:37 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 | * |
@@ -282,7 +282,7 @@ static const uint16_t eccurves_default[] = { | |||
282 | }; | 282 | }; |
283 | 283 | ||
284 | int | 284 | int |
285 | tls1_ec_curve_id2nid(uint16_t curve_id) | 285 | tls1_ec_curve_id2nid(const uint16_t curve_id) |
286 | { | 286 | { |
287 | /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ | 287 | /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ |
288 | if ((curve_id < 1) || | 288 | if ((curve_id < 1) || |
@@ -405,27 +405,15 @@ tls1_get_curvelist(SSL *s, int client_curves, const uint16_t **pcurves, | |||
405 | 405 | ||
406 | /* Check that a curve is one of our preferences. */ | 406 | /* Check that a curve is one of our preferences. */ |
407 | int | 407 | int |
408 | tls1_check_curve(SSL *s, const unsigned char *p, size_t len) | 408 | tls1_check_curve(SSL *s, const uint16_t curve_id) |
409 | { | 409 | { |
410 | CBS cbs; | ||
411 | const uint16_t *curves; | 410 | const uint16_t *curves; |
412 | size_t curveslen, i; | 411 | size_t curveslen, i; |
413 | uint8_t type; | ||
414 | uint16_t cid; | ||
415 | |||
416 | CBS_init(&cbs, p, len); | ||
417 | |||
418 | /* Only named curves are supported. */ | ||
419 | if (CBS_len(&cbs) != 3 || | ||
420 | !CBS_get_u8(&cbs, &type) || | ||
421 | type != NAMED_CURVE_TYPE || | ||
422 | !CBS_get_u16(&cbs, &cid)) | ||
423 | return (0); | ||
424 | 412 | ||
425 | tls1_get_curvelist(s, 0, &curves, &curveslen); | 413 | tls1_get_curvelist(s, 0, &curves, &curveslen); |
426 | 414 | ||
427 | for (i = 0; i < curveslen; i++) { | 415 | for (i = 0; i < curveslen; i++) { |
428 | if (curves[i] == cid) | 416 | if (curves[i] == curve_id) |
429 | return (1); | 417 | return (1); |
430 | } | 418 | } |
431 | return (0); | 419 | return (0); |