pcpeccpmethodcomca.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /*
  2. * Copyright (C) 2016 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include "owndefs.h"
  32. #include "owncp.h"
  33. #include "pcpeccppoint.h"
  34. #include "pcpeccpmethod.h"
  35. #include "pcpeccpmethodcom.h"
  36. #include "pcppma.h"
  37. #include "pcpeccpsscm.h"
  38. static
  39. ECCP_METHOD ECCPcom = {
  40. ECCP_SetPointProjective,
  41. ECCP_SetPointAffine,
  42. ECCP_GetPointAffine,
  43. ECCP_IsPointOnCurve,
  44. ECCP_ComparePoint,
  45. ECCP_NegPoint,
  46. ECCP_DblPoint,
  47. ECCP_AddPoint,
  48. ECCP_MulPoint,
  49. ECCP_MulBasePoint,
  50. ECCP_ProdPoint
  51. };
  52. /*
  53. // Returns reference
  54. */
  55. ECCP_METHOD* ECCPcom_Methods(void)
  56. {
  57. return &ECCPcom;
  58. }
  59. /*
  60. // Copy Point
  61. */
  62. void ECCP_CopyPoint(const IppsECCPPointState* pSrc, IppsECCPPointState* pDst)
  63. {
  64. cpBN_copy(ECP_POINT_X(pDst), ECP_POINT_X(pSrc));
  65. cpBN_copy(ECP_POINT_Y(pDst), ECP_POINT_Y(pSrc));
  66. cpBN_copy(ECP_POINT_Z(pDst), ECP_POINT_Z(pSrc));
  67. ECP_POINT_AFFINE(pDst) = ECP_POINT_AFFINE(pSrc);
  68. }
  69. /*
  70. // ECCP_PoinSettProjective
  71. // Converts regular projective triplet (pX,pY,pZ) into pPoint
  72. // (see note above)
  73. */
  74. void ECCP_SetPointProjective(const IppsBigNumState* pX,
  75. const IppsBigNumState* pY,
  76. const IppsBigNumState* pZ,
  77. IppsECCPPointState* pPoint,
  78. const IppsECCPState* pECC)
  79. {
  80. IppsMontState* pMont = ECP_PMONT(pECC);
  81. PMA_enc(ECP_POINT_X(pPoint), (IppsBigNumState*)pX, pMont);
  82. PMA_enc(ECP_POINT_Y(pPoint), (IppsBigNumState*)pY, pMont);
  83. PMA_enc(ECP_POINT_Z(pPoint), (IppsBigNumState*)pZ, pMont);
  84. ECP_POINT_AFFINE(pPoint) = cpBN_cmp(pZ, BN_ONE_REF())==0;
  85. }
  86. /*
  87. // ECCP_PointAffineSet
  88. // Converts regular affine pair (pX,pY) into pPoint
  89. */
  90. void ECCP_SetPointAffine(const IppsBigNumState* pX,
  91. const IppsBigNumState* pY,
  92. IppsECCPPointState* pPoint,
  93. const IppsECCPState* pECC)
  94. {
  95. IppsMontState* pMont = ECP_PMONT(pECC);
  96. PMA_enc(ECP_POINT_X(pPoint), (IppsBigNumState*)pX, pMont);
  97. PMA_enc(ECP_POINT_Y(pPoint), (IppsBigNumState*)pY, pMont);
  98. PMA_enc(ECP_POINT_Z(pPoint), (IppsBigNumState*)cpBN_OneRef(), pMont);
  99. ECP_POINT_AFFINE(pPoint) = 1;
  100. }
  101. /*
  102. // ECCP_GetPointAffine
  103. //
  104. // Converts pPoint into regular affine pair (pX,pY)
  105. //
  106. // Note:
  107. // pPoint is not point at Infinity
  108. // transform (X, Y, Z) into (x, y) = (X/Z^2, Y/Z^3)
  109. */
  110. void ECCP_GetPointAffine(IppsBigNumState* pX, IppsBigNumState* pY,
  111. const IppsECCPPointState* pPoint,
  112. const IppsECCPState* pECC,
  113. BigNumNode* pList)
  114. {
  115. IppsMontState* pMont = ECP_PMONT(pECC);
  116. /* case Z == 1 */
  117. if( ECP_POINT_AFFINE(pPoint) ) {
  118. if(pX) {
  119. PMA_dec(pX, ECP_POINT_X(pPoint), pMont);
  120. }
  121. if(pY) {
  122. PMA_dec(pY, ECP_POINT_Y(pPoint), pMont);
  123. }
  124. }
  125. /* case Z != 1 */
  126. else {
  127. IppsBigNumState* pT = cpBigNumListGet(&pList);
  128. IppsBigNumState* pU = cpBigNumListGet(&pList);
  129. IppsBigNumState* pModulo = ECP_PRIME(pECC);
  130. /* decode Z */
  131. PMA_dec(pU, ECP_POINT_Z(pPoint), pMont);
  132. /* regular T = Z^-1 */
  133. PMA_inv(pT, pU, pModulo);
  134. /* montgomery U = Z^-1 */
  135. PMA_enc(pU, pT, pMont);
  136. /* regular T = Z^-2 */
  137. PMA_mule(pT, pU, pT, pMont);
  138. if(pX) {
  139. PMA_mule(pX,pT, ECP_POINT_X(pPoint), pMont);
  140. }
  141. if(pY) {
  142. /* regular U = Z^-3 */
  143. PMA_mule(pU, pU, pT, pMont);
  144. PMA_mule(pY,pU, ECP_POINT_Y(pPoint), pMont);
  145. }
  146. }
  147. }
  148. /*
  149. // ECCP_SetPointToInfinity
  150. // ECCP_SetPointToAffineInfinity0
  151. // ECCP_SetPointToAffineInfinity1
  152. //
  153. // Set point to Infinity
  154. */
  155. void ECCP_SetPointToInfinity(IppsECCPPointState* pPoint)
  156. {
  157. cpBN_zero(ECP_POINT_X(pPoint));
  158. cpBN_zero(ECP_POINT_Y(pPoint));
  159. cpBN_zero(ECP_POINT_Z(pPoint));
  160. ECP_POINT_AFFINE(pPoint) = 0;
  161. }
  162. void ECCP_SetPointToAffineInfinity0(IppsBigNumState* pX, IppsBigNumState* pY)
  163. {
  164. if(pX) cpBN_zero(pX);
  165. if(pY) cpBN_zero(pY);
  166. }
  167. void ECCP_SetPointToAffineInfinity1(IppsBigNumState* pX, IppsBigNumState* pY)
  168. {
  169. if(pX) cpBN_zero(pX);
  170. if(pY) BN_Word(pY,1);
  171. }
  172. /*
  173. // ECCP_IsPointAtInfinity
  174. // ECCP_IsPointAtAffineInfinity0
  175. // ECCP_IsPointAtAffineInfinity1
  176. //
  177. // Test point is at Infinity
  178. */
  179. int ECCP_IsPointAtInfinity(const IppsECCPPointState* pPoint)
  180. {
  181. return IsZero_BN( ECP_POINT_Z(pPoint) );
  182. }
  183. int ECCP_IsPointAtAffineInfinity0(const IppsBigNumState* pX, const IppsBigNumState* pY)
  184. {
  185. return IsZero_BN(pX) && IsZero_BN(pY);
  186. }
  187. int ECCP_IsPointAtAffineInfinity1(const IppsBigNumState* pX, const IppsBigNumState* pY)
  188. {
  189. return IsZero_BN(pX) && !IsZero_BN(pY);
  190. }
  191. /*
  192. // ECCP_IsPointOnCurve
  193. //
  194. // Test point is lie on curve
  195. //
  196. // Note
  197. // We deal with equation: y^2 = x^3 + A*x + B.
  198. // Or in projective coordinates: Y^2 = X^3 + a*X*Z^4 + b*Z^6.
  199. // The point under test is given by projective triplet (X,Y,Z),
  200. // which represents actually (x,y) = (X/Z^2,Y/Z^3).
  201. */
  202. int ECCP_IsPointOnCurve(const IppsECCPPointState* pPoint,
  203. const IppsECCPState* pECC,
  204. BigNumNode* pList)
  205. {
  206. /* let think Infinity point is on the curve */
  207. if( ECCP_IsPointAtInfinity(pPoint) )
  208. return 1;
  209. else {
  210. IppsMontState* pMont = ECP_PMONT(pECC);
  211. IppsBigNumState* pR = cpBigNumListGet(&pList);
  212. IppsBigNumState* pT = cpBigNumListGet(&pList);
  213. IppsBigNumState* pModulo = ECP_PRIME(pECC);
  214. PMA_sqre(pR, ECP_POINT_X(pPoint), pMont); // R = X^3
  215. PMA_mule(pR, pR, ECP_POINT_X(pPoint), pMont);
  216. /* case Z != 1 */
  217. if( !ECP_POINT_AFFINE(pPoint) ) {
  218. IppsBigNumState* pZ4 = cpBigNumListGet(&pList);
  219. IppsBigNumState* pZ6 = cpBigNumListGet(&pList);
  220. PMA_sqre(pT, ECP_POINT_Z(pPoint), pMont); // Z^2
  221. PMA_sqre(pZ4, pT, pMont); // Z^4
  222. PMA_mule(pZ6, pZ4, pT, pMont); // Z^6
  223. PMA_mule(pT, pZ4, ECP_POINT_X(pPoint), pMont); // T = X*Z^4
  224. if( ECP_AMI3(pECC) ) {
  225. IppsBigNumState* pU = cpBigNumListGet(&pList);
  226. PMA_add(pU, pT, pT, pModulo); // R = X^3 +a*X*Z^4
  227. PMA_add(pU, pU, pT, pModulo);
  228. PMA_sub(pR, pR, pU, pModulo);
  229. }
  230. else {
  231. PMA_mule(pT, pT, ECP_AENC(pECC), pMont); // R = X^3 +a*X*Z^4
  232. PMA_add(pR, pR, pT, pModulo);
  233. }
  234. PMA_mule(pT, pZ6, ECP_BENC(pECC), pMont); // R = X^3 +a*X*Z^4 + b*Z^6
  235. PMA_add(pR, pR, pT, pModulo);
  236. }
  237. /* case Z == 1 */
  238. else {
  239. if( ECP_AMI3(pECC) ) {
  240. PMA_add(pT, ECP_POINT_X(pPoint), ECP_POINT_X(pPoint), pModulo); // R = X^3 +a*X
  241. PMA_add(pT, pT, ECP_POINT_X(pPoint), pModulo);
  242. PMA_sub(pR, pR, pT, pModulo);
  243. }
  244. else {
  245. PMA_mule(pT, ECP_POINT_X(pPoint), ECP_AENC(pECC), pMont); // R = X^3 +a*X
  246. PMA_add(pR, pR, pT, pModulo);
  247. }
  248. PMA_add(pR, pR, ECP_BENC(pECC), pModulo); // R = X^3 +a*X + b
  249. }
  250. PMA_sqre(pT, ECP_POINT_Y(pPoint), pMont); // T = Y^2
  251. return 0==cpBN_cmp(pR, pT);
  252. }
  253. }
  254. /*
  255. // ECCP_ComparePoint
  256. //
  257. // Compare two points:
  258. // returns 0 => pP==pQ (maybe both pP and pQ are at Infinity)
  259. // returns 1 => pP!=pQ
  260. //
  261. // Note
  262. // In general we check:
  263. // P_X*Q_Z^2 ~ Q_X*P_Z^2
  264. // P_Y*Q_Z^3 ~ Q_Y*P_Z^3
  265. */
  266. int ECCP_ComparePoint(const IppsECCPPointState* pP,
  267. const IppsECCPPointState* pQ,
  268. const IppsECCPState* pECC,
  269. BigNumNode* pList)
  270. {
  271. /* P or/and Q at Infinity */
  272. if( ECCP_IsPointAtInfinity(pP) )
  273. return ECCP_IsPointAtInfinity(pQ)? 0:1;
  274. if( ECCP_IsPointAtInfinity(pQ) )
  275. return ECCP_IsPointAtInfinity(pP)? 0:1;
  276. /* (P_Z==1) && (Q_Z==1) */
  277. if( ECP_POINT_AFFINE(pP) && ECP_POINT_AFFINE(pQ) )
  278. return ((0==cpBN_cmp(ECP_POINT_X(pP),ECP_POINT_X(pQ))) && (0==cpBN_cmp(ECP_POINT_Y(pP),ECP_POINT_Y(pQ))))? 0:1;
  279. {
  280. IppsMontState* pMont = ECP_PMONT(pECC);
  281. IppsBigNumState* pPtmp = cpBigNumListGet(&pList);
  282. IppsBigNumState* pQtmp = cpBigNumListGet(&pList);
  283. IppsBigNumState* pPZ = cpBigNumListGet(&pList);
  284. IppsBigNumState* pQZ = cpBigNumListGet(&pList);
  285. /* P_X*Q_Z^2 ~ Q_X*P_Z^2 */
  286. if( !ECP_POINT_AFFINE(pQ) ) {
  287. PMA_sqre(pQZ, ECP_POINT_Z(pQ), pMont); /* Ptmp = P_X*Q_Z^2 */
  288. PMA_mule(pPtmp, ECP_POINT_X(pP), pQZ, pMont);
  289. }
  290. else {
  291. PMA_set(pPtmp, ECP_POINT_X(pP));
  292. }
  293. if( !ECP_POINT_AFFINE(pP) ) {
  294. PMA_sqre(pPZ, ECP_POINT_Z(pP), pMont); /* Qtmp = Q_X*P_Z^2 */
  295. PMA_mule(pQtmp, ECP_POINT_X(pQ), pPZ, pMont);
  296. }
  297. else {
  298. PMA_set(pQtmp, ECP_POINT_X(pQ));
  299. }
  300. if ( cpBN_cmp(pPtmp, pQtmp) )
  301. return 1; /* points are different: (P_X*Q_Z^2) != (Q_X*P_Z^2) */
  302. /* P_Y*Q_Z^3 ~ Q_Y*P_Z^3 */
  303. if( !ECP_POINT_AFFINE(pQ) ) {
  304. PMA_mule(pQZ, pQZ, ECP_POINT_Z(pQ), pMont); /* Ptmp = P_Y*Q_Z^3 */
  305. PMA_mule(pPtmp, ECP_POINT_Y(pP), pQZ, pMont);
  306. }
  307. else {
  308. PMA_set(pPtmp, ECP_POINT_Y(pP));
  309. }
  310. if( !ECP_POINT_AFFINE(pP) ) {
  311. PMA_mule(pPZ, pPZ, ECP_POINT_Z(pP), pMont); /* Qtmp = Q_Y*P_Z^3 */
  312. PMA_mule(pQtmp, ECP_POINT_Y(pQ), pPZ, pMont);
  313. }
  314. else {
  315. PMA_set(pQtmp, ECP_POINT_Y(pQ));
  316. }
  317. return cpBN_cmp(pPtmp, pQtmp)? 1:0;
  318. }
  319. }
  320. /*
  321. // ECCP_NegPoint
  322. //
  323. // Negative point
  324. */
  325. void ECCP_NegPoint(const IppsECCPPointState* pP,
  326. IppsECCPPointState* pR,
  327. const IppsECCPState* pECC)
  328. {
  329. /* test point at Infinity */
  330. if( ECCP_IsPointAtInfinity(pP) )
  331. ECCP_SetPointToInfinity(pR);
  332. else {
  333. IppsBigNumState* pModulo = ECP_PRIME(pECC);
  334. if( pP!=pR ) {
  335. PMA_set(ECP_POINT_X(pR), ECP_POINT_X(pP));
  336. PMA_set(ECP_POINT_Z(pR), ECP_POINT_Z(pP));
  337. }
  338. PMA_sub(ECP_POINT_Y(pR), pModulo, ECP_POINT_Y(pP), pModulo);
  339. ECP_POINT_AFFINE(pR) = ECP_POINT_AFFINE(pP);
  340. }
  341. }
  342. /*
  343. // ECCP_DblPoint
  344. //
  345. // Double point
  346. */
  347. void ECCP_DblPoint(const IppsECCPPointState* pP,
  348. IppsECCPPointState* pR,
  349. const IppsECCPState* pECC,
  350. BigNumNode* pList)
  351. {
  352. /* P at infinity */
  353. if( ECCP_IsPointAtInfinity(pP) )
  354. ECCP_SetPointToInfinity(pR);
  355. else {
  356. IppsMontState* pMont = ECP_PMONT(pECC);
  357. IppsBigNumState* bnV = cpBigNumListGet(&pList);
  358. IppsBigNumState* bnU = cpBigNumListGet(&pList);
  359. IppsBigNumState* bnM = cpBigNumListGet(&pList);
  360. IppsBigNumState* bnS = cpBigNumListGet(&pList);
  361. IppsBigNumState* bnT = cpBigNumListGet(&pList);
  362. IppsBigNumState* pModulo = ECP_PRIME(pECC);
  363. /* M = 3*X^2 + A*Z^4 */
  364. if( ECP_POINT_AFFINE(pP) ) {
  365. PMA_sqre(bnU, ECP_POINT_X(pP), pMont);
  366. PMA_add(bnM, bnU, bnU, pModulo);
  367. PMA_add(bnM, bnM, bnU, pModulo);
  368. PMA_add(bnM, bnM, ECP_AENC(pECC), pModulo);
  369. }
  370. else if( ECP_AMI3(pECC) ) {
  371. PMA_sqre(bnU, ECP_POINT_Z(pP), pMont);
  372. PMA_add(bnS, ECP_POINT_X(pP), bnU, pModulo);
  373. PMA_sub(bnT, ECP_POINT_X(pP), bnU, pModulo);
  374. PMA_mule(bnM, bnS, bnT, pMont);
  375. PMA_add(bnU, bnM, bnM, pModulo);
  376. PMA_add(bnM, bnU, bnM, pModulo);
  377. }
  378. else {
  379. PMA_sqre(bnU, ECP_POINT_X(pP), pMont);
  380. PMA_add(bnM, bnU, bnU, pModulo);
  381. PMA_add(bnM, bnM, bnU, pModulo);
  382. PMA_sqre(bnU, ECP_POINT_Z(pP), pMont);
  383. PMA_sqre(bnU, bnU, pMont);
  384. PMA_mule(bnU, bnU, ECP_AENC(pECC), pMont);
  385. PMA_add(bnM, bnM, bnU, pModulo);
  386. }
  387. PMA_add(bnV, ECP_POINT_Y(pP), ECP_POINT_Y(pP), pModulo);
  388. /* R_Z = 2*Y*Z */
  389. if( ECP_POINT_AFFINE(pP) ) {
  390. PMA_set(ECP_POINT_Z(pR), bnV);
  391. }
  392. else {
  393. PMA_mule(ECP_POINT_Z(pR), bnV, ECP_POINT_Z(pP), pMont);
  394. }
  395. /* S = 4*X*Y^2 */
  396. PMA_sqre(bnT, bnV, pMont);
  397. PMA_mule(bnS, bnT, ECP_POINT_X(pP), pMont);
  398. /* R_X = M^2 - 2*S */
  399. PMA_sqre(bnU, bnM, pMont);
  400. PMA_sub(bnU, bnU, bnS, pModulo);
  401. PMA_sub(ECP_POINT_X(pR), bnU, bnS, pModulo);
  402. /* T = 8*Y^4 */
  403. PMA_mule(bnV, bnV, ECP_POINT_Y(pP), pMont);
  404. PMA_mule(bnT, bnT, bnV, pMont);
  405. /* R_Y = M*(S - R_X) - T */
  406. PMA_sub(bnS, bnS, ECP_POINT_X(pR), pModulo);
  407. PMA_mule(bnS, bnS, bnM, pMont);
  408. PMA_sub(ECP_POINT_Y(pR), bnS, bnT, pModulo);
  409. ECP_POINT_AFFINE(pR) = 0;
  410. }
  411. }
  412. /*
  413. // ECCP_AddPoint
  414. //
  415. // Add points
  416. */
  417. void ECCP_AddPoint(const IppsECCPPointState* pP,
  418. const IppsECCPPointState* pQ,
  419. IppsECCPPointState* pR,
  420. const IppsECCPState* pECC,
  421. BigNumNode* pList)
  422. {
  423. /* prevent operation with point at Infinity */
  424. if( ECCP_IsPointAtInfinity(pP) ) {
  425. ECCP_CopyPoint(pQ, pR);
  426. return;
  427. }
  428. if( ECCP_IsPointAtInfinity(pQ) ) {
  429. ECCP_CopyPoint(pP, pR);
  430. return;
  431. }
  432. /*
  433. // addition
  434. */
  435. {
  436. IppsMontState* pMont = ECP_PMONT(pECC);
  437. IppsBigNumState* bnU0 = cpBigNumListGet(&pList);
  438. IppsBigNumState* bnS0 = cpBigNumListGet(&pList);
  439. IppsBigNumState* bnU1 = cpBigNumListGet(&pList);
  440. IppsBigNumState* bnS1 = cpBigNumListGet(&pList);
  441. IppsBigNumState* bnW = cpBigNumListGet(&pList);
  442. IppsBigNumState* bnR = cpBigNumListGet(&pList);
  443. IppsBigNumState *bnT = bnU0;
  444. IppsBigNumState *bnM = bnS0;
  445. IppsBigNumState* pModulo = ECP_PRIME(pECC);
  446. /* U0 = P_X * Q_Z^2 */
  447. /* S0 = P_Y * Q_Z^3 */
  448. if( ECP_POINT_AFFINE(pQ) ) {
  449. PMA_set(bnU0, ECP_POINT_X(pP));
  450. PMA_set(bnS0, ECP_POINT_Y(pP));
  451. }
  452. else {
  453. PMA_sqre(bnW, ECP_POINT_Z(pQ), pMont);
  454. PMA_mule(bnU0,ECP_POINT_X(pP), bnW, pMont);
  455. PMA_mule(bnW, ECP_POINT_Z(pQ), bnW, pMont);
  456. PMA_mule(bnS0,ECP_POINT_Y(pP), bnW, pMont);
  457. }
  458. /* U1 = Q_X * P_Z^2 */
  459. /* S1 = Q_Y * P_Z^3 */
  460. if( ECP_POINT_AFFINE(pP) ) {
  461. PMA_set(bnU1, ECP_POINT_X(pQ));
  462. PMA_set(bnS1, ECP_POINT_Y(pQ));
  463. }
  464. else {
  465. PMA_sqre(bnW, ECP_POINT_Z(pP), pMont);
  466. PMA_mule(bnU1,ECP_POINT_X(pQ), bnW, pMont);
  467. PMA_mule(bnW, ECP_POINT_Z(pP), bnW, pMont);
  468. PMA_mule(bnS1,ECP_POINT_Y(pQ), bnW, pMont);
  469. }
  470. /* W = U0-U1 */
  471. /* R = S0-S1 */
  472. PMA_sub(bnW, bnU0, bnU1, pModulo);
  473. PMA_sub(bnR, bnS0, bnS1, pModulo);
  474. if( IsZero_BN(bnW) ) {
  475. if( IsZero_BN(bnR) ) {
  476. ECCP_DblPoint(pP, pR, pECC, pList);
  477. return;
  478. }
  479. else {
  480. ECCP_SetPointToInfinity(pR);
  481. return;
  482. }
  483. }
  484. /* T = U0+U1 */
  485. /* M = S0+S1 */
  486. PMA_add(bnT, bnU0, bnU1, pModulo);
  487. PMA_add(bnM, bnS0, bnS1, pModulo);
  488. /* R_Z = P_Z * Q_Z * W */
  489. if( ECP_POINT_AFFINE(pQ) && ECP_POINT_AFFINE(pP) ) {
  490. PMA_set(ECP_POINT_Z(pR), bnW);
  491. }
  492. else {
  493. if( ECP_POINT_AFFINE(pQ) ) {
  494. PMA_set(bnU1, ECP_POINT_Z(pP));
  495. }
  496. else if( ECP_POINT_AFFINE(pP) ) {
  497. PMA_set(bnU1, ECP_POINT_Z(pQ));
  498. }
  499. else {
  500. PMA_mule(bnU1, ECP_POINT_Z(pP), ECP_POINT_Z(pQ), pMont);
  501. }
  502. PMA_mule(ECP_POINT_Z(pR), bnU1, bnW, pMont);
  503. }
  504. PMA_sqre(bnU1, bnW, pMont); /* U1 = W^2 */
  505. PMA_mule(bnS1, bnT, bnU1, pMont); /* S1 = T * W^2 */
  506. /* R_X = R^2 - T * W^2 */
  507. PMA_sqre(ECP_POINT_X(pR), bnR, pMont);
  508. PMA_sub(ECP_POINT_X(pR), ECP_POINT_X(pR), bnS1, pModulo);
  509. /* V = T * W^2 - 2 * R_X (S1) */
  510. PMA_sub(bnS1, bnS1, ECP_POINT_X(pR), pModulo);
  511. PMA_sub(bnS1, bnS1, ECP_POINT_X(pR), pModulo);
  512. /* R_Y = (V * R - M * W^3) /2 */
  513. PMA_mule(ECP_POINT_Y(pR), bnS1, bnR, pMont);
  514. PMA_mule(bnU1, bnU1, bnW, pMont);
  515. PMA_mule(bnU1, bnU1, bnM, pMont);
  516. PMA_sub(bnU1, ECP_POINT_Y(pR), bnU1, pModulo);
  517. PMA_div2(ECP_POINT_Y(pR), bnU1, pModulo);
  518. ECP_POINT_AFFINE(pR) = 0;
  519. }
  520. }
  521. /*
  522. // ECCP_MulPoint
  523. //
  524. // Multiply point by scalar
  525. */
  526. void ECCP_MulPoint(const IppsECCPPointState* pP,
  527. const IppsBigNumState* bnN,
  528. IppsECCPPointState* pR,
  529. const IppsECCPState* pECC,
  530. BigNumNode* pList)
  531. {
  532. /* test zero scalar or input point at Infinity */
  533. if( IsZero_BN(bnN) || ECCP_IsPointAtInfinity(pP) ) {
  534. ECCP_SetPointToInfinity(pR);
  535. return;
  536. }
  537. /*
  538. // scalar multiplication
  539. */
  540. else {
  541. Ipp8u* pScratchAligned = ECP_SCCMBUFF(pECC);
  542. BNU_CHUNK_T* pN = BN_NUMBER(bnN);
  543. cpSize nsN = BN_SIZE(bnN);
  544. /* scalar bitsize */
  545. int scalarBitSize = BITSIZE_BNU(pN, nsN);
  546. /* optimal size of window */
  547. int w = cpECCP_OptimalWinSize(scalarBitSize);
  548. /* number of table entries */
  549. int nPrecomputed = 1<<w;
  550. /* allocate temporary scalar */
  551. IppsBigNumState* bnTN = cpBigNumListGet(&pList);
  552. BNU_CHUNK_T* pTN = BN_NUMBER(bnTN);
  553. int coordSize = BITS_BNU_CHUNK(ECP_GFEBITS(pECC));
  554. IppsECCPPointState T;
  555. ECP_POINT_X(&T) = cpBigNumListGet(&pList);
  556. ECP_POINT_Y(&T) = cpBigNumListGet(&pList);
  557. ECP_POINT_Z(&T) = cpBigNumListGet(&pList);
  558. ECCP_SetPointToInfinity(&T);
  559. /* init result */
  560. ECCP_CopyPoint(pP, pR);
  561. if( ippBigNumNEG == BN_SIGN(bnN) )
  562. ECCP_NegPoint(pR, pR, pECC);
  563. /* pre-compute auxiliary table t[] = {(2^w)*P, 1*P, 2*P, ..., (2^(w-1))*P} */
  564. {
  565. int n;
  566. for(n=1; n<nPrecomputed; n++) {
  567. ECCP_AddPoint(pR, &T, &T, pECC, pList);
  568. cpECCP_ScramblePut(pScratchAligned+n, nPrecomputed, &T, coordSize);
  569. }
  570. ECCP_AddPoint(pR, &T, &T, pECC, pList);
  571. cpECCP_ScramblePut(pScratchAligned, nPrecomputed, &T, coordSize);
  572. }
  573. /* copy scalar */
  574. cpCpy_BNU(pTN, pN, nsN);
  575. /* and convert it presentaion to avoid usage of O point */
  576. scalarBitSize = cpECCP_ConvertRepresentation(pTN, scalarBitSize, w);
  577. /* prepare temporary scalar for processing */
  578. pTN[BITS_BNU_CHUNK(scalarBitSize)] = 0;
  579. scalarBitSize = ((scalarBitSize+w-1)/w)*w;
  580. /*
  581. // scalar multiplication
  582. */
  583. {
  584. Ipp32u dmask = nPrecomputed-1;
  585. /* position (bit number) of the leftmost window */
  586. int wPosition = scalarBitSize-w;
  587. /* extract leftmost window value */
  588. Ipp32u eChunk = *((Ipp32u*)((Ipp16u*)pTN + wPosition/BITSIZE(Ipp16u)));
  589. int shift = wPosition & 0xF;
  590. Ipp32u windowVal = (eChunk>>shift) & dmask;
  591. /* initialize result (ECP_FINITE_POINT|ECP_PROJECTIVE) */
  592. cpECCP_ScrambleGet(pR, coordSize, pScratchAligned+windowVal, nPrecomputed);
  593. ECP_POINT_AFFINE(pR) = 0;
  594. /* initialize temporary T (ECP_PROJECTIVE) */
  595. ECP_POINT_AFFINE(&T) = 0;
  596. for(wPosition-=w; wPosition>=0; wPosition-=w) {
  597. /* w times doubling */
  598. int k;
  599. for(k=0; k<w; k++)
  600. ECCP_DblPoint(pR, pR, pECC, pList);
  601. /* extract next window value */
  602. eChunk = *((Ipp32u*)((Ipp16u*)pTN + wPosition/BITSIZE(Ipp16u)));
  603. shift = wPosition & 0xF;
  604. windowVal = (eChunk>>shift) & dmask;
  605. /* extract value from the pre-computed table */
  606. cpECCP_ScrambleGet(&T, coordSize, pScratchAligned+windowVal, nPrecomputed);
  607. /* and add it */
  608. ECCP_AddPoint(pR, &T, pR, pECC, pList);
  609. }
  610. }
  611. }
  612. }
  613. void ECCP_MulBasePoint(const IppsBigNumState* pK,
  614. IppsECCPPointState* pR,
  615. const IppsECCPState* pECC,
  616. BigNumNode* pList)
  617. {
  618. ECCP_MulPoint(ECP_GENC(pECC), pK, pR, pECC, pList);
  619. }
  620. /*
  621. // ECCP_ProdPoint
  622. //
  623. // Point product
  624. */
  625. void ECCP_ProdPoint(const IppsECCPPointState* pP,
  626. const IppsBigNumState* bnPscalar,
  627. const IppsECCPPointState* pQ,
  628. const IppsBigNumState* bnQscalar,
  629. IppsECCPPointState* pR,
  630. const IppsECCPState* pECC,
  631. BigNumNode* pList)
  632. {
  633. IppsECCPPointState T;
  634. IppsECCPPointState U;
  635. ECP_POINT_X(&T) = cpBigNumListGet(&pList);
  636. ECP_POINT_Y(&T) = cpBigNumListGet(&pList);
  637. ECP_POINT_Z(&T) = cpBigNumListGet(&pList);
  638. ECP_POINT_X(&U) = cpBigNumListGet(&pList);
  639. ECP_POINT_Y(&U) = cpBigNumListGet(&pList);
  640. ECP_POINT_Z(&U) = cpBigNumListGet(&pList);
  641. ECCP_MulPoint(pP, bnPscalar, &T, (IppsECCPState*)pECC, pList);
  642. ECCP_MulPoint(pQ, bnQscalar, &U, (IppsECCPState*)pECC, pList);
  643. ECCP_AddPoint(&T, &U, pR, pECC, pList);
  644. }