本文介紹在Link TEE上適配ID2,適合于使用Link TEE作為ID2載體的用戶。

適用范圍

  • 適用于使用Link SDK v2.3.0 、安全SDK v2.0集成安全功能(包括ID2、iTLS),使用Link TEE安全存儲ID2及相關的機密信息的場景。
  • 適用于通過阿里云物聯網平臺創建的產品,且產品節點類型為網關類型。產品下創建的設備通過獲取設備證書(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上適配ID2-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相同的設備。

    若存在,則該設備已通過ID2認證并且接入物聯網平臺,您可以進行后續的設備topic訂閱與推送等功能。