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 <tomcrypt.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) { 3089ed30d1SJens Wiklander #if defined(CFG_CRYPTO_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 3789ed30d1SJens Wiklander #if defined(CFG_CRYPTO_MD5) 3889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 3989ed30d1SJens Wiklander *ltc_hashindex = find_hash("md5"); 4089ed30d1SJens Wiklander break; 4189ed30d1SJens Wiklander #endif 4289ed30d1SJens Wiklander #if defined(CFG_CRYPTO_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 4989ed30d1SJens Wiklander #if defined(CFG_CRYPTO_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 5689ed30d1SJens Wiklander #if defined(CFG_CRYPTO_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 6389ed30d1SJens Wiklander #if defined(CFG_CRYPTO_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) 8889ed30d1SJens Wiklander { 8989ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 9089ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 9189ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 9289ed30d1SJens Wiklander if (!bn_alloc_max(&s->d)) 9389ed30d1SJens Wiklander goto err; 9489ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 9589ed30d1SJens Wiklander goto err; 9689ed30d1SJens Wiklander if (!bn_alloc_max(&s->p)) 9789ed30d1SJens Wiklander goto err; 9889ed30d1SJens Wiklander if (!bn_alloc_max(&s->q)) 9989ed30d1SJens Wiklander goto err; 10089ed30d1SJens Wiklander if (!bn_alloc_max(&s->qp)) 10189ed30d1SJens Wiklander goto err; 10289ed30d1SJens Wiklander if (!bn_alloc_max(&s->dp)) 10389ed30d1SJens Wiklander goto err; 10489ed30d1SJens Wiklander if (!bn_alloc_max(&s->dq)) 10589ed30d1SJens Wiklander goto err; 10689ed30d1SJens Wiklander 10789ed30d1SJens Wiklander return TEE_SUCCESS; 10889ed30d1SJens Wiklander err: 10989ed30d1SJens Wiklander crypto_bignum_free(s->e); 11089ed30d1SJens Wiklander crypto_bignum_free(s->d); 11189ed30d1SJens Wiklander crypto_bignum_free(s->n); 11289ed30d1SJens Wiklander crypto_bignum_free(s->p); 11389ed30d1SJens Wiklander crypto_bignum_free(s->q); 11489ed30d1SJens Wiklander crypto_bignum_free(s->qp); 11589ed30d1SJens Wiklander crypto_bignum_free(s->dp); 11689ed30d1SJens Wiklander 11789ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 11889ed30d1SJens Wiklander } 11989ed30d1SJens Wiklander 12089ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, 12189ed30d1SJens Wiklander size_t key_size_bits __unused) 12289ed30d1SJens Wiklander { 12389ed30d1SJens Wiklander memset(s, 0, sizeof(*s)); 12489ed30d1SJens Wiklander if (!bn_alloc_max(&s->e)) 12589ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 12689ed30d1SJens Wiklander if (!bn_alloc_max(&s->n)) 12789ed30d1SJens Wiklander goto err; 12889ed30d1SJens Wiklander return TEE_SUCCESS; 12989ed30d1SJens Wiklander err: 13089ed30d1SJens Wiklander crypto_bignum_free(s->e); 13189ed30d1SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 13289ed30d1SJens Wiklander } 13389ed30d1SJens Wiklander 13489ed30d1SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) 13589ed30d1SJens Wiklander { 13689ed30d1SJens Wiklander if (!s) 13789ed30d1SJens Wiklander return; 13889ed30d1SJens Wiklander crypto_bignum_free(s->n); 13989ed30d1SJens Wiklander crypto_bignum_free(s->e); 14089ed30d1SJens Wiklander } 14189ed30d1SJens Wiklander 14289ed30d1SJens Wiklander TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) 14389ed30d1SJens Wiklander { 14489ed30d1SJens Wiklander TEE_Result res; 14589ed30d1SJens Wiklander rsa_key ltc_tmp_key; 14689ed30d1SJens Wiklander int ltc_res; 14789ed30d1SJens Wiklander long e; 14889ed30d1SJens Wiklander 14989ed30d1SJens Wiklander /* get the public exponent */ 15089ed30d1SJens Wiklander e = mp_get_int(key->e); 15189ed30d1SJens Wiklander 15289ed30d1SJens Wiklander /* Generate a temporary RSA key */ 153*1f3b1115SJens Wiklander ltc_res = rsa_make_key(NULL, find_prng("prng_crypto"), key_size / 8, e, 15489ed30d1SJens Wiklander <c_tmp_key); 15589ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 15689ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 15789ed30d1SJens Wiklander } else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) { 15889ed30d1SJens Wiklander rsa_free(<c_tmp_key); 15989ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 16089ed30d1SJens Wiklander } else { 16189ed30d1SJens Wiklander /* Copy the key */ 16289ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.e, key->e); 16389ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.d, key->d); 16489ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.N, key->n); 16589ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.p, key->p); 16689ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.q, key->q); 16789ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.qP, key->qp); 16889ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dP, key->dp); 16989ed30d1SJens Wiklander ltc_mp.copy(ltc_tmp_key.dQ, key->dq); 17089ed30d1SJens Wiklander 17189ed30d1SJens Wiklander /* Free the temporary key */ 17289ed30d1SJens Wiklander rsa_free(<c_tmp_key); 17389ed30d1SJens Wiklander res = TEE_SUCCESS; 17489ed30d1SJens Wiklander } 17589ed30d1SJens Wiklander 17689ed30d1SJens Wiklander return res; 17789ed30d1SJens Wiklander } 17889ed30d1SJens Wiklander 17989ed30d1SJens Wiklander static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src, 18089ed30d1SJens Wiklander size_t src_len, uint8_t *dst, size_t *dst_len) 18189ed30d1SJens Wiklander { 18289ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 18389ed30d1SJens Wiklander uint8_t *buf = NULL; 18489ed30d1SJens Wiklander unsigned long blen, offset; 18589ed30d1SJens Wiklander int ltc_res; 18689ed30d1SJens Wiklander 18789ed30d1SJens Wiklander /* 18889ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large the 18989ed30d1SJens Wiklander * required size of the out buffer without doing a partial decrypt. 19089ed30d1SJens Wiklander * We know the upper bound though. 19189ed30d1SJens Wiklander */ 19289ed30d1SJens Wiklander blen = CFG_CORE_BIGNUM_MAX_BITS / sizeof(uint8_t); 19389ed30d1SJens Wiklander buf = malloc(blen); 19489ed30d1SJens Wiklander if (!buf) { 19589ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 19689ed30d1SJens Wiklander goto out; 19789ed30d1SJens Wiklander } 19889ed30d1SJens Wiklander 19989ed30d1SJens Wiklander ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type, 20089ed30d1SJens Wiklander ltc_key); 20189ed30d1SJens Wiklander switch (ltc_res) { 20289ed30d1SJens Wiklander case CRYPT_PK_NOT_PRIVATE: 20389ed30d1SJens Wiklander case CRYPT_PK_INVALID_TYPE: 20489ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 20589ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 20689ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 20789ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 20889ed30d1SJens Wiklander goto out; 20989ed30d1SJens Wiklander case CRYPT_OK: 21089ed30d1SJens Wiklander break; 21189ed30d1SJens Wiklander default: 21289ed30d1SJens Wiklander /* This will result in a panic */ 21389ed30d1SJens Wiklander EMSG("rsa_exptmod() returned %d", ltc_res); 21489ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 21589ed30d1SJens Wiklander goto out; 21689ed30d1SJens Wiklander } 21789ed30d1SJens Wiklander 21889ed30d1SJens Wiklander /* Remove the zero-padding (leave one zero if buff is all zeroes) */ 21989ed30d1SJens Wiklander offset = 0; 22089ed30d1SJens Wiklander while ((offset < blen - 1) && (buf[offset] == 0)) 22189ed30d1SJens Wiklander offset++; 22289ed30d1SJens Wiklander 22389ed30d1SJens Wiklander if (*dst_len < blen - offset) { 22489ed30d1SJens Wiklander *dst_len = blen - offset; 22589ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 22689ed30d1SJens Wiklander goto out; 22789ed30d1SJens Wiklander } 22889ed30d1SJens Wiklander 22989ed30d1SJens Wiklander res = TEE_SUCCESS; 23089ed30d1SJens Wiklander *dst_len = blen - offset; 23189ed30d1SJens Wiklander memcpy(dst, (char *)buf + offset, *dst_len); 23289ed30d1SJens Wiklander 23389ed30d1SJens Wiklander out: 23489ed30d1SJens Wiklander if (buf) 23589ed30d1SJens Wiklander free(buf); 23689ed30d1SJens Wiklander 23789ed30d1SJens Wiklander return res; 23889ed30d1SJens Wiklander } 23989ed30d1SJens Wiklander 24089ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, 24189ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 24289ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 24389ed30d1SJens Wiklander { 24489ed30d1SJens Wiklander TEE_Result res; 24589ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 24689ed30d1SJens Wiklander 24789ed30d1SJens Wiklander ltc_key.type = PK_PUBLIC; 24889ed30d1SJens Wiklander ltc_key.e = key->e; 24989ed30d1SJens Wiklander ltc_key.N = key->n; 25089ed30d1SJens Wiklander 25189ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 25289ed30d1SJens Wiklander return res; 25389ed30d1SJens Wiklander } 25489ed30d1SJens Wiklander 25589ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, 25689ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 25789ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 25889ed30d1SJens Wiklander { 25989ed30d1SJens Wiklander TEE_Result res; 26089ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 26189ed30d1SJens Wiklander 26289ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 26389ed30d1SJens Wiklander ltc_key.e = key->e; 26489ed30d1SJens Wiklander ltc_key.N = key->n; 26589ed30d1SJens Wiklander ltc_key.d = key->d; 26689ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 26789ed30d1SJens Wiklander ltc_key.p = key->p; 26889ed30d1SJens Wiklander ltc_key.q = key->q; 26989ed30d1SJens Wiklander ltc_key.qP = key->qp; 27089ed30d1SJens Wiklander ltc_key.dP = key->dp; 27189ed30d1SJens Wiklander ltc_key.dQ = key->dq; 27289ed30d1SJens Wiklander } 27389ed30d1SJens Wiklander 27489ed30d1SJens Wiklander res = rsadorep(<c_key, src, src_len, dst, dst_len); 27589ed30d1SJens Wiklander return res; 27689ed30d1SJens Wiklander } 27789ed30d1SJens Wiklander 27889ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, 27989ed30d1SJens Wiklander const uint8_t *label, size_t label_len, 28089ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 28189ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 28289ed30d1SJens Wiklander { 28389ed30d1SJens Wiklander TEE_Result res = TEE_SUCCESS; 28489ed30d1SJens Wiklander void *buf = NULL; 28589ed30d1SJens Wiklander unsigned long blen; 28689ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo; 28789ed30d1SJens Wiklander size_t mod_size; 28889ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 28989ed30d1SJens Wiklander 29089ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 29189ed30d1SJens Wiklander ltc_key.e = key->e; 29289ed30d1SJens Wiklander ltc_key.d = key->d; 29389ed30d1SJens Wiklander ltc_key.N = key->n; 29489ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 29589ed30d1SJens Wiklander ltc_key.p = key->p; 29689ed30d1SJens Wiklander ltc_key.q = key->q; 29789ed30d1SJens Wiklander ltc_key.qP = key->qp; 29889ed30d1SJens Wiklander ltc_key.dP = key->dp; 29989ed30d1SJens Wiklander ltc_key.dQ = key->dq; 30089ed30d1SJens Wiklander } 30189ed30d1SJens Wiklander 30289ed30d1SJens Wiklander /* Get the algorithm */ 30389ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 30489ed30d1SJens Wiklander if (res != TEE_SUCCESS) { 30589ed30d1SJens Wiklander EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res); 30689ed30d1SJens Wiklander goto out; 30789ed30d1SJens Wiklander } 30889ed30d1SJens Wiklander 30989ed30d1SJens Wiklander /* 31089ed30d1SJens Wiklander * Use a temporary buffer since we don't know exactly how large 31189ed30d1SJens Wiklander * the required size of the out buffer without doing a partial 31289ed30d1SJens Wiklander * decrypt. We know the upper bound though. 31389ed30d1SJens Wiklander */ 31489ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { 31589ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 31689ed30d1SJens Wiklander blen = mod_size - 11; 31789ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 31889ed30d1SJens Wiklander } else { 31989ed30d1SJens Wiklander /* Decoded message is always shorter than encrypted message */ 32089ed30d1SJens Wiklander blen = src_len; 32189ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 32289ed30d1SJens Wiklander } 32389ed30d1SJens Wiklander 32489ed30d1SJens Wiklander buf = malloc(blen); 32589ed30d1SJens Wiklander if (!buf) { 32689ed30d1SJens Wiklander res = TEE_ERROR_OUT_OF_MEMORY; 32789ed30d1SJens Wiklander goto out; 32889ed30d1SJens Wiklander } 32989ed30d1SJens Wiklander 33089ed30d1SJens Wiklander ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen, 33189ed30d1SJens Wiklander ((label_len == 0) ? 0 : label), label_len, 33289ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_stat, 33389ed30d1SJens Wiklander <c_key); 33489ed30d1SJens Wiklander switch (ltc_res) { 33589ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 33689ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 33789ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 33889ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 33989ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 34089ed30d1SJens Wiklander goto out; 34189ed30d1SJens Wiklander case CRYPT_OK: 34289ed30d1SJens Wiklander break; 34389ed30d1SJens Wiklander default: 34489ed30d1SJens Wiklander /* This will result in a panic */ 34589ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); 34689ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 34789ed30d1SJens Wiklander goto out; 34889ed30d1SJens Wiklander } 34989ed30d1SJens Wiklander if (ltc_stat != 1) { 35089ed30d1SJens Wiklander /* This will result in a panic */ 35189ed30d1SJens Wiklander EMSG("rsa_decrypt_key_ex() returned %d and %d", 35289ed30d1SJens Wiklander ltc_res, ltc_stat); 35389ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 35489ed30d1SJens Wiklander goto out; 35589ed30d1SJens Wiklander } 35689ed30d1SJens Wiklander 35789ed30d1SJens Wiklander if (*dst_len < blen) { 35889ed30d1SJens Wiklander *dst_len = blen; 35989ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 36089ed30d1SJens Wiklander goto out; 36189ed30d1SJens Wiklander } 36289ed30d1SJens Wiklander 36389ed30d1SJens Wiklander res = TEE_SUCCESS; 36489ed30d1SJens Wiklander *dst_len = blen; 36589ed30d1SJens Wiklander memcpy(dst, buf, blen); 36689ed30d1SJens Wiklander 36789ed30d1SJens Wiklander out: 36889ed30d1SJens Wiklander if (buf) 36989ed30d1SJens Wiklander free(buf); 37089ed30d1SJens Wiklander 37189ed30d1SJens Wiklander return res; 37289ed30d1SJens Wiklander } 37389ed30d1SJens Wiklander 37489ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, 37589ed30d1SJens Wiklander struct rsa_public_key *key, 37689ed30d1SJens Wiklander const uint8_t *label, size_t label_len, 37789ed30d1SJens Wiklander const uint8_t *src, size_t src_len, 37889ed30d1SJens Wiklander uint8_t *dst, size_t *dst_len) 37989ed30d1SJens Wiklander { 38089ed30d1SJens Wiklander TEE_Result res; 38189ed30d1SJens Wiklander uint32_t mod_size; 38289ed30d1SJens Wiklander int ltc_hashindex, ltc_res, ltc_rsa_algo; 38389ed30d1SJens Wiklander rsa_key ltc_key = { 38489ed30d1SJens Wiklander .type = PK_PUBLIC, 38589ed30d1SJens Wiklander .e = key->e, 38689ed30d1SJens Wiklander .N = key->n 38789ed30d1SJens Wiklander }; 38889ed30d1SJens Wiklander 38989ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 39089ed30d1SJens Wiklander if (*dst_len < mod_size) { 39189ed30d1SJens Wiklander *dst_len = mod_size; 39289ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 39389ed30d1SJens Wiklander goto out; 39489ed30d1SJens Wiklander } 39589ed30d1SJens Wiklander *dst_len = mod_size; 39689ed30d1SJens Wiklander 39789ed30d1SJens Wiklander /* Get the algorithm */ 39889ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 39989ed30d1SJens Wiklander if (res != TEE_SUCCESS) 40089ed30d1SJens Wiklander goto out; 40189ed30d1SJens Wiklander 40289ed30d1SJens Wiklander if (algo == TEE_ALG_RSAES_PKCS1_V1_5) 40389ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 40489ed30d1SJens Wiklander else 40589ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_OAEP; 40689ed30d1SJens Wiklander 40789ed30d1SJens Wiklander ltc_res = rsa_encrypt_key_ex(src, src_len, dst, 40889ed30d1SJens Wiklander (unsigned long *)(dst_len), label, 409*1f3b1115SJens Wiklander label_len, NULL, find_prng("prng_crypto"), 41089ed30d1SJens Wiklander ltc_hashindex, ltc_rsa_algo, <c_key); 41189ed30d1SJens Wiklander switch (ltc_res) { 41289ed30d1SJens Wiklander case CRYPT_PK_INVALID_PADDING: 41389ed30d1SJens Wiklander case CRYPT_INVALID_PACKET: 41489ed30d1SJens Wiklander case CRYPT_PK_INVALID_SIZE: 41589ed30d1SJens Wiklander EMSG("rsa_encrypt_key_ex() returned %d", ltc_res); 41689ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 41789ed30d1SJens Wiklander goto out; 41889ed30d1SJens Wiklander case CRYPT_OK: 41989ed30d1SJens Wiklander break; 42089ed30d1SJens Wiklander default: 42189ed30d1SJens Wiklander /* This will result in a panic */ 42289ed30d1SJens Wiklander res = TEE_ERROR_GENERIC; 42389ed30d1SJens Wiklander goto out; 42489ed30d1SJens Wiklander } 42589ed30d1SJens Wiklander res = TEE_SUCCESS; 42689ed30d1SJens Wiklander 42789ed30d1SJens Wiklander out: 42889ed30d1SJens Wiklander return res; 42989ed30d1SJens Wiklander } 43089ed30d1SJens Wiklander 43189ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, 43289ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 43389ed30d1SJens Wiklander size_t msg_len, uint8_t *sig, 43489ed30d1SJens Wiklander size_t *sig_len) 43589ed30d1SJens Wiklander { 43689ed30d1SJens Wiklander TEE_Result res; 43789ed30d1SJens Wiklander size_t hash_size, mod_size; 43889ed30d1SJens Wiklander int ltc_res, ltc_rsa_algo, ltc_hashindex; 43989ed30d1SJens Wiklander unsigned long ltc_sig_len; 44089ed30d1SJens Wiklander rsa_key ltc_key = { 0, }; 44189ed30d1SJens Wiklander 44289ed30d1SJens Wiklander ltc_key.type = PK_PRIVATE; 44389ed30d1SJens Wiklander ltc_key.e = key->e; 44489ed30d1SJens Wiklander ltc_key.N = key->n; 44589ed30d1SJens Wiklander ltc_key.d = key->d; 44689ed30d1SJens Wiklander if (key->p && crypto_bignum_num_bytes(key->p)) { 44789ed30d1SJens Wiklander ltc_key.p = key->p; 44889ed30d1SJens Wiklander ltc_key.q = key->q; 44989ed30d1SJens Wiklander ltc_key.qP = key->qp; 45089ed30d1SJens Wiklander ltc_key.dP = key->dp; 45189ed30d1SJens Wiklander ltc_key.dQ = key->dq; 45289ed30d1SJens Wiklander } 45389ed30d1SJens Wiklander 45489ed30d1SJens Wiklander switch (algo) { 45589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 45689ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 45789ed30d1SJens Wiklander break; 45889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 45989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 46089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 46189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 46289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 46389ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 46489ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 46589ed30d1SJens Wiklander break; 46689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 46789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 46889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 46989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 47089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 47189ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 47289ed30d1SJens Wiklander break; 47389ed30d1SJens Wiklander default: 47489ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 47589ed30d1SJens Wiklander goto err; 47689ed30d1SJens Wiklander } 47789ed30d1SJens Wiklander 47889ed30d1SJens Wiklander if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) { 47989ed30d1SJens Wiklander ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 48089ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 48189ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 48289ed30d1SJens Wiklander goto err; 48389ed30d1SJens Wiklander } 48489ed30d1SJens Wiklander 48589ed30d1SJens Wiklander res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 48689ed30d1SJens Wiklander &hash_size); 48789ed30d1SJens Wiklander if (res != TEE_SUCCESS) 48889ed30d1SJens Wiklander goto err; 48989ed30d1SJens Wiklander 49089ed30d1SJens Wiklander if (msg_len != hash_size) { 49189ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 49289ed30d1SJens Wiklander goto err; 49389ed30d1SJens Wiklander } 49489ed30d1SJens Wiklander } 49589ed30d1SJens Wiklander 49689ed30d1SJens Wiklander mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); 49789ed30d1SJens Wiklander 49889ed30d1SJens Wiklander if (*sig_len < mod_size) { 49989ed30d1SJens Wiklander *sig_len = mod_size; 50089ed30d1SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 50189ed30d1SJens Wiklander goto err; 50289ed30d1SJens Wiklander } 50389ed30d1SJens Wiklander 50489ed30d1SJens Wiklander ltc_sig_len = mod_size; 50589ed30d1SJens Wiklander 50689ed30d1SJens Wiklander ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, 507*1f3b1115SJens Wiklander ltc_rsa_algo, NULL, find_prng("prng_crypto"), 50889ed30d1SJens Wiklander ltc_hashindex, salt_len, <c_key); 50989ed30d1SJens Wiklander 51089ed30d1SJens Wiklander *sig_len = ltc_sig_len; 51189ed30d1SJens Wiklander 51289ed30d1SJens Wiklander if (ltc_res != CRYPT_OK) { 51389ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 51489ed30d1SJens Wiklander goto err; 51589ed30d1SJens Wiklander } 51689ed30d1SJens Wiklander res = TEE_SUCCESS; 51789ed30d1SJens Wiklander 51889ed30d1SJens Wiklander err: 51989ed30d1SJens Wiklander return res; 52089ed30d1SJens Wiklander } 52189ed30d1SJens Wiklander 52289ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, 52389ed30d1SJens Wiklander struct rsa_public_key *key, 52489ed30d1SJens Wiklander int salt_len, const uint8_t *msg, 52589ed30d1SJens Wiklander size_t msg_len, const uint8_t *sig, 52689ed30d1SJens Wiklander size_t sig_len) 52789ed30d1SJens Wiklander { 52889ed30d1SJens Wiklander TEE_Result res; 52989ed30d1SJens Wiklander uint32_t bigint_size; 53089ed30d1SJens Wiklander size_t hash_size; 53189ed30d1SJens Wiklander int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; 53289ed30d1SJens Wiklander rsa_key ltc_key = { 53389ed30d1SJens Wiklander .type = PK_PUBLIC, 53489ed30d1SJens Wiklander .e = key->e, 53589ed30d1SJens Wiklander .N = key->n 53689ed30d1SJens Wiklander }; 53789ed30d1SJens Wiklander 53889ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 53989ed30d1SJens Wiklander res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), 54089ed30d1SJens Wiklander &hash_size); 54189ed30d1SJens Wiklander if (res != TEE_SUCCESS) 54289ed30d1SJens Wiklander goto err; 54389ed30d1SJens Wiklander 54489ed30d1SJens Wiklander if (msg_len != hash_size) { 54589ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 54689ed30d1SJens Wiklander goto err; 54789ed30d1SJens Wiklander } 54889ed30d1SJens Wiklander } 54989ed30d1SJens Wiklander 55089ed30d1SJens Wiklander bigint_size = ltc_mp.unsigned_size(ltc_key.N); 55189ed30d1SJens Wiklander if (sig_len < bigint_size) { 55289ed30d1SJens Wiklander res = TEE_ERROR_SIGNATURE_INVALID; 55389ed30d1SJens Wiklander goto err; 55489ed30d1SJens Wiklander } 55589ed30d1SJens Wiklander 55689ed30d1SJens Wiklander /* Get the algorithm */ 55789ed30d1SJens Wiklander if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { 55889ed30d1SJens Wiklander res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); 55989ed30d1SJens Wiklander if (res != TEE_SUCCESS) 56089ed30d1SJens Wiklander goto err; 56189ed30d1SJens Wiklander } 56289ed30d1SJens Wiklander 56389ed30d1SJens Wiklander switch (algo) { 56489ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5: 56589ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; 56689ed30d1SJens Wiklander break; 56789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 56889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 56989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 57089ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 57189ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 57289ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 57389ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_V1_5; 57489ed30d1SJens Wiklander break; 57589ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 57689ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 57789ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 57889ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 57989ed30d1SJens Wiklander case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 58089ed30d1SJens Wiklander ltc_rsa_algo = LTC_PKCS_1_PSS; 58189ed30d1SJens Wiklander break; 58289ed30d1SJens Wiklander default: 58389ed30d1SJens Wiklander res = TEE_ERROR_BAD_PARAMETERS; 58489ed30d1SJens Wiklander goto err; 58589ed30d1SJens Wiklander } 58689ed30d1SJens Wiklander 58789ed30d1SJens Wiklander ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo, 58889ed30d1SJens Wiklander ltc_hashindex, salt_len, &stat, <c_key); 58989ed30d1SJens Wiklander res = convert_ltc_verify_status(ltc_res, stat); 59089ed30d1SJens Wiklander err: 59189ed30d1SJens Wiklander return res; 59289ed30d1SJens Wiklander } 593