xref: /openbsd-src/lib/libssl/ssl_kex.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /* $OpenBSD: ssl_kex.c,v 1.1 2020/01/30 16:25:09 jsing Exp $ */
2 /*
3  * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <stdlib.h>
19 
20 #include <openssl/ec.h>
21 #include <openssl/ecdh.h>
22 
23 #include "bytestring.h"
24 
25 int
26 ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid)
27 {
28 	EC_GROUP *group;
29 	int ret = 0;
30 
31 	if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
32 		goto err;
33 
34 	if (!EC_KEY_set_group(ecdh, group))
35 		goto err;
36 	if (!EC_KEY_generate_key(ecdh))
37 		goto err;
38 
39 	ret = 1;
40 
41  err:
42 	EC_GROUP_free(group);
43 
44 	return ret;
45 }
46 
47 int
48 ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb)
49 {
50 	const EC_GROUP *group;
51 	const EC_POINT *point;
52 	uint8_t *ecp;
53 	size_t ecp_len;
54 	int ret = 0;
55 
56 	if ((group = EC_KEY_get0_group(ecdh)) == NULL)
57 		goto err;
58 	if ((point = EC_KEY_get0_public_key(ecdh)) == NULL)
59 		goto err;
60 
61 	if ((ecp_len = EC_POINT_point2oct(group, point,
62 	    POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0)
63 		goto err;
64 	if (!CBB_add_space(cbb, &ecp, ecp_len))
65 		goto err;
66 	if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED,
67 	    ecp, ecp_len, NULL)) == 0)
68 		goto err;
69 
70 	ret = 1;
71 
72  err:
73 	return ret;
74 }
75 
76 int
77 ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs)
78 {
79 	EC_GROUP *group = NULL;
80 	EC_POINT *point = NULL;
81 	int ret = 0;
82 
83 	if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
84 		goto err;
85 
86 	if (!EC_KEY_set_group(ecdh, group))
87 		goto err;
88 
89 	if ((point = EC_POINT_new(group)) == NULL)
90 		goto err;
91 	if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs),
92 	    NULL) == 0)
93 		goto err;
94 	if (!EC_KEY_set_public_key(ecdh, point))
95 		goto err;
96 
97 	ret = 1;
98 
99  err:
100 	EC_GROUP_free(group);
101 	EC_POINT_free(point);
102 
103 	return ret;
104 }
105 
106 int
107 ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer,
108     uint8_t **shared_key, size_t *shared_key_len)
109 {
110 	const EC_POINT *point;
111 	uint8_t *sk = NULL;
112 	int sk_len = 0;
113 	int ret = 0;
114 
115 	if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL))
116 		goto err;
117 	if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL))
118 		goto err;
119 
120 	if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL)
121 		goto err;
122 
123 	if ((sk_len = ECDH_size(ecdh)) <= 0)
124 		goto err;
125 	if ((sk = calloc(1, sk_len)) == NULL)
126 		goto err;
127 
128 	if (ECDH_compute_key(sk, sk_len, point, ecdh, NULL) <= 0)
129 		goto err;
130 
131 	*shared_key = sk;
132 	*shared_key_len = sk_len;
133 	sk = NULL;
134 
135 	ret = 1;
136 
137  err:
138 	freezero(sk, sk_len);
139 
140 	return ret;
141 }
142