Imported Upstream version 3.2.0
[platform/upstream/libwebsockets.git] / lib / jose / jwe / jwe-rsa-aesgcm.c
1 /*
2  * libwebsockets - JSON Web Encryption support
3  *
4  * Copyright (C) 2018 Andy Green <andy@warmcat.com>
5  *
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.
10  *
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.
15  *
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,
19  *  MA  02110-1301  USA
20  *
21  *
22  * JWE code related to aes gcm
23  *
24  */
25 #include "core/private.h"
26 #include "jose/jwe/private.h"
27
28 #define LWS_AESGCM_IV 12
29
30
31 int
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 + (ot - *temp_len), 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, ekbytes) !=
71                                                                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, 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                                 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, 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] = n;
115
116         ret = jwe->jws.map.len[LJWE_CTXT];
117
118 bail:
119
120         return ret;
121 }
122
123 int
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                                 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 jwe->jws.map.len[LJWE_CTXT];
183 }