p_256_multprecision.cc 13 KB

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