[Freedom K82f] Help to configure QSPI for encrypted I/O

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

[Freedom K82f] Help to configure QSPI for encrypted I/O

2,127 Views
javiersoriano
Contributor II

I need some help to configure the QSPI for encrypted I/O. This in in general terms what I want to do:

1. My application resides in the internal flash. 

       - This means that I do not want to have my application on the QSPI. Many examples assume you want to boot your                 application from the encrypted QSPI. I do not want this.

2. My application creates the keyblob, and uses aes-128 to wrap it. Then it writes the aes-keyblob in the internal flash.

3. My application writes the KEK to the place where it should go.

4. My application reboots the device, so after the system is up, the new (and valid) keyblob will be used to configure the OTFAD.

5. Because the OTFAD is configured, encrypted data form the QSPI can be read (because it is decrypted on the fly).

     - Data that will be written to the QSPI needs to be encrypted by my application before the writing operation.

So far, I have reached point 2, and I have some questions about point 3:

This document states that "KEK needs to be preprogrammed in flash's IFR region. In MK82F256, the Flash IFR index for KEK is from index 0x20 to 0x23 ... using elftosb tools"

- How can I verify the current value of [0x20 - 0x23] ?

- Is there an alternative to the elftosb tools?

- Can my application write the KEK at runtime?

- If the KEK is programmed using elftosb tools (or any existing alternative), is there ANY way to erase/reset it?

Thanks in advance!

Javier

0 Kudos
Reply
7 Replies

1,781 Views
javiersoriano
Contributor II

I think I am very close to getting the encrypted read/write to work. My problem right now (I believe), has to do with the counters used for encryption of the data. 

Problem:

The first 16-byte chunk is decrypted without problems:

1) I encrypt plain text -> cipher

2) I write the cipher to the QSPI

3) I enable the OTFAD

4) Read back cipher from QSPI, which is decrypted on the fly

5) Decrypted cipher is exactly the same as original plain text from step 1)

BUT, from the second 16-byte chunk, and all chunks afterwards, the decrypted plain text not matching the input plain text:

0) Increase the address by 16.

Repeat steps 1-5 above..

The difference is that at step 5 I do not get the original plain text anymore. :smileysad:

What I know so far:

- The data has to be encrypted per 16-byte chunks.

- The "extended counter" is formed with the counter, XOR'ed counter, and address.

- The address needs to be incremented by 16 per 16-byte chunk. (is this correct?)

- The encrypt_16byte_block part has been verified using the example values in the K82 sub-family reference manual, Rev2 09/2015. This is why I believe my error is somewhere in the "increase counter" logic. 

HELP! I'm almost there :smileysilly:!!

Regards,

Javier

PS: I attach my code for reference. I have copied it from different parts of my code into a single file for the sake of clarity. 

0 Kudos
Reply

1,781 Views
juying_zhong
NXP Employee
NXP Employee

Hi

I found some problems in your code, they are below:

static void encrypt_256byte(uint32_t* qspi_addr, uint32_t* data, uint8_t* key, uint8_t* counter)
{
    uint32_t address_as_uint32_t = (uint32_t)qspi_addr;
    address_as_uint32_t &= 0xfffffff0; // Bitwise AND to force address to 0-mod-16
    uint32_t cipher[4] = {0};
    uint32_t plain[4] = {0};

    int i;
    int iterations = FLASH_PAGE_SIZE / 16;
    uint32_t* offset = data;

    uint16_t expand_temp;
    uint8_t expanded_counter[16] = {0};
    expand_counter(counter, address_as_uint32_t, expanded_counter);
    expand_temp = ((uint16_t)expanded_counter[14]) << 8 | (uint16_t)expanded_counter[15]; // maybe be modified according to your image size
    for(i = 0; i < iterations ; i++)
    {
        memcpy( plain, offset, 16 );
        encrypt_16byte_block(plain, expanded_counter, key, cipher);
        memcpy(offset, cipher, 16);
        memset(plain, 0, 16);
        memset(cipher, 0, 16);
        expand_temp += 16;

        expanded_counter[15] = (uint8_t)(expand_temp);  // maybe be modified according to your image size

        expanded_counter[14] = (uint8_t)(expand_temp >> 8); // maybe be modified according to your image size
        offset += sizeof(uint32_t) * 4;
    }
}

1,781 Views
javiersoriano
Contributor II

Thanks for the quick answer. These changes did the trick (mostly). :smileyhappy:

What I adjusted:

offset += sizeof(uint32_t);  // Because offset is a pointer to a uint32_t.

I thought my problem was only on the counter. However I later found that calling mbedtls_aes_crypt_ctr (see attached code above) modified the key. Restoring the key to its initial value fixed the rest of the problems. Now I am able to read (with OTFAD) and write (with software encryption).

