Analysis of the open source library of Miracle cryptographic algorithm: mrebrick.c

2021SC@SDUSC Application and practice of software engineering in school of software, Shandong University

1. mrebrick.c structure


The overall structure of mrebrick.c is as follows, which mainly implements ebrick_init(), ebrick_end(),mul_brick() is a few important functions in the miracl open source library. This blog is to read the functions of this function.

   2. Source code  

BOOL ebrick_init(_MIPD_ ebrick *B,big x,big y,big a,big b,big n,int window,int nb)
{ /* Uses Montgomery arithmetic internally              *
   * (x,y) is the fixed base                            *
   * a,b and n are parameters and modulus of the curve  *
   * window is the window size in bits and              *
   * nb is the maximum number of bits in the multiplier */
    int i,j,k,t,bp,len,bptr,is;
    epoint **table;
    epoint *w;

#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif
    if (nb<2 || window<1 || window>nb || mr_mip->ERNUM) return FALSE;

    t=MR_ROUNDUP(nb,window);
    if (t<2) return FALSE;

    MR_IN(115)

#ifndef MR_ALWAYS_BINARY
    if (mr_mip->base != mr_mip->base2)
    {
        mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
        MR_OUT
        return FALSE;
    }
#endif

    B->window=window;
    B->max=nb;
    table=(epoint **)mr_alloc(_MIPP_ (1<<window),sizeof(epoint *));
    if (table==NULL)
    {
        mr_berror(_MIPP_ MR_ERR_OUT_OF_MEMORY);   
        MR_OUT
        return FALSE;
    }
    B->a=mirvar(_MIPP_ 0);
    B->b=mirvar(_MIPP_ 0);
    B->n=mirvar(_MIPP_ 0);
    copy(a,B->a);
    copy(b,B->b);
    copy(n,B->n);

    ecurve_init(_MIPP_ a,b,n,MR_BEST);
    w=epoint_init(_MIPPO_ );
    epoint_set(_MIPP_ x,y,0,w);
    table[0]=epoint_init(_MIPPO_ );
    table[1]=epoint_init(_MIPPO_ );
    epoint_copy(w,table[1]);
    for (j=0;j<t;j++)
        ecurve_double(_MIPP_ w);
    k=1;
    for (i=2;i<(1<<window);i++)
    {
        table[i]=epoint_init(_MIPPO_ );
        if (i==(1<<k))
        {
            k++;
			epoint_norm(_MIPP_ w);
            epoint_copy(w,table[i]);
            
            for (j=0;j<t;j++)
                ecurve_double(_MIPP_ w);
            continue;
        }
        bp=1;
        for (j=0;j<k;j++)
        {
            if (i&bp)
			{
				is=1<<j;
                ecurve_add(_MIPP_ table[is],table[i]);
			}
            bp<<=1;
        }
        epoint_norm(_MIPP_ table[i]);
    }
    epoint_free(w);

/* create the table */

    len=n->len;
    bptr=0;
    B->table=(mr_small *)mr_alloc(_MIPP_ 2*len*(1<<window),sizeof(mr_small));

    for (i=0;i<(1<<window);i++)
    {
        for (j=0;j<len;j++)
        {
            B->table[bptr++]=table[i]->X->w[j];
        }
        for (j=0;j<len;j++)
        {
            B->table[bptr++]=table[i]->Y->w[j];
        }

        epoint_free(table[i]);
    }
        
    mr_free(table);  

    MR_OUT
    return TRUE;
}

void ebrick_end(ebrick *B)
{
    mirkill(B->n);
    mirkill(B->b);
    mirkill(B->a);
    mr_free(B->table);  
}

ebrick_ The main function of init () method is to initialize the GF (p) elliptic curve multiplication and pre calculated Comb method instance.. The internal memory is allocated to 20000 elliptic curve points, and these large numbers will be calculated and stored in advance* B is the ebrick structure pointer to be initialized. Other input data is to improve various attributes of * B. This method uses Montgomery algorithm to initialize * B inside the function. The input data a, B and N determine a curve function y2 = (x3 + ax + b) mod n, X and y are combined into a two-dimensional coordinate point (x,y) on the curve. Window determines the window size in bits and. For larger input data, windows needs more space to store data, and the input data nb limits the maximum bits to be used in the index.

void ebrick_init(ebrick *B,const mr_small* rom,big a,big b,big n,int window,int nb)
{
    B->table=rom;
    B->a=a; /* just pass a pointer */
    B->b=b;
    B->n=n;
    B->window=window;  /* 2^4=16  stored values */
    B->max=nb;
}

