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.

CC2640R2F: CC2640R2

Part Number: CC2640R2F
Other Parts Discussed in Thread: CC2640

I’m in the process to revive the security code from an older project to the a new project using sdk 4.10.0.10

The older project uses sdk 2.2.0.31 and supports ECC_ECDSA_sign(),  ECC_ECDSA_verify() ROM functions.

 

With the same app building with sdk4.10.0.10, I encountered these link errors below.

 

Since these are supported in the ROM and using the same device, these functions should be supported but maybe the name has changed to eccRom_signHash(), eccRom_verifyHash() resp. The function prototype for eccRom_verifyHash() seems to match ECC_ECDSA_verify(). Please confirm that to be the case.

 

If so, I can see an example on eccRom_verifyHash() usage in sign_util.c file -  function bimVerifyImage_ecc(), but when I just substitute the name change in my app, the code crashes.

 

is this large enough for sign and verify ?

uint8_t workZone[288*4];

do we need 2 times for eccWorkzone and tempWorkzone ?

Also, I like to see an example on how to generate an ECC signature by using the eccRom_signHash().

 

Tony

 

 

// this is the sdk2.2.0.31 function prototype

//*****************************************************************************
/*!
 * \brief Sign data.
 *
 * \param secretKey  Pointer to the secret key, input.
 * \param text       Pointer to the message, input.
 * \param randString Pointer to random string, input.
 * \param sign1      Pointer to signature part 1, output.
 * \param sign2      Pointer to signature part 2, output.
 *
 * \return Status
 */
//*****************************************************************************
extern uint8_t ECC_ECDSA_sign(uint32_t *secretKey, uint32_t *text, uint32_t *randString,
                              uint32_t *sign1, uint32_t *sign2);

//*****************************************************************************
/*!
 * \brief Verify signature.
 *
 * \param publicKey_x Pointer to public key X-coordinate, input.
 * \param publicKey_y Pointer to public key Y-coordinate, input.
 * \param text        Pointer to message data, input.
 * \param sign1       Pointer to signature part 1, input.
 * \param sign2       Pointer to signature part 2, input.
 *
 * \return Status
 */
//*****************************************************************************
extern uint8_t ECC_ECDSA_verify(uint32_t *publicKey_x, uint32_t *publicKey_y,
                                uint32_t *text, uint32_t *sign1, uint32_t *sign2);

 

 

Performing Pre-Build Action

Linking

Error[Li005]: no definition for "ECC_ECDSA_sign" [referenced from 

C:\svn\L3_Reader\cc2640\simplelink_cc2640r2_sdk_4_10_00_10\

project\L3_SC_Reader\tirtos\iar\app\FlashROM_StackLibrary\Obj\

cgm_crypto.o]

