本文介绍ID²-KM在Link SDK的适配过程。
适用范围
适用于使用Link SDK v2.3.0 、安全SDK v2.0集成安全功能(包括ID²、iTLS)的场景。
适用于通过阿里云物联网平台创建的产品,且节点类型为网关类型。产品下创建的设备通过获取设备证书(ProductKey、DeviceName和DeviceSecret)进行认证。
步骤一:配置Link SDK
下载Link SDK,推荐使用v2.3.0版本。
使用
make menuconfig
命令进入编译配置。在编译选项中使能iTLS和GATEWAY。使能iTLS:
使能GATEWAY:
配置ProductKey和ProductSecret。
打开linkkit_example_gateway.c,按照实际产品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定义,保证每个设备唯一即可。
$ vim examples/linkkit/linkkit_example_gateway.c
(可选)集成安全SDK库。
如果您针对嵌入式设备平台进行开发集成,请联系阿里云IoT安全团队获取相关平台的安全库。
步骤二:集成安全SDK
集成安全SDK v0.5
如果您直接使用Ubuntu,请确认Link C-SDK里的prebuilt目录下,已经包含了预编译完成的安全SDK库。这样您即可自行集成。
prebuilt/
│├── ubuntu
│ ├── bin
│ │ └── kconfig-mconf
│ ├── include
│ └── libs
│ ├── libalicrypto.a
│ ├── libcurl.a
│ ├── libID²client.a
│ ├── libitls.a
│ ├── libkm.a
│ ├── libmbedcrypto.a
│ └── libplat_gen.a
集成安全SDK v1.0/v2.0
Link SDK和安全SDK调用过程如下图所示。
安全SDK调用原理图如下。
集成安全SDK相关库。
将安全相关库复制至
prebuilt/$(os_name)/libs
。复制完之后,prebuilt/$(os_name)/libs目录下的库为:libicrypto.a、libid2.a、libitls.a、libkm.a、libls_hal.a和libls_osa.a。
其中libicrypto.a、libid2.a、libitls.a、libkm.a为安全团队提供的库;libls_osa.a、libls_hal.a为厂商适配的OSA及HAL层库。
输入命令
make menuconfig
,切换TLS连接方式为iTLS连接方式。修改示例代码,编译并运行example。
a.按照实际产品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定义,保证每个设备唯一即可。b.修改iotkit-embedded/examples/iot.mk链接选项中添加安全相关库依赖。c.修改iotkit-embedded/src/ref-impl/hal/os/$os_name /HAL_Crypt_Linux.c,使其适配alicrypto的接口。参考代码实现如下:
#include "iot_import.h" #include "ali_crypto.h" #define AES_BLOCK_SIZE 16 #define KEY_LEN 16 // aes 128 cbc #define p_aes128_t p_HAL_Aes128_t #define PLATFORM_AES_ENCRYPTION HAL_AES_ENCRYPTION #define PLATFORM_AES_DECRYPTION HAL_AES_DECRYPTION p_HAL_Aes128_t HAL_Aes128_Init( _IN_ const uint8_t *key, _IN_ const uint8_t *iv, _IN_ AES_DIR_t dir) { ali_crypto_result result; void * aes_ctx; size_t aes_ctx_size, alloc_siz; uint8_t * p; bool is_en = true; // encrypto by default if (dir == PLATFORM_AES_DECRYPTION) { is_en = false; } result = ali_aes_get_ctx_size(AES_CBC, &aes_ctx_size); if (result != ALI_CRYPTO_SUCCESS) { HAL_Printf("get ctx size fail(%08x)", result); return NULL; } alloc_siz = aes_ctx_size + KEY_LEN * 2 + sizeof(bool); aes_ctx = HAL_Malloc(alloc_siz); if (aes_ctx == NULL) { HAL_Printf("kmalloc(%d) fail", (int)aes_ctx_size); return NULL; } memset(aes_ctx, 0, alloc_siz); p = (uint8_t *)aes_ctx + aes_ctx_size; memcpy(p, key, KEY_LEN); p += KEY_LEN; memcpy(p, iv, KEY_LEN); p += KEY_LEN; *((bool *)p) = is_en; return aes_ctx; } int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes) { if (aes) { HAL_Free(aes); } return 0; } static int platform_aes128_encrypt_decrypt(p_HAL_Aes128_t aes_ctx, const void *src, size_t siz, void *dst, aes_type_t t) { ali_crypto_result result; size_t dlen, in_len = siz, ctx_siz; uint8_t * p, *key, *iv; bool is_en; if (aes_ctx == NULL) { HAL_Printf("platform_aes128_encrypt_decrypt aes_ctx is NULL"); return -1; } result = ali_aes_get_ctx_size(AES_CBC, &ctx_siz); if (result != ALI_CRYPTO_SUCCESS) { HAL_Printf("get ctx size fail(%08x)", result); return 0; } p = (uint8_t *)aes_ctx + ctx_siz; key = p; p += KEY_LEN; iv = p; p += KEY_LEN; is_en = *((uint8_t *)p); in_len <<= t == AES_CBC ? 4 : 0; dlen = in_len; result = ali_aes_init(t, is_en, key, NULL, KEY_LEN, iv, aes_ctx); if (result != ALI_CRYPTO_SUCCESS) { HAL_Printf("ali_aes_init fail(%08x)", result); return 0; } result = ali_aes_finish(src, in_len, dst, &dlen, SYM_NOPAD, aes_ctx); if (result != ALI_CRYPTO_SUCCESS) { HAL_Printf("aes_finish fail(%08x)", result); return -1; } return 0; } int HAL_Aes128_Cbc_Encrypt( _IN_ p_HAL_Aes128_t aes, _IN_ const void *src, _IN_ size_t blockNum, _OU_ void *dst) { return platform_aes128_encrypt_decrypt(aes, src, blockNum, dst, AES_CBC); } int HAL_Aes128_Cbc_Decrypt( _IN_ p_HAL_Aes128_t aes, _IN_ const void *src, _IN_ size_t blockNum, _OU_ void *dst) { return platform_aes128_encrypt_decrypt(aes, src, blockNum, dst, AES_CBC); } int HAL_Aes128_Cfb_Encrypt( _IN_ p_HAL_Aes128_t aes, _IN_ const void *src, _IN_ size_t length, _OU_ void *dst) { return platform_aes128_encrypt_decrypt(aes, src, length, dst, AES_CFB128); } int HAL_Aes128_Cfb_Decrypt( _IN_ p_HAL_Aes128_t aes, _IN_ const void *src, _IN_ size_t length, _OU_ void *dst) { return platform_aes128_encrypt_decrypt(aes, src, length, dst, AES_CFB128); }
d.执行
make
命令。编译成功后,运行iotkit-embedded/output/release/bin文件夹下的mqtt-example文件。若出现以下log信息,表示已成功切换成iTLS的链接方式。出现以下log信息表示mqtt测试成功。
调试。
如需更多的调试log,请使用debug版本的iTLS库和id2库,替换原prebuilt/ubuntu/libs文件夹中的libitls.a和libid2.a文件。
修改src/ref-impl/hal/ssl/itls/HAL_TLS_itls.c,在该文件中添加宏定义MBEDTLS_DEBUG_C,并将DEBUG_LEVEL设置为4。如下面代码所示。
完成后,重新编译运行测试程序。
-#define DEBUG_LEVEL 0 +#define MBEDTLS_DEBUG_C +#define DEBUG_LEVEL 4
错误码。
错误码详细信息,请查看iTLS错误码。
说明错误码中的消息警告,是在通信过程中,服务端发生异常,主动向设备端发送的消息通告。
错误码的消息类型,是指iTLS Native返回的警告类型。Android Link接口返回的值已做加权(10000)处理。
步骤三:编译
使用
make
命令编译链接,生成gateway example程序,并运行该程序。详细信息,请参见实际代码。./output/release/bin/linkkit-example-gw 5 auto
查看日志。确认Host端口的后缀为
itls.cn-shanghai.aliyuncs.com
。查看日志,当显示下图中的信息时,建链成功。
步骤四:验证
登录阿里云物联网平台控制台。
在实例概览页面,找到对应的实例,单击实例进入实例详情页面。
在左侧导航栏选择设备管理 > 设备。
在设备列表中,查找与步骤三:编译gateway example代码中,设置的DeviceName相同的设备。
若存在,则该设备已经通过ID²认证,并且已接入阿里云IoT平台,您可以进行后续的设备topic订阅与推送等操作。