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