This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF52840 Cryptocell register setting reading problem

I am trying to set the Lifecycle state of the cryptocell, but it seems like I am having an issue.

I do 


/** Enable crypto cell to configure it **/
NRF_CRYPTOCELL->ENABLE = CRYPTOCELL_ENABLE_ENABLE_Enabled << CRYPTOCELL_ENABLE_ENABLE_Pos;

/** Config cryptocell resgister so Device root key can only be set once per reset*/
NRF_CC_HOST_RGF->HOST_IOT_LCS = CC_HOST_RGF_HOST_IOT_LCS_LCS_Secure << CC_HOST_RGF_HOST_IOT_LCS_LCS_Pos;

/** Disable crypto cell until next use**/
NRF_CRYPTOCELL->ENABLE = CRYPTOCELL_ENABLE_ENABLE_Disabled << CRYPTOCELL_ENABLE_ENABLE_Pos;

But then later when I enable the cryptocell again and read the value of HOST_IOT_LCS,

LCS is 2 (like I expected) but LCS_IS_VALID is 0 which means invalid.

Any ideas?

I am using zephyr and I am doing this configuration post kernel with a priority after CONFIG_KERNEL_INIT_PRIORITY_DEFAULT. So the cryptocell is already being initialized by hw_cc310_init in file hw_cc310.c

Parents
  • Sorry about so many posts, but I think I have another thing that is contributing to the issue. This code is executing in a bootloader whose partition is from 0 to 0x22000. Another protection I implement in the bootloader is to use ACL[0] to protect the bootloader from writes. I use this code

    NRF_ACL->ACL[0].ADDR = 0;
    NRF_ACL->ACL[0].PERM = ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos; // 0x2
    NRF_ACL->ACL[0].SIZE = DT_FLASH_AREA_MCUBOOT_SIZE;  // this is 0x22000

    When I do this before I write the LCS register, I get the behavior I described in my original post. If I don't write to this ACL i get he behavior from my second post.

    I don't see how this ACL code affects the writing to the NRF_CRYPTOCELL, or NRF_CC_HOST_RGF

    I also notice that if I do the ACL setup before I write the LCS resgister, and I have more than 5 break points set anywhere in the code. Then I try to step past a line in the disassembly that stores a value to either the RF_CRYPTOCELL->ENABLE register or the NRF_CC_HOST_RGF->HOST_IOT_LCS register,  SES takes a long time and then SES spits out a message saying something like 

    "Timeout while erasing sectors, RAMCode did not respond in time. (PC = 0x00000000, CPSR = 0x00000000, LR = 0x01000005)!
    Failed to erase sectors.
    Programming failed @ address 0x00001A50 (block verification error)"

    Sometimes execution stays at the line  and does not execute it, sometimes execution goes past it

    If I have no debug points the code runs fine. 

    These are software breakpoints. 

    If I remove the ACL protection I can use as many breakpoints as I want and there is no timeout problems. 

  • Hi,

    I am not sure about the debugger issues here, nor am I able to find a link between ACL and this. But, there seems to be a requirement here which may be related to what you see.

    Testing your code from the original question the HOST_IOT_LCS register will not be set, even if waiting a long time to read it out (it will be 0x00000002). But, adding a delay between writing to ENABLE and HOST_IOT_LCS and before reading it back this works as expected, and HOST_IOT_LCS is read back as 0x00000102.

        /** Enable crypto cell to configure it **/
        NRF_CRYPTOCELL->ENABLE = CRYPTOCELL_ENABLE_ENABLE_Enabled << CRYPTOCELL_ENABLE_ENABLE_Pos;
    
        nrf_delay_us(1);
    
        /** Config cryptocell resgister so Device root key can only be set once per reset*/
        NRF_CC_HOST_RGF->HOST_IOT_LCS = CC_HOST_RGF_HOST_IOT_LCS_LCS_Secure << CC_HOST_RGF_HOST_IOT_LCS_LCS_Pos;
    
        nrf_delay_us(1);
    
        NRF_LOG_INFO("HOST_IOT_LCS: 0x%08x", NRF_CC_HOST_RGF->HOST_IOT_LCS);

  • Thanks. This did work. I appreciate the help. Although obviously you guys need more documentation around the cryptocell. 

Reply Children
  • Hi,

    Yes, the documentation for CrytoCell is a bit lacking. This has been reported, so hopefully, it will improve in the future.

    I have a few more details to share.

    1. CryptoCell must alway be enabled before writing to any of the other registers. This is not explicitly stated in the PS.
    2. The simple delay approach I used to show that there is a timing dependency is not the best (it might give you a race condition of timing changed due to temperature or something else). Instead, you could try to read back the registers until it has the expected value. (E.g. use "while (NRF_CC_HOST_RGF->HOST_IOT_LCS != 0x102) {}" after writing to HOST_IOT_LCS).
Related