CryptoCell lazy initialization

nrf5340
NCS 3.1.0

Hello,

I am trying to improve boot time and here are some spikes and timings.


What I have found out is that CryptoCell init (hw_cc3xx_init_internal) takes majority of PRE_KERNEL_1 time.
As Crypto is not used early in the application, idea was to defer init of the driver, but I didn't had any success.

I've tried to comment out both SYS_INIT for hw_cc3xx_init (with and witout mutex), commented out entropy_cc3xx_rng_init, commented out _psa_crypto_init SYS_INIT and called those functions from main().
This is not working, board keeps rebooting

just for a test:
* I've tried to disable completely CC312 hardware and use Oberon instead without success.

* I've also tried to set zephyr,deferred-init; for &cryptocell. This just makes device disabled, but that 171ms function is still called in PRE_KERNEL_1

Do you have any recommendation how to make CryptoCell driver initialization later, during application run?
Thank you in advance,
Nemanja

Parents
  • HI  

    It seems like I succeeded.

    What I've changed:

    nrf/drivers/hw_cc3xx/hw_cc3xx.c

    // Removed this SYS_INIT calls and made hw_cc3xx_init global function
    /* Driver initalization done when mutex is not usable (pre kernel) */
    SYS_INIT(hw_cc3xx_init_internal, PRE_KERNEL_1,
    	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
    
    /* Driver initialization when mutex is usable (post kernel) */
    SYS_INIT(hw_cc3xx_init, POST_KERNEL,
    	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
    


    nrf/drivers/entropy/entropy_cc3xx.c

    // Changed this:
    DEVICE_DT_DEFINE(CRYPTOCELL_NODE_ID, entropy_cc3xx_rng_init,
    		 NULL, NULL, NULL, PRE_KERNEL_1,
    		 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &entropy_cc3xx_rng_api);
    
    // To this:
    DEVICE_DT_DEFINE(CRYPTOCELL_NODE_ID, NULL,
    		 NULL, NULL, NULL, PRE_KERNEL_1,
    		 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &entropy_cc3xx_rng_api);
    		 
    // Made entropy_cc3xx_rng_init global function


    nrf/subsys/nrf_security/src/zephyr/psa_crypto_init.c
    // Removed this SYS_INIT call
    SYS_INIT(_psa_crypto_init, POST_KERNEL,
    	 CONFIG_KERNEL_INIT_PRIORITY_DEVICE);


    nrf/subsys/nrf_security/src/zephyr/mbedtls_heap.c
    // Removed this SYS_INIT call and made mbedtls_heap_init global function
    SYS_INIT(mbedtls_heap_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);


    This is my work in progress lazy init piece of code that I can run from main or from work_q...
    extern int hw_cc3xx_init(void);
    extern int entropy_cc3xx_rng_init(const struct device *dev);
    extern int mbedtls_heap_init(void);
    
    static int lazy_crypto_init(void)
    {
    	static bool lazy_crypto_done = false;
    
    	if (lazy_crypto_done) {
    		return 0;
    	}
    
    	LOG_INF("lazy start!!!!");
    	int res = hw_cc3xx_init();
    	LOG_INF("hw_cc3xx_init returned: %d", res);
    
    	if (res != 0) {
    		LOG_ERR("CC3XX init failed: %d", res);
    		return res;
    	}
    
    	const struct device *entropy_dev = DEVICE_DT_GET(DT_NODELABEL(cryptocell));
    	if (entropy_dev == NULL) {
    		LOG_ERR("ERROR: Entropy device is NULL!");
    		return -ENODEV;
    	}
    
    	res = entropy_cc3xx_rng_init(entropy_dev);
    	LOG_INF("entropy_cc3xx_rng_init returned: %d", res);
    
    	psa_status_t err = psa_crypto_init();
    
    	LOG_INF("psa_crypto_init returned: %d", err);
    	if (err != PSA_SUCCESS) {
    
    		LOG_ERR("psa_crypto_init failed: %d", err);
    	}
    
    	LOG_INF("mbedtls_heap_init");
    	mbedtls_heap_init();
    
    	lazy_crypto_done = true;
    	return res;
    }


    After this crypto lazy init I can setup BLE and run advertising. I've used PSA functions, I've did DFU over BLE.

    Do you see any possible downside here?

  • Thank you for the update. I was actually just looking into this when you posted this. hw_cc3xx_init_internal() initializes the RNG by calling nrf_cc3xx_platform_init(). While the zephyr,deferred-init property added to the cryptocell node correctly defers the entropy driver initialisation, it does not matter because the RNG is already being initialised by hw_cc3xx_init_internal(), which is not gated by this zephyr,deferred-init property that only applies to device drivers.

    I did the following in my test:

    1. Patched the hw_cc3xx.c file with this:

    diff --git a/drivers/hw_cc3xx/hw_cc3xx.c b/drivers/hw_cc3xx/hw_cc3xx.c
    index b4218477e4..88d34b772d 100644
    --- a/drivers/hw_cc3xx/hw_cc3xx.c
    +++ b/drivers/hw_cc3xx/hw_cc3xx.c
    @@ -25,13 +25,13 @@ static int hw_cc3xx_init_internal(void)
     	/* Initialize the cc3xx HW with or without RNG support */
     
     	/* Using same configurations as the users of entropy, see NCSDK-24914. */
    -#if CONFIG_ENTROPY_CC3XX || defined(CONFIG_PSA_NEED_CC3XX_CTR_DRBG_DRIVER)
    -	res = nrf_cc3xx_platform_init();
    -#elif defined(CONFIG_PSA_NEED_CC3XX_HMAC_DRBG_DRIVER)
    -	res = nrf_cc3xx_platform_init_hmac_drbg();
    -#else
    +//#if CONFIG_ENTROPY_CC3XX || defined(CONFIG_PSA_NEED_CC3XX_CTR_DRBG_DRIVER)
    +//	res = nrf_cc3xx_platform_init();
    +//#elif defined(CONFIG_PSA_NEED_CC3XX_HMAC_DRBG_DRIVER)
    +//	res = nrf_cc3xx_platform_init_hmac_drbg();
    +//#else
     	res = nrf_cc3xx_platform_init_no_rng();
    -#endif
    +//#endif
     
     	return res;
     }

    2. Then made sure to initialise the device before enabling bluetooth:

    const struct device *c312 = DEVICE_DT_GET(DT_NODELABEL(cryptocell));
    
    ...
    
        err = device_init(c312);
    	if (err) {
    		printk("Failed to initialize device: %s (err %s)", c312->name, err);
    	}

    I don't immediately see any problems with this approach but at a minimum you should check if there is anything else that tries to request entropy data on startup.

Reply
  • Thank you for the update. I was actually just looking into this when you posted this. hw_cc3xx_init_internal() initializes the RNG by calling nrf_cc3xx_platform_init(). While the zephyr,deferred-init property added to the cryptocell node correctly defers the entropy driver initialisation, it does not matter because the RNG is already being initialised by hw_cc3xx_init_internal(), which is not gated by this zephyr,deferred-init property that only applies to device drivers.

    I did the following in my test:

    1. Patched the hw_cc3xx.c file with this:

    diff --git a/drivers/hw_cc3xx/hw_cc3xx.c b/drivers/hw_cc3xx/hw_cc3xx.c
    index b4218477e4..88d34b772d 100644
    --- a/drivers/hw_cc3xx/hw_cc3xx.c
    +++ b/drivers/hw_cc3xx/hw_cc3xx.c
    @@ -25,13 +25,13 @@ static int hw_cc3xx_init_internal(void)
     	/* Initialize the cc3xx HW with or without RNG support */
     
     	/* Using same configurations as the users of entropy, see NCSDK-24914. */
    -#if CONFIG_ENTROPY_CC3XX || defined(CONFIG_PSA_NEED_CC3XX_CTR_DRBG_DRIVER)
    -	res = nrf_cc3xx_platform_init();
    -#elif defined(CONFIG_PSA_NEED_CC3XX_HMAC_DRBG_DRIVER)
    -	res = nrf_cc3xx_platform_init_hmac_drbg();
    -#else
    +//#if CONFIG_ENTROPY_CC3XX || defined(CONFIG_PSA_NEED_CC3XX_CTR_DRBG_DRIVER)
    +//	res = nrf_cc3xx_platform_init();
    +//#elif defined(CONFIG_PSA_NEED_CC3XX_HMAC_DRBG_DRIVER)
    +//	res = nrf_cc3xx_platform_init_hmac_drbg();
    +//#else
     	res = nrf_cc3xx_platform_init_no_rng();
    -#endif
    +//#endif
     
     	return res;
     }

    2. Then made sure to initialise the device before enabling bluetooth:

    const struct device *c312 = DEVICE_DT_GET(DT_NODELABEL(cryptocell));
    
    ...
    
        err = device_init(c312);
    	if (err) {
    		printk("Failed to initialize device: %s (err %s)", c312->name, err);
    	}

    I don't immediately see any problems with this approach but at a minimum you should check if there is anything else that tries to request entropy data on startup.

Children
No Data
Related