This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2745R10-Q1: Methods using more than 35 keys

Part Number: CC2745R10-Q1

Tool/software:

Related Questions:
https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1495304/cc2745r10-q1-about-persistent-keys-max/5746055?tisearch=e2e-sitesearch&keymatch=KeyStore#5746055

We want to implement a system using key information that exceeds the maximum number of keys registered in the PSA KeyStore (35 keys). 
So, after importing the plaintext keys, we export the encrypted keys and store them in the data flash, and then delete the key information in PSAKeyStore with destroy. After that, I thought of re-importing the encrypted key stored in the data flash to perform the cryptographic operation.

To test whether this method is feasible, we compared the results of the cipher operation with the key that was first imported with the following code and the results of the cipher operation with the key that was reimported after exporting that key, and found that the results were completely different. 
Is it possible to import as key information that yields the same cipher operation result by setting some parameter?

If this is not possible, is there any other way to handle key information exceeding 35 keys without calling plaintext key information into RAM?

This code is a rewrite of the sample code empty.c.

The environment used is as follows:
・Bord : CC2745R10-Q1
・Debugger : XDS110 
・SDK : SimpleLink Lowpower f3 ver.9.10

/* For usleep() */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <third_party/psa_crypto/include/psa/crypto.h>
#include <ti/drivers/cryptoutils/hsm/HSMLPF3.h>

/* Driver configuration */
#include "ti_drivers_config.h"

#define KEY_LIFETIME PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_HSM_ASSET_STORE)

uint8_t keyingMaterial[16] = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 };
uint8_t keyingMaterial2[16] = { 0x02, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 };   /* FSI_add */
uint8_t iv[16] = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 };
uint8_t plaintext[16] = { 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67 };
uint8_t ciphertext[16];
uint8_t ciphertext_exp[16];                                     /* FSI_add */
uint8_t expkey_encflg;                                          /* FSI_add */
uint8_t aescbc_matchflg;                                        /* FSI_add */
uint8_t exported_key[sizeof(keyingMaterial)];

//ciphertest { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a };


/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    psa_status_t status;
    psa_key_id_t key_id;
    size_t exported_key_length;
    psa_cipher_operation_t op = PSA_CIPHER_OPERATION_INIT;
    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
    size_t cipher_length = 0;
    int_fast16_t ret;
    psa_key_id_t key_id_exp;                                        /* FSI_add */
    psa_key_id_t key_id_oth;                                        /* FSI_add */
    uint8_t i;                                                      /* FSI_add */
    psa_cipher_operation_t op_exp = PSA_CIPHER_OPERATION_INIT;      /* FSI_add */

    status = psa_crypto_init();
    if (status != PSA_SUCCESS)
    {
        while(1);
    }

    ret = HSMLPF3_provisionHUK();
    if (ret != HSMLPF3_STATUS_SUCCESS)
    {
        while(1);
    }

    /* Import Key*/
    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT);
    psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING);
    psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);

    psa_set_key_lifetime(&attributes, KEY_LIFETIME);
    psa_set_key_bits(&attributes, 128);

    key_id = PSA_KEY_ID_USER_MIN;
    psa_set_key_id(&attributes, key_id);

    status = psa_import_key(&attributes, keyingMaterial, sizeof(keyingMaterial), &key_id);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
/* FSI_add_st */
#if 0
    /* ★Operation Check. Other Key import */
    key_id_oth = PSA_KEY_ID_USER_MIN + 1;
    psa_set_key_id(&attributes, key_id_oth);
    status = psa_import_key(&attributes, keyingMaterial2, sizeof(keyingMaterial2), &key_id_oth);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
    key_id_exp = PSA_KEY_ID_USER_MIN + 2;
    psa_set_key_id(&attributes, key_id_exp);
    status = psa_import_key(&attributes, keyingMaterial, sizeof(keyingMaterial), &key_id_exp);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
#endif
/* FSI_add_ed */