Thanks again for all the help!

0 Kudos
Reply

1,781 Views
juying_zhong
NXP Employee
NXP Employee

Hi Javier,

Addtional note:

KEK placed in  [0x30 - 0x33] is not as high security as [0x20 - 0x23], propose to enable flash security feature.

 [0x30 - 0x33] erase operation is ame with [0x20 - 0x23], if erasing the key, it should cause to erase your application.

Best regards,

Juying

0 Kudos
Reply

1,781 Views
juying_zhong
NXP Employee
NXP Employee

Hi Javier,

Upon my understanding for your application, i guessed that you don't want to use ROM bootloader, then questions answer as below:

1. Firstly, i want you to pay attention on the below description in K82's RM.

34.3.3 Program Flash Erasable IFR Map
The program flash erasable IFR is nonvolatile information memory that can be erased but
has limited program capabilities and limited read access. The contents of the program
flash erasable IFR fields are summarized in the table found here.

34.3.3.1 Erasable Program Once Field
The Program Once Field in the program flash erasable IFR with indexes 0x20 - 0x23
provides 16 bytes of user data storage that can be programmed using the Program Once
command but cannot be read using the Read Once command. The Program Once Field in
the program flash erasable IFR with indexes 0x30 - 0x33 provides 16 bytes of user data
storage that can be programmed using the Program Once command and read using the
Read Once command. The program flash erasable IFR is erased using the Erase All
Blocks command, Erase All Blocks Unsecure command, and using the external erase all
feature (mass erase).

- How can I verify the current value of [0x20 - 0x23] ?

[Q/A] You can't verify them, because they can only be read by ROM bootlaoder.

- Is there an alternative to the elftosb tools?

[Q/A] No, there isn't.

- Can my application write the KEK at runtime?

[Q/A] No, you can't.  [0x20 - 0x23] can only be programed once after using erase all block (Flash unsesure) or mass erase (Flash secured and Mass erase enabled).

- If the KEK is programmed using elftosb tools (or any existing alternative), is there ANY way to erase/reset it?

[Q/A] yes, there is. you could use "erase all block command (Flash unsesure) " or "mass erase command (Flash secured and Mass erase enabled)" .

Summary:

KEK placed in [0x20 - 0x23] can't be read by application firmware except for ROM bootloader (because of considering KEK's security).

Upon your application requirement and K82's features, i proposed that your KEK is same with SB Key placed in [0x30 - 0x33] . Your application must read it, then use it to decrypt keyblob, finally config OTFAD.

Note:

5. Because the OTFAD is configured, encrypted data form the QSPI can be read (because it is decrypted on the fly).

     - Data that will be written to the QSPI needs to be encrypted by my application before the writing operation.

OTFAD is one-way, in other word, it can only read data from QSPI and can't write to QSPI.

Best regards,

Juying

0 Kudos
Reply

1,781 Views
javiersoriano
Contributor II

Hi Juying,

Thanks for the very specific answers. They are definitely helpful!

I have one follow up question, though, about this:

Juying Zhong wrote:

...

Note:

5. Because the OTFAD is configured, encrypted data form the QSPI can be read (because it is decrypted on the fly).

     - Data that will be written to the QSPI needs to be encrypted by my application before the writing operation.

OTFAD is one-way, in other word, it can only read data from QSPI and can't write to QSPI.

The OTFAD is able to decrypt only when reading. That much is clear. What I would like to do is to write content back to the QSPI, even if I have to encrypt it on my application. 

Let's assume, for example, that I configure the OTFAD context 1 between 0x6800_0000 and 0x6800_1FFF with a key:

1. Is the region 0x6800_000 - 0x6800_1FFF writable? 

2. Is it possible to read the output of the OTFAD via an IP command? Or must it be done with AHB commands? I may have misunderstood completely, because I think an IP command read should do the trick.

Thanks in advance for all the help.

Javier

0 Kudos
Reply

1,781 Views
juying_zhong
NXP Employee
NXP Employee

Hi Javier,

1. Is the region 0x6800_000 - 0x6800_1FFF writable? 

Yes,it is. Data (code is regarded as data) are wrote through peripheral bus for qspi controller.

 

2. Is it possible to read the output of the OTFAD via an IP command?

No, it isn't. IP commands are used to control qspi's IF module by reading preconfigured LUT.

OTFAD returns decrypted data to qspi controller.

Or must it be done with AHB commands?

Yes. In fact,  you needn't distinguish between IP commands and AHB commands, just need configure LUT and access memory mapped to "0x6800_000 - 0x6800_1FFF".

Best regards,

Juying

0 Kudos
Reply