打印
[技术讨论]

全志R128 SDK HAL 模块开发指南——Crypto Engine

[复制链接]
479|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
神棍地海棠|  楼主 | 2024-3-21 11:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
# Crypto Engine

## 模块介绍

CE 模块主要支持对称算法、非对称算法、摘要算法进行数据的加密和解密功能。

CE 模块主要支持的算法如下:

- AES 算法 ECB/CBC/CTR/CTS/OFB/CFB/CBC-MAC/XTS 等模式.
- HASH 算法 MD5/SHA1/SHA224/SHA256/SHA384/SHA512/HMAC-SHA1/HMAC-SHA256.
- 非对称算法 RSA512/1024/2048/3072/4096.

## 模块配置

其menuconfig 的配置如下:

```shell
Kernel Setup --->
    Drivers Setup --->
        SoC HAL Drivers --->
            CE devices --->
                [*] enable ce driver
                [*] enbale ce hal APIs Test command
```

## 源码结构

CE 驱动位于 `source/drivers/hal/source/ce/` 目录下。

```c
hal/
├── source
│ ├── ce
│ │ ├── ce_common.c    # CE公用操作接口函数文件
│ │ ├── ce_common.h    # CE操作接口函数头文件
│ │ ├── hal_ce.c       # CE底层驱动文件
│ │ ├── hal_ce.h       # CE底层驱动头文件
│ │ ├── Makefile
│ │ └── platform.h     # 平台配置头文件
| ├── platform
│ └── ce_sun20iw2.h    # 具体的平台配置头文件
├── include/hal
  └── sunxi_hal_ce.h   # CE公用操作接口函数头文件
```

## 模块接口说明

头文件

```c
#include <sunxi_hal_ce.h>
```

### CE 初始化接口

CE 模块初始化,主要申请中断、clk 初始化等

函数原型:

```c
int sunxi_ce_init(void)
```

参数:

- 无

返回值:

- 0:成功
- 负数:失败

### CE 去初始化接口

CE 模块去初始化,主要注销中断等

函数原型:

```c
int sunxi_ce_uninit(void)
```

参数:

- 无

返回值:

- 0:成功
- 负数:失败

### AES 算法加解密接口

主要实现对 AES 算法进行加解密

函数原型:

```c
int do_aes_crypto(crypto_aes_req_ctx_t *req_ctx)
```

参数:

- req_ctx: 为 AES 算法上下文的结构体

返回值:

- 0:成功
- 负数:失败

```c
typedef struct {
    uint8_t *src_buffer;
    uint32_t src_length;
    uint8_t *dst_buffer;
    uint32_t dst_length;
    uint8_t *iv;
    uint8_t *iv_next;
    uint8_t *key;
    uint32_t key_length;
    __aligned(CACHELINE_LEN) uint8_t padding[AES_BLOCK_SIZE];
    uint32_t padding_len;
    uint32_t dir;                         /*0--加密,1--解密*/
    uint32_t mode;                         /*AES算法的模式*/
    uint32_t bitwidth;
} crypto_aes_req_ctx_t;
```

### HASH 算法运算接口

主要实现对HASH 算法进行运算

函数原型:

```c
int do_hash_crypto(crypto_hash_req_ctx_t *req_ctx)
```

参数:

- req_ctx: 为HASH 算法上下文的结构体

返回值:

- 0:成功
- 负数:失败

```c
typedef struct {
    uint8_t *src_buffer;
    uint32_t src_length;
    uint8_t *dst_buffer;
    uint32_t dst_length;
    __aligned(CACHELINE_LEN) uint8_t md[SHA_MAX_DIGEST_SIZE];
    uint32_t md_size;
    __aligned(CACHELINE_LEN) uint8_t padding[SHA512_BLOCK_SIZE * 2];
    uint32_t padding_len;
    uint32_t type;                         /*hash算法的模式*/
    uint32_t dir;
    uint32_t padding_mode;         /*hash算法的填充模式*/
} crypto_hash_req_ctx_t;
```

### RSA 算法运算接口

主要实现对RSA 算法进行加解密

函数原型:

```c
int do_rsa_crypto(crypto_rsa_req_ctx_t *req_ctx)
```

参数:

- req_ctx: 为 RSA算法上下文的结构体

返回值:

- 0:成功
- 负数:失败

