使用蓝牙设备接入HarmonyOS智慧生活,设备注册后,必须使用密钥来对通信进行加解密。
Mbed TLS简介
相比互联网的openSSL,物联网的嵌入式设备适合小巧灵活的MbedTLS,曾用名PolarSSL,可以根据需求进行配置,降低对硬件资源的消耗。
mbedtls是一款采用Apache 2.0许可证协议开源软件加密库,使用标准C语言编写;独立的模块设计,降低模块之间的耦合度。
Mbed TLS官网
mbedtls官方名称为Mbed TLS,如果网上搜不到相关资源,就用“Mbed TLS”来做关键词来搜索,毕竟对搜索引擎来说“Mbed TLS”和“mbedtls”搜索的是不同的东西。
下面介绍如何简单的植入和使用mbedtls, 希望在不同开发平台开发的同学可以找到启发。
获取MbedTLS源码
这是官方的下载地址 https://github.com/Mbed-TLS/mbedtls
打不开的原因各位同学都懂的。
本人使用的是2.24.0版本
解压后的目录如下, 我们只使用 configs,include 和 library 这三个目录下的文件
植入步骤
1.导入文件
- 新建目录
mbedtls
- 把
include /mbedtls
目录下的所有文件复制到新建目录mbedtls
下 - 把
include/psa
整个目录和下的文件复制到新建目录mbedtls
下 - 把
library
目录下的所有文件复制到新建目录mbedtls
下 - 删除
config.h
文件多余的内容,最终代码如下
2.根据项目所需而使用相应的模块
不同品牌/平台和芯片型号或者编译器不一定对所有的mbedtls算法都支持,有些情况可能导致编译的失败,而当你又找不到原因的时候,你内心会崩溃的,所以重要的事情说三遍:
只编译项目所需的模块
只编译项目所需的模块
只编译项目所需的模块
华为提供的实例代码是这样的
于是我们就全局搜索mbedtls_md_context_t
这个类型是在哪个模块定义的,结果显示是在md.h
文件中定义的,因此必须引入这个文件。以此类推,搜索要使用到的类型和函数,结果显示在md.h
和pkcs5.h
这两个文件中定义的。
测试代码如下
/**
* 使用
* #define size_t TLK_SIZE_T
* #undef size_t
* 解决 size_t重定义的冲突
*/
#define size_t TLK_SIZE_T
#include "mbedtls/md.h"
#include "mbedtls/pkcs5.h"
#undef size_t
void test_mbedtls(){
unsigned char authCode[] = {
0x8d, 0xcd, 0xfb, 0x4c, 0x9d, 0xdc, 0x2f, 0x57,
0xc7, 0x2d, 0x4d, 0x21, 0x1d, 0x4c, 0x22, 0x4b};
unsigned int authCodeLen = sizeof(authCode);
unsigned char salt[] = {
0x85, 0x79, 0xea, 0xa6, 0x3c, 0xe5, 0x69, 0x75,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38};
unsigned int saltLen = sizeof(salt);
unsigned int iterCount = 1;
unsigned char output[16] = {0x00};
unsigned int keyLen = sizeof(output);
memset(output, 0, keyLen);
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *mdInfo = NULL;
mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_md_init(&ctx);
/* 数字 1 表示使用 HMAC */
mbedtls_md_setup(&ctx, mdInfo, 1);
mbedtls_pkcs5_pbkdf2_hmac(&ctx,
authCode, //设备代理注册生成的 authCode
authCodeLen, //authCode 的长度,16Byte
salt, //SN1|SN2 生成的盐值
saltLen, //salt 长度,16Byte
iterCount, //设置值为 1
keyLen, //sessionKey 的长度,16Byte
output); //sessionKey
tlkapi_send_string_data(1, "test sessionKey: ", output, keyLen); // 打印输出
}
编译显示相关的函数没有定义,说明这些函数并没有被编译
打开md.c
后会发现MBEDTLS_MD_C
这个宏并没有定义
因此在config.h
中添加定义。
相应的pkcs5.h
需要宏定义MBEDTLS_PKCS5_C
才能使用,也需要在config.h
中添加。
编译成功了!!
你以为结束了吗?还没!!!
运行得到的结果是
查看mbedtls_md_setup
函数的源码发现,此过程需要用到mdInfo
结构体下的type
成员,根据mbedtls_md_info_from_type(MBEDTLS_MD_SHA256)
发现必须定义MBEDTLS_SHA256_C
后MBEDTLS_MD_SHA256
才有效,因此在config.h
里也加上宏定义。
再编译,发现free
和calloc
两个函数没有定义。这是内存管理常用的两个函数,由于不同芯片使用不同的SDK,某些SDK不一定包含这两个函数,因此必须额外导入。
在此引入内存管理的heap.h
和heap.c
,其中含有这连个函数(具体这两个文件出自哪里,在这里不深入研究了)。
编译运行,看样子是成功了。
另外,很多教程都会在config.h
里加入宏定义 MBEDTLS_NO_PLATFORM_ENTROPY
表示没有平台支持,对本示例没有影响,全局搜索了一下,只有这几个文件里使用
最后,config.h
的完整代码如下
#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H
#define MBEDTLS_MD_C
#define MBEDTLS_PKCS5_C
#define MBEDTLS_SHA256_C
// 添加一个宏定义,表示没有平台支持
#define MBEDTLS_NO_PLATFORM_ENTROPY
#include "mbedtls/check_config.h"
#endif /* MBEDTLS_CONFIG_H */
heap.h
和heap.c
在本文章的附件资源,请自行下载。