diff options
| author | tb <> | 2026-06-08 11:52:43 +0000 |
|---|---|---|
| committer | tb <> | 2026-06-08 11:52:43 +0000 |
| commit | 66583c24ec477c457c733302a390034dcf581c73 (patch) | |
| tree | 4bbcfe74ebaef4b5c765a0acc2fc97b57089b600 /src/lib/libssl | |
| parent | 7646f48d882beb02b217ec30dc5d9f2508d1b95b (diff) | |
| download | openbsd-66583c24ec477c457c733302a390034dcf581c73.tar.gz openbsd-66583c24ec477c457c733302a390034dcf581c73.tar.bz2 openbsd-66583c24ec477c457c733302a390034dcf581c73.zip | |
ssl_kex: ensure the public key uses uncompressed encoding
EC_POINT_oct2point() does most of the validation we need it to do, but it
has to accept the point at infinity, compressed and hybrid encodings for
historic reasons. So exclude these cases: the point at infinity makes no
sense here and will be caught later in ECDH_compute_key(), the compressed
and hybrid encodings MUST NOT be supported per RFC 8422 section 5.1.2.
This is implemented using the strategy already used in ec_convert.c since
the point_conversion_form_t is completely unfit for anything.
Set decode_error to ensure we send that alert. We may make some effort to
use illegal_parameter later.
Issue about the missing alert and the point at infinity raised by Lucca
Hirschi et al.
ok jsing kenjiro
Diffstat (limited to 'src/lib/libssl')
| -rw-r--r-- | src/lib/libssl/ssl_kex.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/src/lib/libssl/ssl_kex.c b/src/lib/libssl/ssl_kex.c index ad69b2f485..a7d02892bc 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.14 2026/06/08 11:38:04 tb Exp $ */ | 1 | /* $OpenBSD: ssl_kex.c,v 1.15 2026/06/08 11:52:43 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2020, 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2020, 2021 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -355,14 +355,32 @@ ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) | |||
| 355 | return ret; | 355 | return ret; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | #define EC_POINT_UNCOMPRESSED 0x04 | ||
| 359 | #define EC_POINT_CONVERSION_MASK 0x06 | ||
| 360 | |||
| 358 | int | 361 | int |
| 359 | ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs, | 362 | ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs, |
| 360 | int *decode_error) | 363 | int *decode_error) |
| 361 | { | 364 | { |
| 362 | EC_GROUP *group = NULL; | 365 | EC_GROUP *group = NULL; |
| 363 | EC_POINT *point = NULL; | 366 | EC_POINT *point = NULL; |
| 367 | uint8_t form; | ||
| 364 | int ret = 0; | 368 | int ret = 0; |
| 365 | 369 | ||
| 370 | /* | ||
| 371 | * Check that the peer's public key uses uncompressed encoding. | ||
| 372 | * This ensures that the public key is not the point at infinity | ||
| 373 | * and enforces correct point encoding via EC_POINT_oct2point(). | ||
| 374 | */ | ||
| 375 | if (!CBS_peek_u8(cbs, &form)) { | ||
| 376 | *decode_error = 1; | ||
| 377 | goto err; | ||
| 378 | } | ||
| 379 | if ((form & EC_POINT_CONVERSION_MASK) != EC_POINT_UNCOMPRESSED) { | ||
| 380 | *decode_error = 1; | ||
| 381 | goto err; | ||
| 382 | } | ||
| 383 | |||
| 366 | if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) | 384 | if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) |
| 367 | goto err; | 385 | goto err; |
| 368 | 386 | ||
| @@ -372,8 +390,10 @@ ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs, | |||
| 372 | if ((point = EC_POINT_new(group)) == NULL) | 390 | if ((point = EC_POINT_new(group)) == NULL) |
| 373 | goto err; | 391 | goto err; |
| 374 | if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), | 392 | if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), |
| 375 | NULL) == 0) | 393 | NULL) == 0) { |
| 394 | *decode_error = 1; | ||
| 376 | goto err; | 395 | goto err; |
| 396 | } | ||
| 377 | if (!EC_KEY_set_public_key(ecdh, point)) | 397 | if (!EC_KEY_set_public_key(ecdh, point)) |
| 378 | goto err; | 398 | goto err; |
| 379 | 399 | ||
