• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 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.h"
27 #include "private-lib-jose-jwe.h"
28 
29 /*
30  * Currently only support flattened or compact (implicitly single signature)
31  */
32 
33 static const char * const jwe_json[] = {
34 	"protected",
35 	"iv",
36 	"ciphertext",
37 	"tag",
38 	"encrypted_key"
39 };
40 
41 enum enum_jwe_complete_tokens {
42 	LWS_EJCT_PROTECTED,
43 	LWS_EJCT_IV,
44 	LWS_EJCT_CIPHERTEXT,
45 	LWS_EJCT_TAG,
46 	LWS_EJCT_RECIP_ENC_KEY,
47 };
48 
49 /* parse a JWS complete or flattened JSON object */
50 
51 struct jwe_cb_args {
52 	struct lws_jws *jws;
53 
54 	char *temp;
55 	int *temp_len;
56 };
57 
58 static signed char
lws_jwe_json_cb(struct lejp_ctx * ctx,char reason)59 lws_jwe_json_cb(struct lejp_ctx *ctx, char reason)
60 {
61 	struct jwe_cb_args *args = (struct jwe_cb_args *)ctx->user;
62 	int n, m;
63 
64 	if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
65 		return 0;
66 
67 	switch (ctx->path_match - 1) {
68 
69 	/* strings */
70 
71 	case LWS_EJCT_PROTECTED:  /* base64u: JOSE: must contain 'alg' */
72 		m = LJWS_JOSE;
73 		goto append_string;
74 	case LWS_EJCT_IV:	/* base64u */
75 		m = LJWE_IV;
76 		goto append_string;
77 	case LWS_EJCT_CIPHERTEXT:  /* base64u */
78 		m = LJWE_CTXT;
79 		goto append_string;
80 	case LWS_EJCT_TAG:  /* base64u */
81 		m = LJWE_ATAG;
82 		goto append_string;
83 	case LWS_EJCT_RECIP_ENC_KEY:  /* base64u */
84 		m = LJWE_EKEY;
85 		goto append_string;
86 
87 	default:
88 		return -1;
89 	}
90 
91 	return 0;
92 
93 append_string:
94 
95 	if (*args->temp_len < ctx->npos) {
96 		lwsl_err("%s: out of parsing space\n", __func__);
97 		return -1;
98 	}
99 
100 	/*
101 	 * We keep both b64u and decoded in temp mapped using map / map_b64,
102 	 * the jws signature is actually over the b64 content not the plaintext,
103 	 * and we can't do it until we see the protected alg.
104 	 */
105 
106 	if (!args->jws->map_b64.buf[m]) {
107 		args->jws->map_b64.buf[m] = args->temp;
108 		args->jws->map_b64.len[m] = 0;
109 	}
110 
111 	memcpy(args->temp, ctx->buf, ctx->npos);
112 	args->temp += ctx->npos;
113 	*args->temp_len -= ctx->npos;
114 	args->jws->map_b64.len[m] += ctx->npos;
115 
116 	if (reason == LEJPCB_VAL_STR_END) {
117 		args->jws->map.buf[m] = args->temp;
118 
119 		n = lws_b64_decode_string_len(
120 			(const char *)args->jws->map_b64.buf[m],
121 			args->jws->map_b64.len[m],
122 			(char *)args->temp, *args->temp_len);
123 		if (n < 0) {
124 			lwsl_err("%s: b64 decode failed\n", __func__);
125 			return -1;
126 		}
127 
128 		args->temp += n;
129 		*args->temp_len -= n;
130 		args->jws->map.len[m] = n;
131 	}
132 
133 	return 0;
134 }
135 
136 int
lws_jwe_json_parse(struct lws_jwe * jwe,const uint8_t * buf,int len,char * temp,int * temp_len)137 lws_jwe_json_parse(struct lws_jwe *jwe, const uint8_t *buf, int len,
138 		   char *temp, int *temp_len)
139 {
140 	struct jwe_cb_args args;
141 	struct lejp_ctx jctx;
142 	int m = 0;
143 
144 	args.jws = &jwe->jws;
145 	args.temp = temp;
146 	args.temp_len = temp_len;
147 
148 	lejp_construct(&jctx, lws_jwe_json_cb, &args, jwe_json,
149 		       LWS_ARRAY_SIZE(jwe_json));
150 
151 	m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, len);
152 	lejp_destruct(&jctx);
153 	if (m < 0) {
154 		lwsl_notice("%s: parse returned %d\n", __func__, m);
155 		return -1;
156 	}
157 
158 	return 0;
159 }
160 
161 void
lws_jwe_init(struct lws_jwe * jwe,struct lws_context * context)162 lws_jwe_init(struct lws_jwe *jwe, struct lws_context *context)
163 {
164 	lws_jose_init(&jwe->jose);
165 	lws_jws_init(&jwe->jws, &jwe->jwk, context);
166 	memset(&jwe->jwk, 0, sizeof(jwe->jwk));
167 	jwe->recip = 0;
168 	jwe->cek_valid = 0;
169 }
170 
171 void
lws_jwe_destroy(struct lws_jwe * jwe)172 lws_jwe_destroy(struct lws_jwe *jwe)
173 {
174 	lws_jws_destroy(&jwe->jws);
175 	lws_jose_destroy(&jwe->jose);
176 	lws_jwk_destroy(&jwe->jwk);
177 	/* cleanse the CEK we held on to in case of further encryptions of it */
178 	lws_explicit_bzero(jwe->cek, sizeof(jwe->cek));
179 	jwe->cek_valid = 0;
180 }
181 
182 static uint8_t *
be32(uint32_t i,uint32_t * p32)183 be32(uint32_t i, uint32_t *p32)
184 {
185 	uint8_t *p = (uint8_t *)p32;
186 
187 	*p++ = (i >> 24) & 0xff;
188 	*p++ = (i >> 16) & 0xff;
189 	*p++ = (i >> 8) & 0xff;
190 	*p++ = i & 0xff;
191 
192 	return (uint8_t *)p32;
193 }
194 
195 /*
196  * The key derivation process derives the agreed-upon key from the
197  * shared secret Z established through the ECDH algorithm, per
198  * Section 6.2.2.2 of [NIST.800-56A].
199  *
200  *
201  * Key derivation is performed using the Concat KDF, as defined in
202  * Section 5.8.1 of [NIST.800-56A], where the Digest Method is SHA-256.
203  *
204  * out must be prepared to take at least 32 bytes or the encrypted key size,
205  * whichever is larger.
206  */
207 
208 int
lws_jwa_concat_kdf(struct lws_jwe * jwe,int direct,uint8_t * out,const uint8_t * shared_secret,int sslen)209 lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, uint8_t *out,
210 		   const uint8_t *shared_secret, int sslen)
211 {
212 	int hlen = lws_genhash_size(LWS_GENHASH_TYPE_SHA256), aidlen;
213 	struct lws_genhash_ctx hash_ctx;
214 	uint32_t ctr = 1, t;
215 	const char *aid;
216 
217 	if (!jwe->jose.enc_alg || !jwe->jose.alg)
218 		return -1;
219 
220 	/*
221 	 * Hash
222 	 *
223 	 * AlgorithmID || PartyUInfo || PartyVInfo
224 	 * 	{|| SuppPubInfo }{|| SuppPrivInfo }
225 	 *
226 	 * AlgorithmID
227 	 *
228 	 * The AlgorithmID value is of the form Datalen || Data, where Data
229 	 * is a variable-length string of zero or more octets, and Datalen is
230 	 * a fixed-length, big-endian 32-bit counter that indicates the
231 	 * length (in octets) of Data.  In the Direct Key Agreement case,
232 	 * Data is set to the octets of the ASCII representation of the "enc"
233 	 * Header Parameter value.  In the Key Agreement with Key Wrapping
234 	 * case, Data is set to the octets of the ASCII representation of the
235 	 * "alg" (algorithm) Header Parameter value.
236 	 */
237 
238 	aid = direct ? jwe->jose.enc_alg->alg : jwe->jose.alg->alg;
239 	aidlen = strlen(aid);
240 
241 	/*
242 	 *   PartyUInfo (PartyVInfo is the same deal)
243 	 *
244 	 *    The PartyUInfo value is of the form Datalen || Data, where Data is
245 	 *    a variable-length string of zero or more octets, and Datalen is a
246 	 *    fixed-length, big-endian 32-bit counter that indicates the length
247 	 *    (in octets) of Data.  If an "apu" (agreement PartyUInfo) Header
248 	 *    Parameter is present, Data is set to the result of base64url
249 	 *    decoding the "apu" value and Datalen is set to the number of
250 	 *    octets in Data.  Otherwise, Datalen is set to 0 and Data is set to
251 	 *    the empty octet sequence
252 	 *
253 	 *   SuppPubInfo
254 	 *
255 	 *    This is set to the keydatalen represented as a 32-bit big-endian
256 	 *    integer.
257 	 *
258 	 *   keydatalen
259 	 *
260 	 *    This is set to the number of bits in the desired output key.  For
261 	 *    "ECDH-ES", this is length of the key used by the "enc" algorithm.
262 	 *    For "ECDH-ES+A128KW", "ECDH-ES+A192KW", and "ECDH-ES+A256KW", this
263 	 *    is 128, 192, and 256, respectively.
264 	 *
265 	 *    Compute Hash i = H(counter || Z || OtherInfo).
266 	 *
267 	 *    We must iteratively hash over key material that's larger than
268 	 *    one hash output size (256b for SHA-256)
269 	 */
270 
271 	while (ctr <= (uint32_t)((jwe->jose.enc_alg->keybits_fixed + (hlen - 1)) / hlen)) {
272 
273 		/*
274 		 * Key derivation is performed using the Concat KDF, as defined
275 		 * in Section 5.8.1 of [NIST.800-56A], where the Digest Method
276 		 * is SHA-256.
277 		 */
278 
279 		if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
280 			return -1;
281 
282 		if (/* counter */
283 		    lws_genhash_update(&hash_ctx, be32(ctr++, &t), 4) ||
284 		    /* Z */
285 		    lws_genhash_update(&hash_ctx, shared_secret, sslen) ||
286 		    /* other info */
287 		    lws_genhash_update(&hash_ctx, be32(strlen(aid), &t), 4) ||
288 		    lws_genhash_update(&hash_ctx, aid, aidlen) ||
289 		    lws_genhash_update(&hash_ctx,
290 				       be32(jwe->jose.e[LJJHI_APU].len, &t), 4) ||
291 		    lws_genhash_update(&hash_ctx, jwe->jose.e[LJJHI_APU].buf,
292 						  jwe->jose.e[LJJHI_APU].len) ||
293 		    lws_genhash_update(&hash_ctx,
294 				       be32(jwe->jose.e[LJJHI_APV].len, &t), 4) ||
295 		    lws_genhash_update(&hash_ctx, jwe->jose.e[LJJHI_APV].buf,
296 						  jwe->jose.e[LJJHI_APV].len) ||
297 		    lws_genhash_update(&hash_ctx,
298 				       be32(jwe->jose.enc_alg->keybits_fixed, &t),
299 					    4) ||
300 		    lws_genhash_destroy(&hash_ctx, out)) {
301 			lwsl_err("%s: fail\n", __func__);
302 			lws_genhash_destroy(&hash_ctx, NULL);
303 
304 			return -1;
305 		}
306 
307 		out += hlen;
308 	}
309 
310 	return 0;
311 }
312 
313 void
lws_jwe_be64(uint64_t c,uint8_t * p8)314 lws_jwe_be64(uint64_t c, uint8_t *p8)
315 {
316 	int n;
317 
318 	for (n = 56; n >= 0; n -= 8)
319 		*p8++ = (uint8_t)((c >> n) & 0xff);
320 }
321 
322 int
lws_jwe_auth_and_decrypt(struct lws_jwe * jwe,char * temp,int * temp_len)323 lws_jwe_auth_and_decrypt(struct lws_jwe *jwe, char *temp, int *temp_len)
324 {
325 	int valid_aescbc_hmac, valid_aesgcm;
326 	char dotstar[96];
327 
328 	if (lws_jwe_parse_jose(&jwe->jose, jwe->jws.map.buf[LJWS_JOSE],
329 			       jwe->jws.map.len[LJWS_JOSE],
330 			       temp, temp_len) < 0) {
331 		lws_strnncpy(dotstar, jwe->jws.map.buf[LJWS_JOSE],
332 			     jwe->jws.map.len[LJWS_JOSE], sizeof(dotstar));
333 		lwsl_err("%s: JOSE parse '%s' failed\n", __func__, dotstar);
334 		return -1;
335 	}
336 
337 	if (!jwe->jose.alg) {
338 		lws_strnncpy(dotstar, jwe->jws.map.buf[LJWS_JOSE],
339 			     jwe->jws.map.len[LJWS_JOSE], sizeof(dotstar));
340 		lwsl_err("%s: no jose.alg: %s\n", __func__, dotstar);
341 
342 		return -1;
343 	}
344 
345 	valid_aescbc_hmac = jwe->jose.enc_alg &&
346 		jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_AES_CBC &&
347 		(jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA256 ||
348 		 jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA384 ||
349 		 jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA512);
350 
351 	valid_aesgcm = jwe->jose.enc_alg &&
352 		jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_AES_GCM;
353 
354 	if ((jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_RSASSA_PKCS1_1_5 ||
355 	     jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_RSASSA_PKCS1_OAEP)) {
356 		/* RSA + AESCBC */
357 		if (valid_aescbc_hmac)
358 			return lws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(jwe);
359 		/* RSA + AESGCM */
360 		if (valid_aesgcm)
361 			return lws_jwe_auth_and_decrypt_rsa_aes_gcm(jwe);
362 	}
363 
364 	/* AESKW */
365 
366 	if (jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_AES_ECB &&
367 	    valid_aescbc_hmac)
368 		return lws_jwe_auth_and_decrypt_aeskw_cbc_hs(jwe);
369 
370 	/* ECDH-ES + AESKW */
371 
372 	if (jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_ECDHES &&
373 	    valid_aescbc_hmac)
374 		return lws_jwe_auth_and_decrypt_ecdh_cbc_hs(jwe,
375 							    temp, temp_len);
376 
377 	lwsl_err("%s: unknown cipher alg combo %s / %s\n", __func__,
378 			jwe->jose.alg->alg, jwe->jose.enc_alg ?
379 					jwe->jose.enc_alg->alg : "NULL");
380 
381 	return -1;
382 }
383 int
lws_jwe_encrypt(struct lws_jwe * jwe,char * temp,int * temp_len)384 lws_jwe_encrypt(struct lws_jwe *jwe, char *temp, int *temp_len)
385 {
386 	int valid_aescbc_hmac, valid_aesgcm, ot = *temp_len, ret = -1;
387 
388 	if (jwe->jose.recipients >= (int)LWS_ARRAY_SIZE(jwe->jose.recipient)) {
389 		lwsl_err("%s: max recipients reached\n", __func__);
390 
391 		return -1;
392 	}
393 
394 	valid_aesgcm = jwe->jose.enc_alg &&
395 		jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_AES_GCM;
396 
397 	if (lws_jwe_parse_jose(&jwe->jose, jwe->jws.map.buf[LJWS_JOSE],
398 			       jwe->jws.map.len[LJWS_JOSE], temp, temp_len) < 0) {
399 		lwsl_err("%s: JOSE parse failed\n", __func__);
400 		goto bail;
401 	}
402 
403 	temp += ot - *temp_len;
404 
405 	valid_aescbc_hmac = jwe->jose.enc_alg &&
406 		jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_AES_CBC &&
407 		(jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA256 ||
408 		 jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA384 ||
409 		 jwe->jose.enc_alg->hmac_type == LWS_GENHMAC_TYPE_SHA512);
410 
411 	if ((jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_RSASSA_PKCS1_1_5 ||
412 	     jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_RSASSA_PKCS1_OAEP)) {
413 		/* RSA + AESCBC */
414 		if (valid_aescbc_hmac) {
415 			ret = lws_jwe_encrypt_rsa_aes_cbc_hs(jwe, temp, temp_len);
416 			goto bail;
417 		}
418 		/* RSA + AESGCM */
419 		if (valid_aesgcm) {
420 			ret = lws_jwe_encrypt_rsa_aes_gcm(jwe, temp, temp_len);
421 			goto bail;
422 		}
423 	}
424 
425 	/* AESKW */
426 
427 	if (jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_AES_ECB &&
428 	    valid_aescbc_hmac) {
429 		ret = lws_jwe_encrypt_aeskw_cbc_hs(jwe, temp, temp_len);
430 		goto bail;
431 	}
432 
433 	/* ECDH-ES + AESKW */
434 
435 	if (jwe->jose.alg->algtype_signing == LWS_JOSE_ENCTYPE_ECDHES &&
436 	    valid_aescbc_hmac) {
437 		ret = lws_jwe_encrypt_ecdh_cbc_hs(jwe, temp, temp_len);
438 		goto bail;
439 	}
440 
441 	lwsl_err("%s: unknown cipher alg combo %s / %s\n", __func__,
442 			jwe->jose.alg->alg, jwe->jose.enc_alg ?
443 					jwe->jose.enc_alg->alg : "NULL");
444 
445 bail:
446 	if (ret)
447 		memset(&jwe->jose.recipient[jwe->jose.recipients], 0,
448 			sizeof(jwe->jose.recipient[0]));
449 	else
450 		jwe->jose.recipients++;
451 
452 	return ret;
453 }
454 
455 /*
456  * JWE Compact Serialization consists of
457  *
458  *     BASE64URL(UTF8(JWE Protected Header)) || '.' ||
459  *     BASE64URL(JWE Encrypted Key)	     || '.' ||
460  *     BASE64URL(JWE Initialization Vector)  || '.' ||
461  *     BASE64URL(JWE Ciphertext)	     || '.' ||
462  *     BASE64URL(JWE Authentication Tag)
463  *
464  *
465  * In the JWE Compact Serialization, no JWE Shared Unprotected Header or
466  * JWE Per-Recipient Unprotected Header are used.  In this case, the
467  * JOSE Header and the JWE Protected Header are the same.
468  *
469  * Therefore:
470  *
471  *  - Everything needed in the header part must go in the protected header
472  *    (it's the only part emitted).  We expect the caller did this.
473  *
474  *  - You can't emit Compact representation if there are multiple recipients
475  */
476 
477 int
lws_jwe_render_compact(struct lws_jwe * jwe,char * out,size_t out_len)478 lws_jwe_render_compact(struct lws_jwe *jwe, char *out, size_t out_len)
479 {
480 	size_t orig = out_len;
481 	int n;
482 
483 	if (jwe->jose.recipients > 1) {
484 		lwsl_notice("%s: can't issue compact representation for"
485 			    " multiple recipients (%d)\n", __func__,
486 			    jwe->jose.recipients);
487 
488 		return -1;
489 	}
490 
491 	n = lws_jws_base64_enc(jwe->jws.map.buf[LJWS_JOSE],
492 			       jwe->jws.map.len[LJWS_JOSE], out, out_len);
493 	if (n < 0 || (int)out_len == n) {
494 		lwsl_info("%s: unable to encode JOSE\n", __func__);
495 		return -1;
496 	}
497 
498 	out += n;
499 	*out++ = '.';
500 	out_len -= n + 1;
501 
502 	n = lws_jws_base64_enc(jwe->jws.map.buf[LJWE_EKEY],
503 			       jwe->jws.map.len[LJWE_EKEY], out, out_len);
504 	if (n < 0 || (int)out_len == n) {
505 		lwsl_info("%s: unable to encode EKEY\n", __func__);
506 		return -1;
507 	}
508 
509 	out += n;
510 	*out++ = '.';
511 	out_len -= n + 1;
512 	n = lws_jws_base64_enc(jwe->jws.map.buf[LJWE_IV],
513 			       jwe->jws.map.len[LJWE_IV], out, out_len);
514 	if (n < 0 || (int)out_len == n) {
515 		lwsl_info("%s: unable to encode IV\n", __func__);
516 		return -1;
517 	}
518 
519 	out += n;
520 	*out++ = '.';
521 	out_len -= n + 1;
522 
523 	n = lws_jws_base64_enc(jwe->jws.map.buf[LJWE_CTXT],
524 			       jwe->jws.map.len[LJWE_CTXT], out, out_len);
525 	if (n < 0 || (int)out_len == n) {
526 		lwsl_info("%s: unable to encode CTXT\n", __func__);
527 		return -1;
528 	}
529 
530 	out += n;
531 	*out++ = '.';
532 	out_len -= n + 1;
533 	n = lws_jws_base64_enc(jwe->jws.map.buf[LJWE_ATAG],
534 			       jwe->jws.map.len[LJWE_ATAG], out, out_len);
535 	if (n < 0 || (int)out_len == n) {
536 		lwsl_info("%s: unable to encode ATAG\n", __func__);
537 		return -1;
538 	}
539 
540 	out += n;
541 	*out++ = '\0';
542 	out_len -= n;
543 
544 	return orig - out_len;
545 }
546 
547 int
lws_jwe_create_packet(struct lws_jwe * jwe,const char * payload,size_t len,const char * nonce,char * out,size_t out_len,struct lws_context * context)548 lws_jwe_create_packet(struct lws_jwe *jwe, const char *payload, size_t len,
549 		      const char *nonce, char *out, size_t out_len,
550 		      struct lws_context *context)
551 {
552 	char *buf, *start, *p, *end, *p1, *end1;
553 	struct lws_jws jws;
554 	int n, m;
555 
556 	lws_jws_init(&jws, &jwe->jwk, context);
557 
558 	/*
559 	 * This buffer is local to the function, the actual output is prepared
560 	 * into out.  Only the plaintext protected header
561 	 * (which contains the public key, 512 bytes for 4096b) goes in
562 	 * here temporarily.
563 	 */
564 	n = LWS_PRE + 2048;
565 	buf = malloc(n);
566 	if (!buf) {
567 		lwsl_notice("%s: malloc %d failed\n", __func__, n);
568 		return -1;
569 	}
570 
571 	p = start = buf + LWS_PRE;
572 	end = buf + n - LWS_PRE - 1;
573 
574 	/*
575 	 * temporary JWS protected header plaintext
576 	 */
577 
578 	if (!jwe->jose.alg || !jwe->jose.alg->alg)
579 		goto bail;
580 
581 	p += lws_snprintf(p, end - p, "{\"alg\":\"%s\",\"jwk\":",
582 			  jwe->jose.alg->alg);
583 	m = end - p;
584 	n = lws_jwk_export(&jwe->jwk, 0, p, &m);
585 	if (n < 0) {
586 		lwsl_notice("failed to export jwk\n");
587 
588 		goto bail;
589 	}
590 	p += n;
591 	p += lws_snprintf(p, end - p, ",\"nonce\":\"%s\"}", nonce);
592 
593 	/*
594 	 * prepare the signed outer JSON with all the parts in
595 	 */
596 
597 	p1 = out;
598 	end1 = out + out_len - 1;
599 
600 	p1 += lws_snprintf(p1, end1 - p1, "{\"protected\":\"");
601 	jws.map_b64.buf[LJWS_JOSE] = p1;
602 	n = lws_jws_base64_enc(start, p - start, p1, end1 - p1);
603 	if (n < 0) {
604 		lwsl_notice("%s: failed to encode protected\n", __func__);
605 		goto bail;
606 	}
607 	jws.map_b64.len[LJWS_JOSE] = n;
608 	p1 += n;
609 
610 	p1 += lws_snprintf(p1, end1 - p1, "\",\"payload\":\"");
611 	jws.map_b64.buf[LJWS_PYLD] = p1;
612 	n = lws_jws_base64_enc(payload, len, p1, end1 - p1);
613 	if (n < 0) {
614 		lwsl_notice("%s: failed to encode payload\n", __func__);
615 		goto bail;
616 	}
617 	jws.map_b64.len[LJWS_PYLD] = n;
618 	p1 += n;
619 
620 	p1 += lws_snprintf(p1, end1 - p1, "\",\"header\":\"");
621 	jws.map_b64.buf[LJWS_UHDR] = p1;
622 	n = lws_jws_base64_enc(payload, len, p1, end1 - p1);
623 	if (n < 0) {
624 		lwsl_notice("%s: failed to encode payload\n", __func__);
625 		goto bail;
626 	}
627 	jws.map_b64.len[LJWS_UHDR] = n;
628 
629 	p1 += n;
630 	p1 += lws_snprintf(p1, end1 - p1, "\",\"signature\":\"");
631 
632 	/*
633 	 * taking the b64 protected header and the b64 payload, sign them
634 	 * and place the signature into the packet
635 	 */
636 	n = lws_jws_sign_from_b64(&jwe->jose, &jws, p1, end1 - p1);
637 	if (n < 0) {
638 		lwsl_notice("sig gen failed\n");
639 
640 		goto bail;
641 	}
642 	jws.map_b64.buf[LJWS_SIG] = p1;
643 	jws.map_b64.len[LJWS_SIG] = n;
644 
645 	p1 += n;
646 	p1 += lws_snprintf(p1, end1 - p1, "\"}");
647 
648 	free(buf);
649 
650 	return p1 - out;
651 
652 bail:
653 	lws_jws_destroy(&jws);
654 	free(buf);
655 
656 	return -1;
657 }
658 
659 static const char *protected_en[] = {
660 	"encrypted_key", "aad", "iv", "ciphertext", "tag"
661 };
662 
663 static int protected_idx[] = {
664 	LJWE_EKEY, LJWE_AAD, LJWE_IV, LJWE_CTXT, LJWE_ATAG
665 };
666 
667 /*
668  * The complete JWE may look something like this:
669  *
670  *  {
671  *    "protected":
672  *     "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
673  *    "unprotected":
674  *     {"jku":"https://server.example.com/keys.jwks"},
675  *    "recipients":[
676  *     {"header":
677  *       {"alg":"RSA1_5","kid":"2011-04-29"},
678  *      "encrypted_key":
679  *       "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-
680  *        kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx
681  *        GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3
682  *        YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh
683  *        cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg
684  *        wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A"},
685  *     {"header":
686  *       {"alg":"A128KW","kid":"7"},
687  *      "encrypted_key":
688  *       "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ"}],
689  *    "iv":
690  *     "AxY8DCtDaGlsbGljb3RoZQ",
691  *    "ciphertext":
692  *     "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
693  *    "tag":
694  *     "Mz-VPPyU4RlcuYv1IwIvzw"
695  *   }
696  *
697  *  The flattened JWE ends up like this
698  *
699  *   {
700  *    "protected": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
701  *    "unprotected": {"jku":"https://server.example.com/keys.jwks"},
702  *    "header": {"alg":"A128KW","kid":"7"},
703  *    "encrypted_key": "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ",
704  *    "iv": "AxY8DCtDaGlsbGljb3RoZQ",
705  *    "ciphertext": "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
706  *    "tag": "Mz-VPPyU4RlcuYv1IwIvzw"
707  *   }
708  *
709  *    {
710  *      "protected":"<integrity-protected header contents>",
711  *      "unprotected":<non-integrity-protected header contents>,
712  *      "header":<more non-integrity-protected header contents>,
713  *      "encrypted_key":"<encrypted key contents>",
714  *      "aad":"<additional authenticated data contents>",
715  *      "iv":"<initialization vector contents>",
716  *      "ciphertext":"<ciphertext contents>",
717  *      "tag":"<authentication tag contents>"
718  *     }
719  */
720 
721 int
lws_jwe_render_flattened(struct lws_jwe * jwe,char * out,size_t out_len)722 lws_jwe_render_flattened(struct lws_jwe *jwe, char *out, size_t out_len)
723 {
724 	char buf[3072], *p1, *end1, protected[128];
725 	int m, n, jlen, plen;
726 
727 	jlen = lws_jose_render(&jwe->jose, jwe->jws.jwk, buf, sizeof(buf));
728 	if (jlen < 0) {
729 		lwsl_err("%s: lws_jose_render failed\n", __func__);
730 
731 		return -1;
732 	}
733 
734 	/*
735 	 * prepare the JWE JSON with all the parts in
736 	 */
737 
738 	p1 = out;
739 	end1 = out + out_len - 1;
740 
741 	/*
742 	 * The protected header is b64url encoding of the JOSE header part
743 	 */
744 
745 	plen = lws_snprintf(protected, sizeof(protected),
746 			    "{\"alg\":\"%s\",\"enc\":\"%s\"}",
747 			    jwe->jose.alg->alg, jwe->jose.enc_alg->alg);
748 
749 	p1 += lws_snprintf(p1, end1 - p1, "{\"protected\":\"");
750 	jwe->jws.map_b64.buf[LJWS_JOSE] = p1;
751 	n = lws_jws_base64_enc(protected, plen, p1, end1 - p1);
752 	if (n < 0) {
753 		lwsl_notice("%s: failed to encode protected\n", __func__);
754 		goto bail;
755 	}
756 	jwe->jws.map_b64.len[LJWS_JOSE] = n;
757 	p1 += n;
758 
759 	/* unprotected not supported atm */
760 
761 	p1 += lws_snprintf(p1, end1 - p1, "\",\n\"header\":");
762 	lws_strnncpy(p1, buf, jlen, end1 - p1);
763 	p1 += strlen(p1);
764 
765 	for (m = 0; m < (int)LWS_ARRAY_SIZE(protected_en); m++)
766 		if (jwe->jws.map.buf[protected_idx[m]]) {
767 			p1 += lws_snprintf(p1, end1 - p1, ",\n\"%s\":\"",
768 					   protected_en[m]);
769 			//jwe->jws.map_b64.buf[protected_idx[m]] = p1;
770 			n = lws_jws_base64_enc(jwe->jws.map.buf[protected_idx[m]],
771 					       jwe->jws.map.len[protected_idx[m]],
772 					       p1, end1 - p1);
773 			if (n < 0) {
774 				lwsl_notice("%s: failed to encode %s\n",
775 					    __func__, protected_en[m]);
776 				goto bail;
777 			}
778 			//jwe->jws.map_b64.len[protected_idx[m]] = n;
779 			p1 += n;
780 			p1 += lws_snprintf(p1, end1 - p1, "\"");
781 		}
782 
783 	p1 += lws_snprintf(p1, end1 - p1, "\n}\n");
784 
785 	return p1 - out;
786 
787 bail:
788 	lws_jws_destroy(&jwe->jws);
789 
790 	return -1;
791 }
792