xref: /aosp_15_r20/external/libwebsockets/lib/jose/jwe/jwe-rsa-aesgcm.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 #define LWS_AESGCM_IV 12
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker int
lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe * jwe,char * temp,int * temp_len)32*1c60b9acSAndroid Build Coastguard Worker lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe, char *temp, int *temp_len)
33*1c60b9acSAndroid Build Coastguard Worker {
34*1c60b9acSAndroid Build Coastguard Worker 	int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8;
35*1c60b9acSAndroid Build Coastguard Worker 	struct lws_genrsa_ctx rsactx;
36*1c60b9acSAndroid Build Coastguard Worker 	int n, ret = -1, ot = *temp_len;
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker 	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
39*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: wrong kty %d\n", __func__, jwe->jws.jwk->kty);
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker 		return -1;
42*1c60b9acSAndroid Build Coastguard Worker 	}
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker 	/* create the IV + CEK */
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	if (lws_jws_randomize_element(jwe->jws.context, &jwe->jws.map, LJWE_IV,
47*1c60b9acSAndroid Build Coastguard Worker 				      temp, temp_len,
48*1c60b9acSAndroid Build Coastguard Worker 				      LWS_AESGCM_IV, 0))
49*1c60b9acSAndroid Build Coastguard Worker 		return -1;
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
52*1c60b9acSAndroid Build Coastguard Worker 				  temp + (ot - *temp_len),
53*1c60b9acSAndroid Build Coastguard Worker 				  temp_len, LWS_AESGCM_TAG, 0))
54*1c60b9acSAndroid Build Coastguard Worker 		return -1;
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker 	/* create a b64 version of the JOSE header, needed as aad */
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker 	if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
59*1c60b9acSAndroid Build Coastguard Worker 				       temp + (ot - *temp_len), temp_len,
60*1c60b9acSAndroid Build Coastguard Worker 				       jwe->jws.map.buf[LJWE_JOSE],
61*1c60b9acSAndroid Build Coastguard Worker 				       jwe->jws.map.len[LJWE_JOSE]))
62*1c60b9acSAndroid Build Coastguard Worker 		return -1;
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker 	/*
65*1c60b9acSAndroid Build Coastguard Worker 	 * If none already, create a new, random CEK in the JWE (so it can be
66*1c60b9acSAndroid Build Coastguard Worker 	 * reused for other recipients on same payload).  If it already exists,
67*1c60b9acSAndroid Build Coastguard Worker 	 * just reuse it.  It will be cleansed in the JWE destroy.
68*1c60b9acSAndroid Build Coastguard Worker 	 */
69*1c60b9acSAndroid Build Coastguard Worker 	if (!jwe->cek_valid) {
70*1c60b9acSAndroid Build Coastguard Worker 		if (lws_get_random(jwe->jws.context, jwe->cek, (unsigned int)ekbytes) !=
71*1c60b9acSAndroid Build Coastguard Worker 							      (size_t)ekbytes) {
72*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Problem getting random\n", __func__);
73*1c60b9acSAndroid Build Coastguard Worker 			return -1;
74*1c60b9acSAndroid Build Coastguard Worker 		}
75*1c60b9acSAndroid Build Coastguard Worker 		jwe->cek_valid = 1;
76*1c60b9acSAndroid Build Coastguard Worker 	}
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker 	if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY,
79*1c60b9acSAndroid Build Coastguard Worker 			        temp + (ot - *temp_len), temp_len,
80*1c60b9acSAndroid Build Coastguard Worker 			        jwe->cek, (unsigned int)ekbytes, 0))
81*1c60b9acSAndroid Build Coastguard Worker 		return -1;
82*1c60b9acSAndroid Build Coastguard Worker 
83*1c60b9acSAndroid Build Coastguard Worker 	/* encrypt the payload */
84*1c60b9acSAndroid Build Coastguard Worker 
85*1c60b9acSAndroid Build Coastguard Worker 	n = lws_jwe_encrypt_gcm(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
86*1c60b9acSAndroid Build Coastguard Worker 				(uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
87*1c60b9acSAndroid Build Coastguard Worker 				(int)jwe->jws.map_b64.len[LJWE_JOSE]);
88*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
89*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: lws_jwe_encrypt_gcm failed\n",
90*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
91*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
92*1c60b9acSAndroid Build Coastguard Worker 	}
93*1c60b9acSAndroid Build Coastguard Worker 
94*1c60b9acSAndroid Build Coastguard Worker 	/* Encrypt the CEK into EKEY to make the JWE Encrypted Key */
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
97*1c60b9acSAndroid Build Coastguard Worker 			!strcmp(jwe->jose.alg->alg,   "RSA-OAEP") ?
98*1c60b9acSAndroid Build Coastguard Worker 				LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
99*1c60b9acSAndroid Build Coastguard Worker 			LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
100*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
101*1c60b9acSAndroid Build Coastguard Worker 			    __func__);
102*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
103*1c60b9acSAndroid Build Coastguard Worker 	}
104*1c60b9acSAndroid Build Coastguard Worker 
105*1c60b9acSAndroid Build Coastguard Worker 	n = lws_genrsa_public_encrypt(&rsactx, jwe->cek, (unsigned int)ekbytes,
106*1c60b9acSAndroid Build Coastguard Worker 				      (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
107*1c60b9acSAndroid Build Coastguard Worker 	lws_genrsa_destroy(&rsactx);
108*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
109*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: encrypt cek fail: \n", __func__);
110*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
111*1c60b9acSAndroid Build Coastguard Worker 	}
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 	/* set the EKEY length to the actual enciphered length */
114*1c60b9acSAndroid Build Coastguard Worker 	jwe->jws.map.len[LJWE_EKEY] = (unsigned int)n;
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 	ret = (int32_t)jwe->jws.map.len[LJWE_CTXT];
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker bail:
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 	return ret;
121*1c60b9acSAndroid Build Coastguard Worker }
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker int
lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe * jwe)124*1c60b9acSAndroid Build Coastguard Worker lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe)
125*1c60b9acSAndroid Build Coastguard Worker {
126*1c60b9acSAndroid Build Coastguard Worker 	int n;
127*1c60b9acSAndroid Build Coastguard Worker 	struct lws_genrsa_ctx rsactx;
128*1c60b9acSAndroid Build Coastguard Worker 	uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
131*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 		return -1;
134*1c60b9acSAndroid Build Coastguard Worker 	}
135*1c60b9acSAndroid Build Coastguard Worker 
136*1c60b9acSAndroid Build Coastguard Worker 	if (jwe->jws.map.len[LJWE_EKEY] < 32) {
137*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EKEY length too short %d\n", __func__,
138*1c60b9acSAndroid Build Coastguard Worker 				jwe->jws.map.len[LJWE_EKEY]);
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 		return -1;
141*1c60b9acSAndroid Build Coastguard Worker 	}
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	/* Decrypt the JWE Encrypted Key to get the direct CEK */
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
146*1c60b9acSAndroid Build Coastguard Worker 			!strcmp(jwe->jose.alg->alg,   "RSA-OAEP") ?
147*1c60b9acSAndroid Build Coastguard Worker 				LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
148*1c60b9acSAndroid Build Coastguard Worker 			LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
149*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
150*1c60b9acSAndroid Build Coastguard Worker 			    __func__);
151*1c60b9acSAndroid Build Coastguard Worker 		return -1;
152*1c60b9acSAndroid Build Coastguard Worker 	}
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker 	n = lws_genrsa_private_decrypt(&rsactx,
155*1c60b9acSAndroid Build Coastguard Worker 				       (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
156*1c60b9acSAndroid Build Coastguard Worker 				       jwe->jws.map.len[LJWE_EKEY], enc_cek,
157*1c60b9acSAndroid Build Coastguard Worker 				       sizeof(enc_cek));
158*1c60b9acSAndroid Build Coastguard Worker 	lws_genrsa_destroy(&rsactx);
159*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
160*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: decrypt cek fail: \n", __func__);
161*1c60b9acSAndroid Build Coastguard Worker 		return -1;
162*1c60b9acSAndroid Build Coastguard Worker 	}
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	n = lws_jwe_auth_and_decrypt_gcm(jwe, enc_cek,
165*1c60b9acSAndroid Build Coastguard Worker 			(uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
166*1c60b9acSAndroid Build Coastguard Worker 				(int)jwe->jws.map_b64.len[LJWE_JOSE]);
167*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
168*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: lws_jwe_auth_and_decrypt_gcm_hs failed\n",
169*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
170*1c60b9acSAndroid Build Coastguard Worker 		return -1;
171*1c60b9acSAndroid Build Coastguard Worker 	}
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
174*1c60b9acSAndroid Build Coastguard Worker 	/* strip padding */
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
177*1c60b9acSAndroid Build Coastguard Worker 	if (n > 16)
178*1c60b9acSAndroid Build Coastguard Worker 		return -1;
179*1c60b9acSAndroid Build Coastguard Worker 	jwe->jws.map.len[LJWE_CTXT] -= n;
180*1c60b9acSAndroid Build Coastguard Worker #endif
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 	return (int)jwe->jws.map.len[LJWE_CTXT];
183*1c60b9acSAndroid Build Coastguard Worker }
184