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 * Requirements on entry:
30d4afb5ceSopenharmony_ci *
31d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_JOSE contains the ASCII JOSE header
32d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_EKEY contains cek of enc_alg hmac length
33d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_CTXT contains the plaintext
34d4afb5ceSopenharmony_ci *
35d4afb5ceSopenharmony_ci * On successful exit:
36d4afb5ceSopenharmony_ci *
37d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_ATAG contains the tag
38d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_IV contains the new random IV that was used
39d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_EKEY contains the encrypted CEK
40d4afb5ceSopenharmony_ci *  - jwe->jws.map LJWE_CTXT contains the ciphertext
41d4afb5ceSopenharmony_ci *
42d4afb5ceSopenharmony_ci *  Return the amount of temp used, or -1
43d4afb5ceSopenharmony_ci */
44d4afb5ceSopenharmony_ci
45d4afb5ceSopenharmony_ciint
46d4afb5ceSopenharmony_cilws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe,
47d4afb5ceSopenharmony_ci			       char *temp, int *temp_len)
48d4afb5ceSopenharmony_ci{
49d4afb5ceSopenharmony_ci	int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type),
50d4afb5ceSopenharmony_ci	    ot = *temp_len;
51d4afb5ceSopenharmony_ci	char ekey[LWS_GENHASH_LARGEST];
52d4afb5ceSopenharmony_ci	struct lws_genrsa_ctx rsactx;
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_ci	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
55d4afb5ceSopenharmony_ci		lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
56d4afb5ceSopenharmony_ci
57d4afb5ceSopenharmony_ci		return -1;
58d4afb5ceSopenharmony_ci	}
59d4afb5ceSopenharmony_ci
60d4afb5ceSopenharmony_ci	/*
61d4afb5ceSopenharmony_ci	 * Notice that the unencrypted EKEY coming in is smaller than the
62d4afb5ceSopenharmony_ci	 * RSA-encrypted EKEY going out, which is going to be the RSA key size
63d4afb5ceSopenharmony_ci	 *
64d4afb5ceSopenharmony_ci	 * Create a b64 version of the JOSE header, needed as aad
65d4afb5ceSopenharmony_ci	 */
66d4afb5ceSopenharmony_ci	if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
67d4afb5ceSopenharmony_ci				       temp, temp_len,
68d4afb5ceSopenharmony_ci				       jwe->jws.map.buf[LJWE_JOSE],
69d4afb5ceSopenharmony_ci				       jwe->jws.map.len[LJWE_JOSE]))
70d4afb5ceSopenharmony_ci		return -1;
71d4afb5ceSopenharmony_ci
72d4afb5ceSopenharmony_ci	if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG, temp + (ot - *temp_len),
73d4afb5ceSopenharmony_ci				  temp_len, (unsigned int)hlen / 2, 0))
74d4afb5ceSopenharmony_ci		return -1;
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ci	if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV, temp + (ot - *temp_len),
77d4afb5ceSopenharmony_ci				  temp_len, LWS_JWE_AES_IV_BYTES, 0))
78d4afb5ceSopenharmony_ci		return -1;
79d4afb5ceSopenharmony_ci
80d4afb5ceSopenharmony_ci	/*
81d4afb5ceSopenharmony_ci	 * Without changing the unencrypted CEK in EKEY, reallocate enough
82d4afb5ceSopenharmony_ci	 * space to write the RSA-encrypted version in-situ.
83d4afb5ceSopenharmony_ci	 */
84d4afb5ceSopenharmony_ci	if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY, temp + (ot - *temp_len),
85d4afb5ceSopenharmony_ci				temp_len, jwe->jws.map.buf[LJWE_EKEY],
86d4afb5ceSopenharmony_ci				jwe->jws.map.len[LJWE_EKEY],
87d4afb5ceSopenharmony_ci				jwe->jws.jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len))
88d4afb5ceSopenharmony_ci		return -1;
89d4afb5ceSopenharmony_ci
90d4afb5ceSopenharmony_ci	/* Encrypt using the raw CEK (treated as MAC KEY | ENC KEY) */
91d4afb5ceSopenharmony_ci
92d4afb5ceSopenharmony_ci	n = lws_jwe_encrypt_cbc_hs(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
93d4afb5ceSopenharmony_ci				     (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
94d4afb5ceSopenharmony_ci				     (int)jwe->jws.map_b64.len[LJWE_JOSE]);
95d4afb5ceSopenharmony_ci	if (n < 0) {
96d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__);
97d4afb5ceSopenharmony_ci		return -1;
98d4afb5ceSopenharmony_ci	}
99d4afb5ceSopenharmony_ci
100d4afb5ceSopenharmony_ci	if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
101d4afb5ceSopenharmony_ci			!strcmp(jwe->jose.alg->alg,   "RSA-OAEP") ?
102d4afb5ceSopenharmony_ci					LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
103d4afb5ceSopenharmony_ci					LWS_GENHASH_TYPE_UNKNOWN)) {
104d4afb5ceSopenharmony_ci		lwsl_notice("%s: lws_genrsa_create\n",
105d4afb5ceSopenharmony_ci			    __func__);
106d4afb5ceSopenharmony_ci		return -1;
107d4afb5ceSopenharmony_ci	}
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	/* encrypt the CEK using RSA, mbedtls can't handle both in and out are
110d4afb5ceSopenharmony_ci	 * the EKEY, so copy the unencrypted ekey out temporarily */
111d4afb5ceSopenharmony_ci
112d4afb5ceSopenharmony_ci	memcpy(ekey, jwe->jws.map.buf[LJWE_EKEY], (unsigned int)hlen);
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ci	n = lws_genrsa_public_encrypt(&rsactx, (uint8_t *)ekey, (unsigned int)hlen,
115d4afb5ceSopenharmony_ci				      (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
116d4afb5ceSopenharmony_ci	lws_genrsa_destroy(&rsactx);
117d4afb5ceSopenharmony_ci	lws_explicit_bzero(ekey, (unsigned int)hlen); /* cleanse the temp CEK copy */
118d4afb5ceSopenharmony_ci	if (n < 0) {
119d4afb5ceSopenharmony_ci		lwsl_err("%s: encrypt cek fail\n", __func__);
120d4afb5ceSopenharmony_ci		return -1;
121d4afb5ceSopenharmony_ci	}
122d4afb5ceSopenharmony_ci	jwe->jws.map.len[LJWE_EKEY] = (unsigned int)n; /* update to encrypted EKEY size */
123d4afb5ceSopenharmony_ci
124d4afb5ceSopenharmony_ci	/*
125d4afb5ceSopenharmony_ci	 * We end up with IV, ATAG, set, EKEY encrypted and CTXT is ciphertext,
126d4afb5ceSopenharmony_ci	 * and b64u version of ATAG in map_b64.
127d4afb5ceSopenharmony_ci	 */
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ci	return 0;
130d4afb5ceSopenharmony_ci}
131d4afb5ceSopenharmony_ci
132d4afb5ceSopenharmony_ciint
133d4afb5ceSopenharmony_cilws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe)
134d4afb5ceSopenharmony_ci{
135d4afb5ceSopenharmony_ci	int n;
136d4afb5ceSopenharmony_ci	struct lws_genrsa_ctx rsactx;
137d4afb5ceSopenharmony_ci	uint8_t enc_cek[512];
138d4afb5ceSopenharmony_ci
139d4afb5ceSopenharmony_ci	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
140d4afb5ceSopenharmony_ci		lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
141d4afb5ceSopenharmony_ci
142d4afb5ceSopenharmony_ci		return -1;
143d4afb5ceSopenharmony_ci	}
144d4afb5ceSopenharmony_ci
145d4afb5ceSopenharmony_ci	if (jwe->jws.map.len[LJWE_EKEY] < 40) {
146d4afb5ceSopenharmony_ci		lwsl_err("%s: EKEY length too short %d\n", __func__,
147d4afb5ceSopenharmony_ci				jwe->jws.map.len[LJWE_EKEY]);
148d4afb5ceSopenharmony_ci
149d4afb5ceSopenharmony_ci		return -1;
150d4afb5ceSopenharmony_ci	}
151d4afb5ceSopenharmony_ci
152d4afb5ceSopenharmony_ci	/* Decrypt the JWE Encrypted Key to get the raw MAC || CEK */
153d4afb5ceSopenharmony_ci
154d4afb5ceSopenharmony_ci	if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
155d4afb5ceSopenharmony_ci			!strcmp(jwe->jose.alg->alg,   "RSA-OAEP") ?
156d4afb5ceSopenharmony_ci				LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
157d4afb5ceSopenharmony_ci				LWS_GENHASH_TYPE_UNKNOWN)) {
158d4afb5ceSopenharmony_ci		lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
159d4afb5ceSopenharmony_ci			    __func__);
160d4afb5ceSopenharmony_ci		return -1;
161d4afb5ceSopenharmony_ci	}
162d4afb5ceSopenharmony_ci
163d4afb5ceSopenharmony_ci	n = lws_genrsa_private_decrypt(&rsactx,
164d4afb5ceSopenharmony_ci				       (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
165d4afb5ceSopenharmony_ci				       jwe->jws.map.len[LJWE_EKEY], enc_cek,
166d4afb5ceSopenharmony_ci				       sizeof(enc_cek));
167d4afb5ceSopenharmony_ci	lws_genrsa_destroy(&rsactx);
168d4afb5ceSopenharmony_ci	if (n < 0) {
169d4afb5ceSopenharmony_ci		lwsl_err("%s: decrypt cek fail: \n", __func__);
170d4afb5ceSopenharmony_ci		return -1;
171d4afb5ceSopenharmony_ci	}
172d4afb5ceSopenharmony_ci
173d4afb5ceSopenharmony_ci	n = lws_jwe_auth_and_decrypt_cbc_hs(jwe, enc_cek,
174d4afb5ceSopenharmony_ci			     (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
175d4afb5ceSopenharmony_ci			     (int)jwe->jws.map_b64.len[LJWE_JOSE]);
176d4afb5ceSopenharmony_ci	if (n < 0) {
177d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs failed\n",
178d4afb5ceSopenharmony_ci			 __func__);
179d4afb5ceSopenharmony_ci		return -1;
180d4afb5ceSopenharmony_ci	}
181d4afb5ceSopenharmony_ci
182d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
183d4afb5ceSopenharmony_ci
184d4afb5ceSopenharmony_ci	/* strip padding */
185d4afb5ceSopenharmony_ci
186d4afb5ceSopenharmony_ci	n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
187d4afb5ceSopenharmony_ci	if (n > 16) {
188d4afb5ceSopenharmony_ci		lwsl_err("%s: n == %d, plen %d\n", __func__, n,
189d4afb5ceSopenharmony_ci				(int)jwe->jws.map.len[LJWE_CTXT]);
190d4afb5ceSopenharmony_ci		return -1;
191d4afb5ceSopenharmony_ci	}
192d4afb5ceSopenharmony_ci	jwe->jws.map.len[LJWE_CTXT] -= n;
193d4afb5ceSopenharmony_ci#endif
194d4afb5ceSopenharmony_ci
195d4afb5ceSopenharmony_ci	return (int)jwe->jws.map.len[LJWE_CTXT];
196d4afb5ceSopenharmony_ci}
197