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.

CC1312R: Overwriting memory when using ECC_generateKey under TIRTOS7

Part Number: CC1312R
Other Parts Discussed in Thread: SYSCONFIG, CC1310

Hi,

I upgrade my system to TIRTOS7.

When I call to ECC_generateKey() i see overwriting memory on ram memory :

Addresses  0x2000014B- 0x200001b0

In map file you can see that this memory allocated to other parameters : 

This problem not happened when I used with TIRTOS old version 

Ho I can fixe it ?

Thank 

Yaki

The running code : 

  • Hi Yaki,

    Did you have a functional project with TIRTOS? What steps did you follow to port the example to TIRTOS 7?

    Regards,
    Sid

  • Hi ,

    Yes this function work good on old version of TI-RTOS.

    To move to TIRTOS7 I open the RTOS7 empty example project and merge the SysConfig on my project with empty project .

    The new project (TIRTOS7 ) compiled and run .but I have this memory Overwriting .

    Thanks 

    Yaki 

  • Hi Yaki, 

    Was this project ported from CC1310 to CC1312? If you take a look a the aesKeyAgreement example in the SDK. I see it is different compared to the CC1310 example. 

    In the CC1312 aesKeyAgreement example, I see that the ECDH_generatePublicKey function is used instead of directly calling ECC_generateKey.. Please refer to the example and use that function.

    Regards,

    Sid

  • Hi Sid,

    We alredy move to CC1312 and not see problem to use with ECC_generateKey .

    The problem start when I moved to TIRTOS7 .

    I don't see example project of ecc/ecdh on RTOS7 .

    Please advice 

    Yaki 

  • Hi Yaki, 

    You can find the aesKeyAgreement Exmple. THis uses the ECDH driver.

    SDK_PATH\examples\rtos\CC1312R1_LAUNCHXL\drivers\aesKeyAgreement

    I am still trying to figure out what the difference is between the implementations of these with respect to the OS versions.

    Regards,

    Sid

  • Hi Sid,

    I looked on the example code the function is different

    The input parameters are different. (See below)

    How I can be sure that it do the same functionality ?

    We already have devices in the field that work based on original function .

    In my new project the old function work .The only problem is the overwriting memory

    I prefer to keep work with the same function and understand the problem .

    Can we involve  more people to understand this issue ? 

    Thanks

    Yaki

        

    My function :  

    Define in : C:\ti\simplelink_cc13xx_cc26xx_sdk_6_20_00_29\source\ti\devices\cc13x2_cc26x2\driverlib\rom_crypto.h

    //*****************************************************************************
    /*!
    * \brief Generate a key.
    *
    * This is used for both ECDH and ECDSA.
    *
    * \param randString Pointer to random string, input.
    * \param privateKey Pointer to the private key, output.
    * \param publicKey_x Pointer to public key X-coordinate, output.
    * \param publicKey_y Pointer to public key Y-coordinate, output.
    *
    * \return Status
    */
    //*****************************************************************************
    extern uint8_t ECC_generateKey(uint32_t *randString, uint32_t *privateKey,
    uint32_t *publicKey_x, uint32_t *publicKey_y);

    Example  function : 

    Define in : C:\ti\simplelink_cc13xx_cc26xx_sdk_6_20_00_29\source\ti\drivers\ECDH.h

    /*!
    * @brief Generates a public key for use in key agreement.
    *
    * This function can be used to generate a public key from a private key.
    *
    * @param handle A ECDH handle returned from ECDH_open()
    *
    * @param operation A pointer to a struct containing the requisite
    * parameters to execute the function.
    *
    * @pre Call ECDH_OperationGeneratePublicKey_init() on @c operation.
    *
    * @post ECDH_computeSharedSecret()
    *
    * @retval #ECDH_STATUS_SUCCESS The operation succeeded.
    * @retval #ECDH_STATUS_ERROR The operation failed.
    * @retval #ECDH_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available. Try again
    * later.
    * @retval #ECDH_STATUS_CANCELED The operation was canceled.
    * @retval #ECDH_STATUS_POINT_AT_INFINITY The computed public key is the point at infinity.
    * @retval #ECDH_STATUS_PRIVATE_KEY_ZERO The provided private key is zero.
    * @retval #ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER The provided private key is larger than or equal to the order
    * of the curve.
    *
    */
    int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation);

  • Hi Yaki, 

    I will consult RnD and get back to you ASAP. Is it possible for you to provide us a minimal example that causes this issue? 

    Regards,

    Sid

  • Hi Sid ,

    I can show you this problem on my system in debug but I can't send you this project .

    If you can, we can do a call and share my debug project .

    Please update Yaki

  • Hi Yaki, 

    Sorry, I was out sick. But I did get some feedback from RnD.

    They said the behavior of the function should be OS independent.

    But they also said ECC_generateKey is a ROM function that is not exactly documented in the SDK. It is recommended to use the ECDH_generatePublicKey, which has an example and also has documetation found in this path. 

    simplelink_cc13xx_cc26xx_sdk_6_20_00_24/docs/drivers/doxygen/html/_e_c_d_h_8h.html

    It is hard to debug ECC_generateKey without an example. 

    Which of the following scenarios is correct in your situtation?

    1. In your code, is the function ECC_generateKey is writing to a different memory location when you change TIRTOS to TIRTOS7? 

    2. Or is the function writing to the same location, but in TIRTOS it is not allocated to something else, hence it is not a problem. But in TIRTOS7 it has been allocated to something else and is being overwritten.

    We could have a call. 

    Regards,

    Sid 

  • Hi SId ,

    We are in holiday season in Israel so my answer is delayed , Sorry .

    Answer 1 : In TIRTOS and TIRTOS7 I see that the same memory is change . 

    Ti RTTOS : 

    Answer 2 : It look like in TIRTOS the memory not used by other parameters 

    Yaki 

  • Hi Yaki, 

    No problem, I think the behavior of the API ECC_generateKeys cannot be changed. But what we can do is try to protect the memory area by keeping a variable there with a big enough size in that location, so that the TIRTOS7 constructs are not placed in that memory location. This location will be written by the ECC_GenerateKey function, but this should not be a problem since this is a dummy variable that should not be used in the code.

    This is compiler dependent.  Which compiler are you using? 

    Regards,

    Sid

  • Hi,

    We are using IAR compiler .

    If we will try to work with ECDH_generatePublicKey , but our released devices used with ECC_generateKeys;

    Do you think we will have problem ? Do you have example code that using ECDH_generatePublicKey and other side used with ECDH_generatePublicKey ?

    Do you have Instructions to this situation ?

    Thanks
    Yaki

      

  • Hi Yaki, 

    I apologize for the delay of the reply. The aesKeyAgreement  example is the only one we have for this API. 

    Regards,

    Sid

  • Hi Sid ,

    I succeeded to work with ECC_generateKeys by protect the memory .

    And now I try to move to new driver and work with ECDH_generatePublicKey .

    I implement the code according the sample that we have in ti\simplelink_cc13xx_cc26xx_sdk_6_20_00_29\source\ti\drivers\ECDH.c

    To verify that ECDH_generatePublicKey  work the same as ECC_generateKeys I insert the same myPrivateKey to the both of function and test the function output . The public key not equal (compere the PublicKey in  ECDH_generatePublicKey   to PublicKey X or PublicKey Y in ECC_generateKeys )

    The running code show below  .

    In both setting I used with NIST-P256 definition .

    Do you you have compere example ? 

    Please advice .

    Yaki 

    Common definition :

    **************************************************** 

    uint8_t myPrivateKeyingMaterial[CURVE_LENGTH] = {0x00, 0xCC, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0xBB, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0xDD, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x01};

    code based on "ECC_generateKeys "

    ****************************************************

    uint8_t ecc_genKeys(eccData_t* p_eccData)
    {
    uint8_t status = true;

    /* Allocate workzone memory for ecc, recommended workzone size is 275 bytes */
    uint8_t workzone[275*ECC_WINDOW_SIZE];

    memset(workzone, 0, 275*ECC_WINDOW_SIZE);

    /* Initialize ECC with a pointer to the allocated workzone */
    ECC_initialize((uint32_t *)workzone);

    /* Buffer for the private key generated */
    uint8_t eccPrivateKey[ROM_MODULE_KEY_LENGTH] = {8};

    memcpy(eccPrivateKey + ECC_KEY_LENGTH_OFFSET,myPrivateKeyingMaterial,ECC_KEY_LENGTH);

    /* Generate public key pair for this unit by using elliptic curve cryptography
    * The local private key is used as the random input, generating the same private key
    * as the local private key
    */
    status = ECC_generateKey((uint32_t *)eccPrivateKey,
    (uint32_t *)p_eccData->privateKey,
    (uint32_t *)p_eccData->publicKeyX,
    (uint32_t *)p_eccData->publicKeyY);



    if(status != ECC_ECDH_KEYGEN_OK) {
    /* generation of public key failed */
    return false;
    }



    return true;
    }

    code based on "ECDH_generatePublicKey  "

    ****************************************************

    uint8_t ecc_genKeys(eccData_t* p_eccData)
    {

    ecdhHandle = ECDH_open(0, NULL);
    if (!ecdhHandle) {
    // Handle error
    asm("nop");

    }

    /* Buffer for the private key generated */
    //uint8_t eccPrivateKey[ROM_MODULE_KEY_LENGTH] = {8};

    //gen32ByteRandomValue(myPrivateKeyingMaterial, CURVE_LENGTH);

    CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
    CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));

    ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);

    operationGeneratePublicKey.curve = &ECCParams_NISTP256;
    operationGeneratePublicKey.myPrivateKey = &myPrivateKey;//(CryptoKey*)(p_eccData->privateKey + ECC_KEY_LENGTH_OFFSET);
    operationGeneratePublicKey.myPublicKey = &myPublicKey;//(CryptoKey*)(p_eccData->publicKeyX + ECC_KEY_LENGTH_OFFSET);;

    // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
    operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
    if (operationResult != ECDH_STATUS_SUCCESS) {
    // Handle error
    asm("nop");
    }

    memcpy(p_eccData->privateKey + ECC_KEY_LENGTH_OFFSET,&myPrivateKeyingMaterial,CURVE_LENGTH );
    memcpy(p_eccData->publicKeyX + ECC_KEY_LENGTH_OFFSET,&myPublicKeyingMaterial,CURVE_LENGTH );

    return true;
    }

  • Hi Yaki,

    From the documentation on the Rom function (ECC_generateKey) and the ECDH driver (ECDH_generatePublicKey), the two function calls have different behavior so they can't be compared with respect to the output they generate. Correct me if I'm wrong:

    ECC_generateKey receives as input a buffer containing random data (randString) and uses this as entropy source to generate both private and public keys (privateKey and PubicKey_x/y).

    On the Contrary, ECDH_generatePublicKey receives an already final private key (operationGeneratePublicKey->myPrivateKey) and simply generate the associated public key (operationGeneratePublicKey->myPublicKey)

    Assuming you are providing the exact same data (myPrivateKeyingMaterial) and passing it as:

    • random string to ECC_generateKey
    • private key to ECDH_generatePublicKey

    you will not get the same public key, as the two function will be treating that buffer as a different element in the process of key generation.

    Regards,

    Fausto

  • Hi Fausto ,

    Thanks for your replay ,

    I understend my mistacke .

    My main problem is that today we have already released devices that used with ECC_generateKey function .

    and now I want to start use with ECDH_generatePublicKey according Sid recommendation .

    What the process I need to do to work with ECDH_generatePublicKey in system that used with ECC_generateKey ?

    My process today is based on ECC_generateKey 

    uint8_t ecc_genKeys(eccData_t* p_eccData)
    {
    uint8_t status = true;
    #if 1
    /* Allocate workzone memory for ecc, recommended workzone size is 275 bytes */
    uint8_t workzone[275*ECC_WINDOW_SIZE];

    memset(workzone, 0, 275*ECC_WINDOW_SIZE);

    /* Initialize ECC with a pointer to the allocated workzone */
    ECC_initialize((uint32_t *)workzone);

    /* Buffer for the private key generated */
    uint8_t eccPrivateKey[ROM_MODULE_KEY_LENGTH] = {8};

    /* Use TRNG to generate a new random private key */
    gen32ByteRandomValue(eccPrivateKey + ECC_KEY_LENGTH_OFFSET, ECC_KEY_LENGTH);

    memcpy(eccPrivateKey + ECC_KEY_LENGTH_OFFSET,myPrivateKeyingMaterial,ECC_KEY_LENGTH);

    /* Generate public key pair for this unit by using elliptic curve cryptography
    * The local private key is used as the random input, generating the same private key
    * as the local private key
    */
    status = ECC_generateKey((uint32_t *)eccPrivateKey,
    (uint32_t *)p_eccData->privateKey,
    (uint32_t *)p_eccData->publicKeyX,
    (uint32_t *)p_eccData->publicKeyY);



    if(status != ECC_ECDH_KEYGEN_OK) {
    /* generation of public key failed */
    return false;
    }
    #endif


    return true;
    }

    Please advice

    Yaki

  • Hi Yaki,

    If you are always generating a new key pair inside your function ecc_genKeys, starting from a randomly generated private key, what issue are you encountering when porting to the new ECDH driver? As long as the private and public key are generated correctly, I don't see the issue in creating the key pair using two APIs that behave slightly differently. At the end of ecc_genKeys you will still have a valid NISTP256 key pair, no matter which API you use.

    I believe the generateKeys function, available in the aesKeyAgreement example shows precisely how your function ecc_genKeys should be modified when using using the ECDH driver.

    Regards,

    Fausto

  • Hi Fausto ,

    We agree that if I used with the same  myPrivateKeyingMaterial as based key we need to get the same result from both API's ? 

    Below I show the process that I implement one is based on "ECC_generateKeys" (Old implementation ) and second based on "ECDH_generatePublicKey"

    In both  process I used with the same myPrivateKeyingMaterial as based key.

    Please see the code below :

    ********************************************

    Common key definition 

    ********************************************

    uint8_t myPrivateKeyingMaterial[CURVE_LENGTH] = {0x00, 0xCC, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0xBB, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE,
    0x00, 0xDD, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x01};

    typedef __packed struct
    {
    uint8_t publicKeyX[ROM_MODULE_KEY_LENGTH];
    uint8_t publicKeyY[ROM_MODULE_KEY_LENGTH];
    uint8_t privateKey[ROM_MODULE_KEY_LENGTH];
    }eccData_t;

    *********************************************

    Process based on "ECC_generateKeys "

    *********************************************

    uint8_t ecc_genKeys(eccData_t* p_eccData)
    {
                 uint8_t status = true;

                 /* Allocate workzone memory for ecc, recommended workzone size is 275 bytes */
                 uint8_t workzone[275*ECC_WINDOW_SIZE];

                memset(workzone, 0, 275*ECC_WINDOW_SIZE);

                /* Initialize ECC with a pointer to the allocated workzone */
               ECC_initialize((uint32_t *)workzone);

               /* Buffer for the private key generated */
               uint8_t eccPrivateKey[ROM_MODULE_KEY_LENGTH] = {8};

               memcpy(eccPrivateKey + ECC_KEY_LENGTH_OFFSET,myPrivateKeyingMaterial,ECC_KEY_LENGTH);

                /* Generate public key pair for this unit by using elliptic curve cryptography
                 * The local private key is used as the random input, generating the same private key
                 * as the local private key
                 */
                status = ECC_generateKey((uint32_t *)eccPrivateKey,
               (uint32_t *)p_eccData->privateKey,
               (uint32_t *)p_eccData->publicKeyX,
               (uint32_t *)p_eccData->publicKeyY);

               //******************************************************

               //All Keys stored in p_eccData parameter 

               //******************************************************

               if(status != ECC_ECDH_KEYGEN_OK) {
                  /* generation of public key failed */
                 return false;
                }

              return true;
    }

    ****************************************************

    Process  based on "ECDH_generatePublicKey  "

    ****************************************************

    uint8_t myPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};

    CryptoKey myPrivateKey;
    CryptoKey myPublicKey;

    ECDH_OperationGeneratePublicKey operationGeneratePublicKey;

    uint8_t ecc_genKeys(eccData_t* p_eccData)
    {

    ecdhHandle = ECDH_open(0, NULL);
    if (!ecdhHandle) {
    // Handle error
    asm("nop");

    }


    CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
    CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));

    ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);

    operationGeneratePublicKey.curve = &ECCParams_NISTP256;
    operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
    operationGeneratePublicKey.myPublicKey = &myPublicKey;

    // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
    operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
    if (operationResult != ECDH_STATUS_SUCCESS) {
    // Handle error
    asm("nop");
    }

    memcpy(p_eccData->privateKey + ECC_KEY_LENGTH_OFFSET,&myPrivateKeyingMaterial,CURVE_LENGTH );
    memcpy(p_eccData->publicKeyX + ECC_KEY_LENGTH_OFFSET,&myPublicKeyingMaterial,CURVE_LENGTH );

             //******************************************************

               //All Keys stored in p_eccData parameter 

               //******************************************************



    return true;
    }

    If you can, we can arrange a conference call.

    Thanks 

    Yaki

  • Hi Fausto ,

    I run the ECDH test and the process not work good 

    In email I sent you can see the common txPrivateKey and the output keys , they are  not the same .

    I run also my system with the new driver and the decryption not work good .

    Thanks 

    Yaki 

  • Hi Yaki, 

    I concluded my investigation regarding this issue and finally figured what was the mistake in the porting fro the rom_crypto library to the ECDH driver. 

    The rom_crypto library on CC1310 is using the ECC keys as little endian. This is not configurable therefore it is invisible to the user.

    On the contrary, in the ECDH driver for CC1312 the endianness of the key can be configured as a parameter in the ECDH_OperationGeneratePublicKey  that is passed to ECDH_generatePublicKey().

    The default for the keyMaterialEndianness field in ECDH_OperationGeneratePublicKey  is ECDH_BIG_ENDIAN_KEY, therefore if it not changed by the user, the public key generated will be different than the one generated on CC1310 with the rom_crypto library.

    I verified that the code below produces the same public key when providing the same private key:

    /* Generates private-public key pair and fill both inputs with the results */
    static int_fast16_t generateKeys(CryptoKey *privateKey, CryptoKey *publicKey)
    {
        int_fast16_t result;
        ECDH_Handle handle;
        ECDH_Params params;
        ECDH_OperationGeneratePublicKey operation;
    
        /* Use TRNG to generate a new random private key */
        //COM_generateRandomBytes(privateKey);
    
        /* Hard code the private for the sake of the experiment, without random generating it */
        CryptoKeyPlaintext_initKey(privateKey, (uint8_t *) myprivKey, PRIVATE_KEY_LENGTH);
        CryptoKeyPlaintext_initBlankKey(publicKey, mypubKey, PRIVATE_KEY_LENGTH * 2);
    
        ECDH_init();
        ECDH_Params_init(&params);
        params.returnBehavior = ECDH_RETURN_BEHAVIOR_BLOCKING;
        handle                = ECDH_open(CONFIG_ECDH_0, &params);
    
        ECDH_OperationGeneratePublicKey_init(&operation);
        operation.curve        = &ECCParams_NISTP256;
        operation.myPrivateKey = privateKey;
        operation.myPublicKey  = publicKey;
        operation.keyMaterialEndianness = ECDH_LITTLE_ENDIAN_KEY;
    
        /* Generate public key pair for this unit by using elliptic curve cryptography */
        result = ECDH_generatePublicKey(handle, &operation);
    
        ECDH_close(handle); 
        return result;
    }

    Note that when changing endianness to ECDH_LITTLE_ENDIAN_KEY, the public key size will have to be exactly twice the private key size (as it was in the rom_crypto library). This is different when using ECDH_BIG_ENDIAN_KEY (the default in the driver and what it is used in the aesKeyAgreement example) where the public key length is twice as long as the private key + 1 additional byte.

    Could you verify the above in your application as well and confirm that your issue is solved?

    Regards,

    Fausto