rt-thread-official/components/drivers/hwcrypto/hw_bignum.c

354 lines
7.9 KiB
C

/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-25 tyx the first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <hw_bignum.h>
static struct rt_hwcrypto_ctx *bignum_default;
rt_inline rt_err_t rt_hwcrypto_bignum_init(void)
{
struct rt_hwcrypto_device *dev;
if (bignum_default)
{
return RT_EOK;
}
dev = rt_hwcrypto_dev_dufault();
if (dev == RT_NULL)
{
return -RT_ERROR;
}
return rt_hwcrypto_bignum_default(dev);
}
/**
* @brief Setting bignum default devices
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device)
{
if (bignum_default)
{
rt_hwcrypto_ctx_destroy(bignum_default);
bignum_default = RT_NULL;
}
if (device == RT_NULL)
{
return RT_EOK;
}
bignum_default = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_BIGNUM, sizeof(struct hwcrypto_bignum));
if (bignum_default == RT_NULL)
{
return -RT_ERROR;
}
return RT_EOK;
}
/**
* @brief Allocate memory for bignum
*
* @return Pointer to allocated bignum obj
*/
struct hw_bignum_mpi *rt_hwcrypto_bignum_alloc(void)
{
struct hw_bignum_mpi *n;
n = rt_malloc(sizeof(struct hw_bignum_mpi));
if (n)
{
rt_memset(n, 0, sizeof(struct hw_bignum_mpi));
}
return n;
}
/**
* @brief free a bignum obj
*
* @param Pointer to bignum obj
*/
void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n)
{
if (n)
{
rt_free(n->p);
rt_free(n);
}
}
/**
* @brief Get length of bignum as an unsigned binary buffer
*
* @param n bignum obj
*
* @return binary buffer Length
*/
int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n)
{
int tmp_len, total;
if (n == RT_NULL || n->p == RT_NULL)
{
return 0;
}
tmp_len = 0;
total = n->total;
while ((total > 0) && (n->p[total - 1] == 0))
{
tmp_len++;
total--;
}
return n->total - tmp_len;
}
/**
* @brief Get length of bignum as an unsigned binary buffer
*
* @param n bignum obj
* @param buf Buffer for the binary number
* @param len Length of the buffer
*
* @return binary buffer Length
*/
int rt_hwcrypto_bignum_get_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len)
{
int cp_len;
if (n == RT_NULL || n->p == RT_NULL || buf == RT_NULL)
{
return 0;
}
cp_len = n->total > len ? len : n->total;
rt_memcpy(n->p, buf, cp_len);
return cp_len;
}
/**
* @brief Set binary buffer to unsigned bignum
*
* @param n bignum obj
* @param buf Buffer for the binary number
* @param len Length of the buffer
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_set_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len)
{
void *temp_p;
if (n == RT_NULL)
{
return -RT_EINVAL;
}
if (n->p && n->total >= len)
{
rt_memcpy(n->p, buf, len);
return RT_EOK;
}
temp_p = rt_malloc(len);
if (temp_p == RT_NULL)
{
return -RT_ENOMEM;
}
if (n->p)
{
rt_free(n->p);
n->p = temp_p;
n->total = 0;
}
rt_memcpy(n->p, buf, len);
n->total = len;
return RT_EOK;
}
/**
* @brief Unsigned comparison
*
* @param a bignum obj
* @param b bignum obj
*
* @return 0 is equal
*/
int rt_hwcrypto_bignum_cmp(const struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b)
{
int a_len, b_len;
if (a == RT_NULL || a->p == RT_NULL
|| b == RT_NULL || b->p == RT_NULL)
{
return -1;
}
a_len = rt_hwcrypto_bignum_get_len(a);
b_len = rt_hwcrypto_bignum_get_len(b);
if (a_len != b_len)
{
return a_len - b_len;
}
return rt_memcmp(a->p, b->p, a_len);
}
/**
* @brief Compare bignum to standard Unsigned integer
*
* @param a bignum obj
* @param b Unsigned integer
*
* @return 0 is equal
*/
int rt_hwcrypto_bignum_cmp_d(const struct hw_bignum_mpi *a, unsigned long b)
{
struct hw_bignum_mpi tmp_b;
b = b <= 0 ? -b : b;
tmp_b.total = sizeof(unsigned long);
tmp_b.p = &b;
return rt_hwcrypto_bignum_cmp(a, &tmp_b);
}
/**
* @brief a = b + c
*
* @param a bignum obj
* @param b bignum obj
* @param c bignum obj
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b,
const struct hw_bignum_mpi *c)
{
struct hwcrypto_bignum *bignum_ctx;
if (rt_hwcrypto_bignum_init() != RT_EOK)
{
return -RT_ERROR;
}
bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
if (bignum_ctx->ops->add)
{
return bignum_ctx->ops->add(bignum_ctx, a, b, c);
}
return -RT_ERROR;
}
/**
* @brief a = b - c
*
* @param a bignum obj
* @param b bignum obj
* @param c bignum obj
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b,
const struct hw_bignum_mpi *c)
{
struct hwcrypto_bignum *bignum_ctx;
if (rt_hwcrypto_bignum_init() != RT_EOK)
{
return -RT_ERROR;
}
bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
if (bignum_ctx->ops->sub)
{
return bignum_ctx->ops->sub(bignum_ctx, a, b, c);
}
return -RT_ERROR;
}
/**
* @brief a = b * c
*
* @param a bignum obj
* @param b bignum obj
* @param c bignum obj
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b,
const struct hw_bignum_mpi *c)
{
struct hwcrypto_bignum *bignum_ctx;
if (rt_hwcrypto_bignum_init() != RT_EOK)
{
return -RT_ERROR;
}
bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
if (bignum_ctx->ops->mul)
{
return bignum_ctx->ops->mul(bignum_ctx, a, b, c);
}
return -RT_ERROR;
}
/**
* @brief a = b * c (mod d)
*
* @param a bignum obj
* @param b bignum obj
* @param c bignum obj
*
* @return RT_EOK on success.
*/
rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b,
const struct hw_bignum_mpi *c,
const struct hw_bignum_mpi *d)
{
struct hwcrypto_bignum *bignum_ctx;
if (rt_hwcrypto_bignum_init() != RT_EOK)
{
return -RT_ERROR;
}
bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
if (bignum_ctx->ops->mulmod)
{
return bignum_ctx->ops->mulmod(bignum_ctx, a, b, c, d);
}
return -RT_ERROR;
}
/**
* @brief a = b ^ c (mod d)
*
* @param a bignum obj
* @param b bignum obj
* @param c bignum obj
*
* @return RT_EOK on success.
*/
rt_err_t bignum_exptmod(struct hw_bignum_mpi *a,
const struct hw_bignum_mpi *b,
const struct hw_bignum_mpi *c,
const struct hw_bignum_mpi *d)
{
struct hwcrypto_bignum *bignum_ctx;
if (rt_hwcrypto_bignum_init() != RT_EOK)
{
return -RT_ERROR;
}
bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
if (bignum_ctx->ops->exptmod)
{
return bignum_ctx->ops->exptmod(bignum_ctx, a, b, c, d);
}
return -RT_ERROR;
}