10.3 CAAM Job Ring后端驱动规范
CAAM作业环后端驱动(caam_jr)实现并使用作业环接口(JRI)向CAAM引擎提交来自前端驱动(caamalg, caamhash, caampkc, caamrng, caamkeyblob)的加密API服务请求。
CAAM驱动程序有几个选项,最显著的是硬件工作环大小和中断合并。它们可以用于对特定用例的性能进行微调。
Freescale CAAM作业环驱动后端选项启用作业环后端(caam_jr)。子选项Job Ring Size允许用户选择硬件作业环的大小。如果请求以突发的方式到达驱动队列入口点,则突发的最大长度可以近似。用户可以设置最大突发长度,以保存性能和内存消耗。
作业环中断合并子选项允许用户选择使用硬件的中断合并特性。注意,驱动程序已经在软件中执行了IRQ合并,如果关闭这个选项,零损失基准测试实际上产生了更好的结果。如果选中,另外两个选项将生效:
作业环中断合并计数阈值(CRYPTO_DEV_FSL_CAAM_INTC_THLD)设备驱动程序。选择描述符补全阈值,范围为1-256。选择1有效地破坏了合并特性,任何等于或大于所选环大小的选择将强制每个中断超时。
•作业环中断合并计时器阈值(CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD)选择64个CAAM接口时钟倍数的完成超时阈值,如果在此窗口内没有新的描述符完成(并且至少有一个已完成的作业正在等待完成),则将发生中断。取值范围为1-65535。
分别注册到Crypto API和hwrng API的选项,允许前端驱动程序将其算法能力注册到相应的API。只有当目的是在软件中(在GPPs上)执行Crypto API请求,而不是在CAAM引擎上卸载它们时,才应该取消选择它们。
Caamhash前端(散列算法)可以单独关闭,因为应用程序的性质可能是这样的,它更喜欢软件(核心)加密延迟,这是由于许多小的请求。
如果需要,也可以关闭Caampkc前端(公钥/非对称算法)。
caamrng frontend(随机数生成)可能被关闭,如果有一个可供内核使用的备用熵源。
Caamkeyblob前端(支持标记键的算法)可以关闭,如果标记键或blob不使用。
10.3.1验证驱动程序的正确性
除了注意加密卸载带来的性能优势外,还可以通过在dmesg中查找驱动程序消息来确保硬件正在进行加密。驱动程序在初始化时发出控制台消息:
[ 1.830397] caam 30900000.crypto: device ID = 0x0a16040100000000 (Era 9)
[ 1.837113] caam 30900000.crypto: job rings = 2, qi = 0
[ 1.849949] caam algorithms registered in /proc/crypto
[ 1.855972] caam 30900000.crypto: caam pkc algorithms registered in /proc/crypto
[ 1.865564] caam_jr 30901000.jr: registering rng-caam
[ 1.870766] Device caam-keygen registered
如果日志中没有消息,要么是内核中没有配置驱动程序,要么是设备树中没有与CAAM兼容的设备树节点。
10.3.2在/proc/interrupts中增加irq
给定发出加密请求的一段时间,CAAM硬件将在相应的Job Ring上触发完成通知中断:
root@imx8qxpmek:~# cat /proc/interrupts | grep jr
418: 1059 0 0 0 GICv3 485 Level 31430000.jr2
419: 21 0 0 0 GICv3 486 Level 31440000.jr3
root@imx8qxpmek:~#
如果触发的中断数增加,则使用硬件进行加密。如果数字没有增加,那么检查正在执行的算法是否被驱动程序支持。如果支持该算法,就有可能驱动程序处于轮询模式(NAPI机制),debugfs中的硬件统计信息(入站/出站字节加密/保护-见下文)应该被监控。
10.3.3验证“self test”字段在/proc/crypto中显示“passed”
一个像下面这样的条目意味着驱动已经成功地用内核加密API注册了对算法的支持:
name : cbc(des)
driver : cbc-des-caam
module : kernel
priority : 3000
refcnt : 1
selftest : passed
internal : no
type : givcipher
async : yes
blocksize : 8
min keysize : 8
max keysize : 8
ivsize : 8
geniv : <built-in>
注意,尽管驱动支持的特定算法可能不存在测试向量,但内核会发出消息说哪些算法没有测试,并将它们标记为“通过”:
4.647985] alg: No test for authenc(hmac(sha224),ecb(cipher_null)) (authenc-hmac-sha224-ecbcipher_null-caam)
[ 4.661181] alg: No test for authenc(hmac(sha256),ecb(cipher_null)) (authenc-hmac-sha256-ecbcipher_null-caam)
[ 4.671345] alg: No test for authenc(hmac(sha384),ecb(cipher_null)) (authenc-hmac-sha384-ecbcipher_null-caam)
[ 4.681486] alg: No test for authenc(hmac(sha512),ecb(cipher_null)) (authenc-hmac-sha512-ecbcipher_null-caam)
10.4 OpenSSL卸载
SSL (Secure Socket Layer)协议是目前应用最广泛的应用协议,通过使用AES、DES、3DES等常用的加密算法对数据进行加密,保护数据在传输过程中的安全。除了加密,它还提供使用哈希/摘要算法(如SHA1和MD5)的消息认证服务。SSL广泛应用于应用web服务器(HTTP)和其他应用程序,如SMTP POP3、IMAP和代理服务器,在这些应用程序中,保护传输中的数据是数据完整性的关键。SSL协议有多种版本,如TLSv1.0、TLSv1.1、TLSv1.2、TLSv1.3和DTLS(数据报TLS)。本文档描述了使用OpenSSL的i.MX平台上的NXP SSL加速解决方案:
•OpenSSL软件架构
•使用硬件卸载支持构建OpenSSL
•OpenSSL Offloading的例子
10.4.1 OpenSSL软件架构
SSL协议是作为OpenSSL中的一个库实现的——OpenSSL是Linux和BSD系统中最流行的库发行版。OpenSSL库有几个子组件,比如:
•SSL协议库
•SSL协议库加密库(对称和非对称密码支持,摘要支持等)
•证书管理
下图展示了OpenSSL的通用互连架构。每个相关层都以Linux用户空间和Linux内核空间之间的明确分离来表示。
10.4.2 OpenSSL的引擎接口
OpenSSL加密库提供对称和非对称(PKI)密码支持,广泛用于各种应用程序,如OpenSSH、OpenVPN、PGP、IKE和XML-SEC。OpenSSL加密库提供以下软件支持:
•密码算法
•摘要算法
•随机数生成
•公钥基础设施
除了软件支持之外,OpenSSL还可以通过引擎接口将这些功能卸载到硬件加速器。引擎接口提供回调钩子,将硬件加速器与加密库集成在一起。回调钩子提供与硬件加速器接口的粘合逻辑。密码和摘要算法的通用卸载通过Linux内核可以使用cryptodev引擎。
10.4.3用于OpenSSL硬件卸载的NXP解决方案
在NXP的OpenSSL硬件卸载解决方案中可以看到以下几层:
•OpenSSL(用户空间):实现SSL协议
• cryptodev-engine(用户空间):实现OpenSSL引擎接口;与cryptodev-linux (/dev/crypto)对话通过IOCTL,卸载内核中的加密操作
•cryptodev-linux(内核空间):将来自cryptodev引擎的ioctl请求转换为对linux加密API的调用的linux模块
• AF_ALG是基于内核异步接口的网络链接,它添加了2.6.38中引入的AF_ALG地址系列。
•Linux加密API(内核空间):Linux内核加密抽象层
•CAAM驱动程序(内核空间):用于CAAM加密引擎的Linux设备驱动程序
以下是当前BSP中的硬件卸载:
•对称加密操作-AES(CBC、ECB)、3DES(CBC、ECB)
•摘要操作-SHA(1, 256, 384, 512),MD5
•公钥操作-RSA签名(1k、2k、4k)/RSA验证(1k、2k、4k)
10.4.4将OpenSSL部署到rootfs中
通常,imx-image-full包括OpenSSL和cryptodev模块,但对于其他Yocto目标,用户需要从构建目录更新conf文件。更新conf/local.conf通过添加以下行进行:
CORE_IMAGE_EXTRA_INSTALL+="cryptodev-module openssl-bin"
重新启动生成过程:
bitbake imx-image-full
10.4.5使用cryptodev引擎运行OpenSSL基准测试
探测cryptodev模块:
root@imx8qxpmek:~# modprobe cryptodev
[17044.896494] cryptodev: driver 1.10 loaded.
root@imx8qxpmek:~# openssl engine
(devcrypto) /dev/crypto engine
(dynamic) Dynamic engine loading support
root@imx8qxpmek:~#
10.4.5.1为对称加密和摘要运行OpenSSL基准测试
在速度测试文件中,进行了一系列性能测试,以检查对称和摘要操作的性能。
OpenSSL测试执行中描述了以下内容:
root@imx8qxpmek:~# openssl speed -engine devcrypto -multi 8 -elapsed -evp aes-128-cbc
Forked child 1
engine "devcrypto" set.
Forked child 2
engine "devcrypto" set.
...
Got: +F:22:aes-128-cbc:378616.72:1611328.00:5084501.33:13994666.67:10731793.98:16219060.40 from 6
Got: +H:16:64:256:1024:8192:16384 from 7
Got: +F:22:aes-128-cbc:120773.33:9344.00:3088298.67:13588480.00:31642965.33:16471967.79 from 7
OpenSSL 1.1.1b 26 Feb 2019
built on: Thu Nov 14 13:22:07 2019 UTC
options:bn(64,64) rc4(char) des(int) aes(partial) idea(int) blowfish(ptr)
compiler: aarch64-poky-linux-gcc --sysroot=recipe-sysroot -O2 -pipe -g -feliminate-unused-debugtypes -fmacro-prefix-map=
-fdebug-prefix-map= -fdebug-prefix-map= -fdebug-prefix-map= -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -
DOPENSSL_CPUID_OBJ -DOPENSSL_BN_ASM_MONT
-DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM
-DNDEBUG
evp 2242.05k 9681.05k 35017.46k 106866.86k 127787.74k 130077.23k
root@imx8qxpmek:~#
可以进行基准测试的其他密码:aes-192-cbc、aes-256-cbc、aes-128-ecb、aes-192-ecb、aes-256-ecb,
aes-128-ctr、aes-192-ctr、aes-256-ctr、des cbc、des cbc、des-ede3-cbc。
可以进行基准测试的其他摘要:sha1、SH224、SH256、SH384、SH512、md5。
10.4.6使用AF_ALG引擎运行OpenSSL基准测试
执行以下命令:
Probe the af_alg:
root@imx8mmevk:~# rmmod cryptodev
root@imx8mmevk:~# modprobe af_alg
root@imx8mmevk:~# modprobe algif_hash
root@imx8mmevk:~# modprobe algif_skcipher
root@imx8mmevk:~# modprobe algif_rng
root@imx8mmevk:~# modprobe algif_aead
10.4.6.1为对称加密和摘要运行OpenSSL基准测试
执行以下命令:
root@imx8mmevk:~# openssl speed -engine afalg -multi 8 -elapsed -evp aes-128-cbc
Forked child 0
Forked child 1
engine "afalg" set.
+DT:aes-128-cbc:3:16
engine "afalg" set.
engine "afalg" set.
engine "afalg" set.
...
Got: +H:16:64:256:1024:8192:16384 from 0
Got: +F:22:aes-128-cbc:333888.00:1359317.33:4248405.33:5720064.00:6160384.00:6176768.00 from 0
Got: +H:16:64:256:1024:8192:16384 from 1
Got: +F:22:aes-128-cbc:378336.00:1382826.67:5117269.33:5739178.67:6190421.33:6176768.00 from 1
...
OpenSSL 1.1.1k 25 Mar 2021
built on: Thu Mar 25 13:28:38 2021 UTC
options:bn(64,64) rc4(char) des(int) aes(partial) blowfish(ptr)
compiler: aarch64-poky-linux-gcc -mcpu=cortex-a53 -march=armv8-a+crc+crypto -fstack-protectorstrong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=recipesysroot -O2 -pipe -g -feliminate-unused-debug-types -fmacro-prefix-map= -fdebugprefix-map= -fdebug-prefix-map= -fdebug-prefix-map= -
DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM
-DSHA512_ASM -DKECCAK1600_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DNDEBUG
evp 2682.45k 10842.73k 35957.50k 45915.48k 49722.71k 50135.04k
10.5硬盘加密加速
磁盘加密是一种通过将信息转换成不可读的代码来保护信息的技术,未经授权的人无法轻易破译这些代码。磁盘加密使用磁盘加密软件或硬件对磁盘或磁盘卷上的每一位数据进行加密。用于防止未经授权的访问数据存储。在i.MX应用处理器上,磁盘加密场景可以通过不同的密钥保护方法以不同的方式实现。
本节提供了使用DM-Crypt在块级别运行透明存储加密的步骤。下图展示了实现磁盘加密的软件栈。
10.5.1在内核中启用磁盘加密支持
默认情况下,内核配置文件将Device Mapper配置和Crypt Target支持作为模块启用。因此,为了启用硬盘加密场景,在单板启动后,需要插入以下模块:
root@imx8mqevk:/# modprobe dm-mod
[ 266.982638] device-mapper: ioctl: 4.41.0-ioctl (2019-09-16) initialised: [email protected]
root@imx8mqevk:/# modprobe dm-crypt
root@imx8mqevk:/# dmsetup targets
crypt v1.19.0
striped v1.6.0
linear v1.4.0
error v1.5.0
如果不启用磁盘加密场景,需要启用内核中的一些特性:
10.5.2用于硬盘加密的用户空间工具
当使用Linux i.MX BSP时,DM-Crypt所需的所有用户空间工具都已经安装在板上。
如果构建中没有安装所需的用户空间工具,可以通过编辑conf/local.conf文件并添加:
CORE_IMAGE_EXTRA_INSTALL+=“coreutils keyutils lvm2 e2fsprogs-mke2fs utillinux”
•keyutils:提供keyctl,用于管理Linux密钥保留服务。
•lvm2:提供dmsetup实用程序和库来管理设备映射器。
•e2fsprogs-mke2fs:包含创建文件系统所需的工具。
•util-linux:提供从卷读取扇区数量所需的blockdev实用程序。
10.5.3 DM-Crypt使用CAAM的标记键
在Linux Unified Key Setup (LUKS)模式中,要生成磁盘加密密钥(主密钥),用户需要提供一个密码短语,该密码短语与一个salt组合在一起,然后为提供的轮数应用一个哈希函数。当用户想要挂载一个加密卷时,应该提供密码短语。另一种方法是提供一个存储在包含必要解密信息的外部驱动器中的密钥文件。这些方法对于嵌入式设备的使用并不方便。
将DM-Crypt与CAAM的标记密钥一起使用的目的是抑制使用从用户提供的密码短语派生的密钥加密主卷密钥的机制。DM-Crypt还可以利用带标签的密钥来保护存储卷不被脱机解密。此外,只有在保险丝中烧有相同OTPMK的设备才能打开音量。有关详细信息,请参阅特定SoC的安全参考手册。
标记密钥特性基于CAAM的黑密钥机制。黑键保护用户键不受总线窥探,当键被写入或从SoC外部内存读取时。CAAM支持AES-ECB和AES-CCM两种不同的黑密钥封装方案。
对于AES-ECB加密,数据长度是16字节的倍数,用于快速解密。
AES-CCM模式不如AES-ECB模式快,但是它包含一个“MAC标记”(完整性检查值),可以确保被封装键的完整性。ccm加密的黑密钥总是比被封装的密钥(nonce值+ MAC标记)长至少12字节。
黑键是会话键;因此,它们不是电力循环安全的。CAAM的blob机制提供了一种跨系统电源周期保护用户定义数据的方法。它提供机密性和完整性保护。要保护的数据是加密的,以便它可以在SoC断电前安全地放入非易失性存储。
下图说明了为支持使用带标记的密钥进行全磁盘加密而添加的更改。CAAM驱动程序在内核中注册新的加密转换,以使用ECB和CBC黑密钥tk(ECB (aes))和tk(CBC (aes))。tk前缀指的是Tagged Key。
Tagged Key是一个黑键,包含指示它是什么以及如何处理它的元数据。
Linux OS提供了一个名为Keyrings的内核密钥管理和保留工具。Keyring还允许接口访问密钥,并从用户空间执行添加、更新和删除等操作。
内核提供了几种基本类型的密钥,包括密匙环、用户和登录。
CAAM驱动程序关联了一个用户空间应用程序,用于生成带标记的键,并将其封装到一个黑色blob中。
这也用于从黑色blob导入带标记的键。
$ ./caam-keygen
CAAM keygen usage: caam-keygen [options]
Options:
create <key_name> <key_enc> <key_mode> <key_val>
<key_name> the name of the file that will contain the black key.
A file with the same name, but with .bb extension, will contain the black blob.
<key_enc> can be ecb or ccm
<key_mode> can be -s or -t.
-s generate a black key from random with the size given in the next argument
-t generate a black key from a plaintext given in the next argument
<key_val> the size or the plaintext based on the previous argument (<key_mode>)
import <blob_name> <key_name>
<blob_name> the absolute path of the file that contains the blob
<key_name> the name of the file that will contain the black key.
默认情况下,键和blob是在KEYBLOB_LOCATION中创建的,它是/data/caam/。
随后,CAAM Tagged Key被添加到Linux Key Retention服务中,并由keyctl等用户空间应用程序管理。
黑色blob可以存储在任何非易失性存储器上。
Dmsetup (libdevmapper包的一部分)是一个强大的工具,用于执行非常低级的配置,并用于管理加密的卷。
10.5.4用法
以下是在i.MX设备上执行全磁盘加密的步骤。
root@imx8mqevk:~# grep -B1 -A2 tk- /proc/crypto|grep -v kernel
name : tk(ecb(aes))
driver : tk-ecb-aes-caam
priority : 3000
--
name : tk(cbc(aes))
driver : tk-cbc-aes-caam
priority : 3000
root@imx8mqevk:~#
和camam -keygen应用程序是可用的:
root@imx8mmevk:~# cd /; find -name "caam-keygen"
./usr/bin/caam-keygen
./dev/caam-keygen
./sys/class/misc/caam-keygen
./sys/devices/virtual/misc/caam-keygen
目前,我们只支持AES算法。因此,用于加密/解密的密钥的大小为16、24和32字节。
2. 确保DM-Crypt已启用。
root@imx8mqevk:~# dmsetup targets
crypt v1.19.0
striped v1.6.0
linear v1.4.0
error v1.5.0
如果缺少上述任何一项,请检查内核配置或查看在内核中启用磁盘加密支持一节。
3.然后,为设备提供它的密钥,即黑密钥,它可以从定义的普通密钥创建,也可以随机创建。
下面是一个用ECB加密的黑密钥的例子,它来自一个大小为16字节的明文:
root@imx8mqevk:~# ./caam-keygen create fromTextkey ecb -t 0123456789abcdef
结果是一个Tagged Key和一个写入文件系统的Blob文件(默认位置是/data/caam)。使用的密钥加密方案是ECB。
root@imx8mqevk:~# ls -la /data/caam/
total 16
drwxr-xr-x 2 root root 4096 Aug 25 15:38 .
drwxr-xr-x 3 root root 4096 Aug 25 15:38 ..
-rw-r--r-- 1 root root 36 Aug 25 15:38 fromTextkey
-rw-r--r-- 1 root root 96 Aug 25 15:38 fromTextkey.bb
接下来,使用keyctl在密钥保留服务中添加密钥:
root@imx8mqevk:~# cat /data/caam/fromTextkey | keyctl padd logon logkey: @s
876928653
root@imx8mqevk:~# dd if=/dev/zero of=encrypted.img bs=1M count=32
32+0 records in
32+0 records out
33554432 bytes (34 MB, 32 MiB) copied, 3.20227 s, 10.5 MB/s
root@imx8mqevk:~#
root@imx8mqevk:~# losetup /dev/loop0 encrypted.img
root@imx8mqevk:~#
root@imx8mqevk:~# dmsetup -v create encrypted --table "0 $(blockdev --getsz /dev/loop0) crypt
capi:tk(cbc(aes))-plain :36:logon:logkey: 0 /dev/loop0 0 1 sector_size:512"
Name: encrypted
State: ACTIVE
Read Ahead: 256
Tables present: LIVE
Open count: 0
Event number: 0
Major, minor: 253, 0
Number of targets: 1
下面是映射表的细分:
•start表示加密从0扇区开始。
•size是扇区中卷的大小。
•blockdev获取设备扇区的数量。
•目标是crypt。
•cipher设置为Kernel Crypto API格式,使用Tagged Key。cipher设置为capi:tk(cbc(aes))-plain和密钥设置为:36:logon:logkey:导致使用CAAM标记密钥转换的登录密钥。
•IV是初始化向量,定义为普通的初始向量,它是扇区号的32位小端版本,必要时用零填充。
•“key type”为Keyring密钥服务类型,选择“Logon key”,36为密钥大小,单位为字节。
•key name是键描述,用来识别要加载的键。
•IV offset是要加到扇区号上计算IV值的值。
•device是到device的路径,device被用作后端;它包含加密的数据。
•offset表示从设备扇区0开始的加密数据。
•optional parameters表示可选参数的数量。
•sector_size指定加密扇区大小。
要获得更详细的选项和描述,请参阅https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMCrypt。
创建的设备出现在/dev/mapper中:
root@imx8mqevk:~# dmsetup table --showkey encrypted
0 65536 crypt capi:tk(cbc(aes))-plain :36:logon:logkey: 0 7:0 0
root@imx8mqevk:~# mkfs.ext4 /dev/mapper/encrypted
mke2fs 1.45.3 (14-Jul-2019)
Creating filesystem with 32768 1k blocks and 8192 inodes
Filesystem UUID: 3ba01ad8-ba03-4389-a955-5136b3173c35
Superblock backups stored on blocks:
8193, 24577
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information:l done
root@imx8mqevk:~# mkdir /mnt/encrypted
root@imx8mqevk:~# mount -t ext4 /dev/mapper/encrypted /mnt/encrypted/
[ 9409.936183] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: (null)
[ 9409.943892] ext4 filesystem being mounted at /mnt/encrypted supports timestamps until
2038 (0x7fffffff)
root@imx8mqevk:~# echo "This is an encrypt with black key (ECB from text 16 bytes key size) test of full disk encryption on i.MX" > /mnt/encrypted/readme.txt
root@imx8mqevk:~# umount /mnt/encrypted/
root@imx8mqevk:~# dmsetup remove encrypted
root@imx8mqevk:~# reboot
...
root@imx8mqevk:~#
root@imx8mqevk:~# ./caam-keygen import /data/caam/fromTextkey.bb importKey
root@imx8mqevk:~# cat /data/caam/importKey | keyctl padd logon logkey2: @s
605536287
root@imx8mqevk:~# ls -la /data/caam/
total 20
drwxr-xr-x 2 root root 4096 Aug 25 15:47 .
drwxr-xr-x 3 root root 4096 Aug 25 15:38 ..
-rw-r--r-- 1 root root 36 Aug 25 15:38 fromTextkey
-rw-r--r-- 1 root root 96 Aug 25 15:38 fromTextkey.bb
-rw-r--r-- 1 root root 36 Aug 25 15:47 importKey
root@imx8mqevk:~#
root@imx8mqevk:~# losetup /dev/loop0 encrypted.img
root@imx8mqevk:~#
root@imx8mqevk:~# dmsetup -v create encrypted --table "0 $(blockdev --getsz /dev/loop0) crypt
capi:tk(cbc(aes))-plain :36:logon:logkey2: 0 /dev/loop0 0 1 sector_size:512"
Name: encrypted
State: ACTIVE
Read Ahead: 256
Tables present: LIVE
Open count: 0
Event number: 0
Major, minor: 253, 0
Number of targets: 1
root@imx8mqevk:~# mount /dev/mapper/encrypted /mnt/encrypted/
[ 191.961828] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: (null)
[ 191.969533] ext4 filesystem being mounted at /mnt/encrypted supports timestamps until
2038 (0x7fffffff)
root@imx8mqevk:~
root@imx8mqevk:~# cat /mnt/encrypted/readme.txt
This is an encrypt with black key (ECB from text 16 bytes key size) test of full disk
encryption on i.MX.
root@imx8mqevk:~#
root@imx8mqevk:~# umount /mnt/encrypted/; dmsetup remove encrypted
10.6 crypto_af_alg应用程序支持
10.6.1先决条件
需要camam -keygen应用程序从黑色blob导入黑色键。确保caam-keygen应用程序已经存在于/usr/bin中。
10.6.2构建内核
10.6.2.1内核配置
•CONFIG_CRYPTO_USER_API
•CONFIG_CRYPTO_USER_API_HASH
•CONFIG_CRYPTO_USER_API_SKCIPHER
•CONFIG_CRYPTO_USER_API_RNG
•CONFIG_CRYPTO_USER_API_AEAD
获取一个可引导映像,其中包含Linux内核的黑键支持和AF_ALG套接字接口。或者从这里构建内核:https://source.codeaurora.org/external/imx/linux-imx/。
10.6.2.2构建工具链
构建工具链来交叉编译camam-decrypt应用程序的源代码。详细信息请参见《i.MX Yocto项目用户指南(IMXLXYOCTOUG)》。
$ wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2019.01/gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz
$ tar xf gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz
10.6.2.3交叉编译用户空间源
使用前面准备的工具链设置用于交叉编译的环境。
$ export CROSS_COMPILE=<path to toolchain>/bin/aarch64-linux-gnu-
$ export CC=${CROSS_COMPILE}gcc
$ export LD=${CROSS_COMPILE}ld
$ make clean
$ make
10.6.3用法
在使用之前生成的映像成功引导设备之后,可以使用caam-decrypt对存储在文件中的加密数据进行解密。
$ ./caam-decrypt
Application usage: caam-decrypt [options]
Options:
<blob_name> <enc_algo> <input_file> <output_file>
<blob_name> the absolute path of the file that contains the black blob
<enc_algo> can be AES-256-CBC
<input_file> the absolute path of the file that contains input data
initialization vector(iv) of 16 bytes prepended
size of input file must be multiple of 16
<output_file> the absolute path of the file that contains output data
10.6.4用例
$ caam-decrypt myblob AES-256-CBC my_encrypted_file output_decrypted
这里:
•myblob:生成黑键blob。caam-keygen应用程序从黑色blob导入一个黑色键。该黑密钥被CAAM用于解密。
•AES-256-CBC:目前唯一支持的用于解密操作的对称算法。确保加密数据必须使用相同的算法。
•my_encrypted_file:保存在文件中的加密数据。加密过程中使用的初始化向量(iv)为16字节,必须预先添加到加密数据中。
AES Encrypted file format
16 Octets - Initialization Vector (IV) is an input to encryption algorithm.
nn Octets - Encrypted message (for AES-256-CBC, it must be multiple of 16)
•output_decrypted:表示解密成功后,已解密的数据。
10.7内核TLS卸载
Linux内核提供TLS连接卸载基础架构。一旦TCP连接处于ESTABLISHED状态,用户空间就可以启用TLS Upper Layer Protocol (ULP)并安装加密连接状态。关于面向用户的界面,请参考内核TLS中的TLS文档。
10.7.1先决条件
使用以下命令检查OpenSSL版本。它必须是3.0.0或更高。
openssl version
10.7.2运行内核TLS测试
在服务器端生成RSA 2048密钥、证书,并运行openssl s_server:
root@imx8mmevk:~# openssl req -new -newkey rsa:2048 -nodes -keyout rsa.key -out rsa.csr
root@imx8mmevk:~# openssl x509 -req -sha256 -days 365 -in rsa.csr -signkey rsa.key -out server.pem
root@imx8mmevk:~# openssl s_server -key rsa.key -cert server.pem -accept 443 -ssl_config ktls
Using default temp DH parameters
ACCEPT
在其他终端运行openssl s_client:
root@imx8mmevk:~# openssl s_client -quiet -connect :443 -tls1_2 -ssl_config ktls -
cipher 'ECDHE-RSA-AES256-GCM-SHA384'
Connecting to <server ip>
Can't use SSL_get_servername
...
Using Kernel TLS for sending
Using Kernel TLS for receiving
<write some message and enter>
删除-quiet以查看完整的客户端日志。使用TLSv1.2,内核TLS支持以下密码:
•AES128-GCM-SHA256
•AES256-GCM-SHA384
•ECDHE-RSA-AES128-GCM-SHA256
•ECDHE-RSA-AES256-GCM-SHA384
第十一章 连接
本节介绍蓝牙无线技术和Wi-Fi,以及USB type-C的连接。
11.1蓝牙无线技术和Wi-Fi的连接
通过板载芯片解决方案和外部硬件,i.MX支持蓝牙和Wi-Fi。下表列出了各种板载芯片和外部解决方案。
无线驱动支持wpa_supplicant, wpa_supplicant是一个WEP/WPA/WPA2/WPA3加密认证工具。
•Wi-Fi驱动:支持基于NXP 88w8987的SDIO接口模块、基于PCIe和SDIO接口模块、基于NXP SDIO 88w8997的模块、基于NXP LBEE6ZZ-1TA的模块、基于iw416的SDIO接口模块、基于NXP 88w8801的SDIO接口模块。
•固件
NXP发布包已经包含了所有的NXP、Wi-Fi/蓝牙固件。它需要接受NXP的许可证。
要运行Wi-Fi,请先执行以下命令,然后再执行以下常用命令:
•对于以下步骤,使用connman执行这些命令
modprobe moal mod_para=nxp/wifi_mod_para.conf
$connmanctl
connmanctl> enable wifi
connmanctl> scan wifi
connmanctl> services /* This should list of the network. For
example wifi_c0e4347f5053_4a62726f_managed_psk*/
connmanctl> agent on
connmanctl> connect wifi_c0e4347f5053_4a62726f_managed_psk /* Enter Passphrase */
Agent RequestInput wifi_c0e4347f5053_4a62726f_managed_psk
Passphrase = [ Type=psk, Requirement=mandatory ]
Passphrase?
connmanctl> quit
使用BlueZ栈运行NXP蓝牙,执行以下命令(需要先加载Wi-Fi来加载蓝牙固件):
# For PCIe9098 and SDIO9098:
hciattach <device> any -s 3000000 3000000 flow
hciconfig hci0 up
# For For PCIe8997/SDIO8997/SDIO8987 and SDIO IW416:
hciattach <device> any 115200 flow
hciconfig hci0 up
hcitool -i hci0 cmd 0x3f 0x0009 0xc0 0xc6 0x2d 0x00
killall hciattach
hciattach <device> any -s 3000000 3000000 flow
hciconfig hci0 up
执行以下命令连接所有芯片的蓝牙设备:
$ bluetoothctl
[bluetooth]# default-agent
[bluetooth]# agent on
[bluetooth]# scan on
[bluetooth]# pair xx:xx:xx:xx:xx:xx
[BT dev]# connect xx:xx:xx:xx:xx:xx
[BT dev]# quit
i.MX 6单板需要返工,以支持蓝牙/Wi-Fi,并与蓝牙/Wi-Fi设备树运行。下面列出了所需的硬件修改以及这些修改可能导致的冲突。
•i.MX 6QuadPlus/Quad/Dual/DualLite/Solo:参见https://community.nxp.com/docs/DOC-94235。此更改与:EPDC/SPI-NOR/GPIO-LED的引脚冲突。
•i.MX 6SoloX:安装R328,断开R327连接。连接SD2插槽和蓝牙电缆连接器J19。它与其他模块没有Pin冲突。
•i.MX 6SLL:安装R127,并再次检查确保R126和R128已安装。连接SD3插槽和蓝牙电缆连接器J4。它与其他模块没有Pin冲突。
•i.m x6ul /ULL/ULZ:安装R1701。它与其他模块没有Pin冲突。
Rework还需要支持i.MX 8M Plus的NXP PCIe 88W9098、i.MX 8M Quad的NXP SDIO 88W89997、NXP SDIO IW416、NXP SDIO 88W8801和SDIO 88W9098。
•在i.MX 8M Plus上运行NXP PCIe 88W9098,需要进行如下硬件重做:
将R452改为0欧姆。
•在i.MX 8M Quad上运行NXP SDIO 88W89997、NXP SDIO IW416、SDIO 88W8801和SDIO 88W9098,硬件重做如下:
拆卸以下0 Ω 0402电阻:R1603、R1617、R1618、R1619、R1620、R1621 (micro - SD卡J1601)
安装以下0 Ω 0402电阻:R1429、R1430、R1431、R1432、R1433、R1434、R1435、R1436 (M.2 J1401)
11.2 USB type-C连通性
下面以i.MX 8QuadXPlus MEK单板的USB type-C和电源下发连接为例进行说明。
Linux版本包括USB type-C和PD栈,默认是启用的。具体的功率参数由DTS传入。例如:fsl-imx8qxp-mek
typec_ptn5110: typec@50 {
compatible = "usb,tcpci";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_typec>;
reg = <0x50>;
interrupt-parent = <&gpio1>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
ss-sel-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
reset-gpios = <&pca9557_a 7 GPIO_ACTIVE_HIGH>;
src-pdos = <0x380190c8>;
snk-pdos = <0x380190c8 0x3802d0c8>;
max-snk-mv = <9000>;
max-snk-ma = <1000>;
op-snk-mw = <9000>;
port-type = "drp";
sink-disable;
default-role = "source";
status = "okay";
};
对于功率能力相关的配置,用户需要查看PD规范,了解如何组合PDO值。
要使其支持更多电压的电源角色,请指定电源PDO。i.MX 8QuadXPlus单板支持5v和12v电源。
•i.MX 8QuadXPlus MEK平台上Alpha和Beta版本的Linux BSP只支持5v的电源角色。
•用户可以使用/sys/kernel/debug/tcpm/2-0050查看电源下发状态,用于调试信息。
•Alpha版本不支持只通过c类型端口电源引导。
11.3 NXP蓝牙/Wi-Fi信息
NXP蓝牙/Wi-Fi信息如下:
•SoC版本:SDIO 88W8987, PCIe 88W8997, SDIO 88W8997, PCIe 88w9098, SDIO IW416, SDIO 88W8801
•SDIO W8801固件版本14.92.36.p171
•SDIO-UART IW416固件版本16.92.21.p11.2
•PCIE-UART W9098固件版本:17.92.5.p11
•SDIO-UART W8997固件版本:16.92.10.p219.5
•PCIE-UART W8997固件版本:16.92.21.p26.1
•SDIO-UART W8987固件版本:16.92.21.p26
•SDIO-UART W9098固件版本:17.92.1.p98.1
•Wi-Fi/蓝牙固件版本:16.92.10.p210
•i.MX 8QuadMax/8QuadXPlus/8M quadad /8M Mini/8M Nano: cycles, read-cycles, write-cycles
•i.MX 8M Plus: axid-read, axid-write
•i.MX 8DXL: cycles, read-cycles, write-cycles, axid-read, axid-write
12.3显示支持的事件
运行如下命令查询系统支持的事件:
# perf list pmu | grep imx8_ddr
imx8_ddr0/activate/ [Kernel PMU event]
imx8_ddr0/axid-read/ [Kernel PMU event]
imx8_ddr0/axid-write/ [Kernel PMU event]
imx8_ddr0/cycles/ [Kernel PMU event]
imx8_ddr0/hp-read-credit-cnt/ [Kernel PMU event]
imx8_ddr0/hp-read/ [Kernel PMU event]
imx8_ddr0/hp-req-nocredit/ [Kernel PMU event]
imx8_ddr0/hp-xact-credit/ [Kernel PMU event]
imx8_ddr0/load-mode/ [Kernel PMU event]
imx8_ddr0/lp-read-credit-cnt/ [Kernel PMU event]
imx8_ddr0/lp-req-nocredit/ [Kernel PMU event]
imx8_ddr0/lp-xact-credit/ [Kernel PMU event]
imx8_ddr0/perf-mwr/ [Kernel PMU event]
imx8_ddr0/precharge/ [Kernel PMU event]
imx8_ddr0/raw-hazard/ [Kernel PMU event]
imx8_ddr0/read-accesses/ [Kernel PMU event]
imx8_ddr0/read-activate/ [Kernel PMU event]
imx8_ddr0/read-command/ [Kernel PMU event]
imx8_ddr0/read-cycles/ [Kernel PMU event]
imx8_ddr0/read-modify-write-command/ [Kernel PMU event]
imx8_ddr0/read-queue-depth/ [Kernel PMU event]
imx8_ddr0/read-write-transition/ [Kernel PMU event]
imx8_ddr0/read/ [Kernel PMU event]
imx8_ddr0/refresh/ [Kernel PMU event]
imx8_ddr0/selfresh/ [Kernel PMU event]
imx8_ddr0/wr-xact-credit/ [Kernel PMU event]
imx8_ddr0/write-accesses/ [Kernel PMU event]
imx8_ddr0/write-command/ [Kernel PMU event]
imx8_ddr0/write-credit-cnt/ [Kernel PMU event]
imx8_ddr0/write-cycles/ [Kernel PMU event]
imx8_ddr0/write-queue-depth/ [Kernel PMU event]
imx8_ddr0/write/ [Kernel PMU event]
12.4监视事务的示例
本节将展示一些监视DDR事务的示例。
•对于i.MX 8QuadMax/8QuadXPlus/8M quadad /8M Mini/8M Nano:
# perf stat -a -I 1000 -e imx8_ddr0/cycles/,imx8_ddr0/read-cycles/,imx8_ddr0/write-cycles/
• For i.MX 8M Plus:
— All masters:
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_mask=0xffff/,imx8_ddr0/axidwrite,axi_mask=0xffff/
— GPU 3D:
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_id=0x70/,imx8_ddr0/axid-write,axi_id=0x70/
— LCDIF1:
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_id=0x68/,imx8_ddr0/axid-write,axi_id=0x68/
• For i.MX 8DXL:
— All masters:
# perf stat -a -I 1000 -e imx8_ddr0/cycles/,imx8_ddr0/read-cycles/,imx8_ddr0/write-cycles/
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_mask=0xffff/,imx8_ddr0/axidwrite,axi_mask=0xffff/
— USB 2.0:
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_mask=0xb0,axi_id=0x40b/,imx8_ddr0/axidwrite,axi_mask=0xb0,axi_id=0x40b/
— USDHC0:
# perf stat -a -I 1000 -e imx8_ddr0/axid-read,axi_id=0x1b/,imx8_ddr0/axid-write,axi_id=0x1b/
12.5性能指标
如果事件命令行对您来说太麻烦,那么尝试使用度量而不是事件。以下是i.m x8quadxplus上的示例。
12.5.1显示支持的度量
运行以下命令显示支持的度量值:
# perf list metric
List of pre-defined events (to be used in -e):
Metrics:
imx8qxp_bandwidth_usage.lpddr4
[bandwidth usage for lpddr4 mek board. Unit: imx8_ddr ]
imx8qxp_ddr_read.all
[bytes all masters read from ddr based on read-cycles event. Unit: imx8_ddr ]
imx8qxp_ddr_write.all
[bytes all masters wirte to ddr based on write-cycles event. Unit: imx8_ddr ]
12.5.2监控交易
运行如下命令监控事务:
# perf stat -a -I 1000 -M imx8qxp_ddr_read.all,imx8qxp_ddr_write.all
# time counts unit events
1.001115250 28264 imx8_ddr0/read-cycles/ # 441.6 KB imx8qxp_ddr_read.all
1.001115250 11622 imx8_ddr0/write-cycles/ # 181.6 KB imx8qxp_ddr_write.all
2.002718000 14496 imx8_ddr0/read-cycles/ # 226.5 KB imx8qxp_ddr_read.all
2.002718000 4585 imx8_ddr0/write-cycles/ # 71.6 KB imx8qxp_ddr_write.all
12.6 DDR性能使用汇总
建议使用度量来监视DDR事务,因为它更方便。您可以直接获得所有主机或特定主机的DDR带宽,而无需进行额外的计算。特别是在支持AXI ID过滤的平台上,不要搜索主ID。
第十三章 一次性可编程控制器驱动程序使用
NVMEM子系统
13.1介绍
一次性可编程控制器驱动程序是通过NVMEM子系统实现的,该子系统为消费设备引入DT表示,以便从NVMEMs获得它们所需的数据(MAC地址、SoC/Revision ID、零件号等)。
13.2 NVMEM provider OCOTP
使用struct nvmem_config设置nvmem设备的OCOTP配置。这个结构可以定义回调来读/写eFUSE数据。
在读/写函数原型中:
•第一个参数是OCOTP设备的私有数据,它包含一个指向重映射内存的指针。
•第二个参数来自于NVMEM消费者的属性reg中的第一个数据,这个偏移量代表OCOTP影子寄存器,一个eFuse地址被映射到它。
•第3个参数读时返回读数据,写时传递要写的数据。
•第4个参数表示要读/写多少字节,来自NVMEM消费者属性reg中的第二个数据。
typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, void *val, size_t bytes);
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, void *val, size_t bytes);
13.3 NVMEM消费者
NVMEM消费者是利用NVMEM提供程序从NVMEM读取和读取NVMEM的实体。在DTS文件中,需要将NVMEM使用者节点写入NVMEM提供者节点。不可缺少的属性是reg。第一个数据表示OCOTP影子寄存器的偏移量,它映射了一个eFuse地址。第二个数据表示要读或写的字节数。
以i.MX 8M Nano上的MAC地址为例:
reg中的第一个数据是0x90, 0x400 + 0x90 * 0x4 = 0x640, 0x640是MAC_ADDR的第一个Fuse地址。0x4表示4字节。
13.4在用户空间读写NVMEM原始文件示例
• i.MX 6/i.MX 7/i.MX 8M Mini/8M Nano/8M Plus/8M Quad
# hexdump /sys/bus/nvmem/devices/imx-ocotp0/nvmem
• i.MX 8ULP
# hexdump /sys/bus/nvmem/devices/fsb_s400_fuse1/nvmem
第14章 NXP eIQ® 机器学习
NXP eIQ机器学习软件开发环境能够在i.MX家族soc上使用机器学习算法。用于i.MX的eIQ软件包括推理引擎、用于硬件加速的优化库和一个ML安全包。
主要的eIQ工具包集成在Yocto BSP中,包含在meta-imx/meta-ml层中。目前支持的推理引擎如下:TensorFlow Lite, ONNX Runtime, OpenCV, DeepViewRTTM, PyTorch和Arm NN。关于eIQ软件开发环境的详细信息,请参阅i.MX机器学习用户指南(IMXMLUG)。
除了集成在Yocto BPS中的工具包外,还有一个单独交付的ML安全包。请参见机器学习包的安全性(AN12867)。