• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 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 int
lws_jwe_encrypt_cbc_hs(struct lws_jwe * jwe,uint8_t * cek,uint8_t * aad,int aad_len)29 lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *cek,
30 		       uint8_t *aad, int aad_len)
31 {
32 	int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
33 	uint8_t digest[LWS_GENHASH_LARGEST];
34 	struct lws_gencrypto_keyelem el;
35 	struct lws_genhmac_ctx hmacctx;
36 	struct lws_genaes_ctx aesctx;
37 	size_t paddedlen;
38 	uint8_t al[8];
39 
40 	/* Caller must have prepared space for the results */
41 
42 	if (jwe->jws.map.len[LJWE_ATAG] != (unsigned int)hlen / 2) {
43 		lwsl_notice("%s: expected tag len %d, got %d\n", __func__,
44 			    hlen / 2, jwe->jws.map.len[LJWE_ATAG]);
45 		return -1;
46 	}
47 
48 	if (jwe->jws.map.len[LJWE_IV] != 16) {
49 		lwsl_notice("expected iv len %d, got %d\n", 16,
50 				jwe->jws.map.len[LJWE_IV]);
51 		return -1;
52 	}
53 
54 	/* first create the authentication hmac */
55 
56 	/* JWA Section 5.2.2.1
57 	 *
58 	 * 1.  The secondary keys MAC_KEY and ENC_KEY are generated from the
59 	 *     input key K as follows.  Each of these two keys is an octet
60 	 *     string.
61 	 *
62 	 *       MAC_KEY consists of the initial MAC_KEY_LEN octets of K, in
63 	 *        order.
64 	 *       ENC_KEY consists of the final ENC_KEY_LEN octets of K, in
65 	 *        order.
66 	 */
67 
68 	/*
69 	 *    2.  The IV used is a 128-bit value generated randomly or
70 	 *        pseudorandomly for use in the cipher.
71 	 */
72 	lws_get_random(jwe->jws.context, (void *)jwe->jws.map.buf[LJWE_IV], 16);
73 
74 	/*
75 	 *  3.  The plaintext is CBC encrypted using PKCS #7 padding using
76 	 *      ENC_KEY as the key and the IV.  We denote the ciphertext output
77 	 *      from this step as E.
78 	 */
79 
80 	/* second half is the AES ENC_KEY */
81 	el.buf = cek + (hlen / 2);
82 	el.len = hlen / 2;
83 
84 	if (lws_genaes_create(&aesctx, LWS_GAESO_ENC, LWS_GAESM_CBC, &el,
85 			      LWS_GAESP_WITH_PADDING, NULL)) {
86 		lwsl_err("%s: lws_genaes_create failed\n", __func__);
87 
88 		return -1;
89 	}
90 
91 	/*
92 	 * the plaintext gets delivered to us in LJWE_CTXT, this replaces the
93 	 * plaintext there with the ciphertext, which will be larger by some
94 	 * padding bytes
95 	 */
96 	n = lws_genaes_crypt(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
97 			     jwe->jws.map.len[LJWE_CTXT],
98 			     (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
99 			     (uint8_t *)jwe->jws.map.buf[LJWE_IV],
100 			     NULL, NULL, LWS_AES_CBC_BLOCKLEN);
101 	paddedlen = lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN,
102 						jwe->jws.map.len[LJWE_CTXT]);
103 	jwe->jws.map.len[LJWE_CTXT] = paddedlen;
104 	lws_genaes_destroy(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT] +
105 			   paddedlen - LWS_AES_CBC_BLOCKLEN, LWS_AES_CBC_BLOCKLEN);
106 	if (n) {
107 		lwsl_err("%s: lws_genaes_crypt failed\n", __func__);
108 		return -1;
109 	}
110 
111 	/*
112 	 * 4.  The octet string AL is equal to the number of bits in the
113 	 *     Additional Authenticated Data A expressed as a 64-bit unsigned
114 	 *     big-endian integer.
115 	 */
116 	lws_jwe_be64(aad_len * 8, al);
117 
118 	/* first half of the CEK is the MAC key */
119 	if (lws_genhmac_init(&hmacctx, jwe->jose.enc_alg->hmac_type,
120 				cek, hlen / 2))
121 		return -1;
122 
123 	/*
124 	 *    5.  A message Authentication Tag T is computed by applying HMAC
125 	 *    [RFC2104] to the following data, in order:
126 	 *
127 	 *     - the Additional Authenticated Data A,
128 	 *     - the Initialization Vector IV,
129 	 *     - the ciphertext E computed in the previous step, and
130 	 *     - the octet string AL defined above.
131 	 *
132 	 *    The string MAC_KEY is used as the MAC key.  We denote the output
133 	 *    of the MAC computed in this step as M.  The first T_LEN octets of
134 	 *    M are used as T.
135 	 */
136 
137 	if (lws_genhmac_update(&hmacctx, aad, aad_len) ||
138 	    lws_genhmac_update(&hmacctx, jwe->jws.map.buf[LJWE_IV],
139 			       LWS_JWE_AES_IV_BYTES) ||
140 	    /* since we encrypted it, this is the ciphertext */
141 	    lws_genhmac_update(&hmacctx,
142 			       (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
143 				          jwe->jws.map.len[LJWE_CTXT]) ||
144 	    lws_genhmac_update(&hmacctx, al, 8)) {
145 		lwsl_err("%s: hmac computation failed\n", __func__);
146 		lws_genhmac_destroy(&hmacctx, NULL);
147 		return -1;
148 	}
149 
150 	if (lws_genhmac_destroy(&hmacctx, digest)) {
151 		lwsl_err("%s: problem destroying hmac\n", __func__);
152 		return -1;
153 	}
154 
155 	/* create tag */
156 	memcpy((void *)jwe->jws.map.buf[LJWE_ATAG], digest, hlen / 2);
157 
158 	return jwe->jws.map.len[LJWE_CTXT];
159 }
160 
161 int
lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe * jwe,uint8_t * enc_cek,uint8_t * aad,int aad_len)162 lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
163 				uint8_t *aad, int aad_len)
164 {
165 	int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
166 	uint8_t digest[LWS_GENHASH_LARGEST];
167 	struct lws_gencrypto_keyelem el;
168 	struct lws_genhmac_ctx hmacctx;
169 	struct lws_genaes_ctx aesctx;
170 	uint8_t al[8];
171 
172 	/* Some sanity checks on what came in */
173 
174 	if (jwe->jws.map.len[LJWE_ATAG] != (unsigned int)hlen / 2) {
175 		lwsl_notice("%s: expected tag len %d, got %d\n", __func__,
176 				hlen / 2, jwe->jws.map.len[LJWE_ATAG]);
177 		return -1;
178 	}
179 
180 	if (jwe->jws.map.len[LJWE_IV] != 16) {
181 		lwsl_notice("expected iv len %d, got %d\n", 16,
182 				jwe->jws.map.len[LJWE_IV]);
183 		return -1;
184 	}
185 
186 	/* Prepare to check authentication
187 	 *
188 	 * AAD is the b64 JOSE header.
189 	 *
190 	 * The octet string AL, which is the number of bits in AAD expressed as
191 	 * a big-endian 64-bit unsigned integer is:
192 	 *
193 	 * [0, 0, 0, 0, 0, 0, 1, 152]
194 	 *
195 	 * Concatenate the AAD, the Initialization Vector, the ciphertext, and
196 	 * the AL value.
197 	 *
198 	 */
199 
200 	lws_jwe_be64(aad_len * 8, al);
201 
202 	/* first half of enc_cek is the MAC key */
203 	if (lws_genhmac_init(&hmacctx, jwe->jose.enc_alg->hmac_type, enc_cek,
204 			     hlen / 2)) {
205 		lwsl_err("%s: lws_genhmac_init fail\n", __func__);
206 		return -1;
207 	}
208 
209 	if (lws_genhmac_update(&hmacctx, aad, aad_len) ||
210 	    lws_genhmac_update(&hmacctx, (uint8_t *)jwe->jws.map.buf[LJWE_IV],
211 					 jwe->jws.map.len[LJWE_IV]) ||
212 	    lws_genhmac_update(&hmacctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
213 				         jwe->jws.map.len[LJWE_CTXT]) ||
214 	    lws_genhmac_update(&hmacctx, al, 8)) {
215 		lwsl_err("%s: hmac computation failed\n", __func__);
216 		lws_genhmac_destroy(&hmacctx, NULL);
217 		return -1;
218 	}
219 
220 	if (lws_genhmac_destroy(&hmacctx, digest)) {
221 		lwsl_err("%s: problem destroying hmac\n", __func__);
222 		return -1;
223 	}
224 
225 	/* first half of digest is the auth tag */
226 
227 	if (lws_timingsafe_bcmp(digest, jwe->jws.map.buf[LJWE_ATAG], hlen / 2)) {
228 		lwsl_err("%s: auth failed: hmac tag (%d) != ATAG (%d)\n",
229 			 __func__, hlen / 2, jwe->jws.map.len[LJWE_ATAG]);
230 		lwsl_hexdump_notice(jwe->jws.map.buf[LJWE_ATAG], hlen / 2);
231 		lwsl_hexdump_notice(digest, hlen / 2);
232 		return -1;
233 	}
234 
235 	/* second half of enc cek is the CEK KEY */
236 	el.buf = enc_cek + (hlen / 2);
237 	el.len = hlen / 2;
238 
239 	if (lws_genaes_create(&aesctx, LWS_GAESO_DEC, LWS_GAESM_CBC,
240 			      &el, LWS_GAESP_NO_PADDING, NULL)) {
241 		lwsl_err("%s: lws_genaes_create failed\n", __func__);
242 
243 		return -1;
244 	}
245 
246 	n = lws_genaes_crypt(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
247 			     jwe->jws.map.len[LJWE_CTXT],
248 			     (uint8_t *)jwe->jws.map.buf[LJWE_CTXT],
249 			     (uint8_t *)jwe->jws.map.buf[LJWE_IV], NULL, NULL, 16);
250 
251 	/* Strip the PKCS #7 padding */
252 
253 	if (jwe->jws.map.len[LJWE_CTXT] < LWS_AES_CBC_BLOCKLEN ||
254 	    jwe->jws.map.len[LJWE_CTXT] <= (unsigned char)jwe->jws.map.buf[LJWE_CTXT]
255 						[jwe->jws.map.len[LJWE_CTXT] - 1]) {
256 		lwsl_err("%s: invalid padded ciphertext length: %d. Corrupt data?\n",
257 				__func__, jwe->jws.map.len[LJWE_CTXT]);
258 		return -1;
259 	}
260 	jwe->jws.map.len[LJWE_CTXT] -= jwe->jws.map.buf[LJWE_CTXT][
261 						jwe->jws.map.len[LJWE_CTXT] - 1];
262 
263 	n |= lws_genaes_destroy(&aesctx, NULL, 0);
264 	if (n) {
265 		lwsl_err("%s: lws_genaes_crypt failed\n", __func__);
266 		return -1;
267 	}
268 
269 	return jwe->jws.map.len[LJWE_CTXT];
270 }
271 
272