Error[Li005]: no definition for "ECC_ECDSA_verify" [referenced 

from C:\svn\L3_Reader\cc2640\simplelink_cc2640r2_sdk_4_10_00_10\

project\L3_SC_Reader\tirtos\iar\app\FlashROM_StackLibrary\Obj\

cgm_crypto.o]


 

 

  • Hi Tony,

    I assume you are looking at the BLE BIM? In that case yes, it seems they have changed the name of the internal ecc ROM symbols, the function remains the same (as it is in ROM). 

    If using the NIST P256 curve and a window size of 3, the workzone size you suggest should be OK.

    Could you give some more information on your application, like if you are using the BLE stack and BIM or if you are doing something else?

  • Yes, I'm looking at the sign_util.c as a reference.

    Our application is a glucose reader that communicates with the sensor over BLE. The reader has a host processor that communicates to the CC2640 over a UART interface and the CC2640 code is downloaded via the host processor and not over the BLE.

    The BLE application for our sensor and reader does not use the BLE 4.2 security and we designed in our security application layer, so we're only using the BLE stack up to the GAP, GATT and not SM stack. Our application layer security uses much of the ECC rom functions to do mutual authentication, SHA 2 hash, ECC key generation, ECC DH, ECC sign and verify.

    In the last project, I had written some test code to verify the ECC ROM functions can produce the same results with openssl libraries so I know that the CC2640 ECC ROM functions were working. In the new project I was able to re-test all previously used ECC and SHA related functions except ECC_ECDSA_sign() and ECC_ECDSA_verify(). At first these 2 functions gave me a linker error and after changing the function names to  eccRom_signHash and eccRom_verifyHash the linker errors are gone but when executing these functions the code crashes. 

    Enclosed is the test_crypto.c used in the unit test for the CC2640 ROM crypto functions used in our application.

    /*********************************************************************
    * INCLUDES
    */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    #ifdef DEBUG
    #include <driverlib/ioc.h>
    #endif // DEBUG
    
    #include "hci_tl.h"
    #include "gatt.h"
    #include "gapgattserver.h"
    #include "gattservapp.h"
    #include "gatt_uuid.h"
    #include "devinfoservice.h"
    //#include "cgmservice.h"
    //#include "secservice.h"
    #include "sha2cc26xx.h"
    
    //#include "cgm_multi.h"
    #include "gapbondmgr.h"
    
    #include "osal_snv.h"
    #include "icall_ble_apimsg.h"
    
    //#include <ti/mw/display/Display.h>
    #include "util.h"
    #include "board_key.h"
    #include "Board.h"
    
    #include "serial.h"
    #include "btle_cmd.h"
    #include "ble_reader.h"
    
    #define PRIVATE_KEY_SIZE	32
    #define PUBLIC_KEY_X_SIZE		32
    #define PUBLIC_KEY_Y_SIZE		32
    #define PUBLIC_KEY_SIZE		(PUBLIC_KEY_X_SIZE+PUBLIC_KEY_Y_SIZE)
    #define SIGNATURE_SIZE		64
    #define SHARED_kEY_SIZE		32
    
    #if 0
    typedef	struct
    {
        uint8   descriptor;
        uint8   key[PUBLIC_KEY_SIZE];
    } publicKey;
    
    typedef	struct
    {
        uint8   key[PRIVATE_KEY_SIZE];
    } privateKey;
    #endif
    
    #if 1
    struct
    {
        uint8_t counter[4];
        uint8_t Ze[SHARED_kEY_SIZE];
        uint8_t Zs[SHARED_kEY_SIZE];
    } kdef;
    
    static CryptoCC26XX_Handle handle;
    #if 0
    static uint8_t nonce[CGM_NONCE_LEN]; // always 13
    static uint8_t cipherText[CHALLENGE_RESPONSE_LEN+CHALLENGE_TAG_LEN];  // use the largest one from decrypt challenge response
    static CryptoCC26XX_AESCCM_Transaction trans;
    #endif
    
    static uint8_t * eccMalloc(uint16_t len);
    static void eccFree(void *fp);
    static void eccSwapByte32(uint8_t * p);
    
    // used in ECDH
    static uint8_t sharedKeyX[SHARED_kEY_SIZE];
    static uint8_t sharedKeyY[SHARED_kEY_SIZE];
    #endif
    
    #define ECC_ECDSA_verify eccRom_verifyHash
    #define ECC_ECDSA_sign eccRom_signHash
    #define SHA256_runFullAlgorithm SHA2CC26XX_runFullAlgorithm
    
    
    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    
    #if 0
    //*****************************************************************************
    /*!
     * \brief Sign data.
     *
     * \param secretKey  Pointer to the secret key, input.
     * \param text       Pointer to the message, input.
     * \param randString Pointer to random string, input.
     * \param sign1      Pointer to signature part 1, output.
     * \param sign2      Pointer to signature part 2, output.
     *
     * \return Status
     */
    //*****************************************************************************
    uint8_t ECC_ECDSA_sign(uint32_t *secretKey, uint32_t *text, uint32_t *randString,
                                  uint32_t *sign1, uint32_t *sign2)
    {
    }
    
    //*****************************************************************************
    /*!
     * \brief Verify signature.
     *
     * \param publicKey_x Pointer to public key X-coordinate, input.
     * \param publicKey_y Pointer to public key Y-coordinate, input.
     * \param text        Pointer to message data, input.
     * \param sign1       Pointer to signature part 1, input.
     * \param sign2       Pointer to signature part 2, input.
     *
     * \return Status
     */
    //*****************************************************************************
    uint8_t ECC_ECDSA_verify(uint32_t *publicKey_x, uint32_t *publicKey_y,
                                    uint32_t *text, uint32_t *sign1, uint32_t *sign2)
    {
    }
    #endif
    
    
    void getRandomNumber(uint8_t *p, uint8_t len)
    {
    	uint32_t random;
    	
    	if ((len % 4) == 0)
    	{
    		while (len)
    		{
    			random = Util_GetTRNG();
    
    			memcpy (p, &random, 4);
    
    			p += 4;
    			len -= 4;
    		}
    	}
    }
    
    // according to TI, the SHA256 success return code is 0x77
    #define SHA256_SUCCESS	0x77
    int genSHA256(uint8_t * input, uint8_t len, uint8_t * output)
    {
    	int8_t status;
    	SHA256_memory_t sha256WorkMem;
    	
    	// this function returns 0x77 when successful
    	status =  SHA256_runFullAlgorithm(&sha256WorkMem, input, len, output);
    
    	return (status == SHA256_SUCCESS) ? ECCROMCC26XX_STATUS_SUCCESS : status;
    }
    
    int8_t genEccKeys(uint8_t *privateKey, uint8_t *publicKey)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	// gen a random number for private key
    	getRandomNumber(privateKey, PRIVATE_KEY_SIZE);
    
    	bsPublicKeyX = publicKey;
    	bsPublicKeyY = &publicKey[PUBLIC_KEY_X_SIZE];
    	
    	eccSwapByte32(privateKey);
    	eccSwapByte32(bsPublicKeyX);
    	eccSwapByte32(bsPublicKeyY);
    
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	status = ECCROMCC26XX_genKeys(privateKey, bsPublicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		eccSwapByte32(privateKey);
    		eccSwapByte32(bsPublicKeyX);
    		eccSwapByte32(bsPublicKeyY);
    
    		sendPrintBytes(privateKey, 32);
    		sendPrintBytes(bsPublicKeyX, 32);
    		sendPrintBytes(bsPublicKeyY, 32);
    	}
    	return status;
    }
    
    int8_t genPublicKeyFromPrivate(uint8_t *privateKey, uint8_t *publicKey)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	bsPublicKeyX = publicKey;
    	bsPublicKeyY = &publicKey[PUBLIC_KEY_X_SIZE];
    	
    	eccSwapByte32(privateKey);
    	eccSwapByte32(bsPublicKeyX);
    	eccSwapByte32(bsPublicKeyY);
    
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	status = ECCROMCC26XX_genKeys(privateKey, bsPublicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		eccSwapByte32(privateKey);
    		eccSwapByte32(bsPublicKeyX);
    		eccSwapByte32(bsPublicKeyY);
    
    		sendPrintBytes(privateKey, 32);
    		sendPrintBytes(bsPublicKeyX, 32);
    		sendPrintBytes(bsPublicKeyY, 32);
    	}
    
    	return status;
    }
    
    static void eccSwapByte32(uint8_t * p)
    {
    	uint8_t buffer[32];
    	int i;
    
    	for (i=0; i<32; i++)
    	{
    		buffer[i] = p[31-i];
    	}
    
    	memcpy (p, buffer, 32);
    }
    
    int genDHKey(uint8_t * privateKey, uint8_t * publicKeyX, uint8_t * publicKeyY, uint8_t * shareKeyX, uint8_t * shareKeyY)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	eccSwapByte32(privateKey);
    	eccSwapByte32(publicKeyX);
    	eccSwapByte32(publicKeyY);
    
    	// Generate shared secret.
    	status = ECCROMCC26XX_genDHKey(privateKey, publicKeyX,
    	                        publicKeyY, shareKeyX,
    	                        shareKeyY, &params);
    
    	eccSwapByte32(shareKeyX);
    	eccSwapByte32(shareKeyY);
    
    	eccSwapByte32(privateKey);
    	eccSwapByte32(publicKeyX);
    	eccSwapByte32(publicKeyY);
    	
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintBytes(privateKey, 32);
    		sendPrintBytes(publicKeyX, 32);
    		sendPrintBytes(publicKeyY, 32);
    		sendPrintBytes(shareKeyX, 32);
    		sendPrintBytes(shareKeyY, 32);
    	}
    	return status;
    }
    
    void startECDH(readerInfo_t *ri, patchInfo_t *pi, uint8_t * sharedSecret)
    {
    	int8_t status;
            
    	status = genDHKey(ri->staticPrivate.key, pi->staticCert.ECCPubKey.key, &pi->staticCert.ECCPubKey.key[PUBLIC_KEY_X_SIZE], sharedKeyX, sharedKeyY);
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		memcpy (kdef.Zs, sharedKeyX, SHARED_kEY_SIZE);
    	}
    	else
    	{
    		memset (kdef.Zs, 0, SHARED_kEY_SIZE);
    
    		sendPrintString("genDHKey Static failed");
    		sendPrintBytes(&status, 1);
    	}
    
    	status = genDHKey(ri->ephemeralPrivate.key, pi->ephemeralPublic.key, &pi->ephemeralPublic.key[PUBLIC_KEY_X_SIZE], sharedKeyX, sharedKeyY);
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		memcpy (kdef.Ze, sharedKeyX, SHARED_kEY_SIZE);
    	}
    	else
    	{
    		memset (kdef.Ze, 0, SHARED_kEY_SIZE);
    
    		sendPrintString("genDHKey Ephemeral failed");
    		sendPrintBytes(&status, 1);
    	}
    
    	// KDF function
    	// set counter to big endian 0x00000001
    	kdef.counter[0] = 0x00;
    	kdef.counter[1] = 0x00;
    	kdef.counter[2] = 0x00;
    	kdef.counter[3] = 0x01;
    
    	status = genSHA256((uint8_t *)&kdef, sizeof(kdef), sharedSecret);
    	if (status != ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		memset (sharedSecret, 0, 32);
    
    		sendPrintString("genSHA256 failed");
    		sendPrintBytes(&status, 1);
    	}
    }
    
     int8_t decryptCgmData(patchInfo_t *pi, uint8 * data)
    {
    	int8_t status;
    	uint8_t nonce[CGM_NONCE_LEN];
           uint8_t cipherText[CGM_PAYLOAD_LEN+CGM_TAG_LEN];
           CryptoCC26XX_AESCCM_Transaction trans;
           cgmCryptoPacket *p;
    
    	memset (nonce, 0, sizeof(nonce));
    	memset (cipherText, 0, sizeof(cipherText));
    	
    	p = (cgmCryptoPacket*) data;
    	memcpy (nonce, p->cryptoSequence, CGM_CRYPTO_SEQ_LEN);
    	memcpy (nonce+5, pi->keys.IV_enc, sizeof(pi->keys.IV_enc));
    
    	memcpy(cipherText, p->payload, CGM_PAYLOAD_LEN);
    	memcpy(cipherText+CGM_PAYLOAD_LEN, p->payloadTag, CGM_TAG_LEN);
    	
    	// setup trans for decryption
    	CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    	
    	trans.keyIndex   = pi->keyIndex[0];
    	trans.authLength = CGM_TAG_LEN;
    	trans.nonce  = (char *) nonce;
    	trans.header = (char *) NULL;
    	trans.fieldLength  = 15-CGM_NONCE_LEN;
    	trans.msgInLength  = CGM_PAYLOAD_LEN+CGM_TAG_LEN;
    	trans.headerLength = 0;
    	trans.msgIn  = (char *) &cipherText[0];        // Message is encrypted in place
    	trans.msgOut = (char *) &cipherText[CGM_PAYLOAD_LEN];  // MAC will be written to this position
    
    	// Do AES-CCM operation
    	status = CryptoCC26XX_transact(pi->handle, (CryptoCC26XX_Transaction *) &trans);
    	if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    	{
    		memcpy (p->payload, cipherText, CGM_PAYLOAD_LEN);
    	}
    
    	return status;
    }
    
    int8_t decryptRetroData(patchInfo_t *pi, uint8 * data)
    {
    	int8_t status;
    	uint8_t nonce[CGM_NONCE_LEN];
    	uint8_t cipherText[CGM_PAYLOAD_LEN+CGM_TAG_LEN];
    	CryptoCC26XX_AESCCM_Transaction trans;
    	retroCryptoPacket *p;
    
    	memset (nonce, 0, sizeof(nonce));
    	memset (cipherText, 0, sizeof(cipherText));
    
    	p = (retroCryptoPacket*) data;
    	memcpy (nonce, p->dataDescriptor, CGM_DATA_DESCRIPTOR_LEN);
    	nonce[2] = 0xff;
    	nonce[3] = 0xff;
    	nonce[4] = 0xff;
    	memcpy (&nonce[5], pi->keys.IV_enc, sizeof(pi->keys.IV_enc));
    
    	memcpy(cipherText, p->payload, CGM_PAYLOAD_LEN);
    	memcpy(cipherText+CGM_PAYLOAD_LEN, p->payloadTag, CGM_TAG_LEN);
    
    	// setup trans for decryption
    	CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    
    	trans.keyIndex   = pi->keyIndex[0];
    	trans.authLength = CGM_TAG_LEN;
    	trans.nonce  = (char *) nonce;
    	trans.header = (char *) NULL;
    	trans.fieldLength  = 15-CGM_NONCE_LEN;
    	trans.msgInLength  = CGM_PAYLOAD_LEN+CGM_TAG_LEN;
    	trans.headerLength = 0;
    	trans.msgIn  = (char *) &cipherText[0];        // Message is encrypted in place
    	trans.msgOut = (char *) &cipherText[CGM_PAYLOAD_LEN];  // MAC will be written to this position
    
    	// Do AES-CCM operation
    	status = CryptoCC26XX_transact(pi->handle, (CryptoCC26XX_Transaction *) &trans);
    	if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    	{
    		memcpy (p->payload, cipherText, CGM_PAYLOAD_LEN);
    	}
    
    	return status;
    }
    
    int8_t encryptChallengeData(patchInfo_t *pi, challengeDataPacket * p, encryptedChallengeDataPacket* r)
    {
    	int8_t status;
    	uint8_t nonce[CHALLENGE_NONCE_LEN+CHALLENGE_NONCE_PAD];
           uint8_t cipherText[CHALLENGE_PAYLOAD_LEN+CHALLENGE_TAG_LEN];
           CryptoCC26XX_AESCCM_Transaction trans;
    
    	uint8_t *pp;
    	pp = (uint8_t *)p;
    
    	sendPrintBytes(pp, 16);
    	sendPrintBytes(pp+16, 16);
    	sendPrintBytes(pp+32, 4);
    	sendPrintBytes(pp+36, 7);
    
    	memset (nonce, 0, sizeof(nonce));
    	memset (cipherText, 0, sizeof(cipherText));
    
    	memcpy(nonce, p->nonce, CHALLENGE_NONCE_LEN);
    	memcpy(cipherText, p, sizeof(challengeDataPacket) - CHALLENGE_NONCE_LEN);
    	
    	// setup trans for decryption
    	CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCM);	
    	trans.keyIndex   = pi->keyIndex[1];
    	trans.authLength = CHALLENGE_TAG_LEN;
    	trans.nonce  = (char *) nonce;
    	trans.header = (char *) NULL;
    	trans.fieldLength  = 15-CHALLENGE_NONCE_LEN;
    	trans.msgInLength  = CHALLENGE_PAYLOAD_LEN;
    	trans.headerLength = 0;
    	trans.msgIn  = (char *) cipherText;        // Message is encrypted in place
    	trans.msgOut = (char *) &cipherText[CHALLENGE_PAYLOAD_LEN];  // MAC will be written to this position
    
    	// Do AES-CCM operation
    	status = CryptoCC26XX_transact(pi->handle, (CryptoCC26XX_Transaction *) &trans);
    	if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    	{
    		memcpy (r->R1, cipherText, CHALLENGE_PAYLOAD_LEN);
    		memcpy (r->TAG, cipherText+CHALLENGE_PAYLOAD_LEN, CHALLENGE_TAG_LEN);
    
    		sendPrintBytes(r->R1,CHALLENGE_PAYLOAD_LEN);
    		sendPrintBytes(r->TAG,CHALLENGE_TAG_LEN);
    	}
    	else
    	{
    		sendPrintString("CryptoCC26XX_transact failed");
    		sendPrintDebug(status, trans.keyIndex, trans.authLength,0,0);
    	}
    	
    
    	return status;
    }
    
    int8_t decryptChallengeResponse(patchInfo_t *pi, encryptedChallengeResponsePacket *p)
    {
    	int8_t status;
    	uint8_t nonce[CHALLENGE_NONCE_LEN+CHALLENGE_NONCE_PAD];
           uint8_t cipherText[CHALLENGE_RESPONSE_LEN+CHALLENGE_TAG_LEN];
           CryptoCC26XX_AESCCM_Transaction trans;
    
    	memset (nonce, 0, sizeof(nonce));
    	memset (cipherText, 0, sizeof(cipherText));
    	
    	memcpy (nonce, p->nonce, CHALLENGE_NONCE_LEN);
    
    	memcpy(cipherText, p, CHALLENGE_RESPONSE_LEN);
    	memcpy(cipherText+CHALLENGE_RESPONSE_LEN, p->TAG, CHALLENGE_TAG_LEN);
    
    	// setup trans for decryption
    	CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    	
    	trans.keyIndex   = pi->keyIndex[1];
    	trans.authLength = CHALLENGE_TAG_LEN;
    	trans.nonce  = (char *) nonce;
    	trans.header = (char *) NULL;
    	trans.fieldLength  = 15-CHALLENGE_NONCE_LEN;
    	trans.msgInLength  = CHALLENGE_RESPONSE_LEN+CHALLENGE_TAG_LEN;
    	trans.headerLength = 0;
    	trans.msgIn  = (char *) &cipherText[0];        // Message is encrypted in place
    	trans.msgOut = (char *) &cipherText[CHALLENGE_RESPONSE_LEN];  // MAC will be written to this position
    
    	// Do AES-CCM operation
    	status = CryptoCC26XX_transact(pi->handle, (CryptoCC26XX_Transaction *) &trans);
    	if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    	{
    		memcpy (&p->challengeResponse, cipherText, CHALLENGE_RESPONSE_LEN);
    	}
    
    	return status;
    }
    
    	
    static uint8_t * eccMalloc(uint16_t len)
    {
    	uint8_t *p;
    	
    	p = ICall_malloc(len);
    
    	sendPrintString("eccMalloc");
    	sendPrintDebug(len, (uint8_t)p, (uint8_t)p>>8,0,0);
    	return p;
    }
    
    static void eccFree(void *fp)
    {
    	sendPrintString("eccMalloc");
    	sendPrintDebug((uint8_t)fp, (uint8_t)fp>>8,0,0,0);
    	ICall_free(fp);
    }
    
    const uint8_t kPriv_app[] = {
        0xa4, 0x6c, 0xc1, 0x57, 0x0e, 0x67, 0xe8, 0xd6, 0xb8, 0xef, 0xcf, 0xc1, 0x36, 0x76, 0xdf, 0x0c,
        0x69, 0x1e, 0xc5, 0xe1, 0x1e, 0xb3, 0x43, 0xb4, 0xcf, 0x68, 0x94, 0x13, 0x8c, 0x60, 0x27, 0xdb
        
    };
    
    const uint8_t kPub_patch[] = {
        0x04, 0x02, 0xA0, 0xF8, 0xA7, 0x5A, 0xE6, 0xCB, 0x60, 0x6C, 0xF0, 0x63, 0xC9, 0x4E, 0x4F, 0x14,
        0xB1, 0x79, 0xB0, 0xF5, 0x72, 0x7F, 0xF0, 0x50, 0x91, 0x3F, 0xC2, 0xEC, 0x57, 0x5C, 0x24, 0x6E,
        0x94, 0x0D, 0x88, 0x4E, 0x4C, 0xC8, 0x6D, 0xA6, 0x26, 0x59, 0x38, 0x3F, 0x1B, 0xD7, 0x89, 0x79,
        0x65, 0x1E, 0xF2, 0x27, 0xA4, 0xAB, 0x65, 0xA1, 0xBE, 0x72, 0xCB, 0xF3, 0xCD, 0x1A, 0xCF, 0x60,
        0xF3
    };
    
    
    
    /*
    Date: 10Jan2017
    
    Test Data and result. 
    All computation results are the same for SCP and openssl.
    
    1. AES-CCM (13 byte nonce)
    	aes keys (16 bytes):
    	9fd012679e916e56267b5e334925b39d
    
    	Nonce (13 bytes):
    	24000000000000000030ca1502
    
    	Raw Data (14 bytes):
    	0de3ff073c00290000ff07428000 
    
    	Encrypted Data (same for cc2640 and openssl and SCP)
    	854a47577b788852d306fac79a7c 
    
    	MAC (same for cc2640 and openssl and SCP)
    	62d7bfe0
    
    2. AES-CCM (7 byte nonce)
    	aes keys (16 bytes):
    	4e9a37e005fec4ef19a7623fd917490e
    	
    	Nonce (7 bytes):
    	01000000842e45
    	
    	Raw 36 bytes (R1 || R2 || PIN )
    	04d9534a553f10b88ffd80cb20845330 
    	4e0dbf2e623e0f12e6901d007aef2d3c
    	37383733
    
    	Encrypted Data (same for cc2640 and openssl and SCP)
    	227ee7ff007bf7be5c70285478811e92 
    	9a924068663244a5eb023b3e49da6646 
    	008de85c 
    
    	MAC (same for cc2640 and openssl and SCP)
    	59482896
    
    3. ECC key generation
    	Private
    	a46cc1570e67e8d6b8efcfc13676df0c691ec5e11eb343b4cf6894138c6027db
    	Public (openssl and cc2640)
    	87a2a4a74e1b1a741d1dcf10245f2aad4736afd0a11ab134dbbffc204b2365f58b8e57a32a4b0a511e91a9c8debce01dae2de0e74c3a759ac470698802521e0a
    
    4. ECDH Key Agreement using ECCROMCC26XX_genDHKey()
    	private
    	a46cc1570e67e8d6b8efcfc13676df0c691ec5e11eb343b4cf6894138c6027db	
    
    	public
    	02a0f8a75ae6cb606cf063c94e4f14b179b0f5727ff050913fc2ec575c246e940d884e4cc86da62659383f1bd78979651ef227a4ab65a1be72cbf3cd1acf60f3
    
    	shared secret (openssl)
    	0d606518bf90534991207fcd55d414e036b16178e2419cd4c80c93bfc3f1c188
    	
    	shared secret (cc2640)
    	sharedSecretKeyX
    	0d606518bf90534991207fcd55d414e036b16178e2419cd4c80c93bfc3f1c188
    	sharedSecretKeyY
    	2949386284c1c1f86584ff0a7e3062b36b16ed3869b114754f690a69113d7e11
    
    5. SHA256
    	input (68 bytes)
    	00000001	
    	49b53b090dc94ecc4b1f024ca408ad6ec3bd40affcb424682fce618899052a23	
    	0d606518bf90534991207fcd55d414e036b16178e2419cd4c80c93bfc3f1c188
    
    	sha256 output (openssl and cc2640)
    	77cbb657c38dda3fbb93dfaf84db50131ef2ba68bef660f46fb139fb9f23013a
    
    6. ECC Signature generation and verification
    
    	// root signing private key:
    	const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d,
    	};
    
    	// root signature verification public key:
    	const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f,
    	};
    
    	// patch signed certificate
    	typedef struct
    	{
    	    UInt8       version;
    	    UInt8       serialNumber[8];
    	    UInt8       dateStamp[2];
    	    publicKey   ECCPubKey;
    	    UInt8       ECCSignature[64];
    	} patchCertDataStruct;
    
    	uint8_t Patch_certificate[] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3 , 0x32 , 0x99 , 0x87 , 0x5d, 
    	0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 0x4c , 0x77 , 0xea , 0xb5, 
    	0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 0x21 , 0x4e , 0x92 , 0x01, 
    	0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 0xb1 , 0xad , 0xac , 0x8b, 
    	0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    	};
    
    	// thePatchCert
    	// version, sn[8], timestamp[2]
    	35 31 32 33 34 35 36 37 38 34 12 
    
    	// patch public key
    	04 
    	02 a0 f8 a7 5a e6 cb 60 6c f0 63 c9 4e 4f 14 b1 
    	79 b0 f5 72 7f f0 50 91 3f c2 ec 57 5c 24 6e 94 
    	0d 88 4e 4c c8 6d a6 26 59 38 3f 1b d7 89 79 65 
    	1e f2 27 a4 ab 65 a1 be 72 cb f3 cd 1a cf 60 f3 
    
    	// signature
    	32 99 87 5d 0b aa d6 2b 6c ec 25 02 7d 10 21 b7 
    	4c 77 ea b5 09 19 09 6d d6 38 c3 ae 9b a2 88 3c 
    	21 4e 92 01 a4 f6 05 79 ac a7 3d 3c 67 79 a8 8b 
    	b1 ad ac 8b 5c 92 31 87 55 01 45 ed 45 78 99 67
    
    //.................... app certificates ........................
    
    const uint8_t Kpub_app_sig[] = {
    	0x04, 0xef, 0x3c, 0xb0, 0x46, 0xf5, 0xbf, 0x53, 0xd8, 0xe1, 0x24, 0x47, 0x3f, 0x38, 0x9d, 0x65, 
    	0xb4, 0x74, 0x00, 0x56, 0x3c, 0x17, 0x89, 0x0b, 0xf5, 0x30, 0x11, 0xec, 0x20, 0x42, 0x24, 0x36, 
    	0xfe, 0xb0, 0x78, 0x48, 0xce, 0xfb, 0xa9, 0xdc, 0xf5, 0x9c, 0xf7, 0x58, 0xb4, 0x2e, 0xfd, 0x9e, 
    	0xeb, 0x3a, 0x5d, 0x3c, 0x8e, 0x78, 0xb6, 0xa8, 0x87, 0x1d, 0xe1, 0xcd, 0xbe, 0xb8, 0x5b, 0xc5, 
    	0x45, 
    };
    const uint8_t Kpriv_app_sig[] = {
    	0x57, 0x4f, 0xa3, 0x48, 0x70, 0x1c, 0xbb, 0x1e, 0x9f, 0xc4, 0xf6, 0x67, 0x53, 0xb3, 0xfa, 0xc1, 
    	0x2d, 0x00, 0x30, 0xf3, 0xc2, 0xf3, 0x42, 0x71, 0xc8, 0x4f, 0x7d, 0x51, 0xbb, 0x5e, 0x51, 0xa2, 
    };
    
    typedef struct
    {
        UInt8       version;                // certificate data structure version (ascii)
        UInt8       manufactureSeq[16];     // manufacturing sequence data encrypted with Kman_seq
        UInt8       nonce[8];
        UInt8       tag[8];
        publicKey   ECCPubKey;              // Kpub_app
        UInt8       ECCSignature[64];       // ECC Signature of data above
    } applicationCertDataStruct;
    
    const uint8_t App_certificate[] = {
    	0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 
    	0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
    	0x07, 0x04, 0x87, 0xa2, 0xa4, 0xa7, 0x4e, 0x1b, 0x1a, 0x74, 0x1d, 0x1d, 0xcf, 0x10, 0x24, 0x5f, 
    	0x2a, 0xad, 0x47, 0x36, 0xaf, 0xd0, 0xa1, 0x1a, 0xb1, 0x34, 0xdb, 0xbf, 0xfc, 0x20, 0x4b, 0x23, 
    	0x65, 0xf5, 0x8b, 0x8e, 0x57, 0xa3, 0x2a, 0x4b, 0x0a, 0x51, 0x1e, 0x91, 0xa9, 0xc8, 0xde, 0xbc, 
    	0xe0, 0x1d, 0xae, 0x2d, 0xe0, 0xe7, 0x4c, 0x3a, 0x75, 0x9a, 0xc4, 0x70, 0x69, 0x88, 0x02, 0x52, 
    	0x1e, 0x0a, 0x47, 0xdd, 0x48, 0xa2, 0x38, 0x52, 0x81, 0x83, 0xe2, 0x92, 0x24, 0x26, 0x8f, 0x61, 
    	0x49, 0xe8, 0xe6, 0xe0, 0xe3, 0xce, 0x1e, 0xc5, 0x95, 0x74, 0xd6, 0x7e, 0x24, 0x1a, 0x9b, 0x3d, 
    	0x8b, 0xe2, 0xce, 0xef, 0x9e, 0xb5, 0xa6, 0x3e, 0x1f, 0x6a, 0x58, 0xac, 0x02, 0x6b, 0xf5, 0xc0, 
    	0x47, 0x3b, 0xca, 0xaf, 0xf9, 0x34, 0xc6, 0xef, 0xa7, 0xba, 0x85, 0xa8, 0xcf, 0x05, 0x80, 0x83, 
    	0xc3, 0xa4, 
    };
    
    */
    
    //.................... patch certificate ........................
    const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f
    };
    
    const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d
    };
    
    const uint8_t Patch_certificate[] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3 , 0x32 , 0x99 , 0x87 , 0x5d, 
    	0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 0x4c , 0x77 , 0xea , 0xb5, 
    	0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 0x21 , 0x4e , 0x92 , 0x01, 
    	0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 0xb1 , 0xad , 0xac , 0x8b, 
    	0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    };
    
    //.................... app certificate ........................
    const uint8_t Kpub_app_sig[] = {
    	0x04, 0xef, 0x3c, 0xb0, 0x46, 0xf5, 0xbf, 0x53, 0xd8, 0xe1, 0x24, 0x47, 0x3f, 0x38, 0x9d, 0x65, 
    	0xb4, 0x74, 0x00, 0x56, 0x3c, 0x17, 0x89, 0x0b, 0xf5, 0x30, 0x11, 0xec, 0x20, 0x42, 0x24, 0x36, 
    	0xfe, 0xb0, 0x78, 0x48, 0xce, 0xfb, 0xa9, 0xdc, 0xf5, 0x9c, 0xf7, 0x58, 0xb4, 0x2e, 0xfd, 0x9e, 
    	0xeb, 0x3a, 0x5d, 0x3c, 0x8e, 0x78, 0xb6, 0xa8, 0x87, 0x1d, 0xe1, 0xcd, 0xbe, 0xb8, 0x5b, 0xc5, 
    	0x45 
    };
    const uint8_t Kpriv_app_sig[] = {
    	0x57, 0x4f, 0xa3, 0x48, 0x70, 0x1c, 0xbb, 0x1e, 0x9f, 0xc4, 0xf6, 0x67, 0x53, 0xb3, 0xfa, 0xc1, 
    	0x2d, 0x00, 0x30, 0xf3, 0xc2, 0xf3, 0x42, 0x71, 0xc8, 0x4f, 0x7d, 0x51, 0xbb, 0x5e, 0x51, 0xa2 
    };
    
    const uint8_t App_certificate[] = {
    	0x30, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 
    	0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
    	0x07, 0x04, 0x87, 0xa2, 0xa4, 0xa7, 0x4e, 0x1b, 0x1a, 0x74, 0x1d, 0x1d, 0xcf, 0x10, 0x24, 0x5f, 
    	0x2a, 0xad, 0x47, 0x36, 0xaf, 0xd0, 0xa1, 0x1a, 0xb1, 0x34, 0xdb, 0xbf, 0xfc, 0x20, 0x4b, 0x23, 
    	0x65, 0xf5, 0x8b, 0x8e, 0x57, 0xa3, 0x2a, 0x4b, 0x0a, 0x51, 0x1e, 0x91, 0xa9, 0xc8, 0xde, 0xbc, 
    	0xe0, 0x1d, 0xae, 0x2d, 0xe0, 0xe7, 0x4c, 0x3a, 0x75, 0x9a, 0xc4, 0x70, 0x69, 0x88, 0x02, 0x52, 
    	0x1e, 0x0a, 0x47, 0xdd, 0x48, 0xa2, 0x38, 0x52, 0x81, 0x83, 0xe2, 0x92, 0x24, 0x26, 0x8f, 0x61, 
    	0x49, 0xe8, 0xe6, 0xe0, 0xe3, 0xce, 0x1e, 0xc5, 0x95, 0x74, 0xd6, 0x7e, 0x24, 0x1a, 0x9b, 0x3d, 
    	0x8b, 0xe2, 0xce, 0xef, 0x9e, 0xb5, 0xa6, 0x3e, 0x1f, 0x6a, 0x58, 0xac, 0x02, 0x6b, 0xf5, 0xc0, 
    	0x47, 0x3b, 0xca, 0xaf, 0xf9, 0x34, 0xc6, 0xef, 0xa7, 0xba, 0x85, 0xa8, 0xcf, 0x05, 0x80, 0x83, 
    	0xc3, 0xa4 
    };
    
    
    uint8_t workZone[288*4]; // Large enough for verify
      
    void testECCSigning()
    {
    	uint8_t status;
    
    	uint32_t randStrBuf[9] = {8};
    
    	uint32_t sha256Out[9] = {8};      
    	uint32_t localPrivateKey[9] = {8};
    	uint32_t signS1Buf[9] = {8};
    	uint32_t signS2Buf[9] = {8};
    
    	uint32_t localPublicKeyX[9]  = {8};
    	uint32_t localPublicKeyY[9]  = {8};
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    
    //	SHA256_memory_t sha256WorkMem;    
    	     
    	// StandaloneRomCryptoInit(); 
    	ECC_initialize((uint32_t *)&workZone, 2);
    
    	memcpy ((uint8_t *)&randStrBuf[1], Kpriv_patch_sig, 32);
    	eccSwapByte32((uint8_t *)&randStrBuf[1]);
    
            // Generate public key from A's private key
            status = ECC_generateKey(randStrBuf, localPrivateKey, localPublicKeyX, localPublicKeyY);
            if(status != ECC_ECDSA_KEYGEN_OK)
            { 
    //          while(1);
            }
    
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
    
            status = genSHA256(sha256_input, 76, (uint8_t *)&sha256Out[1]);
      
           // Generate sign. ecc_ecdsa_sign ECC_ECDSA_sign eccRom_sign
           status = ECC_ECDSA_sign(localPrivateKey,
                                      (uint32_t *)sha256Out,
                                      randStrBuf,
                                      signS1Buf,
                                      signS2Buf);
         
           if (status != ECC_ECDSA_SIGN_OK) 
           {
    //         while(1);
           }
           
           // Verify that the digest was signed by B.
           status = ECC_ECDSA_verify(localPublicKeyX, localPublicKeyY, (uint32_t *)sha256Out, signS1Buf, signS2Buf);
           if (status != ECC_ECDSA_VALID_SIGNATURE)
           {
    //         while(1);
           }
    }
    
    void testSignatureVerify()
    {
    	uint8_t status;
    
    	uint32_t localPublicKeyX[9]  = {8};
    	uint32_t localPublicKeyY[9]  = {8};
    
    	uint32_t signS1Buf[9] = {8};
    	uint32_t signS2Buf[9] = {8};
    
    	uint32_t signS1[9] = {8};
    	uint32_t signS2[9] = {8};
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[100];
    	uint32_t sha256Out[9] = {8};      
    
    	// StandaloneRomCryptoInit(); 
    	ECC_initialize((uint32_t *)&workZone, 2);
    
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
    
    	// cert signature
    	memcpy ((uint8_t*) &signS1Buf[1], &Patch_certificate[76], 32);
    	memcpy ((uint8_t*) &signS2Buf[1], &Patch_certificate[108], 32);
    
    	// root public key
    	memcpy ((uint8_t *)&localPublicKeyX[1], &Kpub_patch_sig[1], 32);
    	memcpy ((uint8_t *)&localPublicKeyY[1], &Kpub_patch_sig[33], 32);
    
           sendPrintString("testSignatureVerify 1");
    	status = genSHA256(sha256_input, 76, (uint8_t *)&sha256Out[1]);
    
           sendPrintString("testSignatureVerify 1.5");
    
    	eccSwapByte32((uint8_t *)&localPublicKeyX[1]);
    	eccSwapByte32((uint8_t *)&localPublicKeyY[1]);
    	eccSwapByte32((uint8_t *)&sha256Out[1]);
    	eccSwapByte32((uint8_t *)&signS1Buf[1]);
    	eccSwapByte32((uint8_t *)&signS2Buf[1]);
    
           sendPrintString("testSignatureVerify 2");
    	// Verify signature
    	status = ECC_ECDSA_verify(localPublicKeyX, localPublicKeyY, (uint32_t *)sha256Out, signS1Buf, signS2Buf);
    	if (status != ECC_ECDSA_VALID_SIGNATURE)
    	{
    //		while(1);
    	}
           sendPrintString("ECC_ECDSA_verify");
    	sendPrintBytes(&status, 1);
    
    #if 1  
    	uint32_t randStrBuf[9] = {8};
    	uint32_t localPrivateKey[9] = {8};
    	
    	memcpy ((uint8_t *)&randStrBuf[1], Kpriv_patch_sig, 32);
    	eccSwapByte32((uint8_t *)&randStrBuf[1]);
    
           sendPrintString("testSignatureVerify 3");
            status = ECC_generateKey(randStrBuf, localPrivateKey, localPublicKeyX, localPublicKeyY);
            if(status != ECC_ECDSA_KEYGEN_OK)
            { 
    //          while(1);
            }
           sendPrintString("ECC_generateKey");
    	sendPrintBytes(&status, 1);
    
           // Generate sign. ecc_ecdsa_sign ECC_ECDSA_sign eccRom_sign
           status = ECC_ECDSA_sign(localPrivateKey,
                                      (uint32_t *)sha256Out,
                                      localPrivateKey,
                                      signS1,
                                      signS2);
         
           if (status != ECC_ECDSA_SIGN_OK) 
           {
    //         while(1);
           }
           
           sendPrintString("ECC_ECDSA_sign");
    	sendPrintBytes(&status, 1);
    	
    	// Verify signature
    	status = ECC_ECDSA_verify(localPublicKeyX, localPublicKeyY, (uint32_t *)sha256Out, signS1, signS2);
    	if (status != ECC_ECDSA_VALID_SIGNATURE)
    	{
    //		while(1);
    	}
    
           sendPrintString("ECC_ECDSA_verify");
    	sendPrintBytes(&status, 1);
    	
    #endif
    
    
    	// app certificate verification
    	memcpy (sha256_input, App_certificate, 98);
    
    	// cert signature
    	memcpy ((uint8_t*) &signS1Buf[1], &App_certificate[98], 32);
    	memcpy ((uint8_t*) &signS2Buf[1], &App_certificate[130], 32);
    
    	// root public key
    	memcpy ((uint8_t *)&localPublicKeyX[1], &Kpub_app_sig[1], 32);
    	memcpy ((uint8_t *)&localPublicKeyY[1], &Kpub_app_sig[33], 32);
    
    	status = genSHA256(sha256_input, 98, (uint8_t *)&sha256Out[1]);
    
    	eccSwapByte32((uint8_t *)&localPublicKeyX[1]);
    	eccSwapByte32((uint8_t *)&localPublicKeyY[1]);
    	eccSwapByte32((uint8_t *)&sha256Out[1]);
    	eccSwapByte32((uint8_t *)&signS1Buf[1]);
    	eccSwapByte32((uint8_t *)&signS2Buf[1]);
    
    	// Verify signature
    	status = ECC_ECDSA_verify(localPublicKeyX, localPublicKeyY, (uint32_t *)sha256Out, signS1Buf, signS2Buf);
    	if (status != ECC_ECDSA_VALID_SIGNATURE)
    	{
    //		while(1);
    	}
    
           sendPrintString("ECC_ECDSA_verify App cert");
    	sendPrintBytes(&status, 1);
    
    }
    
    void testSHA256()
    {
    	int8_t status;
    	SHA256_memory_t sha256WorkMem;
    	uint8_t sha256Out[32];
    
    	// sha256 input buffers
    	uint8_t sha256_input[] = {
    	    0x00, 0x00, 0x00, 0x01,
    	    0x49, 0xb5, 0x3b, 0x09, 0x0d, 0xc9, 0x4e, 0xcc, 0x4b, 0x1f, 0x02, 0x4c, 0xa4, 0x08, 0xad, 0x6e,
    	    0xc3, 0xbd, 0x40, 0xaf, 0xfc, 0xb4, 0x24, 0x68, 0x2f, 0xce, 0x61, 0x88, 0x99, 0x05, 0x2a, 0x23,
    	    0x0d, 0x60, 0x65, 0x18, 0xbf, 0x90, 0x53, 0x49, 0x91, 0x20, 0x7f, 0xcd, 0x55, 0xd4, 0x14, 0xe0, 
    	    0x36, 0xb1, 0x61, 0x78, 0xe2, 0x41, 0x9c, 0xd4, 0xc8, 0x0c, 0x93, 0xbf, 0xc3, 0xf1, 0xc1, 0x88
    	};
    	
    	// SHA256 test
    	sendPrintBytes(&sha256_input[0], 4);
    	sendPrintBytes(&sha256_input[4], 32);
    	sendPrintBytes(&sha256_input[36], 32);
    
    	status = SHA256_runFullAlgorithm(&sha256WorkMem, sha256_input, 68, sha256Out);
    
    	if (status == SHA256_SUCCESS)
    	{
    		sendPrintBytes(sha256Out, 32);
    	}
    }
    
    int8_t testGenEccKeys(uint8_t *privateKey, uint8_t *publicKey)
    {
    
    #if 0
    	return genEccKeys(privateKey, publicKey);
    #else
    	return genPublicKeyFromPrivate((uint8_t*)kPriv_app, publicKey);
    #endif
    }
    
    void testEcc()
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32]  = {0xa4, 0x6c, 0xc1, 0x57, 0x0e, 0x67, 0xe8, 0xd6, 0xb8, 0xef, 0xcf, 0xc1, 0x36, 0x76, 0xdf, 0x0c, 0x69, 0x1e, 0xc5, 0xe1, 0x1e, 0xb3, 0x43, 0xb4, 0xcf, 0x68, 0x94, 0x13, 0x8c, 0x60, 0x27, 0xdb};
    	uint8_t bsPrivateKey[32];
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t bsPublicKeyX[32];
    	uint8_t bsPublicKeyY[32];
    	uint8_t sharedSecretKeyX[32] = {0};
    	uint8_t sharedSecretKeyY[32] = {0};
    	uint8_t bsSharedSecretKeyX[32];
    	uint8_t bsSharedSecretKeyY[32];
    
    
    	int i;
    	for (i=0; i<32; i++)
    	{
    		bsPrivateKey[i] = privateKey[31-i];
    	}
    
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	status = ECCROMCC26XX_genKeys(bsPrivateKey, bsPublicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		for(i=0; i<32; i++)
    		{
    			publicKeyX[i] = bsPublicKeyX[31-i];
    			publicKeyY[i] = bsPublicKeyY[31-i];
    		}
    		
    		sendPrintBytes(privateKey, 32);
    		sendPrintBytes(publicKeyX, 32);
    		sendPrintBytes(publicKeyY, 32);
    	}
    
    	// use app private key, patch public key
    	memcpy (privateKey, kPriv_app, 32);
    	memcpy (publicKeyX, &kPub_patch[1], 32);
    	memcpy (publicKeyY, &kPub_patch[33], 32);
            
    	for (i=0; i < 32; i++)
    	{
    		bsPrivateKey[i] = privateKey[31-i];
    		bsPublicKeyX[i] = publicKeyX[31-i];
    		bsPublicKeyY[i] = publicKeyY[31-i];
    	}
    	
    	// Generate shared secret.
    	status = ECCROMCC26XX_genDHKey(bsPrivateKey, bsPublicKeyX,
    	                        bsPublicKeyY, bsSharedSecretKeyX,
    	                        bsSharedSecretKeyY, &params);
    
    	for (i=0; i < 32; i++)
    	{
    		sharedSecretKeyX[i] = bsSharedSecretKeyX[31-i];
    		sharedSecretKeyY[i] = bsSharedSecretKeyY[31-i];
    	}
    	
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintBytes(privateKey, 32);
    		sendPrintBytes(publicKeyX, 32);
    		sendPrintBytes(publicKeyY, 32);
    		sendPrintBytes(sharedSecretKeyX, 32);
    		sendPrintBytes(sharedSecretKeyY, 32);
    	}
    
    }
    
    #pragma optimize=none
    void testChallenge()
    {
    	int8_t status;	
    	uint8_t nonce7[13] =  { 0x33, 0x00, 0x00 , 0x00 , 0x35 , 0xfa , 0x84, 0, 0, 0, 0, 0, 0}; // need to pad this array to 13 bytes
    	uint8_t aesKeyMA[16]= { 0x20 , 0x9d , 0x7a , 0xa4 , 0x31 , 0x64 , 0xb4 , 0x9a , 0x48 , 0x47 , 0x71 , 0xda , 0x81 , 0x61 , 0xc9 , 0xad};
    	uint8_t clearAndCipherMA[CHALLENGE_RESPONSE_LEN+CHALLENGE_TAG_LEN] =  
    		{ 0x4e , 0x0d , 0xbf , 0x2e , 0x62 , 0x3e , 0x0f , 0x12 , 0xe6 , 0x90 , 0x1d , 0x00 , 0x7a , 0xef , 0x2d , 0x3c, 
    		0xff , 0xe5 , 0x4e , 0x7f , 0x5a , 0xe1 , 0x4e , 0xff , 0x0b , 0x33 , 0xbd , 0x80 , 0x2f , 0xb1 , 0x8c , 0x67, 
    		0x0e , 0xed , 0x1f , 0x69 , 0x3a , 0xcc , 0x1b , 0xe4 , 0x95 , 0x3c , 0xb6 , 0xb6 , 0xec , 0xd5 , 0x18 , 0x88, 
    		0x00 , 0x00 , 0x00 , 0x00 , 0x50 , 0x55 , 0x07 , 0xa3, 0,0,0,0};
    
    	CryptoCC26XX_AESCCM_Transaction trans;
    	int keyIndex;
    	uint8_t payLen;
    	uint8_t macLen;
    
    	if (handle)
    	{
    		keyIndex = CryptoCC26XX_allocateKey(handle, CRYPTOCC26XX_KEY_1,
    	 		(const uint32_t *) aesKeyMA);
    		payLen = CHALLENGE_RESPONSE_LEN;
    		macLen = CHALLENGE_TAG_LEN;
    
    		// print keys, nonce
    		sendPrintBytes(aesKeyMA, 16);
    		sendPrintBytes(nonce7, 7);
    		sendPrintBytes(clearAndCipherMA, 16);
    		sendPrintBytes(&clearAndCipherMA[16], 16);
    		sendPrintBytes(&clearAndCipherMA[32], 16);
    		sendPrintBytes(&clearAndCipherMA[48], 8);
    		sendPrintBytes(&clearAndCipherMA[56], 4);
    
    		if (keyIndex != CRYPTOCC26XX_STATUS_ERROR)
    		{
    			int j;
    			for (j=0; j<10; j++)
    			{
    				// Encrypt and sign message
    				CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCM);
    				trans.keyIndex   = keyIndex;
    				trans.authLength = macLen;
    				trans.nonce  = (char *) nonce7;
    				trans.header = (char *) NULL;  
    				trans.fieldLength  = 15 - 7;
    				trans.msgInLength  = payLen;
    				trans.headerLength = 0;
    				trans.msgIn  = (char *) clearAndCipherMA;        // Message is encrypted in place
    				trans.msgOut =(char *) &clearAndCipherMA[payLen];  // MAC will be written to this position
    				// Do AES-CCM operation
    				status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    
    				// print encrypted output, mac
    				sendPrintBytes(clearAndCipherMA, 16);
    				sendPrintBytes(&clearAndCipherMA[16], 16);
    				sendPrintBytes(&clearAndCipherMA[32], 16);
    				sendPrintBytes(&clearAndCipherMA[48], 8);
    				sendPrintBytes(&clearAndCipherMA[56], 4);
    				
    				if (status == CRYPTOCC26XX_STATUS_SUCCESS) 
    				{           
    					// Decrypt and authenticate message
    					CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    					trans.keyIndex   = keyIndex;
    					trans.authLength = macLen;
    					trans.nonce  = (char *) nonce7;
    					trans.header = (char *) NULL;
    					trans.fieldLength  = 15 - 7;
    					trans.msgInLength  = payLen+macLen;
    					trans.headerLength = 0;
    					trans.msgIn  = (char *) clearAndCipherMA;        // Message is encrypted in place
    					trans.msgOut = (char *) &clearAndCipherMA[payLen];  // MAC will be written to this position
    
    					// Do AES-CCM operation
    					status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    					if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    					{
    
    						// print decrypted output
    						sendPrintBytes(clearAndCipherMA, 16);
    						sendPrintBytes(&clearAndCipherMA[16], 16);
    						sendPrintBytes(&clearAndCipherMA[32], 16);
    						sendPrintBytes(&clearAndCipherMA[48], 8);
    					}
    				}
    			} 
    
    			// Release the key location
    			status = CryptoCC26XX_releaseKey(handle, &keyIndex);
    			if (status != CRYPTOCC26XX_STATUS_SUCCESS) 
    			{
    				sendPrintString("CryptoCC26XX_releaseKey failed");
    				sendPrintBytes(&status, 1);
    			}
    		} 
    	}
    }
    
    void testAES(uint8_t nLen)
    {
    	int8_t status;	
    	uint8_t nonce13[13] =  { 0x24 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x30 , 0xca , 0x15 , 0x02};
    	uint8_t nonce7[13] =  { 0x01 , 0x00 , 0x00 , 0x00 , 0x84 , 0x2e , 0x45, 0, 0, 0, 0, 0, 0}; // need to pad this array to 13 bytes
    	uint8_t aesKeyCgm[16]= { 0x9f , 0xd0 , 0x12 , 0x67 , 0x9e , 0x91 , 0x6e , 0x56 , 0x26 , 0x7b , 0x5e , 0x33 , 0x49 , 0x25 , 0xb3 , 0x9d };
    	uint8_t aesKeyMA[16]= { 0x4e,  0x9a,  0x37,  0xe0,  0x05,  0xfe,  0xc4,  0xef,  0x19,  0xa7,  0x62,  0x3f,  0xd9,  0x17,  0x49,  0x0e };
    	uint8_t clearAndCipherCgm[CGM_PAYLOAD_LEN+CGM_TAG_LEN] =  { 0x0d , 0xe3 , 0xff , 0x07 , 0x3c , 0x00 , 0x29 , 0x00 , 0x00 , 0xff , 0x07 , 0x42 , 0x80 , 0x00};
    	uint8_t clearAndCipherMA[CHALLENGE_PAYLOAD_LEN+CHALLENGE_TAG_LEN] =  
    		{ 0x04 , 0xd9 , 0x53 , 0x4a , 0x55 , 0x3f , 0x10 , 0xb8 , 0x8f , 0xfd , 0x80 , 0xcb , 0x20 , 0x84 , 0x53 , 0x30 , 
    		   0x4e , 0x0d , 0xbf , 0x2e , 0x62 , 0x3e , 0x0f , 0x12 , 0xe6 , 0x90 , 0x1d, 0x00 , 0x7a , 0xef , 0x2d , 0x3c , 
    		   0x37 , 0x38 , 0x37 , 0x33};
    
    	CryptoCC26XX_AESCCM_Transaction trans;
    	int keyIndex;
    	uint8_t payLen;
    	uint8_t macLen;
    
    	if (handle)
    	{
    		if (nLen == 13)
    		{
    			keyIndex = CryptoCC26XX_allocateKey(handle, CRYPTOCC26XX_KEY_0,
    		 		(const uint32_t *) aesKeyCgm);
    			payLen = CGM_PAYLOAD_LEN;
    			macLen = CGM_TAG_LEN;
    
    			// print keys, nonce, raw input
    			sendPrintBytes(aesKeyCgm, 16);
    			sendPrintBytes(nonce13, nLen);
    			sendPrintBytes(clearAndCipherCgm, CGM_PAYLOAD_LEN);
    		}
    		else 
    		{
    			keyIndex = CryptoCC26XX_allocateKey(handle, CRYPTOCC26XX_KEY_1,
    		 		(const uint32_t *) aesKeyMA);
    			payLen = CHALLENGE_PAYLOAD_LEN;
    			macLen = CHALLENGE_TAG_LEN;
    
    			// print keys, nonce
    			sendPrintBytes(aesKeyMA, 16);
    			sendPrintBytes(nonce7, nLen);
    			sendPrintBytes(clearAndCipherMA, 16);
    			sendPrintBytes(&clearAndCipherMA[16], 16);
    			sendPrintBytes(&clearAndCipherMA[32], 4);
    		}
    
    		if (keyIndex != CRYPTOCC26XX_STATUS_ERROR)
    		{
    
    			// Encrypt and sign message
    			CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCM);
    			trans.keyIndex   = keyIndex;
    			trans.authLength = macLen;
    			trans.nonce  = (nLen == 13) ? (char *) nonce13 : (char *) nonce7;
    			trans.header = (char *) NULL;  
    			trans.fieldLength  = 15 - nLen;
    			trans.msgInLength  = payLen;
    			trans.headerLength = 0;
    			trans.msgIn  = (nLen == 13) ? (char *) clearAndCipherCgm : (char *) clearAndCipherMA;        // Message is encrypted in place
    			trans.msgOut =(nLen == 13) ? (char *) &clearAndCipherCgm[payLen] : (char *) &clearAndCipherMA[payLen];  // MAC will be written to this position
    			// Do AES-CCM operation
    			status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    
    			// print encrypted output, mac
    			if (nLen == 13)
    			{
    				sendPrintBytes(clearAndCipherCgm, CGM_PAYLOAD_LEN);
    				sendPrintBytes(&clearAndCipherCgm[CGM_PAYLOAD_LEN], macLen);
    			}
    			else
    			{
    				sendPrintBytes(clearAndCipherMA, 16);
    				sendPrintBytes(&clearAndCipherMA[16], 16);
    				sendPrintBytes(&clearAndCipherMA[32], 4);
    				sendPrintBytes(&clearAndCipherMA[36], 4);
    			}
    			
    			if (status == CRYPTOCC26XX_STATUS_SUCCESS) 
    			{           
    				// Decrypt and authenticate message
    				CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    				trans.keyIndex   = keyIndex;
    				trans.authLength = macLen;
    				trans.nonce  = (nLen == 13) ? (char *) nonce13 : (char *) nonce7;
    				trans.header = (char *) NULL;
    				trans.fieldLength  = 15 - nLen;
    				trans.msgInLength  = payLen+macLen;
    				trans.headerLength = 0;
    				trans.msgIn  = (nLen == 13) ? (char *) clearAndCipherCgm : (char *) clearAndCipherMA;        // Message is encrypted in place
    				trans.msgOut =(nLen == 13) ? (char *) &clearAndCipherCgm[payLen] : (char *) &clearAndCipherMA[payLen];  // MAC will be written to this position
    
    				// Do AES-CCM operation
    				status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    				if (status== CRYPTOCC26XX_STATUS_SUCCESS) 
    				{
    
    					// print decrypted output
    					if (nLen == 13)
    					{
    						sendPrintBytes(clearAndCipherCgm, CGM_PAYLOAD_LEN);
    					}
    					else
    					{
    						sendPrintBytes(clearAndCipherMA, 16);
    						sendPrintBytes(&clearAndCipherMA[16], 16);
    						sendPrintBytes(&clearAndCipherMA[32], 4);
    					}
    
    					// Release the key location
    					status = CryptoCC26XX_releaseKey(handle, &keyIndex);
    					if (status != CRYPTOCC26XX_STATUS_SUCCESS) 
    					{
    						sendPrintString("CryptoCC26XX_releaseKey failed");
    						sendPrintBytes(&status, 1);
    					}
    				}
    			}
    		} 
    	}
    }
    
    void testCrypto(CryptoCC26XX_Config * p)
    {
    	uint8_t privateKey[32]  = {0xa4, 0x6c, 0xc1, 0x57, 0x0e, 0x67, 0xe8, 0xd6, 0xb8, 0xef, 0xcf, 0xc1, 0x36, 0x76, 0xdf, 0x0c, 0x69, 0x1e, 0xc5, 0xe1, 0x1e, 0xb3, 0x43, 0xb4, 0xcf, 0x68, 0x94, 0x13, 0x8c, 0x60, 0x27, 0xdb};
    	uint8_t publicKey[64];
    
    	handle = p;
    
    	sendPrintString("testECCSigning...");	
    	Task_sleep(333000/10);
    	testECCSigning();
    
    	sendPrintString("testSignatureVerify...");	
    	Task_sleep(333000/10);
    	testSignatureVerify();
    
    	sendPrintString("testSHA256...");	
    	Task_sleep(333000/10);
    	testSHA256();
    
    	sendPrintString("testGenEccKeys...");	
    	Task_sleep(333000/10);
    	testGenEccKeys(privateKey, publicKey);
    
    	// Sleep for 333 ms (we will likely go into standby)
    	sendPrintString("testChallenge...");	
    	Task_sleep(333000/10);
    	testChallenge();
    	
    	sendPrintString("testAES 7...");	
    	Task_sleep(333000/10);
    	testAES(7);
    
    	sendPrintString("testAES 13...");	
    	Task_sleep(333000/10);
    	testAES(13);
    
    	sendPrintString("testEcc...");	
    	Task_sleep(333000/10);
    	testEcc();
    
    }
    
    
     

  • Hi Tony, 

    I will check with a colleague and see if he could verify what I told you previously above.

    Assuming the mapping to ROM is correct (we know ROM did not change as it is, well ROM), there is a few other things worth looking into. The ECC ROM comes with a few caveats that you need to consider and if you miss these, you could end up corrupting parts of the RAM. First part is related to some dedicated RAM usage which easily is missed:

    /*
     * For the CC13x0 and CC26x0, the ECC functions are stored in ROM, and are coded to use the
     * last 100 bytes of RAM as an output buffer. This is normally used by the stack, and so
     * causes unpredictable behaviour unless that region is reserved.
     *
     * The below code is used to define a 0x100 length buffer at the top of RAM and ensure
     * it is placed correctly on supported compilers.
     *
     * GCC also requires a modification to the linker file; see the README for details.
     */
    #define ROM_CRYPTO_BUFFER_ADDR 0x20004F00
    #define ROM_CRYPTO_BUFFER_SIZE 0x100
    
    #ifdef __IAR_SYSTEMS_ICC__
        __no_init uint8_t romCryptoOutputBuffer[ROM_CRYPTO_BUFFER_SIZE] @ ROM_CRYPTO_BUFFER_ADDR;
    #endif
    #ifdef __TI_COMPILER_VERSION__
        #pragma LOCATION(romCryptoOutputBuffer, ROM_CRYPTO_BUFFER_ADDR);
        uint8_t romCryptoOutputBuffer[ROM_CRYPTO_BUFFER_SIZE];
    #endif
    #ifdef __GNUC__
        __attribute((section(".romCryptoSection"))) uint8_t romCryptoOutputBuffer[ROM_CRYPTO_BUFFER_SIZE];
    #endif

    The second part is that the workzone size depends on which operations you use, windows size, curves etc etc. Could you try to "brute force" it by doubling the workzone and see if it changes anything (this would indicate that we are corrupting something with the initial size).

    As you did a migration recently, it is not completely unlikely that you simply got a new program placement which made you more vulnerable to potential RAM corruptions than before (assuming the ECC always did this and you just did not notice it).

  • When allocate the 0x100 bytes at 0x20004F00 for romCryptoOutputBuffer[], the linker complains about address conflict as some addresses were already allocated in the ble_r2.symbols.

    Linking
    Error[Lp023]: absolute placement (in [0x2000'4f00-0x2000'4fff]) overlaps with absolute symbol: C:\svn\L3_Reader\cc2640\simplelink_cc2640r2_sdk_4_10_00_10\project\L3_SC_Reader\tirtos\iar\app\..\..\..\..\..\source\ti\blestack\common\cc26xx\iar\cc26xx_app_and_stack.icf 256
                [0x2000'4f00-0x2000'4f03] "activeConns"
                [0x2000'4f04-0x2000'4f07] "SysBootMsg"

    I've also tried doubling the workzone and the effect is the same.

  • Hi Tony,

    Looking closer at that linker file, it already takes into consideration the ECC ROM area assuming you have set "ENCRYPTION_ROM" to 2. you got this setting in your project? If you are unsure, an easy check is to look at the total SRAM size in the .map file, it should be something along the lines of "expected max size - 0x80".

  • The “ENCRYPTION_ROM” is used in the ccs but not found in iar build environment.

     

    For iar, the linker is configured for FLASH_ROM_BUILD=2, and adding ENCRYPTION_ROM=2 does not change the memory map, so I'll just leave it as the original form and not add ENCRYPTION_ROM=2 to the linker cmd.

    Also, I'll remove the romCryptoOutputBuffer[] allocation at 0x20004F00 so we're back to square one...

     

  • Hi Tony,

    Could you share the map file of you project for me to look at?

  • I was out of the office until today.

    Here it is. I'm unable to post the map file directly, so I inserted the content into a word doc.map.docx

  • Hi Tony,

    The map file looks ok as far as I can tell. Would you be able to share the failing project, with me here or in private? 

    I will also see if I can get someone closer to the BLE stack to comment on this as well.

  • I'll get the example simple_central project and add the test_crypto.c file to build and you can run it using launch pad.

    It should be ready later today.

  • Enclosed is the ecc project clone from the simple central example under

    C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\examples\rtos\CC2640R2_LAUNCHXL\blestack

    You should be able to placed it under the same directory and build it

    simple_central_ecc.zip

  • Running with the Launchpad project that I've sent you fails at ECC_generateKey() whereas on my platform works.

    But if you can get this code to run on the Launchpad, then there's a good chance it'll run on our platform.

    Let me know if you want a webex to see how it behaves on my platform.

  • Hi Tony, 

    I get a compilation issue where "cryptoInit" is not found. I can't seem to find any additional files containing this API call, could there be something missing in the .zip file you attached?

  • cryptoInit() is in test_crypto.c which was under simple_central_ecc\src\app in the zip file.

  • Hi Tony,

    From what I can tell from debugging, your ROM symbol mapping is off. You seem to depend on "ecc_rom.c/h" which is not correct. If you compare the "ecc_generatekey" address you use with the map file you will find that you actually jump right into "linkDB_Init()" and not the ECC routine.

    You could look for "eccRom_*" to find the correct address, for example for genKeys, see below:

    eccRom_genKeys {Abs} 0x1001'6c1d 0x2c Code Gb ble_r2.symbols [2]

    I would advice you to use the ECC driver, this as the stack uses this and it would minimize the possible problems with concurrent access to the resource.

  • Thanks for your suggestion to not rely on the ecc_rom.c for all the ECC functions.

    I'll remove the ecc_rom.c from the build project and only uses ECCROMCC26xx.h and .c files.

    I've done so for the ECCROMCC26XX_genKeys() and ECCROMCC26XX_genDHKey() and they are working.

    I'm in the process of rewriting the test code using ECCROMCC26XX_signHash() and ECCROMCC26XX_verifyHash(). I should know the result by later next week as I'll be out of the office in the next few days.

    In the meantime, please post an example code that uses these 2 functions to sign and verify a message with the ECC keys if you have it. In particular, I like to know the byte order of the private, public keys, the message hash, the signature. A working example would be very helpful.

  • I've re-written the ECC signature generation using the ECCROMCC26XX_signHash() and the code runs, but I'm not able to correlate with the openssl output.

    Enclosed is the test signature

  • I've re-written the ECC signature generation using the ECCROMCC26XX_signHash() and the code runs, but I'm not able to correlate with the openssl output.

    Enclosed is the test_signature.c which should replace the test_crypto.c in the project.

    Also the result.txt has the data that ran on my platform.

    Please rebuild your project using the test_signature.c file and let me know what I need to change to get the expected signature.

    /*********************************************************************
    * INCLUDES
    */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    #ifdef DEBUG
    #include <driverlib/ioc.h>
    #endif // DEBUG
    
    
    #include "CryptoCC26XX.h"
    #include "SHA2CC26XX.h"
    #include "ECCROMCC26XX.h"
    #include "CC2640R2DK_4XS.h"
    
    CryptoCC26XX_Handle handle;
    
    static uint8_t * eccMalloc(uint16_t len);
    static void eccFree(void *fp);
    static void eccSwapByte32(uint8_t * p);
    
    #define SHA256_runFullAlgorithm SHA2CC26XX_runFullAlgorithm
    
    
    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    
    void sendPrintBytes(void *buff, int len)
    {
       // dummy for debug print
    }
    
    void sendPrintString(void *buff)
    {
       // dummy for debug print
    }
    
    void sendPrintDebug(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4)
    {
       // dummy for debug print
    }
    
    
    // according to TI, the SHA256 success return code is 0x77
    #define SHA256_SUCCESS	0x77
    int genSHA256(uint8_t * input, uint8_t len, uint8_t * output)
    {
    	int8_t status;
    	SHA256_memory_t sha256WorkMem;
    	
    	// this function returns 0x77 when successful
    	status =  SHA256_runFullAlgorithm(&sha256WorkMem, input, len, output);
    
    	return (status == SHA256_SUCCESS) ? ECCROMCC26XX_STATUS_SUCCESS : status;
    }
    
    static void eccSwapByte32(uint8_t * p)
    {
    	uint8_t buffer[32];
    	int i;
    
    	for (i=0; i<32; i++)
    	{
    		buffer[i] = p[31-i];
    	}
    
    	memcpy (p, buffer, 32);
    }
    
    
    static uint8_t * eccMalloc(uint16_t len)
    {
    	uint8_t *p;
    	
    	p = (uint8_t*)ICall_malloc(len);
    
    	sendPrintString("eccMalloc");
    	sendPrintDebug(len, (uint8_t)p, (uint8_t)p>>8,0,0);
    	return p;
    }
    
    static void eccFree(void *fp)
    {
    	sendPrintString("eccMalloc");
    	sendPrintDebug((uint8_t)fp, (uint8_t)fp>>8,0,0,0);
    	ICall_free(fp);
    }
    
    /*
    Date: 10Jan2017
    
    Test Data and result. 
    All computation results are the same for SCP and openssl.
    
    6. ECC Signature generation and verification
    
    	// root signing private key:
    	const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d,
    	};
    
    	// root signature verification public key:
    	const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f,
    	};
    
    	// random 76 bytes
    	uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3
    	};
    
    	// expected signature
    	const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    	};
    */
    
    //.................... patch certificate ........................
    // root  public key - used for signature verification:
    const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f
    };
    
    // root signing private key
    const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d
    };
    
    // random string - 76 bytes
    const uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3 
    };
    
    const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    };
    
    uint8_t workZone[288*4]; // Large enough for verify
    
    void testECCKeyGen()
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	bsPublicKeyX = publicKeyX;
    	bsPublicKeyY = publicKeyY;
    	
    	sendPrintString("testECCKeyGen - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	eccSwapByte32(privateKey);
    	sendPrintString("testECCKeyGen - ECCROMCC26XX_genKeys() private key");
    	sendPrintBytes(privateKey, 32);
    	
    	status = ECCROMCC26XX_genKeys(privateKey, publicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		eccSwapByte32(bsPublicKeyX);
    		eccSwapByte32(bsPublicKeyY);
    
    		sendPrintString("testECCKeyGen -  generated public key");	
    		sendPrintBytes(bsPublicKeyX, 32);
    		sendPrintBytes(bsPublicKeyY, 32);
    	}
    }
    
    void testECCSigning()
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    	uint8_t sha256Out[32] = {0};      
    
    	// signatures
    	uint8_t signS1Buf[32] = {0};
    	uint8_t signS2Buf[32] = {0};
    
    	sendPrintString("testECCSigning - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	sendPrintString("testECCSigning - public certificate");	
    	
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
           status = genSHA256(sha256_input, 76, sha256Out);
    
    	Task_sleep(333000/10);
           sendPrintBytes(sha256_input, 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[32], 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[64], 12);
    	Task_sleep(333000/10);
    
    	sendPrintString("testECCSigning - sha2 out");	
           sendPrintBytes(&status, 1);
           sendPrintBytes(sha256Out, 32);
    
    	sendPrintString("testECCSigning - ECCROMCC26XX_signHash() private key");	
    	memcpy(privateKey, Kpriv_patch_sig, 32);
    	eccSwapByte32(privateKey);
    	sendPrintBytes(privateKey, 32);
    
    	status = ECCROMCC26XX_signHash(privateKey, sha256Out,
                                 32, signS1Buf, signS2Buf, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintString("testECCSigning -  signature");	
    		sendPrintBytes(signS1Buf, 32);
    		sendPrintBytes(signS2Buf, 32);
    	}
    
    }
    
    
    void cryptoInit()
    {
    	// Initialize Crypto driver
    	CryptoCC26XX_init();
    	handle = CryptoCC26XX_open(CC2640R2DK_4XS_CRYPTO0, false, NULL);
    
    	// Initialize ECC ROM driver
    	ECCROMCC26XX_init();
    	
    	// this shows that the public key generated from the private key matches with openssl
    	testECCKeyGen();
    
    	// use the same private key and the 76 random bytes to generate the signature
    	testECCSigning();
    }
    
    
    
    // check public key generated with the private key
    BLE [80651]:testECCKeyGen - original private key
    BLE [80652] l=32: E7 A2 4F 2B E2 66 86 11 D0 2C 88 3C 74 F6 E9 0C 7E 43 B8 A9 
    8C 2A CA CD 73 C0 DD 19 86 24 8F 0D
    BLE [80653]:testECCKeyGen - ECCROMCC26XX_genKeys() private key (32 bytes swap)
    BLE [80654] l=32: 0D 8F 24 86 19 DD C0 73 CD CA 2A 8C A9 B8 43 7E 0C E9 F6 74 
    3C 88 2C D0 11 86 66 E2 2B 4F A2 E7
    
    BLE [80662]:testECCKeyGen -  generated public key (64 bytes)
    BLE [80663] l=32: DA 3C 68 85 95 0E A7 F5 83 38 89 3A F1 56 B9 48 55 22 EC 63 
    EB 78 62 EF E9 19 30 E9 6D 0C CC 07
    BLE [80663] l=32: D0 CA 9B A6 04 17 53 D6 D2 8D C5 AF F7 78 F9 CD 0D 31 DE 01 
    93 A3 82 1A F2 01 25 CB 7A 00 17 3F
    
    
    // test signature generation with the private key and the 76 bytes of message 
    // digest (12 bytes of identity + 64 bytes of public key)
    BLE [80678]:testECCSigning - original private key
    BLE [80679] l=32: E7 A2 4F 2B E2 66 86 11 D0 2C 88 3C 74 F6 E9 0C 7E 43 B8 A9 
    8C 2A CA CD 73 C0 DD 19 86 24 8F 0D
    
    BLE [80680]:testECCSigning - public certificate
    BLE [80694] l=32: 35 31 32 33 34 35 36 37 38 34 12 04 02 A0 F8 A7 5A E6 CB 60 
    6C F0 63 C9 4E 4F 14 B1 79 B0 F5 72
    BLE [80708] l=32: 7F F0 50 91 3F C2 EC 57 5C 24 6E 94 0D 88 4E 4C C8 6D A6 26 
    59 38 3F 1B D7 89 79 65 1E F2 27 A4
    BLE [80722] l=12: AB 65 A1 BE 72 CB F3 CD 1A CF 60 F3
    
    BLE [80735]:testECCSigning - sha2 out (status + 32 hash)
    BLE [80736] l=1: 00
    BLE [80736] l=32: C3 54 89 6D 46 1A DA 64 32 0A DF E9 58 DD 91 03 E7 CC 50 A3 
    22
    
     B8 F6 85 90 39 B1 C4 B2 89 51 25
    BLE [80738]:testECCSigning - ECCROMCC26XX_signHash() private key
    BLE [80738] l=32: 0D 8F 24 86 19 DD C0 73 CD CA 2A 8C A9 B8 43 7E 0C E9 F6 74 
    3C 88 2C D0 11 86 66 E2 2B 4F A2 E7
    
    BLE [80747]:testECCSigning -  signature
    BLE [80748] l=32: 69 E7 25 38 AB 8D 20 3B 18 63 C0 43 57 77 88 06 DF 76 F0 84 
    13 52 C4 60 21 31 3D AB AE 24 C5 EB
    BLE [80748] l=32: 6F C8 26 15 88 A9 F2 EE 81 43 6F C3 3D 3F 7C CE 08 66 DD A7 
    BB 76 AA 88 D4 1A 73 1F DC 44 1C 53
    

  • I've added the test case to verifying the signature using ECCROMCC26XX_verifyHash(). The signature used is the one generated in the signature generation test case.

    Enclosed is the updated test_signature.c and the new_result.txt ran on my platform for your review.

    /*********************************************************************
    * INCLUDES
    */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    #ifdef DEBUG
    #include <driverlib/ioc.h>
    #endif // DEBUG
    
    
    #include "CryptoCC26XX.h"
    #include "SHA2CC26XX.h"
    #include "ECCROMCC26XX.h"
    #include "CC2640R2DK_4XS.h"
    
    CryptoCC26XX_Handle handle;
    
    static uint8_t * eccMalloc(uint16_t len);
    static void eccFree(void *fp);
    static void eccSwapByte32(uint8_t * p);
    
    #define SHA256_runFullAlgorithm SHA2CC26XX_runFullAlgorithm
    
    
    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    
    void sendPrintBytes(void *buff, int len)
    {
       // dummy for debug print
    }
    
    void sendPrintString(void *buff)
    {
       // dummy for debug print
    }
    
    void sendPrintDebug(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4)
    {
       // dummy for debug print
    }
    
    
    // according to TI, the SHA256 success return code is 0x77
    #define SHA256_SUCCESS	0x77
    int genSHA256(uint8_t * input, uint8_t len, uint8_t * output)
    {
    	int8_t status;
    	SHA256_memory_t sha256WorkMem;
    	
    	// this function returns 0x77 when successful
    	status =  SHA256_runFullAlgorithm(&sha256WorkMem, input, len, output);
    
    	return (status == SHA256_SUCCESS) ? ECCROMCC26XX_STATUS_SUCCESS : status;
    }
    
    static void eccSwapByte32(uint8_t * p)
    {
    	uint8_t buffer[32];
    	int i;
    
    	for (i=0; i<32; i++)
    	{
    		buffer[i] = p[31-i];
    	}
    
    	memcpy (p, buffer, 32);
    }
    
    
    static uint8_t * eccMalloc(uint16_t len)
    {
    	uint8_t *p;
    	
    	p = (uint8_t*)ICall_malloc(len);
    
    	sendPrintString("eccMalloc");
    	sendPrintDebug(len, (uint8_t)p, (uint8_t)p>>8,0,0);
    	return p;
    }
    
    static void eccFree(void *fp)
    {
    	sendPrintString("eccMalloc");
    	sendPrintDebug((uint8_t)fp, (uint8_t)fp>>8,0,0,0);
    	ICall_free(fp);
    }
    
    /*
    Date: 10Jan2017
    
    Test Data and result. 
    All computation results are the same for SCP and openssl.
    
    6. ECC Signature generation and verification
    
    	// root signing private key:
    	const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d,
    	};
    
    	// root signature verification public key:
    	const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f,
    	};
    
    	// random 76 bytes
    	uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3
    	};
    
    	// expected signature
    	const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    	};
    */
    
    //.................... patch certificate ........................
    // root  public key - used for signature verification:
    const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f
    };
    
    // root signing private key
    const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d
    };
    
    // random string - 76 bytes
    const uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3 
    };
    
    const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    };
    
    uint8_t workZone[288*4]; // Large enough for verify
    
    void testECCKeyGen()
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	bsPublicKeyX = publicKeyX;
    	bsPublicKeyY = publicKeyY;
    	
    	sendPrintString("testECCKeyGen - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	eccSwapByte32(privateKey);
    	sendPrintString("testECCKeyGen - ECCROMCC26XX_genKeys() private key");
    	sendPrintBytes(privateKey, 32);
    	
    	status = ECCROMCC26XX_genKeys(privateKey, publicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		eccSwapByte32(bsPublicKeyX);
    		eccSwapByte32(bsPublicKeyY);
    
    		sendPrintString("testECCKeyGen -  generated public key");	
    		sendPrintBytes(bsPublicKeyX, 32);
    		sendPrintBytes(bsPublicKeyY, 32);
    	}
    }
    
    void testECCSigning(uint8_t* signS1Buf, uint8_t* signS2Buf)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    	uint8_t sha256Out[32] = {0};      
    
    	sendPrintString("testECCSigning - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	sendPrintString("testECCSigning - public certificate");	
    	
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
           status = genSHA256(sha256_input, 76, sha256Out);
    
    	Task_sleep(333000/10);
           sendPrintBytes(sha256_input, 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[32], 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[64], 12);
    	Task_sleep(333000/10);
    
    	sendPrintString("testECCSigning - sha2 out");	
           sendPrintBytes(&status, 1);
           sendPrintBytes(sha256Out, 32);
    
    	sendPrintString("testECCSigning - ECCROMCC26XX_signHash() private key");	
    	memcpy(privateKey, Kpriv_patch_sig, 32);
    	eccSwapByte32(privateKey);
    	sendPrintBytes(privateKey, 32);
    
    	status = ECCROMCC26XX_signHash(privateKey, sha256Out,
                                 32, signS1Buf, signS2Buf, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintString("testECCSigning -  signature");	
    		sendPrintBytes(signS1Buf, 32);
    		sendPrintBytes(signS2Buf, 32);
    	}
    
    }
    
    void testECCVerifying(uint8_t* signS1Buf, uint8_t* signS2Buf)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    	uint8_t sha256Out[32] = {0};      
    
    	bsPublicKeyX = publicKeyX;
    	bsPublicKeyY = publicKeyY;
    	
    	memcpy(bsPublicKeyX, Kpub_patch_sig, 32);
    	memcpy(bsPublicKeyY, &Kpub_patch_sig[32], 32);
    	
    	sendPrintString("testECCVerifying - signature");
    	memcpy(signS1Buf, expected_signature, 32);
    	memcpy(signS2Buf, &expected_signature[32], 32);
    	Task_sleep(333000/10);
    	sendPrintBytes(signS1Buf, 32);
    	Task_sleep(333000/10);
    	sendPrintBytes(signS2Buf, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	sendPrintString("testECCVerifying - public certificate");	
    	
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
           status = genSHA256(sha256_input, 76, sha256Out);
    
    	Task_sleep(333000/10);
           sendPrintBytes(sha256_input, 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[32], 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[64], 12);
    	Task_sleep(333000/10);
    
    	sendPrintString("testECCVerifying - sha2 out");	
           sendPrintBytes(&status, 1);
           sendPrintBytes(sha256Out, 32);
    
    	eccSwapByte32(bsPublicKeyX);
    	eccSwapByte32(bsPublicKeyY);
    	
    	sendPrintString("testECCVerifying -ECCROMCC26XX_verifyHash() public key");
           sendPrintBytes(bsPublicKeyX, 32);
           sendPrintBytes(bsPublicKeyY, 32);
    
    	status = ECCROMCC26XX_verifyHash(publicKeyX, publicKeyY,
    		signS1Buf, signS2Buf, sha256Out, 32, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintString("testECCVerifying -  passed");	
    	}
    	else
    	{
    
    		sendPrintString("testECCVerifying -  failed");
    		sendPrintBytes(&status, 1);
    	}
    
    }
    
    
    void cryptoInit()
    {
    	uint8_t signS1Buf[32] = {0};
    	uint8_t signS2Buf[32] = {0};
    
    	// Initialize Crypto driver
    	CryptoCC26XX_init();
    	handle = CryptoCC26XX_open(CC2640R2DK_4XS_CRYPTO0, false, NULL);
    
    	// Initialize ECC ROM driver
    	ECCROMCC26XX_init();
    	
    	// this shows that the public key generated from the private key matches with openssl
    	testECCKeyGen();
    
    	// use the same private key and the 76 random bytes to generate the signature
    	testECCSigning(signS1Buf, signS2Buf);
    
    	// use the public key and the 76 random bytes and the previosuly generatedthe signature to verify
    	testECCVerifying(signS1Buf, signS2Buf);
    }
    
    
    
    // check public key generated with the private key
    BLE [80651]:testECCKeyGen - original private key
    BLE [80652] l=32: E7 A2 4F 2B E2 66 86 11 D0 2C 88 3C 74 F6 E9 0C 7E 43 B8 A9 
    8C 2A CA CD 73 C0 DD 19 86 24 8F 0D
    BLE [80653]:testECCKeyGen - ECCROMCC26XX_genKeys() private key (32 bytes swap)
    BLE [80654] l=32: 0D 8F 24 86 19 DD C0 73 CD CA 2A 8C A9 B8 43 7E 0C E9 F6 74 
    3C 88 2C D0 11 86 66 E2 2B 4F A2 E7
    
    BLE [80662]:testECCKeyGen -  generated public key (64 bytes)
    BLE [80663] l=32: DA 3C 68 85 95 0E A7 F5 83 38 89 3A F1 56 B9 48 55 22 EC 63 
    EB 78 62 EF E9 19 30 E9 6D 0C CC 07
    BLE [80663] l=32: D0 CA 9B A6 04 17 53 D6 D2 8D C5 AF F7 78 F9 CD 0D 31 DE 01 
    93 A3 82 1A F2 01 25 CB 7A 00 17 3F
    
    
    // test case signature generation with the private key and the 76 bytes of message 
    // digest (12 bytes of identity + 64 bytes of public key)
    BLE [80678]:testECCSigning - original private key
    BLE [80679] l=32: E7 A2 4F 2B E2 66 86 11 D0 2C 88 3C 74 F6 E9 0C 7E 43 B8 A9 
    8C 2A CA CD 73 C0 DD 19 86 24 8F 0D
    
    BLE [80680]:testECCSigning - public certificate
    BLE [80694] l=32: 35 31 32 33 34 35 36 37 38 34 12 04 02 A0 F8 A7 5A E6 CB 60 
    6C F0 63 C9 4E 4F 14 B1 79 B0 F5 72
    BLE [80708] l=32: 7F F0 50 91 3F C2 EC 57 5C 24 6E 94 0D 88 4E 4C C8 6D A6 26 
    59 38 3F 1B D7 89 79 65 1E F2 27 A4
    BLE [80722] l=12: AB 65 A1 BE 72 CB F3 CD 1A CF 60 F3
    
    BLE [80735]:testECCSigning - sha2 out (status + 32 hash)
    BLE [80736] l=1: 00
    BLE [80736] l=32: C3 54 89 6D 46 1A DA 64 32 0A DF E9 58 DD 91 03 E7 CC 50 A3 
    22 B8 F6 85 90 39 B1 C4 B2 89 51 25
    
    BLE [80738]:testECCSigning - ECCROMCC26XX_signHash() private key used
    BLE [80738] l=32: 0D 8F 24 86 19 DD C0 73 CD CA 2A 8C A9 B8 43 7E 0C E9 F6 74 
    3C 88 2C D0 11 86 66 E2 2B 4F A2 E7
    
    BLE [124]:testECCSigning -  signature generated in ECCROMCC26XX_signHash()
    BLE [125] l=32: BA CD 88 12 86 CD 30 5A 05 24 12 C3 B2 D2 32 20 41 F1 E6 E6 09 B4 07 55 EE 6A 87 43 3F C3 02 4E 
    BLE [125] l=32: 9D 13 20 BA FC CA E6 C7 AF E7 26 FC F9 3B 18 5D B3 83 99 7F 9F F4 C9 6F 81 60 4C C4 4B DD 0E 72 
    
    
    // test case for signature verification
    BLE [126]:testECCVerifying... 
    BLE [140]:testECCVerifying - signature used the one generated in signature generated case
    BLE [154] l=32: BA CD 88 12 86 CD 30 5A 05 24 12 C3 B2 D2 32 20 41 F1 E6 E6 09 B4 07 55 EE 6A 87 43 3F C3 02 4E 
    BLE [168] l=32: 9D 13 20 BA FC CA E6 C7 AF E7 26 FC F9 3B 18 5D B3 83 99 7F 9F F4 C9 6F 81 60 4C C4 4B DD 0E 72 
    
    BLE [169]:testECCVerifying - public certificate (same as previous case)
    BLE [183] l=32: 35 31 32 33 34 35 36 37 38 34 12 04 02 A0 F8 A7 5A E6 CB 60 6C F0 63 C9 4E 4F 14 B1 79 B0 F5 72 
    BLE [197] l=32: 7F F0 50 91 3F C2 EC 57 5C 24 6E 94 0D 88 4E 4C C8 6D A6 26 59 38 3F 1B D7 89 79 65 1E F2 27 A4 
    BLE [211] l=12: AB 65 A1 BE 72 CB F3 CD 1A CF 60 F3 
    
    BLE [225]:testECCVerifying - sha2 out 
    BLE [225] l=1: 00 
    BLE [225] l=32: C3 54 89 6D 46 1A DA 64 32 0A DF E9 58 DD 91 03 E7 CC 50 A3 22 B8 F6 85 90 39 B1 C4 B2 89 51 25 
    
    
    BLE [227]:testECCVerifying -ECCROMCC26XX_verifyHash() public key used
    BLE [227] l=32: 07 CC 0C 6D E9 30 19 E9 EF 62 78 EB 63 EC 22 55 48 B9 56 F1 3A 89 38 83 F5 A7 0E 95 85 68 3C DA 
    BLE [228] l=32: 3F 17 00 7A CB 25 01 F2 1A 82 A3 93 01 DE 31 0D CD F9 78 F7 AF C5 8D D2 D6 53 17 04 A6 9B CA D0 
    
    // failed with status 3C
    BLE [235]:testECCVerifying -  failed 
    BLE [235] l=1: 3C 
    

  • FYI

    The ECCROMCC26XX_signHash() produces a different signature every time it is called even when all the input parameters are the same, the implementation in the testECCSigning() is to show you how I would implement it using the ECC driver and it will needs to be debugged to get it to work properly.

    Also, the testECCVerifying() is overwriting the passed in signature before calling the ECCROMCC26XX_verifyHash() and it's corrected in the enclosed file. I suspect that the implementation is probably incorrect.

    Also, removed the workzone memory allocation since the memory is allocated within the ECC functions and the project builds without it.

    /*********************************************************************
    * INCLUDES
    */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Queue.h>
    #ifdef DEBUG
    #include <driverlib/ioc.h>
    #endif // DEBUG
    
    
    #include "CryptoCC26XX.h"
    #include "SHA2CC26XX.h"
    #include "ECCROMCC26XX.h"
    #include "CC2640R2DK_4XS.h"
    
    CryptoCC26XX_Handle handle;
    
    static uint8_t * eccMalloc(uint16_t len);
    static void eccFree(void *fp);
    static void eccSwapByte32(uint8_t * p);
    
    #define SHA256_runFullAlgorithm SHA2CC26XX_runFullAlgorithm
    
    
    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    
    void sendPrintBytes(void *buff, int len)
    {
       // dummy for debug print
    }
    
    void sendPrintString(void *buff)
    {
       // dummy for debug print
    }
    
    void sendPrintDebug(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4)
    {
       // dummy for debug print
    }
    
    
    // according to TI, the SHA256 success return code is 0x77
    #define SHA256_SUCCESS	0x77
    int genSHA256(uint8_t * input, uint8_t len, uint8_t * output)
    {
    	int8_t status;
    	SHA256_memory_t sha256WorkMem;
    	
    	// this function returns 0x77 when successful
    	status =  SHA256_runFullAlgorithm(&sha256WorkMem, input, len, output);
    
    	return (status == SHA256_SUCCESS) ? ECCROMCC26XX_STATUS_SUCCESS : status;
    }
    
    static void eccSwapByte32(uint8_t * p)
    {
    	uint8_t buffer[32];
    	int i;
    
    	for (i=0; i<32; i++)
    	{
    		buffer[i] = p[31-i];
    	}
    
    	memcpy (p, buffer, 32);
    }
    
    
    static uint8_t * eccMalloc(uint16_t len)
    {
    	uint8_t *p;
    	
    	p = (uint8_t*)ICall_malloc(len);
    
    	sendPrintString("eccMalloc");
    	sendPrintDebug(len, (uint8_t)p, (uint8_t)p>>8,0,0);
    	return p;
    }
    
    static void eccFree(void *fp)
    {
    	sendPrintString("eccMalloc");
    	sendPrintDebug((uint8_t)fp, (uint8_t)fp>>8,0,0,0);
    	ICall_free(fp);
    }
    
    /*
    Date: 10Jan2017
    
    Test Data and result. 
    All computation results are the same for SCP and openssl.
    
    6. ECC Signature generation and verification
    
    	// root signing private key:
    	const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d,
    	};
    
    	// root signature verification public key:
    	const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f,
    	};
    
    	// random 76 bytes
    	uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3
    	};
    
    	// expected signature
    	const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    	};
    */
    
    //.................... patch certificate ........................
    // root  public key - used for signature verification:
    const uint8_t Kpub_patch_sig[] = {
    	0x04, 0xda, 0x3c, 0x68, 0x85, 0x95, 0x0e, 0xa7, 0xf5, 0x83, 0x38, 0x89, 0x3a, 0xf1, 0x56, 0xb9,
    	0x48, 0x55, 0x22, 0xec, 0x63, 0xeb, 0x78, 0x62, 0xef, 0xe9, 0x19, 0x30, 0xe9, 0x6d, 0x0c, 0xcc,
    	0x07, 0xd0, 0xca, 0x9b, 0xa6, 0x04, 0x17, 0x53, 0xd6, 0xd2, 0x8d, 0xc5, 0xaf, 0xf7, 0x78, 0xf9,
    	0xcd, 0x0d, 0x31, 0xde, 0x01, 0x93, 0xa3, 0x82, 0x1a, 0xf2, 0x01, 0x25, 0xcb, 0x7a, 0x00, 0x17,
    	0x3f
    };
    
    // root signing private key
    const uint8_t Kpriv_patch_sig[] = {
    	0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11, 0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
    	0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd, 0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d
    };
    
    // random string - 76 bytes
    const uint8_t Patch_certificate[76] = {
    	0x35 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x34 , 0x12 , 0x04 , 0x02 , 0xa0 , 0xf8 , 0xa7, 
    	0x5a , 0xe6 , 0xcb , 0x60 , 0x6c , 0xf0 , 0x63 , 0xc9 , 0x4e , 0x4f , 0x14 , 0xb1 , 0x79 , 0xb0 , 0xf5 , 0x72, 
    	0x7f , 0xf0 , 0x50 , 0x91 , 0x3f , 0xc2 , 0xec , 0x57 , 0x5c , 0x24 , 0x6e , 0x94 , 0x0d , 0x88 , 0x4e , 0x4c, 
    	0xc8 , 0x6d , 0xa6 , 0x26 , 0x59 , 0x38 , 0x3f , 0x1b , 0xd7 , 0x89 , 0x79 , 0x65 , 0x1e , 0xf2 , 0x27 , 0xa4, 
    	0xab , 0x65 , 0xa1 , 0xbe , 0x72 , 0xcb , 0xf3 , 0xcd , 0x1a , 0xcf , 0x60 , 0xf3 
    };
    
    const uint8_t expected_signature[] = {
    	0x32 , 0x99 , 0x87 , 0x5d, 0x0b , 0xaa , 0xd6 , 0x2b , 0x6c , 0xec , 0x25 , 0x02 , 0x7d , 0x10 , 0x21 , 0xb7 , 
    	0x4c , 0x77 , 0xea , 0xb5, 0x09 , 0x19 , 0x09 , 0x6d , 0xd6 , 0x38 , 0xc3 , 0xae , 0x9b , 0xa2 , 0x88 , 0x3c , 
    	0x21 , 0x4e , 0x92 , 0x01, 0xa4 , 0xf6 , 0x05 , 0x79 , 0xac , 0xa7 , 0x3d , 0x3c , 0x67 , 0x79 , 0xa8 , 0x8b , 
    	0xb1 , 0xad , 0xac , 0x8b, 0x5c , 0x92 , 0x31 , 0x87 , 0x55 , 0x01 , 0x45 , 0xed , 0x45 , 0x78 , 0x99 , 0x67
    };
    
    //uint8_t workZone[288*4]; // Large enough for verify
    
    void testECCKeyGen()
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	bsPublicKeyX = publicKeyX;
    	bsPublicKeyY = publicKeyY;
    	
    	sendPrintString("testECCKeyGen - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	// Generate public keys
    	eccSwapByte32(privateKey);
    	sendPrintString("testECCKeyGen - ECCROMCC26XX_genKeys() private key");
    	sendPrintBytes(privateKey, 32);
    	
    	status = ECCROMCC26XX_genKeys(privateKey, publicKeyX,
    		bsPublicKeyY, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		eccSwapByte32(bsPublicKeyX);
    		eccSwapByte32(bsPublicKeyY);
    
    		sendPrintString("testECCKeyGen -  generated public key");	
    		sendPrintBytes(bsPublicKeyX, 32);
    		sendPrintBytes(bsPublicKeyY, 32);
    	}
    }
    
    void testECCSigning(uint8_t* signS1Buf, uint8_t* signS2Buf)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t privateKey[32];
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    	uint8_t sha256Out[32] = {0};      
    
    	sendPrintString("testECCSigning - original private key");
    	memcpy(privateKey, Kpriv_patch_sig,32);
    	sendPrintBytes(privateKey, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	sendPrintString("testECCSigning - public certificate");	
    	
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
           status = genSHA256(sha256_input, 76, sha256Out);
    
    	Task_sleep(333000/10);
           sendPrintBytes(sha256_input, 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[32], 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[64], 12);
    	Task_sleep(333000/10);
    
    	sendPrintString("testECCSigning - sha2 out");	
           sendPrintBytes(&status, 1);
           sendPrintBytes(sha256Out, 32);
    
    	sendPrintString("testECCSigning - ECCROMCC26XX_signHash() private key");	
    	memcpy(privateKey, Kpriv_patch_sig, 32);
    	eccSwapByte32(privateKey);
    	sendPrintBytes(privateKey, 32);
    
    	status = ECCROMCC26XX_signHash(privateKey, sha256Out,
                                 32, signS1Buf, signS2Buf, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintString("testECCSigning -  signature");	
    		sendPrintBytes(signS1Buf, 32);
    		sendPrintBytes(signS2Buf, 32);
    	}
    
    }
    
    void testECCVerifying(uint8_t* signS1Buf, uint8_t* signS2Buf)
    {
    	int8_t status;
    	ECCROMCC26XX_Params      params;
    	
    	uint8_t publicKeyX[32]  = {0};
    	uint8_t publicKeyY[32]  = {0};
    	uint8_t *bsPublicKeyX;
    	uint8_t *bsPublicKeyY;
    
    	// sha256 input/output buffers
    	uint8_t sha256_input[76];
    	uint8_t sha256Out[32] = {0};      
    
    	bsPublicKeyX = publicKeyX;
    	bsPublicKeyY = publicKeyY;
    	
    	memcpy(bsPublicKeyX, Kpub_patch_sig, 32);
    	memcpy(bsPublicKeyY, &Kpub_patch_sig[32], 32);
    	
    	sendPrintString("testECCVerifying - signature");
    	Task_sleep(333000/10);
    	sendPrintBytes(signS1Buf, 32);
    	Task_sleep(333000/10);
    	sendPrintBytes(signS2Buf, 32);
    	
    	// Initialize this client's ECCROMCC26XX parameters.
    	ECCROMCC26XX_Params_init(&params);
    
    	// Set the Malloc and Free functions for internal buffer allocation.
    	params.malloc = (uint8_t *(*)(uint16_t))eccMalloc;
    	params.free   = (void (*)(uint8_t *))eccFree;
    
    	// If an indefinite timeout is undesirable, alter the timeout here.
    	// the value specified here will be a multiple of Clock.tickPeriod is
    	// specified as.
    	params.timeout = 1000; // wait a maximum of 1000 system time units
    
    	sendPrintString("testECCVerifying - public certificate");	
    	
    	// patch certificate verification
    	memcpy (sha256_input, Patch_certificate, 76);
           status = genSHA256(sha256_input, 76, sha256Out);
    
    	Task_sleep(333000/10);
           sendPrintBytes(sha256_input, 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[32], 32);
    	Task_sleep(333000/10);
           sendPrintBytes(&sha256_input[64], 12);
    	Task_sleep(333000/10);
    
    	sendPrintString("testECCVerifying - sha2 out");	
           sendPrintBytes(&status, 1);
           sendPrintBytes(sha256Out, 32);
    
    	eccSwapByte32(bsPublicKeyX);
    	eccSwapByte32(bsPublicKeyY);
    	
    	sendPrintString("testECCVerifying -ECCROMCC26XX_verifyHash() public key");
           sendPrintBytes(bsPublicKeyX, 32);
           sendPrintBytes(bsPublicKeyY, 32);
    
    	status = ECCROMCC26XX_verifyHash(publicKeyX, publicKeyY,
    		signS1Buf, signS2Buf, sha256Out, 32, &params);
    
    	if (status == ECCROMCC26XX_STATUS_SUCCESS)
    	{
    		sendPrintString("testECCVerifying -  passed");	
    	}
    	else
    	{
    
    		sendPrintString("testECCVerifying -  failed");
    		sendPrintBytes(&status, 1);
    	}
    
    }
    
    
    void cryptoInit()
    {
    	uint8_t signS1Buf[32] = {0};
    	uint8_t signS2Buf[32] = {0};
    
    	// Initialize Crypto driver
    	CryptoCC26XX_init();
    	handle = CryptoCC26XX_open(CC2640R2DK_4XS_CRYPTO0, false, NULL);
    
    	// Initialize ECC ROM driver
    	ECCROMCC26XX_init();
    	
    	// this shows that the public key generated from the private key matches with openssl
    	testECCKeyGen();
    
    	// use the same private key and the 76 random bytes to generate the signature
    	testECCSigning(signS1Buf, signS2Buf);
    
    	// use the public key and the 76 random bytes and the previosuly generatedthe signature to verify
    	testECCVerifying(signS1Buf, signS2Buf);
    }
    
    
    

  • Hi Tony,

    Thanks for sharing this with me. I will look into it ASAP when I'm back from vacation if you have not found the issue (or someone else helped you debug this) by then.

  • Tony,

    I'm taking this thread in the meantime. 

    Without looking deeply at all the details in the discussion, I wanted to address your first question:

    "I’m in the process to revive the security code from an older project to the a new project using sdk 4.10.0.10

    The older project uses sdk 2.2.0.31 and supports ECC_ECDSA_sign(),  ECC_ECDSA_verify() ROM functions.

    With the same app building with sdk4.10.0.10, I encountered these link errors below.

    Since these are supported in the ROM and using the same device, these functions should be supported but maybe the name has changed to eccRom_signHash(), eccRom_verifyHash() resp. The function prototype for eccRom_verifyHash() seems to match ECC_ECDSA_verify(). Please confirm that to be the case."

    It looks to me that these APIs changed from ECC_ECDS_sign() to simply ECDS_sign(), and  ECC_ECDSA_verify() to ECDSA_verify(). If you installed the SDK v4.10, these functions are documented here: 

    C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/docs/tidrivers/doxygen/html/_e_c_d_s_a_8h.html#a3ad7bc590603181380f2f8d4c01e09f3

    (or look at ...\docs\Documentation_Overview.html and navigate to 'TI Drivers Runtime APIs', then ECDSA.h)

    Or is the issue / question deeper than this? Maybe I'm missing something?

    I'll address your other questions next, but please let me know your thoughts.

    Thanks,

    Luis

  • Luis,

    Thanks for pointing me to this part of the documentation. I'll take a more detail look and probably have more questions. I've looked at the signing example and have some initial questions:

    1. what are the formats of the parameters in CryptoKeyPlaintext_initKey() - &pmsnKey, pmsn?

    2. Are the signatures returned in ECDSA_sign() operationSign.r and operationSign.s ? If so, should the application allocate the memory for signature or it's allocated and need the application to free it when it's finished.

    Tony

    // Import ECDSA Driver definitions
    // Since we are using default ECDSA_Params, we just pass in NULL for that parameter.
    ecdsaHandle = ECDSA_open(0, NULL);
    if (!ecdsaHandle) {
    // Handle error
    }
    // Initialize myPrivateKey
    CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
    CryptoKeyPlaintext_initKey(&pmsnKey, pmsn, sizeof(pmsn));
    // Initialize the operation
    ECDSA_OperationSign_init(&operationSign);
    operationSign.curve = &ECCParams_NISTP256;
    operationSign.myPrivateKey = &myPrivateKey;
    operationSign.pmsn = &pmsnKey;
    operationSign.hash = messageHash;
    operationSign.r = r;
    operationSign.s = s;
    // Generate the signature
    operationResult = ECDSA_sign(ecdsaHandle, &operationSign);
  • Tony,

    As shown in...

    file:///C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/docs/tidrivers/doxygen/html/_crypto_key_plaintext_8h.html

    ...the CryptoKeyPlaintext_initKey() function expects something like this:

    uint8_t keyingMaterial[16];
    CryptoKey cryptoKey;
    // Initialise the CryptoKey
    CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
    // Use the CryptoKey in another crypto operation

    And yes, the signatures are returned in r and s. As mentioned in the section "Signing a Message", the r and s vectors will be written to the buffers provided in the function call. So yes, you have to allocate them like they do in the synopsis or example. Something like this:

    uint8_t r[32] = {0};
    uint8_t s[32] = {0};
    I hope this helps. 
    -Luis

  • Yes, I saw that and in the process of re-writing the test code using this set of API.

    Now, I'm running into a problem with compiling ECDSACC26X2.c. Without this file, it get a linker error.

    Can you send me a project with sample c file which generates and verifies the signature with the ECC keys and message using these API ?

    Tony

    // linker error

    Linking
    Error[Li005]: no definition for "ECDSA_open" [referenced from C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\examples\rtos\
    CC2640R2_LAUNCHXL\blestack\simple_central_ecc\tirtos\iar\app\FlashROM_StackLibrary\Obj\test_signature.o]
    Error[Li005]: no definition for "ECDSA_OperationSign_init" [referenced from C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\examples\rtos\
    CC2640R2_LAUNCHXL\blestack\simple_central_ecc\tirtos\iar\app\FlashROM_StackLibrary\Obj\test_signature.o]
    Error[Li005]: no definition for "ECDSA_sign" [referenced from C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\examples\rtos\
    CC2640R2_LAUNCHXL\blestack\simple_central_ecc\tirtos\iar\app\FlashROM_StackLibrary\Obj\test_signature.o]
    Error[Li005]: no definition for "ECCParams_NISTP256" [referenced from C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\examples\rtos\
    CC2640R2_LAUNCHXL\blestack\simple_central_ecc\tirtos\iar\app\FlashROM_StackLibrary\Obj\test_signature.o]

    // compilation error - missing hw_pka.h file

    Performing Pre-Build Action
    ECDSACC26X2.c 
    Fatal Error[Pe1696]: cannot open source file "ti/devices/cc26x0r2/inc/hw_pka.h" C:\ti\simplelink_cc2640r2_sdk_4_10_00_10\source\ti\drivers\ecdsa\ECDSACC26X2.c 53
                searched: "C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/kernel/tirtos/packages/"
                searched: "C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/source/"
                searched: "C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/source/ti/blestack/"
                searched: "C:/ti/xdctools_3_51_03_28_core/packages/"
                searched: 
    "C:/ti/simplelink_cc2640r2_sdk_4_10_00_10/examples/rtos/CC2640R2_LAUNCHXL/blestack/simple_central_ecc/tirtos/iar/config/conf

  • Tony,

    I'm working with my team of experts to get you an answer and an example that can enable you to use our product. 

    This is a high priority for me. I should provide an update on 7/16/2020.

    Thanks for your patience.

    -Luis

  • Sounds good Luis.

    Also it would be great if your example can run the ECC private/public keys, hash message to generate and verify the signature provided in the test_signature.c file submitted earlier in this thread.

    Thanks for your help.

  • Tony,

    Just a quick update. It looks like using the ECDSACC26X2.c file was the wrong approach. That file is designed for other parts that have HW support for this feature (i.e. CC2642), so the result of hw_pka.h missing is the expected result. The APIs don't apply, then. My apologies for this mistake.

    While it is technically feasible to use ECC / ECDSA in your project, there will be more effort involved.

    I'm working with my dev team to understand exactly how this should be done. I know that the BLE Stack uses ECC from <sdk>\source\ti\blestack\common\cc26xx\ecc, but I have to get more details. Feel free to explore that file and try to figure out a way to use it in the meantime.

    As I have mentioned before, this issue is a high priority for me, but it will still take me a few days to figure out. I'll plan to have an update in a week from now on 7/23 or sooner.

    Thanks,

    Luis

  • Tony,

    I've analyzed the code and I'm coming to the conclusion that the driver you need is:

    C:\ti\simplelink_cc2640r2_sdk_3_40_00_10\source\ti\blestack\common\cc26xx\ecc\ECCROMCC26XX.c

    This file includes functions to initialize, generate keys, sign, and verify, which I believe is what you need; and that can be used through the ICall interface.

    Now, I should mention that this code is in Flash, and makes use of the functions that you had mentioned before, the ones that start with eccRom, such as eccRom_signHash and eccRom_verifyHash. That code is not directly accesible.

    However, I noticed that the eccDriverTable[] in icall_user_config.c does not include all global functions from this file. In particular, the sign and verify functions are missing, and I believe that is an error. I am trying to confirm that with the team. 

    Very importantly, I am in the process of putting together an example application that uses this driver. However, I wanted to share this with you as it may be helpful to make progress in parallel.

    Please consider this information, which I hope will be helpful.

    I'll keep you updated and I look fw to hear from you.

    Thanks,

    Luis

  • Luis,

    On July 7 @11pm I've posted my test_signature.c file which uses the ECCROMCC26XX.c functions, but the signature generated were incorrect, and furthermore the generated signatures are different every time the function is executed.

    Please take a look at that file and perhaps you can spot something wrong.

    Tony

  • Tony,

    Got it. I'll review the code. 

    Thanks,

    Luis

  • Tony,

    I have good news. I have an example that works.

    In summary, the solution was fairly simple: increase the workzone length from 684 to 1100 bytes. The instructions in the comments suggest it that way. Basically, modify function ECCROMCC26XX_Params_init(), as follows:

    void ECCROMCC26XX_Params_init(ECCROMCC26XX_Params *params)
    {
      // Initialize Curve to NIST P-256 with window size 3 by default.
      params->curve.keyLen      = ECCROMCC26XX_NIST_P256_KEY_LEN_IN_BYTES;
      
      // Initialize the workzone length according to whether only keys are
      // generated or if sign and verify are used
      // #before
      //  params->curve.workzoneLen = ECCROMCC26XX_NIST_P256_WORKZONE_LEN_IN_BYTES;
      // #after
      params->curve.workzoneLen = ECCROMCC26XX_NIST_P256_WORKZONE_SIGN_VERIFY_LEN_IN_BYTES;
      ...
    }
    

    Then, the example of how to use the driver is located at the top of the header file, in ECCROMCC26XX.h.

    So, I implemented the use of the driver in simple_peripheral.c, at the beginning of the simple peripheral task. There are many variables and constants at the top of the file. See the code attached. It contains simple_peripheral.c and the driver itself ECCROMCC26XX.c and .h. Important Note: This is for the SDK 3.40.

    I tested the file with the input you provided as "Patch_certificate". I renamed it input_array_1. Then, I basically took that 76-byte array and computed its hash using an online SHA-256 generator and put it in hash_1. To test further, I created another pair input_array_2 using random.org, and again produced online its SHA256 hash. I verified that the signatures for both hashes can be generated (i.e. with the Sign operation) and verified. 

    I also added a line just before the verify operation, in which you can introduce a modification to the signature in order to produce an error in the verification step. You'll see:

        // Enable the following line to introduce an error and fail the verification
        //sign2[7] += 10; // <<<--- offset and value are arbitrary, you may try others
    
        verify_result = ECCROMCC26XX_verifyHash(localPublicKeyX,
    

    I hope this is helpful and enables you to use our ECC driver.

    Thanks,

    Luis

    simple_peripheral_cc2640r2_sdk_3.40.zip

  • Tony,

    I have good news. I have an example that works.

    In summary, the solution was fairly simple: increase the workzone length from 684 to 1100 bytes. The instructions in the comments suggest it that way. Basically, modify function ECCROMCC26XX_Params_init(), as follows:

    void ECCROMCC26XX_Params_init(ECCROMCC26XX_Params *params)
    {
      // Initialize Curve to NIST P-256 with window size 3 by default.
      params->curve.keyLen      = ECCROMCC26XX_NIST_P256_KEY_LEN_IN_BYTES;
      
      // Initialize the workzone length according to whether only keys are
      // generated or if sign and verify are used
      // #before
      //  params->curve.workzoneLen = ECCROMCC26XX_NIST_P256_WORKZONE_LEN_IN_BYTES;
      // #after
      params->curve.workzoneLen = ECCROMCC26XX_NIST_P256_WORKZONE_SIGN_VERIFY_LEN_IN_BYTES;
      ...
    }
    

    Then, the example of how to use the driver is located at the top of the header file, in ECCROMCC26XX.h.

    So, I implemented the use of the driver in simple_peripheral.c, at the beginning of the simple peripheral task. There are many variables and constants at the top of the file. See the code attached. It contains simple_peripheral.c and the driver itself ECCROMCC26XX.c and .h. Important Note: This is for the SDK 3.40.

    I tested the file with the input you provided as "Patch_certificate". I renamed it input_array_1. Then, I basically took that 76-byte array and computed its hash using an online SHA-256 generator and put it in hash_1. To test further, I created another pair input_array_2 using random.org, and again produced online its SHA256 hash. I verified that the signatures for both hashes can be generated (i.e. with the Sign operation) and verified. 

    I also added a line just before the verify operation, in which you can introduce a modification to the signature in order to produce an error in the verification step. You'll see:

        // Enable the following line to introduce an error and fail the verification
        //sign2[7] += 10; // <<<--- offset and value are arbitrary, you may try others
    
        verify_result = ECCROMCC26XX_verifyHash(localPublicKeyX,
    

    I hope this is helpful and enables you to use our ECC driver.

    Thanks,

    Luis

    simple_peripheral_cc2640r2_sdk_3.40.zip

  • Luis,

    I'll try your example and get back to you in a few days.

    Thanks for your help.

    Tony

  • Luis,

    I have re-written the test code using your file and my findings are as follow:

    1. increasing the workzone memory solves the problem of inconsistent signature generation results, i.e. the signatures generated is the same from run to run.
    2. To get the private key and public key generation to match, I had to do a 32 byte swap of the private key as input to the ECCROMCC26XX_genKeys(). This was a known symptom and our application can deal with this so it's not a problem.
    3. The hash of the 76 bytes digest is correct and it matches with the hash_1[] you used for the signature generation.
    4. The expected signature is not matching with my data set. So I've gone back to using the NIST data set found in ecdsa.h and the signature does not match either.
    5. Although the verification reports success, it is not meaningful since the signature used is not the right one to begin with. We need to make sure the signature generated is correct and then verify that signature with the signer's public key to authenticate the certificate.

    Please take a look at the test_signature_1.c file for the test and run the NIST example to see if you can get the expected r[] and s[] data

    #define USE_NIST_DATA_SET
    
    // Declaration of this client's ECCROMCC26XX parameters.
    ECCROMCC26XX_Params      params;
    
    #ifdef USE_NIST_DATA_SET
     #define myPrivateKeyingMaterial localPrivateKey
     // This vector is taken from the NIST ST toolkit examples from ECDSA_Prime.pdf
     uint8_t myPrivateKeyingMaterial[32] = {0x96, 0xBF, 0x85, 0x49, 0xC3, 0x79, 0xE4, 0x04,
                                            0xED, 0xA1, 0x08, 0xA5, 0x51, 0xF8, 0x36, 0x23,
                                            0x12, 0xD8, 0xD1, 0xB2, 0xA5, 0xFA, 0x57, 0x06,
                                            0xE2, 0xCC, 0x22, 0x5C, 0xF6, 0xF9, 0x77, 0xC4};
    
     #define messageHashSHA256 hash_1
     uint8_t messageHashSHA256[32]        = {0xC4, 0xA8, 0xC8, 0x99, 0x28, 0xCF, 0x80, 0xB6,
                                            0xE4, 0x42, 0xD5, 0xBD, 0x28, 0x4D, 0xE3, 0xFD,
                                            0x3A, 0x13, 0xD8, 0x65, 0x0C, 0x41, 0x1C, 0x21,
                                            0x48, 0x95, 0x79, 0x2A, 0xA1, 0x41, 0x1A, 0xA4};
    
     /* // Send out signature
     * // r should be   0x4F, 0x10, 0x46, 0xCA, 0x9A, 0xB6, 0x25, 0x73,
     * //               0xF5, 0x3E, 0x0B, 0x1F, 0x6F, 0x31, 0x4C, 0xE4,
     * //               0x81, 0x0F, 0x50, 0xB1, 0xF3, 0xD1, 0x65, 0xFF,
     * //               0x65, 0x41, 0x7F, 0xD0, 0x76, 0xF5, 0x42, 0x2B
     * //
     * // s should be   0xF1, 0xFA, 0x63, 0x6B, 0xDB, 0x9B, 0x32, 0x4B,
     * //               0x2C, 0x26, 0x9D, 0xE6, 0x6F, 0x88, 0xC1, 0x98,
     * //               0x81, 0x2A, 0x50, 0x89, 0x3A, 0x99, 0x3A, 0x3E,
     * //               0xCD, 0x92, 0x63, 0x2D, 0x12, 0xC2, 0x42, 0xDC
     */
    
    /*
     * // This vector is taken from the NIST ST toolkit examples from ECDSA_Prime.pdf
     * uint8_t theirPublicKeyingMaterial[64] =  {0x19, 0x7A, 0xBC, 0x89, 0x08, 0xCD, 0x01, 0x82,
     *                                           0xA3, 0xA2, 0x9E, 0x1E, 0xAD, 0xA0, 0xB3, 0x62,
     *                                           0x1C, 0xBA, 0x98, 0x47, 0x73, 0x8C, 0xDC, 0xF1,
     *                                           0xD3, 0xBA, 0x94, 0xFE, 0xFD, 0x8A, 0xE0, 0xB7,
     *                                           0x09, 0x5E, 0xCC, 0x06, 0xC6, 0xBB, 0x63, 0xB5,
     *                                           0x61, 0x9E, 0x52, 0x43, 0xAE, 0xC7, 0xAD, 0x63,
     *                                           0x90, 0x72, 0x28, 0x19, 0xE4, 0x26, 0xB2, 0x4B,
     *                                           0x7A, 0xBF, 0x9D, 0x95, 0x47, 0xF7, 0x03, 0x36};
    */
    
    #else
    // Declaration of local public keys
    uint8_t localPrivateKey[32] = { 0xe7, 0xa2, 0x4f, 0x2b, 0xe2, 0x66, 0x86, 0x11,
                                    0xd0, 0x2c, 0x88, 0x3c, 0x74, 0xf6, 0xe9, 0x0c,
                                    0x7e, 0x43, 0xb8, 0xa9, 0x8c, 0x2a, 0xca, 0xcd,
                                    0x73, 0xc0, 0xdd, 0x19, 0x86, 0x24, 0x8f, 0x0d };
    
    uint8_t hash_1[32] = { 0xc3, 0x54, 0x89, 0x6d, 0x46, 0x1a, 0xda, 0x64, 0x32,
                           0x0a, 0xdf, 0xe9, 0x58, 0xdd, 0x91, 0x03, 0xe7, 0xcc,
                           0x50, 0xa3, 0x22, 0xb8, 0xf6, 0x85, 0x90, 0x39, 0xb1,
                           0xc4, 0xb2, 0x89, 0x51, 0x25 };
    #endif
    
    uint8_t localPublicKeyX[32]  = {0};
    uint8_t localPublicKeyY[32]  = {0};
    uint8_t sharedSecretKeyX[32] = {0};
    uint8_t sharedSecretKeyY[32] = {0};
    uint8_t sign1[32]  = {0};
    uint8_t sign2[32]  = {0};
    
    const uint8_t input_array_1[76] = { 0x35, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
                                        0x37, 0x38, 0x34, 0x12, 0x04, 0x02, 0xa0,
                                        0xf8, 0xa7, 0x5a, 0xe6, 0xcb, 0x60, 0x6c,
                                        0xf0, 0x63, 0xc9, 0x4e, 0x4f, 0x14, 0xb1,
                                        0x79, 0xb0, 0xf5, 0x72, 0x7f, 0xf0, 0x50,
                                        0x91, 0x3f, 0xc2, 0xec, 0x57, 0x5c, 0x24,
                                        0x6e, 0x94, 0x0d, 0x88, 0x4e, 0x4c, 0xc8,
                                        0x6d, 0xa6, 0x26, 0x59, 0x38, 0x3f, 0x1b,
                                        0xd7, 0x89, 0x79, 0x65, 0x1e, 0xf2, 0x27,
                                        0xa4, 0xab, 0x65, 0xa1, 0xbe, 0x72, 0xcb,
                                        0xf3, 0xcd, 0x1a, 0xcf, 0x60, 0xf3 };
    const uint8_t input_array_2[76] = { 0x05, 0xa7, 0x12, 0xc7, 0x87, 0x33, 0x86,
                                        0x4f, 0xd3, 0x0f, 0x1e, 0x5d, 0xd4, 0xd0,
                                        0xa7, 0x20, 0x93, 0xfb, 0x58, 0x8f, 0x74,
                                        0x0b, 0x23, 0x26, 0x12, 0x95, 0xf0, 0x88,
                                        0x10, 0x39, 0xeb, 0x41, 0xb7, 0x84, 0xfb,
                                        0x79, 0x4b, 0x5c, 0xe2, 0xc0, 0x46, 0x08,
                                        0xa5, 0x1c, 0xd5, 0x71, 0x89, 0x02, 0x31,
                                        0x60, 0x3d, 0x5c, 0x0f, 0x27, 0xec, 0xb6,
                                        0x60, 0xe5, 0x41, 0x38, 0x06, 0x25, 0xb7,
                                        0x6d, 0x7b, 0xca, 0x04, 0x84, 0x16, 0x36,
                                        0xee, 0x6d, 0x71, 0xdb, 0xa6, 0xb1 };
    
    uint8_t hash_2[32] = { 0x4b, 0x5e, 0x3c, 0x79, 0xee, 0x64, 0x36, 0x60, 0xba,
                           0x3f, 0x4f, 0x83, 0xe8, 0x58, 0x62, 0xcb, 0xf5, 0x77,
                           0x7f, 0x02, 0x97, 0x96, 0xe4, 0x9e, 0x6c, 0x25, 0x56,
                           0xc4, 0x8a, 0x0d, 0x13, 0x9b };
    
    int8_t gen_keys_result = 0xFF;
    int8_t sign_result = 0xFF;
    int8_t verify_result = 0xFF;
    
    void testECCSigning(uint8_t* signS1Buf, uint8_t* signS2Buf)
    {
      // Declaration of a remote client's public keys.
      // Assume they have already been generated.
    //  extern uint8_t remotePublicKeyX[32];
    //  extern uint8_t remotePublicKeyY[32];
    
      // Fill localPrivateKey with 256 bits from a random number generator.
      //myRandomNumberGenerator(localPrivateKey, 32);
    
      // Initialize ECC ROM driver
      ECCROMCC26XX_init();
    
      // Initialize this client's ECCROMCC26XX parameters.
      ECCROMCC26XX_Params_init(&params);
    
      params.malloc = (uint8_t *(*)(uint16_t)) &ICall_malloc;
      params.free = (void (*)(uint8_t *))&ICall_free;
    
      sendPrintString("private key:");
      sendPrintBytes(localPrivateKey, 32);
    
      // Generate public keys
      gen_keys_result = ECCROMCC26XX_genKeys(localPrivateKey,
                                             localPublicKeyX,
                                             localPublicKeyY,
                                             &params);
      if (gen_keys_result == ECCROMCC26XX_STATUS_SUCCESS) {
          sendPrintString("Function: ECCROMCC26XX_genKeys succeeded");
          sendPrintBytes(localPublicKeyX, 32);
          sendPrintBytes(localPublicKeyY, 32);
      } else {
          sendPrintString("Function: ECCROMCC26XX_genKeys failed");
          sendPrintBytes(&gen_keys_result,1);
      }
    
    //  // Generate shared secret.
    //  // Note: given your local Public Keys, the remote device can generate the
    //  // same shared secret using its local private key.
    //  ECCROMCC26XX_genDHKey(localPrivateKey, remotePublicKeyX,
    //                        remotePublicKeyY, sharedSecretKeyX,
    //                        sharedSecretKeyY, &params);
    
      // Generate signature for hashed message
      // Given the local private key and hash, the remote device can generate 64
      // byte signature split into two 32 byte buffers
    
      // Fill with SHA256 hashed message
    //  mySha2HashGenerator(hash);
    
        sign_result = ECCROMCC26XX_signHash(localPrivateKey,
                                            hash_1,
                                            32,
                                            sign1,
                                            sign2,
                                            &params);
    
        if (sign_result == ECCROMCC26XX_STATUS_SUCCESS) {
            sendPrintString("Function: ECCROMCC26XX_signHash succeeded");
    	 sendPrintBytes(sign1, 32);
    	 sendPrintBytes(sign2, 32);
        } else {
            sendPrintString("Function: ECCROMCC26XX_signHash failed");
            sendPrintBytes(&sign_result,1);
        }
    
      // Verify signature for hashed message
      // Given the local public keys, hash, and generated signature the remote
      // device can verify the signature generated using the local private keys
    
        // Enable the following line to introduce an error and fail the verification
        //sign2[7] += 10;
    
        verify_result = ECCROMCC26XX_verifyHash(localPublicKeyX,
                                                localPublicKeyY,
                                                sign1,
                                                sign2,
                                                hash_1,
                                                32,
                                                &params);
    
        if (verify_result == ECCROMCC26XX_STATUS_SUCCESS) {
            sendPrintString("Function: ECCROMCC26XX_verifyHash succeeded");
        } else {
            sendPrintString("Function: ECCROMCC26XX_verifyHash failed");
            sendPrintBytes(&verify_result,1);
        }
    }
    
    
    /* result of NIST data signature outputs
    BLE [47]:Function: ECCROMCC26XX_signHash succeeded
    BLE [48] l=32: D6 B6 15 96 65 77 63 9E 47 5B E8 95 A7 93 47 91 34 83 E4 0B 45 FA 86 33 99 5C 31 FC 8A 7A 88 E8
    BLE [48] l=32: 14 88 C7 71 5A CE AA A2 DA F6 5D 06 B4 51 85 0C D7 FB E3 36 C7 2B B8 6A 3A 47 9D 17 75 58 9D 30
    
    BLE [62]:Function: ECCROMCC26XX_verifyHash succeeded
    */
    

    Tony

    Here's the NIST set:

     * // This vector is taken from the NIST ST toolkit examples from ECDSA_Prime.pdf
     * uint8_t theirPublicKeyingMaterial[64] =  {0x19, 0x7A, 0xBC, 0x89, 0x08, 0xCD, 0x01, 0x82,
     *                                           0xA3, 0xA2, 0x9E, 0x1E, 0xAD, 0xA0, 0xB3, 0x62,
     *                                           0x1C, 0xBA, 0x98, 0x47, 0x73, 0x8C, 0xDC, 0xF1,
     *                                           0xD3, 0xBA, 0x94, 0xFE, 0xFD, 0x8A, 0xE0, 0xB7,
     *                                           0x09, 0x5E, 0xCC, 0x06, 0xC6, 0xBB, 0x63, 0xB5,
     *                                           0x61, 0x9E, 0x52, 0x43, 0xAE, 0xC7, 0xAD, 0x63,
     *                                           0x90, 0x72, 0x28, 0x19, 0xE4, 0x26, 0xB2, 0x4B,
     *                                           0x7A, 0xBF, 0x9D, 0x95, 0x47, 0xF7, 0x03, 0x36};
     * uint8_t messageHashSHA256[32] =          {0xC4, 0xA8, 0xC8, 0x99, 0x28, 0xCF, 0x80, 0xB6,
     *                                           0xE4, 0x42, 0xD5, 0xBD, 0x28, 0x4D, 0xE3, 0xFD,
     *                                           0x3A, 0x13, 0xD8, 0x65, 0x0C, 0x41, 0x1C, 0x21,
     *                                           0x48, 0x95, 0x79, 0x2A, 0xA1, 0x41, 0x1A, 0xA4};
     * uint8_t r[32] =                          {0x4F, 0x10, 0x46, 0xCA, 0x9A, 0xB6, 0x25, 0x73,
     *                                           0xF5, 0x3E, 0x0B, 0x1F, 0x6F, 0x31, 0x4C, 0xE4,
     *                                           0x81, 0x0F, 0x50, 0xB1, 0xF3, 0xD1, 0x65, 0xFF,
     *                                           0x65, 0x41, 0x7F, 0xD0, 0x76, 0xF5, 0x42, 0x2B};
     * uint8_t s[32] =                          {0xF1, 0xFA, 0x63, 0x6B, 0xDB, 0x9B, 0x32, 0x4B,
     *                                           0x2C, 0x26, 0x9D, 0xE6, 0x6F, 0x88, 0xC1, 0x98,
     *                                           0x81, 0x2A, 0x50, 0x89, 0x3A, 0x99, 0x3A, 0x3E,
     *                                           0xCD, 0x92, 0x63, 0x2D, 0x12, 0xC2, 0x42, 0xDC};

    This is the result running this code with the NIST data set in my platform, it doesn't match r[32] & s[32]

    /* result of NIST data signature outputs
    BLE [47]:Function: ECCROMCC26XX_signHash succeeded
    BLE [48] l=32: D6 B6 15 96 65 77 63 9E 47 5B E8 95 A7 93 47 91 34 83 E4 0B 45 FA 86 33 99 5C 31 FC 8A 7A 88 E8
    BLE [48] l=32: 14 88 C7 71 5A CE AA A2 DA F6 5D 06 B4 51 85 0C D7 FB E3 36 C7 2B B8 6A 3A 47 9D 17 75 58 9D 30

    BLE [62]:Function: ECCROMCC26XX_verifyHash succeeded
    */

  • Luis,

    I'm happy to let you know that my initial thinking of requiring the bit-exactness of the signature generation is flawed.

    ECDSA signature generation can be non-deterministic with an internal random number therefore different valid signatures can be generated. The key thing for me then is to verify the signature with the signer's root public key.

    After some experimentation, I was able to use the ECCROMCC26XX_verifyHash() to verify the message and the signature with the signer's public key. FYI, I had to byte swap the hash_1 and the signatures to get a good verification status.

    Thanks very much for your help.

    Tony