嵌入式技术论坛
直播中

贾小龙

7年用户 1613经验值
私信 关注
[经验]

如何对Numaker-IoT-M487开发板上的CRYPTO模块功能进行测试呢

硬件介绍

NuMaker-IoT-M487 开发板以 NuMicro M487 系列微控制器为主控核心,主频 192MHz,512KB FLASH,160KB RAM。具体内容就不再复制粘贴了,请直接查看NuMaker-IoT-M487 上手指南。

首次拿到开发板,它的大红配色让人眼前一亮。

本评测着重在 Crypto 模块,将展示各 API 的用法,遇到的小“坑”,以及 M487 的一个(很可能)硬件缺陷BSP 配置错误的发现过程。

使用说明

参照RT-Thread Studio 快速上手指南可以很快创建出一个闪灯程序:不需要写一行代码,Studio 生成的项目就是一个闪灯程序。

温馨提示

拨码开关太小,最好准一个小螺丝刀。

功能测试

根据 M487 本身的硬件能力,本次评测将涉及、对称加密、散列、循环冗余检验等方面。

熟悉环境、API

RT-Thread 采用组件式架构,Crypto 组件的接口定义在 rt-thread\components\drivers\hwcrypto 目录。M487 通过两层代码实现 hwcrypto 接口:一层是原本的硬件驱动,另一层是 RTT porting 代码。

各 API 都是同步调用,所以注意不要在 main 里直接用,而是在一个 thread 里调用。

使用 Crypto 组件时,需要先创建/获取 rt_hwcrypto_device 对象,然后针对要使用的功能创建对应的上下文,使用完成后再销毁上下文。

准备工作

#define print rt_kprintf

// 辅助函数

void print_hex(const uint8_t *buffer, int len)

{

int i;

for (i = 0; i < len; i++)

    print("%02X", buffer[i]);

print("\n");

}

void main_test(void *dummy)

{

// 获取默认 crypto 设备对象

struct rt_hwcrypto_device * dev = rt_hwcrypto_dev_default();

//...

}

int main(int argc, char **argv)

{

rt_thread_t tid = rt_thread_create("t", main_test, NULL,

           1024,

           5,

           50);

rt_thread_startup(tid);

return 0;

}

RNG

M487 内置硬件随机数发生器,这里我们生成一批数据,然后对数据的随机性做一个最最简单的检查:各字节是否在 [0..255] 之间均匀分布。

void test_rng(struct rt_hwcrypto_device *device)

{

struct rt_hwcrypto_ctx *ctx = rt_hwcrypto_rng_create(device);

int i;

static uint32_t counts[256] = {0};

#define CNT_THRES 700

print("generating 256 * 1000 random bytes:\n");

for (i = 0; i < 256 * 1000 / 4; i++)

{

    uint32_t v = rt_hwcrypto_rng_update_ctx(ctx);

    counts[v & 0xff]++; v >>= 8;

    counts[v & 0xff]++; v >>= 8;

    counts[v & 0xff]++; v >>= 8;

    counts[v & 0xff]++;

}

rt_hwcrypto_rng_destroy(ctx);

print("a simple check: if random bytes follow an uniform distribution...");

int flag = 0;

for (i = 0; i < 256; i++)

{

    if (counts[i] < CNT_THRES)

        flag = 1;

}

print("%s\n", flag == 0 ? "PASS" : "FAIL");

}

这个函数的运行结果是令人吃惊的:测试失败!

简单检查 RTT Porting 代码可确认问题不在这一层。但是这个地方需要进一步讨论:TRNG 失败后,回退到 rand() 是否合适?

从现象看,或许是漏配了 TRNG 的 0/1 均匀分布开关,再查 M487 TRNG 寄存器定义,无此开关。这个问题只能由新唐解决了,拭目以待。

更新:M487 实际上无 TRNG。

温馨提示

目前不要使用 M487 生成真随机数,不可靠。

CRC

CRC 功能测试如下:

温馨提示

内置的几种 hwcrypto_crc_mode 不好用(不常见),建议直接构造配置,并使用 rt_hwcrypto_crc_cfg。

Hash

试试 SHA256:

void test_hash(struct rt_hwcrypto_device *device)

{

const static uint8_t result[] = {0x9f, 0x64, 0xa7, 0x47, 0xe1, 0xb9, 0x7f, 0x13,

        0x1f, 0xab, 0xb6, 0xb4, 0x47, 0x29, 0x6c, 0x9b, 0x6f, 0x02, 0x01, 0xe7,

        0x9f, 0xb3, 0xc5, 0x35, 0x6e, 0x6c, 0x77, 0xe8, 0x9b, 0x6a, 0x80, 0x6a};

int i;

struct rt_hwcrypto_ctx *ctx = rt_hwcrypto_hash_create(device, HWCRYPTO_TYPE_SHA256);

if (ctx == 0)

{

    print("HWCRYPTO_TYPE_SHA256 not available!\n");

    return;

}

const static uint8_t value[] = {1,2,3,4};

static uint8_t hash[256 / 8];

rt_err_t err = rt_hwcrypto_hash_update(ctx, value, sizeof(value));

if (err)

{

    print("rt_hwcrypto_hash_update: %d\n", err);

}

rt_hwcrypto_hash_finish(ctx, hash, 32);

rt_hwcrypto_hash_destroy(ctx);

print("%s\n", memcmp(hash, result, sizeof(hash)) == 0 ? "PASS" : "FAIL");

}

测试结果令人“遗憾”:程序卡在 rt_hwcrypto_hash_update 里的。

温馨提示

NuMaker-IoT-M487 SDK v1.0.0 有问题,临时解决方案:将 BSP 代码到 main 分支的最新版本。升级时,务必注意只升级 Crypto 相关的二层代码即可,以免其它编译问题。

升级后,测试通过。

AES-128

用 AES-128 算法先加密再解密,看看结果是否一致:

void test_aes_128(struct rt_hwcrypto_device *device)

{

struct rt_hwcrypto_ctx *ctx = rt_hwcrypto_symmetric_create(device, HWCRYPTO_TYPE_AES_ECB);

if (ctx == 0)

{

    print("HWCRYPTO_TYPE_AES_ECB not available!\n");

    return;

}

const static uint8_t key[128 / 8] = {1,2,3,4};

const static uint8_t iv[16] = {4};

static uint8_t msg[16] = {5,6,7,8};

static uint8_t enc[16] = {};

static uint8_t dec[16] = {};

rt_hwcrypto_symmetric_setkey(ctx, key, sizeof(key) * 8);

rt_hwcrypto_symmetric_setiv(ctx, key, sizeof(iv));

rt_err_t err = rt_hwcrypto_symmetric_crypt(ctx, HWCRYPTO_MODE_ENCRYPT, sizeof(msg), msg, enc);

if (err)

{

    print("ENCRYPT err: %d\n", err);

}

err = rt_hwcrypto_symmetric_crypt(ctx, HWCRYPTO_MODE_DECRYPT, sizeof(msg), enc, dec);

if (err)

{

    print("DECRYPT err: %d\n", err);

}

rt_hwcrypto_symmetric_destroy(ctx);

print("%s\n", memcmp(dec, msg, sizeof(msg)) == 0 ? "PASS" : "FAIL");

}

心得与建议

Crypto 组件 API 设计延续 RT-Thread API 的简洁、明快,点赞;

建议 RT-Thread Studio 为新项目生成 .gitignore。

原作者:FLWX_7778

更多回帖

发帖
×
20
完善资料,
赚取积分