• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 using Elliptic Curve
22  *  Cryptography for private public key
23  *
24  ******************************************************************************/
25 #include "security/ecc/p_256_ecc_pp.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "security/ecc/multprecision.h"
30 
31 namespace bluetooth {
32 namespace security {
33 namespace ecc {
34 
35 const uint32_t* modp = curve_p256.p;
36 
p_256_init_point(Point * q)37 static void p_256_init_point(Point* q) {
38   memset(q, 0, sizeof(Point));
39 }
40 
p_256_copy_point(Point * q,const Point * p)41 static void p_256_copy_point(Point* q, const Point* p) {
42   memcpy(q, p, sizeof(Point));
43 }
44 
45 // q=2q
ECC_Double(Point * q,const Point * p)46 static void ECC_Double(Point* q, const Point* p) {
47   uint32_t t1[KEY_LENGTH_DWORDS_P256];
48   uint32_t t2[KEY_LENGTH_DWORDS_P256];
49   uint32_t t3[KEY_LENGTH_DWORDS_P256];
50   const uint32_t* x1;
51   uint32_t* x3;
52   const uint32_t* y1;
53   uint32_t* y3;
54   const uint32_t* z1;
55   uint32_t* z3;
56 
57   if (multiprecision_iszero(p->z)) {
58     multiprecision_init(q->z);
59     return;  // return infinity
60   }
61 
62   x1 = p->x;
63   y1 = p->y;
64   z1 = p->z;
65   x3 = q->x;
66   y3 = q->y;
67   z3 = q->z;
68 
69   multiprecision_mersenns_squa_mod(t1, z1, modp);      // t1=z1^2
70   multiprecision_sub_mod(t2, x1, t1, modp);            // t2=x1-t1
71   multiprecision_add_mod(t1, x1, t1, modp);            // t1=x1+t1
72   multiprecision_mersenns_mult_mod(t2, t1, t2, modp);  // t2=t2*t1
73   multiprecision_lshift_mod(t3, t2, modp);
74   multiprecision_add_mod(t2, t3, t2, modp);  // t2=3t2
75 
76   multiprecision_mersenns_mult_mod(z3, y1, z1, modp);  // z3=y1*z1
77   multiprecision_lshift_mod(z3, z3, modp);
78 
79   multiprecision_mersenns_squa_mod(y3, y1, modp);  // y3=y1^2
80   multiprecision_lshift_mod(y3, y3, modp);
81   multiprecision_mersenns_mult_mod(t3, y3, x1, modp);  // t3=y3*x1=x1*y1^2
82   multiprecision_lshift_mod(t3, t3, modp);
83   multiprecision_mersenns_squa_mod(y3, y3, modp);  // y3=y3^2=y1^4
84   multiprecision_lshift_mod(y3, y3, modp);
85 
86   multiprecision_mersenns_squa_mod(x3, t2, modp);      // x3=t2^2
87   multiprecision_lshift_mod(t1, t3, modp);             // t1=2t3
88   multiprecision_sub_mod(x3, x3, t1, modp);            // x3=x3-t1
89   multiprecision_sub_mod(t1, t3, x3, modp);            // t1=t3-x3
90   multiprecision_mersenns_mult_mod(t1, t1, t2, modp);  // t1=t1*t2
91   multiprecision_sub_mod(y3, t1, y3, modp);            // y3=t1-y3
92 }
93 
94 // q=q+p,     zp must be 1
ECC_Add(Point * r,Point * p,const Point * q)95 static void ECC_Add(Point* r, Point* p, const Point* q) {
96   uint32_t t1[KEY_LENGTH_DWORDS_P256];
97   uint32_t t2[KEY_LENGTH_DWORDS_P256];
98   uint32_t* x1;
99   const uint32_t* x2;
100   uint32_t* x3;
101   uint32_t* y1;
102   const uint32_t* y2;
103   uint32_t* y3;
104   uint32_t* z1;
105   const uint32_t* z2;
106   uint32_t* z3;
107 
108   x1 = p->x;
109   y1 = p->y;
110   z1 = p->z;
111   x2 = q->x;
112   y2 = q->y;
113   z2 = q->z;
114   x3 = r->x;
115   y3 = r->y;
116   z3 = r->z;
117 
118   // if Q=infinity, return p
119   if (multiprecision_iszero(z2)) {
120     p_256_copy_point(r, p);
121     return;
122   }
123 
124   // if P=infinity, return q
125   if (multiprecision_iszero(z1)) {
126     p_256_copy_point(r, q);
127     return;
128   }
129 
130   multiprecision_mersenns_squa_mod(t1, z1, modp);      // t1=z1^2
131   multiprecision_mersenns_mult_mod(t2, z1, t1, modp);  // t2=t1*z1
132   multiprecision_mersenns_mult_mod(t1, x2, t1, modp);  // t1=t1*x2
133   multiprecision_mersenns_mult_mod(t2, y2, t2, modp);  // t2=t2*y2
134 
135   multiprecision_sub_mod(t1, t1, x1, modp);  // t1=t1-x1
136   multiprecision_sub_mod(t2, t2, y1, modp);  // t2=t2-y1
137 
138   if (multiprecision_iszero(t1)) {
139     if (multiprecision_iszero(t2)) {
140       ECC_Double(r, q);
141       return;
142     } else {
143       multiprecision_init(z3);
144       return;  // return infinity
145     }
146   }
147 
148   multiprecision_mersenns_mult_mod(z3, z1, t1, modp);  // z3=z1*t1
149   multiprecision_mersenns_squa_mod(y3, t1, modp);      // t3=t1^2
150   multiprecision_mersenns_mult_mod(z1, y3, t1, modp);  // t4=t3*t1
151   multiprecision_mersenns_mult_mod(y3, y3, x1, modp);  // t3=t3*x1
152   multiprecision_lshift_mod(t1, y3, modp);             // t1=2*t3
153   multiprecision_mersenns_squa_mod(x3, t2, modp);      // x3=t2^2
154   multiprecision_sub_mod(x3, x3, t1, modp);            // x3=x3-t1
155   multiprecision_sub_mod(x3, x3, z1, modp);            // x3=x3-t4
156   multiprecision_sub_mod(y3, y3, x3, modp);            // t3=t3-x3
157   multiprecision_mersenns_mult_mod(y3, y3, t2, modp);  // t3=t3*t2
158   multiprecision_mersenns_mult_mod(z1, z1, y1, modp);  // t4=t4*t1
159   multiprecision_sub_mod(y3, y3, z1, modp);
160 }
161 
162 // Computing the Non-Adjacent Form of a positive integer
ECC_NAF(uint8_t * naf,uint32_t * NumNAF,uint32_t * k)163 static void ECC_NAF(uint8_t* naf, uint32_t* NumNAF, uint32_t* k) {
164   uint32_t sign;
165   int i = 0;
166   int j;
167   uint32_t var;
168 
169   while ((var = multiprecision_most_signbits(k)) >= 1) {
170     if (k[0] & 0x01)  // k is odd
171     {
172       sign = (k[0] & 0x03);  // 1 or 3
173 
174       // k = k-naf[i]
175       if (sign == 1)
176         k[0] = k[0] & 0xFFFFFFFE;
177       else {
178         k[0] = k[0] + 1;
179         if (k[0] == 0)  // overflow
180         {
181           j = 1;
182           do {
183             k[j]++;
184           } while (k[j++] == 0);  // overflow
185         }
186       }
187     } else
188       sign = 0;
189 
190     multiprecision_rshift(k, k);
191     naf[i / 4] |= (sign) << ((i % 4) * 2);
192     i++;
193   }
194 
195   *NumNAF = i;
196 }
197 
198 // Binary Non-Adjacent Form for point multiplication
ECC_PointMult_Bin_NAF(Point * q,const Point * p,uint32_t * n)199 void ECC_PointMult_Bin_NAF(Point* q, const Point* p, uint32_t* n) {
200   uint32_t sign;
201   uint8_t naf[256 / 4 + 1];
202   uint32_t NumNaf;
203   Point minus_p;
204   Point r;
205 
206   p_256_init_point(&r);
207 
208   // initialization
209   p_256_init_point(q);
210 
211   // -p
212   multiprecision_copy(minus_p.x, p->x);
213   multiprecision_sub(minus_p.y, modp, p->y);
214 
215   multiprecision_init(minus_p.z);
216   minus_p.z[0] = 1;
217 
218   // NAF
219   memset(naf, 0, sizeof(naf));
220   ECC_NAF(naf, &NumNaf, n);
221 
222   for (int i = NumNaf - 1; i >= 0; i--) {
223     p_256_copy_point(&r, q);
224     ECC_Double(q, &r);
225     sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
226 
227     if (sign == 1) {
228       p_256_copy_point(&r, q);
229       ECC_Add(q, &r, p);
230     } else if (sign == 3) {
231       p_256_copy_point(&r, q);
232       ECC_Add(q, &r, &minus_p);
233     }
234   }
235 
236   multiprecision_inv_mod(minus_p.x, q->z, modp);
237   multiprecision_mersenns_squa_mod(q->z, minus_p.x, modp);
238   multiprecision_mersenns_mult_mod(q->x, q->x, q->z, modp);
239   multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, modp);
240   multiprecision_mersenns_mult_mod(q->y, q->y, q->z, modp);
241 }
242 
ECC_ValidatePoint(const Point & pt)243 bool ECC_ValidatePoint(const Point& pt) {
244   // Ensure y^2 = x^3 + a*x + b (mod p); a = -3
245 
246   // y^2 mod p
247   uint32_t y2_mod[KEY_LENGTH_DWORDS_P256] = {0};
248   multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, modp);
249 
250   // Right hand side calculation
251   uint32_t rhs[KEY_LENGTH_DWORDS_P256] = {0};
252   multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, modp);
253   uint32_t three[KEY_LENGTH_DWORDS_P256] = {0};
254   three[0] = 3;
255   multiprecision_sub_mod(rhs, rhs, three, modp);
256   multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, modp);
257   multiprecision_add_mod(rhs, rhs, curve_p256.b, modp);
258 
259   return multiprecision_compare(rhs, y2_mod) == 0;
260 }
261 
262 }  // namespace ecc
263 }  // namespace security
264 }  // namespace bluetooth