.github
CMakeModules
dist
externals
FidelityFX-FSR
SDL
Vulkan-Headers
cmake-modules
cpp-httplib
cubeb
discord-rpc
dynarmic
ffmpeg
find-modules
getopt
glad
inih
libressl
crypto
include
ssl
CMakeLists.txt
VERSION
bio_ssl.c
bs_ber.c
bs_cbb.c
bs_cbs.c
bytestring.h
d1_both.c
d1_clnt.c
d1_lib.c
d1_pkt.c
d1_srtp.c
d1_srvr.c
pqueue.c
s3_cbc.c
s3_lib.c
srtp.h
ssl.sym
ssl_algs.c
ssl_asn1.c
ssl_both.c
ssl_cert.c
ssl_ciph.c
ssl_ciphers.c
ssl_clnt.c
ssl_err.c
ssl_init.c
ssl_kex.c
ssl_lib.c
ssl_locl.h
ssl_methods.c
ssl_packet.c
ssl_pkt.c
ssl_rsa.c
ssl_sess.c
ssl_sigalgs.c
ssl_sigalgs.h
ssl_srvr.c
ssl_stat.c
ssl_tlsext.c
ssl_tlsext.h
ssl_transcript.c
ssl_txt.c
ssl_versions.c
t1_enc.c
t1_lib.c
tls12_record_layer.c
tls13_buffer.c
tls13_client.c
tls13_error.c
tls13_handshake.c
tls13_handshake.h
tls13_handshake_msg.c
tls13_internal.h
tls13_key_schedule.c
tls13_key_share.c
tls13_legacy.c
tls13_lib.c
tls13_record.c
tls13_record.h
tls13_record_layer.c
tls13_server.c
tls
.gitignore
CMakeLists.txt
COPYING
ChangeLog
FindLibreSSL.cmake
INSTALL
README.md
README.windows
VERSION
cmake_export_symbol.cmake
ltmain.sh
tap-driver.sh
test-driver
libusb
mbedtls
microprofile
opus
sirit
soundtouch
xbyak
CMakeLists.txt
patches
src
CMakeLists.txt
LICENSE
README.md
license.txt
		
			
				
	
	
		
			325 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* $OpenBSD: tls13_key_share.c,v 1.6 2020/04/18 14:07:56 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)
 | |
| {
 | |
| 	CBB key_exchange;
 | |
| 
 | |
| 	if (!CBB_add_u16(cbb, ks->group_id))
 | |
| 		goto err;
 | |
| 	if (!CBB_add_u16_length_prefixed(cbb, &key_exchange))
 | |
| 		goto err;
 | |
| 
 | |
| 	if (ks->nid == NID_X25519) {
 | |
| 		if (!tls13_key_share_public_x25519(ks, &key_exchange))
 | |
| 			goto err;
 | |
| 	} else {
 | |
| 		if (!tls13_key_share_public_ecdhe_ecp(ks, &key_exchange))
 | |
| 			goto err;
 | |
| 	}
 | |
| 
 | |
| 	if (!CBB_flush(cbb))
 | |
| 		goto err;
 | |
| 
 | |
| 	return 1;
 | |
| 
 | |
|  err:
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| }
 |