p_256_ecc_pp.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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. * This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
  21. *
  22. ******************************************************************************/
  23. //#include <stdio.h>
  24. //#include <stdlib.h>
  25. #include <string.h>
  26. #include "p_256_ecc_pp.h"
  27. #include "p_256_multprecision.h"
  28. #include "common/bt_target.h"
  29. #if SMP_DYNAMIC_MEMORY == FALSE
  30. elliptic_curve_t curve;
  31. elliptic_curve_t curve_p256;
  32. #else
  33. elliptic_curve_t *curve_ptr;
  34. elliptic_curve_t *curve_p256_ptr;
  35. #endif
  36. static void p_256_init_point(Point *q)
  37. {
  38. memset(q, 0, sizeof(Point));
  39. }
  40. static void p_256_copy_point(Point *q, Point *p)
  41. {
  42. memcpy(q, p, sizeof(Point));
  43. }
  44. // q=2q
  45. static void ECC_Double(Point *q, Point *p, uint32_t keyLength)
  46. {
  47. DWORD t1[KEY_LENGTH_DWORDS_P256];
  48. DWORD t2[KEY_LENGTH_DWORDS_P256];
  49. DWORD t3[KEY_LENGTH_DWORDS_P256];
  50. DWORD *x1;
  51. DWORD *x3;
  52. DWORD *y1;
  53. DWORD *y3;
  54. DWORD *z1;
  55. DWORD *z3;
  56. if (multiprecision_iszero(p->z, keyLength)) {
  57. multiprecision_init(q->z, keyLength);
  58. return; // return infinity
  59. }
  60. x1 = p->x; y1 = p->y; z1 = p->z;
  61. x3 = q->x; y3 = q->y; z3 = q->z;
  62. multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
  63. multiprecision_sub_mod(t2, x1, t1, keyLength); // t2=x1-t1
  64. multiprecision_add_mod(t1, x1, t1, keyLength); // t1=x1+t1
  65. multiprecision_mersenns_mult_mod(t2, t1, t2, keyLength); // t2=t2*t1
  66. multiprecision_lshift_mod(t3, t2, keyLength);
  67. multiprecision_add_mod(t2, t3, t2, keyLength); // t2=3t2
  68. multiprecision_mersenns_mult_mod(z3, y1, z1, keyLength); // z3=y1*z1
  69. multiprecision_lshift_mod(z3, z3, keyLength);
  70. multiprecision_mersenns_squa_mod(y3, y1, keyLength); // y3=y1^2
  71. multiprecision_lshift_mod(y3, y3, keyLength);
  72. multiprecision_mersenns_mult_mod(t3, y3, x1, keyLength); // t3=y3*x1=x1*y1^2
  73. multiprecision_lshift_mod(t3, t3, keyLength);
  74. multiprecision_mersenns_squa_mod(y3, y3, keyLength); // y3=y3^2=y1^4
  75. multiprecision_lshift_mod(y3, y3, keyLength);
  76. multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
  77. multiprecision_lshift_mod(t1, t3, keyLength); // t1=2t3
  78. multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
  79. multiprecision_sub_mod(t1, t3, x3, keyLength); // t1=t3-x3
  80. multiprecision_mersenns_mult_mod(t1, t1, t2, keyLength); // t1=t1*t2
  81. multiprecision_sub_mod(y3, t1, y3, keyLength); // y3=t1-y3
  82. }
  83. // q=q+p, zp must be 1
  84. static void ECC_Add(Point *r, Point *p, Point *q, uint32_t keyLength)
  85. {
  86. DWORD t1[KEY_LENGTH_DWORDS_P256];
  87. DWORD t2[KEY_LENGTH_DWORDS_P256];
  88. DWORD *x1;
  89. DWORD *x2;
  90. DWORD *x3;
  91. DWORD *y1;
  92. DWORD *y2;
  93. DWORD *y3;
  94. DWORD *z1;
  95. DWORD *z2;
  96. DWORD *z3;
  97. x1 = p->x; y1 = p->y; z1 = p->z;
  98. x2 = q->x; y2 = q->y; z2 = q->z;
  99. x3 = r->x; y3 = r->y; z3 = r->z;
  100. // if Q=infinity, return p
  101. if (multiprecision_iszero(z2, keyLength)) {
  102. p_256_copy_point(r, p);
  103. return;
  104. }
  105. // if P=infinity, return q
  106. if (multiprecision_iszero(z1, keyLength)) {
  107. p_256_copy_point(r, q);
  108. return;
  109. }
  110. multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
  111. multiprecision_mersenns_mult_mod(t2, z1, t1, keyLength); // t2=t1*z1
  112. multiprecision_mersenns_mult_mod(t1, x2, t1, keyLength); // t1=t1*x2
  113. multiprecision_mersenns_mult_mod(t2, y2, t2, keyLength); // t2=t2*y2
  114. multiprecision_sub_mod(t1, t1, x1, keyLength); // t1=t1-x1
  115. multiprecision_sub_mod(t2, t2, y1, keyLength); // t2=t2-y1
  116. if (multiprecision_iszero(t1, keyLength)) {
  117. if (multiprecision_iszero(t2, keyLength)) {
  118. ECC_Double(r, q, keyLength) ;
  119. return;
  120. } else {
  121. multiprecision_init(z3, keyLength);
  122. return; // return infinity
  123. }
  124. }
  125. multiprecision_mersenns_mult_mod(z3, z1, t1, keyLength); // z3=z1*t1
  126. multiprecision_mersenns_squa_mod(y3, t1, keyLength); // t3=t1^2
  127. multiprecision_mersenns_mult_mod(z1, y3, t1, keyLength); // t4=t3*t1
  128. multiprecision_mersenns_mult_mod(y3, y3, x1, keyLength); // t3=t3*x1
  129. multiprecision_lshift_mod(t1, y3, keyLength); // t1=2*t3
  130. multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
  131. multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
  132. multiprecision_sub_mod(x3, x3, z1, keyLength); // x3=x3-t4
  133. multiprecision_sub_mod(y3, y3, x3, keyLength); // t3=t3-x3
  134. multiprecision_mersenns_mult_mod(y3, y3, t2, keyLength); // t3=t3*t2
  135. multiprecision_mersenns_mult_mod(z1, z1, y1, keyLength); // t4=t4*t1
  136. multiprecision_sub_mod(y3, y3, z1, keyLength);
  137. }
  138. // Computing the Non-Adjacent Form of a positive integer
  139. static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength)
  140. {
  141. uint32_t sign;
  142. int i = 0;
  143. int j;
  144. uint32_t var;
  145. while ((var = multiprecision_most_signbits(k, keyLength)) >= 1) {
  146. if (k[0] & 0x01) { // k is odd
  147. sign = (k[0] & 0x03); // 1 or 3
  148. // k = k-naf[i]
  149. if (sign == 1) {
  150. k[0] = k[0] & 0xFFFFFFFE;
  151. } else {
  152. k[0] = k[0] + 1;
  153. if (k[0] == 0) { //overflow
  154. j = 1;
  155. do {
  156. k[j]++;
  157. } while (k[j++] == 0); //overflow
  158. }
  159. }
  160. } else {
  161. sign = 0;
  162. }
  163. multiprecision_rshift(k, k, keyLength);
  164. naf[i / 4] |= (sign) << ((i % 4) * 2);
  165. i++;
  166. }
  167. *NumNAF = i;
  168. }
  169. // Binary Non-Adjacent Form for point multiplication
  170. void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
  171. {
  172. uint32_t sign;
  173. UINT8 naf[256 / 4 + 1];
  174. uint32_t NumNaf;
  175. Point minus_p;
  176. Point r;
  177. DWORD *modp;
  178. if (keyLength == KEY_LENGTH_DWORDS_P256) {
  179. modp = curve_p256.p;
  180. } else {
  181. modp = curve.p;
  182. }
  183. p_256_init_point(&r);
  184. multiprecision_init(p->z, keyLength);
  185. p->z[0] = 1;
  186. // initialization
  187. p_256_init_point(q);
  188. // -p
  189. multiprecision_copy(minus_p.x, p->x, keyLength);
  190. multiprecision_sub(minus_p.y, modp, p->y, keyLength);
  191. multiprecision_init(minus_p.z, keyLength);
  192. minus_p.z[0] = 1;
  193. // NAF
  194. memset(naf, 0, sizeof(naf));
  195. ECC_NAF(naf, &NumNaf, n, keyLength);
  196. for (int i = NumNaf - 1; i >= 0; i--) {
  197. p_256_copy_point(&r, q);
  198. ECC_Double(q, &r, keyLength);
  199. sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
  200. if (sign == 1) {
  201. p_256_copy_point(&r, q);
  202. ECC_Add(q, &r, p, keyLength);
  203. } else if (sign == 3) {
  204. p_256_copy_point(&r, q);
  205. ECC_Add(q, &r, &minus_p, keyLength);
  206. }
  207. }
  208. multiprecision_inv_mod(minus_p.x, q->z, keyLength);
  209. multiprecision_mersenns_squa_mod(q->z, minus_p.x, keyLength);
  210. multiprecision_mersenns_mult_mod(q->x, q->x, q->z, keyLength);
  211. multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
  212. multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
  213. }
  214. bool ECC_CheckPointIsInElliCur_P256(Point *p)
  215. {
  216. /* y^2 % q */
  217. DWORD y_y_q[KEY_LENGTH_DWORDS_P256] = {0x0};
  218. /* x^2 % q */
  219. DWORD x_x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
  220. /* x % q */
  221. DWORD x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
  222. /* x^2, To prevent overflow, the length of the x square here needs to
  223. be expanded to two times the original one. */
  224. DWORD x_x[2*KEY_LENGTH_DWORDS_P256] = {0x0};
  225. /* y_y_q =(p->y)^2(mod q) */
  226. multiprecision_mersenns_squa_mod(y_y_q, p->y, KEY_LENGTH_DWORDS_P256);
  227. /* Calculate the value of p->x square, x_x = (p->x)^2 */
  228. multiprecision_mult(x_x, p->x, p->x, KEY_LENGTH_DWORDS_P256);
  229. /* The function of the elliptic curve is y^2 = x^3 - 3x + b (mod q) ==>
  230. y^2 = (x^2 - 3)*x + b (mod q),
  231. so we calculate the x^2 - 3 value here */
  232. x_x[0] -= 3;
  233. /* Using math relations. (a*b) % q = ((a%q)*(b%q)) % q ==>
  234. (x^2 - 3)*x = (((x^2 - 3) % q) * x % q) % q */
  235. multiprecision_fast_mod_P256(x_x_q, x_x);
  236. /* x_x = x_x_q * x_q */
  237. multiprecision_mult(x_x, x_x_q, p->x, KEY_LENGTH_DWORDS_P256);
  238. /* x_q = x_x % q */
  239. multiprecision_fast_mod_P256(x_q, x_x);
  240. /* Save the result in x_x_q */
  241. multiprecision_add_mod(x_x_q, x_q, curve_p256.b, KEY_LENGTH_DWORDS_P256);
  242. /* compare the y_y_q and x_x_q, see if they are on a given elliptic curve. */
  243. if (multiprecision_compare(y_y_q, x_x_q, KEY_LENGTH_DWORDS_P256)) {
  244. return false;
  245. } else {
  246. return true;
  247. }
  248. }