2024-07-02
GR5526 GUI专题(4) - Lvgl字体的位图数组合并转换为bin文件的说明
写技术文章
精选推荐
Tim
前言
本文介绍了如何使用GR551X系列芯片的安全外设模块(AES、HMAC、PKC、TRNG)对第三方安全算法库MbedTLS进行硬件加速。
目录
一、简介
1.1 MbedTLS算法集
1.2 硬件加速算法集
二、MbedTLS目录结构
三、环境搭建
3.1 添加MbedTLS源码
3.2 添加硬件加速驱动
3.3 配置MbedTLS
四、应用详解
4.1 AES硬件加速
4.2 SHA硬件加速
4.3 RSA硬件加速
4.4 ECC硬件加速
一、简介
MbedTLS(前身为PolarSSL)是一个由ARM公司开源和维护的SSL/TLS算法库。
核心SSL库是用C编程语言编写的,实现了SSL模块、基本的加密功能并提供了各种实用功能。与OpenSSL和TLS的其他实现不同,MbedTLS与wolfSSL类似,因为它被设计为适合小型嵌入式设备,最小的完整TLS堆栈需要低于60KB的程序空间和低于64KB的RAM。它也是高度模块化的:每个组件,例如加密函数,都可以独立于框架的其余部分使用。版本也可用于Microsoft Windows和Linux。因为Mbed TLS是用C编程语言编写的,没有外部依赖,所以它适用于大多数操作系统和架构。
MbedTLS遵循Apache 2.0开源许可协议,目前由TrustedFirmware(Linaro主持的一个治理开放社区项目)维护,开源仓库地址为 https://github.com/Mbed-TLS/mbedtls
1.1 Mbed TLS算法集
Mbed TLS支持多种不同的加密算法:
MD2, MD4, MD5, RIPEMD160, SHA-1, SHA-2
CMAC, HMAC
AES, ARIA, Blowfish, Camellia, ChaCha, DES, RC4, Triple DES, XTEA
ECB, CBC, CFB, CTR, OFB, XTS
CCM, GCM, NIST Key Wrap,
ChaCha20-Poly1305
HKDF
PBKDF2, PKCS #5 PBE2, PKCS #12 key derivation
RSA, Diffie–Hellman key exchange,
Elliptic curve cryptography (ECC), Elliptic curve Diffie–Hellman (ECDH), Elliptic Curve DSA (ECDSA), Elliptic curve J-PAKE
1.2 硬件加速算法集
AES-ECB-128/192/256
AES-CBC-128/192/256-None padding/PKCS7 padding/Zeros padding
AES-CTR-128/192/256
AES-CFB128-128/192/256
AES-OFB-128/192/256
AES-GCM-128/192/256
SHA-256
HMAC-SHA-256
RSASSA-PKCS1-v1_5(Up to 2048-bit)
RSASSA-PSS(Up to 2048-bit)
ECDSA-SECP256R1/SECP256K1
ECDH-SECP256R1/SECP256K1
二、MbedTLS目录结构
MbedTLS源码位于目录SDK_Folder\external\mbedtls。其中的mbedtls-2.26.0为原版Mbed TLS算法库,mbedtls-2.26.0_hw为带硬件加速的MbedTLS算法库,两者的目录结构一致。
图 2-1 MbedTLS算法库目录结构
如需了解MbedTLS的详细介绍,请访问MbedTLS开源仓库:https://github.com/Mbed-TLS/mbedtls或者MbedTLS官网: https://tls.mbed.org/ 。
三、环境搭建
Mbed TLS支持make、cmake等多种安装方式,本文采用的是直接引用Mbed TLS源码的方式进行编译,省去了make或者cmake所需的运行环境。
目录SDK_Folder\projects\peripheral\crypto目录下的crypto_aes、crypto_ecc、crypto_rsa、crypto_sha工程均已适配Mbed TLS算法库所需的最小配置。若开发者使用其他工程实现Mbed TLS硬件加速,则可参考上述工程的配置项。
3.1 添加MbedTLS源码
在工程中添加MbedTLS算法库的所有源码文件,其路径为SDK_Folder\external\mbedtls\mbedtls-2.26.0_hw\library下所有的C文件。
图 3-1 添加MbedTLS算法库源码
由于将psa_crypto_driver_wrappers.c文件引入后容易引起编译错误,可以将此文件忽略编译。此文件不会影响MbedTLS其他算法的使用性和正确性。
在工程Options中添加MbedTLS算法库的头文件和配置文件,其路径为SDK_Folder\external\mbedtls\mbedtls-2.26.0_hw\include下的H文件和SDK_Folder\external\mbedtls\mbedtls-2.26.0_hw\configs下的H文件。
图 3-2 MbedTLS算法库头文件引用
3.2 添加硬件加速驱动
在工程中添加硬件加速驱动的所有源码文件,其路径为SDK_Folder\components\libraries\crypto_lib\src下所有的C文件。
图 3-3 添加硬件加速驱动源码
在工程Options中添加硬件加速驱动的头文件,其路径为SDK_Folder\components\libraries\crypto_lib\inc下的H文件。
图 3‑4 硬件加速驱动头文件引用
3.3 配置MbedTLS
MbedTLS算法库需要指定相应的配置文件才能运行。若开发者没有指定自定义的配置文件,MbedTLS算法库将默认引用SDK_Folder\external\mbedtls\mbedtls-2.26.0_hw\include\mbedtls下的config.h文件作为配置文件。
在工程的Options中添加MBEDTLS_CONFIG_FILE=<mbedtls_config.h>全局宏定义,即可实现指定自定义的配置文件。自定义的配置文件需要在Include Paths中的路径下。
图 3‑5 指定自定义配置文件
示例工程的自定义配置文件如下所示。
/* System support */
#define MBEDTLS_HAVE_ASM
//#define MBEDTLS_HAVE_TIME
/* mbed base system support */
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
/* MPI / BIGNUM options */
//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */
//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
/* mbed AES support */
#define MBEDTLS_CIPHER_C
#define MBEDTLS_AES_C
#define MBEDTLS_GCM_C
#define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_CIPHER_PADDING_ZEROS
#define MBEDTLS_CIPHER_PADDING_PKCS7
/* mbed SHA support */
#define MBEDTLS_MD_C
#define MBEDTLS_SHA256_C
/* mbed RSA support */
#define MBEDTLS_PK_C
#define MBEDTLS_GENPRIME
#define MBEDTLS_OID_C
#define MBEDTLS_RSA_C
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_PKCS1_V21
/* ECP options */
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_NIST_OPTIM
//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
/* mbed ECDH support */
#define MBEDTLS_ECDH_C
/* mbed ECDSA support */
#define MBEDTLS_ECDSA_C
/* AES Hardware support */
#define HAS_AES_DRIVER
/* SHA Hardware support */
#define HAS_SHA_DRIVER
/* RSA Hardware support */
#define HAS_RSA_DRIVER
/* ECC Hardware support */
#define HAS_ECC_DRIVER
/* For test certificates */
//#define MBEDTLS_BASE64_C
//#define MBEDTLS_CERTS_C
//#define MBEDTLS_PEM_PARSE_C
/* For testing with compat.sh */
//#define MBEDTLS_FS_IO
#include "mbedtls/check_config.h"
其中HAS_AES_DRIVER、HAS_SHA_DRIVER、HAS_RSA_DRIVER和HAS_ECC_DRIVER为特殊宏定义。通过定义或屏蔽上述四个宏定义,可以实现开启或关闭相应的硬件加速功能。
此自定义配置文件为运行示例工程的最小集合配置,若开发者想使用MbedTLS算法库更多的功能,则需自主添加相应的宏定义。详细的宏定义分类可以参考SDK_Folder\external\mbedtls\mbedtls-2.26.0_hw\include\mbedtls下的config.h文件或者在开源仓库 https://github.com/Mbed-TLS/mbedtls 中查询。
四、应用详解
4.1 AES硬件加速
AES硬件加速支持AES-ECB-128/192/256、AES-CBC-128/192/256-None padding/PKCS7 padding/Zeros padding、AES-CTR-128/192/256、AES-CFB128-128/192/256、AES-OFB-128/192/256、AES-GCM-128/192/256算法。
使用AES硬件加速需要在MbedTLS配置文件中定义HAS_AES_DRIVER。相应的示例工程目录为SDK_Folder\projects\peripheral\crypto\crypto_aes。
4.1.1 宏定义相关
使用MbedTLS算法库的AES算法需要开启下列控制宏定义。
表4-1 AES功能宏定义
宏定义 | 说明 |
MBEDTLS_CIPHER_C | 启用通用密码层 |
MBEDTLS_AES_C | 启用AES分组密码 |
MBEDTLS_GCM_C | 启用伽罗瓦/计数器模式 (GCM) |
MBEDTLS_AES_ROM_TABLES | 使用存储在ROM中的预先计算的AES表 |
MBEDTLS_CIPHER_MODE_CBC | 启用密码块链接模式 (CBC) |
MBEDTLS_CIPHER_MODE_CTR | 启用计数器块密码模式 (CTR) |
MBEDTLS_CIPHER_MODE_CFB | 启用密码反馈模式 (CFB) |
MBEDTLS_CIPHER_MODE_OFB | 启用输出反馈模式 (OFB) |
MBEDTLS_CIPHER_PADDING_ZEROS | 开启ZEROS填充方案 |
MBEDTLS_CIPHER_PADDING_PKCS7 | 开启PKCS7填充方案 |
HAS_AES_DRIVER | 开启AES硬件加速 |
4.1.2 API相关
4.1.2.1 AES-ECB/CBC/CTR/CFB/OFB算法
1. 初始化cipher结构体
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
2. 获取AES模式info
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
根据密钥长度可以选择相应的宏定义MBEDTLS_CIPHER_AES_128_ECB、MBEDTLS_CIPHER_AES_192_ECB、MBEDTLS_CIPHER_AES_256_ECB、MBEDTLS_CIPHER_AES_128_CBC、MBEDTLS_CIPHER_AES_192_CBC、MBEDTLS_CIPHER_AES_256_CBC、MBEDTLS_CIPHER_AES_128_CTR、MBEDTLS_CIPHER_AES_192_CTR、MBEDTLS_CIPHER_AES_256_CTR、MBEDTLS_CIPHER_AES_128_CFB128、MBEDTLS_CIPHER_AES_192_CFB128、MBEDTLS_CIPHER_AES_256_CFB128、MBEDTLS_CIPHER_AES_128_OFB、MBEDTLS_CIPHER_AES_192_OFB、MBEDTLS_CIPHER_AES_256_OFB。
3. 设置cipher模式
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info );
4. 设置padding模式
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode );
由于AES-ECB、AES-CTR、AES-CFB128、AES-OFB模式不支持填充,故选择MBEDTLS_PADDING_NONE(不填充)。
AES-CBC模式可根据填充需求选择MBEDTLS_PADDING_NONE(不填充)、MBEDTLS_PADDING_PKCS7(PKCS7填充方案)、MBEDTLS_PADDING_ZEROS(ZEROS填充方案)。
5. 设置密钥
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
const unsigned char *key,
int key_bitlen,
const mbedtls_operation_t operation );
operation 选择MBEDTLS_ENCRYPT则进行加密操作,选择MBEDTLS_DECRYPT则进行解密操作。
6. 设置初始化向量IV
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len );
AES-CBC、AES-CFB128、AES-OFB模式需要指定初始化向量IV,AES-CTR模式需要指定初始计数器,AES-ECB模式可以忽略此步骤。
7. 更新输入数据
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx,
const unsigned char *input,
size_t ilen, unsigned char *output,
size_t *olen );
MbedTLS算法库对AES-ECB的分组大小有限制,单个块数据必须为16Bytes,若想进行大于16Bytes的数据加解密,需重复调用此接口。当开启硬件加速后,此接口允许一次性输入任意长度的数据进行加解密,也可以按16Bytes分组更新输入数据。为了获取更高的性能,当使用硬件加速时,建议一次性输入待加密或待解密的数据,而不要重复调用此接口。
AES-CBC、 AES-CTR、AES-CFB128、AES-OFB模式对分组大小没有限制,故可以一次性输入任意长度的数据进行加解密,也可以按16Bytes分组更新输入数据。
由于AES算法为16Bytes分组计算,故若没有选择填充模式的话,最后不满足16Bytes的分组将被忽略。
8. 完成计算
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen );
如果仍然需要从不完整的块中刷新数据,则将其中包含的数据填充到最后一个块的大小,然后写入输出缓冲区。若待处理数据满足16Bytes分组且不需要进行任何填充的话,则可以忽略此步骤。
9. 释放cipher结构体
void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
由于cipher结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放cipher结构体,防止堆栈溢出。
4.1.2.2 AES-GCM算法
1. 获取GCM模式info
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
根据密钥长度可以选择相应的宏定义MBEDTLS_CIPHER_AES_128_GCM、MBEDTLS_CIPHER_AES_192_GCM、MBEDTLS_CIPHER_AES_256_GCM。
2. GCM模式加密
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int mode,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *input,
unsigned char *output,
size_t tag_len,
unsigned char *tag );
此接口执行GCM加密和解密。由于当这个函数执行解密时,它输出认证标签并且不验证数据是否真实,故此接口推荐仅执行加密。
对于加密,输出缓冲区可以与输入缓冲区相同。对于解密,输出缓冲区不能与输入缓冲区相同。如果缓冲区重叠,则输出缓冲区必须在输入缓冲区后面至少落后8个字节。
附件信息至少具有以字节为单位的大小。当没有附加信息的时候,可以将NULL传入add,并将0传入add_len。
3. GCM模式解密
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *tag,
size_t tag_len,
const unsigned char *input,
unsigned char *output );
此接口执行GCM解密与认证。对于解密,输出缓冲区不能与输入缓冲区相同。如果缓冲区重叠,则输出缓冲区必须在输入缓冲区后面至少落后8个字节。
附件信息至少具有以字节为单位的大小。当没有附加信息的时候,可以将NULL传入add,并将0传入add_len。
4.2 SHA硬件加速
SHA硬件加速支持SHA-256和HMAC-SHA-256算法。
使用SHA硬件加速需要在Mbed TLS配置文件中定义HAS_SHA_DRIVER。相应的示例工程目录为SDK_Folder\projects\peripheral\crypto\crypto_sha。
4.2.1 宏定义相关
使用Mbed TLS算法库的SHA算法需要开启下列控制宏定义。
表4-2 SHA功能宏定义
宏定义 | 说明 |
MBEDTLS_MD_C | 启用通用消息摘要层 |
MBEDTLS_SHA256_C | 启用SHA-224和SHA-256加密哈希算法 |
HAS_SHA_DRIVER | 开启SHA硬件加速 |
4.2.2 API相关
4.2.2.1 HASH算法
1. 初始化md结构体
void mbedtls_md_init( mbedtls_md_context_t *ctx );
2. 获取SHA模式info
const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type );
选择MBEDTLS_MD_SHA256以进行SHA-256计算。
3. 设置SHA模式
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
hmac入参为0以进行SHA-256计算。
4. 启动SHA计算
int mbedtls_md_starts( mbedtls_md_context_t *ctx );
5. 更新输入数据
int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );
输入数据没有长度要求限制,可以一次性输入所有数据进行SHA计算,也可以通过分组的方式输入数据进行SHA计算。
6. 完成SHA计算
int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output );
7. 释放md结构体
void mbedtls_md_free( mbedtls_md_context_t *ctx );
由于md结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放md结构体,防止堆栈溢出。
8. 完整SHA计算接口
int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
unsigned char *output );
此接口只需获取SHA模式info即可完成SHA计算。
4.2.2.2 HMAC算法
1. 初始化md结构体
void mbedtls_md_init( mbedtls_md_context_t *ctx );
2. 获取SHA模式info
const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type );
选择MBEDTLS_MD_SHA256以进行HMAC-SHA-256计算。
3. 设置HMAC模式
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
hmac入参为1以进行HMAC-SHA-256计算。
4. 设置密钥
int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen );
硬件加速HMAC密钥仅支持32Bytes。
5. 更新输入数据
int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );
输入数据没有长度要求限制,可以一次性输入所有数据进行HMAC计算,也可以通过分组的方式输入数据进行HMAC计算。
6. 完成HMAC计算
int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output);
7. 释放md结构体
void mbedtls_md_free( mbedtls_md_context_t *ctx );
由于md结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放md结构体,防止堆栈溢出。
8. 完整HMAC计算接口
int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char *output );
此接口只需获取SHA模式info即可完成HMAC计算。
4.3 RSA硬件加速
RSA硬件加速支持RSASSA-PKCS1-v1_5(Up to 2048-bit)和RSASSA-PSS(Up to 2048-bit)算法。
使用RSA硬件加速需要在MbedTLS配置文件中定义HAS_RSA_DRIVER。相应的示例工程目录为SDK_Folder\projects\peripheral\crypto\crypto_rsa。
4.3.1 宏定义相关
使用Mbed TLS算法库的RSA算法需要开启下列控制宏定义。
表4-3 RSA功能宏定义
宏定义 | 说明 |
MBEDTLS_PK_C | 启用通用公共(非对称)密钥层 |
MBEDTLS_GENPRIME | 启用素数生成代码 |
MBEDTLS_OID_C | 启用OID数据库 |
MBEDTLS_RSA_C | 启用RSA公钥密码系统 |
MBEDTLS_PKCS1_V15 | 启用对PKCS#1 v1.5编码的支持 |
MBEDTLS_PKCS1_V21 | 启用对PKCS#1 v2.1编码的支持 |
HAS_RSA_DRIVER | 开启RSA硬件加速 |
4.3.2 API相关
1. 初始化pk结构体
void mbedtls_pk_init( mbedtls_pk_context *ctx );
2. 获取pk模式info
const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type );
选择MBEDTLS_PK_RSA以进行RSA算法计算。
3. 设置pk模式
int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info );
4. 设置RSA参数
void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, int hash_id );
padding模式选择MBEDTLS_RSA_PKCS_V15以进行RSASSA-PKCS1-v1_5数字签名计算,hash_id为MBEDTLS_MD_NONE。
padding模式选择MBEDTLS_RSA_PKCS_V21以进行RSASSA-PSS数字签名计算,hash_id为MBEDTLS_MD_SHA256。
5. 设置RSA公私钥对
int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *N,
const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *E );
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx );
其中D和N为私钥,E和N为公钥。若只进行加签可只输入私钥,若只进行验签可只输入公钥。mbedtls_rsa_import 接口会根据输入的公私钥对来判断RSA的计算长度。硬件加速支持1024-bit至2048-bit的RSA计算。mbedtls_rsa_complete用于完善内部公私钥对计算。
开发者也可以调用下列函数主动生成公私钥对。同样需要注意,硬件加速支持1024-bit至2048-bit的RSA计算。
int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
unsigned int nbits, int exponent );
6. 数字签名加签
int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
由于先前已经设置了hash_id,所以md_alg为MBEDTLS_MD_NONE即可。值得注意的是,RSA硬件加速仅针对消息摘要进行加签,故待加签数据应为SHA-256格式的消息摘要。若想对不定长的数据进行加签,可以先使用SHA-256算法计算出不定长数据的摘要,然后使用该摘要进行加签。
7. 数字签名验签
int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len );
由于先前已经设置了hash_id,所以md_alg为MBEDTLS_MD_NONE即可。值得注意的是,RSA硬件加速仅针对消息摘要进行验签,故待验签数据应为SHA-256格式的消息摘要。若想对不定长的数据进行验签,可以先使用SHA-256算法计算出不定长数据的摘要,然后使用该摘要进行验签。
8. 释放pk结构体
void mbedtls_pk_free( mbedtls_pk_context *ctx );
由于pk结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放pk结构体,防止堆栈溢出。
4.4 ECC硬件加速
ECC硬件加速支持ECDH-SECP256R1/SECP256K1和ECDSA-SECP256R1/SECP256K1算法。
使用ECC硬件加速需要在MbedTLS配置文件中定义HAS_ECC_DRIVER。相应的示例工程目录为SDK_Folder\projects\peripheral\crypto\crypto_ecc。
4.4.1 宏定义相关
使用MbedTLS算法库的ECC算法需要开启下列控制宏定义。
表4-4 ECC功能宏定义
宏定义 | 说明 |
MBEDTLS_ECP_C | 在GF(p)库上启用椭圆曲线 |
MBEDTLS_ECP_NIST_OPTIM | NIST曲线优化 |
MBEDTLS_ECP_DP_SECP256R1_ENABLED | 启用椭圆曲线内的SECP256R1曲线 |
MBEDTLS_ECP_DP_SECP256K1_ENABLED | 启用椭圆曲线内的SECP256K1曲线 |
MBEDTLS_ECDH_C | 启用椭圆曲线Diffie-Hellman库 |
MBEDTLS_ECDSA_C | 启用椭圆曲线DSA库 |
HAS_ECC_DRIVER | 开启ECC硬件加速 |
4.4.2 API相关
4.4.2.1 ECDH算法
1. 初始化ecp_group结构体
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp );
2. 初始化ecp_point结构体
void mbedtls_ecp_point_init( mbedtls_ecp_point *pt );
3. 设置椭圆曲线
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id );
ECC硬件加速支持SECP256R1/SECP256K1曲线,通过设置MBEDTLS_ECP_DP_SECP256R1/ MBEDTLS_ECP_DP_SECP256K1可以进行SECP256R1/SECP256K1曲线相关的计算。
4. 生成ECDH公私钥对
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
5. 计算ECDH共享密钥
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
6. 释放ecp_group结构体
void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
由于ecp_group结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放ecp_group结构体,防止堆栈溢出。
4.4.2.2 ECDSA算法
1. 初始化ecdsa结构体
void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );
2. 设置椭圆曲线
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id );
ECC硬件加速支持SECP256R1/SECP256K1曲线,通过设置MBEDTLS_ECP_DP_SECP256R1/ MBEDTLS_ECP_DP_SECP256K1可以进行SECP256R1/SECP256K1曲线相关的计算。
3. 设置公私钥对
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P,
const unsigned char *buf, size_t ilen );
ECDSA私钥可通过mbedtls_mpi_read_binary导入,ECDSA公钥可通过mbedtls_ecp_point_read_binary导入。
4. 数字签名加签
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
ECC硬件加速要求待加签数据应为SHA-256格式的消息摘要。若想对不定长的数据进行加签,可以先使用SHA-256算法计算出不定长数据的摘要,然后使用该摘要进行加签。由于待加签数据为摘要,故md_alg选择MBEDTLS_MD_NONE。
此函数计算 ECDSA 签名并将其写入缓冲区,按照 RFC-4492:Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) 中的定义进行序列化,输出格式为ASN.1编码格式。
Tag | Len | Tag | Len | R | Tag | Len | S |
30 | X | 02 | X | X | 02 | X | X |
5. 数字签名验签
int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen );
ECC硬件加速要求待验签数据应为SHA-256格式的消息摘要。若想对不定长的数据进行验签,可以先使用SHA-256算法计算出不定长数据的摘要,然后使用该摘要进行验签。签名需要遵从ASN.1编码格式。
6. 释放ecdsa结构体
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
由于ecdsa结构体初始化时存在申请堆空间的行为,故计算完成后需及时释放ecdsa结构体,防止堆栈溢出。
打开微信,使用“扫一扫”即可关注