Encrypted Boot image泄漏讨论

电子说

1.3w人已加入

描述

写在前面

在《安全启动模式下的数据保存问题》中,小编介绍了在HAB boot和XIP encrypted boot下,读写外部Nor Flash数据的特点以及image的数据特征状态,比如使能XIP encrypted boot后,Nor Flash内的bootable image是密文状态,那是否意味着只要在使能XIP encrypted boot后,被加密的bootable image就可以随意下发给OEM进行量产烧录,同时在量产后,客户可随意访问加密的bootable image而无需担心application image泄漏呢?

是否泄漏呢?

为了测试是否有泄漏的风险,在MIMXRT1060-EVK上进行如下步骤测试:

在MCUXpresso Secure Provisioning工具选择XIP encrypted模式,生成并烧录Blink LED的bootable image;

泄漏图1

通过NXP-MCUBootUtility查看烧录后的image,对比右边框中的明文image会发现密文image显得很是杂乱,即使被查看也应该不会泄漏明文image;

泄漏图2

接着换另一种方式查看密文image,即通过pyocd命令读取,具体如下所示,打开9_21_readback.bin与右边框中的明文image比较,发现居然一致,换句话说,明文image被泄漏了;

泄漏图3 泄漏图4

通过上述测试结果表明,使用后一种方式读取查看密文image居然能得到明文image,直接让XIP encrypted boot破防了,这是怎么回事呢?

原因解释

小编在《安全启动模式下的数据保存问题》中提到,存储在Serial Nor flash中的加密代码和数据在送到CPU执行之前,需要经过BEE或者OTFAD解密,这是 Encypted XIP boot模式实现的基础,Jlink在连接目标MCU时,会把对应的flash驱动算法加载在内部RAM中运行,如果此时MCU已经正常启动运行application image的话,则表示BEE或者OTFAD模块也已完成好配置了,那么flash驱动在读Nor Flash内的密文时,数据会被自动解密。

泄漏图 5

应对策略

既然我们已经了解泄漏的原因,就要阻断外部工具加载flashloader或者flash驱动算法到内部RAM运行,所以除了禁止Debug port外,我们还需要禁止Serial Download方式,预防不怀好意者利用Serial Downloader方式,使得ROM code加载专门的flashloader到RAM中运行,通过配置BEE或OTFAD模块来读取image明文(如下代码所示)。

 

    status = SLN_AUTH_check_context(SLN_CRYPTO_CTX_1);

    configPRINTF(("Context check status %d
", status));
    // DEBUG_LOG_DELAY_MS(1000);  // Optional delay, enable for debugging to ensure log is printed before a crash

    if (SLN_AUTH_NO_CONTEXT == status)
    {
        configPRINTF(("Ensuring context...
"));
        // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

        // Load crypto contexts and make sure they are valid (our own context should be good to get to this point!)
        status = bl_nor_encrypt_ensure_context();

        if (kStatus_Fail == status)
        {
            configPRINTF(("Failed to load crypto context...
"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Double check if encrypted XIP is enabled
            if (!bl_nor_encrypt_is_enabled())
            {
                configPRINTF(("Not running in encrypted XIP mode, ignore error.
"));
                // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a
                // crash

                // No encrypted XIP enabled, we can ignore the bad status
                status = kStatus_Success;
            }
        }
        else if (kStatus_ReadOnly ==
                 status) // Using this status from standard status to indicate that we need to split PRDB
        {
            volatile uint32_t delay = 1000000;
            // Set up context as needed for this application
            status = bl_nor_encrypt_split_prdb();

            configPRINTF(("Restarting BOOTLOADER...
"));

            while (delay--)
                ;

            // Restart
            DbgConsole_Deinit();
            NVIC_DisableIRQ(LPUART6_IRQn);
            NVIC_SystemReset();
        }
    }
    else if (SLN_AUTH_OK == status)
    {
        configPRINTF(("Ensuring context...
"));
        // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

        // We will check to see if we need to update the backup to the reduced scope PRDB0 for bootloader space
        status = bl_nor_encrypt_ensure_context();

        if (kStatus_Fail == status)
        {
            configPRINTF(("Failed to load crypto context...
"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Double check if encrypted XIP is enabled
            if (!bl_nor_encrypt_is_enabled())
            {
                configPRINTF(("Not running in encrypted XIP mode, ignore error.
"));

                // No encrypted XIP enabled, we can ignore the bad status
                status = kStatus_Success;
            }
        }
        else if (kStatus_Success == status) // We have good PRDBs so we can update the backup
        {
            bool isMatch    = false;
            bool isOriginal = false;

            configPRINTF(("Checking backup context...
"));
            // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before a crash

            // Check if we have identical KIBs and initial CTR
            status = bl_nor_crypto_ctx_compare_backup(&isMatch, &isOriginal, SLN_CRYPTO_CTX_0);

            if (kStatus_Success == status)
            {
                if (isMatch && isOriginal)
                {
                    configPRINTF(("Updating backup context with valid address space...
"));
                    // DEBUG_LOG_DELAY_MS(1000); // Optional delay, enable for debugging to ensure log is printed before
                    // a crash

                    // Update backup PRDB0
                    status = SLN_AUTH_backup_context(SLN_CRYPTO_CTX_0);
                }
            }
        }
    }

 

但相较于直接永久禁止Debug port的简单粗暴, 小编更加推荐Secure Debug安全调试,因为产品的售后,维护往往不是一帆风顺的,产品在客户现场有时也是状况频出,所以Secure Debug[1]就像给Debug port加了一把坚固的锁,只有能打开这把锁的人才能使用调试功能。

 

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分