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
     22   *
     23   ******************************************************************************/
     24 
     25 #include <string.h>
     26 #include "bt_target.h"
     27 #include "p_256_ecc_pp.h"
     28 #include "p_256_multprecision.h"
     29 
     30 void multiprecision_init(DWORD *c, uint32_t keyLength)
     31 {
     32     for (uint32_t i = 0; i < keyLength; i++)
     33         c[i] = 0;
     34 }
     35 
     36 void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength)
     37 {
     38     for (uint32_t i = 0; i < keyLength; i++)
     39         c[i] = a[i];
     40 }
     41 
     42 int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength)
     43 {
     44     for (int i = keyLength - 1; i >= 0; i--)
     45     {
     46         if (a[i] > b[i])
     47             return 1;
     48         if (a[i] < b[i])
     49             return -1;
     50     }
     51     return 0;
     52 }
     53 
     54 int multiprecision_iszero(DWORD *a, uint32_t keyLength)
     55 {
     56     for (uint32_t i = 0; i < keyLength; i++)
     57         if (a[i])
     58             return 0;
     59 
     60     return 1;
     61 }
     62 
     63 UINT32 multiprecision_dword_bits(DWORD a)
     64 {
     65     uint32_t i;
     66     for (i = 0; i < DWORD_BITS; i++, a >>= 1)
     67         if (a == 0)
     68             break;
     69 
     70     return i;
     71 }
     72 
     73 UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength)
     74 {
     75     int  i;
     76     for (i = keyLength - 1; i >= 0; i--)
     77         if (a[i])
     78            break;
     79     return (i + 1);
     80 }
     81 
     82 UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength)
     83 {
     84     int aMostSignDWORDs;
     85 
     86     aMostSignDWORDs = multiprecision_most_signdwords(a, keyLength);
     87     if (aMostSignDWORDs == 0)
     88         return 0;
     89 
     90     return (((aMostSignDWORDs-1) << DWORD_BITS_SHIFT) +
     91             multiprecision_dword_bits(a[aMostSignDWORDs-1]) );
     92 }
     93 
     94 DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
     95 {
     96     DWORD carrier;
     97     DWORD temp;
     98 
     99     carrier=0;
    100     for (uint32_t i = 0; i < keyLength; i++)
    101     {
    102         temp = a[i] + carrier;
    103         carrier = (temp < carrier);
    104         temp += b[i];
    105         carrier |= (temp < b[i]);
    106         c[i]=temp;
    107     }
    108 
    109     return carrier;
    110 }
    111 
    112 //c=a-b
    113 DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
    114 {
    115     DWORD borrow;
    116     DWORD temp;
    117 
    118     borrow=0;
    119     for (uint32_t i=0; i < keyLength; i++)
    120     {
    121         temp = a[i] - borrow;
    122         borrow = (temp > a[i]);
    123         c[i] = temp - b[i];
    124         borrow |= (c[i] > temp);
    125     }
    126 
    127     return borrow;
    128 }
    129 
    130 // c = a << 1
    131 void multiprecision_lshift_mod(DWORD * c, DWORD * a, uint32_t keyLength)
    132 {
    133     DWORD carrier;
    134     DWORD *modp;
    135 
    136     if (keyLength == KEY_LENGTH_DWORDS_P192)
    137     {
    138         modp = curve.p;
    139     }
    140     else if (keyLength == KEY_LENGTH_DWORDS_P256)
    141     {
    142         modp = curve_p256.p;
    143     }
    144     else
    145         return;
    146 
    147     carrier = multiprecision_lshift(c, a, keyLength);
    148     if (carrier)
    149     {
    150         multiprecision_sub(c, c, modp, keyLength);
    151     }
    152     else if (multiprecision_compare(c, modp, keyLength)>=0)
    153     {
    154         multiprecision_sub(c, c, modp, keyLength);
    155     }
    156 }
    157 
    158 // c=a>>1
    159 void multiprecision_rshift(DWORD * c, DWORD * a, uint32_t keyLength)
    160 {
    161     int j;
    162     DWORD b = 1;
    163 
    164     j = DWORD_BITS - b;
    165 
    166     DWORD carrier = 0;
    167     DWORD temp;
    168     for (int i = keyLength-1; i >= 0; i--)
    169     {
    170         temp = a[i]; // in case of c==a
    171         c[i] = (temp >> b) | carrier;
    172         carrier = temp << j;
    173     }
    174 }
    175 
    176 // Curve specific optimization when p is a pseudo-Mersenns prime, p=2^(KEY_LENGTH_BITS)-omega
    177 void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
    178 {
    179     DWORD cc[2*KEY_LENGTH_DWORDS_P256];
    180 
    181     multiprecision_mult(cc, a, b, keyLength);
    182     if (keyLength == 6)
    183     {
    184         multiprecision_fast_mod(c, cc);
    185     }
    186     else if (keyLength == 8)
    187     {
    188         multiprecision_fast_mod_P256(c, cc);
    189     }
    190 }
    191 
    192 // Curve specific optimization when p is a pseudo-Mersenns prime
    193 void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength)
    194 {
    195     multiprecision_mersenns_mult_mod(c, a, a, keyLength);
    196 }
    197 
    198 // c=(a+b) mod p, b<p, a<p
    199 void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
    200 {
    201     DWORD carrier;
    202     DWORD *modp;
    203 
    204     if (keyLength == KEY_LENGTH_DWORDS_P192)
    205     {
    206         modp = curve.p;
    207     }
    208     else if (keyLength == KEY_LENGTH_DWORDS_P256)
    209     {
    210         modp = curve_p256.p;
    211     }
    212     else
    213         return;
    214 
    215     carrier = multiprecision_add(c, a, b, keyLength);
    216     if (carrier)
    217     {
    218         multiprecision_sub(c, c, modp, keyLength);
    219     }
    220     else if (multiprecision_compare(c, modp, keyLength) >= 0)
    221     {
    222         multiprecision_sub(c, c, modp, keyLength);
    223     }
    224 }
    225 
    226 // c=(a-b) mod p, a<p, b<p
    227 void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
    228 {
    229     DWORD borrow;
    230     DWORD *modp;
    231 
    232     if (keyLength == KEY_LENGTH_DWORDS_P192)
    233     {
    234         modp = curve.p;
    235     }
    236     else if(keyLength == KEY_LENGTH_DWORDS_P256)
    237     {
    238         modp = curve_p256.p;
    239     }
    240     else
    241         return;
    242 
    243     borrow = multiprecision_sub(c, a, b, keyLength);
    244     if(borrow)
    245         multiprecision_add(c, c, modp, keyLength);
    246 }
    247 
    248 // c=a<<b, b<DWORD_BITS, c has a buffer size of NumDWORDs+1
    249 DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength)
    250 {
    251     int j;
    252     uint32_t b = 1;
    253     j = DWORD_BITS - b;
    254 
    255     DWORD carrier = 0;
    256     DWORD temp;
    257 
    258     for (uint32_t i = 0; i < keyLength; i++)
    259     {
    260         temp = a[i];  // in case c==a
    261         c[i] = (temp << b) | carrier;
    262         carrier = temp >> j;
    263     }
    264 
    265     return carrier;
    266 }
    267 
    268 // c=a*b; c must have a buffer of 2*Key_LENGTH_DWORDS, c != a != b
    269 void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
    270 {
    271     DWORD W;
    272     DWORD U;
    273     DWORD V;
    274 
    275     U = V = W = 0;
    276     multiprecision_init(c, keyLength);
    277 
    278     //assume little endian right now
    279     for (uint32_t i = 0; i < keyLength; i++)
    280     {
    281         U = 0;
    282         for (uint32_t j = 0; j < keyLength; j++)
    283         {
    284             uint64_t result;
    285             result = ((UINT64)a[i]) * ((uint64_t) b[j]);
    286             W = result >> 32;
    287             V = a[i] * b[j];
    288             V = V + U;
    289             U = (V < U);
    290             U += W;
    291             V = V + c[i+j];
    292             U += (V < c[i+j]);
    293             c[i+j] = V;
    294         }
    295         c[i+keyLength] = U;
    296     }
    297 }
    298 
    299 void multiprecision_fast_mod(DWORD *c, DWORD *a)
    300 {
    301     DWORD U;
    302     DWORD V;
    303     DWORD *modp = curve.p;
    304 
    305     c[0] = a[0] + a[6];
    306     U=c[0] < a[0];
    307     c[0] += a[10];
    308     U += c[0] < a[10];
    309 
    310     c[1] = a[1] + U;
    311     U = c[1] < a[1];
    312     c[1] += a[7];
    313     U += c[1] < a[7];
    314     c[1] += a[11];
    315     U += c[1]< a[11];
    316 
    317     c[2] = a[2] + U;
    318     U = c[2] < a[2];
    319     c[2] += a[6];
    320     U += c[2] < a[6];
    321     c[2] += a[8];
    322     U += c[2] < a[8];
    323     c[2] += a[10];
    324     U += c[2] < a[10];
    325 
    326     c[3] = a[3]+U;
    327     U = c[3] < a[3];
    328     c[3] += a[7];
    329     U += c[3] < a[7];
    330     c[3] += a[9];
    331     U += c[3] < a[9];
    332     c[3] += a[11];
    333     U += c[3] < a[11];
    334 
    335     c[4] = a[4]+U;
    336     U = c[4] < a[4];
    337     c[4] += a[8];
    338     U += c[4] < a[8];
    339     c[4] += a[10];
    340     U += c[4] < a[10];
    341 
    342     c[5] = a[5]+U;
    343     U = c[5] < a[5];
    344     c[5] += a[9];
    345     U += c[5] < a[9];
    346     c[5] += a[11];
    347     U += c[5] < a[11];
    348 
    349     c[0] += U;
    350     V = c[0] < U;
    351     c[1] += V;
    352     V = c[1] < V;
    353     c[2] += V;
    354     V = c[2] < V;
    355     c[2] += U;
    356     V = c[2] < U;
    357     c[3] += V;
    358     V = c[3] < V;
    359     c[4] += V;
    360     V = c[4] < V;
    361     c[5] += V;
    362     V = c[5] < V;
    363 
    364     if (V)
    365     {
    366         multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
    367     }
    368     else if(multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P192) >= 0)
    369     {
    370         multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
    371     }
    372 }
    373 
    374 void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
    375 {
    376     DWORD A;
    377     DWORD B;
    378     DWORD C;
    379     DWORD D;
    380     DWORD E;
    381     DWORD F;
    382     DWORD G;
    383     uint8_t UA;
    384     uint8_t UB;
    385     uint8_t UC;
    386     uint8_t UD;
    387     uint8_t UE;
    388     uint8_t UF;
    389     uint8_t UG;
    390     DWORD U;
    391     DWORD *modp = curve_p256.p;
    392 
    393     // C = a[13] + a[14] + a[15];
    394     C = a[13];
    395     C += a[14];
    396     UC = (C < a[14]);
    397     C += a[15];
    398     UC += (C < a[15]);
    399 
    400     // E = a[8] + a[9];
    401     E = a[8];
    402     E += a[9];
    403     UE = (E < a[9]);
    404 
    405     // F = a[9] + a[10];
    406     F = a[9];
    407     F += a[10];
    408     UF = (F < a[10]);
    409 
    410     // G = a[10] + a[11]
    411     G = a[10];
    412     G += a[11];
    413     UG = (G < a[11]);
    414 
    415     // B = a[12] + a[13] + a[14] + a[15] == C + a[12]
    416     B = C;
    417     UB = UC;
    418     B += a[12];
    419     UB += (B < a[12]);
    420 
    421     // A = a[11] + a[12] + a[13] + a[14] == B + a[11] - a[15]
    422     A = B;
    423     UA = UB;
    424     A += a[11];
    425     UA += (A < a[11]);
    426     UA -= (A < a[15]);
    427     A -= a[15];
    428 
    429     // D = a[10] + a[11] + a[12] + a[13] == A + a[10] - a[14]
    430     D = A;
    431     UD = UA;
    432     D += a[10];
    433     UD += (D < a[10]);
    434     UD -= (D < a[14]);
    435     D -= a[14];
    436 
    437     c[0] = a[0];
    438     c[0] += E;
    439     U = (c[0] < E);
    440     U += UE;
    441     U -= (c[0] < A);
    442     U -= UA;
    443     c[0] -= A;
    444 
    445     if (U & 0x80000000)
    446     {
    447         DWORD UU;
    448         UU = 0 - U;
    449         U = (a[1] < UU);
    450         c[1] = a[1] - UU;
    451     }
    452     else
    453     {
    454         c[1] = a[1] + U;
    455         U = (c[1] < a[1]);
    456     }
    457 
    458     c[1] += F;
    459     U += (c[1] < F);
    460     U += UF;
    461     U -= (c[1] < B);
    462     U -= UB;
    463     c[1] -= B;
    464 
    465     if (U & 0x80000000)
    466     {
    467         DWORD UU;
    468         UU = 0 - U;
    469         U = (a[2] < UU);
    470         c[2] = a[2] - UU;
    471     }
    472     else
    473     {
    474         c[2] = a[2] + U;
    475         U = (c[2] < a[2]);
    476     }
    477 
    478     c[2] += G;
    479     U += (c[2] < G);
    480     U += UG;
    481     U -= (c[2] < C);
    482     U -= UC;
    483     c[2] -= C;
    484 
    485     if (U & 0x80000000)
    486     {
    487         DWORD UU;
    488         UU = 0 - U;
    489         U = (a[3] < UU);
    490         c[3] = a[3] - UU;
    491     }
    492     else
    493     {
    494         c[3] = a[3] + U;
    495         U = (c[3] < a[3]);
    496     }
    497 
    498     c[3] += A;
    499     U += (c[3] < A);
    500     U += UA;
    501     c[3] += a[11];
    502     U += (c[3] < a[11]);
    503     c[3] += a[12];
    504     U += (c[3] < a[12]);
    505     U -= (c[3] < a[14]);
    506     c[3] -= a[14];
    507     U -= (c[3] < a[15]);
    508     c[3] -= a[15];
    509     U -= (c[3] < E);
    510     U -= UE;
    511     c[3] -= E;
    512 
    513     if (U & 0x80000000)
    514     {
    515         DWORD UU;
    516         UU = 0 - U;
    517         U = (a[4] < UU);
    518         c[4] = a[4] - UU;
    519     }
    520     else
    521     {
    522         c[4] = a[4] + U;
    523         U = (c[4] < a[4]);
    524     }
    525 
    526     c[4] += B;
    527     U += (c[4] < B);
    528     U += UB;
    529     U -= (c[4] < a[15]);
    530     c[4] -= a[15];
    531     c[4] += a[12];
    532     U += (c[4] < a[12]);
    533     c[4] += a[13];
    534     U += (c[4] < a[13]);
    535     U -= (c[4] < F);
    536     U -= UF;
    537     c[4] -= F;
    538 
    539     if (U & 0x80000000)
    540     {
    541         DWORD UU;
    542         UU = 0 - U;
    543         U = (a[5] < UU);
    544         c[5] = a[5] - UU;
    545     }
    546     else
    547     {
    548         c[5] = a[5] + U;
    549         U = (c[5] < a[5]);
    550     }
    551 
    552     c[5] += C;
    553     U += (c[5] < C);
    554     U += UC;
    555     c[5] += a[13];
    556     U += (c[5] < a[13]);
    557     c[5] += a[14];
    558     U += (c[5] < a[14]);
    559     U -= (c[5] < G);
    560     U -= UG;
    561     c[5] -= G;
    562 
    563     if (U & 0x80000000)
    564     {
    565         DWORD UU;
    566         UU = 0 - U;
    567         U = (a[6] < UU);
    568         c[6] = a[6] - UU;
    569     }
    570     else
    571     {
    572         c[6] = a[6] + U;
    573         U = (c[6] < a[6]);
    574     }
    575 
    576     c[6] += C;
    577     U += (c[6] < C);
    578     U += UC;
    579     c[6] += a[14];
    580     U += (c[6] < a[14]);
    581     c[6] += a[14];
    582     U += (c[6] < a[14]);
    583     c[6] += a[15];
    584     U += (c[6] < a[15]);
    585     U -= (c[6] < E);
    586     U -= UE;
    587     c[6] -= E;
    588 
    589     if (U & 0x80000000)
    590     {
    591         DWORD UU;
    592         UU = 0 - U;
    593         U = (a[7] < UU);
    594         c[7] = a[7] - UU;
    595     }
    596     else
    597     {
    598         c[7] = a[7] + U;
    599         U = (c[7] < a[7]);
    600     }
    601 
    602     c[7] += a[15];
    603     U += (c[7] < a[15]);
    604     c[7] += a[15];
    605     U += (c[7] < a[15]);
    606     c[7] += a[15];
    607     U += (c[7] < a[15]);
    608     c[7] += a[8];
    609     U += (c[7] < a[8]);
    610     U -= (c[7] < D);
    611     U -= UD;
    612     c[7] -= D;
    613 
    614     if (U & 0x80000000)
    615     {
    616         while (U)
    617         {
    618             multiprecision_add(c, c, modp, KEY_LENGTH_DWORDS_P256);
    619             U++;
    620         }
    621     }
    622     else if (U)
    623     {
    624         while (U)
    625         {
    626             multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
    627             U--;
    628         }
    629     }
    630 
    631     if (multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P256)>=0)
    632         multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
    633 
    634 }
    635 
    636 void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
    637 {
    638     DWORD v[KEY_LENGTH_DWORDS_P256];
    639     DWORD A[KEY_LENGTH_DWORDS_P256+1];
    640     DWORD C[KEY_LENGTH_DWORDS_P256+1];
    641     DWORD *modp;
    642 
    643     if(keyLength == KEY_LENGTH_DWORDS_P256)
    644     {
    645         modp = curve_p256.p;
    646     }
    647     else
    648     {
    649         modp = curve.p;
    650     }
    651 
    652     multiprecision_copy(v, modp, keyLength);
    653     multiprecision_init(A, keyLength);
    654     multiprecision_init(C, keyLength);
    655     A[0] = 1;
    656 
    657     while (!multiprecision_iszero(u, keyLength))
    658     {
    659         while (!(u[0] & 0x01))  // u is even
    660         {
    661             multiprecision_rshift(u, u, keyLength);
    662             if(!(A[0] & 0x01))  // A is even
    663                 multiprecision_rshift(A, A, keyLength);
    664             else
    665             {
    666                 A[keyLength]=multiprecision_add(A, A, modp, keyLength); // A =A+p
    667                 multiprecision_rshift(A, A, keyLength);
    668                 A[keyLength-1] |= (A[keyLength]<<31);
    669             }
    670         }
    671 
    672         while (!(v[0] & 0x01))  // v is even
    673         {
    674             multiprecision_rshift(v, v, keyLength);
    675             if (!(C[0] & 0x01))  // C is even
    676             {
    677                 multiprecision_rshift(C, C, keyLength);
    678             }
    679             else
    680             {
    681                 C[keyLength] = multiprecision_add(C, C, modp, keyLength); // C =C+p
    682                 multiprecision_rshift(C, C, keyLength);
    683                 C[keyLength-1] |= (C[keyLength] << 31);
    684             }
    685         }
    686 
    687         if (multiprecision_compare(u, v, keyLength) >= 0)
    688         {
    689             multiprecision_sub(u, u, v, keyLength);
    690             multiprecision_sub_mod(A, A, C, keyLength);
    691         }
    692         else
    693         {
    694             multiprecision_sub(v, v, u, keyLength);
    695             multiprecision_sub_mod(C, C, A, keyLength);
    696         }
    697     }
    698 
    699     if (multiprecision_compare(C, modp, keyLength) >= 0)
    700         multiprecision_sub(aminus, C, modp, keyLength);
    701     else
    702         multiprecision_copy(aminus, C, keyLength);
    703 }
    704 
    705