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.

LAUNCHXL-CC1310: rom_crypto.h usage with openssl keys

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310, UNIFLASH

Hi,

I am trying to verify a signature that was signed by ECDSACng Dot Net library, but it always return invalid signature with the same public key corresponding to the private key which signed the data.

After several rounds of ensuring the inputs to the verify function on cc1310 is correct, I realized that when I run ECC_generateKey() with a random string, the random string will always become the private key, with public keys x and y. 

I tried inputting the private key that was generated by OpenSSL which was used by ECDSACng Dot net library, into the ECC_generateKey() function on the CC1310, and as expected the random string became the private key, but what was interesting its the public key x and y were different as compared to the ones generated by OpenSSL. 

This is strange as I thought that private keys only correspond to a single public key x and y (correct me if im wrong on this) for ECC/RSA asymmetric key schemes. This could either mean the ECC curve parameter is different, or there is something wrong in the key generation function. I have checked the ecc curve scheme used in OpenSSL for key generation, ECDSACng dot net lib and the CC1310, and it all uses the same curve which is P-256/secp256r1/prime256v1.

So I am currently stuck, are the keys from the same curve but different library not compatible with CC1310 ecc rom functions? 

Edit: I was reviewing other questions, and I believe others have faced this issue of wrong public key generation too, see this. However the answer is pretty unsatisfactory as it just says it could be a possible bug in the library implentation

  • Just adding relevant information to this thread, I have checked the curves parameter in the NIST standards for P256 page 100, it corresponds to the memory values pointed to in driver lib file: /cpu/cc26x0-cc13x0/lib/cc26xxware/driverlib/rom_crypto.c . 

    It double confirms its the same curve and parameters. However the question still remains why I could call ECC_generateKey() resulting in the same private key but different public keys as when I did with OpenSSL library. 

    One point to note is that there are no problems with workzone memory allocation and all, because I have manage to sign and verify successfully on the CC1310, with using the above ECC_generatekey() call. But once I use the public and private keys from OpenSSL it does not work, even with signing and verifying on the device itself. 

  • Hi Ben,

    Could you share some code snippets (and maybe the test vectors you use) for me to look at and test out? Have you considered the "key length" offset of the input to ECC_generateKey()?

    Also, have you checked if there is a difference in endianness of the OpenSSL library and the CC1310 implementation?

  • Hi MW,

    Just to clarify on the key length offset, I've seen in examples its the first 4 bytes usually defined as 

    uint8_t pubx[ROM_MODULE_KEY_LENGTH] = {8};

    If you could explain to me if this the proper way, as the actual key length is 32 bytes, I do not know why in examples 8 is used. 

    I am sorry i cant really share test vectors as i just tried 3 different keys in my application that is built ontop of contiki. 

    I tried looking into the endianness too, i believe openssl outputs in bigendian-readable format, and cc1310 is small endian looking at the actual memory through uniflash memory browser. I did convert the big endian hex format to small by reversing every 4 bytes, but the public keys generated does not match the one that is created by openssl.

    Appreciate your help!

  • Hi Ben,

    Could you not share one of those keys and what result you expect? In other words, what is the private key you enter into both sides and what is your result? This would make it much easier for me to help you out debugging this.

    The 8 is due to the length being in "number of words" and not bytes. So 32 bytes = 8 words.

  • Hi MW,

    I've pmed you with the OpenSSL test keys and CC1310 outputs.

    Thanks,

    Ben 

  • Hi Ben, I tried this myself now and as long as I keep endianness in mind, I have no issue generating the same keys:

    OpenSSL output:

    Private-Key: (256 bit)
    priv:
    98:0e:d0:6f:aa:97:1f:24:cd:b9:c6:f1:02:06:8b:
    81:33:03:42:1c:bd:aa:5f:d8:a1:9d:cf:13:23:ee:
    2b:65

    pub:
    04:b0:b2:a7:f2:b6:22:36:b1:7e:dd:26:ca:bb:f7:
    63:2a:a2:c0:a2:35:d4:8e:32:f5:fd:81:52:8f:0c:
    18:20:8b:73:0c:9d:93:20:b2:17:dd:79:05:3d:75:
    d1:68:09:56:9a:92:c5:dc:7d:72:32:8d:53:47:51:
    5d:08:7e:34:16

    or if we separate it as Y and X:

    Y = 73:0c:9d:93:20:b2:17:dd:79:05:3d:75:
    d1:68:09:56:9a:92:c5:dc:7d:72:32:8d:53:47:51:
    5d:08:7e:34:16

    X = b0:b2:a7:f2:b6:22:36:b1:7e:dd:26:ca:bb:f7:

    63:2a:a2:c0:a2:35:d4:8e:32:f5:fd:81:52:8f:0c:
    18:20:8b

    Now I run ECC on the device with my reversed key (as I need it to be little-endian):

    uint8_t test_pric_key_rev[32] = {
    0x65, 0x2b, 0xee, 0x23, 0x13, 0xcf, 0x9d, 0xa1, 0xd8, 0x5f, 0xaa, 0xbd, 0x1c, 0x42, 0x03,
    0x33, 0x81, 0x8b, 0x06, 0x02, 0xf1, 0xc6, 0xb9, 0xcd, 0x24, 0x1f, 0x97, 0xaa, 0x6f, 0xd0,
    0x0e, 0x98
    };
    
    memcpy(&txPrivateKey[ECC_KEY_DATA_OFFSET_BYTES], test_again_rev, ECC_KEY_BYTES);
    
    
    /* Generate public key pair for this unit by using elliptic curve cryptography
    * The newly generated local private key is used as the input */
    status = ECC_generateKey((uint32_t *)txPrivateKey,
    (uint32_t *)txPrivateKey,
    (uint32_t *)rxPublicKeyX,
    (uint32_t *)rxPublicKeyY);

    The result is:

    txPublicKeyY = 16 34 7E 08 5D 51 47 53 8D 32 72 7D DC C5 92 9A 56 09 68 D1 75 3D 05 79 DD 17 B2 20 93 9D 0C 73

    txPublicKeyX =  8B 20 18 0C 8F 52 81 FD F5 32 8E D4 35 A2 C0 A2 2A 63 F7 BB CA 26 DD 7E B1 36 22 B6 F2 A7 B2 B0

    As you can see, the public keys are the same if you reverse the byte order to get matching endianness. 

  • Hi MW,

    Thanks for clarifying the endianness issue! Its a little confusing because from what I know is that endianness affects would cause changes to word-size chunks, not arbitrary lengths. Eg.

    Private-Key: (256 bit)
    priv:
    98:0e:d0:6f:aa:97:1f:24:cd:b9:c6:f1:02:06:8b:
    81:33:03:42:1c:bd:aa:5f:d8:a1:9d:cf:13:23:ee:
    2b:65 (big endian)

    would be 

    6f:d0:0e:98: 24:1f:97:aa:
    f1:c6:b9:cd: 81:8b:06:02:
    1c:42:03:33: d8:5f:aa:bd:
    13:cf:9d:a1: 65:2b:ee:23:  (small endian) (Words-size chunks are internally swapped)

    Final question, would the input to the hashing algorithm need be inputted as small endian too? Eg. b"HASHTHIS" hash input in a big endian system would be b"SIHTHSAH" input the small endian system ?  

  • Hi Ben,

    If I remember correctly OpenSSL treats arrays as a unit in terms of endianness. What I mean by this is that it does not consider the endianness of each word in the array, it treats the byte series as a whole as being big-endian. In other words, you swap the byte order of the array only, not the individual words. 

    Generally, you could assume any OpenSSL array being the wrong format and that you need to reverse the array byte order before doing the same operation on the CC1310 side.