在Link SDK上適配ID2-KM
本文介紹ID2-KM在Link SDK的適配過程。
適用范圍
適用于使用Link SDK v2.3.0 、安全SDK v2.0集成安全功能(包括ID2、iTLS)的場(chǎng)景。
適用于通過阿里云物聯(lián)網(wǎng)平臺(tái)創(chuàng)建的產(chǎn)品,且節(jié)點(diǎn)類型為網(wǎng)關(guān)類型。產(chǎn)品下創(chuàng)建的設(shè)備通過獲取設(shè)備證書(ProductKey、DeviceName和DeviceSecret)進(jìn)行認(rèn)證。
步驟一:配置Link SDK
下載Link SDK,推薦使用v2.3.0版本。
使用
make menuconfig
命令進(jìn)入編譯配置。在編譯選項(xiàng)中使能iTLS和GATEWAY。使能iTLS:
使能GATEWAY:
配置ProductKey和ProductSecret。
打開linkkit_example_gateway.c,按照實(shí)際產(chǎn)品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定義,保證每個(gè)設(shè)備唯一即可。
$ vim examples/linkkit/linkkit_example_gateway.c
(可選)集成安全SDK庫。
如果您針對(duì)嵌入式設(shè)備平臺(tái)進(jìn)行開發(fā)集成,請(qǐng)聯(lián)系阿里云IoT安全團(tuán)隊(duì)獲取相關(guān)平臺(tái)的安全庫。
步驟二:集成安全SDK
集成安全SDK v0.5
如果您直接使用Ubuntu,請(qǐng)確認(rèn)Link C-SDK里的prebuilt目錄下,已經(jīng)包含了預(yù)編譯完成的安全SDK庫。這樣您即可自行集成。
prebuilt/
│├── ubuntu
│ ├── bin
│ │ └── kconfig-mconf
│ ├── include
│ └── libs
│ ├── libalicrypto.a
│ ├── libcurl.a
│ ├── libID2client.a
│ ├── libitls.a
│ ├── libkm.a
│ ├── libmbedcrypto.a
│ └── libplat_gen.a
集成安全SDK v1.0/v2.0
Link SDK和安全SDK調(diào)用過程如下圖所示。
安全SDK調(diào)用原理圖如下。
集成安全SDK相關(guān)庫。
將安全相關(guān)庫復(fù)制至
prebuilt/$(os_name)/libs
。復(fù)制完之后,prebuilt/$(os_name)/libs目錄下的庫為:libicrypto.a、libid2.a、libitls.a、libkm.a、libls_hal.a和libls_osa.a。
其中l(wèi)ibicrypto.a、libid2.a、libitls.a、libkm.a為安全團(tuán)隊(duì)提供的庫;libls_osa.a、libls_hal.a為廠商適配的OSA及HAL層庫。
輸入命令
make menuconfig
,切換TLS連接方式為iTLS連接方式。修改示例代碼,編譯并運(yùn)行example。
a.按照實(shí)際產(chǎn)品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定義,保證每個(gè)設(shè)備唯一即可。b.修改iotkit-embedded/examples/iot.mk鏈接選項(xiàng)中添加安全相關(guān)庫依賴。c.修改iotkit-embedded/src/ref-impl/hal/os/$os_name /HAL_Crypt_Linux.c,使其適配alicrypto的接口。參考代碼實(shí)現(xiàn)如下:
#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.執(zhí)行
make
命令。編譯成功后,運(yùn)行iotkit-embedded/output/release/bin文件夾下的mqtt-example文件。若出現(xiàn)以下log信息,表示已成功切換成iTLS的鏈接方式。出現(xiàn)以下log信息表示mqtt測(cè)試成功。
調(diào)試。
如需更多的調(diào)試log,請(qǐng)使用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設(shè)置為4。如下面代碼所示。
完成后,重新編譯運(yùn)行測(cè)試程序。
-#define DEBUG_LEVEL 0 +#define MBEDTLS_DEBUG_C +#define DEBUG_LEVEL 4
錯(cuò)誤碼。
錯(cuò)誤碼詳細(xì)信息,請(qǐng)查看iTLS錯(cuò)誤碼。
說明錯(cuò)誤碼中的消息警告,是在通信過程中,服務(wù)端發(fā)生異常,主動(dòng)向設(shè)備端發(fā)送的消息通告。
錯(cuò)誤碼的消息類型,是指iTLS Native返回的警告類型。Android Link接口返回的值已做加權(quán)(10000)處理。
步驟三:編譯
使用
make
命令編譯鏈接,生成gateway example程序,并運(yùn)行該程序。詳細(xì)信息,請(qǐng)參見實(shí)際代碼。./output/release/bin/linkkit-example-gw 5 auto
查看日志。確認(rèn)Host端口的后綴為
itls.cn-shanghai.aliyuncs.com
。查看日志,當(dāng)顯示下圖中的信息時(shí),建鏈成功。
步驟四:驗(yàn)證
在實(shí)例概覽頁面,找到對(duì)應(yīng)的實(shí)例,單擊實(shí)例進(jìn)入實(shí)例詳情頁面。
在左側(cè)導(dǎo)航欄選擇設(shè)備管理 > 設(shè)備。
在設(shè)備列表中,查找與步驟三:編譯gateway example代碼中,設(shè)置的DeviceName相同的設(shè)備。
若存在,則該設(shè)備已經(jīng)通過ID2認(rèn)證,并且已接入阿里云IoT平臺(tái),您可以進(jìn)行后續(xù)的設(shè)備topic訂閱與推送等操作。