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 * RFC3394 Key Wrap uses a 128-bit key, and bloats what it is wrapping by
30d4afb5ceSopenharmony_ci * one 8-byte block.  So, if you had a 32 byte plaintext CEK to wrap, after
31d4afb5ceSopenharmony_ci * wrapping it becomes a 40 byte wrapped, enciphered, key.
32d4afb5ceSopenharmony_ci *
33d4afb5ceSopenharmony_ci * The CEK comes in from and goes out in LJWE_EKEY.  So LJWE_EKEY length
34d4afb5ceSopenharmony_ci * increases by 8 from calling this.
35d4afb5ceSopenharmony_ci */
36d4afb5ceSopenharmony_ci
37d4afb5ceSopenharmony_ciint
38d4afb5ceSopenharmony_cilws_jwe_encrypt_aeskw_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len)
39d4afb5ceSopenharmony_ci{
40d4afb5ceSopenharmony_ci	struct lws_genaes_ctx aesctx;
41d4afb5ceSopenharmony_ci	/* we are wrapping a key, so size for the worst case after wrap */
42d4afb5ceSopenharmony_ci	uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES +
43d4afb5ceSopenharmony_ci	                LWS_JWE_RFC3394_OVERHEAD_BYTES];
44d4afb5ceSopenharmony_ci	int n, m, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type),
45d4afb5ceSopenharmony_ci			 ot = *temp_len;
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_ci	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_OCT) {
48d4afb5ceSopenharmony_ci		lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_ci		return -1;
51d4afb5ceSopenharmony_ci	}
52d4afb5ceSopenharmony_ci
53d4afb5ceSopenharmony_ci	/* create a b64 version of the JOSE header, needed for hashing */
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_ci	if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
56d4afb5ceSopenharmony_ci				       temp, temp_len,
57d4afb5ceSopenharmony_ci				       jwe->jws.map.buf[LJWE_JOSE],
58d4afb5ceSopenharmony_ci				       jwe->jws.map.len[LJWE_JOSE]))
59d4afb5ceSopenharmony_ci		return -1;
60d4afb5ceSopenharmony_ci
61d4afb5ceSopenharmony_ci	/* Allocate temp space for ATAG and IV */
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_ci	if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG, temp + (ot - *temp_len),
64d4afb5ceSopenharmony_ci				  temp_len, (unsigned int)hlen / 2, 0))
65d4afb5ceSopenharmony_ci		return -1;
66d4afb5ceSopenharmony_ci
67d4afb5ceSopenharmony_ci	if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV, temp + (ot - *temp_len),
68d4afb5ceSopenharmony_ci				  temp_len, LWS_JWE_AES_IV_BYTES, 0))
69d4afb5ceSopenharmony_ci		return -1;
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci	/* 1) Encrypt the payload...  */
72d4afb5ceSopenharmony_ci
73d4afb5ceSopenharmony_ci	/* the CEK is 256-bit in the example encrypted with a 128-bit key */
74d4afb5ceSopenharmony_ci
75d4afb5ceSopenharmony_ci	n = lws_jwe_encrypt_cbc_hs(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
76d4afb5ceSopenharmony_ci				   (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
77d4afb5ceSopenharmony_ci				   (int)jwe->jws.map_b64.len[LJWE_JOSE]);
78d4afb5ceSopenharmony_ci	if (n < 0) {
79d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__);
80d4afb5ceSopenharmony_ci		return -1;
81d4afb5ceSopenharmony_ci	}
82d4afb5ceSopenharmony_ci
83d4afb5ceSopenharmony_ci	/* 2) Encrypt the JWE Encrypted Key: RFC3394 Key Wrap uses 64 bit blocks
84d4afb5ceSopenharmony_ci	 *    and 128-bit input key*/
85d4afb5ceSopenharmony_ci
86d4afb5ceSopenharmony_ci	if (lws_genaes_create(&aesctx, LWS_GAESO_ENC, LWS_GAESM_KW,
87d4afb5ceSopenharmony_ci			      jwe->jws.jwk->e, 1, NULL)) {
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci		lwsl_notice("%s: lws_genaes_create\n", __func__);
90d4afb5ceSopenharmony_ci		return -1;
91d4afb5ceSopenharmony_ci	}
92d4afb5ceSopenharmony_ci
93d4afb5ceSopenharmony_ci	/* tag size is determined by enc cipher key length */
94d4afb5ceSopenharmony_ci
95d4afb5ceSopenharmony_ci	n = lws_genaes_crypt(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
96d4afb5ceSopenharmony_ci			     jwe->jws.map.len[LJWE_EKEY], enc_cek, NULL, NULL, NULL,
97d4afb5ceSopenharmony_ci			     lws_gencrypto_bits_to_bytes(
98d4afb5ceSopenharmony_ci					     jwe->jose.enc_alg->keybits_fixed));
99d4afb5ceSopenharmony_ci	m = lws_genaes_destroy(&aesctx, NULL, 0);
100d4afb5ceSopenharmony_ci	if (n < 0) {
101d4afb5ceSopenharmony_ci		lwsl_err("%s: encrypt cek fail\n", __func__);
102d4afb5ceSopenharmony_ci		return -1;
103d4afb5ceSopenharmony_ci	}
104d4afb5ceSopenharmony_ci	if (m < 0) {
105d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
106d4afb5ceSopenharmony_ci		return -1;
107d4afb5ceSopenharmony_ci	}
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	jwe->jws.map.len[LJWE_EKEY] += LWS_JWE_RFC3394_OVERHEAD_BYTES;
110d4afb5ceSopenharmony_ci	memcpy((uint8_t *)jwe->jws.map.buf[LJWE_EKEY], enc_cek,
111d4afb5ceSopenharmony_ci	       jwe->jws.map.len[LJWE_EKEY]);
112d4afb5ceSopenharmony_ci
113d4afb5ceSopenharmony_ci	return (int)jwe->jws.map.len[LJWE_CTXT];
114d4afb5ceSopenharmony_ci}
115d4afb5ceSopenharmony_ci
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ciint
118d4afb5ceSopenharmony_cilws_jwe_auth_and_decrypt_aeskw_cbc_hs(struct lws_jwe *jwe)
119d4afb5ceSopenharmony_ci{
120d4afb5ceSopenharmony_ci	struct lws_genaes_ctx aesctx;
121d4afb5ceSopenharmony_ci	uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES +
122d4afb5ceSopenharmony_ci	                LWS_JWE_RFC3394_OVERHEAD_BYTES];
123d4afb5ceSopenharmony_ci	int n, m;
124d4afb5ceSopenharmony_ci
125d4afb5ceSopenharmony_ci	if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_OCT) {
126d4afb5ceSopenharmony_ci		lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
127d4afb5ceSopenharmony_ci
128d4afb5ceSopenharmony_ci		return -1;
129d4afb5ceSopenharmony_ci	}
130d4afb5ceSopenharmony_ci
131d4afb5ceSopenharmony_ci	/* the CEK is 256-bit in the example encrypted with a 128-bit key */
132d4afb5ceSopenharmony_ci
133d4afb5ceSopenharmony_ci	if (jwe->jws.map.len[LJWE_EKEY] > sizeof(enc_cek))
134d4afb5ceSopenharmony_ci		return -1;
135d4afb5ceSopenharmony_ci
136d4afb5ceSopenharmony_ci	/* 1) Decrypt the JWE Encrypted Key to get the raw MAC / CEK */
137d4afb5ceSopenharmony_ci
138d4afb5ceSopenharmony_ci	if (lws_genaes_create(&aesctx, LWS_GAESO_DEC, LWS_GAESM_KW,
139d4afb5ceSopenharmony_ci			      jwe->jws.jwk->e, 1, NULL)) {
140d4afb5ceSopenharmony_ci
141d4afb5ceSopenharmony_ci		lwsl_notice("%s: lws_genaes_create\n", __func__);
142d4afb5ceSopenharmony_ci		return -1;
143d4afb5ceSopenharmony_ci	}
144d4afb5ceSopenharmony_ci
145d4afb5ceSopenharmony_ci	/*
146d4afb5ceSopenharmony_ci	 * Decrypt the CEK into enc_cek
147d4afb5ceSopenharmony_ci	 * tag size is determined by enc cipher key length */
148d4afb5ceSopenharmony_ci
149d4afb5ceSopenharmony_ci	n = lws_genaes_crypt(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
150d4afb5ceSopenharmony_ci			     jwe->jws.map.len[LJWE_EKEY], enc_cek, NULL, NULL, NULL,
151d4afb5ceSopenharmony_ci			     lws_gencrypto_bits_to_bytes(
152d4afb5ceSopenharmony_ci					     jwe->jose.enc_alg->keybits_fixed));
153d4afb5ceSopenharmony_ci	m = lws_genaes_destroy(&aesctx, NULL, 0);
154d4afb5ceSopenharmony_ci	if (n < 0) {
155d4afb5ceSopenharmony_ci		lwsl_err("%s: decrypt CEK fail\n", __func__);
156d4afb5ceSopenharmony_ci		return -1;
157d4afb5ceSopenharmony_ci	}
158d4afb5ceSopenharmony_ci	if (m < 0) {
159d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
160d4afb5ceSopenharmony_ci		return -1;
161d4afb5ceSopenharmony_ci	}
162d4afb5ceSopenharmony_ci
163d4afb5ceSopenharmony_ci	/* 2) Decrypt the payload */
164d4afb5ceSopenharmony_ci
165d4afb5ceSopenharmony_ci	n = lws_jwe_auth_and_decrypt_cbc_hs(jwe, enc_cek,
166d4afb5ceSopenharmony_ci			     (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
167d4afb5ceSopenharmony_ci			     (int)jwe->jws.map_b64.len[LJWE_JOSE]);
168d4afb5ceSopenharmony_ci	if (n < 0) {
169d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs failed\n",
170d4afb5ceSopenharmony_ci				__func__);
171d4afb5ceSopenharmony_ci		return -1;
172d4afb5ceSopenharmony_ci	}
173d4afb5ceSopenharmony_ci
174d4afb5ceSopenharmony_ci	return (int)jwe->jws.map.len[LJWE_CTXT];
175d4afb5ceSopenharmony_ci}
176d4afb5ceSopenharmony_ci
177d4afb5ceSopenharmony_ci
178