/** * @file sdrv_crypto_utility.c * @brief crypto utility api * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #include "sdrv_crypto_utility.h" #ifdef PKE_PRINT_BUF void print_buf_U8(uint8_t buf[], uint32_t byteLen, char name[]) { uint32_t i; printf(" %s: \n", name); printf(" addr:0x%x:", (uint32_t)buf); for (i = 0; i < byteLen; i++) { printf("%02x", buf[i]); } printf("\n"); } void print_buf_U32(uint32_t buf[], uint32_t wordLen, char name[]) { uint32_t i; printf(" %s: %08x\n", name, (uint32_t)buf); for (i = 0; i < wordLen; i++) { printf("%08x", buf[i]); } printf("\n"); } void print_BN_buf_U32(uint32_t buf[], uint32_t wordLen, char name[]) { uint32_t i; printf(" %08x %s: \n", (uint32_t)buf, name); for (i = 0; i < wordLen; i++) { printf("%08x", buf[wordLen - 1 - i]); } printf("\n"); } #endif void memcpy_(void *dst, void *src, uint32_t size) { uint8_t *a = (uint8_t *)dst; uint8_t *b = (uint8_t *)src; uint32_t *aa = (uint32_t *)dst; uint32_t *bb = (uint32_t *)src; uint32_t i, count, tmp; if ((((uint32_t)dst) & 3) || (((uint32_t)src) & 3)) { while (size--) { *a++ = *b++; } } else { count = size / 4; for (i = 0; i < count; i++) { *aa++ = *bb++; } tmp = size & 3; if (tmp) { a += (size & (~0x03)); b += (size & (~0x03)); while (tmp--) { *a++ = *b++; } } } } void memset_(void *dst, uint8_t value, uint32_t size) { uint8_t *a = (uint8_t *)dst; uint32_t i, count, tmp; tmp = ((uint32_t)dst) & 3; if (tmp) { if (size > 4 - tmp) { for (i = 0; i < 4 - tmp; i++) { *a++ = value; } size -= (4 - tmp); } else { for (i = 0; i < size; i++) { *a++ = value; } return; } } count = size / 4; if (count) { tmp = value; tmp = (tmp << 8) | value; tmp = (tmp << 8) | value; tmp = (tmp << 8) | value; for (i = 0; i < count; i++) { *((uint32_t *)a) = tmp; a += 4; } } tmp = size & 3; if (tmp) { for (i = 0; i < tmp; i++) { *a++ = value; } } } int8_t memcmp_(void *m1, void *m2, uint32_t size) { int8_t *a = (int8_t *)m1; int8_t *b = (int8_t *)m2; int8_t c; while (size--) { c = (*a++ - *b++); if (c) { return c; } } return 0; } /** * @brief set uint32 buffer * * This function set uint32 buffer * * @param[out] a output word buffer * @param[in] value input word value * @param[in] wordLen word length of buffer a */ void uint32_set(uint32_t *a, uint32_t value, uint32_t wordLen) { while (wordLen) { a[--wordLen] = value; } } /* function: copy uint32 buffer * parameters: * dst ------------------------ output, output word buffer * src ------------------------ input, input word buffer * wordLen -------------------- input, word length of buffer dst or src * return: none * caution: */ void uint32_copy(uint32_t *dst, uint32_t *src, uint32_t wordLen) { uint32_t i; if (dst != src) { for (i = 0; i < wordLen; i++) { dst[i] = src[i]; } } } /* function: clear uint32 buffer * parameters: * a -------------------------- input&output, word buffer a * aWordLen ------------------- input, word length of buffer a * return: none * caution: */ void uint32_clear(uint32_t *a, uint32_t wordLen) { uint32_t i = wordLen; while (i) { a[--i] = 0; } } static void uint32_sleep1(uint32_t count) { uint32_t a = 0; uint32_t b = 0; uint32_t result = 0; uint32_t i; for (i = 0; i < count; i++) { result |= ((a + i) - (b + i)); } } static void uint32_sleep2(uint32_t count) { uint32_t a = 0; uint32_t b = 0; uint32_t result = 0; uint32_t i; for (i = 0; i < count; i++) { result |= ((a + i) ^ (b + i)); } } /* function: sleep for a while * parameters: * count ---------------------- input, count * return: none * caution: */ void uint32_sleep(uint32_t count, uint8_t rand) { uint8_t rand1 = rand & 0x01; if (0 == rand1) { uint32_sleep1(count); } else { uint32_sleep2(count); } } /* function: convert 0x1122334455667788 to 0x4433221188776655 * parameters: * in ------------------------- source address * out ------------------------ destination address * wordLen -------------------- word length of in/out * return: none * caution: */ void uint32_endian_reverse(uint8_t *in, uint8_t *out, uint32_t wordLen) { uint8_t tmp; if (in == out) { while (wordLen > 0) { tmp = *in; *in = *(in + 3); *(in + 3) = tmp; in += 1; tmp = *in; *in = *(in + 1); *(in + 1) = tmp; wordLen--; in += 3; } } else { while (wordLen > 0) { *(out) = *(in + 3); *(out + 1) = *(in + 2); *(out + 2) = *(in + 1); *(out + 3) = *(in); wordLen--; in += 4; out += 4; } } } /* function: reverse word array * parameters: * in ------------------------- input, input buffer * out ------------------------ output, output buffer * wordLen -------------------- input, word length of in or out * return: none * caution: * 1. in and out could point the same buffer */ void reverse_word_array(uint8_t *in, uint32_t *out, uint32_t wordLen) { uint32_t idx, round = wordLen >> 1; uint32_t tmp; uint32_t *p_in; if (((uint32_t)(in)) & 3) { memcpy_(out, in, wordLen << 2); p_in = out; } else { p_in = (uint32_t *)in; } for (idx = 0; idx < round; idx++) { tmp = p_in[idx]; out[idx] = p_in[wordLen - 1 - idx]; out[wordLen - 1 - idx] = tmp; } if ((wordLen & 0x1) && (p_in != out)) { out[round] = p_in[round]; } } /* function: reverse byte array * parameters: * in ------------------------- input, input buffer * out ------------------------ output, output buffer * byteLen -------------------- input, byte length of in or out * return: none * caution: * 1. in and out could point the same buffer */ void reverse_byte_array(uint8_t *in, uint8_t *out, uint32_t byteLen) { uint32_t idx, round = byteLen >> 1; uint8_t tmp; for (idx = 0; idx < round; idx++) { tmp = in[idx]; out[idx] = in[byteLen - 1 - idx]; out[byteLen - 1 - idx] = tmp; } if ((byteLen & 0x1) && (in != out)) { out[round] = in[round]; } } /* function: C = A XOR B * parameters: * A -------------------------- input, byte buffer a * B -------------------------- input, byte buffer b * C -------------------------- output, C = A XOR B * byteLen -------------------- input, byte length of A,B,C * return: none * caution: */ void uint8_xor(uint8_t *a, uint8_t *b, uint8_t *c, uint32_t byteLen) { uint32_t i; for (i = 0; i < byteLen; i++) { c[i] = a[i] ^ b[i]; } } /* function: get real bit length of big number a of wordLen words */ uint32_t get_valid_bits(const uint32_t *a, uint32_t wordLen) { uint32_t i = 0; uint32_t j = 0; if (0 == wordLen) { return 0; } for (i = wordLen; i > 0; i--) { if (a[i - 1]) { break; } } if (0 == i) { return 0; } for (j = 32; j > 0; j--) { if (a[i - 1] & (((uint32_t)0x1) << (j - 1))) { break; } } return ((i - 1) << 5) + j; } /* function: get real word lenth of big number a of max_words words * parameters: * a -------------------------- input, big integer a * max_words ------------------ input, max word length of a * return: real word lenth of big number a * caution: */ uint32_t get_valid_words(uint32_t *a, uint32_t max_words) { uint32_t i; for (i = max_words; i > 0; i--) { if (a[i - 1]) { return i; } } return 0; } /* function: check whether big number or uint8_t buffer a is all zero or not * parameters: * a -------------------------- input, byte buffer a * aByteLen ------------------- input, byte length of a * return: 0(a is not zero),1(a is all zero) * caution: */ uint8_t uint8_bignum_check_zero(uint8_t a[], uint32_t aByteLen) { uint32_t i; for (i = 0; i < aByteLen; i++) { if (a[i]) { return 0; } } return 1; } /* function: check whether big number or uint32_t buffer a is all zero or not * parameters: * a -------------------------- input, big integer or word buffer a * aWordLen ------------------- input, word length of a * return: 0(a is not zero), 1(a is all zero) * caution: */ uint8_t uint32_bignum_check_zero(uint32_t a[], uint32_t aWordLen) { uint32_t i; for (i = 0; i < aWordLen; i++) { if (a[i]) { return 0; } } return 1; } /* function: compare big integer a and b * parameters: * a -------------------------- input, big integer a * aWordLen ------------------- input, word length of a * b -------------------------- input, big integer b * bWordLen ------------------- input, word length of b * return: * 0:a=b, 1:a>b, -1: a bWordLen) { return 1; } if (aWordLen < bWordLen) { return -1; } for (i = (aWordLen - 1); i >= 0; i--) { if (a[i] > b[i]) { return 1; } if (a[i] < b[i]) { return -1; } } return 0; } /* function: securely compare big integer a and b * parameters: * a -------------------------- input, big integer a * b -------------------------- input, big integer b * wordLen -------------------- input, word length of a and b * return: 0(a=b), other(a!=b) * caution: */ static uint32_t uint32_sec_cmp1(uint32_t *a, uint32_t *b, uint32_t wordLen) { uint32_t i, result; result = 0; for (i = 0; i < wordLen; i++) { result |= (a[i] - b[i]); } return result; } /* function: securely compare big integer a and b * parameters: * a -------------------------- input, big integer a * b -------------------------- input, big integer b * wordLen -------------------- input, word length of a and b * return: 0(a=b), other(a!=b) * caution: */ static uint32_t uint32_sec_cmp2(uint32_t *a, uint32_t *b, uint32_t wordLen) { uint32_t i, result; result = 0; for (i = 0; i < wordLen; i++) { result |= (a[i] ^ b[i]); } return result; } /* function: securely compare big integer a and b * parameters: * a -------------------------- input, big integer a * b -------------------------- input, big integer b * wordLen -------------------- input, word length of a and b * return: 0(a=b), other(a!=b) * caution: */ uint32_t uint32_sec_cmp(uint32_t *a, uint32_t *b, uint32_t wordLen, uint8_t rand) { uint8_t rand1 = rand & 0x01; if (0 == rand1) { return uint32_sec_cmp1(a, b, wordLen); } else { return uint32_sec_cmp2(a, b, wordLen); } } /* function: for a = b*2^t, b is odd, get t * parameters: * a -------------------------- big integer a * return: * number of multiple by 2, for a * caution: * 1. make sure a != 0 */ uint32_t get_multiple2_number(uint32_t a[]) { uint32_t t, i = 0, j = 0; while (0 == (a[i])) { i++; } t = a[i]; while (!(t & 1)) { j++; t >>= 1; } return (i << 5) + j; } /* function: a = a/(2^n) * parameters: * a -------------------------- big integer a * aWordLen ------------------- word length of a * n -------------------------- exponent of 2^n * return: * word length of a = a/(2^n) * caution: * 1. make sure aWordLen is real word length of a * 2. a may be 0, then aWordLen is 0, to make sure aWordLen-1 is available, * so data type of aWordLen is int32_t, not uint32_t */ uint32_t big_div2n(uint32_t a[], int32_t aWordLen, uint32_t n) { int32_t i; uint32_t j; aWordLen = get_valid_words(a, aWordLen); if (0 == n) { return aWordLen; } if (!aWordLen) { return 0; } if (n <= 32) { for (i = 0; i < aWordLen - 1; i++) { a[i] >>= n; a[i] |= (a[i + 1] << (32 - n)); } a[i] >>= n; if (!a[i]) { return i; } return aWordLen; } else { j = n >> 5; n &= 31; for (i = 0; i < aWordLen - (int32_t)j - 1; i++) { a[i] = a[i + j] >> n; a[i] |= (a[i + j + 1] << (32 - n)); } a[i] = a[i + j] >> n; uint32_clear(a + aWordLen - j, j); if (!a[i]) { return i; } return aWordLen - j; } } /* Function: check whether a is equal to 1 or not * Parameters: * a ---------------- pointer to uint32_t big integer a * aWordLen --------- word length of big integer a * Return: 1(a is 1), 0(a is not 1) * Caution: */ uint8_t bigint_check_1(uint32_t a[], uint32_t aWordLen) { uint32_t i; if (!aWordLen) { return 0; } if (a[0] != 1) { return 0; } for (i = 1; i < aWordLen; i++) { if (a[i]) { return 0; } } return 1; } /* function: check whether a is equal to p-1 or not * parameters: * a ---------------- pointer to uint32_t big integer a * p ---------------- pointer to uint32_t big integer p, p must be odd * wordLen ---------- word length of a and p * return: 1(a is 1), 0(a is not 1) * caution: * 1. make sure p is odd */ uint8_t bigint_check_p_1(uint32_t a[], uint32_t p[], uint32_t wordLen) { uint32_t i; if (!wordLen) { return 0; } if (a[0] != p[0] - 1) { return 0; } for (i = 1; i < wordLen; i++) { if (a[i] != p[i]) { return 0; } } return 1; } uint32_t ce_get_current_time(void) { #ifdef BOARD_KERNEL_TIMER return timer_get_current_time(&g_kernel_timer); #else return 0; #endif }