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> 7*c2c27539SJorge Ramirez-Ortiz #include <crypto/crypto_impl.h> 889ed30d1SJens Wiklander #include <stdlib.h> 989ed30d1SJens Wiklander #include <string.h> 1089ed30d1SJens Wiklander #include <tee_api_types.h> 1189ed30d1SJens Wiklander #include <tee_api_defines_extensions.h> 1289ed30d1SJens Wiklander #include <tee/tee_cryp_utl.h> 1389ed30d1SJens Wiklander #include <trace.h> 1489ed30d1SJens Wiklander #include <utee_defines.h> 1589ed30d1SJens Wiklander 1689ed30d1SJens Wiklander #include "acipher_helpers.h" 1789ed30d1SJens Wiklander 1889ed30d1SJens Wiklander 1989ed30d1SJens Wiklander /* 2089ed30d1SJens Wiklander * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo" 2189ed30d1SJens Wiklander * Return 2289ed30d1SJens Wiklander * - TEE_SUCCESS in case of success, 2389ed30d1SJens Wiklander * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo 2489ed30d1SJens Wiklander * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC 2589ed30d1SJens Wiklander * Return -1 in case of error 2689ed30d1SJens Wiklander */ 2789ed30d1SJens Wiklander static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex) 2889ed30d1SJens Wiklander { 2989ed30d1SJens Wiklander switch (algo) { 30a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA1) 3189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 3289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 3389ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: 3489ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha1"); 3589ed30d1SJens Wiklander break; 3689ed30d1SJens Wiklander #endif 37a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_MD5) 3889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 3989ed30d1SJens Wiklander *ltc_hashindex = find_hash("md5"); 4089ed30d1SJens Wiklander break; 4189ed30d1SJens Wiklander #endif 42a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA224) 4389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 4489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 4589ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: 4689ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha224"); 4789ed30d1SJens Wiklander break; 4889ed30d1SJens Wiklander #endif 49a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA256) 5089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 5189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 5289ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: 5389ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha256"); 5489ed30d1SJens Wiklander break; 5589ed30d1SJens Wiklander #endif 56a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA384) 5789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 5889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 5989ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: 6089ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha384"); 6189ed30d1SJens Wiklander break; 6289ed30d1SJens Wiklander #endif 63a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA512) 6489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 6589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 6689ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: 6789ed30d1SJens Wiklander *ltc_hashindex = find_hash("sha512"); 6889ed30d1SJens Wiklander break; 6989ed30d1SJens Wiklander #endif 7089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 7189ed30d1SJens Wiklander case TEE_ALG_RSAES_PKCS1_V1_5: 7289ed30d1SJens Wiklander /* invalid one. but it should not be used anyway */ 7389ed30d1SJens Wiklander *ltc_hashindex = -1; 7489ed30d1SJens Wiklander return TEE_SUCCESS; 7589ed30d1SJens Wiklander 7689ed30d1SJens Wiklander default: 7789ed30d1SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 7889ed30d1SJens Wiklander } 7989ed30d1SJens Wiklander 8089ed30d1SJens Wiklander if (*ltc_hashindex < 0) 8189ed30d1SJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 8289ed30d1SJens Wiklander else 8389ed30d1SJens Wiklander return TEE_SUCCESS; 8489ed30d1SJens Wiklander } 8589ed30d1SJens Wiklander 8689ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, 8789ed30d1SJens Wiklander size_t key_size_bits __unused) 88*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_keypair"); 89*c2c27539SJorge Ramirez-Ortiz 90*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, 91*c2c27539SJorge Ramirez-Ortiz size_t key_size_bits __unused) 9289ed30d1SJens Wiklander { 9389ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 9489ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 9589ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 9689ed30d1SJens Wiklander if (!bn_alloc_max(&s->d)) 9789ed30d1SJens Wiklander goto err; 9889ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 9989ed30d1SJens Wiklander goto err; 10089ed30d1SJens Wiklander if (!bn_alloc_max(&s->p)) 10189ed30d1SJens Wiklander goto err; 10289ed30d1SJens Wiklander if (!bn_alloc_max(&s->q)) 10389ed30d1SJens Wiklander goto err; 10489ed30d1SJens Wiklander if (!bn_alloc_max(&s->qp)) 10589ed30d1SJens Wiklander goto err; 10689ed30d1SJens Wiklander if (!bn_alloc_max(&s->dp)) 10789ed30d1SJens Wiklander goto err; 10889ed30d1SJens Wiklander if (!bn_alloc_max(&s->dq)) 10989ed30d1SJens Wiklander goto err; 11089ed30d1SJens Wiklander 11189ed30d1SJens Wiklander return TEE_SUCCESS; 11289ed30d1SJens Wiklander err: 11392e38694SJerome Forissier crypto_acipher_free_rsa_keypair(s); 11489ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 11589ed30d1SJens Wiklander } 11689ed30d1SJens Wiklander 117*c2c27539SJorge Ramirez-Ortiz 11889ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, 11989ed30d1SJens Wiklander size_t key_size_bits __unused) 120*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_public_key"); 121*c2c27539SJorge Ramirez-Ortiz 122*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, 123*c2c27539SJorge Ramirez-Ortiz size_t key_size_bits __unused) 12489ed30d1SJens Wiklander { 12589ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 12689ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 12789ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 12889ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 12989ed30d1SJens Wiklander goto err; 13089ed30d1SJens Wiklander return TEE_SUCCESS; 13189ed30d1SJens Wiklander err: 13289ed30d1SJens Wiklander crypto_bignum_free(s->e); 13389ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 13489ed30d1SJens Wiklander } 13589ed30d1SJens Wiklander 136*c2c27539SJorge Ramirez-Ortiz 13789ed30d1SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) 138*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_public_key"); 139*c2c27539SJorge Ramirez-Ortiz 140*c2c27539SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) 14189ed30d1SJens Wiklander { 14289ed30d1SJens Wiklander if (!s) 14389ed30d1SJens Wiklander return; 14489ed30d1SJens Wiklander crypto_bignum_free(s->n); 14589ed30d1SJens Wiklander crypto_bignum_free(s->e); 14689ed30d1SJens Wiklander } 14789ed30d1SJens Wiklander 148*c2c27539SJorge Ramirez-Ortiz 149a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) 150*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_keypair"); 151*c2c27539SJorge Ramirez-Ortiz 152*c2c27539SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) 153a1d5c81fSElias von Däniken { 154a1d5c81fSElias von Däniken if (!s) 155a1d5c81fSElias von Däniken return; 156a1d5c81fSElias von Däniken crypto_bignum_free(s->e); 157a1d5c81fSElias von Däniken crypto_bignum_free(s->d); 158a1d5c81fSElias von Däniken crypto_bignum_free(s->n); 159a1d5c81fSElias von Däniken crypto_bignum_free(s->p); 160a1d5c81fSElias von Däniken crypto_bignum_free(s->q); 161a1d5c81fSElias von Däniken crypto_bignum_free(s->qp); 162a1d5c81fSElias von Däniken crypto_bignum_free(s->dp); 16385f7c554SJerome Forissier crypto_bignum_free(s->dq); 164a1d5c81fSElias von Däniken } 165a1d5c81fSElias von Däniken 166*c2c27539SJorge Ramirez-Ortiz TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, 167*c2c27539SJorge Ramirez-Ortiz size_t key_size) 168*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_gen_rsa_key"); 169*c2c27539SJorge Ramirez-Ortiz 170*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, 171*c2c27539SJorge Ramirez-Ortiz size_t key_size) 17289ed30d1SJens Wiklander { 17389ed30d1SJens Wiklander TEE_Result res; 17489ed30d1SJens Wiklander rsa_key ltc_tmp_key; 17589ed30d1SJens Wiklander int ltc_res; 17689ed30d1SJens Wiklander 17789ed30d1SJens Wiklander /* Generate a temporary RSA key */ 17874524a75SCedric Neveux ltc_res = rsa_make_key_bn_e(NULL, find_prng("prng_crypto"), 17974524a75SCedric Neveux key_size / 8, key->e, <c_tmp_key); 18089ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 18189ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 18289ed30d1SJens Wiklander } else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) { 18389ed30d1SJens Wiklander rsa_free(<c_tmp_key); 18489ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 18589ed30d1SJens Wiklander } else { 18689ed30d1SJens Wiklander /* Copy the key */ 18789ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.d, key->d); 18889ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.N, key->n); 18989ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.p, key->p); 19089ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.q, key->q); 19189ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.qP, key->qp); 19289ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dP, key->dp); 19389ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dQ, key->dq); 19489ed30d1SJens Wiklander 19589ed30d1SJens Wiklander /* Free the temporary key */ 19689ed30d1SJens Wiklander rsa_free(<c_tmp_key); 19789ed30d1SJens Wiklander res = TEE_SUCCESS; 19889ed30d1SJens Wiklander } 19989ed30d1SJens Wiklander 20089ed30d1SJens Wiklander return res; 20189ed30d1SJens Wiklander } 20289ed30d1SJens Wiklander 20389ed30d1SJens Wiklander static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src, 20489ed30d1SJens Wiklander size_t src_len, uint8_t *dst, size_t *dst_len) 20589ed30d1SJens Wiklander { 20689ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 20789ed30d1SJens Wiklander uint8_t *buf = NULL; 20889ed30d1SJens Wiklander unsigned long blen, offset; 20989ed30d1SJens Wiklander int ltc_res; 21089ed30d1SJens Wiklander 21189ed30d1SJens Wiklander /* 21289ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large the 21389ed30d1SJens Wiklander * required size of the out buffer without doing a partial decrypt. 21489ed30d1SJens Wiklander * We know the upper bound though. 21589ed30d1SJens Wiklander */ 216a1cbb728SJens Wiklander blen = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t); 21789ed30d1SJens Wiklander buf = malloc(blen); 21889ed30d1SJens Wiklander if (!buf) { 21989ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 22089ed30d1SJens Wiklander goto out; 22189ed30d1SJens Wiklander } 22289ed30d1SJens Wiklander 22389ed30d1SJens Wiklander ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type, 22489ed30d1SJens Wiklander ltc_key); 22589ed30d1SJens Wiklander switch (ltc_res) { 22689ed30d1SJens Wiklander case CRYPT_PK_NOT_PRIVATE: 22789ed30d1SJens Wiklander case CRYPT_PK_INVALID_TYPE: 22889ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 22989ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 23089ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 23189ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 23289ed30d1SJens Wiklander goto out; 23389ed30d1SJens Wiklander case CRYPT_OK: 23489ed30d1SJens Wiklander break; 23589ed30d1SJens Wiklander default: 23689ed30d1SJens Wiklander /* This will result in a panic */ 23789ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 23889ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 23989ed30d1SJens Wiklander goto out; 24089ed30d1SJens Wiklander } 24189ed30d1SJens Wiklander 24289ed30d1SJens Wiklander /* Remove the zero-padding (leave one zero if buff is all zeroes) */ 24389ed30d1SJens Wiklander offset = 0; 24489ed30d1SJens Wiklander while ((offset < blen - 1) && (buf[offset] == 0)) 24589ed30d1SJens Wiklander offset++; 24689ed30d1SJens Wiklander 24789ed30d1SJens Wiklander if (*dst_len < blen - offset) { 24889ed30d1SJens Wiklander *dst_len = blen - offset; 24989ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 25089ed30d1SJens Wiklander goto out; 25189ed30d1SJens Wiklander } 25289ed30d1SJens Wiklander 25389ed30d1SJens Wiklander res = TEE_SUCCESS; 25489ed30d1SJens Wiklander *dst_len = blen - offset; 25589ed30d1SJens Wiklander memcpy(dst, (char *)buf + offset, *dst_len); 25689ed30d1SJens Wiklander 25789ed30d1SJens Wiklander out: 25889ed30d1SJens Wiklander if (buf) 25989ed30d1SJens Wiklander free(buf); 26089ed30d1SJens Wiklander 26189ed30d1SJens Wiklander return res; 26289ed30d1SJens Wiklander } 26389ed30d1SJens Wiklander 26489ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, 265*c2c27539SJorge Ramirez-Ortiz const uint8_t *src, 266*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 267*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 268*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_encrypt"); 269*c2c27539SJorge Ramirez-Ortiz 270*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, 271*c2c27539SJorge Ramirez-Ortiz const uint8_t *src, 272*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 273*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 27489ed30d1SJens Wiklander { 27589ed30d1SJens Wiklander TEE_Result res; 27689ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 27789ed30d1SJens Wiklander 27889ed30d1SJens Wiklander ltc_key.type = PK_PUBLIC; 27989ed30d1SJens Wiklander ltc_key.e = key->e; 28089ed30d1SJens Wiklander ltc_key.N = key->n; 28189ed30d1SJens Wiklander 28289ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 28389ed30d1SJens Wiklander return res; 28489ed30d1SJens Wiklander } 28589ed30d1SJens Wiklander 28689ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, 287*c2c27539SJorge Ramirez-Ortiz const uint8_t *src, 288*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 289*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 290*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_decrypt"); 291*c2c27539SJorge Ramirez-Ortiz 292*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, 293*c2c27539SJorge Ramirez-Ortiz const uint8_t *src, 294*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 295*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 29689ed30d1SJens Wiklander { 29789ed30d1SJens Wiklander TEE_Result res; 29889ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 29989ed30d1SJens Wiklander 30089ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 30189ed30d1SJens Wiklander ltc_key.e = key->e; 30289ed30d1SJens Wiklander ltc_key.N = key->n; 30389ed30d1SJens Wiklander ltc_key.d = key->d; 30489ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 30589ed30d1SJens Wiklander ltc_key.p = key->p; 30689ed30d1SJens Wiklander ltc_key.q = key->q; 30789ed30d1SJens Wiklander ltc_key.qP = key->qp; 30889ed30d1SJens Wiklander ltc_key.dP = key->dp; 30989ed30d1SJens Wiklander ltc_key.dQ = key->dq; 31089ed30d1SJens Wiklander } 31189ed30d1SJens Wiklander 31289ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 31389ed30d1SJens Wiklander return res; 31489ed30d1SJens Wiklander } 31589ed30d1SJens Wiklander 316*c2c27539SJorge Ramirez-Ortiz TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, 317*c2c27539SJorge Ramirez-Ortiz struct rsa_keypair *key, 318*c2c27539SJorge Ramirez-Ortiz const uint8_t *label, 319*c2c27539SJorge Ramirez-Ortiz size_t label_len, const uint8_t *src, 320*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 321*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 322*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_decrypt"); 323*c2c27539SJorge Ramirez-Ortiz 324*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, 325*c2c27539SJorge Ramirez-Ortiz struct rsa_keypair *key, 326*c2c27539SJorge Ramirez-Ortiz const uint8_t *label, 327*c2c27539SJorge Ramirez-Ortiz size_t label_len, const uint8_t *src, 328*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 329*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 33089ed30d1SJens Wiklander { 33189ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 33289ed30d1SJens Wiklander void *buf = NULL; 33389ed30d1SJens Wiklander unsigned long blen; 33489ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo; 33589ed30d1SJens Wiklander size_t mod_size; 33689ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 33789ed30d1SJens Wiklander 33889ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 33989ed30d1SJens Wiklander ltc_key.e = key->e; 34089ed30d1SJens Wiklander ltc_key.d = key->d; 34189ed30d1SJens Wiklander ltc_key.N = key->n; 34289ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 34389ed30d1SJens Wiklander ltc_key.p = key->p; 34489ed30d1SJens Wiklander ltc_key.q = key->q; 34589ed30d1SJens Wiklander ltc_key.qP = key->qp; 34689ed30d1SJens Wiklander ltc_key.dP = key->dp; 34789ed30d1SJens Wiklander ltc_key.dQ = key->dq; 34889ed30d1SJens Wiklander } 34989ed30d1SJens Wiklander 35089ed30d1SJens Wiklander /* Get the algorithm */ 35189ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 35289ed30d1SJens Wiklander if (res != TEE_SUCCESS) { 35389ed30d1SJens Wiklander EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res); 35489ed30d1SJens Wiklander goto out; 35589ed30d1SJens Wiklander } 35689ed30d1SJens Wiklander 35789ed30d1SJens Wiklander /* 35889ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large 35989ed30d1SJens Wiklander * the required size of the out buffer without doing a partial 36089ed30d1SJens Wiklander * decrypt. We know the upper bound though. 36189ed30d1SJens Wiklander */ 36289ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { 36389ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 36489ed30d1SJens Wiklander blen = mod_size - 11; 36589ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 36689ed30d1SJens Wiklander } else { 36789ed30d1SJens Wiklander /* Decoded message is always shorter than encrypted message */ 36889ed30d1SJens Wiklander blen = src_len; 36989ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 37089ed30d1SJens Wiklander } 37189ed30d1SJens Wiklander 37289ed30d1SJens Wiklander buf = malloc(blen); 37389ed30d1SJens Wiklander if (!buf) { 37489ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 37589ed30d1SJens Wiklander goto out; 37689ed30d1SJens Wiklander } 37789ed30d1SJens Wiklander 37889ed30d1SJens Wiklander ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen, 37989ed30d1SJens Wiklander ((label_len == 0) ? 0 : label), label_len, 38089ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_stat, 38189ed30d1SJens Wiklander <c_key); 38289ed30d1SJens Wiklander switch (ltc_res) { 38389ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 38489ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 38589ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 38689ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 38789ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 38889ed30d1SJens Wiklander goto out; 38989ed30d1SJens Wiklander case CRYPT_OK: 39089ed30d1SJens Wiklander break; 39189ed30d1SJens Wiklander default: 39289ed30d1SJens Wiklander /* This will result in a panic */ 39389ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 39489ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 39589ed30d1SJens Wiklander goto out; 39689ed30d1SJens Wiklander } 39789ed30d1SJens Wiklander if (ltc_stat != 1) { 39889ed30d1SJens Wiklander /* This will result in a panic */ 39989ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d and %d", 40089ed30d1SJens Wiklander ltc_res, ltc_stat); 40189ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 40289ed30d1SJens Wiklander goto out; 40389ed30d1SJens Wiklander } 40489ed30d1SJens Wiklander 40589ed30d1SJens Wiklander if (*dst_len < blen) { 40689ed30d1SJens Wiklander *dst_len = blen; 40789ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 40889ed30d1SJens Wiklander goto out; 40989ed30d1SJens Wiklander } 41089ed30d1SJens Wiklander 41189ed30d1SJens Wiklander res = TEE_SUCCESS; 41289ed30d1SJens Wiklander *dst_len = blen; 41389ed30d1SJens Wiklander memcpy(dst, buf, blen); 41489ed30d1SJens Wiklander 41589ed30d1SJens Wiklander out: 41689ed30d1SJens Wiklander if (buf) 41789ed30d1SJens Wiklander free(buf); 41889ed30d1SJens Wiklander 41989ed30d1SJens Wiklander return res; 42089ed30d1SJens Wiklander } 42189ed30d1SJens Wiklander 42289ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, 42389ed30d1SJens Wiklander struct rsa_public_key *key, 424*c2c27539SJorge Ramirez-Ortiz const uint8_t *label, 425*c2c27539SJorge Ramirez-Ortiz size_t label_len, const uint8_t *src, 426*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 427*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 428*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_encrypt"); 429*c2c27539SJorge Ramirez-Ortiz 430*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, 431*c2c27539SJorge Ramirez-Ortiz struct rsa_public_key *key, 432*c2c27539SJorge Ramirez-Ortiz const uint8_t *label, 433*c2c27539SJorge Ramirez-Ortiz size_t label_len, const uint8_t *src, 434*c2c27539SJorge Ramirez-Ortiz size_t src_len, uint8_t *dst, 435*c2c27539SJorge Ramirez-Ortiz size_t *dst_len) 43689ed30d1SJens Wiklander { 43789ed30d1SJens Wiklander TEE_Result res; 43889ed30d1SJens Wiklander uint32_t mod_size; 43989ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_rsa_algo; 44089ed30d1SJens Wiklander rsa_key ltc_key = { 44189ed30d1SJens Wiklander .type = PK_PUBLIC, 44289ed30d1SJens Wiklander .e = key->e, 44389ed30d1SJens Wiklander .N = key->n 44489ed30d1SJens Wiklander }; 44589ed30d1SJens Wiklander 44689ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 44789ed30d1SJens Wiklander if (*dst_len < mod_size) { 44889ed30d1SJens Wiklander *dst_len = mod_size; 44989ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 45089ed30d1SJens Wiklander goto out; 45189ed30d1SJens Wiklander } 45289ed30d1SJens Wiklander *dst_len = mod_size; 45389ed30d1SJens Wiklander 45489ed30d1SJens Wiklander /* Get the algorithm */ 45589ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 45689ed30d1SJens Wiklander if (res != TEE_SUCCESS) 45789ed30d1SJens Wiklander goto out; 45889ed30d1SJens Wiklander 45989ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) 46089ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 46189ed30d1SJens Wiklander else 46289ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 46389ed30d1SJens Wiklander 46489ed30d1SJens Wiklander ltc_res = rsa_encrypt_key_ex(src, src_len, dst, 46589ed30d1SJens Wiklander (unsigned long *)(dst_len), label, 4661f3b1115SJens Wiklander label_len, NULL, find_prng("prng_crypto"), 46789ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_key); 46889ed30d1SJens Wiklander switch (ltc_res) { 46989ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 47089ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 47189ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 47289ed30d1SJens Wiklander EMSG("rsa_encrypt_key_ex() returned %d", ltc_res); 47389ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 47489ed30d1SJens Wiklander goto out; 47589ed30d1SJens Wiklander case CRYPT_OK: 47689ed30d1SJens Wiklander break; 47789ed30d1SJens Wiklander default: 47889ed30d1SJens Wiklander /* This will result in a panic */ 47989ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 48089ed30d1SJens Wiklander goto out; 48189ed30d1SJens Wiklander } 48289ed30d1SJens Wiklander res = TEE_SUCCESS; 48389ed30d1SJens Wiklander 48489ed30d1SJens Wiklander out: 48589ed30d1SJens Wiklander return res; 48689ed30d1SJens Wiklander } 48789ed30d1SJens Wiklander 48889ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, 48989ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 49089ed30d1SJens Wiklander size_t msg_len, uint8_t *sig, 49189ed30d1SJens Wiklander size_t *sig_len) 492*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_sign"); 493*c2c27539SJorge Ramirez-Ortiz 494*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, 495*c2c27539SJorge Ramirez-Ortiz int salt_len, const uint8_t *msg, 496*c2c27539SJorge Ramirez-Ortiz size_t msg_len, uint8_t *sig, 497*c2c27539SJorge Ramirez-Ortiz size_t *sig_len) 49889ed30d1SJens Wiklander { 49989ed30d1SJens Wiklander TEE_Result res; 50089ed30d1SJens Wiklander size_t hash_size, mod_size; 50189ed30d1SJens Wiklander int ltc_res, ltc_rsa_algo, ltc_hashindex; 50289ed30d1SJens Wiklander unsigned long ltc_sig_len; 50389ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 50489ed30d1SJens Wiklander 50589ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 50689ed30d1SJens Wiklander ltc_key.e = key->e; 50789ed30d1SJens Wiklander ltc_key.N = key->n; 50889ed30d1SJens Wiklander ltc_key.d = key->d; 50989ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 51089ed30d1SJens Wiklander ltc_key.p = key->p; 51189ed30d1SJens Wiklander ltc_key.q = key->q; 51289ed30d1SJens Wiklander ltc_key.qP = key->qp; 51389ed30d1SJens Wiklander ltc_key.dP = key->dp; 51489ed30d1SJens Wiklander ltc_key.dQ = key->dq; 51589ed30d1SJens Wiklander } 51689ed30d1SJens Wiklander 51789ed30d1SJens Wiklander switch (algo) { 51889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 51989ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 52089ed30d1SJens Wiklander break; 52189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 52289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 52389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 52489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 52589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 52689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 52789ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 52889ed30d1SJens Wiklander break; 52989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 53089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 53189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 53289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 53389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 53489ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 53589ed30d1SJens Wiklander break; 53689ed30d1SJens Wiklander default: 53789ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 53889ed30d1SJens Wiklander goto err; 53989ed30d1SJens Wiklander } 54089ed30d1SJens Wiklander 54189ed30d1SJens Wiklander if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) { 54289ed30d1SJens Wiklander ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 54389ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 54489ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 54589ed30d1SJens Wiklander goto err; 54689ed30d1SJens Wiklander } 54789ed30d1SJens Wiklander 5487c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 54989ed30d1SJens Wiklander &hash_size); 55089ed30d1SJens Wiklander if (res != TEE_SUCCESS) 55189ed30d1SJens Wiklander goto err; 55289ed30d1SJens Wiklander 55389ed30d1SJens Wiklander if (msg_len != hash_size) { 55489ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 55589ed30d1SJens Wiklander goto err; 55689ed30d1SJens Wiklander } 55789ed30d1SJens Wiklander } 55889ed30d1SJens Wiklander 55989ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 56089ed30d1SJens Wiklander 56189ed30d1SJens Wiklander if (*sig_len < mod_size) { 56289ed30d1SJens Wiklander *sig_len = mod_size; 56389ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 56489ed30d1SJens Wiklander goto err; 56589ed30d1SJens Wiklander } 56689ed30d1SJens Wiklander 56789ed30d1SJens Wiklander ltc_sig_len = mod_size; 56889ed30d1SJens Wiklander 56989ed30d1SJens Wiklander ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, 5701f3b1115SJens Wiklander ltc_rsa_algo, NULL, find_prng("prng_crypto"), 57189ed30d1SJens Wiklander ltc_hashindex, salt_len, <c_key); 57289ed30d1SJens Wiklander 57389ed30d1SJens Wiklander *sig_len = ltc_sig_len; 57489ed30d1SJens Wiklander 57589ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 57689ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 57789ed30d1SJens Wiklander goto err; 57889ed30d1SJens Wiklander } 57989ed30d1SJens Wiklander res = TEE_SUCCESS; 58089ed30d1SJens Wiklander 58189ed30d1SJens Wiklander err: 58289ed30d1SJens Wiklander return res; 58389ed30d1SJens Wiklander } 58489ed30d1SJens Wiklander 58589ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, 58689ed30d1SJens Wiklander struct rsa_public_key *key, 58789ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 58889ed30d1SJens Wiklander size_t msg_len, const uint8_t *sig, 58989ed30d1SJens Wiklander size_t sig_len) 590*c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_verify"); 591*c2c27539SJorge Ramirez-Ortiz 592*c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, 593*c2c27539SJorge Ramirez-Ortiz struct rsa_public_key *key, 594*c2c27539SJorge Ramirez-Ortiz int salt_len, const uint8_t *msg, 595*c2c27539SJorge Ramirez-Ortiz size_t msg_len, const uint8_t *sig, 596*c2c27539SJorge Ramirez-Ortiz size_t sig_len) 59789ed30d1SJens Wiklander { 59889ed30d1SJens Wiklander TEE_Result res; 59989ed30d1SJens Wiklander uint32_t bigint_size; 60089ed30d1SJens Wiklander size_t hash_size; 60189ed30d1SJens Wiklander int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; 60289ed30d1SJens Wiklander rsa_key ltc_key = { 60389ed30d1SJens Wiklander .type = PK_PUBLIC, 60489ed30d1SJens Wiklander .e = key->e, 60589ed30d1SJens Wiklander .N = key->n 60689ed30d1SJens Wiklander }; 60789ed30d1SJens Wiklander 60889ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 6097c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 61089ed30d1SJens Wiklander &hash_size); 61189ed30d1SJens Wiklander if (res != TEE_SUCCESS) 61289ed30d1SJens Wiklander goto err; 61389ed30d1SJens Wiklander 61489ed30d1SJens Wiklander if (msg_len != hash_size) { 61589ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 61689ed30d1SJens Wiklander goto err; 61789ed30d1SJens Wiklander } 61889ed30d1SJens Wiklander } 61989ed30d1SJens Wiklander 62089ed30d1SJens Wiklander bigint_size = ltc_mp.unsigned_size(ltc_key.N); 62189ed30d1SJens Wiklander if (sig_len < bigint_size) { 62289ed30d1SJens Wiklander res = TEE_ERROR_SIGNATURE_INVALID; 62389ed30d1SJens Wiklander goto err; 62489ed30d1SJens Wiklander } 62589ed30d1SJens Wiklander 62689ed30d1SJens Wiklander /* Get the algorithm */ 62789ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 62889ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 62989ed30d1SJens Wiklander if (res != TEE_SUCCESS) 63089ed30d1SJens Wiklander goto err; 63189ed30d1SJens Wiklander } 63289ed30d1SJens Wiklander 63389ed30d1SJens Wiklander switch (algo) { 63489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 63589ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 63689ed30d1SJens Wiklander break; 63789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 63889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 63989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 64089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 64189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 64289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 64389ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 64489ed30d1SJens Wiklander break; 64589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 64689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 64789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 64889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 64989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 65089ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 65189ed30d1SJens Wiklander break; 65289ed30d1SJens Wiklander default: 65389ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 65489ed30d1SJens Wiklander goto err; 65589ed30d1SJens Wiklander } 65689ed30d1SJens Wiklander 65789ed30d1SJens Wiklander ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo, 65889ed30d1SJens Wiklander ltc_hashindex, salt_len, &stat, <c_key); 65989ed30d1SJens Wiklander res = convert_ltc_verify_status(ltc_res, stat); 66089ed30d1SJens Wiklander err: 66189ed30d1SJens Wiklander return res; 66289ed30d1SJens Wiklander } 663