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