ippsECCPSignDSA function call fail !

ippsECCPSignDSA function call fail !

Floating point exception (core dumped) when calling ippsECCPSignDSA. 

It may bugs in the function.

Sample code:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#include "ippcp.h"

#define MAX_RETRY 20
#define RAND_SEED_BYTES 32
#define MAX_RAND_BITS 512
#define BYTES2U32LEN(n) ((n + sizeof(Ipp32u) - 1) / sizeof(Ipp32u))

void data_dump(char *prompt, unsigned char *data, int len)
{
   int i;
   int prev;
   int curr; 

   fprintf(stderr, "[%s] [length = %d]\n", prompt, len);
   prev = curr = 0;
   for (i = 0; i < len; i++) {
      if (i == (prev + 16)) { 
         i = prev;
         curr = prev + 16;
         fprintf(stderr, "    |    ");
         for (; i < curr; i++)
            if (isprint(data[i]))
               fprintf(stderr, "%c", data[i]);
            else
               fprintf(stderr, " ");
         fprintf(stderr, "\n");
         prev = curr;
      }
      fprintf(stderr, "%02x ", data[i]); 
   }
 
   if (i != curr) {
      curr = i;
      for (; i < (prev + 16); i++)
         fprintf(stderr, "   ");
      fprintf(stderr, "    |    ");
      for (i = prev ; i < curr; i++) {
         if (isprint(data[i]))
            fprintf(stderr, "%c", data[i]);
         else
            fprintf(stderr, " ");
      }
   }
   fprintf(stderr, "\n");
   
   fflush(stderr);
}

static void RAND_bytes(Ipp8u *randData, int nBytes)
{
    int i, round;
    int *pRnd = (int *)randData;
    
    round = (nBytes + sizeof(int) - 1) / sizeof(int);
    
    for(i = 0; i < round; i++){
        *pRnd = rand();
        pRnd++;
    }
#ifdef DUMP
    data_dump("Random", randData, nBytes);
#endif    
    return;
}

static IppsPRNGState* newRandCtx()
{
    IppsPRNGState *pRndCtx = NULL;
    int rndCtxSize, bnCtxSize;
    IppStatus ret;
    IppsBigNumState* bnTmp;
    Ipp8u tmpSeed[RAND_SEED_BYTES] = {0};    
    
    ippsPRNGGetSize(&rndCtxSize);
    if(rndCtxSize & 0x07)
        rndCtxSize = ((rndCtxSize >> 3) + 1) << 3;

    pRndCtx = (IppsPRNGState*)malloc(rndCtxSize);
    if(!pRndCtx){
        return NULL;
    }

    ret = ippsPRNGInit(MAX_RAND_BITS, pRndCtx);
    if(ippStsNoErr != ret){
        fprintf(stderr, "ippsPRNGInit fial: %s\n", ippcpGetStatusString(ret));
        free(pRndCtx);
        pRndCtx = NULL;
        return NULL;
    }
    
    ippsBigNumGetSize(BYTES2U32LEN(RAND_SEED_BYTES), &bnCtxSize);
    bnTmp = (IppsBigNumState*) malloc(bnCtxSize);
    if(bnTmp){
        RAND_bytes(tmpSeed, RAND_SEED_BYTES);
        ippsBigNumInit(BYTES2U32LEN(RAND_SEED_BYTES), bnTmp);
        ippsSetOctString_BN(tmpSeed, RAND_SEED_BYTES, bnTmp);
        ippsPRNGSetSeed(bnTmp, pRndCtx);
        free(bnTmp);
        return pRndCtx;
    }else{
        free(pRndCtx);
        return NULL;
    }
}

static int genECCKey(IppsBigNumState* priKey, IppsECCPPointState* pubKey, const IppsECCPState* pCtx)
{
    IppStatus ret = -1;
    IppsPRNGState *pRndCtx;
    
    int i;
    
    pRndCtx = newRandCtx();
    if(!pRndCtx)
        return -1;
    
    for(i = 0; i < MAX_RETRY; i++){
        ret = ippsECCPGenKeyPair(priKey, pubKey, pCtx, ippsPRNGen, pRndCtx);
        if(ippStsNoErr == ret)
                break;
    }

    free(pRndCtx);
    return ret;
}

