diff options
author | 2020-01-30 16:25:09 +0000 | |
---|---|---|
committer | 2020-01-30 16:25:09 +0000 | |
commit | 69428dcae83cc2110bdec85102a22da1502f1acd (patch) | |
tree | 05c6402225d05668e7659acdaa57cfff8dd6b1cf /lib/libssl/ssl_kex.c | |
parent | add a short EXAMPLES section; (diff) | |
download | wireguard-openbsd-69428dcae83cc2110bdec85102a22da1502f1acd.tar.xz wireguard-openbsd-69428dcae83cc2110bdec85102a22da1502f1acd.zip |
Factor out/rewrite the ECDHE EC point key exchange code.
This reduces replication between the existing TLS client/server and allows
the code to soon be reused for TLSv1.3.
With feedback from inoguchi@ and tb@
ok inoguchi@ tb@
Diffstat (limited to 'lib/libssl/ssl_kex.c')
-rw-r--r-- | lib/libssl/ssl_kex.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/lib/libssl/ssl_kex.c b/lib/libssl/ssl_kex.c new file mode 100644 index 00000000000..439c1702b32 --- /dev/null +++ b/lib/libssl/ssl_kex.c @@ -0,0 +1,141 @@ +/* $OpenBSD: ssl_kex.c,v 1.1 2020/01/30 16:25:09 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/ec.h> +#include <openssl/ecdh.h> + +#include "bytestring.h" + +int +ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid) +{ + EC_GROUP *group; + int ret = 0; + + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) + goto err; + + if (!EC_KEY_set_group(ecdh, group)) + goto err; + if (!EC_KEY_generate_key(ecdh)) + goto err; + + ret = 1; + + err: + EC_GROUP_free(group); + + return ret; +} + +int +ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) +{ + const EC_GROUP *group; + const EC_POINT *point; + uint8_t *ecp; + size_t ecp_len; + int ret = 0; + + if ((group = EC_KEY_get0_group(ecdh)) == NULL) + goto err; + if ((point = EC_KEY_get0_public_key(ecdh)) == NULL) + goto err; + + if ((ecp_len = EC_POINT_point2oct(group, point, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) + goto err; + if (!CBB_add_space(cbb, &ecp, ecp_len)) + goto err; + if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + ecp, ecp_len, NULL)) == 0) + goto err; + + ret = 1; + + err: + return ret; +} + +int +ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs) +{ + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + int ret = 0; + + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) + goto err; + + if (!EC_KEY_set_group(ecdh, group)) + goto err; + + if ((point = EC_POINT_new(group)) == NULL) + goto err; + if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), + NULL) == 0) + goto err; + if (!EC_KEY_set_public_key(ecdh, point)) + goto err; + + ret = 1; + + err: + EC_GROUP_free(group); + EC_POINT_free(point); + + return ret; +} + +int +ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, + uint8_t **shared_key, size_t *shared_key_len) +{ + const EC_POINT *point; + uint8_t *sk = NULL; + int sk_len = 0; + int ret = 0; + + if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) + goto err; + if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL)) + goto err; + + if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) + goto err; + + if ((sk_len = ECDH_size(ecdh)) <= 0) + goto err; + if ((sk = calloc(1, sk_len)) == NULL) + goto err; + + if (ECDH_compute_key(sk, sk_len, point, ecdh, NULL) <= 0) + goto err; + + *shared_key = sk; + *shared_key_len = sk_len; + sk = NULL; + + ret = 1; + + err: + freezero(sk, sk_len); + + return ret; +} |