```c
typedef struct {
    uint8_t *key_n;    /*公钥模数*/
    uint32_t n_len;
    uint8_t *key_e;    /*公钥指数*/
    uint32_t e_len;
    uint8_t *key_d;    /*私钥*/
    uint32_t d_len;
    uint8_t *src_buffer;
    uint32_t src_length;
    uint8_t *dst_buffer;
    uint32_t dst_length;
    uint32_t dir;      /*0--加密,1--解密*/
    uint32_t type;     /*RSA算法的模式*/
    uint32_t bitwidth; /*RSA算法位宽*/
} crypto_rsa_req_ctx_t;
```

### RNG 算法运算接口

主要实现随机数的生成

函数原型:

```c
int do_rng_gen(crypto_rsa_req_ctx_t *req_ctx)
```

参数:

- req_ctx: 为 RNG 算法上下文的结构体

返回值:

- 0:成功
- 负数:失败

```c
typedef struct {
    uint8_t *rng_buf;
    uint32_t rng_len;
    uint32_t mode;
    uint8_t *key;
    uint32_t key_len;
} crypto_rng_req_ctx_t;
```

## 模块使用范例

由于测试用例较大,所以将其拆分进入一个头文件内,可以从这里下载:[test_ce.h](sdk_module/assets/demo/ce/test_ce.h ':ignore')

