1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26 #include "private-lib-jose-jwe.h"
27
28 #define LWS_AESGCM_IV 12
29
30
31 int
lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe * jwe,char * temp,int * temp_len)32 lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe, char *temp, int *temp_len)
33 {
34 int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8;
35 struct lws_genrsa_ctx rsactx;
36 int n, ret = -1, ot = *temp_len;
37
38 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
39 lwsl_err("%s: wrong kty %d\n", __func__, jwe->jws.jwk->kty);
40
41 return -1;
42 }
43
44 /* create the IV + CEK */
45
46 if (lws_jws_randomize_element(jwe->jws.context, &jwe->jws.map, LJWE_IV,
47 temp, temp_len,
48 LWS_AESGCM_IV, 0))
49 return -1;
50
51 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
52 temp + (ot - *temp_len),
53 temp_len, LWS_AESGCM_TAG, 0))
54 return -1;
55
56 /* create a b64 version of the JOSE header, needed as aad */
57
58 if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
59 temp + (ot - *temp_len), temp_len,
60 jwe->jws.map.buf[LJWE_JOSE],
61 jwe->jws.map.len[LJWE_JOSE]))
62 return -1;
63
64 /*
65 * If none already, create a new, random CEK in the JWE (so it can be
66 * reused for other recipients on same payload). If it already exists,
67 * just reuse it. It will be cleansed in the JWE destroy.
68 */
69 if (!jwe->cek_valid) {
70 if (lws_get_random(jwe->jws.context, jwe->cek, (unsigned int)ekbytes) !=
71 (size_t)ekbytes) {
72 lwsl_err("%s: Problem getting random\n", __func__);
73 return -1;
74 }
75 jwe->cek_valid = 1;
76 }
77
78 if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY,
79 temp + (ot - *temp_len), temp_len,
80 jwe->cek, (unsigned int)ekbytes, 0))
81 return -1;
82
83 /* encrypt the payload */
84
85 n = lws_jwe_encrypt_gcm(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
86 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
87 (int)jwe->jws.map_b64.len[LJWE_JOSE]);
88 if (n < 0) {
89 lwsl_err("%s: lws_jwe_encrypt_gcm failed\n",
90 __func__);
91 goto bail;
92 }
93
94 /* Encrypt the CEK into EKEY to make the JWE Encrypted Key */
95
96 if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
97 !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
98 LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
99 LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
100 lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
101 __func__);
102 goto bail;
103 }
104
105 n = lws_genrsa_public_encrypt(&rsactx, jwe->cek, (unsigned int)ekbytes,
106 (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
107 lws_genrsa_destroy(&rsactx);
108 if (n < 0) {
109 lwsl_err("%s: encrypt cek fail: \n", __func__);
110 goto bail;
111 }
112
113 /* set the EKEY length to the actual enciphered length */
114 jwe->jws.map.len[LJWE_EKEY] = (unsigned int)n;
115
116 ret = (int32_t)jwe->jws.map.len[LJWE_CTXT];
117
118 bail:
119
120 return ret;
121 }
122
123 int
lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe * jwe)124 lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe)
125 {
126 int n;
127 struct lws_genrsa_ctx rsactx;
128 uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
129
130 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
131 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
132
133 return -1;
134 }
135
136 if (jwe->jws.map.len[LJWE_EKEY] < 32) {
137 lwsl_err("%s: EKEY length too short %d\n", __func__,
138 jwe->jws.map.len[LJWE_EKEY]);
139
140 return -1;
141 }
142
143 /* Decrypt the JWE Encrypted Key to get the direct CEK */
144
145 if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
146 !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
147 LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
148 LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
149 lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
150 __func__);
151 return -1;
152 }
153
154 n = lws_genrsa_private_decrypt(&rsactx,
155 (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
156 jwe->jws.map.len[LJWE_EKEY], enc_cek,
157 sizeof(enc_cek));
158 lws_genrsa_destroy(&rsactx);
159 if (n < 0) {
160 lwsl_err("%s: decrypt cek fail: \n", __func__);
161 return -1;
162 }
163
164 n = lws_jwe_auth_and_decrypt_gcm(jwe, enc_cek,
165 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
166 (int)jwe->jws.map_b64.len[LJWE_JOSE]);
167 if (n < 0) {
168 lwsl_err("%s: lws_jwe_auth_and_decrypt_gcm_hs failed\n",
169 __func__);
170 return -1;
171 }
172
173 #if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
174 /* strip padding */
175
176 n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
177 if (n > 16)
178 return -1;
179 jwe->jws.map.len[LJWE_CTXT] -= n;
180 #endif
181
182 return (int)jwe->jws.map.len[LJWE_CTXT];
183 }
184