• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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