ebrick_ The init () method is also overloaded in another form. This method only roughly replaces various attributes required by * B with input data, rather than using Montgomery algorithm to initialize * B.

void ebrick_end(ebrick *B)
{
    mirkill(B->n);
    mirkill(B->b);
    mirkill(B->a);
    mr_free(B->table);  
}

brick_ The main function of the end () method is to release the memory space occupied by the brick structure pointer * B. First, call the mirkill() method. By zeroing the large numbers B - > N, B - > b and B - > A and freeing their memory, you can safely kill the large number. Call Mr again_ The free () method frees the memory space dynamically allocated to B - > table by the calloc() method.

void ebrick_init(ebrick *B,const mr_small* rom,big a,big b,big n,int window,int nb)
{
    B->table=rom;
    B->a=a; /* just pass a pointer */
    B->b=b;
    B->n=n;
    B->window=window;  /* 2^4=16  stored values */
    B->max=nb;
}

#endif

int mul_brick(_MIPD_ ebrick *B,big e,big x,big y)
{
    int i,j,t,d,len,maxsize,promptr;
    epoint *w,*z;
 
#ifdef MR_STATIC
    char mem[MR_ECP_RESERVE(2)];
#else
    char *mem;
#endif
#ifdef MR_OS_THREADS
    miracl *mr_mip=get_mip();
#endif

    if (size(e)<0) mr_berror(_MIPP_ MR_ERR_NEG_POWER);
    t=MR_ROUNDUP(B->max,B->window);
    
    MR_IN(116)

#ifndef MR_ALWAYS_BINARY
    if (mr_mip->base != mr_mip->base2)
    {
        mr_berror(_MIPP_ MR_ERR_NOT_SUPPORTED);
        MR_OUT
        return 0;
    }
#endif

    if (logb2(_MIPP_ e) > B->max)
    {
        mr_berror(_MIPP_ MR_ERR_EXP_TOO_BIG);
        MR_OUT
        return 0;
    }

    ecurve_init(_MIPP_ B->a,B->b,B->n,MR_BEST);
#ifdef MR_STATIC
    memset(mem,0,MR_ECP_RESERVE(2));
#else
    mem=(char *)ecp_memalloc(_MIPP_ 2);
#endif
    w=epoint_init_mem(_MIPP_ mem,0);
    z=epoint_init_mem(_MIPP_ mem,1);

    len=B->n->len;
    maxsize=2*(1<<B->window)*len;

    j=recode(_MIPP_ e,t,B->window,t-1);
    if (j>0)
    {
        promptr=2*j*len;
        init_point_from_rom(w,len,B->table,maxsize,&promptr);
    }
    for (i=t-2;i>=0;i--)
    {
        j=recode(_MIPP_ e,t,B->window,i);
        ecurve_double(_MIPP_ w);
        if (j>0)
        {
            promptr=2*j*len;
            init_point_from_rom(z,len,B->table,maxsize,&promptr);
            ecurve_add(_MIPP_ z,w);
        }
    }

    d=epoint_get(_MIPP_ w,x,y);
#ifndef MR_STATIC
    ecp_memkill(_MIPP_ mem,2);
#else
    memset(mem,0,MR_ECP_RESERVE(2));
#endif
    MR_OUT
    return d;
}

mul_ The main function of the brick () method is to multiply GF (P) elliptic curves using the pre calculated values stored in the ebrick structure. First call   ecurve_init method initializes the internal parameters of the currently active GF (P) elliptic curve: y2 = (x3 + Ax + B) mod p, and then call ECP_ The memalloc method preserves 2 spaces at the elliptic curve point and then calls epoint_. init_ The MEM method initializes the memory of the two elliptic curve points from the pre allocated font field array mem. After that, call init_. point_ from_ The ROM method initializes elliptical curve points W from ROM memory. Next, the recode method is called recursively, encoding the index for the Comb method, and then calling ecurve_. The double method multiplies the w on the active curve by twice, and calls init_ point_ from_ The ROM method initializes the elliptic curve point z from ROM memory, and then calls ecurve_ The add method adds W and Z on the active curve to W. After the end of the loop, call epoint_. The get method obtains the coordinates on the w (x,y), and finally calls ecp_. The memkill method is deleted and set to zero previously by ECP_ Two memory space elliptical curve points allocated by memalloc.

Tags: C Algorithm

Posted on Mon, 29 Nov 2021 15:00:49 -0500 by metazai