```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <hal_cmd.h>
#include <hal_mem.h>
#include <sunxi_hal_ce.h>
#include "test_ce.h"

#define AES_MODE_ECB (0)
#define AES_MODE_CBC (1)
#define AES_MODE_CTR (2)
#define AES_MODE_CTS (3)
#define AES_MODE_OFB (4)
#define AES_MODE_CFB (5)

#define AES_DIR_ENCRYPT (0)
#define AES_DIR_DECRYPT (1)

#define HASH_METHOD_MD5 (16)
#define HASH_METHOD_SHA1 (17)
#define HASH_METHOD_SHA224 (18)
#define HASH_METHOD_SHA256 (19)
#define HASH_METHOD_SHA384 (20)
#define HASH_METHOD_SHA512 (21)

void ce_dump(char *str, unsigned char *data, int len, int align) {
  int i = 0;
  if (str) printf("\n%s: ", str);
  for (i = 0; i < len; i++) {
    if ((i % align) == 0) {
      printf("\n");
      printf("0x08%x: ", data + i * align);
    }
    printf("%02x ", *(data++));
  }
  printf("\n");
}

int aes_test(void) {
  int ret = -1;
  int i = 0;
  int j = 0;
  int m = 0;
  uint8_t *enc_buffer = 0;
  uint32_t enc_len = 0;
  uint32_t blk_num = 0;
  __aligned(CACHELINE_LEN) uint8_t iv_next[AES_BLOCK_SIZE] = {0};
  uint8_t *(*aes_enc[])[5] = {aes_ecb, aes_cbc, aes_ctr,
                              aes_cbc, aes_ofb, aes_cfb8};
  crypto_aes_req_ctx_t *aes_ctx = NULL;

  aes_ctx = (crypto_aes_req_ctx_t *)hal_malloc_align(
      sizeof(crypto_aes_req_ctx_t), max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (aes_ctx == NULL) {
    printf(" malloc data buffer fail\n");
    return -1;
  }
  memset(aes_ctx, 0x0, sizeof(crypto_aes_req_ctx_t));

  aes_ctx->dst_buffer =
      (u8 *)hal_malloc_align(512, max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (aes_ctx->dst_buffer == NULL) {
    printf(" malloc dest buffer fail\n");
    ret = -1;
    goto out;
  }

  for (m = AES_MODE_ECB; m < AES_MODE_CFB + 1; m++) {
    for (i = 0; i < sizeof(aes_key_len) / sizeof(aes_key_len[0]); i++) {
      for (j = 0; j < sizeof(aes_src) / sizeof(aes_src[0]); j++) {
        /* aes encrypt */
        aes_ctx->src_buffer = aes_src[j];
        aes_ctx->src_length = aes_src_len[j];
        aes_ctx->key = aes_key[i];
        aes_ctx->key_length = aes_key_len[i];
        if (m == AES_MODE_ECB)
          aes_ctx->iv = NULL;
        else
          aes_ctx->iv = aes_iv;
        if (m == AES_MODE_CTR) {
          memset(iv_next, 0, AES_BLOCK_SIZE);
          aes_ctx->iv_next = iv_next;
        } else
          aes_ctx->iv_next = NULL;
        if (m == AES_MODE_CFB)
          aes_ctx->bitwidth = 8;
        else
          aes_ctx->bitwidth = 0;
        aes_ctx->mode = m;
        aes_ctx->dir = AES_DIR_ENCRYPT;
        aes_ctx->dst_length = CE_ROUND_UP(aes_ctx->src_length, AES_BLOCK_SIZE);

        printf(
            "###############AES, mode: %d, ksize %d, src len %d, "
            "begin###############\n",
            m, aes_key_len[i], aes_src_len[j]);

        ret = do_aes_crypto(aes_ctx);
        if (ret < 0) {
          printf("aes encrypt fail %d\n", ret);
          goto out;
        }

        // for ecb/cbc/cts, enc data len should be 16 bytes aligned
        if (m == AES_MODE_ECB || m == AES_MODE_CBC || m == AES_MODE_CTS)
          enc_len = aes_ctx->dst_length;
        else
          enc_len = aes_src_len[j];

        // openssl enc do not support cts, so create enc data manually.
        if (m == AES_MODE_CTS) {
          enc_buffer = (uint8_t *)hal_malloc_align(
              enc_len, max(CE_ALIGN_SIZE, CACHELINE_LEN));
          if (enc_buffer == NULL) {
            printf("malloc ctr buffer fail\n");
            ret = -1;
            goto out;
          }

          blk_num = enc_len / AES_BLOCK_SIZE;
          if (blk_num > 1) {
            if (blk_num > 2)
              memcpy(enc_buffer, aes_enc[m - AES_MODE_ECB][i][j],
                     (blk_num - 2) * AES_BLOCK_SIZE);
            memcpy(enc_buffer + (blk_num - 2) * AES_BLOCK_SIZE,
                   aes_enc[m - AES_MODE_ECB][i][j] +
                       (blk_num - 1) * AES_BLOCK_SIZE,
                   AES_BLOCK_SIZE);
            memcpy(enc_buffer + (blk_num - 1) * AES_BLOCK_SIZE,
                   aes_enc[m - AES_MODE_ECB][i][j] +
                       (blk_num - 2) * AES_BLOCK_SIZE,
                   AES_BLOCK_SIZE);
          } else {
            memcpy(enc_buffer, aes_enc[m - AES_MODE_ECB][i][j], enc_len);
          }
        } else
          enc_buffer = aes_enc[m - AES_MODE_ECB][i][j];

        if (memcmp(aes_ctx->dst_buffer, enc_buffer, enc_len) != 0) {
          ce_dump("want data: ", enc_buffer, enc_len, 16);
          ce_dump("calc data: ", aes_ctx->dst_buffer, enc_len, 16);
          printf(
              "###############AES ENC, mode: %d, ksize %d, src len %d, "
              "fail###############\n",
              m, aes_key_len[i], aes_src_len[j]);
          ret = -1;
          goto out;
        }

        /* aes decrypt */
        memset(aes_ctx->dst_buffer, 0x0, aes_ctx->dst_length);
        aes_ctx->dir = AES_DIR_DECRYPT;
        aes_ctx->src_buffer = enc_buffer;
        aes_ctx->src_length = enc_len;

        ret = do_aes_crypto(aes_ctx);
        if (ret < 0) {
          printf("aes decrypt fail %d\n", ret);
          goto out;
        }

        if (memcmp(aes_ctx->dst_buffer, aes_src[j], aes_src_len[j]) != 0) {
          ce_dump("want data: ", aes_src[j], aes_src_len[j], 16);
          ce_dump("calc data: ", aes_ctx->dst_buffer, aes_src_len[j], 16);
          printf(
              "###############AES DEC, mode: %d, ksize %d, src len %d, "
              "fail###############\n",
              m, aes_key_len[i], aes_src_len[j]);
          ret = -1;
          goto out;
        }

        if (m == AES_MODE_CTS) {
          if (enc_buffer) hal_free_align(enc_buffer);
        }

        printf(
            "###############AES, mode: %d, ksize %d, src len %d, "
            "pass###############\n\n\n",
            m, aes_key_len[i], aes_src_len[j]);
      }
    }
  }

out:
  if (aes_ctx->dst_buffer != NULL) {
    hal_free_align(aes_ctx->dst_buffer);
  }
  if (m == AES_MODE_CTS) {
    if (enc_buffer) hal_free_align(enc_buffer);
  }

  hal_free_align(aes_ctx);

  return ret;
}

int hash_test(void) {
  int i = 0;
  int j = 0;
  uint8_t *dst_data = NULL;
  // uint32_t data_size = 512; SHA_MAX_DIGEST_SIZE
  uint32_t data_size = SHA_MAX_DIGEST_SIZE;
  uint32_t hash_length = 0;
  int ret = -1;
  uint8_t *(*hash_digest[]) = {hash_md5,    hash_sha1,   hash_sha224,
                               hash_sha256, hash_sha384, hash_sha512};
  crypto_hash_req_ctx_t *hash_ctx = NULL;

  hash_ctx = (crypto_hash_req_ctx_t *)hal_malloc_align(
      sizeof(crypto_hash_req_ctx_t), max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (hash_ctx == NULL) {
    printf(" malloc hash_ctx fail\n");
    ret = -1;
    goto out;
  }

  /*malloc dst buf*/
  dst_data =
      (u8 *)hal_malloc_align(data_size, max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (dst_data == NULL) {
    printf(" malloc dst buffer fail\n");
    ret = -1;
    goto out;
  }

  for (i = HASH_METHOD_MD5; i < HASH_METHOD_SHA512 + 1; i++) {
    for (j = 0; j < sizeof(hash_src_len) / sizeof(hash_src_len[0]); j++) {
      memset(hash_ctx, 0x0, sizeof(crypto_hash_req_ctx_t));
      hash_ctx->src_buffer = hash_src[j];
      hash_ctx->src_length = hash_src_len[j];
      memset(dst_data, 0x0, data_size);
      hash_ctx->dst_buffer = dst_data;
      hash_ctx->type = i;
      hash_ctx->md_size = 0;
      switch (i) {
        case HASH_METHOD_MD5:
          hash_ctx->dst_length = MD5_DIGEST_SIZE;
          hash_length = MD5_DIGEST_SIZE;
          break;
        case HASH_METHOD_SHA1:
          hash_ctx->dst_length = SHA1_DIGEST_SIZE;
          hash_length = SHA1_DIGEST_SIZE;
          break;
        case HASH_METHOD_SHA224:
          hash_ctx->dst_length = SHA256_DIGEST_SIZE;
          hash_length = SHA224_DIGEST_SIZE;
          break;
        case HASH_METHOD_SHA256:
          hash_ctx->dst_length = SHA256_DIGEST_SIZE;
          hash_length = SHA256_DIGEST_SIZE;
          break;
        case HASH_METHOD_SHA384:
          hash_ctx->dst_length = SHA512_DIGEST_SIZE;
          hash_length = SHA384_DIGEST_SIZE;
          break;
        case HASH_METHOD_SHA512:
          hash_ctx->dst_length = SHA512_DIGEST_SIZE;
          hash_length = SHA512_DIGEST_SIZE;
          break;
        default:
          break;
      }

      printf("############hash type: %d, src len: %d, begin#############\n", i,
             hash_src_len[j]);

      ret = do_hash_crypto(hash_ctx);
      if (ret < 0) {
        printf("do_hash_crypto fail\n");
        goto out;
      }

      if (memcmp(hash_ctx->dst_buffer, hash_digest[i - HASH_METHOD_MD5][j],
                 hash_length) == 0) {
        printf(
            "############hash type: %d, src len: %d, pass#############\n\n\n",
            i, hash_src_len[j]);
      } else {
        ce_dump("want digest: ", hash_digest[i - HASH_METHOD_MD5][j],
                hash_length, 16);
        ce_dump("calc digest: ", hash_ctx->dst_buffer, hash_length, 16);
        printf(
            "############hash type: %d, src len: %d, fail#############\n\n\n",
            i, hash_src_len[j]);
        ret = -1;
        goto out;
      }
    }
  }

out:
  if (hash_ctx != NULL) {
    hal_free_align(hash_ctx);
  }

  if (dst_data != NULL) {
    hal_free_align(dst_data);
  }

  return ret;
}

#ifndef CONFIG_ARCH_SUN20IW2
int rng_test(void) {
  int ret = 0;
  int i = 0;
  uint8_t *rng_buf = NULL;
  uint32_t rng_size[] = {16, 31, 32, 8100};
  __aligned(CACHELINE_LEN) uint8_t key[24] = {
      0xa1, 0xb7, 0x78, 0xf7, 0xbf, 0x2c, 0xfa, 0xad, 0x6a, 0x46, 0x79, 0xc2,
      0xd2, 0x9c, 0x45, 0x1f, 0x3f, 0xcb, 0xef, 0xa5, 0x4e, 0x0e, 0xc3, 0x51};
  uint32_t key_len = 24;
  crypto_rng_req_ctx_t *rng_ctx = NULL;

  rng_ctx = (crypto_rng_req_ctx_t *)hal_malloc_align(
      sizeof(crypto_rng_req_ctx_t), max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (rng_ctx == NULL) {
    printf(" malloc rng ctx fail\n");
    ret = -1;
    goto out;
  }

  /*malloc trng buf*/
  rng_buf = (u8 *)hal_malloc_align(8192, max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (rng_buf == NULL) {
    printf("malloc rng buffer fail\n");
    ret = -1;
    goto out;
  }

#ifndef CE_FPGA_TEST
  /* FPGA do not support TRNG, so enable CE_FPGA_TEST when do CE FPGA
   * verification */
  /*TRNG test*/
  for (i = 0; i < sizeof(rng_size) / sizeof(uint32_t); i++) {
    printf("############TRNG, len: %d, begin#############\n", rng_size[i]);
    memset(rng_buf, 0, 8192);
    rng_ctx->rng_buf = rng_buf;
    rng_ctx->rng_len = rng_size[i];
    rng_ctx->mode = 0x30; /*CE_METHOD_TRNG*/
    rng_ctx->key = NULL;
    rng_ctx->key_len = 0;
    ret = do_rng_gen(rng_ctx);
    if (ret < 0) {
      printf("############TRNG, len: %d, fail#############\n\n\n", rng_size[i]);
      goto out;
    }
#if 0
                if (rng_size[i] < 100)
                        ce_dump("trng:", rng_buf, rng_size[i], 16);
#endif
    printf("############TRNG, len: %d, pass#############\n\n\n", rng_size[i]);
  }
#endif

  /*PRNG test*/
  for (i = 0; i < sizeof(rng_size) / sizeof(uint32_t); i++) {
    printf("############PRNG, len: %d, begin#############\n", rng_size[i]);
    memset(rng_buf, 0, 8192);
    rng_ctx->rng_buf = rng_buf;
    rng_ctx->rng_len = rng_size[i];
    rng_ctx->mode = 0x31; /*CE_METHOD_PRNG*/
    rng_ctx->key = key;
    rng_ctx->key_len = key_len;
    ret = do_rng_gen(rng_ctx);
    if (ret < 0) {
      printf("############PRNG, len: %d, fail#############\n\n\n", rng_size[i]);
      goto out;
    }
#if 0
                if (rng_size[i] < 100)
                        ce_dump("prng:", rng_buf, rng_size[i], 16);
#endif
    printf("############PRNG, len: %d, pass#############\n\n\n", rng_size[i]);
  }

out:
  if (rng_ctx) hal_free_align(rng_ctx);

  if (rng_buf) hal_free_align(rng_buf);

  return ret;
}
#else
int rng_test(void) {
  printf("sun20iw2 crypto engine do not support rng, please use hal_trng.\n");

  return 0;
}
#endif

int rsa_test(void) {
  int ret = 0;
  int i = 0;
  __aligned(CACHELINE_LEN) uint8_t dst_buffer[256] = {0};
  crypto_rsa_req_ctx_t *rsa_ctx = NULL;

  rsa_ctx = (crypto_rsa_req_ctx_t *)hal_malloc_align(
      sizeof(crypto_rsa_req_ctx_t), max(CE_ALIGN_SIZE, CACHELINE_LEN));
  if (rsa_ctx == NULL) {
    printf(" malloc rsa ctx fail\n");
    return -1;
  }

  /*rsa enc and dec*/
  for (i = 0; i < sizeof(rsa_bitwidth) / sizeof(rsa_bitwidth[0]); i++) {
    /* enc with public key*/
    printf("############RSA ENC/DEC, len: %d, begin#############\n",
           rsa_bitwidth[i]);
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = rsa_keye[i];
    rsa_ctx->e_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_d = 0;
    rsa_ctx->d_len = 0;

    rsa_ctx->src_buffer = rsa_src[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = rsa_bitwidth[i] / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_enc[i], rsa_bitwidth[i] / 8);
    if (ret) {
      printf("rsa encrypt failed\n");
      ce_dump("want data: ", rsa_enc[i], rsa_bitwidth[i] / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA ENC, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      goto out;
    }

    /* dec with private key */
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = 0;
    rsa_ctx->e_len = 0;
    rsa_ctx->key_d = rsa_keyd[i];
    rsa_ctx->d_len = rsa_bitwidth[i] / 8;

    rsa_ctx->src_buffer = rsa_enc[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = rsa_bitwidth[i] / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_src[i], rsa_bitwidth[i] / 8);
    if (ret) {
      printf("rsa decrypt failed\n");
      ce_dump("want data: ", rsa_src[i], rsa_bitwidth[i] / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA DEC, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      goto out;
    }

    printf("############RSA ENC/DEC, len: %d, pass#############\n\n\n",
           rsa_bitwidth[i]);
  }

  /* rsa sign/verify sha256 value */
  for (i = 0; i < sizeof(rsa_bitwidth) / sizeof(rsa_bitwidth[0]); i++) {
    /* sign with private key */
    printf("############RSA SIGN/VERIFY SHA256, len: %d, begin#############\n",
           rsa_bitwidth[i]);
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = 0;
    rsa_ctx->e_len = 0;
    rsa_ctx->key_d = rsa_keyd[i];
    rsa_ctx->d_len = rsa_bitwidth[i] / 8;

    rsa_ctx->src_buffer = rsa_sha256_raw[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = rsa_bitwidth[i] / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_sha256_sign[i], rsa_bitwidth[i] / 8);
    if (ret) {
      printf("rsa encrypt failed\n");
      ce_dump("want data: ", rsa_sha256_sign[i], rsa_bitwidth[i] / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA SIGN SHA256, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      // goto out;
    }

    /* verify with public key */
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = rsa_keye[i];
    rsa_ctx->e_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_d = 0;
    rsa_ctx->d_len = 0;

    rsa_ctx->src_buffer = rsa_sha256_sign[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = 256 / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_sha256[i], 256 / 8);
    if (ret) {
      printf("rsa decrypt failed\n");
      ce_dump("want data: ", rsa_sha256[i], 256 / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA VERIFY SHA256, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      goto out;
    }

    printf("############RSA SIGN/VERIFY SHA256, len: %d, pass#############\n\n\n",rsa_bitwidth[i]);
  }

  /* rsa sign/verify */
  for (i = 0; i < sizeof(rsa_bitwidth) / sizeof(rsa_bitwidth[0]); i++) {
    /* sign with private key */
    printf("############RSA SIGN/VERIFY, len: %d, begin#############\n",
           rsa_bitwidth[i]);
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = 0;
    rsa_ctx->e_len = 0;
    rsa_ctx->key_d = rsa_keyd[i];
    rsa_ctx->d_len = rsa_bitwidth[i] / 8;

    rsa_ctx->src_buffer = rsa_sign_raw[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = rsa_bitwidth[i] / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_signature[i], rsa_bitwidth[i] / 8);
    if (ret) {
      printf("rsa encrypt failed\n");
      ce_dump("want data: ", rsa_signature[i], rsa_bitwidth[i] / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA SIGN, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      // goto out;
    }

    /* verify with public key */
    memset(dst_buffer, 0, 256);
    memset(rsa_ctx, 0, sizeof(crypto_rsa_req_ctx_t));

    rsa_ctx->key_n = rsa_keyn[i];
    rsa_ctx->n_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_e = rsa_keye[i];
    rsa_ctx->e_len = rsa_bitwidth[i] / 8;
    rsa_ctx->key_d = 0;
    rsa_ctx->d_len = 0;

    rsa_ctx->src_buffer = rsa_signature[i];
    rsa_ctx->src_length = rsa_bitwidth[i] / 8;
    rsa_ctx->dst_buffer = dst_buffer;
    rsa_ctx->dst_length = 256 / 8;

    rsa_ctx->dir = 0;
    rsa_ctx->type = 0x20; /*CE_METHOD_RSA*/
    rsa_ctx->bitwidth = rsa_bitwidth[i];

    ret = do_rsa_crypto(rsa_ctx);
    if (ret < 0) {
      printf("do rsa crypto failed: %d\n", ret);
      goto out;
    }

    ret = memcmp(rsa_ctx->dst_buffer, rsa_sha256[i], 256 / 8);
    if (ret) {
      printf("rsa decrypt failed\n");
      ce_dump("want data: ", rsa_sha256[i], 256 / 8, 16);
      ce_dump("calc data: ", rsa_ctx->dst_buffer, rsa_ctx->dst_length, 16);
      printf("############RSA VERIFY, len: %d, fail#############\n\n\n",
             rsa_bitwidth[i]);
      goto out;
    }

    printf("############RSA SIGN/VERIFY, len: %d, pass#############\n\n\n",
           rsa_bitwidth[i]);
  }

out:
  if (rsa_ctx) hal_free_align(rsa_ctx);

  return ret;
}

#ifndef configAPPLICATION_NORMAL_PRIORITY
#define configAPPLICATION_NORMAL_PRIORITY (15)
#endif
static void aes_task(void *pvParameters) {
  int ret = 0;

  ret = aes_test();
  if (ret) {
    printf("ERROR: aes test failed\n");
  }

  vTaskDelete(NULL);
}
static void hash_task(void *pvParameters) {
  int ret = 0;

  ret = hash_test();
  if (ret) {
    printf("ERROR: hash test failed\n");
  }

  vTaskDelete(NULL);
}
static void rsa_task(void *pvParameters) {
  int ret = 0;

  ret = rsa_test();
  if (ret) {
    printf("ERROR: rsa test failed\n");
  }

  vTaskDelete(NULL);
}
static void rng_task(void *pvParameters) {
  int ret = 0;

  ret = rng_test();
  if (ret) {
    printf("ERROR: rng test failed\n");
  }

  vTaskDelete(NULL);
}

int cmd_test_ce(int argc, const char *argv[]) {
  int ret = 0;

  if (argc != 2) {
    printf("Parameter number Error!\n");
    printf("Usage: hal_ce <aes|hash|rsa|rng>\n");
    return -1;
  }

  sunxi_ce_init();

  if (strcmp(argv[1], "aes") == 0) {
    ret = aes_test();
  } else if (strcmp(argv[1], "hash") == 0) {
    ret = hash_test();
  } else if (strcmp(argv[1], "rsa") == 0) {
    ret = rsa_test();
  } else if (strcmp(argv[1], "rng") == 0) {
    ret = rng_test();
  } else if (strcmp(argv[1], "all") == 0) {
    TaskHandle_t task0, task1, task2, task3;
    portBASE_TYPE ret0, ret1, ret2, ret3;

    printf("******************************************************\n");
    printf("* NOTE: please enable CE_NO_IRQ when doing this test *\n");
    printf("******************************************************\n");

    ret0 = xTaskCreate(aes_task, (signed portCHAR *)"aes test", 4096, NULL,
                       configAPPLICATION_NORMAL_PRIORITY, &task0);
    if (ret0 != pdPASS) {
      printf("create aes task failed\n");
      return -1;
    }
    ret1 = xTaskCreate(hash_task, (signed portCHAR *)"hash test", 4096, NULL,
                       configAPPLICATION_NORMAL_PRIORITY, &task1);
    if (ret1 != pdPASS) {
      printf("create hash task failed\n");
      return -1;
    }
    ret2 = xTaskCreate(rsa_task, (signed portCHAR *)"rsa test", 4096, NULL,
                       configAPPLICATION_NORMAL_PRIORITY, &task2);
    if (ret2 != pdPASS) {
      printf("create rsa task failed\n");
      return -1;
    }
    ret3 = xTaskCreate(rng_task, (signed portCHAR *)"rng test", 4096, NULL,
                       configAPPLICATION_NORMAL_PRIORITY, &task3);
    if (ret3 != pdPASS) {
      printf("create rng task failed\n");
      return -1;
    }

  } else {
    printf("Parameter Error!\n");
    printf("Usage: hal_ce <aes|hash|rsa|rng|all>\n");
    ret = -1;
  }

  if (strcmp(argv[1], "all")) {
    sunxi_ce_uninit();
  }

  return ret;
}

FINSH_FUNCTION_EXPORT_CMD(cmd_test_ce, hal_ce, tina rtos ce test demo)
```


使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

260

主题

268

帖子

0

粉丝