文档

在Link SDK上适配ID²-KM

更新时间:

本文介绍ID²-KM在Link SDK的适配过程。

适用范围

  • 适用于使用Link SDK v2.3.0 、安全SDK v2.0集成安全功能(包括ID²、iTLS)的场景。

  • 适用于通过阿里云物联网平台创建的产品,且节点类型为网关类型。产品下创建的设备通过获取设备证书(ProductKey、DeviceName和DeviceSecret)进行认证。

步骤一:配置Link SDK

  1. 下载Link SDK,推荐使用v2.3.0版本。

  2. 使用make menuconfig命令进入编译配置。在编译选项中使能iTLS和GATEWAY。

    使能iTLS:3

    使能GATEWAY: 3

  3. 配置ProductKey和ProductSecret。

    打开linkkit_example_gateway.c,按照实际产品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定义,保证每个设备唯一即可。

    $ vim examples/linkkit/linkkit_example_gateway.cPKPS

  4. (可选)集成安全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调用过程如下图所示。LK1

安全SDK调用原理图如下。LK2

  1. 集成安全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层库。

  2. 输入命令make menuconfig,切换TLS连接方式为iTLS连接方式。

    2
  3. 修改示例代码,编译并运行example。

    a.按照实际产品信息配置ProductKey和ProductSecret,DeviceName和DeviceSecret可以自定义,保证每个设备唯一即可。2b.修改iotkit-embedded/examples/iot.mk链接选项中添加安全相关库依赖。2c.修改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的链接方式。2出现以下log信息表示mqtt测试成功。2

  4. 调试。

    如需更多的调试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
  5. 错误码。

    错误码详细信息,请查看iTLS错误码

    说明

    • 错误码中的消息警告,是在通信过程中,服务端发生异常,主动向设备端发送的消息通告。

    • 错误码的消息类型,是指iTLS Native返回的警告类型。Android Link接口返回的值已做加权(10000)处理。

步骤三:编译

  1. 使用make命令编译链接,生成gateway example程序,并运行该程序。详细信息,请参见实际代码。

    ./output/release/bin/linkkit-example-gw 5 auto            
  2. 查看日志。确认Host端口的后缀为itls.cn-shanghai.aliyuncs.com1

  3. 查看日志,当显示下图中的信息时,建链成功。2

步骤四:验证

  1. 登录阿里云物联网平台控制台

  2. 实例概览页面,找到对应的实例,单击实例进入实例详情页面。

  3. 在左侧导航栏选择设备管理 > 设备

  4. 设备列表中,查找与步骤三:编译gateway example代码中,设置的DeviceName相同的设备。

若存在,则该设备已经通过ID²认证,并且已接入阿里云IoT平台,您可以进行后续的设备topic订阅与推送等操作。