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