CN / EN
CN / EN

写技术文章

MbedTLS硬件加速使用指南

Tim

2023-07-28 12:00:53

前言

本文介绍了如何使用GR551X系列芯片的安全外设模块(AESHMACPKCTRNG)对第三方安全算法库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支持多种不同的加密算法:

  • Cryptographic hash functions

MD2, MD4, MD5, RIPEMD160, SHA-1, SHA-2

  • MAC modes

CMAC, HMAC

  • Ciphers

AES, ARIA, Blowfish, Camellia, ChaCha, DES, RC4, Triple DES, XTEA

  • Cipher modes

ECB, CBC, CFB, CTR, OFB, XTS

  • Authenticated encryption modes

CCM, GCM, NIST Key Wrap,

ChaCha20-Poly1305

  • Key derivation

HKDF

  • Key stretching

PBKDF2, PKCS #5 PBE2, PKCS #12 key derivation

  • Public-key cryptography

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

  • Hash函数

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算法库目录结构

  • 3rdparty:第三方源码
  • ChangeLog.d:更改日志
  • configs:Mbed TLS配置文件
  • docs:参考文档
  • doxygen:用于doxygen生成
  • include:Mbed TLS源码头文件
  • library:Mbed TLS源码源文件
  • programs:示例工程
  • scripts:运行脚本
  • tests:测试工程
  • visualc:VS2010适配工程

如需了解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_OPTIMNIST曲线优化
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编码格式。

TagLenTagLenRTagLenS
30X02XX02XX

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结构体,防止堆栈溢出。

0收藏

1赞成

您的评论
我们时刻倾听您的声音
联系销售

扫描关注公众号

打开微信,使用“扫一扫”即可关注