CoolSilicon 发表于 2023-3-14 21:35

在Linux下交叉编译Cryptoauthlib到ARM平台下


Cryptoauthlib是Microchip针对安全芯片发布的C语言的代码库。具有优秀的分层结构,可以很方便地移植到任意平台中。并且提供了针对常用SSL库的适配层,支持OpenSSL, MbedTLS, WolfSSL等。

目前大部分的Linux系统中使用OpenSSL,OpenSSL调用硬件SE是通过PKCS11来实现的。本文将介绍OpenSSL通过PKCS11来调用Cryptoauthlib,实现操作硬件SE的步骤。

基本的依赖关系为:
OpenSSL -> p11-kit -> libpkcs -> Cryptoauthlib

## 1. 硬件平台
在Arm平台下可以使用I2C或HID接口。对于嵌入式平台通常使用I2C接口直接操作安全芯片。

> 本文主要介绍I2C接口。

> 注意:安全芯片在平时处于休眠模式,不会响应I2C的操作,所以每次操作前都需要先唤醒芯片。
> 唤醒时序是:在SDA上发一个超过60uS的低电平,拉高后再等待1.5ms,通过器件地址比如0xC0直接读4个字节,如果是0x04, 0x11, 0x33, 0x43则说明芯片确实正确唤醒了。接下来才可以发正常需要的命令。
> 由于原生Linux内核不支持动态调整I2C的时钟频率,所以建议I2C时钟频率固定在100K,这样只需要通过I2C发送0x00就可以满足唤醒时序了。

由于软件的依赖关系比较复杂,强烈推荐使用Buildroot构建工具,其中已经支持了大部分的依赖库,比如openssl, openssl-engine, libp11, p11-kit, gnutls, libffi, libtasn1等。

## 2. 安装交叉编译工具

有两种方式安装编译工具链。

### 1. 使用apt自动安装
```shell
$ sudo apt-get install gcc-arm-linux-gnueabi
```

### 2. 使用buildroot搭建编译工具链

两种方式:
- 从buildroot源码自行构建工具链
- 安装Buildroot的SDK

通常如果需要自行定义目标板的运行库和相关工具时,需要按照需求配置目标板的运行环境。建议自行搭建builroot工具链。具体参考buildroot相关文档。

或者直接复制SDK安装文件到需要的目录下,运行解压命令即可。
解压后进入目录,运行一个shell脚本重定向编译环境。

命令如下
```shell
$ tar xzvf arm-buildroot-linux-gnueabi_sdk-buildroot.tar.gz
$ cd arm-buildroot-linux-gnueabi_sdk-buildroot
$ ./relocate-sdk.sh
```

## 3. 下载编译支持pkcs11的Cryptoauthlib库

我们需要支持pkcs11的版本, 在v3.3.0和之后的版本中,已经集成了pkcs11的功能,所以不需要专门下载这个pkcs11分支。

### 1. 获取cryptoauthlib最新版本
```shell
$ git clone https://github.com/MicrochipTech/cryptoauthlib
```
由于国内网络访问github比较慢,可以用下面的备用库
```shell
$ git clone https://gitee.com/flyerink/cryptoauthlib
```

### 2. 在源码目录下建立cmake交叉编译工具链文件arm_toolchain.cmake,具体路径需要根据自己的编译环境修改。
1. 使用gcc-arm-linux-gnueabi工具链时
```
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(tools /usr)

SET(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabi-g++)
SET(CMAKE_LINKER ${tools}/bin/arm-linux-gnueabi-ld)
SET(CMAKE_NM ${tools}/bin/arm-linux-gnueabi-nm)
SET(CMAKE_OBJCOPY ${tools}/bin/arm-linux-gnueabi-objcopy)
SET(CMAKE_OBJDUMP ${tools}/bin/arm-linux-gnueabi-objdump)
SET(CMAKE_RANLIB ${tools}/bin/arm-linux-gnueabi-ranlib)
```
2. 使用buildroot工具链时
```
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(tools /opt/arm-buildroot-linux-gnueabi_sdk-buildroot)

SET(CMAKE_C_COMPILER ${tools}/bin/arm-buildroot-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER ${tools}/bin/arm-buildroot-linux-gnueabi-g++)
SET(CMAKE_LINKER ${tools}/bin/arm-buildroot-linux-gnueabi-ld)
SET(CMAKE_NM ${tools}/bin/arm-buildroot-linux-gnueabi-nm)
SET(CMAKE_OBJCOPY ${tools}/bin/arm-buildroot-linux-gnueabi-objcopy)
SET(CMAKE_OBJDUMP ${tools}/bin/arm-buildroot-linux-gnueabi-objdump)
SET(CMAKE_RANLIB ${tools}/bin/arm-buildroot-linux-gnueabi-ranlib)
```

