blob: a323a3baafe1aa49cb409b9075dadd80d05fb55e [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (C) 2018, ARM Limited
* Copyright (C) 2019, Linaro Limited
*/
#include <assert.h>
#include <crypto/crypto.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/pk.h>
#include <mbedtls/pk_internal.h>
#include <stdlib.h>
#include <string.h>
#include <tee/tee_cryp_utl.h>
#include <utee_defines.h>
#include "mbd_rand.h"
static TEE_Result get_tee_result(int lmd_res)
{
switch (lmd_res) {
case 0:
return TEE_SUCCESS;
case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
case MBEDTLS_ERR_RSA_INVALID_PADDING:
case MBEDTLS_ERR_PK_TYPE_MISMATCH:
return TEE_ERROR_BAD_PARAMETERS;
case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
return TEE_ERROR_SHORT_BUFFER;
default:
return TEE_ERROR_BAD_STATE;
}
}
static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo)
{
switch (algo) {
#if defined(CFG_CRYPTO_SHA1)
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
case TEE_ALG_SHA1:
case TEE_ALG_DSA_SHA1:
case TEE_ALG_HMAC_SHA1:
return MBEDTLS_MD_SHA1;
#endif
#if defined(CFG_CRYPTO_MD5)
case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
case TEE_ALG_MD5:
case TEE_ALG_HMAC_MD5:
return MBEDTLS_MD_MD5;
#endif
#if defined(CFG_CRYPTO_SHA224)
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
case TEE_ALG_SHA224:
case TEE_ALG_DSA_SHA224:
case TEE_ALG_HMAC_SHA224:
return MBEDTLS_MD_SHA224;
#endif
#if defined(CFG_CRYPTO_SHA256)
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
case TEE_ALG_SHA256:
case TEE_ALG_DSA_SHA256:
case TEE_ALG_HMAC_SHA256:
return MBEDTLS_MD_SHA256;
#endif
#if defined(CFG_CRYPTO_SHA384)
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
case TEE_ALG_SHA384:
case TEE_ALG_HMAC_SHA384:
return MBEDTLS_MD_SHA384;
#endif
#if defined(CFG_CRYPTO_SHA512)
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
case TEE_ALG_SHA512:
case TEE_ALG_HMAC_SHA512:
return MBEDTLS_MD_SHA512;
#endif
default:
return MBEDTLS_MD_NONE;
}
}
static void rsa_init_from_key_pair(mbedtls_rsa_context *rsa,
struct rsa_keypair *key)
{
mbedtls_rsa_init(rsa, 0, 0);
rsa->E = *(mbedtls_mpi *)key->e;
rsa->N = *(mbedtls_mpi *)key->n;
rsa->D = *(mbedtls_mpi *)key->d;
if (key->p && crypto_bignum_num_bytes(key->p)) {
rsa->P = *(mbedtls_mpi *)key->p;
rsa->Q = *(mbedtls_mpi *)key->q;
rsa->QP = *(mbedtls_mpi *)key->qp;
rsa->DP = *(mbedtls_mpi *)key->dp;
rsa->DQ = *(mbedtls_mpi *)key->dq;
}
rsa->len = mbedtls_mpi_size(&rsa->N);
}
static void mbd_rsa_free(mbedtls_rsa_context *rsa)
{
/* Reset mpi to skip freeing here, those mpis will be freed with key */
mbedtls_mpi_init(&rsa->E);
mbedtls_mpi_init(&rsa->N);
mbedtls_mpi_init(&rsa->D);
if (mbedtls_mpi_size(&rsa->P)) {
mbedtls_mpi_init(&rsa->P);
mbedtls_mpi_init(&rsa->Q);
mbedtls_mpi_init(&rsa->QP);
mbedtls_mpi_init(&rsa->DP);
mbedtls_mpi_init(&rsa->DQ);
}
mbedtls_rsa_free(rsa);
}
TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
size_t key_size_bits)
{
memset(s, 0, sizeof(*s));
s->e = crypto_bignum_allocate(key_size_bits);
if (!s->e)
goto err;
s->d = crypto_bignum_allocate(key_size_bits);
if (!s->d)
goto err;
s->n = crypto_bignum_allocate(key_size_bits);
if (!s->n)
goto err;
s->p = crypto_bignum_allocate(key_size_bits);
if (!s->p)
goto err;
s->q = crypto_bignum_allocate(key_size_bits);
if (!s->q)
goto err;
s->qp = crypto_bignum_allocate(key_size_bits);
if (!s->qp)
goto err;
s->dp = crypto_bignum_allocate(key_size_bits);
if (!s->dp)
goto err;
s->dq = crypto_bignum_allocate(key_size_bits);
if (!s->dq)
goto err;
return TEE_SUCCESS;
err:
crypto_bignum_free(s->e);
crypto_bignum_free(s->d);
crypto_bignum_free(s->n);
crypto_bignum_free(s->p);
crypto_bignum_free(s->q);
crypto_bignum_free(s->qp);
crypto_bignum_free(s->dp);
return TEE_ERROR_OUT_OF_MEMORY;
}
TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
size_t key_size_bits)
{
memset(s, 0, sizeof(*s));
s->e = crypto_bignum_allocate(key_size_bits);
if (!s->e)
return TEE_ERROR_OUT_OF_MEMORY;
s->n = crypto_bignum_allocate(key_size_bits);
if (!s->n)
goto err;
return TEE_SUCCESS;
err:
crypto_bignum_free(s->e);
return TEE_ERROR_OUT_OF_MEMORY;
}
void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
{
if (!s)
return;
crypto_bignum_free(s->n);
crypto_bignum_free(s->e);
}
TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size)
{
TEE_Result res = TEE_SUCCESS;
mbedtls_rsa_context rsa;
int lmd_res = 0;
uint32_t e = 0;
memset(&rsa, 0, sizeof(rsa));
mbedtls_rsa_init(&rsa, 0, 0);
/* get the public exponent */
mbedtls_mpi_write_binary((mbedtls_mpi *)key->e,
(unsigned char *)&e, sizeof(uint32_t));
e = TEE_U32_FROM_BIG_ENDIAN(e);
lmd_res = mbedtls_rsa_gen_key(&rsa, mbd_rand, NULL, key_size, (int)e);
if (lmd_res != 0) {
res = get_tee_result(lmd_res);
} else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) {
res = TEE_ERROR_BAD_PARAMETERS;
} else {
/* Copy the key */
crypto_bignum_copy(key->e, (void *)&rsa.E);
crypto_bignum_copy(key->d, (void *)&rsa.D);
crypto_bignum_copy(key->n, (void *)&rsa.N);
crypto_bignum_copy(key->p, (void *)&rsa.P);
crypto_bignum_copy(key->q, (void *)&rsa.Q);
crypto_bignum_copy(key->qp, (void *)&rsa.QP);
crypto_bignum_copy(key->dp, (void *)&rsa.DP);
crypto_bignum_copy(key->dq, (void *)&rsa.DQ);
res = TEE_SUCCESS;
}
mbedtls_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
const uint8_t *src, size_t src_len,
uint8_t *dst, size_t *dst_len)
{
TEE_Result res = TEE_SUCCESS;
mbedtls_rsa_context rsa;
int lmd_res = 0;
uint8_t *buf = NULL;
unsigned long blen = 0;
unsigned long offset = 0;
memset(&rsa, 0, sizeof(rsa));
mbedtls_rsa_init(&rsa, 0, 0);
rsa.E = *(mbedtls_mpi *)key->e;
rsa.N = *(mbedtls_mpi *)key->n;
rsa.len = crypto_bignum_num_bytes((void *)&rsa.N);
blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
buf = malloc(blen);
if (!buf) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
memset(buf, 0, blen);
memcpy(buf + rsa.len - src_len, src, src_len);
lmd_res = mbedtls_rsa_public(&rsa, buf, buf);
if (lmd_res != 0) {
FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res);
res = get_tee_result(lmd_res);
goto out;
}
/* Remove the zero-padding (leave one zero if buff is all zeroes) */
offset = 0;
while ((offset < rsa.len - 1) && (buf[offset] == 0))
offset++;
if (*dst_len < rsa.len - offset) {
*dst_len = rsa.len - offset;
res = TEE_ERROR_SHORT_BUFFER;
goto out;
}
*dst_len = rsa.len - offset;
memcpy(dst, buf + offset, *dst_len);
out:
free(buf);
/* Reset mpi to skip freeing here, those mpis will be freed with key */
mbedtls_mpi_init(&rsa.E);
mbedtls_mpi_init(&rsa.N);
mbedtls_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
const uint8_t *src, size_t src_len,
uint8_t *dst, size_t *dst_len)
{
TEE_Result res = TEE_SUCCESS;
mbedtls_rsa_context rsa;
int lmd_res = 0;
uint8_t *buf = NULL;
unsigned long blen = 0;
unsigned long offset = 0;
memset(&rsa, 0, sizeof(rsa));
rsa_init_from_key_pair(&rsa, key);
blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
buf = malloc(blen);
if (!buf) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
memset(buf, 0, blen);
memcpy(buf + rsa.len - src_len, src, src_len);
lmd_res = mbedtls_rsa_private(&rsa, NULL, NULL, buf, buf);
if (lmd_res != 0) {
FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res);
res = get_tee_result(lmd_res);
goto out;
}
/* Remove the zero-padding (leave one zero if buff is all zeroes) */
offset = 0;
while ((offset < rsa.len - 1) && (buf[offset] == 0))
offset++;
if (*dst_len < rsa.len - offset) {
*dst_len = rsa.len - offset;
res = TEE_ERROR_SHORT_BUFFER;
goto out;
}
*dst_len = rsa.len - offset;
memcpy(dst, (char *)buf + offset, *dst_len);
out:
if (buf)
free(buf);
mbd_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
const uint8_t *label __unused,
size_t label_len __unused,
const uint8_t *src, size_t src_len,
uint8_t *dst, size_t *dst_len)
{
TEE_Result res = TEE_SUCCESS;
int lmd_res = 0;
int lmd_padding = 0;
size_t blen = 0;
size_t mod_size = 0;
void *buf = NULL;
mbedtls_rsa_context rsa;
const mbedtls_pk_info_t *pk_info = NULL;
uint32_t md_algo = MBEDTLS_MD_NONE;
memset(&rsa, 0, sizeof(rsa));
rsa_init_from_key_pair(&rsa, key);
/*
* Use a temporary buffer since we don't know exactly how large
* the required size of the out buffer without doing a partial
* decrypt. We know the upper bound though.
*/
if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
mod_size = crypto_bignum_num_bytes(key->n);
blen = mod_size - 11;
lmd_padding = MBEDTLS_RSA_PKCS_V15;
} else {
/* Decoded message is always shorter than encrypted message */
blen = src_len;
lmd_padding = MBEDTLS_RSA_PKCS_V21;
}
buf = malloc(blen);
if (!buf) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (!pk_info) {
res = TEE_ERROR_NOT_SUPPORTED;
goto out;
}
/*
* TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
* not be used in rsa, so skip it here.
*/
if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
md_algo = tee_algo_to_mbedtls_hash_algo(algo);
if (md_algo == MBEDTLS_MD_NONE) {
res = TEE_ERROR_NOT_SUPPORTED;
goto out;
}
}
mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
if (lmd_padding == MBEDTLS_RSA_PKCS_V15)
lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
blen, NULL, NULL);
else
lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
blen, mbd_rand, NULL);
if (lmd_res != 0) {
FMSG("decrypt_func() returned 0x%x", -lmd_res);
res = get_tee_result(lmd_res);
goto out;
}
if (*dst_len < blen) {
*dst_len = blen;
res = TEE_ERROR_SHORT_BUFFER;
goto out;
}
res = TEE_SUCCESS;
*dst_len = blen;
memcpy(dst, buf, blen);
out:
if (buf)
free(buf);
mbd_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
struct rsa_public_key *key,
const uint8_t *label __unused,
size_t label_len __unused,
const uint8_t *src, size_t src_len,
uint8_t *dst, size_t *dst_len)
{
TEE_Result res = TEE_SUCCESS;
int lmd_res = 0;
int lmd_padding = 0;
size_t mod_size = 0;
mbedtls_rsa_context rsa;
const mbedtls_pk_info_t *pk_info = NULL;
uint32_t md_algo = MBEDTLS_MD_NONE;
memset(&rsa, 0, sizeof(rsa));
mbedtls_rsa_init(&rsa, 0, 0);
rsa.E = *(mbedtls_mpi *)key->e;
rsa.N = *(mbedtls_mpi *)key->n;
mod_size = crypto_bignum_num_bytes(key->n);
if (*dst_len < mod_size) {
*dst_len = mod_size;
res = TEE_ERROR_SHORT_BUFFER;
goto out;
}
*dst_len = mod_size;
rsa.len = mod_size;
if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
lmd_padding = MBEDTLS_RSA_PKCS_V15;
else
lmd_padding = MBEDTLS_RSA_PKCS_V21;
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (!pk_info) {
res = TEE_ERROR_NOT_SUPPORTED;
goto out;
}
/*
* TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
* not be used in rsa, so skip it here.
*/
if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
md_algo = tee_algo_to_mbedtls_hash_algo(algo);
if (md_algo == MBEDTLS_MD_NONE) {
res = TEE_ERROR_NOT_SUPPORTED;
goto out;
}
}
mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
lmd_res = pk_info->encrypt_func(&rsa, src, src_len, dst, dst_len,
*dst_len, mbd_rand, NULL);
if (lmd_res != 0) {
FMSG("encrypt_func() returned 0x%x", -lmd_res);
res = get_tee_result(lmd_res);
goto out;
}
res = TEE_SUCCESS;
out:
/* Reset mpi to skip freeing here, those mpis will be freed with key */
mbedtls_mpi_init(&rsa.E);
mbedtls_mpi_init(&rsa.N);
mbedtls_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
int salt_len __unused, const uint8_t *msg,
size_t msg_len, uint8_t *sig,
size_t *sig_len)
{
TEE_Result res = TEE_SUCCESS;
int lmd_res = 0;
int lmd_padding = 0;
size_t mod_size = 0;
size_t hash_size = 0;
mbedtls_rsa_context rsa;
const mbedtls_pk_info_t *pk_info = NULL;
uint32_t md_algo = 0;
memset(&rsa, 0, sizeof(rsa));
rsa_init_from_key_pair(&rsa, key);
switch (algo) {
case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
lmd_padding = MBEDTLS_RSA_PKCS_V15;
break;
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
lmd_padding = MBEDTLS_RSA_PKCS_V21;
break;
default:
res = TEE_ERROR_BAD_PARAMETERS;
goto err;
}
res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
&hash_size);
if (res != TEE_SUCCESS)
goto err;
if (msg_len != hash_size) {
res = TEE_ERROR_BAD_PARAMETERS;
goto err;
}
mod_size = crypto_bignum_num_bytes(key->n);
if (*sig_len < mod_size) {
*sig_len = mod_size;
res = TEE_ERROR_SHORT_BUFFER;
goto err;
}
rsa.len = mod_size;
md_algo = tee_algo_to_mbedtls_hash_algo(algo);
if (md_algo == MBEDTLS_MD_NONE) {
res = TEE_ERROR_NOT_SUPPORTED;
goto err;
}
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (!pk_info) {
res = TEE_ERROR_NOT_SUPPORTED;
goto err;
}
mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
if (lmd_padding == MBEDTLS_RSA_PKCS_V15)
lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
sig_len, NULL, NULL);
else
lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
sig_len, mbd_rand, NULL);
if (lmd_res != 0) {
FMSG("sign_func failed, returned 0x%x", -lmd_res);
res = get_tee_result(lmd_res);
goto err;
}
res = TEE_SUCCESS;
err:
mbd_rsa_free(&rsa);
return res;
}
TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
struct rsa_public_key *key,
int salt_len __unused,
const uint8_t *msg,
size_t msg_len, const uint8_t *sig,
size_t sig_len)
{
TEE_Result res = TEE_SUCCESS;
int lmd_res = 0;
int lmd_padding = 0;
size_t hash_size = 0;
size_t bigint_size = 0;
mbedtls_rsa_context rsa;
const mbedtls_pk_info_t *pk_info = NULL;
uint32_t md_algo = 0;
memset(&rsa, 0, sizeof(rsa));
mbedtls_rsa_init(&rsa, 0, 0);
rsa.E = *(mbedtls_mpi *)key->e;
rsa.N = *(mbedtls_mpi *)key->n;
res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
&hash_size);
if (res != TEE_SUCCESS)
goto err;
if (msg_len != hash_size) {
res = TEE_ERROR_BAD_PARAMETERS;
goto err;
}
bigint_size = crypto_bignum_num_bytes(key->n);
if (sig_len < bigint_size) {
res = TEE_ERROR_MAC_INVALID;
goto err;
}
rsa.len = bigint_size;
switch (algo) {
case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
lmd_padding = MBEDTLS_RSA_PKCS_V15;
break;
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
lmd_padding = MBEDTLS_RSA_PKCS_V21;
break;
default:
res = TEE_ERROR_BAD_PARAMETERS;
goto err;
}
md_algo = tee_algo_to_mbedtls_hash_algo(algo);
if (md_algo == MBEDTLS_MD_NONE) {
res = TEE_ERROR_NOT_SUPPORTED;
goto err;
}
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (!pk_info) {
res = TEE_ERROR_NOT_SUPPORTED;
goto err;
}
mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
lmd_res = pk_info->verify_func(&rsa, md_algo, msg, msg_len,
sig, sig_len);
if (lmd_res != 0) {
FMSG("verify_func failed, returned 0x%x", -lmd_res);
res = TEE_ERROR_SIGNATURE_INVALID;
goto err;
}
res = TEE_SUCCESS;
err:
/* Reset mpi to skip freeing here, those mpis will be freed with key */
mbedtls_mpi_init(&rsa.E);
mbedtls_mpi_init(&rsa.N);
mbedtls_rsa_free(&rsa);
return res;
}