p_256_multprecision.c 14 KB

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