189ed30d1SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 289ed30d1SJens Wiklander /* 389ed30d1SJens Wiklander * Copyright (c) 2014-2019, Linaro Limited 489ed30d1SJens Wiklander */ 589ed30d1SJens Wiklander 689ed30d1SJens Wiklander #include <crypto/crypto.h> 789ed30d1SJens Wiklander #include <stdlib.h> 889ed30d1SJens Wiklander #include <string.h> 989ed30d1SJens Wiklander #include <tee_api_types.h> 1089ed30d1SJens Wiklander #include <tee_api_defines_extensions.h> 1189ed30d1SJens Wiklander #include <tee/tee_cryp_utl.h> 1289ed30d1SJens Wiklander #include <trace.h> 1389ed30d1SJens Wiklander #include <utee_defines.h> 1489ed30d1SJens Wiklander 1589ed30d1SJens Wiklander #include "acipher_helpers.h" 1689ed30d1SJens Wiklander 1789ed30d1SJens Wiklander 1889ed30d1SJens Wiklander /* 1989ed30d1SJens Wiklander * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo" 2089ed30d1SJens Wiklander * Return 2189ed30d1SJens Wiklander * - TEE_SUCCESS in case of success, 2289ed30d1SJens Wiklander * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo 2389ed30d1SJens Wiklander * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC 2489ed30d1SJens Wiklander * Return -1 in case of error 2589ed30d1SJens Wiklander */ 2689ed30d1SJens Wiklander static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex) 2789ed30d1SJens Wiklander { 2889ed30d1SJens Wiklander switch (algo) { 29a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA1) 3089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 3189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 3289ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: 3389ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha1"); 3489ed30d1SJens Wiklander break; 3589ed30d1SJens Wiklander #endif 36a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_MD5) 3789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 3889ed30d1SJens Wiklander *ltc_hashindex = find_hash("md5"); 3989ed30d1SJens Wiklander break; 4089ed30d1SJens Wiklander #endif 41a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA224) 4289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 4389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 4489ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: 4589ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha224"); 4689ed30d1SJens Wiklander break; 4789ed30d1SJens Wiklander #endif 48a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA256) 4989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 5089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 5189ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: 5289ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha256"); 5389ed30d1SJens Wiklander break; 5489ed30d1SJens Wiklander #endif 55a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA384) 5689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 5789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 5889ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: 5989ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha384"); 6089ed30d1SJens Wiklander break; 6189ed30d1SJens Wiklander #endif 62a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA512) 6389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 6489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 6589ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: 6689ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha512"); 6789ed30d1SJens Wiklander break; 6889ed30d1SJens Wiklander #endif 6989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 7089ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_V1_5: 7189ed30d1SJens Wiklander /* invalid one. but it should not be used anyway */ 7289ed30d1SJens Wiklander *ltc_hashindex = -1; 7389ed30d1SJens Wiklander return TEE_SUCCESS; 7489ed30d1SJens Wiklander 7589ed30d1SJens Wiklander default: 7689ed30d1SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 7789ed30d1SJens Wiklander } 7889ed30d1SJens Wiklander 7989ed30d1SJens Wiklander if (*ltc_hashindex < 0) 8089ed30d1SJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 8189ed30d1SJens Wiklander else 8289ed30d1SJens Wiklander return TEE_SUCCESS; 8389ed30d1SJens Wiklander } 8489ed30d1SJens Wiklander 8589ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, 8689ed30d1SJens Wiklander size_t key_size_bits __unused) 8789ed30d1SJens Wiklander { 8889ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 8989ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 9089ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 9189ed30d1SJens Wiklander if (!bn_alloc_max(&s->d)) 9289ed30d1SJens Wiklander goto err; 9389ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 9489ed30d1SJens Wiklander goto err; 9589ed30d1SJens Wiklander if (!bn_alloc_max(&s->p)) 9689ed30d1SJens Wiklander goto err; 9789ed30d1SJens Wiklander if (!bn_alloc_max(&s->q)) 9889ed30d1SJens Wiklander goto err; 9989ed30d1SJens Wiklander if (!bn_alloc_max(&s->qp)) 10089ed30d1SJens Wiklander goto err; 10189ed30d1SJens Wiklander if (!bn_alloc_max(&s->dp)) 10289ed30d1SJens Wiklander goto err; 10389ed30d1SJens Wiklander if (!bn_alloc_max(&s->dq)) 10489ed30d1SJens Wiklander goto err; 10589ed30d1SJens Wiklander 10689ed30d1SJens Wiklander return TEE_SUCCESS; 10789ed30d1SJens Wiklander err: 108*92e38694SJerome Forissier crypto_acipher_free_rsa_keypair(s); 10989ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 11089ed30d1SJens Wiklander } 11189ed30d1SJens Wiklander 11289ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, 11389ed30d1SJens Wiklander size_t key_size_bits __unused) 11489ed30d1SJens Wiklander { 11589ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 11689ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 11789ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 11889ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 11989ed30d1SJens Wiklander goto err; 12089ed30d1SJens Wiklander return TEE_SUCCESS; 12189ed30d1SJens Wiklander err: 12289ed30d1SJens Wiklander crypto_bignum_free(s->e); 12389ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 12489ed30d1SJens Wiklander } 12589ed30d1SJens Wiklander 12689ed30d1SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) 12789ed30d1SJens Wiklander { 12889ed30d1SJens Wiklander if (!s) 12989ed30d1SJens Wiklander return; 13089ed30d1SJens Wiklander crypto_bignum_free(s->n); 13189ed30d1SJens Wiklander crypto_bignum_free(s->e); 13289ed30d1SJens Wiklander } 13389ed30d1SJens Wiklander 134a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) 135a1d5c81fSElias von Däniken { 136a1d5c81fSElias von Däniken if (!s) 137a1d5c81fSElias von Däniken return; 138a1d5c81fSElias von Däniken crypto_bignum_free(s->e); 139a1d5c81fSElias von Däniken crypto_bignum_free(s->d); 140a1d5c81fSElias von Däniken crypto_bignum_free(s->n); 141a1d5c81fSElias von Däniken crypto_bignum_free(s->p); 142a1d5c81fSElias von Däniken crypto_bignum_free(s->q); 143a1d5c81fSElias von Däniken crypto_bignum_free(s->qp); 144a1d5c81fSElias von Däniken crypto_bignum_free(s->dp); 14585f7c554SJerome Forissier crypto_bignum_free(s->dq); 146a1d5c81fSElias von Däniken } 147a1d5c81fSElias von Däniken 14889ed30d1SJens Wiklander TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) 14989ed30d1SJens Wiklander { 15089ed30d1SJens Wiklander TEE_Result res; 15189ed30d1SJens Wiklander rsa_key ltc_tmp_key; 15289ed30d1SJens Wiklander int ltc_res; 15389ed30d1SJens Wiklander long e; 15489ed30d1SJens Wiklander 15589ed30d1SJens Wiklander /* get the public exponent */ 15689ed30d1SJens Wiklander e = mp_get_int(key->e); 15789ed30d1SJens Wiklander 15889ed30d1SJens Wiklander /* Generate a temporary RSA key */ 1591f3b1115SJens Wiklander ltc_res = rsa_make_key(NULL, find_prng("prng_crypto"), key_size / 8, e, 16089ed30d1SJens Wiklander <c_tmp_key); 16189ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 16289ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 16389ed30d1SJens Wiklander } else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) { 16489ed30d1SJens Wiklander rsa_free(<c_tmp_key); 16589ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 16689ed30d1SJens Wiklander } else { 16789ed30d1SJens Wiklander /* Copy the key */ 16889ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.e, key->e); 16989ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.d, key->d); 17089ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.N, key->n); 17189ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.p, key->p); 17289ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.q, key->q); 17389ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.qP, key->qp); 17489ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dP, key->dp); 17589ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dQ, key->dq); 17689ed30d1SJens Wiklander 17789ed30d1SJens Wiklander /* Free the temporary key */ 17889ed30d1SJens Wiklander rsa_free(<c_tmp_key); 17989ed30d1SJens Wiklander res = TEE_SUCCESS; 18089ed30d1SJens Wiklander } 18189ed30d1SJens Wiklander 18289ed30d1SJens Wiklander return res; 18389ed30d1SJens Wiklander } 18489ed30d1SJens Wiklander 18589ed30d1SJens Wiklander static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src, 18689ed30d1SJens Wiklander size_t src_len, uint8_t *dst, size_t *dst_len) 18789ed30d1SJens Wiklander { 18889ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 18989ed30d1SJens Wiklander uint8_t *buf = NULL; 19089ed30d1SJens Wiklander unsigned long blen, offset; 19189ed30d1SJens Wiklander int ltc_res; 19289ed30d1SJens Wiklander 19389ed30d1SJens Wiklander /* 19489ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large the 19589ed30d1SJens Wiklander * required size of the out buffer without doing a partial decrypt. 19689ed30d1SJens Wiklander * We know the upper bound though. 19789ed30d1SJens Wiklander */ 198a1cbb728SJens Wiklander blen = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t); 19989ed30d1SJens Wiklander buf = malloc(blen); 20089ed30d1SJens Wiklander if (!buf) { 20189ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 20289ed30d1SJens Wiklander goto out; 20389ed30d1SJens Wiklander } 20489ed30d1SJens Wiklander 20589ed30d1SJens Wiklander ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type, 20689ed30d1SJens Wiklander ltc_key); 20789ed30d1SJens Wiklander switch (ltc_res) { 20889ed30d1SJens Wiklander case CRYPT_PK_NOT_PRIVATE: 20989ed30d1SJens Wiklander case CRYPT_PK_INVALID_TYPE: 21089ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 21189ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 21289ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 21389ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 21489ed30d1SJens Wiklander goto out; 21589ed30d1SJens Wiklander case CRYPT_OK: 21689ed30d1SJens Wiklander break; 21789ed30d1SJens Wiklander default: 21889ed30d1SJens Wiklander /* This will result in a panic */ 21989ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 22089ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 22189ed30d1SJens Wiklander goto out; 22289ed30d1SJens Wiklander } 22389ed30d1SJens Wiklander 22489ed30d1SJens Wiklander /* Remove the zero-padding (leave one zero if buff is all zeroes) */ 22589ed30d1SJens Wiklander offset = 0; 22689ed30d1SJens Wiklander while ((offset < blen - 1) && (buf[offset] == 0)) 22789ed30d1SJens Wiklander offset++; 22889ed30d1SJens Wiklander 22989ed30d1SJens Wiklander if (*dst_len < blen - offset) { 23089ed30d1SJens Wiklander *dst_len = blen - offset; 23189ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 23289ed30d1SJens Wiklander goto out; 23389ed30d1SJens Wiklander } 23489ed30d1SJens Wiklander 23589ed30d1SJens Wiklander res = TEE_SUCCESS; 23689ed30d1SJens Wiklander *dst_len = blen - offset; 23789ed30d1SJens Wiklander memcpy(dst, (char *)buf + offset, *dst_len); 23889ed30d1SJens Wiklander 23989ed30d1SJens Wiklander out: 24089ed30d1SJens Wiklander if (buf) 24189ed30d1SJens Wiklander free(buf); 24289ed30d1SJens Wiklander 24389ed30d1SJens Wiklander return res; 24489ed30d1SJens Wiklander } 24589ed30d1SJens Wiklander 24689ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, 24789ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 24889ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 24989ed30d1SJens Wiklander { 25089ed30d1SJens Wiklander TEE_Result res; 25189ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 25289ed30d1SJens Wiklander 25389ed30d1SJens Wiklander ltc_key.type = PK_PUBLIC; 25489ed30d1SJens Wiklander ltc_key.e = key->e; 25589ed30d1SJens Wiklander ltc_key.N = key->n; 25689ed30d1SJens Wiklander 25789ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 25889ed30d1SJens Wiklander return res; 25989ed30d1SJens Wiklander } 26089ed30d1SJens Wiklander 26189ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, 26289ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 26389ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 26489ed30d1SJens Wiklander { 26589ed30d1SJens Wiklander TEE_Result res; 26689ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 26789ed30d1SJens Wiklander 26889ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 26989ed30d1SJens Wiklander ltc_key.e = key->e; 27089ed30d1SJens Wiklander ltc_key.N = key->n; 27189ed30d1SJens Wiklander ltc_key.d = key->d; 27289ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 27389ed30d1SJens Wiklander ltc_key.p = key->p; 27489ed30d1SJens Wiklander ltc_key.q = key->q; 27589ed30d1SJens Wiklander ltc_key.qP = key->qp; 27689ed30d1SJens Wiklander ltc_key.dP = key->dp; 27789ed30d1SJens Wiklander ltc_key.dQ = key->dq; 27889ed30d1SJens Wiklander } 27989ed30d1SJens Wiklander 28089ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 28189ed30d1SJens Wiklander return res; 28289ed30d1SJens Wiklander } 28389ed30d1SJens Wiklander 28489ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, 28589ed30d1SJens Wiklander const uint8_t *label, size_t label_len, 28689ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 28789ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 28889ed30d1SJens Wiklander { 28989ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 29089ed30d1SJens Wiklander void *buf = NULL; 29189ed30d1SJens Wiklander unsigned long blen; 29289ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo; 29389ed30d1SJens Wiklander size_t mod_size; 29489ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 29589ed30d1SJens Wiklander 29689ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 29789ed30d1SJens Wiklander ltc_key.e = key->e; 29889ed30d1SJens Wiklander ltc_key.d = key->d; 29989ed30d1SJens Wiklander ltc_key.N = key->n; 30089ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 30189ed30d1SJens Wiklander ltc_key.p = key->p; 30289ed30d1SJens Wiklander ltc_key.q = key->q; 30389ed30d1SJens Wiklander ltc_key.qP = key->qp; 30489ed30d1SJens Wiklander ltc_key.dP = key->dp; 30589ed30d1SJens Wiklander ltc_key.dQ = key->dq; 30689ed30d1SJens Wiklander } 30789ed30d1SJens Wiklander 30889ed30d1SJens Wiklander /* Get the algorithm */ 30989ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 31089ed30d1SJens Wiklander if (res != TEE_SUCCESS) { 31189ed30d1SJens Wiklander EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res); 31289ed30d1SJens Wiklander goto out; 31389ed30d1SJens Wiklander } 31489ed30d1SJens Wiklander 31589ed30d1SJens Wiklander /* 31689ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large 31789ed30d1SJens Wiklander * the required size of the out buffer without doing a partial 31889ed30d1SJens Wiklander * decrypt. We know the upper bound though. 31989ed30d1SJens Wiklander */ 32089ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { 32189ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 32289ed30d1SJens Wiklander blen = mod_size - 11; 32389ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 32489ed30d1SJens Wiklander } else { 32589ed30d1SJens Wiklander /* Decoded message is always shorter than encrypted message */ 32689ed30d1SJens Wiklander blen = src_len; 32789ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 32889ed30d1SJens Wiklander } 32989ed30d1SJens Wiklander 33089ed30d1SJens Wiklander buf = malloc(blen); 33189ed30d1SJens Wiklander if (!buf) { 33289ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 33389ed30d1SJens Wiklander goto out; 33489ed30d1SJens Wiklander } 33589ed30d1SJens Wiklander 33689ed30d1SJens Wiklander ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen, 33789ed30d1SJens Wiklander ((label_len == 0) ? 0 : label), label_len, 33889ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_stat, 33989ed30d1SJens Wiklander <c_key); 34089ed30d1SJens Wiklander switch (ltc_res) { 34189ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 34289ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 34389ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 34489ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 34589ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 34689ed30d1SJens Wiklander goto out; 34789ed30d1SJens Wiklander case CRYPT_OK: 34889ed30d1SJens Wiklander break; 34989ed30d1SJens Wiklander default: 35089ed30d1SJens Wiklander /* This will result in a panic */ 35189ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 35289ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 35389ed30d1SJens Wiklander goto out; 35489ed30d1SJens Wiklander } 35589ed30d1SJens Wiklander if (ltc_stat != 1) { 35689ed30d1SJens Wiklander /* This will result in a panic */ 35789ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d and %d", 35889ed30d1SJens Wiklander ltc_res, ltc_stat); 35989ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 36089ed30d1SJens Wiklander goto out; 36189ed30d1SJens Wiklander } 36289ed30d1SJens Wiklander 36389ed30d1SJens Wiklander if (*dst_len < blen) { 36489ed30d1SJens Wiklander *dst_len = blen; 36589ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 36689ed30d1SJens Wiklander goto out; 36789ed30d1SJens Wiklander } 36889ed30d1SJens Wiklander 36989ed30d1SJens Wiklander res = TEE_SUCCESS; 37089ed30d1SJens Wiklander *dst_len = blen; 37189ed30d1SJens Wiklander memcpy(dst, buf, blen); 37289ed30d1SJens Wiklander 37389ed30d1SJens Wiklander out: 37489ed30d1SJens Wiklander if (buf) 37589ed30d1SJens Wiklander free(buf); 37689ed30d1SJens Wiklander 37789ed30d1SJens Wiklander return res; 37889ed30d1SJens Wiklander } 37989ed30d1SJens Wiklander 38089ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, 38189ed30d1SJens Wiklander struct rsa_public_key *key, 38289ed30d1SJens Wiklander const uint8_t *label, size_t label_len, 38389ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 38489ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 38589ed30d1SJens Wiklander { 38689ed30d1SJens Wiklander TEE_Result res; 38789ed30d1SJens Wiklander uint32_t mod_size; 38889ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_rsa_algo; 38989ed30d1SJens Wiklander rsa_key ltc_key = { 39089ed30d1SJens Wiklander .type = PK_PUBLIC, 39189ed30d1SJens Wiklander .e = key->e, 39289ed30d1SJens Wiklander .N = key->n 39389ed30d1SJens Wiklander }; 39489ed30d1SJens Wiklander 39589ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 39689ed30d1SJens Wiklander if (*dst_len < mod_size) { 39789ed30d1SJens Wiklander *dst_len = mod_size; 39889ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 39989ed30d1SJens Wiklander goto out; 40089ed30d1SJens Wiklander } 40189ed30d1SJens Wiklander *dst_len = mod_size; 40289ed30d1SJens Wiklander 40389ed30d1SJens Wiklander /* Get the algorithm */ 40489ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 40589ed30d1SJens Wiklander if (res != TEE_SUCCESS) 40689ed30d1SJens Wiklander goto out; 40789ed30d1SJens Wiklander 40889ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) 40989ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 41089ed30d1SJens Wiklander else 41189ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 41289ed30d1SJens Wiklander 41389ed30d1SJens Wiklander ltc_res = rsa_encrypt_key_ex(src, src_len, dst, 41489ed30d1SJens Wiklander (unsigned long *)(dst_len), label, 4151f3b1115SJens Wiklander label_len, NULL, find_prng("prng_crypto"), 41689ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_key); 41789ed30d1SJens Wiklander switch (ltc_res) { 41889ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 41989ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 42089ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 42189ed30d1SJens Wiklander EMSG("rsa_encrypt_key_ex() returned %d", ltc_res); 42289ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 42389ed30d1SJens Wiklander goto out; 42489ed30d1SJens Wiklander case CRYPT_OK: 42589ed30d1SJens Wiklander break; 42689ed30d1SJens Wiklander default: 42789ed30d1SJens Wiklander /* This will result in a panic */ 42889ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 42989ed30d1SJens Wiklander goto out; 43089ed30d1SJens Wiklander } 43189ed30d1SJens Wiklander res = TEE_SUCCESS; 43289ed30d1SJens Wiklander 43389ed30d1SJens Wiklander out: 43489ed30d1SJens Wiklander return res; 43589ed30d1SJens Wiklander } 43689ed30d1SJens Wiklander 43789ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, 43889ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 43989ed30d1SJens Wiklander size_t msg_len, uint8_t *sig, 44089ed30d1SJens Wiklander size_t *sig_len) 44189ed30d1SJens Wiklander { 44289ed30d1SJens Wiklander TEE_Result res; 44389ed30d1SJens Wiklander size_t hash_size, mod_size; 44489ed30d1SJens Wiklander int ltc_res, ltc_rsa_algo, ltc_hashindex; 44589ed30d1SJens Wiklander unsigned long ltc_sig_len; 44689ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 44789ed30d1SJens Wiklander 44889ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 44989ed30d1SJens Wiklander ltc_key.e = key->e; 45089ed30d1SJens Wiklander ltc_key.N = key->n; 45189ed30d1SJens Wiklander ltc_key.d = key->d; 45289ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 45389ed30d1SJens Wiklander ltc_key.p = key->p; 45489ed30d1SJens Wiklander ltc_key.q = key->q; 45589ed30d1SJens Wiklander ltc_key.qP = key->qp; 45689ed30d1SJens Wiklander ltc_key.dP = key->dp; 45789ed30d1SJens Wiklander ltc_key.dQ = key->dq; 45889ed30d1SJens Wiklander } 45989ed30d1SJens Wiklander 46089ed30d1SJens Wiklander switch (algo) { 46189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 46289ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 46389ed30d1SJens Wiklander break; 46489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 46589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 46689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 46789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 46889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 46989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 47089ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 47189ed30d1SJens Wiklander break; 47289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 47389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 47489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 47589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 47689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 47789ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 47889ed30d1SJens Wiklander break; 47989ed30d1SJens Wiklander default: 48089ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 48189ed30d1SJens Wiklander goto err; 48289ed30d1SJens Wiklander } 48389ed30d1SJens Wiklander 48489ed30d1SJens Wiklander if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) { 48589ed30d1SJens Wiklander ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 48689ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 48789ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 48889ed30d1SJens Wiklander goto err; 48989ed30d1SJens Wiklander } 49089ed30d1SJens Wiklander 4917c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 49289ed30d1SJens Wiklander &hash_size); 49389ed30d1SJens Wiklander if (res != TEE_SUCCESS) 49489ed30d1SJens Wiklander goto err; 49589ed30d1SJens Wiklander 49689ed30d1SJens Wiklander if (msg_len != hash_size) { 49789ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 49889ed30d1SJens Wiklander goto err; 49989ed30d1SJens Wiklander } 50089ed30d1SJens Wiklander } 50189ed30d1SJens Wiklander 50289ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 50389ed30d1SJens Wiklander 50489ed30d1SJens Wiklander if (*sig_len < mod_size) { 50589ed30d1SJens Wiklander *sig_len = mod_size; 50689ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 50789ed30d1SJens Wiklander goto err; 50889ed30d1SJens Wiklander } 50989ed30d1SJens Wiklander 51089ed30d1SJens Wiklander ltc_sig_len = mod_size; 51189ed30d1SJens Wiklander 51289ed30d1SJens Wiklander ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, 5131f3b1115SJens Wiklander ltc_rsa_algo, NULL, find_prng("prng_crypto"), 51489ed30d1SJens Wiklander ltc_hashindex, salt_len, <c_key); 51589ed30d1SJens Wiklander 51689ed30d1SJens Wiklander *sig_len = ltc_sig_len; 51789ed30d1SJens Wiklander 51889ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 51989ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 52089ed30d1SJens Wiklander goto err; 52189ed30d1SJens Wiklander } 52289ed30d1SJens Wiklander res = TEE_SUCCESS; 52389ed30d1SJens Wiklander 52489ed30d1SJens Wiklander err: 52589ed30d1SJens Wiklander return res; 52689ed30d1SJens Wiklander } 52789ed30d1SJens Wiklander 52889ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, 52989ed30d1SJens Wiklander struct rsa_public_key *key, 53089ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 53189ed30d1SJens Wiklander size_t msg_len, const uint8_t *sig, 53289ed30d1SJens Wiklander size_t sig_len) 53389ed30d1SJens Wiklander { 53489ed30d1SJens Wiklander TEE_Result res; 53589ed30d1SJens Wiklander uint32_t bigint_size; 53689ed30d1SJens Wiklander size_t hash_size; 53789ed30d1SJens Wiklander int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; 53889ed30d1SJens Wiklander rsa_key ltc_key = { 53989ed30d1SJens Wiklander .type = PK_PUBLIC, 54089ed30d1SJens Wiklander .e = key->e, 54189ed30d1SJens Wiklander .N = key->n 54289ed30d1SJens Wiklander }; 54389ed30d1SJens Wiklander 54489ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 5457c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 54689ed30d1SJens Wiklander &hash_size); 54789ed30d1SJens Wiklander if (res != TEE_SUCCESS) 54889ed30d1SJens Wiklander goto err; 54989ed30d1SJens Wiklander 55089ed30d1SJens Wiklander if (msg_len != hash_size) { 55189ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 55289ed30d1SJens Wiklander goto err; 55389ed30d1SJens Wiklander } 55489ed30d1SJens Wiklander } 55589ed30d1SJens Wiklander 55689ed30d1SJens Wiklander bigint_size = ltc_mp.unsigned_size(ltc_key.N); 55789ed30d1SJens Wiklander if (sig_len < bigint_size) { 55889ed30d1SJens Wiklander res = TEE_ERROR_SIGNATURE_INVALID; 55989ed30d1SJens Wiklander goto err; 56089ed30d1SJens Wiklander } 56189ed30d1SJens Wiklander 56289ed30d1SJens Wiklander /* Get the algorithm */ 56389ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 56489ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 56589ed30d1SJens Wiklander if (res != TEE_SUCCESS) 56689ed30d1SJens Wiklander goto err; 56789ed30d1SJens Wiklander } 56889ed30d1SJens Wiklander 56989ed30d1SJens Wiklander switch (algo) { 57089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 57189ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 57289ed30d1SJens Wiklander break; 57389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 57489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 57589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 57689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 57789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 57889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 57989ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 58089ed30d1SJens Wiklander break; 58189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 58289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 58389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 58489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 58589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 58689ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 58789ed30d1SJens Wiklander break; 58889ed30d1SJens Wiklander default: 58989ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 59089ed30d1SJens Wiklander goto err; 59189ed30d1SJens Wiklander } 59289ed30d1SJens Wiklander 59389ed30d1SJens Wiklander ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo, 59489ed30d1SJens Wiklander ltc_hashindex, salt_len, &stat, <c_key); 59589ed30d1SJens Wiklander res = convert_ltc_verify_status(ltc_res, stat); 59689ed30d1SJens Wiklander err: 59789ed30d1SJens Wiklander return res; 59889ed30d1SJens Wiklander } 599