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 * Requirements on entry: 30d4afb5ceSopenharmony_ci * 31d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_JOSE contains the ASCII JOSE header 32d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_EKEY contains cek of enc_alg hmac length 33d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_CTXT contains the plaintext 34d4afb5ceSopenharmony_ci * 35d4afb5ceSopenharmony_ci * On successful exit: 36d4afb5ceSopenharmony_ci * 37d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_ATAG contains the tag 38d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_IV contains the new random IV that was used 39d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_EKEY contains the encrypted CEK 40d4afb5ceSopenharmony_ci * - jwe->jws.map LJWE_CTXT contains the ciphertext 41d4afb5ceSopenharmony_ci * 42d4afb5ceSopenharmony_ci * Return the amount of temp used, or -1 43d4afb5ceSopenharmony_ci */ 44d4afb5ceSopenharmony_ci 45d4afb5ceSopenharmony_ciint 46d4afb5ceSopenharmony_cilws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe, 47d4afb5ceSopenharmony_ci char *temp, int *temp_len) 48d4afb5ceSopenharmony_ci{ 49d4afb5ceSopenharmony_ci int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), 50d4afb5ceSopenharmony_ci ot = *temp_len; 51d4afb5ceSopenharmony_ci char ekey[LWS_GENHASH_LARGEST]; 52d4afb5ceSopenharmony_ci struct lws_genrsa_ctx rsactx; 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) { 55d4afb5ceSopenharmony_ci lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty); 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci return -1; 58d4afb5ceSopenharmony_ci } 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci /* 61d4afb5ceSopenharmony_ci * Notice that the unencrypted EKEY coming in is smaller than the 62d4afb5ceSopenharmony_ci * RSA-encrypted EKEY going out, which is going to be the RSA key size 63d4afb5ceSopenharmony_ci * 64d4afb5ceSopenharmony_ci * Create a b64 version of the JOSE header, needed as aad 65d4afb5ceSopenharmony_ci */ 66d4afb5ceSopenharmony_ci if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE, 67d4afb5ceSopenharmony_ci temp, temp_len, 68d4afb5ceSopenharmony_ci jwe->jws.map.buf[LJWE_JOSE], 69d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_JOSE])) 70d4afb5ceSopenharmony_ci return -1; 71d4afb5ceSopenharmony_ci 72d4afb5ceSopenharmony_ci if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG, temp + (ot - *temp_len), 73d4afb5ceSopenharmony_ci temp_len, (unsigned int)hlen / 2, 0)) 74d4afb5ceSopenharmony_ci return -1; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV, temp + (ot - *temp_len), 77d4afb5ceSopenharmony_ci temp_len, LWS_JWE_AES_IV_BYTES, 0)) 78d4afb5ceSopenharmony_ci return -1; 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci /* 81d4afb5ceSopenharmony_ci * Without changing the unencrypted CEK in EKEY, reallocate enough 82d4afb5ceSopenharmony_ci * space to write the RSA-encrypted version in-situ. 83d4afb5ceSopenharmony_ci */ 84d4afb5ceSopenharmony_ci if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY, temp + (ot - *temp_len), 85d4afb5ceSopenharmony_ci temp_len, jwe->jws.map.buf[LJWE_EKEY], 86d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_EKEY], 87d4afb5ceSopenharmony_ci jwe->jws.jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len)) 88d4afb5ceSopenharmony_ci return -1; 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_ci /* Encrypt using the raw CEK (treated as MAC KEY | ENC KEY) */ 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ci n = lws_jwe_encrypt_cbc_hs(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY], 93d4afb5ceSopenharmony_ci (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE], 94d4afb5ceSopenharmony_ci (int)jwe->jws.map_b64.len[LJWE_JOSE]); 95d4afb5ceSopenharmony_ci if (n < 0) { 96d4afb5ceSopenharmony_ci lwsl_err("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__); 97d4afb5ceSopenharmony_ci return -1; 98d4afb5ceSopenharmony_ci } 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context, 101d4afb5ceSopenharmony_ci !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ? 102d4afb5ceSopenharmony_ci LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5, 103d4afb5ceSopenharmony_ci LWS_GENHASH_TYPE_UNKNOWN)) { 104d4afb5ceSopenharmony_ci lwsl_notice("%s: lws_genrsa_create\n", 105d4afb5ceSopenharmony_ci __func__); 106d4afb5ceSopenharmony_ci return -1; 107d4afb5ceSopenharmony_ci } 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci /* encrypt the CEK using RSA, mbedtls can't handle both in and out are 110d4afb5ceSopenharmony_ci * the EKEY, so copy the unencrypted ekey out temporarily */ 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci memcpy(ekey, jwe->jws.map.buf[LJWE_EKEY], (unsigned int)hlen); 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci n = lws_genrsa_public_encrypt(&rsactx, (uint8_t *)ekey, (unsigned int)hlen, 115d4afb5ceSopenharmony_ci (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]); 116d4afb5ceSopenharmony_ci lws_genrsa_destroy(&rsactx); 117d4afb5ceSopenharmony_ci lws_explicit_bzero(ekey, (unsigned int)hlen); /* cleanse the temp CEK copy */ 118d4afb5ceSopenharmony_ci if (n < 0) { 119d4afb5ceSopenharmony_ci lwsl_err("%s: encrypt cek fail\n", __func__); 120d4afb5ceSopenharmony_ci return -1; 121d4afb5ceSopenharmony_ci } 122d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_EKEY] = (unsigned int)n; /* update to encrypted EKEY size */ 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_ci /* 125d4afb5ceSopenharmony_ci * We end up with IV, ATAG, set, EKEY encrypted and CTXT is ciphertext, 126d4afb5ceSopenharmony_ci * and b64u version of ATAG in map_b64. 127d4afb5ceSopenharmony_ci */ 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci return 0; 130d4afb5ceSopenharmony_ci} 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ciint 133d4afb5ceSopenharmony_cilws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe) 134d4afb5ceSopenharmony_ci{ 135d4afb5ceSopenharmony_ci int n; 136d4afb5ceSopenharmony_ci struct lws_genrsa_ctx rsactx; 137d4afb5ceSopenharmony_ci uint8_t enc_cek[512]; 138d4afb5ceSopenharmony_ci 139d4afb5ceSopenharmony_ci if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) { 140d4afb5ceSopenharmony_ci lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty); 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci return -1; 143d4afb5ceSopenharmony_ci } 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci if (jwe->jws.map.len[LJWE_EKEY] < 40) { 146d4afb5ceSopenharmony_ci lwsl_err("%s: EKEY length too short %d\n", __func__, 147d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_EKEY]); 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci return -1; 150d4afb5ceSopenharmony_ci } 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci /* Decrypt the JWE Encrypted Key to get the raw MAC || CEK */ 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ci if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context, 155d4afb5ceSopenharmony_ci !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ? 156d4afb5ceSopenharmony_ci LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5, 157d4afb5ceSopenharmony_ci LWS_GENHASH_TYPE_UNKNOWN)) { 158d4afb5ceSopenharmony_ci lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", 159d4afb5ceSopenharmony_ci __func__); 160d4afb5ceSopenharmony_ci return -1; 161d4afb5ceSopenharmony_ci } 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci n = lws_genrsa_private_decrypt(&rsactx, 164d4afb5ceSopenharmony_ci (uint8_t *)jwe->jws.map.buf[LJWE_EKEY], 165d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_EKEY], enc_cek, 166d4afb5ceSopenharmony_ci sizeof(enc_cek)); 167d4afb5ceSopenharmony_ci lws_genrsa_destroy(&rsactx); 168d4afb5ceSopenharmony_ci if (n < 0) { 169d4afb5ceSopenharmony_ci lwsl_err("%s: decrypt cek fail: \n", __func__); 170d4afb5ceSopenharmony_ci return -1; 171d4afb5ceSopenharmony_ci } 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci n = lws_jwe_auth_and_decrypt_cbc_hs(jwe, enc_cek, 174d4afb5ceSopenharmony_ci (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE], 175d4afb5ceSopenharmony_ci (int)jwe->jws.map_b64.len[LJWE_JOSE]); 176d4afb5ceSopenharmony_ci if (n < 0) { 177d4afb5ceSopenharmony_ci lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs failed\n", 178d4afb5ceSopenharmony_ci __func__); 179d4afb5ceSopenharmony_ci return -1; 180d4afb5ceSopenharmony_ci } 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE) 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci /* strip padding */ 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1]; 187d4afb5ceSopenharmony_ci if (n > 16) { 188d4afb5ceSopenharmony_ci lwsl_err("%s: n == %d, plen %d\n", __func__, n, 189d4afb5ceSopenharmony_ci (int)jwe->jws.map.len[LJWE_CTXT]); 190d4afb5ceSopenharmony_ci return -1; 191d4afb5ceSopenharmony_ci } 192d4afb5ceSopenharmony_ci jwe->jws.map.len[LJWE_CTXT] -= n; 193d4afb5ceSopenharmony_ci#endif 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci return (int)jwe->jws.map.len[LJWE_CTXT]; 196d4afb5ceSopenharmony_ci} 197