前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >全志R128 SDK HAL 模块开发指南——Crypto Engine

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

作者头像
阿志小管家
发布2024-03-22 09:04:09
680
发布2024-03-22 09:04:09
举报

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 的配置如下:

代码语言:javascript
复制
Kernel Setup --->
    Drivers Setup --->
        SoC HAL Drivers --->
            CE devices --->
                [*] enable ce driver
                [*] enbale ce hal APIs Test command

源码结构

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

代码语言:javascript
复制
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公用操作接口函数头文件

模块接口说明

头文件

代码语言:javascript
复制
#include <sunxi_hal_ce.h>
CE 初始化接口

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

函数原型:

代码语言:javascript
复制
int sunxi_ce_init(void)

参数:

返回值:

  • 0:成功
  • 负数:失败
CE 去初始化接口

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

函数原型:

代码语言:javascript
复制
int sunxi_ce_uninit(void)

参数:

返回值:

  • 0:成功
  • 负数:失败
AES 算法加解密接口

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

函数原型:

代码语言:javascript
复制
int do_aes_crypto(crypto_aes_req_ctx_t *req_ctx)

参数:

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

返回值:

  • 0:成功
  • 负数:失败
代码语言:javascript
复制
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 算法进行运算

函数原型:

代码语言:javascript
复制
int do_hash_crypto(crypto_hash_req_ctx_t *req_ctx)

参数:

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

返回值:

  • 0:成功
  • 负数:失败
代码语言:javascript
复制
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 算法进行加解密

函数原型:

代码语言:javascript
复制
int do_rsa_crypto(crypto_rsa_req_ctx_t *req_ctx)

参数:

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

返回值:

  • 0:成功
  • 负数:失败
代码语言:javascript
复制
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 算法运算接口

主要实现随机数的生成

函数原型:

代码语言:javascript
复制
int do_rng_gen(crypto_rsa_req_ctx_t *req_ctx)

参数:

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

返回值:

  • 0:成功
  • 负数:失败
代码语言:javascript
复制
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;

模块使用范例

由于测试用例较大,所以将其拆分进入一个头文件内,

代码语言:javascript
复制
#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) {
  i
  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) {

      // goto out;

  return ret;
}

FINSH_FUNCTION_EXPORT_CMD(cmd_test_ce, hal_ce, tina rtos ce test demo)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Crypto Engine
    • 模块介绍
      • 模块配置
        • 源码结构
          • 模块接口说明
            • CE 初始化接口
            • CE 去初始化接口
            • AES 算法加解密接口
            • HASH 算法运算接口
            • RSA 算法运算接口
            • RNG 算法运算接口
          • 模块使用范例
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档