739 lines
20 KiB
C
739 lines
20 KiB
C
/*
|
|
* Copyright (c) 2019 Winner Microelectronics Co., Ltd.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2019-05-17 tyx 1st version
|
|
*/
|
|
|
|
#include <rtthread.h>
|
|
#include <rtdevice.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "drv_crypto.h"
|
|
#include "wm_crypto_hard.h"
|
|
|
|
// #define WM_HWCRYPTO_NOT_LOCK
|
|
// #define WM_HWCRYPTO_NOT_ALIGN_CHECK
|
|
|
|
extern u32 tls_crypto_crc_update_adv(u32 crc_val, CRYPTO_CRC_TYPE type, u8 mode, const unsigned char *in, u32 len);
|
|
extern int tls_crypto_des_encrypt_decrypt_adv(unsigned char *key, unsigned char *IV, const unsigned char *in, unsigned char *out, u32 len, CRYPTO_MODE cbc, CRYPTO_WAY dec);
|
|
extern int tls_crypto_3des_encrypt_decrypt_adv(unsigned char *key, unsigned char *IV, const unsigned char *in, unsigned char *out, u32 len, CRYPTO_MODE cbc, CRYPTO_WAY dec);
|
|
extern int tls_crypto_aes_encrypt_decrypt_adv(unsigned char *key, unsigned char *IV, const unsigned char *in, unsigned char *out, u32 len, CRYPTO_MODE cbc, CRYPTO_WAY dec);
|
|
extern int tls_crypto_rc4_adv(unsigned char *key, u32 keylen, const unsigned char *in, unsigned char *out, u32 len);
|
|
|
|
struct wm_hwcrypto_device
|
|
{
|
|
struct rt_hwcrypto_device dev;
|
|
struct rt_mutex mutex;
|
|
};
|
|
|
|
struct hash_ctx_des
|
|
{
|
|
psDigestContext_t contex;
|
|
};
|
|
|
|
static rt_uint32_t _rng_rand(struct hwcrypto_rng *ctx)
|
|
{
|
|
rt_uint32_t rand_num;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)ctx->parent.device;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
tls_crypto_random_init((u32)rt_tick_get(), CRYPTO_RNG_SWITCH_32);
|
|
tls_crypto_random_bytes((unsigned char *)&rand_num, sizeof(rand_num));
|
|
tls_crypto_random_stop();
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
return rand_num;
|
|
}
|
|
|
|
static rt_uint32_t _crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
|
|
{
|
|
rt_uint32_t crc_result;
|
|
CRYPTO_CRC_TYPE type;
|
|
u8 mode = 0;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)ctx->parent.device;
|
|
unsigned char align_flag = 0;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0)
|
|
{
|
|
void *temp;
|
|
temp = rt_malloc(length);
|
|
if (temp)
|
|
{
|
|
memcpy(temp, in, length);
|
|
in = temp;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
switch (ctx->crc_cfg.poly)
|
|
{
|
|
case 0x04C11DB7:
|
|
type = CRYPTO_CRC_TYPE_32;
|
|
break;
|
|
case 0x00001021:
|
|
type = CRYPTO_CRC_TYPE_16_CCITT;
|
|
break;
|
|
case 0x00008005:
|
|
type = CRYPTO_CRC_TYPE_16_MODBUS;
|
|
break;
|
|
case 0x00000007:
|
|
case 0x00000207:
|
|
type = CRYPTO_CRC_TYPE_8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
mode |= ctx->crc_cfg.flags & CRC_FLAG_REFOUT ? OUTPUT_REFLECT : 0;
|
|
mode |= ctx->crc_cfg.flags & CRC_FLAG_REFIN ? INPUT_REFLECT : 0;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
crc_result = tls_crypto_crc_update_adv(ctx->crc_cfg.last_val, type, mode, in, length);
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
rt_free((rt_uint8_t *)in);
|
|
}
|
|
#endif
|
|
|
|
ctx->crc_cfg.last_val = crc_result;
|
|
return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout;
|
|
}
|
|
|
|
static rt_err_t _hash_update(struct hwcrypto_hash *ctx, const rt_uint8_t *in, rt_size_t length)
|
|
{
|
|
rt_err_t err = RT_EOK;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)ctx->parent.device;
|
|
unsigned char align_flag = 0;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0)
|
|
{
|
|
void *temp;
|
|
temp = rt_malloc(length);
|
|
if (temp)
|
|
{
|
|
memcpy(temp, in, length);
|
|
in = temp;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
switch (ctx->parent.type & HWCRYPTO_MAIN_TYPE_MASK)
|
|
{
|
|
case HWCRYPTO_TYPE_MD5:
|
|
tls_crypto_md5_update(&((struct hash_ctx_des *)(ctx->parent.contex))->contex, in, length);
|
|
break;
|
|
case HWCRYPTO_TYPE_SHA1:
|
|
tls_crypto_sha1_update(&((struct hash_ctx_des *)(ctx->parent.contex))->contex, in, length);
|
|
break;
|
|
default:
|
|
err = -RT_ERROR;
|
|
break;
|
|
}
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
rt_free((rt_uint8_t *)in);
|
|
}
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
static rt_err_t _hash_finish(struct hwcrypto_hash *ctx, rt_uint8_t *out, rt_size_t length)
|
|
{
|
|
rt_err_t err = RT_EOK;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)ctx->parent.device;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
switch (ctx->parent.type & HWCRYPTO_MAIN_TYPE_MASK)
|
|
{
|
|
case HWCRYPTO_TYPE_MD5:
|
|
tls_crypto_md5_final(&((struct hash_ctx_des *)(ctx->parent.contex))->contex, out);
|
|
break;
|
|
case HWCRYPTO_TYPE_SHA1:
|
|
tls_crypto_sha1_final(&((struct hash_ctx_des *)(ctx->parent.contex))->contex, out);
|
|
break;
|
|
default:
|
|
err = -RT_ERROR;
|
|
break;
|
|
}
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
static rt_err_t _des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
|
|
{
|
|
CRYPTO_WAY mode;
|
|
CRYPTO_MODE cbc;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)symmetric_ctx->parent.device;
|
|
unsigned char *in, *out, align_flag = 0;
|
|
|
|
if ((symmetric_ctx->key_bitlen >> 3) != 8
|
|
|| (symmetric_info->length % 8) != 0)
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
in = (unsigned char *)symmetric_info->in;
|
|
out = (unsigned char *)symmetric_info->out;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)out % 4) != 0)
|
|
{
|
|
in = rt_malloc(symmetric_info->length);
|
|
if (in)
|
|
{
|
|
memcpy(in, symmetric_info->in, symmetric_info->length);
|
|
out = in;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
mode = symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? CRYPTO_WAY_ENCRYPT : CRYPTO_WAY_DECRYPT;
|
|
|
|
switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
|
|
{
|
|
case HWCRYPTO_TYPE_DES_ECB:
|
|
cbc = CRYPTO_MODE_ECB;
|
|
break;
|
|
case HWCRYPTO_TYPE_DES_CBC:
|
|
cbc = CRYPTO_MODE_CBC;
|
|
break;
|
|
default :
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
tls_crypto_des_encrypt_decrypt_adv(symmetric_ctx->key, symmetric_ctx->iv,
|
|
symmetric_info->in, symmetric_info->out,
|
|
symmetric_info->length, cbc, mode);
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
memcpy(symmetric_info->out, out, symmetric_info->length);
|
|
rt_free(in);
|
|
}
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t _des3_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
|
|
{
|
|
CRYPTO_WAY mode;
|
|
CRYPTO_MODE cbc;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)symmetric_ctx->parent.device;
|
|
unsigned char *in, *out, align_flag = 0;
|
|
|
|
if ((symmetric_ctx->key_bitlen >> 3) != 24
|
|
|| (symmetric_info->length % 8) != 0)
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
in = (unsigned char *)symmetric_info->in;
|
|
out = (unsigned char *)symmetric_info->out;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)out % 4) != 0)
|
|
{
|
|
in = rt_malloc(symmetric_info->length);
|
|
if (in)
|
|
{
|
|
memcpy(in, symmetric_info->in, symmetric_info->length);
|
|
out = in;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
mode = symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? CRYPTO_WAY_ENCRYPT : CRYPTO_WAY_DECRYPT;
|
|
|
|
switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
|
|
{
|
|
case HWCRYPTO_TYPE_3DES_ECB:
|
|
cbc = CRYPTO_MODE_ECB;
|
|
break;
|
|
case HWCRYPTO_TYPE_3DES_CBC:
|
|
cbc = CRYPTO_MODE_CBC;
|
|
break;
|
|
default :
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
tls_crypto_3des_encrypt_decrypt_adv(symmetric_ctx->key, symmetric_ctx->iv,
|
|
symmetric_info->in, symmetric_info->out,
|
|
symmetric_info->length, cbc, mode);
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
memcpy(symmetric_info->out, out, symmetric_info->length);
|
|
rt_free(in);
|
|
}
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t _rc4_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
|
|
{
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)symmetric_ctx->parent.device;
|
|
unsigned char *in, *out, align_flag = 0;
|
|
|
|
if ((symmetric_ctx->key_bitlen >> 3) != 16)
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
in = (unsigned char *)symmetric_info->in;
|
|
out = (unsigned char *)symmetric_info->out;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)out % 4) != 0)
|
|
{
|
|
in = rt_malloc(symmetric_info->length);
|
|
if (in)
|
|
{
|
|
memcpy(in, symmetric_info->in, symmetric_info->length);
|
|
out = in;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
tls_crypto_rc4_adv(symmetric_ctx->key, symmetric_ctx->key_bitlen >> 3,
|
|
(unsigned char *)symmetric_info->in,
|
|
symmetric_info->out,
|
|
symmetric_info->length);
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
memcpy(symmetric_info->out, out, symmetric_info->length);
|
|
rt_free(in);
|
|
}
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t _aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
|
|
{
|
|
CRYPTO_WAY mode;
|
|
CRYPTO_MODE cbc;
|
|
struct wm_hwcrypto_device *_hwcrypto = (struct wm_hwcrypto_device *)symmetric_ctx->parent.device;
|
|
unsigned char *in, *out, align_flag = 0;
|
|
|
|
if ((symmetric_ctx->key_bitlen >> 3) != 16
|
|
|| (symmetric_info->length % 16) != 0)
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
in = (unsigned char *)symmetric_info->in;
|
|
out = (unsigned char *)symmetric_info->out;
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)out % 4) != 0)
|
|
{
|
|
in = rt_malloc(symmetric_info->length);
|
|
if (in)
|
|
{
|
|
memcpy(in, symmetric_info->in, symmetric_info->length);
|
|
out = in;
|
|
align_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
mode = symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? CRYPTO_WAY_ENCRYPT : CRYPTO_WAY_DECRYPT;
|
|
|
|
switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
|
|
{
|
|
case HWCRYPTO_TYPE_AES_ECB:
|
|
cbc = CRYPTO_MODE_ECB;
|
|
break;
|
|
case HWCRYPTO_TYPE_AES_CBC:
|
|
cbc = CRYPTO_MODE_CBC;
|
|
break;
|
|
case HWCRYPTO_TYPE_AES_CTR:
|
|
cbc = CRYPTO_MODE_CTR;
|
|
break;
|
|
default :
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_take(&_hwcrypto->mutex, RT_WAITING_FOREVER);
|
|
#endif
|
|
tls_crypto_aes_encrypt_decrypt_adv(symmetric_ctx->key, symmetric_ctx->iv,
|
|
in, out, symmetric_info->length, cbc, mode);
|
|
#if !defined(WM_HWCRYPTO_NOT_LOCK)
|
|
rt_mutex_release(&_hwcrypto->mutex);
|
|
#endif
|
|
|
|
#if !defined(WM_HWCRYPTO_NOT_ALIGN_CHECK)
|
|
if (align_flag)
|
|
{
|
|
memcpy(symmetric_info->out, out, symmetric_info->length);
|
|
rt_free(in);
|
|
}
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**< a = b ^ c (mod d) */
|
|
static rt_err_t _bignum_exptmod(struct hwcrypto_bignum *bignum_ctx,
|
|
struct hw_bignum_mpi *x,
|
|
const struct hw_bignum_mpi *a,
|
|
const struct hw_bignum_mpi *b,
|
|
const struct hw_bignum_mpi *c)
|
|
{
|
|
pstm_int pa, pb, pm, pres;
|
|
u32 * buff_a = NULL;
|
|
u32 * buff_b = NULL;
|
|
u32 * buff_m = NULL;
|
|
int err = -1;
|
|
void *buff;
|
|
int buff_len;
|
|
|
|
pstm_init(NULL, &pres);
|
|
|
|
buff_a = tls_mem_alloc(a->total);
|
|
if(buff_a == NULL)
|
|
goto out;
|
|
buff_b = tls_mem_alloc(b->total);
|
|
if(buff_b == NULL)
|
|
goto out;
|
|
buff_m = tls_mem_alloc(c->total);
|
|
if(buff_m == NULL)
|
|
goto out;
|
|
|
|
memset(buff_a, 0, a->total);
|
|
memset(buff_b, 0, b->total);
|
|
memset(buff_m, 0, c->total);
|
|
|
|
memcpy(buff_a, a->p, a->total);
|
|
memcpy(buff_b, b->p, b->total);
|
|
memcpy(buff_m, c->p, c->total);
|
|
|
|
pstm_reverse((unsigned char *)buff_a, a->total);
|
|
pstm_reverse((unsigned char *)buff_b, b->total);
|
|
pstm_reverse((unsigned char *)buff_m, c->total);
|
|
|
|
// *((volatile unsigned int *)0x40000710) = *((volatile unsigned int *)0x40000710) | (0x1 << 28);
|
|
|
|
if ((err = pstm_init_for_read_unsigned_bin(NULL, &pa, a->total)) != PS_SUCCESS){
|
|
goto out;
|
|
}
|
|
if ((err = pstm_read_unsigned_bin(&pa, (unsigned char *)buff_a, a->total)) != PS_SUCCESS) {
|
|
goto out;
|
|
}
|
|
if ((err = pstm_init_for_read_unsigned_bin(NULL, &pb, b->total)) != PS_SUCCESS){
|
|
goto out;
|
|
}
|
|
if ((err = pstm_read_unsigned_bin(&pb, (unsigned char *)buff_b, b->total)) != PS_SUCCESS) {
|
|
goto out;
|
|
}
|
|
if ((err = pstm_init_for_read_unsigned_bin(NULL, &pm, c->total)) != PS_SUCCESS){
|
|
goto out;
|
|
}
|
|
if ((err = pstm_read_unsigned_bin(&pm, (unsigned char *)buff_m, c->total)) != PS_SUCCESS) {
|
|
goto out;
|
|
}
|
|
|
|
tls_crypto_exptmod(&pa, &pb, &pm, &pres);
|
|
buff_len = pstm_unsigned_bin_size(&pres);
|
|
buff = rt_malloc(buff_len);
|
|
pstm_to_unsigned_bin_nr(NULL, &pres, buff);
|
|
x->sign = pres.sign;
|
|
x->p = buff;
|
|
x->total = buff_len;
|
|
|
|
out:
|
|
if(buff_a)
|
|
tls_mem_free(buff_a);
|
|
if(buff_b)
|
|
tls_mem_free(buff_b);
|
|
if(buff_m)
|
|
tls_mem_free(buff_m);
|
|
|
|
pstm_clear(&pa);
|
|
pstm_clear(&pb);
|
|
pstm_clear(&pm);
|
|
pstm_clear(&pres);
|
|
|
|
if (a->sign < 0)
|
|
{
|
|
rt_kprintf("a->sign < 0\n");
|
|
}
|
|
|
|
return err == PS_SUCCESS ? RT_EOK : -RT_ERROR;
|
|
}
|
|
|
|
static const struct hwcrypto_symmetric_ops aes_ops =
|
|
{
|
|
.crypt = _aes_crypt,
|
|
};
|
|
|
|
static const struct hwcrypto_symmetric_ops rc4_ops =
|
|
{
|
|
.crypt = _rc4_crypt,
|
|
};
|
|
|
|
static const struct hwcrypto_symmetric_ops des_ops =
|
|
{
|
|
.crypt = _des_crypt,
|
|
};
|
|
|
|
static const struct hwcrypto_symmetric_ops des3_ops =
|
|
{
|
|
.crypt = _des3_crypt,
|
|
};
|
|
|
|
static const struct hwcrypto_hash_ops hash_ops =
|
|
{
|
|
.update = _hash_update,
|
|
.finish = _hash_finish,
|
|
};
|
|
|
|
static const struct hwcrypto_rng_ops rng_ops =
|
|
{
|
|
.update = _rng_rand,
|
|
};
|
|
|
|
static const struct hwcrypto_crc_ops crc_ops =
|
|
{
|
|
.update = _crc_update,
|
|
};
|
|
|
|
static const struct hwcrypto_bignum_ops bignum_ops =
|
|
{
|
|
.add = RT_NULL,
|
|
.sub = RT_NULL,
|
|
.mul = RT_NULL,
|
|
.mulmod = RT_NULL,
|
|
.exptmod = _bignum_exptmod,
|
|
};
|
|
|
|
static rt_err_t _crypto_create(struct rt_hwcrypto_ctx *ctx)
|
|
{
|
|
rt_err_t res = RT_EOK;
|
|
void *contex;
|
|
|
|
switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
|
|
{
|
|
case HWCRYPTO_TYPE_AES :
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_symmetric *)ctx)->ops = &aes_ops;
|
|
break;
|
|
case HWCRYPTO_TYPE_RC4 :
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_symmetric *)ctx)->ops = &rc4_ops;
|
|
break;
|
|
case HWCRYPTO_TYPE_MD5:
|
|
case HWCRYPTO_TYPE_SHA1:
|
|
contex = rt_malloc(sizeof(struct hash_ctx_des));
|
|
if (contex == RT_NULL)
|
|
{
|
|
return -RT_ENOMEM;
|
|
}
|
|
memset(contex, 0, sizeof(struct hash_ctx_des));
|
|
ctx->contex = contex;
|
|
((struct hwcrypto_hash *)ctx)->ops = &hash_ops;
|
|
if ((ctx->type & HWCRYPTO_MAIN_TYPE_MASK) == HWCRYPTO_TYPE_MD5)
|
|
{
|
|
tls_crypto_md5_init(&((struct hash_ctx_des *)contex)->contex);
|
|
}
|
|
else
|
|
{
|
|
tls_crypto_sha1_init(&((struct hash_ctx_des *)contex)->contex);
|
|
}
|
|
break;
|
|
case HWCRYPTO_TYPE_DES:
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_symmetric *)ctx)->ops = &des_ops;
|
|
break;
|
|
case HWCRYPTO_TYPE_3DES:
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_symmetric *)ctx)->ops = &des3_ops;
|
|
break;
|
|
case HWCRYPTO_TYPE_RNG:
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_rng *)ctx)->ops = &rng_ops;
|
|
ctx->contex = RT_NULL;
|
|
break;
|
|
case HWCRYPTO_TYPE_CRC:
|
|
ctx->contex = RT_NULL;
|
|
((struct hwcrypto_crc *)ctx)->ops = &crc_ops;
|
|
break;
|
|
case HWCRYPTO_TYPE_BIGNUM:
|
|
((struct hwcrypto_bignum *)ctx)->ops = &bignum_ops;
|
|
break;
|
|
default:
|
|
res = -RT_ERROR;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void _crypto_destroy(struct rt_hwcrypto_ctx *ctx)
|
|
{
|
|
rt_free(ctx->contex);
|
|
}
|
|
|
|
static rt_err_t _crypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
|
|
{
|
|
rt_err_t res = RT_EOK;
|
|
|
|
switch (src->type & HWCRYPTO_MAIN_TYPE_MASK)
|
|
{
|
|
case HWCRYPTO_TYPE_AES:
|
|
case HWCRYPTO_TYPE_RC4:
|
|
case HWCRYPTO_TYPE_RNG:
|
|
case HWCRYPTO_TYPE_CRC:
|
|
case HWCRYPTO_TYPE_BIGNUM:
|
|
break;
|
|
case HWCRYPTO_TYPE_MD5:
|
|
case HWCRYPTO_TYPE_SHA1:
|
|
if (des->contex && src->contex)
|
|
{
|
|
rt_memcpy(des->contex, src->contex, sizeof(struct hash_ctx_des));
|
|
}
|
|
break;
|
|
default:
|
|
res = -RT_ERROR;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void _crypto_reset(struct rt_hwcrypto_ctx *ctx)
|
|
{
|
|
switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
|
|
{
|
|
case HWCRYPTO_TYPE_AES:
|
|
case HWCRYPTO_TYPE_RC4:
|
|
case HWCRYPTO_TYPE_RNG:
|
|
case HWCRYPTO_TYPE_CRC:
|
|
break;
|
|
case HWCRYPTO_TYPE_MD5:
|
|
tls_crypto_md5_init(&((struct hash_ctx_des *)(ctx->contex))->contex);
|
|
break;
|
|
case HWCRYPTO_TYPE_SHA1:
|
|
tls_crypto_sha1_init(&((struct hash_ctx_des *)(ctx->contex))->contex);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const struct rt_hwcrypto_ops _ops =
|
|
{
|
|
.create = _crypto_create,
|
|
.destroy = _crypto_destroy,
|
|
.copy = _crypto_clone,
|
|
.reset = _crypto_reset,
|
|
};
|
|
|
|
extern u8 *wpa_supplicant_get_mac(void);
|
|
|
|
int wm_hw_crypto_device_init(void)
|
|
{
|
|
static struct wm_hwcrypto_device _crypto_dev;
|
|
|
|
_crypto_dev.dev.ops = &_ops;
|
|
_crypto_dev.dev.id = 0;
|
|
rt_memcpy(&_crypto_dev.dev.id, wpa_supplicant_get_mac(),
|
|
sizeof(_crypto_dev.dev.id) > 6 ?
|
|
6 : sizeof(_crypto_dev.dev.id));
|
|
_crypto_dev.dev.user_data = &_crypto_dev;
|
|
|
|
if (rt_hwcrypto_register(&_crypto_dev.dev,
|
|
RT_HWCRYPTO_DEFAULT_NAME) != RT_EOK)
|
|
{
|
|
return -1;
|
|
}
|
|
rt_mutex_init(&_crypto_dev.mutex, RT_HWCRYPTO_DEFAULT_NAME, RT_IPC_FLAG_FIFO);
|
|
return 0;
|
|
}
|
|
INIT_DEVICE_EXPORT(wm_hw_crypto_device_init);
|