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.

CC3235SF: Suggestions for creating a ECDSA-SHA256 signature on the CC3235SF

Part Number: CC3235SF
Other Parts Discussed in Thread: UNIFLASH,

Hi,

I have been trying to create a JWT (JSON Web Token) for Google's MQTT broker.  A portion of this is an ES256 (ECDSA-SHA256) signature that is then url-safe-base64 encoded.

Section 17.1.1.5  of the programmer's guide says that only a buffer can only be signed using ECDSA-SHA .

1)  I would like to verify the validity of this.

2) Should this be true, are there any plans to ad ECDSA-SHA256 signing?

3) If I create the SHA256 hash using the crypto peripheral (have successfully done this on this chip before), is there a library or source code (TI or 3rd party) that you could point me to that would sign that buffer using the ECC constant private key in the chip's key store?

Thanks in advance!

-Ben

  • Hi Ben,

    ECDSA-SHA256 is supported by the crypto utilities in the device from sp_3.6.0.3 and on. This is a mistake in the documentation and, as long as you are using the latest servicepack, you should be good to go.

    Best Regards,

    Ben M

  • Hi Ben,

    Thanks for the response.  I am starting to think I am not using the library correctly.  On a separate post I was told the following would do the SHA256 hash on the data fed into it and then EC sign it:

        /* create es256 signature of b64(h).b64(p): sha256(b64(h).b64(p)) */
        uint16_t bytes_written_ecc_signature = 255;
        uint8_t ecc_signature[256];
        memset(&ecc_signature[0], 0, 256);

        SlNetUtilCryptoCmdSignAttrib_t signAttrib;
        signAttrib.Flags = 0;
        signAttrib.ObjId = 1;
        signAttrib.SigType = SL_NETUTIL_CRYPTO_SIG_SHA256wECDSA;

        int err = sl_NetUtilCmd(SL_NETUTIL_CRYPTO_CMD_SIGN_MSG,
                      (uint8_t *)&signAttrib,
                      sizeof(SlNetUtilCryptoCmdSignAttrib_t),
                      (const uint8_t *) &jwt[0],
                      strlen(&jwt[0]),
                      &ecc_signature[0],
                      &bytes_written_ecc_signature);

    I have loaded my own EC key pair (secp256r1) via UniFlash, I then added it to the key store with the following code:

        SlNetUtilCryptoCmdKeyMgnt_t keyAttrib;
        SlNetUtilCryptoPubKeyInfo_t *pInfoKey = NULL;

        _i16 Status;
        _u8 buf[256];
        _u16 resultLen;

        _u8 *name;

        keyAttrib.ObjId = 1; /* key index is 1 */
        keyAttrib.SubCmd = SL_NETUTIL_CRYPTO_INSTALL_SUB_CMD;

        pInfoKey->KeyAlgo = SL_NETUTIL_CRYPTO_PUB_KEY_ALGO_EC;
        pInfoKey->KeyParams.EcParams.CurveType = SL_NETUTIL_CRYPTO_EC_CURVE_TYPE_NAMED;
        pInfoKey->KeyParams.EcParams.CurveParams.NamedCurveParams = SL_NETUTIL_CRYPTO_EC_NAMED_CURVE_SECP256R1;
        pInfoKey = (SlNetUtilCryptoPubKeyInfo_t *)buf;

        name = ((_u8 *)pInfoKey) + sizeof(SlNetUtilCryptoPubKeyInfo_t);

        pInfoKey->KeyAlgo = SL_NETUTIL_CRYPTO_PUB_KEY_ALGO_EC;
        pInfoKey->KeyParams.EcParams.CurveType = SL_NETUTIL_CRYPTO_EC_CURVE_TYPE_NAMED;
        pInfoKey->KeyParams.EcParams.CurveParams.NamedCurveParams = SL_NETUTIL_CRYPTO_EC_NAMED_CURVE_SECP256R1;
        pInfoKey->CertFileNameLen = 0; /* unused */

        name += pInfoKey->CertFileNameLen;

        strcpy((char *)name, "private-key.der"); /* private key in the file system */

        pInfoKey->KeyFileNameLen = strlen("private-key.der")+1;

        Status = sl_NetUtilCmd(SL_NETUTIL_CRYPTO_CMD_INSTALL_OP, (_u8 *)&keyAttrib, sizeof(SlNetUtilCryptoCmdKeyMgnt_t), (_u8 *)pInfoKey,   sizeof(SlNetUtilCryptoPubKeyInfo_t) + pInfoKey->KeyFileNameLen, NULL, &resultLen);
        if(Status < 0)
        {
        /* error */
        }

    I am still getting invalid signatures.  Is there something trivial I am missing?  Do I have to explicitly initialize the crypto peripheral for the SL_NETUTIL_CRYPTO_SIG_SHA256wECDSA to be able to do its hash?

    Thanks,

    Ben

  • Hi Ben,

    No, since this triggers the operation inside the network processor you don't have to initialize any hardware from the application. The device uses the signature type you specify to determine which algorithm to use.

    Can you run a quick test with the built-in unique key-pair (index 0) to isolate the key-installation step from the issue?

    Thanks,
    Ben M

  • Hi Ben,

    That's not an issue.  The only issue would be properly converting the X9.63 raw format of the built in public key to a .der format and then ultimately to a .pem format. This is what our MQTT broker supports.  I know there are bytes prior to the 65 of the public key (I know the 0x04 indicates uncompressed) if you want to create a .der.

    If you could point me to some information on how to do that successful, I can give it a shot.  This is also an area of confusion.

    Thanks,

    Ben

  • Hi Ben,

    I have written some test code that outputs the base64 encoded signature of a test buffer using the built in ECC key:

        uint16_t bytes_written_ecc_signature = 255;
        uint8_t ecc_signature[256];
        memset(&ecc_signature[0], 0, sizeof(ecc_signature));

        char test_buffer[] = "this is a test buffer";
        char base64_encoded_test_buffer[128];
        size_t encoded_data_size;
        SlNetUtilCryptoCmdSignAttrib_t signAttrib;

        signAttrib.Flags = 0;
        signAttrib.ObjId = 0;
        signAttrib.SigType = SL_NETUTIL_CRYPTO_SIG_SHA256wECDSA;

        sl_NetUtilCmd(SL_NETUTIL_CRYPTO_CMD_SIGN_MSG,
                      (uint8_t *)&signAttrib,
                      sizeof(SlNetUtilCryptoCmdSignAttrib_t),
                      (const uint8_t *) &jwt[0],
                      strlen(&test_buffer[0]),
                      &ecc_signature[0],
                      &bytes_written_ecc_signature);

        memset(&base64_encoded_test_buffer[0], 0, sizeof(base64_encoded_test_buffer));

        StrMpl_encodeBase64(&ecc_signature[0],
                            bytes_written_ecc_signature,
                            (uint8_t*) &base64_encoded_test_buffer[0],
                            &encoded_data_size);

        Message("\n\r");
        Message(&base64_encoded_test_buffer[0]);
        Message("\n\r");

    Using the built in key produces this:

    MEYCIQCr_4vdR1ZEoBYkC9EYFgB7ht-u2d0YD_-TGICkOzhI3AIhAPeaFqsGJ7Ok6kv8rzhK6WJ0LraP5Pln8i2E2EEwyL1J

  • Hi Ben,

    I found a decent amount of source code to do this in OtaArchive.c.  I will give this a shot and see how it goes.

    Thanks,

    Ben

  • Hi Ben,

    Thanks for the updates. Apologies for not being able to get back to you on this yet. I still need to go through your latest responses. I will plan to follow-up before the end of the day tomorrow.

    Best,
    Ben M

  • Hi Ben,

    Looking back at the code you are using to install the key, I notice that you set pInfoKey to NULL when you declare it and then you have some code that starts setting some of the info attributes. Was that a copy-paste error?

    It looks like later you re-write those values, so I assume you aren't actually using the pointer while it's NULL.

    I found your other post here and I think this background helps: https://e2e.ti.com/support/wireless-connectivity/wifi/f/968/t/897756

    It seems you already have functions for converting the device public key from raw x9.63 format to .der (and ultimately .pem) to be used by your server. Are you still wondering if this conversion was done successfully? Is your test for this not successful?

    Let me know if referencing the OTA example helped. I know its usefulness may be limited because it is only for verifying the signature on the OTA vs. your case which is signing a data buffer.

    Best Regards,

    Ben M

  • Hi Ben,

    Thank you for your response.  The pointer is initialized to NULL.  I should probably make it an actual variable instead of a pointer and convert the code.

    I think I am at the point where I do not trust my x9.63 / .der conversions, either way.  I realize a .pem file is a header and a footer with the base64 encoded key in the middle.  The part I am uncertain of is the addiction bytes preceding the raw x9.63 to make it basically un-raw and a full .pem.  Not sure if that makes sense?  I have searched the web for this info, but have had no luck; do you know of any resources to assist?

    Thanks,

    Ben

  • Hi Ben,

    Are you needing the raw public key in .der format, or do you actually need a certificate with the public key? Do you think that using the certificate signing request feature and generating an actual certificate would work for you?

    http://dev.ti.com/tirex/explore/node?node=AMpkGCJkwCqQ.cWUJcYKJA__fc2e6sr__LATEST

    Best,

    Ben M

  • Hi Ben,

    Essentially, I just need the raw key to go to .der formate and I can convert it to .pem from there.  I don't think the CSR demo is applicable as I already have a root CA from Google for the TLS connection; this is working.

    The raw key from the chip, that would be converted to .der, then to .pem would go to Google for a specific device so that Google can verify a JSON Web Token, generated on that device using the chip's private key (contains an ES256 signature).

    Thanks in advance,

    Ben

  • The following shell script converts an hex formatted raw key to both der and pem public key formats: 

    ###### Get a public key - based on the user input

    ###### example usage : "<script-name>.sh  04489541c4d1ec.......f73b6479b76"

    # add public key prefix for prime256v1
    echo 3059301306072a8648ce3d020106082a8648ce3d030107034200 | xxd -r -p > pub_key.der

    # add the binary key
    echo $1 | xxd -r -p >> pub_key.der
    openssl pkey -pubin -inform DER -in pub_key.der -out pub_key.pem

  • Hi Kobi and Ben,

    Much appreciated!  I would like to finalize this thread...  Is there a way I can test my CC3235SF ECDSA-256 signature of data against something else?  I have generated a prime256v1 key pair in OpenSSL, loaded it into my devboard, and used this for my signature; that way I have access to the private key.

    We're in critical path and may have to ditch this library for something else.  We would like to avoid that as it has a ton of repercussions on our project and its timeline.

    Thanks for your time,

    -Ben