178887e60SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
278887e60SJens Wiklander /*
378887e60SJens Wiklander * Copyright (c) 2018, Linaro Limited
478887e60SJens Wiklander */
578887e60SJens Wiklander
678887e60SJens Wiklander #include <crypto/crypto.h>
778887e60SJens Wiklander #include <kernel/panic.h>
878887e60SJens Wiklander #include <mbedtls/bignum.h>
978887e60SJens Wiklander #include <mempool.h>
1078887e60SJens Wiklander #include <stdlib.h>
1178887e60SJens Wiklander #include <string.h>
125a913ee7SJerome Forissier #include <tomcrypt_private.h>
1378887e60SJens Wiklander #include <tomcrypt_mp.h>
1478887e60SJens Wiklander #include <util.h>
1578887e60SJens Wiklander
16a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_PAGER)
1778887e60SJens Wiklander #include <mm/core_mmu.h>
1878887e60SJens Wiklander #include <mm/tee_pager.h>
1978887e60SJens Wiklander #endif
2078887e60SJens Wiklander
2178887e60SJens Wiklander /* Size needed for xtest to pass reliably on both ARM32 and ARM64 */
22bfb19bc2SSahil Malhotra #define MPI_MEMPOOL_SIZE (46 * 1024)
2378887e60SJens Wiklander
244b5c81ccSJens Wiklander /* From mbedtls/library/bignum.c */
254b5c81ccSJens Wiklander #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
264b5c81ccSJens Wiklander #define biL (ciL << 3) /* bits in limb */
274b5c81ccSJens Wiklander #define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
284b5c81ccSJens Wiklander
29a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_PAGER)
3078887e60SJens Wiklander /* allocate pageable_zi vmem for mp scratch memory pool */
get_mp_scratch_memory_pool(void)3178887e60SJens Wiklander static struct mempool *get_mp_scratch_memory_pool(void)
3278887e60SJens Wiklander {
3378887e60SJens Wiklander size_t size;
3478887e60SJens Wiklander void *data;
3578887e60SJens Wiklander
3678887e60SJens Wiklander size = ROUNDUP(MPI_MEMPOOL_SIZE, SMALL_PAGE_SIZE);
377513149eSJens Wiklander data = tee_pager_alloc(size);
3878887e60SJens Wiklander if (!data)
3978887e60SJens Wiklander panic();
4078887e60SJens Wiklander
4178887e60SJens Wiklander return mempool_alloc_pool(data, size, tee_pager_release_phys);
4278887e60SJens Wiklander }
43a1cbb728SJens Wiklander #else /* _CFG_CORE_LTC_PAGER */
get_mp_scratch_memory_pool(void)4478887e60SJens Wiklander static struct mempool *get_mp_scratch_memory_pool(void)
4578887e60SJens Wiklander {
4678887e60SJens Wiklander static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN);
4778887e60SJens Wiklander
4878887e60SJens Wiklander return mempool_alloc_pool(data, sizeof(data), NULL);
4978887e60SJens Wiklander }
5078887e60SJens Wiklander #endif
5178887e60SJens Wiklander
init_mp_tomcrypt(void)5278887e60SJens Wiklander void init_mp_tomcrypt(void)
5378887e60SJens Wiklander {
5478887e60SJens Wiklander struct mempool *p = get_mp_scratch_memory_pool();
5578887e60SJens Wiklander
5678887e60SJens Wiklander if (!p)
5778887e60SJens Wiklander panic();
5878887e60SJens Wiklander mbedtls_mpi_mempool = p;
5995d0db1eSJens Wiklander assert(!mempool_default);
6095d0db1eSJens Wiklander mempool_default = p;
6178887e60SJens Wiklander }
6278887e60SJens Wiklander
init(void ** a)6378887e60SJens Wiklander static int init(void **a)
6478887e60SJens Wiklander {
6578887e60SJens Wiklander mbedtls_mpi *bn = mempool_alloc(mbedtls_mpi_mempool, sizeof(*bn));
6678887e60SJens Wiklander
6778887e60SJens Wiklander if (!bn)
6878887e60SJens Wiklander return CRYPT_MEM;
6978887e60SJens Wiklander
7078887e60SJens Wiklander mbedtls_mpi_init_mempool(bn);
7178887e60SJens Wiklander *a = bn;
7278887e60SJens Wiklander return CRYPT_OK;
7378887e60SJens Wiklander }
7478887e60SJens Wiklander
init_size(int size_bits __unused,void ** a)7578887e60SJens Wiklander static int init_size(int size_bits __unused, void **a)
7678887e60SJens Wiklander {
7778887e60SJens Wiklander return init(a);
7878887e60SJens Wiklander }
7978887e60SJens Wiklander
deinit(void * a)8078887e60SJens Wiklander static void deinit(void *a)
8178887e60SJens Wiklander {
8278887e60SJens Wiklander mbedtls_mpi_free((mbedtls_mpi *)a);
8378887e60SJens Wiklander mempool_free(mbedtls_mpi_mempool, a);
8478887e60SJens Wiklander }
8578887e60SJens Wiklander
neg(void * a,void * b)8678887e60SJens Wiklander static int neg(void *a, void *b)
8778887e60SJens Wiklander {
8878887e60SJens Wiklander if (mbedtls_mpi_copy(b, a))
8978887e60SJens Wiklander return CRYPT_MEM;
9078887e60SJens Wiklander ((mbedtls_mpi *)b)->s *= -1;
9178887e60SJens Wiklander return CRYPT_OK;
9278887e60SJens Wiklander }
9378887e60SJens Wiklander
copy(void * a,void * b)9478887e60SJens Wiklander static int copy(void *a, void *b)
9578887e60SJens Wiklander {
9678887e60SJens Wiklander if (mbedtls_mpi_copy(b, a))
9778887e60SJens Wiklander return CRYPT_MEM;
9878887e60SJens Wiklander return CRYPT_OK;
9978887e60SJens Wiklander }
10078887e60SJens Wiklander
init_copy(void ** a,void * b)10178887e60SJens Wiklander static int init_copy(void **a, void *b)
10278887e60SJens Wiklander {
10378887e60SJens Wiklander if (init(a) != CRYPT_OK) {
10478887e60SJens Wiklander return CRYPT_MEM;
10578887e60SJens Wiklander }
10678887e60SJens Wiklander return copy(b, *a);
10778887e60SJens Wiklander }
10878887e60SJens Wiklander
10978887e60SJens Wiklander /* ---- trivial ---- */
set_int(void * a,ltc_mp_digit b)1105a913ee7SJerome Forissier static int set_int(void *a, ltc_mp_digit b)
11178887e60SJens Wiklander {
11278887e60SJens Wiklander uint32_t b32 = b;
11378887e60SJens Wiklander
11478887e60SJens Wiklander if (b32 != b)
11578887e60SJens Wiklander return CRYPT_INVALID_ARG;
11678887e60SJens Wiklander
11778887e60SJens Wiklander mbedtls_mpi_uint p = b32;
11878887e60SJens Wiklander mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p };
11978887e60SJens Wiklander
12078887e60SJens Wiklander if (mbedtls_mpi_copy(a, &bn))
12178887e60SJens Wiklander return CRYPT_MEM;
12278887e60SJens Wiklander return CRYPT_OK;
12378887e60SJens Wiklander }
12478887e60SJens Wiklander
get_int(void * a)12578887e60SJens Wiklander static unsigned long get_int(void *a)
12678887e60SJens Wiklander {
12778887e60SJens Wiklander mbedtls_mpi *bn = a;
12878887e60SJens Wiklander
12978887e60SJens Wiklander if (!bn->n)
13078887e60SJens Wiklander return 0;
13178887e60SJens Wiklander
13278887e60SJens Wiklander return bn->p[bn->n - 1];
13378887e60SJens Wiklander }
13478887e60SJens Wiklander
get_digit(void * a,int n)13578887e60SJens Wiklander static ltc_mp_digit get_digit(void *a, int n)
13678887e60SJens Wiklander {
13778887e60SJens Wiklander mbedtls_mpi *bn = a;
13878887e60SJens Wiklander
13978887e60SJens Wiklander COMPILE_TIME_ASSERT(sizeof(ltc_mp_digit) >= sizeof(mbedtls_mpi_uint));
14078887e60SJens Wiklander
14178887e60SJens Wiklander if (n < 0 || (size_t)n >= bn->n)
14278887e60SJens Wiklander return 0;
14378887e60SJens Wiklander
14478887e60SJens Wiklander return bn->p[n];
14578887e60SJens Wiklander }
14678887e60SJens Wiklander
get_digit_count(void * a)14778887e60SJens Wiklander static int get_digit_count(void *a)
14878887e60SJens Wiklander {
149*04e46975SEtienne Carriere return ROUNDUP_DIV(mbedtls_mpi_size(a), sizeof(mbedtls_mpi_uint));
15078887e60SJens Wiklander }
15178887e60SJens Wiklander
compare(void * a,void * b)15278887e60SJens Wiklander static int compare(void *a, void *b)
15378887e60SJens Wiklander {
15478887e60SJens Wiklander int ret = mbedtls_mpi_cmp_mpi(a, b);
15578887e60SJens Wiklander
15678887e60SJens Wiklander if (ret < 0)
15778887e60SJens Wiklander return LTC_MP_LT;
15878887e60SJens Wiklander
15978887e60SJens Wiklander if (ret > 0)
16078887e60SJens Wiklander return LTC_MP_GT;
16178887e60SJens Wiklander
16278887e60SJens Wiklander return LTC_MP_EQ;
16378887e60SJens Wiklander }
16478887e60SJens Wiklander
compare_d(void * a,ltc_mp_digit b)1655a913ee7SJerome Forissier static int compare_d(void *a, ltc_mp_digit b)
16678887e60SJens Wiklander {
16778887e60SJens Wiklander unsigned long v = b;
16878887e60SJens Wiklander unsigned int shift = 31;
16978887e60SJens Wiklander uint32_t mask = BIT(shift) - 1;
17078887e60SJens Wiklander mbedtls_mpi bn;
17178887e60SJens Wiklander
17278887e60SJens Wiklander mbedtls_mpi_init_mempool(&bn);
17378887e60SJens Wiklander while (true) {
17478887e60SJens Wiklander mbedtls_mpi_add_int(&bn, &bn, v & mask);
17578887e60SJens Wiklander v >>= shift;
17678887e60SJens Wiklander if (!v)
17778887e60SJens Wiklander break;
17878887e60SJens Wiklander mbedtls_mpi_shift_l(&bn, shift);
17978887e60SJens Wiklander }
18078887e60SJens Wiklander
18178887e60SJens Wiklander int ret = compare(a, &bn);
18278887e60SJens Wiklander
18378887e60SJens Wiklander mbedtls_mpi_free(&bn);
18478887e60SJens Wiklander
18578887e60SJens Wiklander return ret;
18678887e60SJens Wiklander }
18778887e60SJens Wiklander
count_bits(void * a)18878887e60SJens Wiklander static int count_bits(void *a)
18978887e60SJens Wiklander {
19078887e60SJens Wiklander return mbedtls_mpi_bitlen(a);
19178887e60SJens Wiklander }
19278887e60SJens Wiklander
count_lsb_bits(void * a)19378887e60SJens Wiklander static int count_lsb_bits(void *a)
19478887e60SJens Wiklander {
19578887e60SJens Wiklander return mbedtls_mpi_lsb(a);
19678887e60SJens Wiklander }
19778887e60SJens Wiklander
19878887e60SJens Wiklander
twoexpt(void * a,int n)19978887e60SJens Wiklander static int twoexpt(void *a, int n)
20078887e60SJens Wiklander {
20178887e60SJens Wiklander if (mbedtls_mpi_set_bit(a, n, 1))
20278887e60SJens Wiklander return CRYPT_MEM;
20378887e60SJens Wiklander
20478887e60SJens Wiklander return CRYPT_OK;
20578887e60SJens Wiklander }
20678887e60SJens Wiklander
20778887e60SJens Wiklander /* ---- conversions ---- */
20878887e60SJens Wiklander
20978887e60SJens Wiklander /* read ascii string */
read_radix(void * a,const char * b,int radix)21078887e60SJens Wiklander static int read_radix(void *a, const char *b, int radix)
21178887e60SJens Wiklander {
21278887e60SJens Wiklander int res = mbedtls_mpi_read_string(a, radix, b);
21378887e60SJens Wiklander
21478887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
21578887e60SJens Wiklander return CRYPT_MEM;
21678887e60SJens Wiklander if (res)
21778887e60SJens Wiklander return CRYPT_ERROR;
21878887e60SJens Wiklander
21978887e60SJens Wiklander return CRYPT_OK;
22078887e60SJens Wiklander }
22178887e60SJens Wiklander
22278887e60SJens Wiklander /* write one */
write_radix(void * a,char * b,int radix)22378887e60SJens Wiklander static int write_radix(void *a, char *b, int radix)
22478887e60SJens Wiklander {
22578887e60SJens Wiklander size_t ol = SIZE_MAX;
22678887e60SJens Wiklander int res = mbedtls_mpi_write_string(a, radix, b, ol, &ol);
22778887e60SJens Wiklander
22878887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
22978887e60SJens Wiklander return CRYPT_MEM;
23078887e60SJens Wiklander if (res)
23178887e60SJens Wiklander return CRYPT_ERROR;
23278887e60SJens Wiklander
23378887e60SJens Wiklander return CRYPT_OK;
23478887e60SJens Wiklander }
23578887e60SJens Wiklander
23678887e60SJens Wiklander /* get size as unsigned char string */
unsigned_size(void * a)23778887e60SJens Wiklander static unsigned long unsigned_size(void *a)
23878887e60SJens Wiklander {
23978887e60SJens Wiklander return mbedtls_mpi_size(a);
24078887e60SJens Wiklander }
24178887e60SJens Wiklander
24278887e60SJens Wiklander /* store */
unsigned_write(void * a,unsigned char * b)24378887e60SJens Wiklander static int unsigned_write(void *a, unsigned char *b)
24478887e60SJens Wiklander {
24578887e60SJens Wiklander int res = mbedtls_mpi_write_binary(a, b, unsigned_size(a));
24678887e60SJens Wiklander
24778887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
24878887e60SJens Wiklander return CRYPT_MEM;
24978887e60SJens Wiklander if (res)
25078887e60SJens Wiklander return CRYPT_ERROR;
25178887e60SJens Wiklander
25278887e60SJens Wiklander return CRYPT_OK;
25378887e60SJens Wiklander }
25478887e60SJens Wiklander
25578887e60SJens Wiklander /* read */
unsigned_read(void * a,unsigned char * b,unsigned long len)25678887e60SJens Wiklander static int unsigned_read(void *a, unsigned char *b, unsigned long len)
25778887e60SJens Wiklander {
25878887e60SJens Wiklander int res = mbedtls_mpi_read_binary(a, b, len);
25978887e60SJens Wiklander
26078887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
26178887e60SJens Wiklander return CRYPT_MEM;
26278887e60SJens Wiklander if (res)
26378887e60SJens Wiklander return CRYPT_ERROR;
26478887e60SJens Wiklander
26578887e60SJens Wiklander return CRYPT_OK;
26678887e60SJens Wiklander }
26778887e60SJens Wiklander
26878887e60SJens Wiklander /* add */
add(void * a,void * b,void * c)26978887e60SJens Wiklander static int add(void *a, void *b, void *c)
27078887e60SJens Wiklander {
27178887e60SJens Wiklander if (mbedtls_mpi_add_mpi(c, a, b))
27278887e60SJens Wiklander return CRYPT_MEM;
27378887e60SJens Wiklander
27478887e60SJens Wiklander return CRYPT_OK;
27578887e60SJens Wiklander }
27678887e60SJens Wiklander
addi(void * a,ltc_mp_digit b,void * c)2775a913ee7SJerome Forissier static int addi(void *a, ltc_mp_digit b, void *c)
27878887e60SJens Wiklander {
27978887e60SJens Wiklander uint32_t b32 = b;
28078887e60SJens Wiklander
28178887e60SJens Wiklander if (b32 != b)
28278887e60SJens Wiklander return CRYPT_INVALID_ARG;
28378887e60SJens Wiklander
28478887e60SJens Wiklander mbedtls_mpi_uint p = b32;
28578887e60SJens Wiklander mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p };
28678887e60SJens Wiklander
28778887e60SJens Wiklander return add(a, &bn, c);
28878887e60SJens Wiklander }
28978887e60SJens Wiklander
29078887e60SJens Wiklander /* sub */
sub(void * a,void * b,void * c)29178887e60SJens Wiklander static int sub(void *a, void *b, void *c)
29278887e60SJens Wiklander {
29378887e60SJens Wiklander if (mbedtls_mpi_sub_mpi(c, a, b))
29478887e60SJens Wiklander return CRYPT_MEM;
29578887e60SJens Wiklander
29678887e60SJens Wiklander return CRYPT_OK;
29778887e60SJens Wiklander }
29878887e60SJens Wiklander
subi(void * a,ltc_mp_digit b,void * c)2995a913ee7SJerome Forissier static int subi(void *a, ltc_mp_digit b, void *c)
30078887e60SJens Wiklander {
30178887e60SJens Wiklander uint32_t b32 = b;
30278887e60SJens Wiklander
30378887e60SJens Wiklander if (b32 != b)
30478887e60SJens Wiklander return CRYPT_INVALID_ARG;
30578887e60SJens Wiklander
30678887e60SJens Wiklander mbedtls_mpi_uint p = b32;
30778887e60SJens Wiklander mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p };
30878887e60SJens Wiklander
30978887e60SJens Wiklander return sub(a, &bn, c);
31078887e60SJens Wiklander }
31178887e60SJens Wiklander
31278887e60SJens Wiklander /* mul */
mul(void * a,void * b,void * c)31378887e60SJens Wiklander static int mul(void *a, void *b, void *c)
31478887e60SJens Wiklander {
31578887e60SJens Wiklander if (mbedtls_mpi_mul_mpi(c, a, b))
31678887e60SJens Wiklander return CRYPT_MEM;
31778887e60SJens Wiklander
31878887e60SJens Wiklander return CRYPT_OK;
31978887e60SJens Wiklander }
32078887e60SJens Wiklander
muli(void * a,ltc_mp_digit b,void * c)3215a913ee7SJerome Forissier static int muli(void *a, ltc_mp_digit b, void *c)
32278887e60SJens Wiklander {
32378887e60SJens Wiklander if (b > (unsigned long) UINT32_MAX)
32478887e60SJens Wiklander return CRYPT_INVALID_ARG;
32578887e60SJens Wiklander
32678887e60SJens Wiklander if (mbedtls_mpi_mul_int(c, a, b))
32778887e60SJens Wiklander return CRYPT_MEM;
32878887e60SJens Wiklander
32978887e60SJens Wiklander return CRYPT_OK;
33078887e60SJens Wiklander }
33178887e60SJens Wiklander
33278887e60SJens Wiklander /* sqr */
sqr(void * a,void * b)33378887e60SJens Wiklander static int sqr(void *a, void *b)
33478887e60SJens Wiklander {
33578887e60SJens Wiklander return mul(a, a, b);
33678887e60SJens Wiklander }
33778887e60SJens Wiklander
33878887e60SJens Wiklander /* div */
divide(void * a,void * b,void * c,void * d)33978887e60SJens Wiklander static int divide(void *a, void *b, void *c, void *d)
34078887e60SJens Wiklander {
34178887e60SJens Wiklander int res = mbedtls_mpi_div_mpi(c, d, a, b);
34278887e60SJens Wiklander
34378887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
34478887e60SJens Wiklander return CRYPT_MEM;
34578887e60SJens Wiklander if (res)
34678887e60SJens Wiklander return CRYPT_ERROR;
34778887e60SJens Wiklander
34878887e60SJens Wiklander return CRYPT_OK;
34978887e60SJens Wiklander }
35078887e60SJens Wiklander
div_2(void * a,void * b)35178887e60SJens Wiklander static int div_2(void *a, void *b)
35278887e60SJens Wiklander {
35378887e60SJens Wiklander if (mbedtls_mpi_copy(b, a))
35478887e60SJens Wiklander return CRYPT_MEM;
35578887e60SJens Wiklander
35678887e60SJens Wiklander if (mbedtls_mpi_shift_r(b, 1))
35778887e60SJens Wiklander return CRYPT_MEM;
35878887e60SJens Wiklander
35978887e60SJens Wiklander return CRYPT_OK;
36078887e60SJens Wiklander }
36178887e60SJens Wiklander
36278887e60SJens Wiklander /* modi */
modi(void * a,ltc_mp_digit b,ltc_mp_digit * c)3635a913ee7SJerome Forissier static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c)
36478887e60SJens Wiklander {
36578887e60SJens Wiklander mbedtls_mpi bn_b;
36678887e60SJens Wiklander mbedtls_mpi bn_c;
36778887e60SJens Wiklander int res = 0;
36878887e60SJens Wiklander
36978887e60SJens Wiklander mbedtls_mpi_init_mempool(&bn_b);
37078887e60SJens Wiklander mbedtls_mpi_init_mempool(&bn_c);
37178887e60SJens Wiklander
37278887e60SJens Wiklander res = set_int(&bn_b, b);
37378887e60SJens Wiklander if (res)
37478887e60SJens Wiklander return res;
37578887e60SJens Wiklander
37678887e60SJens Wiklander res = mbedtls_mpi_mod_mpi(&bn_c, &bn_b, a);
37778887e60SJens Wiklander if (!res)
37878887e60SJens Wiklander *c = get_int(&bn_c);
37978887e60SJens Wiklander
38078887e60SJens Wiklander mbedtls_mpi_free(&bn_b);
38178887e60SJens Wiklander mbedtls_mpi_free(&bn_c);
38278887e60SJens Wiklander
38378887e60SJens Wiklander if (res)
38478887e60SJens Wiklander return CRYPT_MEM;
38578887e60SJens Wiklander
38678887e60SJens Wiklander return CRYPT_OK;
38778887e60SJens Wiklander }
38878887e60SJens Wiklander
38978887e60SJens Wiklander /* gcd */
gcd(void * a,void * b,void * c)39078887e60SJens Wiklander static int gcd(void *a, void *b, void *c)
39178887e60SJens Wiklander {
39278887e60SJens Wiklander if (mbedtls_mpi_gcd(c, a, b))
39378887e60SJens Wiklander return CRYPT_MEM;
39478887e60SJens Wiklander
39578887e60SJens Wiklander return CRYPT_OK;
39678887e60SJens Wiklander }
39778887e60SJens Wiklander
39878887e60SJens Wiklander /* lcm */
lcm(void * a,void * b,void * c)39978887e60SJens Wiklander static int lcm(void *a, void *b, void *c)
40078887e60SJens Wiklander {
40178887e60SJens Wiklander int res = CRYPT_MEM;
40278887e60SJens Wiklander mbedtls_mpi tmp;
40378887e60SJens Wiklander
40478887e60SJens Wiklander mbedtls_mpi_init_mempool(&tmp);
40578887e60SJens Wiklander if (mbedtls_mpi_mul_mpi(&tmp, a, b))
40678887e60SJens Wiklander goto out;
40778887e60SJens Wiklander
40878887e60SJens Wiklander if (mbedtls_mpi_gcd(c, a, b))
40978887e60SJens Wiklander goto out;
41078887e60SJens Wiklander
41178887e60SJens Wiklander /* We use the following equality: gcd(a, b) * lcm(a, b) = a * b */
41278887e60SJens Wiklander res = divide(&tmp, c, c, NULL);
41378887e60SJens Wiklander out:
41478887e60SJens Wiklander mbedtls_mpi_free(&tmp);
41578887e60SJens Wiklander return res;
41678887e60SJens Wiklander }
41778887e60SJens Wiklander
mod(void * a,void * b,void * c)41878887e60SJens Wiklander static int mod(void *a, void *b, void *c)
41978887e60SJens Wiklander {
42078887e60SJens Wiklander int res = mbedtls_mpi_mod_mpi(c, a, b);
42178887e60SJens Wiklander
42278887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
42378887e60SJens Wiklander return CRYPT_MEM;
42478887e60SJens Wiklander if (res)
42578887e60SJens Wiklander return CRYPT_ERROR;
42678887e60SJens Wiklander
42778887e60SJens Wiklander return CRYPT_OK;
42878887e60SJens Wiklander }
42978887e60SJens Wiklander
addmod(void * a,void * b,void * c,void * d)430d8ab8de7SJerome Forissier static int addmod(void *a, void *b, void *c, void *d)
431d8ab8de7SJerome Forissier {
432d8ab8de7SJerome Forissier int res = add(a, b, d);
433d8ab8de7SJerome Forissier
434d8ab8de7SJerome Forissier if (res)
435d8ab8de7SJerome Forissier return res;
436d8ab8de7SJerome Forissier
437d8ab8de7SJerome Forissier return mod(d, c, d);
438d8ab8de7SJerome Forissier }
439d8ab8de7SJerome Forissier
submod(void * a,void * b,void * c,void * d)440d8ab8de7SJerome Forissier static int submod(void *a, void *b, void *c, void *d)
441d8ab8de7SJerome Forissier {
442d8ab8de7SJerome Forissier int res = sub(a, b, d);
443d8ab8de7SJerome Forissier
444d8ab8de7SJerome Forissier if (res)
445d8ab8de7SJerome Forissier return res;
446d8ab8de7SJerome Forissier
447d8ab8de7SJerome Forissier return mod(d, c, d);
448d8ab8de7SJerome Forissier }
449d8ab8de7SJerome Forissier
mulmod(void * a,void * b,void * c,void * d)45078887e60SJens Wiklander static int mulmod(void *a, void *b, void *c, void *d)
45178887e60SJens Wiklander {
45278887e60SJens Wiklander int res;
45378887e60SJens Wiklander mbedtls_mpi ta;
45478887e60SJens Wiklander mbedtls_mpi tb;
45578887e60SJens Wiklander
45678887e60SJens Wiklander mbedtls_mpi_init_mempool(&ta);
45778887e60SJens Wiklander mbedtls_mpi_init_mempool(&tb);
45878887e60SJens Wiklander
45978887e60SJens Wiklander res = mod(a, c, &ta);
46078887e60SJens Wiklander if (res)
46178887e60SJens Wiklander goto out;
46278887e60SJens Wiklander res = mod(b, c, &tb);
46378887e60SJens Wiklander if (res)
46478887e60SJens Wiklander goto out;
46578887e60SJens Wiklander res = mul(&ta, &tb, d);
46678887e60SJens Wiklander if (res)
46778887e60SJens Wiklander goto out;
46878887e60SJens Wiklander res = mod(d, c, d);
46978887e60SJens Wiklander out:
47078887e60SJens Wiklander mbedtls_mpi_free(&ta);
47178887e60SJens Wiklander mbedtls_mpi_free(&tb);
47278887e60SJens Wiklander return res;
47378887e60SJens Wiklander }
47478887e60SJens Wiklander
sqrmod(void * a,void * b,void * c)47578887e60SJens Wiklander static int sqrmod(void *a, void *b, void *c)
47678887e60SJens Wiklander {
47778887e60SJens Wiklander return mulmod(a, a, b, c);
47878887e60SJens Wiklander }
47978887e60SJens Wiklander
48078887e60SJens Wiklander /* invmod */
invmod(void * a,void * b,void * c)48178887e60SJens Wiklander static int invmod(void *a, void *b, void *c)
48278887e60SJens Wiklander {
48378887e60SJens Wiklander int res = mbedtls_mpi_inv_mod(c, a, b);
48478887e60SJens Wiklander
48578887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
48678887e60SJens Wiklander return CRYPT_MEM;
48778887e60SJens Wiklander if (res)
48878887e60SJens Wiklander return CRYPT_ERROR;
48978887e60SJens Wiklander
49078887e60SJens Wiklander return CRYPT_OK;
49178887e60SJens Wiklander }
49278887e60SJens Wiklander
49378887e60SJens Wiklander
49478887e60SJens Wiklander /* setup */
montgomery_setup(void * a,void ** b)49578887e60SJens Wiklander static int montgomery_setup(void *a, void **b)
49678887e60SJens Wiklander {
497c225295bSJens Wiklander *b = mempool_alloc(mbedtls_mpi_mempool, sizeof(mbedtls_mpi_uint));
49878887e60SJens Wiklander if (!*b)
49978887e60SJens Wiklander return CRYPT_MEM;
50078887e60SJens Wiklander
50178887e60SJens Wiklander mbedtls_mpi_montg_init(*b, a);
50278887e60SJens Wiklander
50378887e60SJens Wiklander return CRYPT_OK;
50478887e60SJens Wiklander }
50578887e60SJens Wiklander
50678887e60SJens Wiklander /* get normalization value */
montgomery_normalization(void * a,void * b)50778887e60SJens Wiklander static int montgomery_normalization(void *a, void *b)
50878887e60SJens Wiklander {
50978887e60SJens Wiklander size_t c = ROUNDUP(mbedtls_mpi_size(b), sizeof(mbedtls_mpi_uint)) * 8;
51078887e60SJens Wiklander
51178887e60SJens Wiklander if (mbedtls_mpi_lset(a, 1))
51278887e60SJens Wiklander return CRYPT_MEM;
51378887e60SJens Wiklander if (mbedtls_mpi_shift_l(a, c))
51478887e60SJens Wiklander return CRYPT_MEM;
51578887e60SJens Wiklander if (mbedtls_mpi_mod_mpi(a, a, b))
51678887e60SJens Wiklander return CRYPT_MEM;
51778887e60SJens Wiklander
51878887e60SJens Wiklander return CRYPT_OK;
51978887e60SJens Wiklander }
52078887e60SJens Wiklander
52178887e60SJens Wiklander /* reduce */
montgomery_reduce(void * a,void * b,void * c)52278887e60SJens Wiklander static int montgomery_reduce(void *a, void *b, void *c)
52378887e60SJens Wiklander {
52478887e60SJens Wiklander mbedtls_mpi A;
52578887e60SJens Wiklander mbedtls_mpi *N = b;
52678887e60SJens Wiklander mbedtls_mpi_uint *mm = c;
52778887e60SJens Wiklander mbedtls_mpi T;
52878887e60SJens Wiklander int ret = CRYPT_MEM;
52978887e60SJens Wiklander
53078887e60SJens Wiklander mbedtls_mpi_init_mempool(&T);
53178887e60SJens Wiklander mbedtls_mpi_init_mempool(&A);
53278887e60SJens Wiklander
53378887e60SJens Wiklander if (mbedtls_mpi_grow(&T, (N->n + 1) * 2))
53478887e60SJens Wiklander goto out;
53578887e60SJens Wiklander
53678887e60SJens Wiklander if (mbedtls_mpi_cmp_mpi(a, N) > 0) {
53778887e60SJens Wiklander if (mbedtls_mpi_mod_mpi(&A, a, N))
53878887e60SJens Wiklander goto out;
53978887e60SJens Wiklander } else {
54078887e60SJens Wiklander if (mbedtls_mpi_copy(&A, a))
54178887e60SJens Wiklander goto out;
54278887e60SJens Wiklander }
54378887e60SJens Wiklander
54478887e60SJens Wiklander if (mbedtls_mpi_grow(&A, N->n + 1))
54578887e60SJens Wiklander goto out;
54678887e60SJens Wiklander
5477901324dSJerome Forissier mbedtls_mpi_montred(&A, N, *mm, &T);
54878887e60SJens Wiklander
54978887e60SJens Wiklander if (mbedtls_mpi_copy(a, &A))
55078887e60SJens Wiklander goto out;
55178887e60SJens Wiklander
55278887e60SJens Wiklander ret = CRYPT_OK;
55378887e60SJens Wiklander out:
55478887e60SJens Wiklander mbedtls_mpi_free(&A);
55578887e60SJens Wiklander mbedtls_mpi_free(&T);
55678887e60SJens Wiklander
55778887e60SJens Wiklander return ret;
55878887e60SJens Wiklander }
55978887e60SJens Wiklander
56078887e60SJens Wiklander /* clean up */
montgomery_deinit(void * a)56178887e60SJens Wiklander static void montgomery_deinit(void *a)
56278887e60SJens Wiklander {
563c225295bSJens Wiklander mempool_free(mbedtls_mpi_mempool, a);
56478887e60SJens Wiklander }
56578887e60SJens Wiklander
56678887e60SJens Wiklander /*
56778887e60SJens Wiklander * This function calculates:
56878887e60SJens Wiklander * d = a^b mod c
56978887e60SJens Wiklander *
57078887e60SJens Wiklander * @a: base
57178887e60SJens Wiklander * @b: exponent
57278887e60SJens Wiklander * @c: modulus
57378887e60SJens Wiklander * @d: destination
57478887e60SJens Wiklander */
exptmod(void * a,void * b,void * c,void * d)57578887e60SJens Wiklander static int exptmod(void *a, void *b, void *c, void *d)
57678887e60SJens Wiklander {
57778887e60SJens Wiklander int res;
57878887e60SJens Wiklander
57978887e60SJens Wiklander if (d == a || d == b || d == c) {
58078887e60SJens Wiklander mbedtls_mpi dest;
58178887e60SJens Wiklander
58278887e60SJens Wiklander mbedtls_mpi_init_mempool(&dest);
58378887e60SJens Wiklander res = mbedtls_mpi_exp_mod(&dest, a, b, c, NULL);
58478887e60SJens Wiklander if (!res)
58578887e60SJens Wiklander res = mbedtls_mpi_copy(d, &dest);
58678887e60SJens Wiklander mbedtls_mpi_free(&dest);
58778887e60SJens Wiklander } else {
58878887e60SJens Wiklander res = mbedtls_mpi_exp_mod(d, a, b, c, NULL);
58978887e60SJens Wiklander }
59078887e60SJens Wiklander
59178887e60SJens Wiklander if (res)
59278887e60SJens Wiklander return CRYPT_MEM;
59378887e60SJens Wiklander else
59478887e60SJens Wiklander return CRYPT_OK;
59578887e60SJens Wiklander }
59678887e60SJens Wiklander
rng_read(void * ignored __unused,unsigned char * buf,size_t blen)59778887e60SJens Wiklander static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen)
59878887e60SJens Wiklander {
59978887e60SJens Wiklander if (crypto_rng_read(buf, blen))
60078887e60SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
60178887e60SJens Wiklander return 0;
60278887e60SJens Wiklander }
60378887e60SJens Wiklander
isprime(void * a,int b,int * c)60432b31808SJens Wiklander static int isprime(void *a, int b, int *c)
60578887e60SJens Wiklander {
60632b31808SJens Wiklander int res = mbedtls_mpi_is_prime_ext(a, b, rng_read, NULL);
60778887e60SJens Wiklander
60878887e60SJens Wiklander if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED)
60978887e60SJens Wiklander return CRYPT_MEM;
61078887e60SJens Wiklander
61178887e60SJens Wiklander if (res)
61278887e60SJens Wiklander *c = LTC_MP_NO;
61378887e60SJens Wiklander else
61478887e60SJens Wiklander *c = LTC_MP_YES;
61578887e60SJens Wiklander
61678887e60SJens Wiklander return CRYPT_OK;
61778887e60SJens Wiklander }
61878887e60SJens Wiklander
mpi_rand(void * a,int size)6197fb525f1SJerome Forissier static int mpi_rand(void *a, int size)
62078887e60SJens Wiklander {
62178887e60SJens Wiklander if (mbedtls_mpi_fill_random(a, size, rng_read, NULL))
62278887e60SJens Wiklander return CRYPT_MEM;
62378887e60SJens Wiklander
62478887e60SJens Wiklander return CRYPT_OK;
62578887e60SJens Wiklander }
62678887e60SJens Wiklander
62778887e60SJens Wiklander ltc_math_descriptor ltc_mp = {
62878887e60SJens Wiklander .name = "MPI",
62978887e60SJens Wiklander .bits_per_digit = sizeof(mbedtls_mpi_uint) * 8,
63078887e60SJens Wiklander
63155b5758dSJerome Forissier .init = init,
63255b5758dSJerome Forissier .init_size = init_size,
63355b5758dSJerome Forissier .init_copy = init_copy,
63455b5758dSJerome Forissier .deinit = deinit,
63578887e60SJens Wiklander
63655b5758dSJerome Forissier .neg = neg,
63755b5758dSJerome Forissier .copy = copy,
63878887e60SJens Wiklander
63955b5758dSJerome Forissier .set_int = set_int,
64055b5758dSJerome Forissier .get_int = get_int,
64155b5758dSJerome Forissier .get_digit = get_digit,
64255b5758dSJerome Forissier .get_digit_count = get_digit_count,
64355b5758dSJerome Forissier .compare = compare,
64455b5758dSJerome Forissier .compare_d = compare_d,
64555b5758dSJerome Forissier .count_bits = count_bits,
64655b5758dSJerome Forissier .count_lsb_bits = count_lsb_bits,
64755b5758dSJerome Forissier .twoexpt = twoexpt,
64878887e60SJens Wiklander
64955b5758dSJerome Forissier .read_radix = read_radix,
65055b5758dSJerome Forissier .write_radix = write_radix,
65155b5758dSJerome Forissier .unsigned_size = unsigned_size,
65255b5758dSJerome Forissier .unsigned_write = unsigned_write,
65355b5758dSJerome Forissier .unsigned_read = unsigned_read,
65478887e60SJens Wiklander
65555b5758dSJerome Forissier .add = add,
65655b5758dSJerome Forissier .addi = addi,
65755b5758dSJerome Forissier .sub = sub,
65855b5758dSJerome Forissier .subi = subi,
65955b5758dSJerome Forissier .mul = mul,
66055b5758dSJerome Forissier .muli = muli,
66155b5758dSJerome Forissier .sqr = sqr,
66255b5758dSJerome Forissier .mpdiv = divide,
66355b5758dSJerome Forissier .div_2 = div_2,
66455b5758dSJerome Forissier .modi = modi,
66555b5758dSJerome Forissier .gcd = gcd,
66655b5758dSJerome Forissier .lcm = lcm,
66778887e60SJens Wiklander
66855b5758dSJerome Forissier .mulmod = mulmod,
66955b5758dSJerome Forissier .sqrmod = sqrmod,
67055b5758dSJerome Forissier .invmod = invmod,
67178887e60SJens Wiklander
67255b5758dSJerome Forissier .montgomery_setup = montgomery_setup,
67355b5758dSJerome Forissier .montgomery_normalization = montgomery_normalization,
67455b5758dSJerome Forissier .montgomery_reduce = montgomery_reduce,
67555b5758dSJerome Forissier .montgomery_deinit = montgomery_deinit,
67678887e60SJens Wiklander
67755b5758dSJerome Forissier .exptmod = exptmod,
67855b5758dSJerome Forissier .isprime = isprime,
67978887e60SJens Wiklander
68078887e60SJens Wiklander #ifdef LTC_MECC
68178887e60SJens Wiklander #ifdef LTC_MECC_FP
68255b5758dSJerome Forissier .ecc_ptmul = ltc_ecc_fp_mulmod,
68378887e60SJens Wiklander #else
68455b5758dSJerome Forissier .ecc_ptmul = ltc_ecc_mulmod,
68578887e60SJens Wiklander #endif /* LTC_MECC_FP */
68655b5758dSJerome Forissier .ecc_ptadd = ltc_ecc_projective_add_point,
68755b5758dSJerome Forissier .ecc_ptdbl = ltc_ecc_projective_dbl_point,
68855b5758dSJerome Forissier .ecc_map = ltc_ecc_map,
68978887e60SJens Wiklander #ifdef LTC_ECC_SHAMIR
69078887e60SJens Wiklander #ifdef LTC_MECC_FP
69155b5758dSJerome Forissier .ecc_mul2add = ltc_ecc_fp_mul2add,
69278887e60SJens Wiklander #else
69355b5758dSJerome Forissier .ecc_mul2add = ltc_ecc_mul2add,
69478887e60SJens Wiklander #endif /* LTC_MECC_FP */
69578887e60SJens Wiklander #endif /* LTC_ECC_SHAMIR */
69678887e60SJens Wiklander #endif /* LTC_MECC */
69778887e60SJens Wiklander
69878887e60SJens Wiklander #ifdef LTC_MRSA
69955b5758dSJerome Forissier .rsa_keygen = rsa_make_key,
70055b5758dSJerome Forissier .rsa_me = rsa_exptmod,
70178887e60SJens Wiklander #endif
702d8ab8de7SJerome Forissier .addmod = addmod,
703d8ab8de7SJerome Forissier .submod = submod,
70455b5758dSJerome Forissier .rand = mpi_rand,
70578887e60SJens Wiklander
70678887e60SJens Wiklander };
70778887e60SJens Wiklander
crypto_bignum_num_bytes(struct bignum * a)70878887e60SJens Wiklander size_t crypto_bignum_num_bytes(struct bignum *a)
70978887e60SJens Wiklander {
71078887e60SJens Wiklander return mbedtls_mpi_size((mbedtls_mpi *)a);
71178887e60SJens Wiklander }
71278887e60SJens Wiklander
crypto_bignum_num_bits(struct bignum * a)71378887e60SJens Wiklander size_t crypto_bignum_num_bits(struct bignum *a)
71478887e60SJens Wiklander {
71578887e60SJens Wiklander return mbedtls_mpi_bitlen((mbedtls_mpi *)a);
71678887e60SJens Wiklander }
71778887e60SJens Wiklander
crypto_bignum_compare(struct bignum * a,struct bignum * b)71878887e60SJens Wiklander int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b)
71978887e60SJens Wiklander {
72078887e60SJens Wiklander return mbedtls_mpi_cmp_mpi((mbedtls_mpi *)a, (mbedtls_mpi *)b);
72178887e60SJens Wiklander }
72278887e60SJens Wiklander
crypto_bignum_bn2bin(const struct bignum * from,uint8_t * to)72378887e60SJens Wiklander void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to)
72478887e60SJens Wiklander {
725e1b46449SJens Wiklander const mbedtls_mpi *f = (const mbedtls_mpi *)from;
726e1b46449SJens Wiklander int rc __maybe_unused = 0;
727e1b46449SJens Wiklander
728e1b46449SJens Wiklander rc = mbedtls_mpi_write_binary(f, (void *)to, mbedtls_mpi_size(f));
729e1b46449SJens Wiklander assert(!rc);
73078887e60SJens Wiklander }
73178887e60SJens Wiklander
crypto_bignum_bin2bn(const uint8_t * from,size_t fromsize,struct bignum * to)73278887e60SJens Wiklander TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize,
73378887e60SJens Wiklander struct bignum *to)
73478887e60SJens Wiklander {
73578887e60SJens Wiklander if (mbedtls_mpi_read_binary((mbedtls_mpi *)to, (const void *)from,
73678887e60SJens Wiklander fromsize))
73778887e60SJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
73878887e60SJens Wiklander return TEE_SUCCESS;
73978887e60SJens Wiklander }
74078887e60SJens Wiklander
crypto_bignum_copy(struct bignum * to,const struct bignum * from)74178887e60SJens Wiklander void crypto_bignum_copy(struct bignum *to, const struct bignum *from)
74278887e60SJens Wiklander {
743ab2e0039SJens Wiklander int rc __maybe_unused = 0;
744ab2e0039SJens Wiklander
745ab2e0039SJens Wiklander rc = mbedtls_mpi_copy((mbedtls_mpi *)to, (const mbedtls_mpi *)from);
746ab2e0039SJens Wiklander assert(!rc);
74778887e60SJens Wiklander }
74878887e60SJens Wiklander
crypto_bignum_allocate(size_t size_bits)7494b5c81ccSJens Wiklander struct bignum *crypto_bignum_allocate(size_t size_bits)
75078887e60SJens Wiklander {
75178887e60SJens Wiklander mbedtls_mpi *bn = malloc(sizeof(*bn));
75278887e60SJens Wiklander
7534b5c81ccSJens Wiklander if (!bn)
7544b5c81ccSJens Wiklander return NULL;
7554b5c81ccSJens Wiklander
75678887e60SJens Wiklander mbedtls_mpi_init(bn);
7574b5c81ccSJens Wiklander if (mbedtls_mpi_grow(bn, BITS_TO_LIMBS(size_bits))) {
7584b5c81ccSJens Wiklander free(bn);
7594b5c81ccSJens Wiklander return NULL;
7604b5c81ccSJens Wiklander }
76178887e60SJens Wiklander
76278887e60SJens Wiklander return (struct bignum *)bn;
76378887e60SJens Wiklander }
76478887e60SJens Wiklander
crypto_bignum_free(struct bignum ** s)765e2ec831cSJihwan Park void crypto_bignum_free(struct bignum **s)
76678887e60SJens Wiklander {
767e2ec831cSJihwan Park assert(s);
768e2ec831cSJihwan Park
769e2ec831cSJihwan Park mbedtls_mpi_free((mbedtls_mpi *)*s);
770e2ec831cSJihwan Park free(*s);
771e2ec831cSJihwan Park *s = NULL;
77278887e60SJens Wiklander }
77378887e60SJens Wiklander
crypto_bignum_clear(struct bignum * s)77478887e60SJens Wiklander void crypto_bignum_clear(struct bignum *s)
77578887e60SJens Wiklander {
77678887e60SJens Wiklander mbedtls_mpi *bn = (mbedtls_mpi *)s;
77778887e60SJens Wiklander
77878887e60SJens Wiklander bn->s = 1;
77978887e60SJens Wiklander if (bn->p)
78078887e60SJens Wiklander memset(bn->p, 0, sizeof(*bn->p) * bn->n);
78178887e60SJens Wiklander }
782