Files
6CAR/drivers/source/crypto/sdrv_crypto_utility.c
2026-04-18 09:16:58 +08:00

698 lines
14 KiB
C

/**
* @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<b
* caution:
*/
int32_t uint32_bignumcmp(uint32_t *a, uint32_t aWordLen, uint32_t *b,
uint32_t bWordLen)
{
int32_t i;
aWordLen = get_valid_words(a, aWordLen);
bWordLen = get_valid_words(b, bWordLen);
if (aWordLen > 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
}