2 * libwebsockets - JSON Web Encryption support
4 * Copyright (C) 2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * JWE code related to aes gcm
25 #include "core/private.h"
26 #include "jose/jwe/private.h"
28 #define LWS_AESGCM_IV 12
32 lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe, char *temp, int *temp_len)
34 int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8;
35 struct lws_genrsa_ctx rsactx;
36 int n, ret = -1, ot = *temp_len;
38 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
39 lwsl_err("%s: wrong kty %d\n", __func__, jwe->jws.jwk->kty);
44 /* create the IV + CEK */
46 if (lws_jws_randomize_element(jwe->jws.context, &jwe->jws.map, LJWE_IV,
47 temp + (ot - *temp_len), temp_len,
51 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
52 temp + (ot - *temp_len),
53 temp_len, LWS_AESGCM_TAG, 0))
56 /* create a b64 version of the JOSE header, needed as aad */
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]))
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.
69 if (!jwe->cek_valid) {
70 if (lws_get_random(jwe->jws.context, jwe->cek, ekbytes) !=
72 lwsl_err("%s: Problem getting random\n", __func__);
78 if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY,
79 temp + (ot - *temp_len), temp_len,
80 jwe->cek, ekbytes, 0))
83 /* encrypt the payload */
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 jwe->jws.map_b64.len[LJWE_JOSE]);
89 lwsl_err("%s: lws_jwe_encrypt_gcm failed\n",
94 /* Encrypt the CEK into EKEY to make the JWE Encrypted Key */
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",
105 n = lws_genrsa_public_encrypt(&rsactx, jwe->cek, ekbytes,
106 (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
107 lws_genrsa_destroy(&rsactx);
109 lwsl_err("%s: encrypt cek fail: \n", __func__);
113 /* set the EKEY length to the actual enciphered length */
114 jwe->jws.map.len[LJWE_EKEY] = n;
116 ret = jwe->jws.map.len[LJWE_CTXT];
124 lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe)
127 struct lws_genrsa_ctx rsactx;
128 uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
130 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
131 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
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]);
143 /* Decrypt the JWE Encrypted Key to get the direct CEK */
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",
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,
158 lws_genrsa_destroy(&rsactx);
160 lwsl_err("%s: decrypt cek fail: \n", __func__);
164 n = lws_jwe_auth_and_decrypt_gcm(jwe, enc_cek,
165 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
166 jwe->jws.map_b64.len[LJWE_JOSE]);
168 lwsl_err("%s: lws_jwe_auth_and_decrypt_gcm_hs failed\n",
173 #if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
176 n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
179 jwe->jws.map.len[LJWE_CTXT] -= n;
182 return jwe->jws.map.len[LJWE_CTXT];