-# $OpenBSD: Makefile,v 1.72 2021/10/23 13:12:14 jsing Exp $
+# $OpenBSD: Makefile,v 1.73 2022/01/05 17:10:02 jsing Exp $
.include <bsd.own.mk>
.ifndef NOMAN
tls13_handshake.c \
tls13_handshake_msg.c \
tls13_key_schedule.c \
- tls13_key_share.c \
tls13_legacy.c \
tls13_lib.c \
tls13_record.c \
tls13_record_layer.c \
tls13_server.c \
tls_buffer.c \
- tls_content.c
+ tls_content.c \
+ tls_key_share.c
HDRS= dtls1.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h tls1.h
-/* $OpenBSD: s3_lib.c,v 1.219 2021/11/02 13:59:29 tb Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.220 2022/01/05 17:10:02 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
EC_KEY_free(S3I(s)->tmp.ecdh);
freezero(S3I(s)->tmp.x25519, X25519_KEY_LENGTH);
- tls13_key_share_free(S3I(s)->hs.tls13.key_share);
+ tls_key_share_free(S3I(s)->hs.key_share);
+
tls13_secrets_destroy(S3I(s)->hs.tls13.secrets);
freezero(S3I(s)->hs.tls13.cookie, S3I(s)->hs.tls13.cookie_len);
tls13_clienthello_hash_clear(&S3I(s)->hs.tls13);
S3I(s)->hs.sigalgs = NULL;
S3I(s)->hs.sigalgs_len = 0;
- tls13_key_share_free(S3I(s)->hs.tls13.key_share);
- S3I(s)->hs.tls13.key_share = NULL;
+ tls_key_share_free(S3I(s)->hs.key_share);
+ S3I(s)->hs.key_share = NULL;
tls13_secrets_destroy(S3I(s)->hs.tls13.secrets);
S3I(s)->hs.tls13.secrets = NULL;
} else if (sc->peer_x25519_tmp != NULL) {
if (!ssl_kex_dummy_ecdhe_x25519(pkey))
goto err;
- } else if (S3I(s)->hs.tls13.key_share != NULL) {
- if (!tls13_key_share_peer_pkey(S3I(s)->hs.tls13.key_share,
+ } else if (S3I(s)->hs.key_share != NULL) {
+ if (!tls_key_share_peer_pkey(S3I(s)->hs.key_share,
pkey))
goto err;
} else {
-/* $OpenBSD: ssl_locl.h,v 1.372 2021/12/04 14:03:22 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.373 2022/01/05 17:10:02 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
uint16_t server_version;
uint16_t server_group;
- struct tls13_key_share *key_share;
struct tls13_secrets *secrets;
uint8_t *cookie;
uint8_t *sigalgs;
size_t sigalgs_len;
+ /* Key share for ephemeral key exchange. */
+ struct tls_key_share *key_share;
+
/*
* Copies of the verify data sent in our finished message and the
* verify data received in the finished message sent by our peer.
-/* $OpenBSD: ssl_tlsext.c,v 1.103 2022/01/04 11:01:58 jsing Exp $ */
+/* $OpenBSD: ssl_tlsext.c,v 1.104 2022/01/05 17:10:02 jsing Exp $ */
/*
* Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
return 0;
if (!CBB_add_u16(&client_shares,
- tls13_key_share_group(S3I(s)->hs.tls13.key_share)))
+ tls_key_share_group(S3I(s)->hs.key_share)))
return 0;
if (!CBB_add_u16_length_prefixed(&client_shares, &key_exchange))
return 0;
- if (!tls13_key_share_public(S3I(s)->hs.tls13.key_share, &key_exchange))
+ if (!tls_key_share_public(S3I(s)->hs.key_share, &key_exchange))
return 0;
if (!CBB_flush(cbb))
*/
if (S3I(s)->hs.our_max_tls_version < TLS1_3_VERSION)
continue;
- if (S3I(s)->hs.tls13.key_share != NULL)
+ if (S3I(s)->hs.key_share != NULL)
continue;
/* XXX - consider implementing server preference. */
continue;
/* Decode and store the selected key share. */
- S3I(s)->hs.tls13.key_share = tls13_key_share_new(group);
- if (S3I(s)->hs.tls13.key_share == NULL)
+ S3I(s)->hs.key_share = tls_key_share_new(group);
+ if (S3I(s)->hs.key_share == NULL)
goto err;
- if (!tls13_key_share_peer_public(S3I(s)->hs.tls13.key_share,
+ if (!tls_key_share_peer_public(S3I(s)->hs.key_share,
group, &key_exchange))
goto err;
}
return CBB_add_u16(cbb, S3I(s)->hs.tls13.server_group);
}
- if (S3I(s)->hs.tls13.key_share == NULL)
+ if (S3I(s)->hs.key_share == NULL)
return 0;
- if (!CBB_add_u16(cbb, tls13_key_share_group(S3I(s)->hs.tls13.key_share)))
+ if (!CBB_add_u16(cbb, tls_key_share_group(S3I(s)->hs.key_share)))
return 0;
if (!CBB_add_u16_length_prefixed(cbb, &key_exchange))
return 0;
- if (!tls13_key_share_public(S3I(s)->hs.tls13.key_share, &key_exchange))
+ if (!tls_key_share_public(S3I(s)->hs.key_share, &key_exchange))
return 0;
if (!CBB_flush(cbb))
if (!CBS_get_u16_length_prefixed(cbs, &key_exchange))
return 0;
- if (S3I(s)->hs.tls13.key_share == NULL)
+ if (S3I(s)->hs.key_share == NULL)
return 0;
- if (!tls13_key_share_peer_public(S3I(s)->hs.tls13.key_share,
+ if (!tls_key_share_peer_public(S3I(s)->hs.key_share,
group, &key_exchange))
goto err;
-/* $OpenBSD: tls13_client.c,v 1.88 2021/10/25 10:01:46 jsing Exp $ */
+/* $OpenBSD: tls13_client.c,v 1.89 2022/01/05 17:10:02 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
tls1_get_group_list(s, 0, &groups, &groups_len);
if (groups_len < 1)
return 0;
- if ((ctx->hs->tls13.key_share = tls13_key_share_new(groups[0])) == NULL)
+ if ((ctx->hs->key_share = tls_key_share_new(groups[0])) == NULL)
return 0;
- if (!tls13_key_share_generate(ctx->hs->tls13.key_share))
+ if (!tls_key_share_generate(ctx->hs->key_share))
return 0;
arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE);
/* Derive the shared key and engage record protection. */
- if (!tls13_key_share_derive(ctx->hs->tls13.key_share, &shared_key,
+ if (!tls_key_share_derive(ctx->hs->key_share, &shared_key,
&shared_key_len))
goto err;
*/
if (!tls1_check_curve(ctx->ssl, ctx->hs->tls13.server_group))
return 0; /* XXX alert */
- if (ctx->hs->tls13.server_group == tls13_key_share_group(ctx->hs->tls13.key_share))
+ if (ctx->hs->tls13.server_group == tls_key_share_group(ctx->hs->key_share))
return 0; /* XXX alert */
/* Switch to new key share. */
- tls13_key_share_free(ctx->hs->tls13.key_share);
- if ((ctx->hs->tls13.key_share =
- tls13_key_share_new(ctx->hs->tls13.server_group)) == NULL)
+ tls_key_share_free(ctx->hs->key_share);
+ if ((ctx->hs->key_share =
+ tls_key_share_new(ctx->hs->tls13.server_group)) == NULL)
return 0;
- if (!tls13_key_share_generate(ctx->hs->tls13.key_share))
+ if (!tls_key_share_generate(ctx->hs->key_share))
return 0;
if (!tls13_client_hello_build(ctx, cbb))
-/* $OpenBSD: tls13_internal.h,v 1.95 2021/10/23 13:12:14 jsing Exp $ */
+/* $OpenBSD: tls13_internal.h,v 1.96 2022/01/05 17:10:02 jsing Exp $ */
/*
* Copyright (c) 2018 Bob Beck <beck@openbsd.org>
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
int tls13_update_client_traffic_secret(struct tls13_secrets *secrets);
int tls13_update_server_traffic_secret(struct tls13_secrets *secrets);
-/*
- * Key shares.
- */
-struct tls13_key_share;
-
-struct tls13_key_share *tls13_key_share_new(uint16_t group_id);
-struct tls13_key_share *tls13_key_share_new_nid(int nid);
-void tls13_key_share_free(struct tls13_key_share *ks);
-
-uint16_t tls13_key_share_group(struct tls13_key_share *ks);
-int tls13_key_share_peer_pkey(struct tls13_key_share *ks, EVP_PKEY *pkey);
-int tls13_key_share_generate(struct tls13_key_share *ks);
-int tls13_key_share_public(struct tls13_key_share *ks, CBB *cbb);
-int tls13_key_share_peer_public(struct tls13_key_share *ks, uint16_t group,
- CBS *cbs);
-int tls13_key_share_derive(struct tls13_key_share *ks, uint8_t **shared_key,
- size_t *shared_key_len);
-
/*
* Record Layer.
*/
+++ /dev/null
-/* $OpenBSD: tls13_key_share.c,v 1.7 2022/01/04 11:01:58 jsing Exp $ */
-/*
- * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdlib.h>
-
-#include <openssl/curve25519.h>
-
-#include "bytestring.h"
-#include "ssl_locl.h"
-#include "tls13_internal.h"
-
-struct tls13_key_share {
- int nid;
- uint16_t group_id;
-
- EC_KEY *ecdhe;
- EC_KEY *ecdhe_peer;
-
- uint8_t *x25519_public;
- uint8_t *x25519_private;
- uint8_t *x25519_peer_public;
-};
-
-struct tls13_key_share *
-tls13_key_share_new(uint16_t group_id)
-{
- struct tls13_key_share *ks;
- int nid;
-
- if ((nid = tls1_ec_curve_id2nid(group_id)) == 0)
- return NULL;
-
- if ((ks = calloc(1, sizeof(struct tls13_key_share))) == NULL)
- return NULL;
-
- ks->group_id = group_id;
- ks->nid = nid;
-
- return ks;
-}
-
-struct tls13_key_share *
-tls13_key_share_new_nid(int nid)
-{
- uint16_t group_id;
-
- if ((group_id = tls1_ec_nid2curve_id(nid)) == 0)
- return NULL;
-
- return tls13_key_share_new(group_id);
-}
-
-void
-tls13_key_share_free(struct tls13_key_share *ks)
-{
- if (ks == NULL)
- return;
-
- EC_KEY_free(ks->ecdhe);
- EC_KEY_free(ks->ecdhe_peer);
-
- freezero(ks->x25519_public, X25519_KEY_LENGTH);
- freezero(ks->x25519_private, X25519_KEY_LENGTH);
- freezero(ks->x25519_peer_public, X25519_KEY_LENGTH);
-
- freezero(ks, sizeof(*ks));
-}
-
-uint16_t
-tls13_key_share_group(struct tls13_key_share *ks)
-{
- return ks->group_id;
-}
-
-int
-tls13_key_share_peer_pkey(struct tls13_key_share *ks, EVP_PKEY *pkey)
-{
- if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) {
- if (!ssl_kex_dummy_ecdhe_x25519(pkey))
- return 0;
- } else if (ks->ecdhe_peer != NULL) {
- if (!EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer))
- return 0;
- } else {
- return 0;
- }
-
- return 1;
-}
-
-static int
-tls13_key_share_generate_ecdhe_ecp(struct tls13_key_share *ks)
-{
- EC_KEY *ecdhe = NULL;
- int ret = 0;
-
- if (ks->ecdhe != NULL)
- goto err;
-
- if ((ecdhe = EC_KEY_new()) == NULL)
- goto err;
- if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid))
- goto err;
-
- ks->ecdhe = ecdhe;
- ecdhe = NULL;
-
- ret = 1;
-
- err:
- EC_KEY_free(ecdhe);
-
- return ret;
-}
-
-static int
-tls13_key_share_generate_x25519(struct tls13_key_share *ks)
-{
- uint8_t *public = NULL, *private = NULL;
- int ret = 0;
-
- if (ks->x25519_public != NULL || ks->x25519_private != NULL)
- goto err;
-
- if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL)
- goto err;
- if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL)
- goto err;
-
- X25519_keypair(public, private);
-
- ks->x25519_public = public;
- ks->x25519_private = private;
- public = NULL;
- private = NULL;
-
- ret = 1;
-
- err:
- freezero(public, X25519_KEY_LENGTH);
- freezero(private, X25519_KEY_LENGTH);
-
- return ret;
-}
-
-int
-tls13_key_share_generate(struct tls13_key_share *ks)
-{
- if (ks->nid == NID_X25519)
- return tls13_key_share_generate_x25519(ks);
-
- return tls13_key_share_generate_ecdhe_ecp(ks);
-}
-
-static int
-tls13_key_share_public_ecdhe_ecp(struct tls13_key_share *ks, CBB *cbb)
-{
- if (ks->ecdhe == NULL)
- return 0;
-
- return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb);
-}
-
-static int
-tls13_key_share_public_x25519(struct tls13_key_share *ks, CBB *cbb)
-{
- if (ks->x25519_public == NULL)
- return 0;
-
- return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH);
-}
-
-int
-tls13_key_share_public(struct tls13_key_share *ks, CBB *cbb)
-{
- if (ks->nid == NID_X25519)
- return tls13_key_share_public_x25519(ks, cbb);
-
- return tls13_key_share_public_ecdhe_ecp(ks, cbb);
-}
-
-static int
-tls13_key_share_peer_public_ecdhe_ecp(struct tls13_key_share *ks, CBS *cbs)
-{
- EC_KEY *ecdhe = NULL;
- int ret = 0;
-
- if (ks->ecdhe_peer != NULL)
- goto err;
-
- if ((ecdhe = EC_KEY_new()) == NULL)
- goto err;
- if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs))
- goto err;
-
- ks->ecdhe_peer = ecdhe;
- ecdhe = NULL;
-
- ret = 1;
-
- err:
- EC_KEY_free(ecdhe);
-
- return ret;
-}
-
-static int
-tls13_key_share_peer_public_x25519(struct tls13_key_share *ks, CBS *cbs)
-{
- size_t out_len;
-
- if (ks->x25519_peer_public != NULL)
- return 0;
-
- if (CBS_len(cbs) != X25519_KEY_LENGTH)
- return 0;
-
- return CBS_stow(cbs, &ks->x25519_peer_public, &out_len);
-}
-
-int
-tls13_key_share_peer_public(struct tls13_key_share *ks, uint16_t group,
- CBS *cbs)
-{
- if (ks->group_id != group)
- return 0;
-
- if (ks->nid == NID_X25519) {
- if (!tls13_key_share_peer_public_x25519(ks, cbs))
- return 0;
- } else {
- if (!tls13_key_share_peer_public_ecdhe_ecp(ks, cbs))
- return 0;
- }
-
- return 1;
-}
-
-static int
-tls13_key_share_derive_ecdhe_ecp(struct tls13_key_share *ks,
- uint8_t **shared_key, size_t *shared_key_len)
-{
- if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL)
- return 0;
-
- return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer,
- shared_key, shared_key_len);
-}
-
-static int
-tls13_key_share_derive_x25519(struct tls13_key_share *ks,
- uint8_t **shared_key, size_t *shared_key_len)
-{
- uint8_t *sk = NULL;
- int ret = 0;
-
- if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL)
- goto err;
-
- if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL)
- goto err;
- if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public))
- goto err;
-
- *shared_key = sk;
- *shared_key_len = X25519_KEY_LENGTH;
- sk = NULL;
-
- ret = 1;
-
- err:
- freezero(sk, X25519_KEY_LENGTH);
-
- return ret;
-}
-
-int
-tls13_key_share_derive(struct tls13_key_share *ks, uint8_t **shared_key,
- size_t *shared_key_len)
-{
- if (*shared_key != NULL)
- return 0;
-
- *shared_key_len = 0;
-
- if (ks->nid == NID_X25519)
- return tls13_key_share_derive_x25519(ks, shared_key,
- shared_key_len);
-
- return tls13_key_share_derive_ecdhe_ecp(ks, shared_key,
- shared_key_len);
-}
-/* $OpenBSD: tls13_server.c,v 1.89 2021/12/26 14:59:52 jsing Exp $ */
+/* $OpenBSD: tls13_server.c,v 1.90 2022/01/05 17:10:02 jsing Exp $ */
/*
* Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
* has been enabled. This would probably mean using either an
* INITIAL | WITHOUT_HRR state, or another intermediate state.
*/
- if (ctx->hs->tls13.key_share != NULL)
+ if (ctx->hs->key_share != NULL)
ctx->handshake_stage.hs_type |= NEGOTIATED | WITHOUT_HRR;
/* XXX - check this is the correct point */
SSL *s = ctx->ssl;
int ret = 0;
- if (!tls13_key_share_derive(ctx->hs->tls13.key_share,
+ if (!tls_key_share_derive(ctx->hs->key_share,
&shared_key, &shared_key_len))
goto err;
if (!tls13_synthetic_handshake_message(ctx))
return 0;
- if (ctx->hs->tls13.key_share != NULL)
+ if (ctx->hs->key_share != NULL)
return 0;
if ((nid = tls1_get_shared_curve(ctx->ssl)) == NID_undef)
return 0;
int
tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb)
{
- if (ctx->hs->tls13.key_share == NULL)
+ if (ctx->hs->key_share == NULL)
return 0;
- if (!tls13_key_share_generate(ctx->hs->tls13.key_share))
+ if (!tls_key_share_generate(ctx->hs->key_share))
return 0;
if (!tls13_servername_process(ctx))
return 0;
-/* $OpenBSD: tls_internal.h,v 1.1 2021/10/23 13:12:14 jsing Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.2 2022/01/05 17:10:03 jsing Exp $ */
/*
* Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org>
*
#ifndef HEADER_TLS_INTERNAL_H
#define HEADER_TLS_INTERNAL_H
+#include <openssl/evp.h>
+
#include "bytestring.h"
__BEGIN_HIDDEN_DECLS
void tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs);
int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len);
+/*
+ * Key shares.
+ */
+struct tls_key_share;
+
+struct tls_key_share *tls_key_share_new(uint16_t group_id);
+struct tls_key_share *tls_key_share_new_nid(int nid);
+void tls_key_share_free(struct tls_key_share *ks);
+
+uint16_t tls_key_share_group(struct tls_key_share *ks);
+int tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey);
+int tls_key_share_generate(struct tls_key_share *ks);
+int tls_key_share_public(struct tls_key_share *ks, CBB *cbb);
+int tls_key_share_peer_public(struct tls_key_share *ks, uint16_t group,
+ CBS *cbs);
+int tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key,
+ size_t *shared_key_len);
+
__END_HIDDEN_DECLS
#endif
--- /dev/null
+/* $OpenBSD: tls_key_share.c,v 1.1 2022/01/05 17:10:03 jsing Exp $ */
+/*
+ * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+
+#include <openssl/curve25519.h>
+#include <openssl/ec.h>
+
+#include "bytestring.h"
+#include "ssl_locl.h"
+#include "tls_internal.h"
+
+struct tls_key_share {
+ int nid;
+ uint16_t group_id;
+
+ EC_KEY *ecdhe;
+ EC_KEY *ecdhe_peer;
+
+ uint8_t *x25519_public;
+ uint8_t *x25519_private;
+ uint8_t *x25519_peer_public;
+};
+
+struct tls_key_share *
+tls_key_share_new(uint16_t group_id)
+{
+ struct tls_key_share *ks;
+ int nid;
+
+ if ((nid = tls1_ec_curve_id2nid(group_id)) == 0)
+ return NULL;
+
+ if ((ks = calloc(1, sizeof(struct tls_key_share))) == NULL)
+ return NULL;
+
+ ks->group_id = group_id;
+ ks->nid = nid;
+
+ return ks;
+}
+
+struct tls_key_share *
+tls_key_share_new_nid(int nid)
+{
+ uint16_t group_id;
+
+ if ((group_id = tls1_ec_nid2curve_id(nid)) == 0)
+ return NULL;
+
+ return tls_key_share_new(group_id);
+}
+
+void
+tls_key_share_free(struct tls_key_share *ks)
+{
+ if (ks == NULL)
+ return;
+
+ EC_KEY_free(ks->ecdhe);
+ EC_KEY_free(ks->ecdhe_peer);
+
+ freezero(ks->x25519_public, X25519_KEY_LENGTH);
+ freezero(ks->x25519_private, X25519_KEY_LENGTH);
+ freezero(ks->x25519_peer_public, X25519_KEY_LENGTH);
+
+ freezero(ks, sizeof(*ks));
+}
+
+uint16_t
+tls_key_share_group(struct tls_key_share *ks)
+{
+ return ks->group_id;
+}
+
+int
+tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey)
+{
+ if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) {
+ if (!ssl_kex_dummy_ecdhe_x25519(pkey))
+ return 0;
+ } else if (ks->ecdhe_peer != NULL) {
+ if (!EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer))
+ return 0;
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+tls_key_share_generate_ecdhe_ecp(struct tls_key_share *ks)
+{
+ EC_KEY *ecdhe = NULL;
+ int ret = 0;
+
+ if (ks->ecdhe != NULL)
+ goto err;
+
+ if ((ecdhe = EC_KEY_new()) == NULL)
+ goto err;
+ if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid))
+ goto err;
+
+ ks->ecdhe = ecdhe;
+ ecdhe = NULL;
+
+ ret = 1;
+
+ err:
+ EC_KEY_free(ecdhe);
+
+ return ret;
+}
+
+static int
+tls_key_share_generate_x25519(struct tls_key_share *ks)
+{
+ uint8_t *public = NULL, *private = NULL;
+ int ret = 0;
+
+ if (ks->x25519_public != NULL || ks->x25519_private != NULL)
+ goto err;
+
+ if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL)
+ goto err;
+ if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL)
+ goto err;
+
+ X25519_keypair(public, private);
+
+ ks->x25519_public = public;
+ ks->x25519_private = private;
+ public = NULL;
+ private = NULL;
+
+ ret = 1;
+
+ err:
+ freezero(public, X25519_KEY_LENGTH);
+ freezero(private, X25519_KEY_LENGTH);
+
+ return ret;
+}
+
+int
+tls_key_share_generate(struct tls_key_share *ks)
+{
+ if (ks->nid == NID_X25519)
+ return tls_key_share_generate_x25519(ks);
+
+ return tls_key_share_generate_ecdhe_ecp(ks);
+}
+
+static int
+tls_key_share_public_ecdhe_ecp(struct tls_key_share *ks, CBB *cbb)
+{
+ if (ks->ecdhe == NULL)
+ return 0;
+
+ return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb);
+}
+
+static int
+tls_key_share_public_x25519(struct tls_key_share *ks, CBB *cbb)
+{
+ if (ks->x25519_public == NULL)
+ return 0;
+
+ return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH);
+}
+
+int
+tls_key_share_public(struct tls_key_share *ks, CBB *cbb)
+{
+ if (ks->nid == NID_X25519)
+ return tls_key_share_public_x25519(ks, cbb);
+
+ return tls_key_share_public_ecdhe_ecp(ks, cbb);
+}
+
+static int
+tls_key_share_peer_public_ecdhe_ecp(struct tls_key_share *ks, CBS *cbs)
+{
+ EC_KEY *ecdhe = NULL;
+ int ret = 0;
+
+ if (ks->ecdhe_peer != NULL)
+ goto err;
+
+ if ((ecdhe = EC_KEY_new()) == NULL)
+ goto err;
+ if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs))
+ goto err;
+
+ ks->ecdhe_peer = ecdhe;
+ ecdhe = NULL;
+
+ ret = 1;
+
+ err:
+ EC_KEY_free(ecdhe);
+
+ return ret;
+}
+
+static int
+tls_key_share_peer_public_x25519(struct tls_key_share *ks, CBS *cbs)
+{
+ size_t out_len;
+
+ if (ks->x25519_peer_public != NULL)
+ return 0;
+
+ if (CBS_len(cbs) != X25519_KEY_LENGTH)
+ return 0;
+
+ return CBS_stow(cbs, &ks->x25519_peer_public, &out_len);
+}
+
+int
+tls_key_share_peer_public(struct tls_key_share *ks, uint16_t group,
+ CBS *cbs)
+{
+ if (ks->group_id != group)
+ return 0;
+
+ if (ks->nid == NID_X25519) {
+ if (!tls_key_share_peer_public_x25519(ks, cbs))
+ return 0;
+ } else {
+ if (!tls_key_share_peer_public_ecdhe_ecp(ks, cbs))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+tls_key_share_derive_ecdhe_ecp(struct tls_key_share *ks,
+ uint8_t **shared_key, size_t *shared_key_len)
+{
+ if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL)
+ return 0;
+
+ return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer,
+ shared_key, shared_key_len);
+}
+
+static int
+tls_key_share_derive_x25519(struct tls_key_share *ks,
+ uint8_t **shared_key, size_t *shared_key_len)
+{
+ uint8_t *sk = NULL;
+ int ret = 0;
+
+ if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL)
+ goto err;
+
+ if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL)
+ goto err;
+ if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public))
+ goto err;
+
+ *shared_key = sk;
+ *shared_key_len = X25519_KEY_LENGTH;
+ sk = NULL;
+
+ ret = 1;
+
+ err:
+ freezero(sk, X25519_KEY_LENGTH);
+
+ return ret;
+}
+
+int
+tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key,
+ size_t *shared_key_len)
+{
+ if (*shared_key != NULL)
+ return 0;
+
+ *shared_key_len = 0;
+
+ if (ks->nid == NID_X25519)
+ return tls_key_share_derive_x25519(ks, shared_key,
+ shared_key_len);
+
+ return tls_key_share_derive_ecdhe_ecp(ks, shared_key,
+ shared_key_len);
+}