summaryrefslogtreecommitdiff
path: root/src/lib/libssl
diff options
context:
space:
mode:
authortb <>2026-06-08 11:52:43 +0000
committertb <>2026-06-08 11:52:43 +0000
commit66583c24ec477c457c733302a390034dcf581c73 (patch)
tree4bbcfe74ebaef4b5c765a0acc2fc97b57089b600 /src/lib/libssl
parent7646f48d882beb02b217ec30dc5d9f2508d1b95b (diff)
downloadopenbsd-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.c24
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
358int 361int
359ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs, 362ssl_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