1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26 #include "private-lib-jose-jwe.h"
27
28 /*
29 * From RFC7518 JWA
30 *
31 * 4.6. Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static
32 * (ECDH-ES)
33 *
34 * This section defines the specifics of key agreement with Elliptic
35 * Curve Diffie-Hellman Ephemeral Static [RFC6090], in combination with
36 * the Concat KDF, as defined in Section 5.8.1 of [NIST.800-56A]. The
37 * key agreement result can be used in one of two ways:
38 *
39 * 1. directly as the Content Encryption Key (CEK) for the "enc"
40 * algorithm, in the Direct Key Agreement mode, or
41 *
42 * 2. as a symmetric key used to wrap the CEK with the "A128KW",
43 * "A192KW", or "A256KW" algorithms, in the Key Agreement with Key
44 * Wrapping mode.
45 *
46 * A new ephemeral public key value MUST be generated for each key
47 * agreement operation.
48 *
49 * In Direct Key Agreement mode, the output of the Concat KDF MUST be a
50 * key of the same length as that used by the "enc" algorithm. In this
51 * case, the empty octet sequence is used as the JWE Encrypted Key
52 * value. The "alg" (algorithm) Header Parameter value "ECDH-ES" is
53 * used in the Direct Key Agreement mode.
54 *
55 * In Key Agreement with Key Wrapping mode, the output of the Concat KDF
56 * MUST be a key of the length needed for the specified key wrapping
57 * algorithm. In this case, the JWE Encrypted Key is the CEK wrapped
58 * with the agreed-upon key.
59 *
60 * The following "alg" (algorithm) Header Parameter values are used to
61 * indicate that the JWE Encrypted Key is the result of encrypting the
62 * CEK using the result of the key agreement algorithm as the key
63 * encryption key for the corresponding key wrapping algorithm:
64 *
65 * +-----------------+-------------------------------------------------+
66 * | "alg" Param | Key Management Algorithm |
67 * | Value | |
68 * +-----------------+-------------------------------------------------+
69 * | ECDH-ES+A128KW | ECDH-ES using Concat KDF and CEK wrapped with |
70 * | | "A128KW" |
71 * | ECDH-ES+A192KW | ECDH-ES using Concat KDF and CEK wrapped with |
72 * | | "A192KW" |
73 * | ECDH-ES+A256KW | ECDH-ES using Concat KDF and CEK wrapped with |
74 * | | "A256KW" |
75 * +-----------------+-------------------------------------------------+
76 *
77 * 4.6.1. Header Parameters Used for ECDH Key Agreement
78 *
79 * The following Header Parameter names are used for key agreement as
80 * defined below.
81 *
82 * 4.6.1.1. "epk" (Ephemeral Public Key) Header Parameter
83 *
84 * The "epk" (ephemeral public key) value created by the originator for
85 * the use in key agreement algorithms. This key is represented as a
86 * JSON Web Key [JWK] public key value. It MUST contain only public key
87 * parameters and SHOULD contain only the minimum JWK parameters
88 * necessary to represent the key; other JWK parameters included can be
89 * checked for consistency and honored, or they can be ignored. This
90 * Header Parameter MUST be present and MUST be understood and processed
91 * by implementations when these algorithms are used.
92 *
93 * 4.6.1.2. "apu" (Agreement PartyUInfo) Header Parameter
94 *
95 * The "apu" (agreement PartyUInfo) value for key agreement algorithms
96 * using it (such as "ECDH-ES"), represented as a base64url-encoded
97 * string. When used, the PartyUInfo value contains information about
98 * the producer. Use of this Header Parameter is OPTIONAL. This Header
99 * Parameter MUST be understood and processed by implementations when
100 * these algorithms are used.
101 *
102 * 4.6.1.3. "apv" (Agreement PartyVInfo) Header Parameter
103 *
104 * The "apv" (agreement PartyVInfo) value for key agreement algorithms
105 * using it (such as "ECDH-ES"), represented as a base64url encoded
106 * string. When used, the PartyVInfo value contains information about
107 * the recipient. Use of this Header Parameter is OPTIONAL. This
108 * Header Parameter MUST be understood and processed by implementations
109 * when these algorithms are used.
110 *
111 * 4.6.2. Key Derivation for ECDH Key Agreement
112 *
113 * The key derivation process derives the agreed-upon key from the
114 * shared secret Z established through the ECDH algorithm, per
115 * Section 6.2.2.2 of [NIST.800-56A].
116 *
117 * Key derivation is performed using the Concat KDF, as defined in
118 * Section 5.8.1 of [NIST.800-56A], where the Digest Method is SHA-256.
119 * The Concat KDF parameters are set as follows:
120 *
121 * Z
122 * This is set to the representation of the shared secret Z as an
123 * octet sequence.
124 *
125 * keydatalen
126 * This is set to the number of bits in the desired output key. For
127 * "ECDH-ES", this is length of the key used by the "enc" algorithm.
128 * For "ECDH-ES+A128KW", "ECDH-ES+A192KW", and "ECDH-ES+A256KW", this
129 * is 128, 192, and 256, respectively.
130 *
131 * AlgorithmID
132 * The AlgorithmID value is of the form Datalen || Data, where Data
133 * is a variable-length string of zero or more octets, and Datalen is
134 * a fixed-length, big-endian 32-bit counter that indicates the
135 * length (in octets) of Data. In the Direct Key Agreement case,
136 * Data is set to the octets of the ASCII representation of the "enc"
137 * Header Parameter value. In the Key Agreement with Key Wrapping
138 * case, Data is set to the octets of the ASCII representation of the
139 * "alg" (algorithm) Header Parameter value.
140 *
141 * PartyUInfo
142 * The PartyUInfo value is of the form Datalen || Data, where Data is
143 * a variable-length string of zero or more octets, and Datalen is a
144 * fixed-length, big-endian 32-bit counter that indicates the length
145 * (in octets) of Data. If an "apu" (agreement PartyUInfo) Header
146 * Parameter is present, Data is set to the result of base64url
147 * decoding the "apu" value and Datalen is set to the number of
148 * octets in Data. Otherwise, Datalen is set to 0 and Data is set to
149 * the empty octet sequence.
150 *
151 * PartyVInfo
152 * The PartyVInfo value is of the form Datalen || Data, where Data is
153 * a variable-length string of zero or more octets, and Datalen is a
154 * fixed-length, big-endian 32-bit counter that indicates the length
155 * (in octets) of Data. If an "apv" (agreement PartyVInfo) Header
156 * Parameter is present, Data is set to the result of base64url
157 * decoding the "apv" value and Datalen is set to the number of
158 * octets in Data. Otherwise, Datalen is set to 0 and Data is set to
159 * the empty octet sequence.
160 *
161 * SuppPubInfo
162 * This is set to the keydatalen represented as a 32-bit big-endian
163 * integer.
164 *
165 * SuppPrivInfo
166 * This is set to the empty octet sequence.
167 *
168 * Applications need to specify how the "apu" and "apv" Header
169 * Parameters are used for that application. The "apu" and "apv" values
170 * MUST be distinct, when used. Applications wishing to conform to
171 * [NIST.800-56A] need to provide values that meet the requirements of
172 * that document, e.g., by using values that identify the producer and
173 * consumer. Alternatively, applications MAY conduct key derivation in
174 * a manner similar to "Diffie-Hellman Key Agreement Method" [RFC2631]:
175 * in that case, the "apu" parameter MAY either be omitted or represent
176 * a random 512-bit value (analogous to PartyAInfo in Ephemeral-Static
177 * mode in RFC 2631) and the "apv" parameter SHOULD NOT be present.
178 *
179 */
180
181
182 /*
183 * - ECDH-ES[-variant] comes in the jose "alg" and just covers key agreement.
184 * The "enc" action is completely separate and handled elsewhere. However
185 * the key size throughout is determined by the needs of the "enc" action.
186 *
187 * - The jwe->jws.jwk is the PEER - the encryption consumer's - public key.
188 *
189 * - The public part of the ephemeral key comes out in jose.jwk_ephemeral
190 *
191 * - Return shared secret length or < 0 for error
192 *
193 * - Unwrapped CEK in EKEY. If any, wrapped CEK in "wrapped".
194 *
195 * - Caller responsibility to cleanse EKEY.
196 */
197
198 static int
lws_jwe_encrypt_ecdh(struct lws_jwe * jwe,char * temp,int * temp_len,uint8_t * cek)199 lws_jwe_encrypt_ecdh(struct lws_jwe *jwe, char *temp, int *temp_len,
200 uint8_t *cek)
201 {
202 uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES],
203 derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
204 int m, n, ret = -1, ot = *temp_len, ss_len = sizeof(shared_secret),
205 // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type),
206 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type),
207 ekbytes = 32; //jwe->jose.alg->keybits_fixed / 8;
208 struct lws_genec_ctx ecctx;
209 struct lws_jwk *ephem = &jwe->jose.recipient[jwe->recip].jwk_ephemeral;
210
211 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) {
212 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
213
214 return -1;
215 }
216
217 ephem->kty = LWS_GENCRYPTO_KTY_EC;
218 ephem->private_key = 1;
219
220 /* Generate jose.jwk_ephemeral on the peer public key curve */
221
222 if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL))
223 goto bail;
224
225 /* ephemeral context gets random key on same curve as recip pubkey */
226 if (lws_genecdh_new_keypair(&ecctx, LDHS_OURS, (const char *)
227 jwe->jws.jwk->e[LWS_GENCRYPTO_EC_KEYEL_CRV].buf,
228 ephem->e))
229 goto bail;
230
231 /* peer context gets js->jwk key */
232 if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_THEIRS)) {
233 lwsl_err("%s: setting peer pubkey failed\n", __func__);
234 goto bail;
235 }
236
237 /* combine our ephemeral key and the peer pubkey to get the secret */
238
239 if (lws_genecdh_compute_shared_secret(&ecctx, shared_secret, &ss_len)) {
240 lwsl_notice("%s: lws_genecdh_compute_shared_secret failed\n",
241 __func__);
242
243 goto bail;
244 }
245
246 /*
247 * The private part of the ephemeral key is finished with...
248 * cleanse and free it. We need to keep the public part around so we
249 * can publish it with the JWE as "epk".
250 */
251
252 lws_explicit_bzero(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
253 ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
254 lws_free_set_NULL(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf);
255 ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len = 0;
256 ephem->private_key = 0;
257
258 /*
259 * Derive the CEK from the shared secret... amount of bytes written to
260 * derived matches bitcount in jwe->jose.enc_alg->keybits_fixed
261 *
262 * In Direct Key Agreement mode, the output of the Concat KDF MUST be a
263 * key of the same length as that used by the "enc" algorithm.
264 */
265
266 if (lws_jwa_concat_kdf(jwe,
267 jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE,
268 derived, shared_secret, ss_len)) {
269 lwsl_notice("%s: lws_jwa_concat_kdf failed\n", __func__);
270
271 goto bail;
272 }
273
274 /* in P-521 case, we get a 66-byte shared secret for a 64-byte key */
275 if (ss_len < enc_hlen) {
276 lwsl_err("%s: concat KDF bad derived key len %d\n", __func__,
277 ss_len);
278 goto bail;
279 }
280
281 /*
282 * For "ECDH-ES", that was it, and we use what we just wrapped in
283 * wrapped as the CEK without publishing it.
284 *
285 * For "ECDH-ES-AES[128,192,256]KW", we generate a new, random CEK and
286 * then wrap it using the key we just wrapped, and make the wrapped
287 * version available in EKEY.
288 */
289
290 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
291 struct lws_gencrypto_keyelem el;
292 struct lws_genaes_ctx aesctx;
293
294 /* generate the actual CEK in cek */
295
296 if (lws_get_random(jwe->jws.context, cek, (unsigned int)enc_hlen) !=
297 (size_t)enc_hlen) {
298 lwsl_err("Problem getting random\n");
299 goto bail;
300 }
301
302 /* wrap with the derived key */
303
304 el.buf = derived;
305 el.len = (unsigned int)enc_hlen / 2;
306
307 if (lws_genaes_create(&aesctx, LWS_GAESO_ENC, LWS_GAESM_KW, &el,
308 1, NULL)) {
309
310 lwsl_notice("%s: lws_genaes_create\n", __func__);
311 goto bail;
312 }
313
314 /* wrap CEK into EKEY */
315
316 n = lws_genaes_crypt(&aesctx, cek, (unsigned int)enc_hlen,
317 (void *)jwe->jws.map.buf[LJWE_EKEY],
318 NULL, NULL, NULL, 0);
319 m = lws_genaes_destroy(&aesctx, NULL, 0);
320 if (n < 0) {
321 lwsl_err("%s: encrypt cek fail\n", __func__);
322 goto bail;
323 }
324 if (m < 0) {
325 lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
326 goto bail;
327 }
328
329 jwe->jws.map.len[LJWE_EKEY] = (unsigned int)enc_hlen + 8;
330
331 /* Wrapped CEK is in EKEY. Random CEK is in cek. */
332
333 } else /* direct derived CEK is in cek */
334 memcpy(cek, derived, (unsigned int)enc_hlen);
335
336 /* rewrite the protected JOSE header to have the epk pieces */
337
338 jwe->jws.map.buf[LJWE_JOSE] = temp;
339
340 m = n = lws_snprintf(temp, (size_t)*temp_len,
341 "{\"alg\":\"%s\", \"enc\":\"%s\", \"epk\":",
342 jwe->jose.alg->alg, jwe->jose.enc_alg->alg);
343 *temp_len -= n;
344
345 n = lws_jwk_export(ephem, 0, temp + (ot - *temp_len), temp_len);
346 if (n < 0) {
347 lwsl_err("%s: ephemeral export failed\n", __func__);
348 goto bail;
349 }
350 m += n;
351
352 n = lws_snprintf(temp + (ot - *temp_len), (size_t)*temp_len, "}");
353 *temp_len -= n + 1;
354 m += n;
355 jwe->jws.map.len[LJWE_JOSE] = (unsigned int)m;
356
357 /* create a b64 version of the JOSE header, needed later for AAD */
358
359 if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
360 temp + (ot - *temp_len), temp_len,
361 jwe->jws.map.buf[LJWE_JOSE],
362 jwe->jws.map.len[LJWE_JOSE]))
363 return -1;
364
365 ret = enc_hlen;
366
367 bail:
368 lws_genec_destroy(&ecctx);
369
370 /* cleanse the shared secret (watch out for cek at parent too) */
371 lws_explicit_bzero(shared_secret, (unsigned int)ekbytes);
372 lws_explicit_bzero(derived, (unsigned int)ekbytes);
373
374 return ret;
375 }
376
377 int
lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe * jwe,char * temp,int * temp_len)378 lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len)
379 {
380 int ss_len, // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type),
381 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
382 uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
383 int ekbytes = jwe->jose.alg->keybits_fixed / 8;
384 int n, ot = *temp_len, ret = -1;
385
386 /* if we will produce an EKEY, make space for it */
387
388 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
389 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_EKEY,
390 temp + (ot - *temp_len), temp_len,
391 (unsigned int)enc_hlen + 8, 0))
392 goto bail;
393 }
394
395 /* decrypt the CEK */
396
397 ss_len = lws_jwe_encrypt_ecdh(jwe, temp + (ot - *temp_len), temp_len, cek);
398 if (ss_len < 0) {
399 lwsl_err("%s: lws_jwe_encrypt_ecdh failed\n", __func__);
400 return -1;
401 }
402
403 /* cek contains the unwrapped CEK. EKEY may contain wrapped CEK */
404
405 /* make space for the payload encryption pieces */
406
407 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
408 temp + (ot - *temp_len),
409 temp_len, (unsigned int)enc_hlen / 2, 0))
410 goto bail;
411
412 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV,
413 temp + (ot - *temp_len),
414 temp_len, LWS_JWE_AES_IV_BYTES, 0))
415 goto bail;
416
417 /* Perform the authenticated encryption on CTXT...
418 * ...the AAD is b64u(protected JOSE header) */
419
420 n = lws_jwe_encrypt_cbc_hs(jwe, cek,
421 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
422 (int)jwe->jws.map_b64.len[LJWE_JOSE]);
423 if (n < 0) {
424 lwsl_notice("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__);
425 goto bail;
426 }
427
428 ret = 0;
429
430 bail:
431 /* if fail or direct CEK, cleanse and remove EKEY */
432 if (ret || jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE) {
433 if (jwe->jws.map.len[LJWE_EKEY])
434 lws_explicit_bzero((void *)jwe->jws.map.buf[LJWE_EKEY],
435 jwe->jws.map.len[LJWE_EKEY]);
436 jwe->jws.map.len[LJWE_EKEY] = 0;
437 }
438
439 lws_explicit_bzero(cek, (unsigned int)ekbytes);
440
441 return ret;
442 }
443
444 /*
445 * jwe->jws.jwk is recipient private key
446 *
447 * If kw mode, then EKEY is the wrapped CEK
448 *
449 *
450 */
451
452 static int
lws_jwe_auth_and_decrypt_ecdh(struct lws_jwe * jwe)453 lws_jwe_auth_and_decrypt_ecdh(struct lws_jwe *jwe)
454 {
455 uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES],
456 derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
457 int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8,
458 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
459 struct lws_genec_ctx ecctx;
460 int n, ret = -1, ss_len = sizeof(shared_secret);
461
462 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) {
463 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
464
465 return -1;
466 }
467
468 if (jwe->jose.recipient[jwe->recip].jwk_ephemeral.kty !=
469 LWS_GENCRYPTO_KTY_EC) {
470 lwsl_err("%s: missing epk\n", __func__);
471
472 return -1;
473 }
474
475 /*
476 * Recompute the shared secret...
477 *
478 * - direct: it's the CEK
479 *
480 * - aeskw: apply it as AES keywrap to EKEY to get the CEK
481 */
482
483 /* Generate jose.jwk_ephemeral on the peer public key curve */
484
485 if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL))
486 goto bail;
487
488 /* Load our private key into our side of the ecdh context */
489
490 if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_OURS)) {
491 lwsl_err("%s: setting our private key failed\n", __func__);
492 goto bail;
493 }
494
495 /* Import the ephemeral public key into the peer side */
496 if (lws_genecdh_set_key(&ecctx,
497 jwe->jose.recipient[jwe->recip].jwk_ephemeral.e,
498 LDHS_THEIRS)) {
499 lwsl_err("%s: setting epk pubkey failed\n", __func__);
500 goto bail;
501 }
502
503 /* combine their ephemeral key and our private key to get the secret */
504
505 if (lws_genecdh_compute_shared_secret(&ecctx, shared_secret, &ss_len)) {
506 lwsl_notice("%s: lws_genecdh_compute_shared_secret failed\n",
507 __func__);
508
509 goto bail;
510 }
511
512 lws_genec_destroy(&ecctx);
513
514 if (ss_len < enc_hlen) {
515 lwsl_err("%s: ss_len %d ekbytes %d\n", __func__, ss_len, enc_hlen);
516 goto bail;
517 }
518
519 /*
520 * Derive the CEK from the shared secret... amount of bytes written to
521 * cek[] matches bitcount in jwe->jose.enc_alg->keybits_fixed
522 */
523
524 if (lws_jwa_concat_kdf(jwe,
525 jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE,
526 derived, shared_secret, ss_len)) {
527 lwsl_notice("%s: lws_jwa_concat_kdf failed\n", __func__);
528
529 goto bail;
530 }
531
532 /*
533 * "ECDH-ES": derived is the CEK
534 * "ECDH-ES-AES[128,192,256]KW": wrapped key is in EKEY,
535 * "derived" contains KEK
536 */
537
538 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
539 struct lws_gencrypto_keyelem el;
540 struct lws_genaes_ctx aesctx;
541 int m;
542
543 /* Confirm space for EKEY */
544
545 if (jwe->jws.map.len[LJWE_EKEY] < (unsigned int)enc_hlen) {
546 lwsl_err("%s: missing EKEY\n", __func__);
547
548 goto bail;
549 }
550
551 /* unwrap with the KEK we derived */
552
553 el.buf = derived;
554 el.len = (unsigned int)enc_hlen / 2;
555
556 if (lws_genaes_create(&aesctx, LWS_GAESO_DEC, LWS_GAESM_KW,
557 &el, 1, NULL)) {
558
559 lwsl_notice("%s: lws_genaes_create\n", __func__);
560 goto bail;
561 }
562
563 /* decrypt the EKEY to end up with CEK in "shared_secret" */
564
565 n = lws_genaes_crypt(&aesctx,
566 (const uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
567 jwe->jws.map.len[LJWE_EKEY],
568 (uint8_t *)shared_secret,
569 NULL, NULL, NULL, 0);
570 m = lws_genaes_destroy(&aesctx, NULL, 0);
571 if (n < 0) {
572 lwsl_err("%s: decrypt cek fail\n", __func__);
573 goto bail;
574 }
575 if (m < 0) {
576 lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
577 goto bail;
578 }
579 } else
580 memcpy(shared_secret, derived, (unsigned int)enc_hlen);
581
582 /* either way, the recovered CEK is in shared_secret */
583
584 if (lws_jwe_auth_and_decrypt_cbc_hs(jwe, shared_secret,
585 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
586 (int)jwe->jws.map_b64.len[LJWE_JOSE]) < 0) {
587 lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs fail\n", __func__);
588 goto bail;
589 }
590
591 /* if all went well, then CTXT is now the plaintext */
592 ret = 0;
593
594 bail:
595 /* cleanse wrapped on stack that contained the CEK / wrapped key */
596 lws_explicit_bzero(derived, (unsigned int)ekbytes);
597 /* cleanse the shared secret */
598 lws_explicit_bzero(shared_secret, (unsigned int)ekbytes);
599
600 return ret;
601 }
602
603 int
lws_jwe_auth_and_decrypt_ecdh_cbc_hs(struct lws_jwe * jwe,char * temp,int * temp_len)604 lws_jwe_auth_and_decrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
605 char *temp, int *temp_len)
606 {
607 /* create a b64 version of the JOSE header, needed later for AAD */
608
609 if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
610 temp, temp_len,
611 jwe->jws.map.buf[LJWE_JOSE],
612 jwe->jws.map.len[LJWE_JOSE]))
613 return -1;
614
615 return lws_jwe_auth_and_decrypt_ecdh(jwe);
616 }
617