本文介绍在Link TEE上适配ID²,适合于使用Link TEE作为ID²载体的用户。

适用范围

  • 适用于使用Link SDK v2.3.0 、安全SDK v2.0集成安全功能(包括ID²、iTLS),使用Link TEE安全存储ID²及相关的机密信息的场景。
  • 适用于通过阿里云物联网平台创建的产品,且产品节点类型为网关类型。产品下创建的设备通过获取设备证书(ProductKey、DeviceName和DeviceSecret)进行认证。
说明 更多Link TEE信息,请参考 Link TEE

步骤一:编译Link SDK

  1. 单击Link SDK v2.3.0下载SDK,推荐使用v2.3.0版本。
  2. 配置编译选项。

    通过make menuconfig进入编译配置。在编译选项中,使能iTLS和网关example。

    图 1. 使能iTLS
    使能iTLS
    图 2. 使能GATEWAY
    使能GATEWAY
  3. 配置Ubuntu运行平台。
    1. 集成安全SDK库。详细信息,请参考在Link SDK上适配ID²-KM>步骤二:集成安全SDK
    2. 将安全SDK的以下库放置于Link SDK的prebuilt/ubuntu/libs目录中。
      libicrypto.a
      libid2.a
      libitls.a
      libkm.a
      libls_hal.a
      libls_osa.a
    3. 将Link TEE发布的库置于Link SDK的prebuilt/ubuntu/libs目录中。
      libtee_client.so
      libtee_internal.so
    4. 修改example/iot.mk,增加对安全SDK及Link TEE相关库的支持。
      $(call Append_Conditional, LDFLAGS, \
        -litls \
        -lid2 \
        -lkm \
        -licrypto \
        -lls_osa \
        -lls_hal \
        -ltee_client \
        -ltee_internal \
    5. 修改mqtt_example.c中的PRODUCT_KEY,PRODUCT_SECRET为您申请购买后可用的值。DEVICE_NAME保证产品唯一即可,DEVICE_SECRET可以为任意值。
      #define PRODUCT_KEY             "a1O******"
      #define PRODUCT_SECRET          "i11**********"
      #define DEVICE_NAME             "test_gateway"
      #define DEVICE_SECRET           "i11f************************"
    6. 修改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);
      }
  4. 编译并运行make命令,编译成功后生成linkkit-example-gw文件。

步骤二:linkkit-example-gw测试验证

在output/release/bin文件夹下,运行命令LD_LIBRARY_PATH=../lib/ ./linkkit-example-gw

出现以下log信息表示已成功切换成iTLS的链接方式,并且已使用Link TEE作为安全存储服务。

log日志

出现以下log信息表示mqtt测试成功。

log日志

步骤三:阿里云物联网平台验证

  1. 登录阿里云物联网平台
  2. 实例概览页面,找到对应的实例,单击实例进入实例详情页面。
  3. 在左侧导航栏选择设备管理 > 设备
  4. 在设备列表中查找与mqtt_example.c代码中设置的Device Name相同的设备。

    若存在,则该设备已通过ID²认证并且接入物联网平台,您可以进行后续的设备topic订阅与推送等功能。