ECC create key, sign and verify sample code

Hi everybody

I want to implement the ECC creation key, sign and verify purpose. But I didn't find sample code in google or in the renesas website.

Does some people who already implement these things ?

Someone have a small example code to start ?

Thanks

  • Hi Tomtom,

     

    Here is an example of how to use the HAL layer ECC to generate keys then sign and verify.

    /* HAL-only entry function */
    #include "hal_data.h"
    #include "string.h"

    /* Recommended Parameters secp256k1
    *
    * Curve E: y^2 = x^3 +ax + b
    *
    */
    uint8_t domain[ECC_256_DOMAIN_PARAMETER_WITH_ORDER_LENGTH_WORDS * sizeof(uint32_t)] =
    {
    /* a */
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    /* b */
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
    /* p = 2^192-2^64-1 */
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
    /* n */
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
    0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
    };
    /*
    *
    * Base Point G (uncompressed)
    *
    */
    uint8_t generator_point[ECC_256_GENERATOR_POINT_LENGTH_WORDS * sizeof(uint32_t)] =
    {
    /* x */
    0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,
    0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
    0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
    /* y */
    0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,
    0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
    0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,
    };

    static uint8_t public_key[ECC_256_PUBLIC_KEY_LENGTH_WORDS * sizeof(uint32_t)]; // plain text key
    static uint8_t wrapped_private_key[ECC_256_PRIVATE_KEY_HRK_LENGTH_WORDS * sizeof(uint32_t)]; // wrapped key


    void hal_entry(void)
    {
    ssp_err_t status;
    /*
    * Create the data handles that the crypto layer uses to access the data
    */
    r_crypto_data_handle_t domain_handle = {(uint32_t *) domain, sizeof(domain)/sizeof(uint32_t)};
    r_crypto_data_handle_t generator_point_handle ={(uint32_t *) generator_point, sizeof(generator_point)/sizeof(uint32_t)};
    r_crypto_data_handle_t public_key_handle = {(uint32_t *) public_key, sizeof(public_key)/sizeof(uint32_t)};
    r_crypto_data_handle_t wrapped_private_key_handle = {(uint32_t *) wrapped_private_key, sizeof(wrapped_private_key)/sizeof(uint32_t)};


    /*
    * We must open the SCE common driver before any crypto operations
    */
    status = g_sce.p_api->open(g_sce.p_ctrl, g_sce.p_cfg);
    if (status)
    __BKPT();

    /*
    * Open the ECC driver
    */
    status = g_sce_ecc_0.p_api->open( g_sce_ecc_0.p_ctrl, g_sce_ecc_0.p_cfg);
    if (status)
    __BKPT();

    /*
    * Create the key pair
    */
    status = g_sce_ecc_0.p_api->keyCreate(g_sce_ecc_0.p_ctrl, &domain_handle, &generator_point_handle, &wrapped_private_key_handle, &public_key_handle);
    if (status)
    __BKPT();

    /*
    * Sign the message digest (hash of a data message)
    *
    * This is a common use case to verify the identity of the sender of a blob of data if we know the public key of the sender
    * The sender would generate a hash over the blob of data and then sign the hash with the private key. The recipient of the blob & the signed hash
    * would then use the public key to verify the signature of the hash and then use the hash to verify the blob of data is correct.
    *
    */
    uint8_t message_digest [ECC_256_MESSAGE_DIGEST_LENGTH_WORDS * sizeof(uint32_t)] = {
    0x7f, 0xed, 0x57, 0x68, 0xb2, 0x85, 0xc9, 0xa2, 0x5b, 0xf0, 0x07, 0xf7, 0x9d, 0x32, 0x48, 0xb5,
    0x5e, 0xba, 0x61, 0x8d, 0xfa, 0x40, 0x52, 0x7d, 0xda, 0x58, 0x0a, 0x32, 0x55, 0x56, 0xcd, 0x10
    };

    uint8_t sign_r[ECC_256_SIGNATURE_R_LENGTH_WORDS * sizeof(uint32_t)];
    uint8_t sign_s[ECC_256_SIGNATURE_S_LENGTH_WORDS * sizeof(uint32_t)];

    /*
    * Create the data handles that the crypto layer uses to access the data
    */
    r_crypto_data_handle_t message_digest_handle = {(uint32_t *) message_digest, ECC_256_MESSAGE_DIGEST_LENGTH_WORDS};
    r_crypto_data_handle_t sign_r_handle = {(uint32_t *) sign_r, ECC_256_SIGNATURE_R_LENGTH_WORDS};
    r_crypto_data_handle_t sign_s_handle = {(uint32_t *) sign_s, ECC_256_SIGNATURE_S_LENGTH_WORDS};

    status = g_sce_ecc_0.p_api->sign(g_sce_ecc_0.p_ctrl, &domain_handle, &generator_point_handle, &wrapped_private_key_handle, &message_digest_handle, &sign_r_handle, &sign_s_handle);
    if (status)
    __BKPT();

    /*
    * Verify the signature
    *
    * This would normally be on a different system...
    *
    */
    status = g_sce_ecc_0.p_api->verify(g_sce_ecc_0.p_ctrl, &domain_handle, &generator_point_handle, &public_key_handle, &message_digest_handle, &sign_r_handle, &sign_s_handle);
    if (status)
    __BKPT();

    }

     

    -Gary