/**
******************************************************************************
* @file ecc.h
* @author MCD Application Team
* @version V2.1
* @date 22-June-2012
* @brief Provides Elliptic Curve Cryptography (ECC) primitives
******************************************************************************
* @attention
*
*
© COPYRIGHT 2012 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/**
* \page Tutorial_ECC ECC Tutorial
*
* This library supports ECC functions for:
* - ECDSA signature verification, Public Key Verification, Scalar Multiplication
* - ECDSA signature generation and ECC Key generation
*
* Unlike other functions in the library ECC objects must be initialized and freed, and to set/get their values
* the user should use special functions.
*
* The first thing to do before starting en ECC operation is to initialize a \ref EC_stt structure containing
* the parameters of the particular ECC curve that the user want to use. This is done through the function
* \ref ECCinitEC and at the end of the ECC operation it can be freed by \ref ECCfreeEC .
*
* After this initial call the user might want to initialize other objects for the functions he will call.
* For example initializing a :
* - Private key (\ref ECCprivKey_stt) with \ref ECCinitPrivKey, settings its value through
* \ref ECCsetPrivKeyValue and at the end of the operation, freeing it with \ref ECCfreePrivKey
* - EC point (\ref ECpoint_stt), which is also a public key, is done by \ref ECCinitPoint, its coordinate
* can be set and get through \ref ECCsetPointCoordinate and \ref ECCgetPointCoordinate and it will be freed
* through \ref ECCfreePoint
* - ECDSA signature (\ref ECDSAsignature_stt) must be initialized by \ref ECDSAinitSign the two signature
* values can be set by \ref ECDSAsetSignature and get by \ref ECDSAgetSignature. At the end it should be
* freed through \ref ECDSAfreeSign
*
* Please note that the functions \ref ECCkeyGen and \ref ECDSAsign, require an initialized random engine structure.
*
* Scalar multiplication is the ECC operation that it is used in ECDSA and in ECDH. It is also used to
* generate a public key.
* A simple usage of the ECC API for scalar multiplication to generate a public key from a known private key is shown below:
*
* \code
* #include
* #include "crypto.h"
* int main()
* {
* const uint8_t ecc_160_a[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFC};
* const uint8_t ecc_160_b[]={0x1C,0x97,0xBE,0xFC,0x54,0xBD,0x7A,0x8B,0x65,0xAC,0xF8,0x9F,0x81,0xD4,0xD4,0xAD,0xC5,0x65,0xFA,0x45};
* const uint8_t ecc_160_p[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF};
* const uint8_t ecc_160_n[]={0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF4,0xC8,0xF9,0x27,0xAE,0xD3,0xCA,0x75,0x22,0x57};
* const uint8_t ecc_160_xG[]={0x4A,0x96,0xB5,0x68,0x8E,0xF5,0x73,0x28,0x46,0x64,0x69,0x89,0x68,0xC3,0x8B,0xB9,0x13,0xCB,0xFC,0x82};
* const uint8_t ecc_160_yG[]={0x23,0xA6,0x28,0x55,0x31,0x68,0x94,0x7D,0x59,0xDC,0xC9,0x12,0x04,0x23,0x51,0x37,0x7A,0xC5,0xFB,0x32};
* const uint8_t ecc_160_privkey[]={0xAA,0x37,0x4F,0xFC,0x3C,0xE1,0x44,0xE6,0xB0,0x73,0x30,0x79,0x72,0xCB,0x6D,0x57,0xB2,0xA4,0xE9,0x82};
*
* // Buffer to keep the returned public key X coordinate
* uint8_t pubKeyX[160/8];
* // Buffer to keep the returned public key Y coordinate
* uint8_t pubKeyY[160/8];
* //integer that will keep the retuned size of the public key X coordinate
* int32_t Xsize;
* //integer that will keep the retuned size of the public key Y coordinate
* int32_t Ysize;
* // Structure that will keep the Elliptic Curve parameters (those values above)
* EC_stt ECparams;
* // These are the Elliptic Curve point objects. In ECC public key ARE just elliptic curve points.
* ECpoint_stt *G = NULL, *PubKey = NULL;
* // This will keep the scalar used in the scalar multiplication
* ECCprivKey_stt *privkey = NULL;
* int32_t retval;
* membuf_stt mb;
* uint8_t preallocated_buffer[4096];
*
* //Set up the membuf_stt structure to a preallocated (on stack) buffer of 4kB
* mb.mSize = sizeof(preallocated_buffer);
* mb.mUsed = 0;
* mb.pmBuf = preallocated_buffer;
*
* // Initialize the EC_stt structure with the known values. We also initialize to NULL and zero the unknown parameter
* ECparams.mAsize = sizeof(ecc_160_a);
* ECparams.pmA = ecc_160_a;
* ECparams.mPsize = sizeof(ecc_160_p);
* ECparams.pmP = ecc_160_p;
* ECparams.pmN = ecc_160_n;
* ECparams.mNsize = sizeof(ecc_160_n);
* ECparams.pmB = NULL;
* ECparams.mBsize = 0;
* ECparams.pmGx = ecc_160_xG;
* ECparams.mGxsize = sizeof(ecc_160_xG);
* ECparams.pmGy = ecc_160_yG;
* ECparams.mGysize = sizeof(ecc_160_yG);
*
* // Call the Elliptic Curve initialization function
* retval = ECCinitEC(&ECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitEC returned %d\n", retval);
* return(-1);
* }
* //Initialize the point that will contain the generator point
* retval = ECCinitPoint(&G, &ECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitPoint returned %d\n", retval);
* return(-1);
* }
*
* //Set the coordinates of the generator point inside G
* retval = ECCsetPointGenerator(G, &ECparams);
* if (retval != 0)
* {
* printf("Error! ECCsetPointGenerator returned %d\n", retval);
* return(-1);
* }
*
* // Init the point the will keep the result of the scalar multiplication
* retval = ECCinitPoint(&PubKey, &ECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitPoint returned %d\n", retval);
* return(-1);
* }
*
* // Initialize the private key object
* retval = ECCinitPrivKey(&privkey, &ECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitPrivKey returned %d\n", retval);
* return(-1);
* }
* //Set the private key object
* retval = ECCsetPrivKeyValue(privkey, ecc_160_privkey, sizeof(ecc_160_privkey));
* if (retval != 0)
* {
* printf("Error! ECCsetPrivKeyValue returned %d\n", retval);
* return(-1);
* }
*
* // All ECCscalarMul parameters are initalized and set, proceed.
* retval = ECCscalarMul(G, privkey, PubKey, &ECparams, &mb);
* if (retval != 0 )
* {
* printf("ECCscalarMul returned %d\n",retval);
* return(-1);
* }
* // Now PubKey contains the result point, we can get its coordinates through
* ECCgetPointCoordinate(PubKey, E_ECC_POINT_COORDINATE_X, pubKeyX, &Xsize);
* ECCgetPointCoordinate(PubKey, E_ECC_POINT_COORDINATE_Y, pubKeyY, &Ysize);
*
* // Finally we free everything we initialized
* ECCfreePrivKey(&privkey, &mb);
* ECCfreePoint(&G, &mb);
* ECCfreePoint(&PubKey, &mb);
* ECCfreeEC(&ECparams, &mb);
* }
* \endcode
*
* The following example will generate a key pair (both private and public key) and will use the private
* key to generate a signature for an hash digest. It will export it and reimport it and verify the signature
* with the public key.
*
* This example will assume to have an already initialized EC_stt and RNGstate_stt.
*
* \code
* int32_t ECCkeygen_and_ECDSA_tests(EC_stt * pECparams, RNGstate_stt * pRNGstate)
* {
* // SHA256("abc")
* uint8_t digest[CRL_SHA256_SIZE] = {0xba,0x78,0x16,0xbf,0x8f,0x01,0xcf,0xea,0x41,0x41,0x40,0xde,0x5d,0xae,
* 0x22,0x23,0xb0,0x03,0x61,0xa3,0x96,0x17,0x7a,0x9c,0xb4,0x10,0xff,0x61,
* 0xf2,0x00,0x15,0xad};
* // Structure that will contain the public key
* ECpoint_stt *PubKey = NULL;
* // Structure that will contain the ECDSA signature
* ECDSAsignature_stt *sign = NULL;
* // Structure context used to call the ECDSAverify
* ECDSAverifyCtx_stt verctx;
* // Private Key Structure
* ECCprivKey_stt *privKey = NULL;
* // Structure context used to call the ECDSAsign
* ECDSAsignCtx_stt signCtx;
* // Used to check the returned values
* int32_t retval;
* //pointers that will keep the byte arrays of the signature object
* uint8_t *signR = NULL, *signS = NULL;
* int32_t signRsize, signSsize;
*
* membuf_stt mb;
* uint8_t preallocated_buffer[4096];
*
* //Set up the membuf_stt structure to a preallocated (on stack) buffer of 4kB
* mb.mSize = sizeof(preallocated_buffer);
* mb.mUsed = 0;
* mb.pmBuf = preallocated_buffer;
*
* //Init PubKey object
* retval = ECCinitPoint(&PubKey, pECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitPoint returned %d\n", retval);
* goto err;
* }
* //Init Privkey object
* retval = ECCinitPrivKey(&privKey, pECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCinitPrivKey returned %d\n", retval);
* goto err;
* }
* //Call the Key Generation Function
* retval = ECCkeyGen(privKey, PubKey, pRNGstate, pECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECCkeyGen returned %d\n",retval);
* }
*
* // We proceed to sign the digest of "message"
* // First initialize the signature that will be returned
* retval = ECDSAinitSign(&sign,pECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECDSAinitSign returned %d\n",retval);
* }
* //Then fill the structure used to call to ECDSAsign function
* // fill the EC_stt
* signCtx.pmEC = pECparams;
* // Fill the privkey
* signCtx.pmPrivKey = privKey;
* //Fill the random engine state
* signCtx.pmRNG = pRNGstate;
*
* // Call the signature generature function
* retval = ECDSAsign(digest, CRL_SHA256_SIZE, sign, &signCtx, &mb);
* if (retval != 0)
* {
* printf("Error! ECDSAsign returned %d\n",retval);
* }
* //The signature now it's inside object sign, let's export it to byte arrays
* //First, allocate the needed size, which is the size of the curve's order (N)
* signR = malloc (pECparams->mNsize);
* signS = malloc (pECparams->mNsize);
* if (signR == NULL || signS ==NULL ) { ... ERROR... }
*
* // Now export the signature
* retval = ECDSAgetSignature(sign,E_ECDSA_SIGNATURE_R_VALUE, signR, &signRsize);
* retval |= ECDSAgetSignature(sign,E_ECDSA_SIGNATURE_S_VALUE, signS, &signSsize);
* if (retval != 0) { ... ERROR... }
*
* // Free the signature structure, reinit and reimport signature, this is just for testing...
* ECDSAfreeSign(&sign, &mb);
*
* retval = ECDSAinitSign(&sign, pECparams, &mb);
* if (retval != 0)
* {
* printf("Error! ECDSAinitSign returned %d\n",retval);
* }
* retval = ECDSAsetSignature(sign,E_ECDSA_SIGNATURE_R_VALUE, signR, signRsize);
* retval |= ECDSAsetSignature(sign,E_ECDSA_SIGNATURE_S_VALUE, signS, signSsize);
* if (retval != 0) { ... ERROR... }
*
* // We now have the signature of the message, we try to verify it
* // First set the parameters for the verification structure
* verctx.pmEC = pECparams;
* verctx.pmPubKey = PubKey;
*
* // then we can call the verification function
* retval = ECDSAverify(digest, CRL_SHA256_SIZE, sign, &verctx, &mb);
*
* if (retval == SIGNATURE_VALID)
* {
* printf("Signature VALID\n");
* }
* else
* {
* printf("Error! ECDSAverify returned %d\n",retval);
* }
*
* // Before returing clean the memory by freeing the signature and the public key
* ECDSAfreeSign(sign, &mb);
* ECCfreePoint(PubKey, &mb);
* ECCfreePrivKey(privKey, &mb);
*
* return(retval);
* }
* \endcode
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __CRL_ECC_H__
#define __CRL_ECC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "../MATH/math.h"
/** @addtogroup ECC
* @{
*/
/**
* @brief Structure continaing the BigNum_stt that describes the parameters of an Elliptic Curve and its generator
*/
typedef struct
{
BigNum_stt *pmA; /*!< Parameter a of the curve equation. */
BigNum_stt *pmB; /*!< Parameter b of the curve equation. */
BigNum_stt *pmP; /*!< Modulus p. */
BigNum_stt *pmN; /*!< Order of the curve n. */
BigNum_stt *pmGx; /*!< Coordinate pmX of curve's generator */
BigNum_stt *pmGy; /*!< Coordinate pmY of curve's generator*/
} intEC_stt;
/**
* @brief Structure that keeps the Elliptic Curve Parameter
*/
typedef struct
{
const uint8_t *pmA; /*!< pointer to paramter "a" */
int32_t mAsize; /*!< size of paramter "a" */
const uint8_t *pmB; /*!< pointer to paramter "b" */
int32_t mBsize; /*!< size of paramter "b" */
const uint8_t *pmP; /*!