### 3. 测试程序中默认的I2C地址和序号
进入lib/atca_cfgs.c, 默认608A的I2C地址是0xC0, 使用Linux系统中的i2c-2设备。

如果不知道自己的板上使用的是哪个i2c时,可以用i2cdetect来检测下:
```shell
$ i2cdetect -l   #查看系统已安装的 I2C 总线列表
$ i2cdetect -y -r 1    #查询i2c-1上的设备
   0123456789abcdef
00: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
```
注意这里的I2C是7位地址表示,0xC0应该是0x60。

### 4. 编译生成ARM下的二进制可执行文件
```shell
$ mkdir build
$ cd build
$ cmake -DCMAKE_TOOLCHAIN_FILE="../arm_toolchain.cmake" -DBUILD_TESTS=ON -DATCA_PKCS11=ON -DATCA_HAL_I2C=ON -DATCA_HAL_KIT_HID=OFF -DATCA_HAL_KIT_CDC=OFF -DATCA_TNGTLS_SUPPORT=ON -DATCA_TFLEX_SUPPORT=ON -DATCA_USE_ATCAB_FUNCTIONS=OFF -DATCA_PRINTF=ON ..
$ make
```
编译生成动态链接库和测试程序。

编译选项的说明:
- BUILD_TESTS:这里已经把BUILD_TESTS打开了,会自动编译生成测试程序,对当前的硬件用命令行的方式访问。可以用来验证硬件是否有问题。
- ATCA_PKCS11:我们是要编译用于PKCS11的链接库,必须打开。
- ATCA_HAL_I2C:如果使用I2C的HAL驱动需要开启,通常是针对带有I2C接口的目标板。
- DATCA_HAL_KIT_HID:使用USB-HID作为通信接口,通常Microchip提供的开发板都支持这种方式,包括DM320118, DM320109和AT88CK101等。
- ATCA_HAL_KIT_CDC:用于USB To UART的开发板连接。
- ATCA_PRINTF:如果想使用库中提供的atca_printf相关函数,可以把ATCA_PRINTF打开。

可以使用file命令检验生成的测试程序是ARM平台的二进制文件
```shell
$ file test/cryptoauth_test
test/cryptoauth_test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 5.4.0, with debug_info, not stripped
```

### 5. 复制可执行文件和生成的库以及配置文件到开发板中:
注意要修改成自己目标板的IP地址
```shell
$ scp cryptoauthlib.conf root@192.168.1.101:/etc/cryptoauthlib
$ scp ../app/pkcs11/slot.conf.tmpl root@192.168.1.101:/var/lib/cryptoauthlib
$ scp lib/libcryptoauth.so root@192.168.1.101:/usr/lib
$ scp test/cryptoauth_test root@192.168.1.101:/root
```

## 4. 运行并测试
通过SSH或串口登录到目标板,运行新下载的可执行程序cryptoauth_test。
由于板子上使用的不是默认的i2c-2, 而是用的i2c-1设备,所以命令中需要用-i i2c 1来指定接口序号。

### 1. 单命令行模式
运行info获取器件的版本信息
```shell
$ ./cryptoauthlib_test info -d ecc608 -i i2c 1 -a 0xC0
revision:
00 00 60 02
```
运行sernum获取器件的序列号
```shell
$ ./cryptoauthlib_test sernum-d ecc608 -i i2c 1 -a 0xC0
serial number:
01 23 EE 52 4A 06 FA 85 EE
```

