intel / ipp-crypto

Apache License 2.0
317 stars 84 forks source link

Issue with SM2 signature demo implementation #64

Closed YWRtaW4 closed 10 months ago

YWRtaW4 commented 10 months ago

Hello,

I am relatively new to the ipp-crypto library and I'm currently trying to work on a demo related to SM2. My goal is to implement SM2 signature generation, but I am encountering difficulties during the initialization and point operations.

To provide some context, I have stored the x and y coordinates of the SM2 generator point in pXbuf and pYbuf respectively. Then, I assigned these values to pX and pY by ippsGFpElementInit. Next, I used the ippsGFpECPointInit function to set the value of point pP. However, when I try to extract and print the coordinates of pP using ippsGFpECGetPointOctString, the values I get are not as expected. Also, I test by ippsECCPCheckPoint and the status indicates that pP is not a valid ECC point.

For more infomation, my demo code are as follows, some initialization operations are executed and then point pP is set by pX and pY, then pP is extracted to oct strings and printed:

#include <stdio.h>
#include <stdlib.h>
#include "ippcp.h"
#include "ippcpdefs.h"
#include "examples_common.h"

#define BIGNUM(a, b, c, d, e, f, g, h) {h, g, f, e, d, c, b, a}

int main()
{
    int i;
    unsigned int tmp;
    int size;

    Ipp8u pPstr[64];
    Ipp8u pQstr[64];

    /* SM2 modulus */
    Ipp32u sm2_p[8] = BIGNUM(0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF);
    /* x-coordinate of SM2 generator */
    Ipp32u pXbuf[8] = BIGNUM(0x32c4ae2c, 0x1f198119, 0x5f990446, 0x6a39c994, 0x8fe30bbf, 0xf2660be1, 0x715a4589, 0x334c74c7);
    /* y-coordinate of SM2 generator */
    Ipp32u pYbuf[8] = BIGNUM(0xbc3736a2, 0xf4f6779c, 0x59bdcee3, 0x6b692153, 0xd0a9877c, 0xc62a4740, 0x02df32e5, 0x2139f0a0);

    IppsGFpECState *pEC;
    IppsGFpState *pGFp;
    IppsGFpElement *pX;
    IppsGFpElement *pY;
    IppsGFpECPoint *pP;
    IppStatus status;

    const IppsGFpMethod *pGFpMethod = ippsGFpMethod_p256sm2();
    IppsBigNumState *pSM2modulus = (IppsBigNumState *)malloc(sizeof(Ipp32u) * 8);
    status = ippsBigNumInit(8, pSM2modulus);
    if (!checkStatus("ippsBigNumInit", ippStsNoErr, status))
        return 1;

    status = ippsSet_BN(IppsBigNumPOS, 8, sm2_p, pSM2modulus);
    if (!checkStatus("ippsSet_BN", ippStsNoErr, status))
        return 1;

    status = ippsGFpGetSize(256, &size);
    if (!checkStatus("ippsGFpGetSize", ippStsNoErr, status))
        return 1;
    pGFp = (IppsGFpState *)malloc(sizeof(Ipp8u) * size);

    status = ippsGFpInitFixed(256, pGFpMethod, pGFp);
    if (!checkStatus("ippsGFpInitFixed", ippStsNoErr, status))
        return 1;

    status = ippsGFpECGetSize(pGFp, &size);
    if (!checkStatus("ippsGFpECGetSize", ippStsNoErr, status))
        return 1;
    pEC = (IppsGFpECState *)malloc(size * sizeof(ipp32u));
    status = ippsGFpECInitStdSM2(pGFp, pEC);
    if (!checkStatus("ippsGFpECInitStdSM2", ippStsNoErr, status))
        return 1;

    // set pX
    pX = (IppsGFpElement *)malloc(8 * sizeof(ipp32u));
    status = ippsGFpElementInit(pXbuf, 8, pX, pGFp);
    if (!checkStatus("ippsGFpElementInit", ippStsNoErr, status))
        return 1;
    // set pY
    pY = (IppsGFpElement *)malloc(8 * sizeof(ipp32u));
    status = ippsGFpElementInit(pYbuf, 8, pY, pGFp);
    if (!checkStatus("ippsGFpElementInit", ippStsNoErr, status))
        return 1;

    status = ippsGFpECPointGetSize(pEC, &size);
    pP = (IppsGFpECPoint *)malloc(size * sizeof(ipp32u));

    // set pP
    status = ippsGFpECPointInit(pX, pY, pP, pEC);
    if (!checkStatus("ippsGFpECPointInit", ippStsNoErr, status))
        return 1;

    IppECResult pResult;
    status = ippsECCPCheckPoint(pP, &pResult, pEC);
    if (!checkStatus("ippsECCPCheckPoint", ippStsNoErr, status))
        return 1;
    printf("%d\n", pResult);

    status = ippsGFpECGetPointOctString(pP, pPstr, 64, pEC);
    if (!checkStatus("ippsGFpECGetPointOctString", ippStsNoErr, status))
        return 1;
    // print P's x-coordinate
    for (i = 31; i >= 0; i--)
    {
        printf("%02x ", pPstr[i]);
    }
    printf("\n");
    // print P's y-coordinate
    for (i = 63; i >= 32; i--)
    {
        printf("%02x ", pPstr[i]);
    }
    printf("\n\n");

    return 0;
}

By executing the codes, the output is

14
f2 39 8b 51 fe 05 05 c2 40 86 7c 83 bf 0b e3 8f 94 c9 39 6a 1a 3f 5a 41 a4 c0 6e ce cc 33 ae a1 
d4 bc 62 9f dc 00 e9 20 14 ad f7 29 7d 87 a9 d0 53 21 69 6b af 02 95 db a4 a9 ec d6 ce d0 69 58 

while I expected it to be

32 c4 ae 2c 1f 19 81 19 5f 99 04 46 6a 39 c9 94 8f e3 0b bf f2 66 0b e1 71 5a 45 89 33 4c 74 c7
bc 37 36 a2 f4 f6 77 9c 59 bd ce e3 6b 69 21 53 d0 a9 87 7c c6 2a 47 40 02 df 32 e5 21 39 f0 a0

I would greatly appreciate it if the developers could review my code and help me identify any issues or mistakes. Additionally, if there are any suggestions or alternative approaches to achieve SM2 signature generation using the ipp-crypto library, I would be grateful for the guidance.

Thank you for your assistance!

ElenaTyuleneva commented 10 months ago

Hi @YWRtaW4, Thanks for your interest in IPP Crypto! We need some time to investigate your findings, we'll write you back when there are any updates.

Elena

opervush commented 10 months ago

Hi @YWRtaW4,

Thanks for reporting an issue. Unfortunately, we couldn't reproduce your scenario, but we took a look at your example and noticed incorrect memory allocation in some places. Some IPP Crypto structures require the calling special "GetSize" method before memory allocation. You call such method, for example, for IppsGFpState type, but don't call for IppsBigNumState and IppsGFpElement types. Could you please try to use ippsBigNumGetSize() and ippsGFpElementGetSize() methods and allocate memory with the correct sizes?

YWRtaW4 commented 10 months ago

Hi @opervush,

Thank you for your response. I appreciate your advice, which has successfully resolved my issue.