diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/libssl/ssl_clnt.c | 10 | ||||
| -rw-r--r-- | src/lib/libssl/ssl_srvr.c | 10 | ||||
| -rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 8 | ||||
| -rw-r--r-- | src/lib/libssl/tls13_client.c | 6 | ||||
| -rw-r--r-- | src/lib/libssl/tls13_server.c | 4 | ||||
| -rw-r--r-- | src/lib/libssl/tls_internal.h | 9 | ||||
| -rw-r--r-- | src/lib/libssl/tls_key_share.c | 327 |
7 files changed, 348 insertions, 26 deletions
diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c index 0d3dcf78af..22469ce346 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.169 2025/03/09 15:53:36 tb Exp $ */ | 1 | /* $OpenBSD: ssl_clnt.c,v 1.170 2025/12/04 21:03:42 beck 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 | * |
| @@ -1195,7 +1195,7 @@ ssl3_get_server_kex_dhe(SSL *s, CBS *cbs) | |||
| 1195 | } | 1195 | } |
| 1196 | goto err; | 1196 | goto err; |
| 1197 | } | 1197 | } |
| 1198 | if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, | 1198 | if (!tls_key_share_client_peer_public(s->s3->hs.key_share, cbs, |
| 1199 | &decode_error, &invalid_key)) { | 1199 | &decode_error, &invalid_key)) { |
| 1200 | if (decode_error) { | 1200 | if (decode_error) { |
| 1201 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); | 1201 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); |
| @@ -1264,7 +1264,7 @@ ssl3_get_server_kex_ecdhe(SSL *s, CBS *cbs) | |||
| 1264 | if ((s->s3->hs.key_share = tls_key_share_new(group_id)) == NULL) | 1264 | if ((s->s3->hs.key_share = tls_key_share_new(group_id)) == NULL) |
| 1265 | goto err; | 1265 | goto err; |
| 1266 | 1266 | ||
| 1267 | if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, | 1267 | if (!tls_key_share_client_peer_public(s->s3->hs.key_share, &public, |
| 1268 | &decode_error, NULL)) { | 1268 | &decode_error, NULL)) { |
| 1269 | if (decode_error) | 1269 | if (decode_error) |
| 1270 | goto decode_err; | 1270 | goto decode_err; |
| @@ -1859,7 +1859,7 @@ ssl3_send_client_kex_dhe(SSL *s, CBB *cbb) | |||
| 1859 | goto err; | 1859 | goto err; |
| 1860 | } | 1860 | } |
| 1861 | 1861 | ||
| 1862 | if (!tls_key_share_generate(s->s3->hs.key_share)) | 1862 | if (!tls_key_share_client_generate(s->s3->hs.key_share)) |
| 1863 | goto err; | 1863 | goto err; |
| 1864 | if (!tls_key_share_public(s->s3->hs.key_share, cbb)) | 1864 | if (!tls_key_share_public(s->s3->hs.key_share, cbb)) |
| 1865 | goto err; | 1865 | goto err; |
| @@ -1898,7 +1898,7 @@ ssl3_send_client_kex_ecdhe(SSL *s, CBB *cbb) | |||
| 1898 | goto err; | 1898 | goto err; |
| 1899 | } | 1899 | } |
| 1900 | 1900 | ||
| 1901 | if (!tls_key_share_generate(s->s3->hs.key_share)) | 1901 | if (!tls_key_share_client_generate(s->s3->hs.key_share)) |
| 1902 | goto err; | 1902 | goto err; |
| 1903 | 1903 | ||
| 1904 | if (!CBB_add_u8_length_prefixed(cbb, &public)) | 1904 | if (!CBB_add_u8_length_prefixed(cbb, &public)) |
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index db4ba38b51..ef93e283de 100644 --- a/src/lib/libssl/ssl_srvr.c +++ b/src/lib/libssl/ssl_srvr.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ssl_srvr.c,v 1.166 2025/03/09 15:53:36 tb Exp $ */ | 1 | /* $OpenBSD: ssl_srvr.c,v 1.167 2025/12/04 21:03:42 beck 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 | * |
| @@ -1357,7 +1357,7 @@ ssl3_send_server_kex_dhe(SSL *s, CBB *cbb) | |||
| 1357 | goto err; | 1357 | goto err; |
| 1358 | } | 1358 | } |
| 1359 | 1359 | ||
| 1360 | if (!tls_key_share_generate(s->s3->hs.key_share)) | 1360 | if (!tls_key_share_server_generate(s->s3->hs.key_share)) |
| 1361 | goto err; | 1361 | goto err; |
| 1362 | 1362 | ||
| 1363 | if (!tls_key_share_params(s->s3->hs.key_share, cbb)) | 1363 | if (!tls_key_share_params(s->s3->hs.key_share, cbb)) |
| @@ -1393,7 +1393,7 @@ ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) | |||
| 1393 | if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) | 1393 | if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) |
| 1394 | goto err; | 1394 | goto err; |
| 1395 | 1395 | ||
| 1396 | if (!tls_key_share_generate(s->s3->hs.key_share)) | 1396 | if (!tls_key_share_server_generate(s->s3->hs.key_share)) |
| 1397 | goto err; | 1397 | goto err; |
| 1398 | 1398 | ||
| 1399 | /* | 1399 | /* |
| @@ -1744,7 +1744,7 @@ ssl3_get_client_kex_dhe(SSL *s, CBS *cbs) | |||
| 1744 | goto err; | 1744 | goto err; |
| 1745 | } | 1745 | } |
| 1746 | 1746 | ||
| 1747 | if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, | 1747 | if (!tls_key_share_server_peer_public(s->s3->hs.key_share, cbs, |
| 1748 | &decode_error, &invalid_key)) { | 1748 | &decode_error, &invalid_key)) { |
| 1749 | if (decode_error) { | 1749 | if (decode_error) { |
| 1750 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); | 1750 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); |
| @@ -1792,7 +1792,7 @@ ssl3_get_client_kex_ecdhe(SSL *s, CBS *cbs) | |||
| 1792 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | 1792 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); |
| 1793 | goto err; | 1793 | goto err; |
| 1794 | } | 1794 | } |
| 1795 | if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, | 1795 | if (!tls_key_share_server_peer_public(s->s3->hs.key_share, &public, |
| 1796 | &decode_error, NULL)) { | 1796 | &decode_error, NULL)) { |
| 1797 | if (decode_error) { | 1797 | if (decode_error) { |
| 1798 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); | 1798 | SSLerror(s, SSL_R_BAD_PACKET_LENGTH); |
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c index 12ede899e8..dcd9a31205 100644 --- a/src/lib/libssl/ssl_tlsext.c +++ b/src/lib/libssl/ssl_tlsext.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ssl_tlsext.c,v 1.157 2025/10/16 14:42:21 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.c,v 1.158 2025/12/04 21:03:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org> |
| 4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> | 4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> |
| @@ -1523,7 +1523,7 @@ tlsext_keyshare_server_process(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) | |||
| 1523 | *alert = SSL_AD_INTERNAL_ERROR; | 1523 | *alert = SSL_AD_INTERNAL_ERROR; |
| 1524 | return 0; | 1524 | return 0; |
| 1525 | } | 1525 | } |
| 1526 | if (!tls_key_share_peer_public(s->s3->hs.key_share, | 1526 | if (!tls_key_share_server_peer_public(s->s3->hs.key_share, |
| 1527 | &key_exchange, &decode_error, NULL)) { | 1527 | &key_exchange, &decode_error, NULL)) { |
| 1528 | if (!decode_error) | 1528 | if (!decode_error) |
| 1529 | *alert = SSL_AD_INTERNAL_ERROR; | 1529 | *alert = SSL_AD_INTERNAL_ERROR; |
| @@ -1614,7 +1614,7 @@ tlsext_keyshare_server_process(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) | |||
| 1614 | *alert = SSL_AD_INTERNAL_ERROR; | 1614 | *alert = SSL_AD_INTERNAL_ERROR; |
| 1615 | return 0; | 1615 | return 0; |
| 1616 | } | 1616 | } |
| 1617 | if (!tls_key_share_peer_public(s->s3->hs.key_share, | 1617 | if (!tls_key_share_server_peer_public(s->s3->hs.key_share, |
| 1618 | &key_exchange, &decode_error, NULL)) { | 1618 | &key_exchange, &decode_error, NULL)) { |
| 1619 | if (!decode_error) | 1619 | if (!decode_error) |
| 1620 | *alert = SSL_AD_INTERNAL_ERROR; | 1620 | *alert = SSL_AD_INTERNAL_ERROR; |
| @@ -1691,7 +1691,7 @@ tlsext_keyshare_client_process(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) | |||
| 1691 | *alert = SSL_AD_INTERNAL_ERROR; | 1691 | *alert = SSL_AD_INTERNAL_ERROR; |
| 1692 | return 0; | 1692 | return 0; |
| 1693 | } | 1693 | } |
| 1694 | if (!tls_key_share_peer_public(s->s3->hs.key_share, | 1694 | if (!tls_key_share_client_peer_public(s->s3->hs.key_share, |
| 1695 | &key_exchange, &decode_error, NULL)) { | 1695 | &key_exchange, &decode_error, NULL)) { |
| 1696 | if (!decode_error) | 1696 | if (!decode_error) |
| 1697 | *alert = SSL_AD_INTERNAL_ERROR; | 1697 | *alert = SSL_AD_INTERNAL_ERROR; |
diff --git a/src/lib/libssl/tls13_client.c b/src/lib/libssl/tls13_client.c index 901b38f860..b0a285694d 100644 --- a/src/lib/libssl/tls13_client.c +++ b/src/lib/libssl/tls13_client.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls13_client.c,v 1.104 2024/07/22 14:47:15 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_client.c,v 1.105 2025/12/04 21:03:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -53,7 +53,7 @@ tls13_client_init(struct tls13_ctx *ctx) | |||
| 53 | return 0; | 53 | return 0; |
| 54 | if ((ctx->hs->key_share = tls_key_share_new(groups[0])) == NULL) | 54 | if ((ctx->hs->key_share = tls_key_share_new(groups[0])) == NULL) |
| 55 | return 0; | 55 | return 0; |
| 56 | if (!tls_key_share_generate(ctx->hs->key_share)) | 56 | if (!tls_key_share_client_generate(ctx->hs->key_share)) |
| 57 | return 0; | 57 | return 0; |
| 58 | 58 | ||
| 59 | arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); | 59 | arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); |
| @@ -450,7 +450,7 @@ tls13_client_hello_retry_send(struct tls13_ctx *ctx, CBB *cbb) | |||
| 450 | if ((ctx->hs->key_share = | 450 | if ((ctx->hs->key_share = |
| 451 | tls_key_share_new(ctx->hs->tls13.server_group)) == NULL) | 451 | tls_key_share_new(ctx->hs->tls13.server_group)) == NULL) |
| 452 | return 0; | 452 | return 0; |
| 453 | if (!tls_key_share_generate(ctx->hs->key_share)) | 453 | if (!tls_key_share_client_generate(ctx->hs->key_share)) |
| 454 | return 0; | 454 | return 0; |
| 455 | 455 | ||
| 456 | if (!tls13_client_hello_build(ctx, cbb)) | 456 | if (!tls13_client_hello_build(ctx, cbb)) |
diff --git a/src/lib/libssl/tls13_server.c b/src/lib/libssl/tls13_server.c index fa56db9563..604dab4cba 100644 --- a/src/lib/libssl/tls13_server.c +++ b/src/lib/libssl/tls13_server.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls13_server.c,v 1.111 2025/10/25 12:31:44 tb Exp $ */ | 1 | /* $OpenBSD: tls13_server.c,v 1.112 2025/12/04 21:03:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org> |
| 4 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
| @@ -502,7 +502,7 @@ tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb) | |||
| 502 | { | 502 | { |
| 503 | if (ctx->hs->key_share == NULL) | 503 | if (ctx->hs->key_share == NULL) |
| 504 | return 0; | 504 | return 0; |
| 505 | if (!tls_key_share_generate(ctx->hs->key_share)) | 505 | if (!tls_key_share_server_generate(ctx->hs->key_share)) |
| 506 | return 0; | 506 | return 0; |
| 507 | if (!tls13_servername_process(ctx)) | 507 | if (!tls13_servername_process(ctx)) |
| 508 | return 0; | 508 | return 0; |
diff --git a/src/lib/libssl/tls_internal.h b/src/lib/libssl/tls_internal.h index 84edde8474..3d8d6aa940 100644 --- a/src/lib/libssl/tls_internal.h +++ b/src/lib/libssl/tls_internal.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_internal.h,v 1.10 2022/11/10 18:06:37 jsing Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.11 2025/12/04 21:03:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -85,12 +85,15 @@ int tls_key_share_nid(struct tls_key_share *ks); | |||
| 85 | void tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits); | 85 | void tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits); |
| 86 | int tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params); | 86 | int tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params); |
| 87 | int tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey); | 87 | int tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey); |
| 88 | int tls_key_share_generate(struct tls_key_share *ks); | 88 | int tls_key_share_client_generate(struct tls_key_share *ks); |
| 89 | int tls_key_share_server_generate(struct tls_key_share *ks); | ||
| 89 | int tls_key_share_params(struct tls_key_share *ks, CBB *cbb); | 90 | int tls_key_share_params(struct tls_key_share *ks, CBB *cbb); |
| 90 | int tls_key_share_public(struct tls_key_share *ks, CBB *cbb); | 91 | int tls_key_share_public(struct tls_key_share *ks, CBB *cbb); |
| 91 | int tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, | 92 | int tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, |
| 92 | int *decode_error, int *invalid_params); | 93 | int *decode_error, int *invalid_params); |
| 93 | int tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, | 94 | int tls_key_share_server_peer_public(struct tls_key_share *ks, CBS *cbs, |
| 95 | int *decode_error, int *invalid_key); | ||
| 96 | int tls_key_share_client_peer_public(struct tls_key_share *ks, CBS *cbs, | ||
| 94 | int *decode_error, int *invalid_key); | 97 | int *decode_error, int *invalid_key); |
| 95 | int tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, | 98 | int tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, |
| 96 | size_t *shared_key_len); | 99 | size_t *shared_key_len); |
diff --git a/src/lib/libssl/tls_key_share.c b/src/lib/libssl/tls_key_share.c index cf7b1da262..3f4c44f558 100644 --- a/src/lib/libssl/tls_key_share.c +++ b/src/lib/libssl/tls_key_share.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_key_share.c,v 1.8 2022/11/26 16:08:56 tb Exp $ */ | 1 | /* $OpenBSD: tls_key_share.c,v 1.9 2025/12/04 21:03:42 beck 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 | * |
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <openssl/dh.h> | 21 | #include <openssl/dh.h> |
| 22 | #include <openssl/ec.h> | 22 | #include <openssl/ec.h> |
| 23 | #include <openssl/evp.h> | 23 | #include <openssl/evp.h> |
| 24 | #include <openssl/mlkem.h> | ||
| 24 | 25 | ||
| 25 | #include "bytestring.h" | 26 | #include "bytestring.h" |
| 26 | #include "ssl_local.h" | 27 | #include "ssl_local.h" |
| @@ -40,6 +41,19 @@ struct tls_key_share { | |||
| 40 | uint8_t *x25519_public; | 41 | uint8_t *x25519_public; |
| 41 | uint8_t *x25519_private; | 42 | uint8_t *x25519_private; |
| 42 | uint8_t *x25519_peer_public; | 43 | uint8_t *x25519_peer_public; |
| 44 | |||
| 45 | uint8_t *mlkem_public; | ||
| 46 | size_t mlkem_public_len; | ||
| 47 | MLKEM_private_key *mlkem_private; | ||
| 48 | MLKEM_public_key *mlkem_peer_public; | ||
| 49 | |||
| 50 | /* The ciphertext from MLKEM_encap. */ | ||
| 51 | uint8_t *mlkem_encap; | ||
| 52 | size_t mlkem_encap_len; | ||
| 53 | |||
| 54 | /* The shared secret from an ML-KEM encapsulation. */ | ||
| 55 | uint8_t *mlkem_shared_secret; | ||
| 56 | size_t mlkem_shared_secret_len; | ||
| 43 | }; | 57 | }; |
| 44 | 58 | ||
| 45 | static struct tls_key_share * | 59 | static struct tls_key_share * |
| @@ -96,6 +110,12 @@ tls_key_share_free(struct tls_key_share *ks) | |||
| 96 | freezero(ks->x25519_private, X25519_KEY_LENGTH); | 110 | freezero(ks->x25519_private, X25519_KEY_LENGTH); |
| 97 | freezero(ks->x25519_peer_public, X25519_KEY_LENGTH); | 111 | freezero(ks->x25519_peer_public, X25519_KEY_LENGTH); |
| 98 | 112 | ||
| 113 | freezero(ks->mlkem_public, ks->mlkem_public_len); | ||
| 114 | MLKEM_private_key_free(ks->mlkem_private); | ||
| 115 | MLKEM_public_key_free(ks->mlkem_peer_public); | ||
| 116 | freezero(ks->mlkem_encap, ks->mlkem_encap_len); | ||
| 117 | freezero(ks->mlkem_shared_secret, ks->mlkem_shared_secret_len); | ||
| 118 | |||
| 99 | freezero(ks, sizeof(*ks)); | 119 | freezero(ks, sizeof(*ks)); |
| 100 | } | 120 | } |
| 101 | 121 | ||
| @@ -230,7 +250,73 @@ tls_key_share_generate_x25519(struct tls_key_share *ks) | |||
| 230 | return ret; | 250 | return ret; |
| 231 | } | 251 | } |
| 232 | 252 | ||
| 233 | int | 253 | static int |
| 254 | tls_key_share_generate_mlkem(struct tls_key_share *ks, int rank) | ||
| 255 | { | ||
| 256 | MLKEM_private_key *private = NULL; | ||
| 257 | uint8_t *public = NULL; | ||
| 258 | size_t p_len = 0; | ||
| 259 | int ret = 0; | ||
| 260 | |||
| 261 | if (ks->mlkem_public != NULL || ks->mlkem_private != NULL) | ||
| 262 | goto err; | ||
| 263 | |||
| 264 | if ((private = MLKEM_private_key_new(rank)) == NULL) | ||
| 265 | goto err; | ||
| 266 | |||
| 267 | if (!MLKEM_generate_key(private, &public, &p_len, NULL, NULL)) | ||
| 268 | goto err; | ||
| 269 | |||
| 270 | ks->mlkem_public = public; | ||
| 271 | ks->mlkem_public_len = p_len; | ||
| 272 | ks->mlkem_private = private; | ||
| 273 | public = NULL; | ||
| 274 | private = NULL; | ||
| 275 | |||
| 276 | ret = 1; | ||
| 277 | |||
| 278 | err: | ||
| 279 | freezero(public, p_len); | ||
| 280 | MLKEM_private_key_free(private); | ||
| 281 | |||
| 282 | return ret; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int | ||
| 286 | tls_key_share_client_generate_mlkem768x25519(struct tls_key_share *ks) | ||
| 287 | { | ||
| 288 | if (!tls_key_share_generate_mlkem(ks, RANK768)) | ||
| 289 | return 0; | ||
| 290 | |||
| 291 | if (!tls_key_share_generate_x25519(ks)) | ||
| 292 | return 0; | ||
| 293 | |||
| 294 | return 1; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int | ||
| 298 | tls_key_share_server_generate_mlkem768x25519(struct tls_key_share *ks) | ||
| 299 | { | ||
| 300 | if (ks->mlkem_private != NULL) | ||
| 301 | return 0; | ||
| 302 | |||
| 303 | /* The server side needs the client's parsed share */ | ||
| 304 | |||
| 305 | if (ks->x25519_peer_public == NULL) | ||
| 306 | return 0; | ||
| 307 | |||
| 308 | if (ks->mlkem_peer_public == NULL) | ||
| 309 | return 0; | ||
| 310 | |||
| 311 | if (!tls_key_share_generate_x25519(ks)) | ||
| 312 | return 0; | ||
| 313 | |||
| 314 | return MLKEM_encap(ks->mlkem_peer_public, &ks->mlkem_encap, | ||
| 315 | &ks->mlkem_encap_len, &ks->mlkem_shared_secret, | ||
| 316 | &ks->mlkem_shared_secret_len); | ||
| 317 | } | ||
| 318 | |||
| 319 | static int | ||
| 234 | tls_key_share_generate(struct tls_key_share *ks) | 320 | tls_key_share_generate(struct tls_key_share *ks) |
| 235 | { | 321 | { |
| 236 | if (ks->nid == NID_dhKeyAgreement) | 322 | if (ks->nid == NID_dhKeyAgreement) |
| @@ -242,6 +328,24 @@ tls_key_share_generate(struct tls_key_share *ks) | |||
| 242 | return tls_key_share_generate_ecdhe_ecp(ks); | 328 | return tls_key_share_generate_ecdhe_ecp(ks); |
| 243 | } | 329 | } |
| 244 | 330 | ||
| 331 | int | ||
| 332 | tls_key_share_client_generate(struct tls_key_share *ks) | ||
| 333 | { | ||
| 334 | if (ks->nid == NID_X25519MLKEM768) | ||
| 335 | return tls_key_share_client_generate_mlkem768x25519(ks); | ||
| 336 | |||
| 337 | return tls_key_share_generate(ks); | ||
| 338 | } | ||
| 339 | |||
| 340 | int | ||
| 341 | tls_key_share_server_generate(struct tls_key_share *ks) | ||
| 342 | { | ||
| 343 | if (ks->nid == NID_X25519MLKEM768) | ||
| 344 | return tls_key_share_server_generate_mlkem768x25519(ks); | ||
| 345 | |||
| 346 | return tls_key_share_generate(ks); | ||
| 347 | } | ||
| 348 | |||
| 245 | static int | 349 | static int |
| 246 | tls_key_share_params_dhe(struct tls_key_share *ks, CBB *cbb) | 350 | tls_key_share_params_dhe(struct tls_key_share *ks, CBB *cbb) |
| 247 | { | 351 | { |
| @@ -287,6 +391,47 @@ tls_key_share_public_x25519(struct tls_key_share *ks, CBB *cbb) | |||
| 287 | return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); | 391 | return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); |
| 288 | } | 392 | } |
| 289 | 393 | ||
| 394 | static int | ||
| 395 | tls_key_share_public_mlkem768x25519(struct tls_key_share *ks, CBB *cbb) | ||
| 396 | { | ||
| 397 | uint8_t *mlkem_part; | ||
| 398 | size_t mlkem_part_len; | ||
| 399 | |||
| 400 | if (ks->x25519_public == NULL) | ||
| 401 | return 0; | ||
| 402 | |||
| 403 | /* | ||
| 404 | * https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/ | ||
| 405 | * Section 3.1.2: | ||
| 406 | * The server's key exchange value is the concatenation of an | ||
| 407 | * ML-KEM ciphertext returned from encapsulation to the client's | ||
| 408 | * encapsulation key, and the server's ephemeral X25519 share. | ||
| 409 | */ | ||
| 410 | mlkem_part = ks->mlkem_encap; | ||
| 411 | mlkem_part_len = ks->mlkem_encap_len; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/ | ||
| 415 | * Section 3.1.1: | ||
| 416 | * The client's key_exchange value is the concatenation of the | ||
| 417 | * client's ML-KEM-768 encapsulation key and the client's X25519 | ||
| 418 | * ephemeral share. | ||
| 419 | */ | ||
| 420 | if (mlkem_part == NULL) { | ||
| 421 | mlkem_part = ks->mlkem_public; | ||
| 422 | mlkem_part_len = ks->mlkem_public_len; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (mlkem_part == NULL) | ||
| 426 | return 0; | ||
| 427 | |||
| 428 | if (!CBB_add_bytes(cbb, mlkem_part, mlkem_part_len)) | ||
| 429 | return 0; | ||
| 430 | |||
| 431 | /* Both the client and server send their x25519 public keys. */ | ||
| 432 | return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); | ||
| 433 | } | ||
| 434 | |||
| 290 | int | 435 | int |
| 291 | tls_key_share_public(struct tls_key_share *ks, CBB *cbb) | 436 | tls_key_share_public(struct tls_key_share *ks, CBB *cbb) |
| 292 | { | 437 | { |
| @@ -296,6 +441,9 @@ tls_key_share_public(struct tls_key_share *ks, CBB *cbb) | |||
| 296 | if (ks->nid == NID_X25519) | 441 | if (ks->nid == NID_X25519) |
| 297 | return tls_key_share_public_x25519(ks, cbb); | 442 | return tls_key_share_public_x25519(ks, cbb); |
| 298 | 443 | ||
| 444 | if (ks->nid == NID_X25519MLKEM768) | ||
| 445 | return tls_key_share_public_mlkem768x25519(ks, cbb); | ||
| 446 | |||
| 299 | return tls_key_share_public_ecdhe_ecp(ks, cbb); | 447 | return tls_key_share_public_ecdhe_ecp(ks, cbb); |
| 300 | } | 448 | } |
| 301 | 449 | ||
| @@ -325,7 +473,7 @@ tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, | |||
| 325 | return 0; | 473 | return 0; |
| 326 | 474 | ||
| 327 | return tls_key_share_peer_params_dhe(ks, cbs, decode_error, | 475 | return tls_key_share_peer_params_dhe(ks, cbs, decode_error, |
| 328 | invalid_params); | 476 | invalid_params); |
| 329 | } | 477 | } |
| 330 | 478 | ||
| 331 | static int | 479 | static int |
| @@ -383,7 +531,91 @@ tls_key_share_peer_public_x25519(struct tls_key_share *ks, CBS *cbs, | |||
| 383 | return CBS_stow(cbs, &ks->x25519_peer_public, &out_len); | 531 | return CBS_stow(cbs, &ks->x25519_peer_public, &out_len); |
| 384 | } | 532 | } |
| 385 | 533 | ||
| 386 | int | 534 | static int |
| 535 | tls_key_share_client_peer_public_mlkem768x25519(struct tls_key_share *ks, | ||
| 536 | CBS *cbs, int *decode_error) | ||
| 537 | { | ||
| 538 | CBS x25519_cbs, mlkem_ciphertext_cbs; | ||
| 539 | size_t out_len; | ||
| 540 | |||
| 541 | if (ks->mlkem_shared_secret != NULL) | ||
| 542 | return 0; | ||
| 543 | |||
| 544 | if (ks->mlkem_private == NULL) | ||
| 545 | return 0; | ||
| 546 | |||
| 547 | if (!CBS_get_bytes(cbs, &mlkem_ciphertext_cbs, | ||
| 548 | MLKEM_private_key_ciphertext_length(ks->mlkem_private))) | ||
| 549 | return 0; | ||
| 550 | |||
| 551 | if (!CBS_get_bytes(cbs, &x25519_cbs, X25519_KEY_LENGTH)) | ||
| 552 | return 0; | ||
| 553 | |||
| 554 | if (CBS_len(cbs) != 0) | ||
| 555 | return 0; | ||
| 556 | |||
| 557 | if (!CBS_stow(&x25519_cbs, &ks->x25519_peer_public, &out_len)) | ||
| 558 | return 0; | ||
| 559 | |||
| 560 | if (!CBS_stow(&mlkem_ciphertext_cbs, &ks->mlkem_encap, &ks->mlkem_encap_len)) | ||
| 561 | return 0; | ||
| 562 | |||
| 563 | return 1; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int | ||
| 567 | tls_key_share_server_peer_public_mlkem768x25519(struct tls_key_share *ks, | ||
| 568 | CBS *cbs, int *decode_error) | ||
| 569 | { | ||
| 570 | CBS x25519_cbs, mlkem768_cbs; | ||
| 571 | size_t out_len; | ||
| 572 | |||
| 573 | *decode_error = 0; | ||
| 574 | |||
| 575 | /* The server should not have an mlkem private key */ | ||
| 576 | if (ks->mlkem_private != NULL) | ||
| 577 | return 0; | ||
| 578 | |||
| 579 | if (ks->mlkem_shared_secret != NULL) | ||
| 580 | return 0; | ||
| 581 | |||
| 582 | if (ks->mlkem_peer_public != NULL) | ||
| 583 | return 0; | ||
| 584 | |||
| 585 | if (ks->x25519_peer_public != NULL) | ||
| 586 | return 0; | ||
| 587 | |||
| 588 | /* Nein, ist nur normal (1024 ist gigantisch) */ | ||
| 589 | if ((ks->mlkem_peer_public = MLKEM_public_key_new(RANK768)) == NULL) | ||
| 590 | goto err; | ||
| 591 | |||
| 592 | if (!CBS_get_bytes(cbs, &mlkem768_cbs, | ||
| 593 | MLKEM_public_key_encoded_length(ks->mlkem_peer_public))) | ||
| 594 | goto err; | ||
| 595 | |||
| 596 | if (!CBS_get_bytes(cbs, &x25519_cbs, X25519_KEY_LENGTH)) | ||
| 597 | goto err; | ||
| 598 | |||
| 599 | if (CBS_len(cbs) != 0) | ||
| 600 | goto err; | ||
| 601 | |||
| 602 | if (!CBS_stow(&x25519_cbs, &ks->x25519_peer_public, &out_len)) | ||
| 603 | goto err; | ||
| 604 | |||
| 605 | /* Poetische */ | ||
| 606 | if (!MLKEM_parse_public_key(ks->mlkem_peer_public, | ||
| 607 | CBS_data(&mlkem768_cbs), CBS_len(&mlkem768_cbs))) | ||
| 608 | goto err; | ||
| 609 | |||
| 610 | return 1; | ||
| 611 | |||
| 612 | err: | ||
| 613 | *decode_error = 1; | ||
| 614 | |||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | static int | ||
| 387 | tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, int *decode_error, | 619 | tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, int *decode_error, |
| 388 | int *invalid_key) | 620 | int *invalid_key) |
| 389 | { | 621 | { |
| @@ -402,6 +634,30 @@ tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, int *decode_error, | |||
| 402 | return tls_key_share_peer_public_ecdhe_ecp(ks, cbs); | 634 | return tls_key_share_peer_public_ecdhe_ecp(ks, cbs); |
| 403 | } | 635 | } |
| 404 | 636 | ||
| 637 | /* Called from client to process a server peer */ | ||
| 638 | int | ||
| 639 | tls_key_share_client_peer_public(struct tls_key_share *ks, CBS *cbs, | ||
| 640 | int *decode_error, int *invalid_key) | ||
| 641 | { | ||
| 642 | if (ks->nid == NID_X25519MLKEM768) | ||
| 643 | return tls_key_share_client_peer_public_mlkem768x25519(ks, cbs, | ||
| 644 | decode_error); | ||
| 645 | |||
| 646 | return tls_key_share_peer_public(ks, cbs, decode_error, invalid_key); | ||
| 647 | } | ||
| 648 | |||
| 649 | /* Called from server to process a client peer */ | ||
| 650 | int | ||
| 651 | tls_key_share_server_peer_public(struct tls_key_share *ks, CBS *cbs, | ||
| 652 | int *decode_error, int *invalid_key) | ||
| 653 | { | ||
| 654 | if (ks->nid == NID_X25519MLKEM768) | ||
| 655 | return tls_key_share_server_peer_public_mlkem768x25519(ks, cbs, | ||
| 656 | decode_error); | ||
| 657 | |||
| 658 | return tls_key_share_peer_public(ks, cbs, decode_error, invalid_key); | ||
| 659 | } | ||
| 660 | |||
| 405 | static int | 661 | static int |
| 406 | tls_key_share_derive_dhe(struct tls_key_share *ks, | 662 | tls_key_share_derive_dhe(struct tls_key_share *ks, |
| 407 | uint8_t **shared_key, size_t *shared_key_len) | 663 | uint8_t **shared_key, size_t *shared_key_len) |
| @@ -451,6 +707,65 @@ tls_key_share_derive_x25519(struct tls_key_share *ks, | |||
| 451 | return ret; | 707 | return ret; |
| 452 | } | 708 | } |
| 453 | 709 | ||
| 710 | /* | ||
| 711 | * https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/ | ||
| 712 | * Section 3.1.3: | ||
| 713 | * For X25519MLKEM768, the shared secret is the concatenation of the ML-KEM | ||
| 714 | * shared secret and the X25519 shared secret. | ||
| 715 | */ | ||
| 716 | static int | ||
| 717 | tls_key_share_derive_mlkem768x25519(struct tls_key_share *ks, | ||
| 718 | uint8_t **out_shared_key, size_t *out_shared_key_len) | ||
| 719 | { | ||
| 720 | uint8_t *x25519_shared_key; | ||
| 721 | CBB cbb; | ||
| 722 | |||
| 723 | memset(&cbb, 0, sizeof(cbb)); | ||
| 724 | |||
| 725 | if (ks->x25519_private == NULL) | ||
| 726 | goto err; | ||
| 727 | |||
| 728 | if (ks->x25519_peer_public == NULL) | ||
| 729 | goto err; | ||
| 730 | |||
| 731 | if (ks->mlkem_shared_secret == NULL) { | ||
| 732 | if (ks->mlkem_private == NULL) | ||
| 733 | goto err; | ||
| 734 | |||
| 735 | if (ks->mlkem_encap == NULL) | ||
| 736 | goto err; | ||
| 737 | |||
| 738 | if (!MLKEM_decap(ks->mlkem_private, ks->mlkem_encap, | ||
| 739 | MLKEM_private_key_ciphertext_length(ks->mlkem_private), | ||
| 740 | &ks->mlkem_shared_secret, &ks->mlkem_shared_secret_len)) | ||
| 741 | goto err; | ||
| 742 | } | ||
| 743 | |||
| 744 | if (!CBB_init(&cbb, ks->mlkem_shared_secret_len + X25519_KEY_LENGTH)) | ||
| 745 | goto err; | ||
| 746 | |||
| 747 | if (!CBB_add_bytes(&cbb, ks->mlkem_shared_secret, | ||
| 748 | ks->mlkem_shared_secret_len)) | ||
| 749 | goto err; | ||
| 750 | |||
| 751 | if (!CBB_add_space(&cbb, &x25519_shared_key, X25519_KEY_LENGTH)) | ||
| 752 | goto err; | ||
| 753 | |||
| 754 | if (!X25519(x25519_shared_key, ks->x25519_private, | ||
| 755 | ks->x25519_peer_public)) | ||
| 756 | goto err; | ||
| 757 | |||
| 758 | if (!CBB_finish(&cbb, out_shared_key, out_shared_key_len)) | ||
| 759 | goto err; | ||
| 760 | |||
| 761 | return 1; | ||
| 762 | |||
| 763 | err: | ||
| 764 | CBB_cleanup(&cbb); | ||
| 765 | |||
| 766 | return 0; | ||
| 767 | } | ||
| 768 | |||
| 454 | int | 769 | int |
| 455 | tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, | 770 | tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, |
| 456 | size_t *shared_key_len) | 771 | size_t *shared_key_len) |
| @@ -468,6 +783,10 @@ tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, | |||
| 468 | return tls_key_share_derive_x25519(ks, shared_key, | 783 | return tls_key_share_derive_x25519(ks, shared_key, |
| 469 | shared_key_len); | 784 | shared_key_len); |
| 470 | 785 | ||
| 786 | if (ks->nid == NID_X25519MLKEM768) | ||
| 787 | return tls_key_share_derive_mlkem768x25519(ks, shared_key, | ||
| 788 | shared_key_len); | ||
| 789 | |||
| 471 | return tls_key_share_derive_ecdhe_ecp(ks, shared_key, | 790 | return tls_key_share_derive_ecdhe_ecp(ks, shared_key, |
| 472 | shared_key_len); | 791 | shared_key_len); |
| 473 | } | 792 | } |