### 2. 交互式模式
```shell
# 运行程序进入交互式命令模式
$ ./cryptoauthlib_test

# 打印帮忙信息,列出全部命令
$ help
Usage:
help - Display Menu
sha204 - Set Target Device to ATSHA204A
sha206 - Set Target Device to ATSHA206A
ecc108 - Set Target Device to ATECC108A
ecc204 - Set Target Device to ECC204
ecc508 - Set Target Device to ATECC508A
ecc608 - Set Target Device to ATECC608
ta100 - Set Target Device to TA100
info - Get the Chip Revision
sernum - Get the Chip Serial Number
rand - Generate Some Random Numbers
readcfg - Read the Config Zone
lockstat - Zone Lock Status
tng - Run unit tests on TNG type part.
wpc - Run unit tests on WPC type part.
basic - Run Basic Test on Selected Device
util - Run Helper Function Tests
clkdivm0 - Set ATECC608 to ClockDivider M0(0x00)
clkdivm1 - Set ATECC608 to ClockDivider M1(0x05)
clkdivm2 - Set ATECC608 to ClockDivider M2(0x0D)
cd - Run Unit Tests on Cert Data
cio - Run Unit Test on Cert I/O
crypto - Run Unit Tests for Software Crypto Functions
jwt - Run JWT support tests
config - Create testing handles in TA100 device
handles - Print info for stored handles in TA100 device
clear - Delete Handles
talib - Run talib tests
power - Change device power state
exit - Exit the test application

# 指定使用的器件型号,这里是ecc608
$ ecc608

# 运行info获取器件的版本信息
$ info -d ecc608 -i i2c 1 -a 0xC0
revision:
00 00 60 02

# 运行sernum获取器件的序列号
$ sernum -d ecc608 -i i2c 1 -a 0xC0
serial number:
01 23 EE 52 4A 06 FA 85 EE
```

## 5. 在应用层代码中调用API
根据自己目标板的设置来修改器件信息:

我们使用的SAM9X60开发板,608A是连接在i2c-1上, I2C时钟是100K, 所以修改如下:
```c
/** \brief configuration for an ECCx08A device */
ATCAIfaceCfg cfg_ateccx08a_i2c = {
    .iface_type               = ATCA_I2C_IFACE,
    .devtype                  = ATECC608A,
    {
      .atcai2c.slave_address= 0xC0,
      .atcai2c.bus            = 1,
      .atcai2c.baud = 100000,
    },
    .wake_delay               = 1500,
    .rx_retries               = 20
};

int main(int argc, char* argv[])
{
      ATCA_STATUS status;

      // Inititalize CryptoAuthLib
      status = atcab_init (&cfg_ateccx08a_i2c);
      if (status != ATCA_SUCCESS) {
            printf ("Fail...\r\n");
            return status;
      }
      
      // Call other APIs
      
      atcab_release();
      return status;
}
```

稳稳の幸福 发表于 2023-4-9 11:20

一直没玩过,这个。

onlycook 发表于 2023-5-9 14:49

高大上的赶脚啊

chenqianqian 发表于 2023-7-3 21:01

牛X,表示没有玩过。

jhcj2014 发表于 2023-7-25 08:08

这些有什么用处吗?

麦小播 发表于 2023-8-28 17:10

小播赶脚是不是可以搬去微信和微博?

玛尼玛尼哄 发表于 2023-8-30 19:35

挺好的一套解决方案。

玛尼玛尼哄 发表于 2023-8-30 19:35

挺好的一套解决方案。

单片小菜 发表于 2023-9-9 11:05

onlycook 发表于 2023-5-9 14:49
高大上的赶脚啊

是的

起飞的龙D 发表于 2023-12-25 13:59

感觉挺复杂的,还不如直接安装一个windows

forgot 发表于 2023-12-28 10:42

看着挺复杂的,没接触过这种

CoolSilicon 发表于 2024-3-26 10:37

在Microchip university上面有一节课,https://mu.microchip.com/ip-production-atsha20xip-sec3-sc
可以参考一下.
页: [1]
查看完整版本: 在Linux下交叉编译Cryptoauthlib到ARM平台下