int ec_sign_verify_test()
{
    int prilen, publen;
    int bnSize, bnCtxSize;
    int ret = -1, nSize;
    IppECResult nResult;

    unsigned char digst[32];
    
    IppsBigNumState *pPrivate = NULL, *pDigst = NULL, *pSignR = NULL, *pSignS = NULL;
    IppsECCPPointState* pPublic = NULL;
    IppsECCPState* pCtx;
    
    //init ECC CTX
    ippsECCPGetSizeStd256r1(&nSize);
    pCtx = (IppsECCPState*)malloc(nSize);
    if(pCtx){
        ippsECCPInitStd256r1(pCtx);
        ippsECCPSetStd256r1(pCtx);
        ippsECCPBindGxyTblStd256r1(pCtx);
    }else
        goto testEnd;

    //generate public & private key
    bnSize = BYTES2U32LEN(32);
    ippsBigNumGetSize(bnSize, &bnCtxSize);
    prilen = bnCtxSize;
    ippsECCPPointGetSize(256, &publen);    

    pPrivate = (IppsBigNumState*)malloc(prilen);
    pPublic = (IppsECCPPointState*)malloc(publen);
    if(!pPrivate || !pPublic)
        goto testEnd;
    ippsBigNumInit(bnSize, pPrivate);
    ippsECCPPointInit(256, pPublic);
    
    fprintf(stderr, "Calling genECCKey to generate ECC key pair ...\n");
    ret = genECCKey(pPrivate, pPublic, pCtx);
    if(ippStsNoErr != ret)
        goto testEnd;
    fprintf(stderr, "Generate ECC key pair suceed !\n");
#ifdef DUMP
    data_dump("Private Key", pPrivate, prilen);
    data_dump("Public Key", pPublic, publen);
#endif    
    //get random digest
    pDigst = (IppsBigNumState*)malloc(bnCtxSize);
    ippsBigNumInit(bnSize, pDigst);
    RAND_bytes(digst, 32);
    ippsSetOctString_BN(digst, 32, pDigst);
#ifdef DUMP
    data_dump("Digest", pDigst, bnCtxSize);
#endif

    //do signature
    pSignR = (IppsBigNumState*)malloc(bnCtxSize);
    pSignS = (IppsBigNumState*)malloc(bnCtxSize);
    if(!pSignR || !pSignS)
            goto testEnd;
    ippsBigNumInit(bnSize, pSignR);
    ippsBigNumInit(bnSize, pSignS);
    fprintf(stderr, "Calling ippsECCPSignDSA to do signature ...\n");
    ret = ippsECCPSignDSA(pDigst, pPrivate, pSignR, pSignS, pCtx);
    fprintf(stderr, "ippsECCPSignDSA return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    if(ret)
        goto testEnd;
#ifdef DUMP
    data_dump("SignR", pSignR, bnCtxSize);
    data_dump("SignS", pSignS, bnCtxSize);
#endif
    //do verify 
    ret = ippsECCPSetKeyPair(NULL, pPublic, ippTrue, pCtx);
    fprintf(stderr, "ippsECCPSetKeyPair return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    if(ret)
        goto testEnd;
    
    ret = ippsECCPVerifyDSA(pDigst, pSignR, pSignS, &nResult, pCtx);
    fprintf(stderr, "ippsECCPSignDSA return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    fprintf(stderr, "ippsECCPSignDSA result: %d, It means: %s\n", nResult, ippsECCGetResultString(nResult));
    
testEnd:
    if(pCtx)
        free(pCtx);
    if(pPrivate)
        free(pPrivate);
    if(pPublic)
        free(pPublic);
    if(pDigst)
        free(pDigst);
    if(pSignR)
        free(pSignR);
    if(pSignS)
        free(pSignS);
        
    return ret;
}

int main()
{
    srand(time(NULL));

    ec_sign_verify_test();
    
    return 0;
}

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

The problem resolved.

before calling  ippsECCPSignDSA

it must set an Ephemeral EC key pair to the ECC context.

The keys can be generated and set up by the functions ECCPGenKeyPair and ECCPSetKeyPair with only
requirement that the key regPrivKey be different from the key ephPrivKey.

thanks for sharing this. kinrong.

hi kinrong,

the right sequence of calls is described in the manual, the corrected code (that works fine) is below.

Calling genECCKey to generate ECC key pair ...

Generate ECC key pair suceed !

Calling ippsECCPSignDSA to do signature ...

ippsECCPSignDSA return: 0, It means: Validation pass successfully

ippsECCPSetKeyPair return: 0, It means: Validation pass successfully

ippsECCPSignDSA return: 0, It means: Validation pass successfully

ippsECCPSignDSA result: 0, It means: Validation pass successfully

Press any key to continue . . .

 

The root of the problem – incorrect sequence of IPP calls

regards, Igor

 

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include "ippcp.h"

#define MAX_RETRY 20
#define RAND_SEED_BYTES 32
#define MAX_RAND_BITS 512
#define BYTES2U32LEN(n) ((n + sizeof(Ipp32u) - 1) / sizeof(Ipp32u))

void data_dump(char *prompt, unsigned char *data, int len)
{
   int i;
   int prev;
   int curr; 
   fprintf(stderr, "[%s] [length = %d]\n", prompt, len);
   prev = curr = 0;
   for (i = 0; i < len; i++) {
      if (i == (prev + 16)) { 
         i = prev;
         curr = prev + 16;
         fprintf(stderr, "    |    ");
         for (; i < curr; i++)
            if (isprint(data[i]))
               fprintf(stderr, "%c", data[i]);
            else
               fprintf(stderr, " ");
         fprintf(stderr, "\n");
         prev = curr;
      }
      fprintf(stderr, "%02x ", data[i]); 
   }
 
   if (i != curr) {
      curr = i;
      for (; i < (prev + 16); i++)
         fprintf(stderr, "   ");
      fprintf(stderr, "    |    ");
      for (i = prev ; i < curr; i++) {
         if (isprint(data[i]))
            fprintf(stderr, "%c", data[i]);
         else
            fprintf(stderr, " ");
      }
   }
   fprintf(stderr, "\n");
   
   fflush(stderr);
}
static void RAND_bytes(Ipp8u *randData, int nBytes)
{
    int i, round;
    int *pRnd = (int *)randData;
    
    round = (nBytes + sizeof(int) - 1) / sizeof(int);
    
    for(i = 0; i < round; i++){
        *pRnd = rand();
        pRnd++;
    }
#ifdef DUMP
    data_dump("Random", randData, nBytes);
#endif    
    return;
}
static IppsPRNGState* newRandCtx()
{
    IppsPRNGState *pRndCtx = NULL;
    int rndCtxSize, bnCtxSize;
    IppStatus ret;
    IppsBigNumState* bnTmp;
    Ipp8u tmpSeed[RAND_SEED_BYTES] = {0};    
    
    ippsPRNGGetSize(&rndCtxSize);
    if(rndCtxSize & 0x07)
        rndCtxSize = ((rndCtxSize >> 3) + 1) << 3;
    pRndCtx = (IppsPRNGState*)malloc(rndCtxSize);
    if(!pRndCtx){
        return NULL;
    }
    ret = ippsPRNGInit(MAX_RAND_BITS, pRndCtx);
    if(ippStsNoErr != ret){
        fprintf(stderr, "ippsPRNGInit fial: %s\n", ippcpGetStatusString(ret));
        free(pRndCtx);
        pRndCtx = NULL;
        return NULL;
    }
    
    ippsBigNumGetSize(BYTES2U32LEN(RAND_SEED_BYTES), &bnCtxSize);
    bnTmp = (IppsBigNumState*) malloc(bnCtxSize);
    if(bnTmp){
        RAND_bytes(tmpSeed, RAND_SEED_BYTES);
        ippsBigNumInit(BYTES2U32LEN(RAND_SEED_BYTES), bnTmp);
        ippsSetOctString_BN(tmpSeed, RAND_SEED_BYTES, bnTmp);
        ippsPRNGSetSeed(bnTmp, pRndCtx);
        free(bnTmp);
        return pRndCtx;
    }else{
        free(pRndCtx);
        return NULL;
    }
}
static int genECCKey(IppsBigNumState* priKey, IppsECCPPointState* pubKey, const IppsECCPState* pCtx)
{
    IppStatus ret = -1;
    IppsPRNGState *pRndCtx;
    
    int i;
    
    pRndCtx = newRandCtx();
    if(!pRndCtx)
        return -1;
    
    for(i = 0; i < MAX_RETRY; i++){
        ret = ippsECCPGenKeyPair(priKey, pubKey, pCtx, ippsPRNGen, pRndCtx);
        if(ippStsNoErr == ret)
                break;
    }
    free(pRndCtx);
    return ret;
}
int ec_sign_verify_test()
{
    int prilen, publen;
    int bnSize, bnCtxSize;
    int ret = -1, nSize;
    IppECResult nResult;
    unsigned char digst[32];
    
    IppsBigNumState *pPrivate = NULL, *pDigst = NULL, *pSignR = NULL, *pSignS = NULL;
    IppsECCPPointState* pPublic = NULL;
    IppsECCPState* pCtx;

    /* gres */IppsBigNumState *pPrivateE = NULL;
    /* gres */IppsECCPPointState* pPublicE = NULL;
    
    //init ECC CTX
    ippsECCPGetSizeStd256r1(&nSize);
    pCtx = (IppsECCPState*)malloc(nSize);
    if(pCtx){
        ippsECCPInitStd256r1(pCtx);
        ippsECCPSetStd256r1(pCtx);
        ippsECCPBindGxyTblStd256r1(pCtx);
    }else
        goto testEnd;
    //generate public & private key
    bnSize = BYTES2U32LEN(32);
    ippsBigNumGetSize(bnSize, &bnCtxSize);
    prilen = bnCtxSize;
    ippsECCPPointGetSize(256, &publen);    
    pPrivate = (IppsBigNumState*)malloc(prilen);
    pPublic = (IppsECCPPointState*)malloc(publen);
    /* gres */ pPrivateE = (IppsBigNumState*)malloc(prilen);
    /* gres */ pPublicE = (IppsECCPPointState*)malloc(publen);
    if(!pPrivate || !pPublic /* gres */ || !pPrivateE || !pPublicE)
        goto testEnd;
    ippsBigNumInit(bnSize, pPrivate);
    ippsECCPPointInit(256, pPublic);
    ippsBigNumInit(bnSize, pPrivateE);
    ippsECCPPointInit(256, pPublicE);
    
    fprintf(stderr, "Calling genECCKey to generate ECC key pair ...\n");
    ret = genECCKey(pPrivate, pPublic, pCtx);
    /* gres: ephemeral keys */ genECCKey(pPrivateE, pPublicE, pCtx);
    if(ippStsNoErr != ret)
        goto testEnd;
    fprintf(stderr, "Generate ECC key pair suceed !\n");
#ifdef DUMP
    data_dump("Private Key", pPrivate, prilen);
    data_dump("Public Key", pPublic, publen);
#endif    
    //get random digest
    pDigst = (IppsBigNumState*)malloc(bnCtxSize);
    ippsBigNumInit(bnSize, pDigst);
    RAND_bytes(digst, 32);
    ippsSetOctString_BN(digst, 32, pDigst);
#ifdef DUMP
    data_dump("Digest", pDigst, bnCtxSize);
#endif
    //do signature
    pSignR = (IppsBigNumState*)malloc(bnCtxSize);
    pSignS = (IppsBigNumState*)malloc(bnCtxSize);
    if(!pSignR || !pSignS)
            goto testEnd;
    ippsBigNumInit(bnSize, pSignR);
    ippsBigNumInit(bnSize, pSignS);
    fprintf(stderr, "Calling ippsECCPSignDSA to do signature ...\n");
    /* gres set ephemeral keys: */ ippsECCPSetKeyPair(pPrivateE, pPublicE, ippFalse, pCtx);
    ret = ippsECCPSignDSA(pDigst, pPrivate, pSignR, pSignS, pCtx);
    fprintf(stderr, "ippsECCPSignDSA return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    if(ret)
        goto testEnd;
#ifdef DUMP
    data_dump("SignR", pSignR, bnCtxSize);
    data_dump("SignS", pSignS, bnCtxSize);
#endif
    //do verify 
    ret = ippsECCPSetKeyPair(NULL, pPublic, ippTrue, pCtx);
    fprintf(stderr, "ippsECCPSetKeyPair return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    if(ret)
        goto testEnd;
    
    ret = ippsECCPVerifyDSA(pDigst, pSignR, pSignS, &nResult, pCtx);
    fprintf(stderr, "ippsECCPSignDSA return: %d, It means: %s\n", ret, ippsECCGetResultString(ret));
    fprintf(stderr, "ippsECCPSignDSA result: %d, It means: %s\n", nResult, ippsECCGetResultString(nResult));
    
testEnd:
    if(pCtx)
        free(pCtx);
    if(pPrivate)
        free(pPrivate);
    if(pPublic)
        free(pPublic);
    if(pPrivateE) /* gres */
        free(pPrivateE);
    if(pPublicE)  /* gres */
        free(pPublicE);
    if(pDigst)
        free(pDigst);
    if(pSignR)
        free(pSignR);
    if(pSignS)
        free(pSignS);
        
    return ret;
}
int main()
{
    srand(time(NULL));
    ec_sign_verify_test();
    
    return 0;
}

 

Leave a Comment

Please sign in to add a comment. Not a member? Join today