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