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上的设备
0 1 2 3 4 5 6 7 8 9 a b c d e f
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;
}
``` |