summaryrefslogtreecommitdiff
path: root/lib/libutee/tee_api_arith.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutee/tee_api_arith.c')
-rw-r--r--lib/libutee/tee_api_arith.c606
1 files changed, 606 insertions, 0 deletions
diff --git a/lib/libutee/tee_api_arith.c b/lib/libutee/tee_api_arith.c
new file mode 100644
index 0000000..9a3cd75
--- /dev/null
+++ b/lib/libutee/tee_api_arith.c
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <tee_api.h>
+#include <tee_arith_internal.h>
+#include <mpalib.h>
+
+/*
+ * The mem pool.
+ * We have a pool of scratch memory for internal usage.
+ * The variables in the pool are twice the size of the max allowed
+ * size from the TA. This is to coop with modulare multiplication.
+ */
+
+#define MPA_INTERNAL_MEM_POOL_SIZE 12
+
+/*
+ * THIS IS THE MAXIMUM NUMBER OF BITS THAT THE LIBRARY SUPPORTS.
+ * It defines the size of the scratch memory pool for the underlying
+ * mpa library.
+ */
+#define TEE_MAX_NUMBER_OF_SUPPORTED_BITS 2048
+
+static uint32_t mempool_u32[mpa_scratch_mem_size_in_U32(
+ MPA_INTERNAL_MEM_POOL_SIZE,
+ TEE_MAX_NUMBER_OF_SUPPORTED_BITS)];
+static mpa_scratch_mem mempool = (void *)mempool_u32;
+
+/*************************************************************
+ * PANIC
+ *************************************************************/
+
+/*
+ * TEE_BigInt_Panic
+ *
+ * This is a temporary solution for testing the TEE_BigInt lib
+ */
+static void __attribute__ ((noreturn)) TEE_BigInt_Panic(const char *msg)
+{
+ printf("PANIC: %s\n", msg);
+ TEE_Panic(0xB16127 /*BIGINT*/);
+ while (1)
+ ; /* Panic will crash the thread */
+}
+
+/*************************************************************
+ * INITIALIZATION FUNCTIONS
+ *************************************************************/
+
+/*
+ * _TEE_MathAPI_Init
+ */
+void _TEE_MathAPI_Init(void)
+{
+ mpa_init_scratch_mem(mempool, sizeof(mempool_u32),
+ TEE_MAX_NUMBER_OF_SUPPORTED_BITS);
+ mpa_set_random_generator(get_rng_array);
+}
+
+/*
+ * TEE_BigIntInit
+ */
+void TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len)
+{
+ mpa_init_static((mpa_num_base *)bigInt, (uint32_t)len);
+}
+
+/*
+ * TEE_BigIntInitFMM
+ */
+void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len)
+{
+ mpanum op = (mpa_num_base *)bigIntFMM;
+
+ op->alloc = U32_TO_ASIZE(len - MPA_NUMBASE_METADATA_SIZE_IN_U32);
+ op->size = 0;
+}
+
+/*
+ * TEE_BigIntInitFMMContext
+ */
+void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context,
+ uint32_t len, const TEE_BigInt *modulus)
+{
+ mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context;
+ mpanum mpa_modulus = (mpa_num_base *)modulus;
+
+ mpa_init_static_fmm_context(mpa_context, (uint32_t)len);
+ mpa_compute_fmm_context(mpa_modulus, mpa_context->r_ptr,
+ mpa_context->r2_ptr, &mpa_context->n_inv,
+ mempool);
+}
+
+/*************************************************************
+ * MEMORY ALLOCATION AND SIZE
+ *************************************************************/
+
+/*
+ * TEE_BigIntFMMSizeInU32
+ */
+uint32_t TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits)
+{
+ return TEE_BigIntSizeInU32(modulusSizeInBits) + 1;
+}
+
+/*
+ * TEE_BigIntFMMContextSizeInU32
+ */
+uint32_t TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits)
+{
+ return mpa_fmm_context_size_in_U32(modulusSizeInBits);
+}
+
+/*************************************************************
+ * CONVERSION FUNCTIONS
+ *************************************************************/
+
+/*
+ * TEE_BigIntConvertFromOctetString
+ */
+TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest,
+ const uint8_t *buffer,
+ uint32_t bufferLen,
+ int32_t sign)
+{
+ TEE_Result res;
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ bool negative = sign < 0;
+
+ if (mpa_set_oct_str(mpa_dest, buffer, bufferLen, negative) != 0)
+ res = TEE_ERROR_OVERFLOW;
+ else
+ res = TEE_SUCCESS;
+
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_OVERFLOW)
+ TEE_Panic(res);
+
+ return res;
+}
+
+/*
+ * TEE_BigIntConvertToOctetString
+ */
+TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer,
+ uint32_t *bufferLen,
+ const TEE_BigInt *bigInt)
+{
+ mpanum n = (mpa_num_base *)bigInt;
+ size_t size = *bufferLen;
+ TEE_Result res;
+
+ if (mpa_get_oct_str(buffer, &size, n) != 0)
+ res = TEE_ERROR_SHORT_BUFFER;
+ else
+ res = TEE_SUCCESS;
+
+ *bufferLen = size;
+
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_SHORT_BUFFER)
+ TEE_Panic(res);
+
+ return res;
+}
+
+/*
+ * TEE_BigIntConvertFromS32
+ */
+void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+
+#if (MPA_WORD_SIZE == 32)
+ mpa_set_S32(mpa_dest, shortVal);
+#else
+#error "Write code for digit size != 32"
+#endif
+}
+
+/*
+ * TEE_BigIntConvertToS32
+ */
+TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src)
+{
+ TEE_Result res;
+ mpanum mpa_src = (mpa_num_base *)src;
+
+ if (mpa_get_S32(dest, mpa_src) == 0)
+ res = TEE_SUCCESS;
+ else
+ res = TEE_ERROR_OVERFLOW;
+
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_OVERFLOW)
+ TEE_Panic(res);
+
+ return res;
+}
+
+/*************************************************************
+ * LOGICAL OPERATIONS
+ *************************************************************/
+
+/*
+ * TEE_BigIntCmp
+ */
+int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2)
+{
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ return mpa_cmp(mpa_op1, mpa_op2);
+}
+
+/*
+ * TEE_BigIntCmpS32
+ */
+int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal)
+{
+ mpanum mpa_op = (mpa_num_base *)op;
+
+ return mpa_cmp_short(mpa_op, shortVal);
+}
+
+/*
+ * TEE_BigIntShiftRight
+ */
+void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op,
+ size_t bits)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op = (mpa_num_base *)op;
+
+ mpa_shift_right(mpa_dest, mpa_op, (mpa_asize_t) bits);
+}
+
+/*
+ * TEE_BigIntGetBit
+ */
+bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex)
+{
+ mpanum mpa_src = (mpa_num_base *)src;
+
+ return mpa_get_bit(mpa_src, bitIndex);
+}
+
+/*
+ * TEE_BigIntGetBitCount
+ */
+uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src)
+{
+ mpanum mpa_src = (mpa_num_base *)src;
+
+ return mpa_highest_bit_index(mpa_src) + 1;
+}
+
+/*************************************************************
+ * BASIC ARITHMETIC OPERATIONS
+ *************************************************************/
+
+/*
+ * TEE_BigIntAdd
+ */
+void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ mpa_add(mpa_dest, mpa_op1, mpa_op2, mempool);
+}
+
+/*
+ * TEE_BigIntSub
+ */
+void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ mpa_sub(mpa_dest, mpa_op1, mpa_op2, mempool);
+}
+
+/*
+ * TEE_BigIntNeg
+ */
+void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_src = (mpa_num_base *)src;
+
+ mpa_neg(mpa_dest, mpa_src);
+}
+
+/*
+ * TEE_BigIntMul
+ */
+void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ mpa_mul(mpa_dest, mpa_op1, mpa_op2, mempool);
+}
+
+/*
+ * TEE_BigIntSquare
+ */
+void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op = (mpa_num_base *)op;
+
+ mpa_mul(mpa_dest, mpa_op, mpa_op, mempool);
+}
+
+/*
+ * TEE_BigIntDiv
+ */
+void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r,
+ const TEE_BigInt *op1, const TEE_BigInt *op2)
+{
+ mpanum mpa_dest_q = (mpa_num_base *)dest_q;
+ mpanum mpa_dest_r = (mpa_num_base *)dest_r;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ if (TEE_BigIntCmpS32(op2, 0) == 0)
+ TEE_BigInt_Panic("Divisor is zero");
+
+ mpa_div(mpa_dest_q, mpa_dest_r, mpa_op1, mpa_op2, mempool);
+}
+
+/*************************************************************
+ * MODULUS OPERATIONS
+ *************************************************************/
+
+/*
+ * TEE_BigIntMod
+ */
+void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op,
+ const TEE_BigInt *n)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op = (mpa_num_base *)op;
+ mpanum mpa_n = (mpa_num_base *)n;
+
+ if (TEE_BigIntCmpS32(n, 2) < 0)
+ TEE_BigInt_Panic("Modulus is too short");
+
+ mpa_mod(mpa_dest, mpa_op, mpa_n, mempool);
+
+ if (mpa_cmp_short(mpa_dest, 0) < 0)
+ mpa_add(mpa_dest, mpa_dest, mpa_n, mempool);
+}
+
+/*
+ * TEE_BigIntAddMod
+ */
+void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2, const TEE_BigInt *n)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+ mpanum mpa_n = (mpa_num_base *)n;
+
+ if (TEE_BigIntCmpS32(n, 2) < 0)
+ TEE_BigInt_Panic("Modulus is too short");
+
+ mpa_add_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool);
+ if (mpa_cmp_short(mpa_dest, 0) < 0)
+ mpa_add(mpa_dest, mpa_dest, mpa_n, mempool);
+}
+
+/*
+ * TEE_BigIntSubMod
+ */
+void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2, const TEE_BigInt *n)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+ mpanum mpa_n = (mpa_num_base *)n;
+
+ if (TEE_BigIntCmpS32(n, 2) < 0)
+ TEE_BigInt_Panic("Modulus is too short");
+
+ mpa_sub_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool);
+ if (mpa_cmp_short(mpa_dest, 0) < 0)
+ mpa_add(mpa_dest, mpa_dest, mpa_n, mempool);
+}
+
+/*
+ * TEE_BigIntMulMod
+ */
+void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1,
+ const TEE_BigInt *op2, const TEE_BigInt *n)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+ mpanum mpa_n = (mpa_num_base *)n;
+ mpanum tmp_dest;
+
+ if (TEE_BigIntCmpS32(n, 2) < 0)
+ TEE_BigInt_Panic("Modulus is too short");
+
+ /*
+ * From the spec, mpa_dest must be of magnitude "mpa_n"
+ * But internal computations in mpa do not have such assumptions
+ * (as __mpa_div_q_r, where "r" must be of magnitude "op1",
+ * whereas GP provides a magnitude of "op2")
+ * This is a tempory variable is used, before storing the
+ * final result.
+ */
+ mpa_alloc_static_temp_var(&tmp_dest, mempool);
+ mpa_mul_mod(tmp_dest, mpa_op1, mpa_op2, mpa_n, mempool);
+ if (mpa_cmp_short(tmp_dest, 0) < 0)
+ mpa_add(tmp_dest, tmp_dest, mpa_n, mempool);
+ mpa_copy(mpa_dest, tmp_dest);
+ mpa_free_static_temp_var(&tmp_dest, mempool);
+}
+
+/*
+ * TEE_BigIntSquareMod
+ */
+void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op,
+ const TEE_BigInt *n)
+{
+ TEE_BigIntMulMod(dest, op, op, n);
+}
+
+/*
+ * TEE_BigIntInvMod
+ */
+void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op,
+ const TEE_BigInt *n)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op = (mpa_num_base *)op;
+ mpanum mpa_n = (mpa_num_base *)n;
+
+ if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0)
+ TEE_BigInt_Panic("too small modulus or trying to invert zero");
+
+ mpa_inv_mod(mpa_dest, mpa_op, mpa_n, mempool);
+}
+
+/*************************************************************
+ * OTHER ARITHMETIC OPERATIONS
+ *************************************************************/
+
+/*
+ * TEE_BigIntRelativePrime
+ */
+bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2)
+{
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+ mpanum gcd;
+ uint32_t cmp;
+
+ mpa_alloc_static_temp_var(&gcd, mempool);
+
+ mpa_gcd(gcd, mpa_op1, mpa_op2, mempool);
+ cmp = mpa_cmp_short(gcd, 1);
+
+ mpa_free_static_temp_var(&gcd, mempool);
+
+ return cmp == 0 ? true : false;
+}
+
+/*
+ * TEE_BigIntExtendedGcd
+ */
+void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u,
+ TEE_BigInt *v, const TEE_BigInt *op1,
+ const TEE_BigInt *op2)
+{
+ mpanum mpa_gcd_res = (mpa_num_base *)gcd;
+ mpanum mpa_u = (mpa_num_base *)u;
+ mpanum mpa_v = (mpa_num_base *)v;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+
+ mpa_extended_gcd(mpa_gcd_res, mpa_u, mpa_v, mpa_op1, mpa_op2, mempool);
+}
+
+/*
+ * TEE_BigIntIsProbablePrime
+ */
+int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op,
+ uint32_t confidenceLevel)
+{
+ mpanum mpa_op = (mpa_num_base *)op;
+
+ if (confidenceLevel < 80)
+ confidenceLevel = 80;
+
+ if (confidenceLevel > 256)
+ confidenceLevel = 256;
+
+ return mpa_is_prob_prime(mpa_op, confidenceLevel, mempool);
+}
+
+/*************************************************************
+ * FAST MODULAR MULTIPLICATION
+ *************************************************************/
+
+/*
+ * TEE_BigIntConvertToFMM
+ */
+void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest,
+ const TEE_BigInt *src,
+ const TEE_BigInt *n,
+ const TEE_BigIntFMMContext *context)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)src;
+ mpanum mpa_n = (mpa_num_base *)n;
+ mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context;
+
+ /* calculate dest = Mont(src, r2) */
+ mpa_montgomery_mul(mpa_dest, mpa_op1, mpa_context->r2_ptr, mpa_n,
+ mpa_context->n_inv, mempool);
+}
+
+/*
+ * TEE_BigIntConvertFromFMM
+ */
+void TEE_BigIntConvertFromFMM(TEE_BigInt *dest,
+ const TEE_BigIntFMM *src,
+ const TEE_BigInt *n,
+ const TEE_BigIntFMMContext *context)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op2 = (mpa_num_base *)src;
+ mpanum mpa_n = (mpa_num_base *)n;
+ mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context;
+ mpanum temp_dest;
+
+ /*
+ * Since dest in BigIntFFMCompute (i.e. dest in mpa_montgomery_mul)
+ * must have alloc one word more than the size of n, we must
+ * use a temp variable during the conversion.
+ */
+ mpa_alloc_static_temp_var(&temp_dest, mempool);
+
+ /* calculate dest = Mont(1,src) */
+ mpa_montgomery_mul(temp_dest, mpa_constant_one(), mpa_op2, mpa_n,
+ mpa_context->n_inv, mempool);
+
+ mpa_copy(mpa_dest, temp_dest);
+ mpa_free_static_temp_var(&temp_dest, mempool);
+}
+
+/*
+ * TEE_BigIntComputeFMM
+ */
+void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest,
+ const TEE_BigIntFMM *op1,
+ const TEE_BigIntFMM *op2,
+ const TEE_BigInt *n,
+ const TEE_BigIntFMMContext *context)
+{
+ mpanum mpa_dest = (mpa_num_base *)dest;
+ mpanum mpa_op1 = (mpa_num_base *)op1;
+ mpanum mpa_op2 = (mpa_num_base *)op2;
+ mpanum mpa_n = (mpa_num_base *)n;
+ mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context;
+
+ mpa_montgomery_mul(mpa_dest, mpa_op1, mpa_op2, mpa_n,
+ mpa_context->n_inv, mempool);
+}