summaryrefslogtreecommitdiff
path: root/src/lib/libssl/tls_key_share.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libssl/tls_key_share.c')
-rw-r--r--src/lib/libssl/tls_key_share.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/lib/libssl/tls_key_share.c b/src/lib/libssl/tls_key_share.c
new file mode 100644
index 0000000000..1bce651e10
--- /dev/null
+++ b/src/lib/libssl/tls_key_share.c
@@ -0,0 +1,307 @@
1/* $OpenBSD: tls_key_share.c,v 1.1 2022/01/05 17:10:03 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/curve25519.h>
21#include <openssl/ec.h>
22
23#include "bytestring.h"
24#include "ssl_locl.h"
25#include "tls_internal.h"
26
27struct tls_key_share {
28 int nid;
29 uint16_t group_id;
30
31 EC_KEY *ecdhe;
32 EC_KEY *ecdhe_peer;
33
34 uint8_t *x25519_public;
35 uint8_t *x25519_private;
36 uint8_t *x25519_peer_public;
37};
38
39struct tls_key_share *
40tls_key_share_new(uint16_t group_id)
41{
42 struct tls_key_share *ks;
43 int nid;
44
45 if ((nid = tls1_ec_curve_id2nid(group_id)) == 0)
46 return NULL;
47
48 if ((ks = calloc(1, sizeof(struct tls_key_share))) == NULL)
49 return NULL;
50
51 ks->group_id = group_id;
52 ks->nid = nid;
53
54 return ks;
55}
56
57struct tls_key_share *
58tls_key_share_new_nid(int nid)
59{
60 uint16_t group_id;
61
62 if ((group_id = tls1_ec_nid2curve_id(nid)) == 0)
63 return NULL;
64
65 return tls_key_share_new(group_id);
66}
67
68void
69tls_key_share_free(struct tls_key_share *ks)
70{
71 if (ks == NULL)
72 return;
73
74 EC_KEY_free(ks->ecdhe);
75 EC_KEY_free(ks->ecdhe_peer);
76
77 freezero(ks->x25519_public, X25519_KEY_LENGTH);
78 freezero(ks->x25519_private, X25519_KEY_LENGTH);
79 freezero(ks->x25519_peer_public, X25519_KEY_LENGTH);
80
81 freezero(ks, sizeof(*ks));
82}
83
84uint16_t
85tls_key_share_group(struct tls_key_share *ks)
86{
87 return ks->group_id;
88}
89
90int
91tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey)
92{
93 if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) {
94 if (!ssl_kex_dummy_ecdhe_x25519(pkey))
95 return 0;
96 } else if (ks->ecdhe_peer != NULL) {
97 if (!EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer))
98 return 0;
99 } else {
100 return 0;
101 }
102
103 return 1;
104}
105
106static int
107tls_key_share_generate_ecdhe_ecp(struct tls_key_share *ks)
108{
109 EC_KEY *ecdhe = NULL;
110 int ret = 0;
111
112 if (ks->ecdhe != NULL)
113 goto err;
114
115 if ((ecdhe = EC_KEY_new()) == NULL)
116 goto err;
117 if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid))
118 goto err;
119
120 ks->ecdhe = ecdhe;
121 ecdhe = NULL;
122
123 ret = 1;
124
125 err:
126 EC_KEY_free(ecdhe);
127
128 return ret;
129}
130
131static int
132tls_key_share_generate_x25519(struct tls_key_share *ks)
133{
134 uint8_t *public = NULL, *private = NULL;
135 int ret = 0;
136
137 if (ks->x25519_public != NULL || ks->x25519_private != NULL)
138 goto err;
139
140 if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL)
141 goto err;
142 if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL)
143 goto err;
144
145 X25519_keypair(public, private);
146
147 ks->x25519_public = public;
148 ks->x25519_private = private;
149 public = NULL;
150 private = NULL;
151
152 ret = 1;
153
154 err:
155 freezero(public, X25519_KEY_LENGTH);
156 freezero(private, X25519_KEY_LENGTH);
157
158 return ret;
159}
160
161int
162tls_key_share_generate(struct tls_key_share *ks)
163{
164 if (ks->nid == NID_X25519)
165 return tls_key_share_generate_x25519(ks);
166
167 return tls_key_share_generate_ecdhe_ecp(ks);
168}
169
170static int
171tls_key_share_public_ecdhe_ecp(struct tls_key_share *ks, CBB *cbb)
172{
173 if (ks->ecdhe == NULL)
174 return 0;
175
176 return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb);
177}
178
179static int
180tls_key_share_public_x25519(struct tls_key_share *ks, CBB *cbb)
181{
182 if (ks->x25519_public == NULL)
183 return 0;
184
185 return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH);
186}
187
188int
189tls_key_share_public(struct tls_key_share *ks, CBB *cbb)
190{
191 if (ks->nid == NID_X25519)
192 return tls_key_share_public_x25519(ks, cbb);
193
194 return tls_key_share_public_ecdhe_ecp(ks, cbb);
195}
196
197static int
198tls_key_share_peer_public_ecdhe_ecp(struct tls_key_share *ks, CBS *cbs)
199{
200 EC_KEY *ecdhe = NULL;
201 int ret = 0;
202
203 if (ks->ecdhe_peer != NULL)
204 goto err;
205
206 if ((ecdhe = EC_KEY_new()) == NULL)
207 goto err;
208 if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs))
209 goto err;
210
211 ks->ecdhe_peer = ecdhe;
212 ecdhe = NULL;
213
214 ret = 1;
215
216 err:
217 EC_KEY_free(ecdhe);
218
219 return ret;
220}
221
222static int
223tls_key_share_peer_public_x25519(struct tls_key_share *ks, CBS *cbs)
224{
225 size_t out_len;
226
227 if (ks->x25519_peer_public != NULL)
228 return 0;
229
230 if (CBS_len(cbs) != X25519_KEY_LENGTH)
231 return 0;
232
233 return CBS_stow(cbs, &ks->x25519_peer_public, &out_len);
234}
235
236int
237tls_key_share_peer_public(struct tls_key_share *ks, uint16_t group,
238 CBS *cbs)
239{
240 if (ks->group_id != group)
241 return 0;
242
243 if (ks->nid == NID_X25519) {
244 if (!tls_key_share_peer_public_x25519(ks, cbs))
245 return 0;
246 } else {
247 if (!tls_key_share_peer_public_ecdhe_ecp(ks, cbs))
248 return 0;
249 }
250
251 return 1;
252}
253
254static int
255tls_key_share_derive_ecdhe_ecp(struct tls_key_share *ks,
256 uint8_t **shared_key, size_t *shared_key_len)
257{
258 if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL)
259 return 0;
260
261 return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer,
262 shared_key, shared_key_len);
263}
264
265static int
266tls_key_share_derive_x25519(struct tls_key_share *ks,
267 uint8_t **shared_key, size_t *shared_key_len)
268{
269 uint8_t *sk = NULL;
270 int ret = 0;
271
272 if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL)
273 goto err;
274
275 if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL)
276 goto err;
277 if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public))
278 goto err;
279
280 *shared_key = sk;
281 *shared_key_len = X25519_KEY_LENGTH;
282 sk = NULL;
283
284 ret = 1;
285
286 err:
287 freezero(sk, X25519_KEY_LENGTH);
288
289 return ret;
290}
291
292int
293tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key,
294 size_t *shared_key_len)
295{
296 if (*shared_key != NULL)
297 return 0;
298
299 *shared_key_len = 0;
300
301 if (ks->nid == NID_X25519)
302 return tls_key_share_derive_x25519(ks, shared_key,
303 shared_key_len);
304
305 return tls_key_share_derive_ecdhe_ecp(ks, shared_key,
306 shared_key_len);
307}