查看: 1635|回复: 0

[原创] OTMPK的‘真面目’

[复制链接]

该用户从未签到

656

主题

6312

帖子

0

超级版主

Rank: 8Rank: 8

积分
20158
最后登录
2024-5-7
发表于 2020-7-9 14:19:55 | 显示全部楼层 |阅读模式
问题
在应用手册《How to use i.MXRT Security Boot》给出的Encrypt XIP启动流程图中(如下所示),第一步需要将EKIB解密成KIB,而其中的Key可以是SW_GP2或者OTPMK值,并且OTPMK只对BEE和DCP‘可见’,且每一块芯片都有唯一的OTPMK。
2020-07-08_14-58-28.png
客户想使用SDK软件库中的dcp例程实现ECB加密,其中加密Key为OTPMK,但是在多块MIMXRT1050开发板测试后发现,明文经加密而产生的密文居然都是一样的 (如图2所示),这样反推可得各开发板芯片所对应的OTPMK值相同,而这与前面的描述明显不符,那到底是哪里出了差错呢?
pastedImage_1.png
分析与解决
经过进一步测试发现,上述相同的密文与Key全为0加密产生的密文一致,表明OTPMK并未真正参与ECB加密,最后通过与AE同事交流,知道原因是eFuse中的SEC_CONFIG未使能HAB Closed mode (如图3所示).
2020-07-08_15-37-55.png
在得知原因后,小编使用dcp例程在曾经做过HAB Signed Image boot启动测试的MIMXRT1050开发板上进行测试,具体代码如下,工程会打印出Key分别为OTMPK和全为0进行ECB加密后的密文,比较后会发现使用OTMPK加密的密文明显有别于Key全为0的密文。
测试代码
  1. /*
  2. * Copyright 2017 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */

  8. /*******************************************************************************
  9. * Includes
  10. ******************************************************************************/
  11. #include "fsl_device_registers.h"
  12. #include "fsl_debug_console.h"
  13. #include "board.h"

  14. #include "fsl_dcp.h"

  15. #include "pin_mux.h"
  16. #include "clock_config.h"
  17. /*******************************************************************************
  18. * Definitions
  19. ******************************************************************************/


  20. #define DCP_TEST_USE_OTP_KEY 1 /* Set to 1 to select OTP key for AES encryption/decryption. */

  21. #define TEST_ASSERT(a)       \
  22.     if (!(a))                \
  23.     {                        \
  24.         PRINTF("error\r\n"); \
  25.         do                   \
  26.         {                    \
  27.         } while (1);         \
  28.     }

  29. #if DCP_TEST_USE_OTP_KEY
  30. typedef enum _dcp_otp_key_select
  31. {
  32.     kDCP_OTPMKKeyLow  = 1U, /* Use [127:0] from snvs key as dcp key */
  33.     kDCP_OTPMKKeyHigh = 2U, /* Use [255:128] from snvs key as dcp key */
  34.     kDCP_OCOTPKeyLow  = 3U, /* Use [127:0] from ocotp key as dcp key */
  35.     kDCP_OCOTPKeyHigh = 4U  /* Use [255:128] from ocotp key as dcp key */
  36. } dcp_otp_key_select;
  37. #endif

  38. /*******************************************************************************
  39. * Prototypes
  40. ******************************************************************************/

  41. /*******************************************************************************
  42. * Code
  43. ******************************************************************************/
  44. #if DCP_TEST_USE_OTP_KEY
  45. status_t DCP_OTPKeySelect(dcp_otp_key_select keySelect)
  46. {
  47.     if (keySelect == kDCP_OTPMKKeyLow)
  48.     {
  49.         IOMUXC_GPR->GPR3 &= ~(1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  50.         IOMUXC_GPR->GPR10 &= ~(1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  51.     }

  52.     else if (keySelect == kDCP_OTPMKKeyHigh)
  53.     {
  54.         IOMUXC_GPR->GPR3 |= (1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  55.         IOMUXC_GPR->GPR10 &= ~(1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  56.     }

  57.     else if (keySelect == kDCP_OCOTPKeyLow)
  58.     {
  59.         IOMUXC_GPR->GPR3 &= ~(1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  60.         IOMUXC_GPR->GPR10 |= (1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  61.     }

  62.     else if (keySelect == kDCP_OCOTPKeyHigh)
  63.     {
  64.         IOMUXC_GPR->GPR3 |= (1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  65.         IOMUXC_GPR->GPR10 |= (1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  66.     }

  67.     else
  68.     {
  69.         return kStatus_InvalidArgument;
  70.     }

  71.     return kStatus_Success;
  72. }
  73. #endif

  74. void TestAesEcb(void)
  75. {
  76.     static const uint8_t keyAes128[] __attribute__((aligned)) = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  77.                                                                  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  78.     static const uint8_t plainAes128[]                        = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
  79.                                           0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a};
  80. //    static const uint8_t cipherAes128[]                       = {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
  81. //                                           0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97};
  82. #if DCP_TEST_USE_OTP_KEY
  83. #warning Please update cipherAes128 variables to match expected AES ciphertext for your OTP key.
  84. #endif

  85.     uint8_t cipher[16];
  86.     uint8_t output[16];
  87.     status_t status;

  88.     uint8_t i;

  89.     dcp_handle_t m_handle;

  90.     m_handle.channel    = kDCP_Channel0;
  91.     m_handle.swapConfig = kDCP_NoSwap;

  92. #if DCP_TEST_USE_OTP_KEY
  93.     m_handle.keySlot = kDCP_OtpUniqueKey;
  94. #else
  95.     m_handle.keySlot = kDCP_KeySlot0;
  96. #endif

  97.     status = DCP_AES_SetKey(DCP, &m_handle, keyAes128, 16);
  98.     TEST_ASSERT(kStatus_Success == status);

  99.     DCP_AES_EncryptEcb(DCP, &m_handle, plainAes128, cipher, 16);

  100.     for(i=0; i < 16 ; i++ )
  101.             PRINTF("ciphertext %d value is %x \r\n", i, cipher[i]);

  102. //    TEST_ASSERT(memcmp(cipher, cipherAes128, 16) == 0);
  103. //


  104.     DCP_AES_DecryptEcb(DCP, &m_handle, cipher, output, 16);
  105.     TEST_ASSERT(memcmp(output, plainAes128, 16) == 0);

  106.     PRINTF("AES ECB Unique KeyTest pass\r\n\r\n");


  107.     m_handle.keySlot = kDCP_KeySlot0;

  108.     status = DCP_AES_SetKey(DCP, &m_handle, keyAes128, 16);
  109.         TEST_ASSERT(kStatus_Success == status);

  110.     DCP_AES_EncryptEcb(DCP, &m_handle, plainAes128, cipher, 16);

  111.     for(i=0; i < 16 ; i++ )
  112.             PRINTF("ciphertext %d value is %x \r\n", i, cipher[i]);

  113.     PRINTF("AES ECB Key All 0 pass\r\n");


  114. }



  115. /*!
  116. * @brief Main function
  117. */
  118. int main(void)
  119. {
  120.     dcp_config_t dcpConfig;

  121.     /* Init hardware*/
  122.     BOARD_ConfigMPU();
  123.     BOARD_InitPins();
  124.     BOARD_BootClockRUN();
  125.     BOARD_InitDebugConsole();

  126.     /* Data cache must be temporarily disabled to be able to use sdram */
  127.     SCB_DisableDCache();

  128.     PRINTF("DCP Driver Example\r\n\r\n");

  129.     /* Initialize DCP */
  130.     DCP_GetDefaultConfig(&dcpConfig);

  131. #if DCP_TEST_USE_OTP_KEY
  132.     /* Set OTP key type in IOMUX registers before initializing DCP. */
  133.     /* Software reset of DCP must be issued after changing the OTP key type. */
  134.     DCP_OTPKeySelect(kDCP_OTPMKKeyLow);
  135. #endif

  136.     /* Reset and initialize DCP */
  137.     DCP_Init(DCP, &dcpConfig);

  138.     /* Call DCP APIs */
  139.     TestAesEcb();


  140.     /* Deinitialize DCP */
  141.     DCP_Deinit(DCP);

  142.     while (1)
  143.     {
  144.     }
  145. }
复制代码
运行结果
  1. DCP Driver Example
  2. ciphertext 0 value is 38
  3. ciphertext 1 value is ee
  4. ciphertext 2 value is 85
  5. ciphertext 3 value is 6a
  6. ciphertext 4 value is 5e
  7. ciphertext 5 value is 51
  8. ciphertext 6 value is bd
  9. ciphertext 7 value is cb
  10. ciphertext 8 value is 3c
  11. ciphertext 9 value is 93
  12. ciphertext 10 value is f9
  13. ciphertext 11 value is 3a
  14. ciphertext 12 value is 1
  15. ciphertext 13 value is b0
  16. ciphertext 14 value is fe
  17. ciphertext 15 value is 92
  18. AES ECB Unique KeyTest pass

  19. ciphertext 0 value is cf
  20. ciphertext 1 value is 2e
  21. ciphertext 2 value is a3
  22. ciphertext 3 value is 8a
  23. ciphertext 4 value is 12
  24. ciphertext 5 value is 3b
  25. ciphertext 6 value is e2
  26. ciphertext 7 value is 7
  27. ciphertext 8 value is 65
  28. ciphertext 9 value is eb
  29. ciphertext 10 value is 8c
  30. ciphertext 11 value is 5c
  31. ciphertext 12 value is 56
  32. ciphertext 13 value is ca
  33. ciphertext 14 value is f2
  34. ciphertext 15 value is 24
  35. AES ECB Key All 0 pass
复制代码




回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /4 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2024-5-7 18:30 , Processed in 0.108139 second(s), 19 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表