#if 0
    /* AES-CBC Encrypt */
    status = psa_cipher_encrypt_setup(&op, key_id, PSA_ALG_CBC_NO_PADDING);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }

    status = psa_cipher_set_iv(&op, iv, sizeof(iv));
    if (status != PSA_SUCCESS)
    {
        while(1);
    }

    status = psa_cipher_update(&op,
                               plaintext,
                               sizeof(plaintext),
                               ciphertext,
                               sizeof(plaintext),
                               &cipher_length);

    if (status != PSA_SUCCESS)
    {
        while(1);
    }

    status = psa_cipher_finish(&op,
                               ciphertext,
                               sizeof(plaintext),
                               &cipher_length);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
#endif

#if 1
    /* Export Key*/
    status = psa_export_key(key_id, exported_key, sizeof(exported_key), &exported_key_length);

    if (status != PSA_SUCCESS)
    {
         while(1);
    }
#endif

/* FSI_add_st */
#if 1
    /* 3. Export Key Encryption Check */
    expkey_encflg = 0;
    for ( i = 0; i < 16; i++ )
    {
        if( exported_key[i] == keyingMaterial[i] )
        {
            /* Check NG */
        }
        else
        {
            expkey_encflg = 1;  /* Check OK */
        }
    }
#endif

#if 1
    /* 4. Export Key import */
    key_id_exp = PSA_KEY_ID_USER_MIN + 1;
    psa_set_key_id(&attributes, key_id_exp);

    status = psa_import_key(&attributes, exported_key, sizeof(exported_key), &key_id_exp);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
#endif

#if 1
    /* 5. AES-CBC Encrypt (By Export Key) */
    status = psa_cipher_encrypt_setup(&op_exp, key_id_exp, PSA_ALG_CBC_NO_PADDING);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
    status = psa_cipher_set_iv(&op_exp, iv, sizeof(iv));
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
    status = psa_cipher_update(&op_exp,
                               plaintext,
                               sizeof(plaintext),
                               ciphertext_exp,
                               sizeof(plaintext),
                               &cipher_length);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
    status = psa_cipher_finish(&op_exp,
                               ciphertext_exp,
                               sizeof(plaintext),
                               &cipher_length);
    if (status != PSA_SUCCESS)
    {
        while(1);
    }
#endif

#if 0
    /* 6. AES-CBC Encrypt Result Match Check */
    aescbc_matchflg = 1;
    for ( i = 0; i < 16; i++ )
    {
        if( ciphertext_exp[i] == ciphertext[i] )
        {
            /* Check OK */
        }
        else
        {
            aescbc_matchflg = 0;    /* Check NG */
        }
    }
#endif
/* FSI_add_ed */

    while(1);
}


  • Hello,

    It seems that the key is exported as a wrapped key, meaning that it was encrypted before it was exported. So the key that you are trying to import is actually an encrypted version of that key. 

    I believe that you will need to unwrap the key, or let KeyStore know that it's wrapped and it must be unwrapped. I'm not aware of a method of doing this, so I'm reaching out to the R&D team to see how your use case can be achieved.

    I should get back to you later today or tomorrow.

    Best,

    Nima Behmanesh

  • Hello,

    There is no way to do this without using HSM baremetal to reimport the wrapped keys. However, using baremetal means that the PSA API can't be used. This isn't a limitation of the HSM, but the PSA crypto API itself. the PSA crypto API is standardized, and in that standard, there is no way to indicate that a key that is wrapped is being imported.

    One method I can think of is the following:

    Store a key in the HSM that is only used for wrapping/unwrapping.

    Wrap all the keys you want to store yourself using the HSM to do the wrapping.

    Store the wrapped keys in your own key storage (a section of non-volatile memory defined by you).

    When you want to use the key, unwrap it, then import it.

    As of right now, this would be the only way to implement your use-case.

    Best,

    Nima Behmanesh 

  • Hello,

    Thank you for your answer.
    I understand how to do this at this time.
    Is there any plan to update the SDK in the future to allow the use of more than 35 keys?

  • Hello,

    There is no plan to add more storage for keys, however, if it's a hard requirement, I recommend reaching out to your TI field representative. 

    Best,

    Nima Behmanesh

  • Hello,

    I Understood.
    Thank you for your response.