• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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