Home | History | Annotate | Download | only in smp
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2006-2015 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19  /******************************************************************************
     20   *
     21   *  This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
     22   *
     23   ******************************************************************************/
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include "p_256_ecc_pp.h"
     28 #include "p_256_multprecision.h"
     29 
     30 elliptic_curve_t curve;
     31 elliptic_curve_t curve_p256;
     32 
     33 static void p_256_init_point(Point *q)
     34 {
     35     memset(q, 0, sizeof(Point));
     36 }
     37 
     38 static void p_256_copy_point(Point *q, Point *p)
     39 {
     40     memcpy(q, p, sizeof(Point));
     41 }
     42 
     43 // q=2q
     44 static void ECC_Double(Point *q, Point *p, uint32_t keyLength)
     45 {
     46     DWORD t1[KEY_LENGTH_DWORDS_P256];
     47     DWORD t2[KEY_LENGTH_DWORDS_P256];
     48     DWORD t3[KEY_LENGTH_DWORDS_P256];
     49     DWORD *x1;
     50     DWORD *x3;
     51     DWORD *y1;
     52     DWORD *y3;
     53     DWORD *z1;
     54     DWORD *z3;
     55 
     56     if (multiprecision_iszero(p->z, keyLength))
     57     {
     58         multiprecision_init(q->z, keyLength);
     59         return;                                     // return infinity
     60     }
     61 
     62     x1=p->x; y1=p->y; z1=p->z;
     63     x3=q->x; y3=q->y; z3=q->z;
     64 
     65     multiprecision_mersenns_squa_mod(t1, z1, keyLength);  // t1=z1^2
     66     multiprecision_sub_mod(t2, x1, t1, keyLength);  // t2=x1-t1
     67     multiprecision_add_mod(t1, x1, t1, keyLength);  // t1=x1+t1
     68     multiprecision_mersenns_mult_mod(t2, t1, t2, keyLength);  // t2=t2*t1
     69     multiprecision_lshift_mod(t3, t2, keyLength);
     70     multiprecision_add_mod(t2, t3, t2, keyLength);  // t2=3t2
     71 
     72     multiprecision_mersenns_mult_mod(z3, y1, z1, keyLength);  // z3=y1*z1
     73     multiprecision_lshift_mod(z3, z3, keyLength);
     74 
     75     multiprecision_mersenns_squa_mod(y3, y1, keyLength);  // y3=y1^2
     76     multiprecision_lshift_mod(y3, y3, keyLength);
     77     multiprecision_mersenns_mult_mod(t3, y3, x1, keyLength);  // t3=y3*x1=x1*y1^2
     78     multiprecision_lshift_mod(t3, t3, keyLength);
     79     multiprecision_mersenns_squa_mod(y3, y3, keyLength);  // y3=y3^2=y1^4
     80     multiprecision_lshift_mod(y3, y3, keyLength);
     81 
     82     multiprecision_mersenns_squa_mod(x3, t2, keyLength);  // x3=t2^2
     83     multiprecision_lshift_mod(t1, t3, keyLength);                // t1=2t3
     84     multiprecision_sub_mod(x3, x3, t1, keyLength);               // x3=x3-t1
     85     multiprecision_sub_mod(t1, t3, x3, keyLength);               // t1=t3-x3
     86     multiprecision_mersenns_mult_mod(t1, t1, t2, keyLength);  // t1=t1*t2
     87     multiprecision_sub_mod(y3, t1, y3, keyLength);               // y3=t1-y3
     88 }
     89 
     90 // q=q+p,     zp must be 1
     91 static void ECC_Add(Point *r, Point *p, Point *q, uint32_t keyLength)
     92 {
     93     DWORD t1[KEY_LENGTH_DWORDS_P256];
     94     DWORD t2[KEY_LENGTH_DWORDS_P256];
     95     DWORD *x1;
     96     DWORD *x2;
     97     DWORD *x3;
     98     DWORD *y1;
     99     DWORD *y2;
    100     DWORD *y3;
    101     DWORD *z1;
    102     DWORD *z2;
    103     DWORD *z3;
    104 
    105     x1=p->x; y1=p->y; z1=p->z;
    106     x2=q->x; y2=q->y; z2=q->z;
    107     x3=r->x; y3=r->y; z3=r->z;
    108 
    109     // if Q=infinity, return p
    110     if (multiprecision_iszero(z2, keyLength))
    111     {
    112         p_256_copy_point(r, p);
    113         return;
    114     }
    115 
    116     // if P=infinity, return q
    117     if (multiprecision_iszero(z1, keyLength))
    118     {
    119         p_256_copy_point(r, q);
    120         return;
    121     }
    122 
    123     multiprecision_mersenns_squa_mod(t1, z1, keyLength);      // t1=z1^2
    124     multiprecision_mersenns_mult_mod(t2, z1, t1, keyLength);  // t2=t1*z1
    125     multiprecision_mersenns_mult_mod(t1, x2, t1, keyLength);  // t1=t1*x2
    126     multiprecision_mersenns_mult_mod(t2, y2, t2, keyLength);  // t2=t2*y2
    127 
    128     multiprecision_sub_mod(t1, t1, x1, keyLength);  // t1=t1-x1
    129     multiprecision_sub_mod(t2, t2, y1, keyLength);  // t2=t2-y1
    130 
    131     if (multiprecision_iszero(t1, keyLength))
    132     {
    133         if (multiprecision_iszero(t2, keyLength))
    134         {
    135             ECC_Double(r, q, keyLength) ;
    136             return;
    137         }
    138         else
    139         {
    140             multiprecision_init(z3, keyLength);
    141             return;                             // return infinity
    142         }
    143     }
    144 
    145     multiprecision_mersenns_mult_mod(z3, z1, t1, keyLength);  // z3=z1*t1
    146     multiprecision_mersenns_squa_mod(y3, t1, keyLength);      // t3=t1^2
    147     multiprecision_mersenns_mult_mod(z1, y3, t1, keyLength);  // t4=t3*t1
    148     multiprecision_mersenns_mult_mod(y3, y3, x1, keyLength);  // t3=t3*x1
    149     multiprecision_lshift_mod(t1, y3, keyLength);            // t1=2*t3
    150     multiprecision_mersenns_squa_mod(x3, t2, keyLength);      // x3=t2^2
    151     multiprecision_sub_mod(x3, x3, t1, keyLength);           // x3=x3-t1
    152     multiprecision_sub_mod(x3, x3, z1, keyLength);           // x3=x3-t4
    153     multiprecision_sub_mod(y3, y3, x3, keyLength);           // t3=t3-x3
    154     multiprecision_mersenns_mult_mod(y3, y3, t2, keyLength);  // t3=t3*t2
    155     multiprecision_mersenns_mult_mod(z1, z1, y1, keyLength);  // t4=t4*t1
    156     multiprecision_sub_mod(y3, y3, z1, keyLength);
    157 }
    158 
    159 // Computing the Non-Adjacent Form of a positive integer
    160 static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength)
    161 {
    162     uint32_t sign;
    163     int i=0;
    164     int j;
    165     uint32_t var;
    166 
    167     while ((var = multiprecision_most_signbits(k, keyLength))>=1)
    168     {
    169         if (k[0] & 0x01)  // k is odd
    170         {
    171             sign = (k[0] & 0x03);  // 1 or 3
    172 
    173             // k = k-naf[i]
    174             if (sign == 1)
    175                 k[0] = k[0] & 0xFFFFFFFE;
    176             else
    177             {
    178                 k[0] = k[0] + 1;
    179                 if (k[0] == 0)  //overflow
    180                 {
    181                     j = 1;
    182                     do
    183                     {
    184                         k[j]++;
    185                     } while (k[j++]==0);  //overflow
    186                 }
    187             }
    188         }
    189         else
    190             sign = 0;
    191 
    192         multiprecision_rshift(k, k, keyLength);
    193         naf[i / 4] |= (sign) << ((i % 4) * 2);
    194         i++;
    195     }
    196 
    197     *NumNAF=i;
    198 }
    199 
    200 // Binary Non-Adjacent Form for point multiplication
    201 void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
    202 {
    203     uint32_t sign;
    204     UINT8 naf[256 / 4 +1];
    205     uint32_t NumNaf;
    206     Point minus_p;
    207     Point r;
    208     DWORD *modp;
    209 
    210     if (keyLength == KEY_LENGTH_DWORDS_P256)
    211     {
    212         modp = curve_p256.p;
    213     }
    214     else
    215     {
    216         modp = curve.p;
    217     }
    218 
    219     p_256_init_point(&r);
    220     multiprecision_init(p->z, keyLength);
    221     p->z[0] = 1;
    222 
    223     // initialization
    224     p_256_init_point(q);
    225 
    226     // -p
    227     multiprecision_copy(minus_p.x, p->x, keyLength);
    228     multiprecision_sub(minus_p.y, modp, p->y, keyLength);
    229 
    230     multiprecision_init(minus_p.z, keyLength);
    231     minus_p.z[0]=1;
    232 
    233     // NAF
    234     memset(naf, 0, sizeof(naf));
    235     ECC_NAF(naf, &NumNaf, n, keyLength);
    236 
    237     for (int i = NumNaf - 1; i >= 0; i--)
    238     {
    239         p_256_copy_point(&r, q);
    240         ECC_Double(q, &r, keyLength);
    241         sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
    242 
    243         if (sign == 1)
    244         {
    245             p_256_copy_point(&r, q);
    246             ECC_Add(q, &r, p, keyLength);
    247         }
    248         else if (sign == 3)
    249         {
    250             p_256_copy_point(&r, q);
    251             ECC_Add(q, &r, &minus_p, keyLength);
    252         }
    253     }
    254 
    255     multiprecision_inv_mod(minus_p.x, q->z, keyLength);
    256     multiprecision_mersenns_squa_mod(q->z, minus_p.x, keyLength);
    257     multiprecision_mersenns_mult_mod(q->x, q->x, q->z, keyLength);
    258     multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
    259     multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
    260 }
    261 
    262 
    263