finitefield.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  1. /*############################################################################
  2. # Copyright 2016-2017 Intel Corporation
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################*/
  16. /*!
  17. * \file
  18. * \brief Finite field implementation.
  19. */
  20. #include "epid/common/math/finitefield.h"
  21. #include <limits.h>
  22. #include <stdint.h>
  23. #include <string.h>
  24. #include "epid/common/math/src/finitefield-internal.h"
  25. #include "epid/common/src/memory.h"
  26. #ifndef MIN
  27. /// Evaluate to minimum of two values
  28. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  29. #endif // MIN
  30. /// Number of leading zero bits in 32 bit integer x.
  31. static size_t Nlz32(uint32_t x) {
  32. size_t nlz = sizeof(x) * 8;
  33. if (x) {
  34. nlz = 0;
  35. if (0 == (x & 0xFFFF0000)) {
  36. nlz += 16;
  37. x <<= 16;
  38. }
  39. if (0 == (x & 0xFF000000)) {
  40. nlz += 8;
  41. x <<= 8;
  42. }
  43. if (0 == (x & 0xF0000000)) {
  44. nlz += 4;
  45. x <<= 4;
  46. }
  47. if (0 == (x & 0xC0000000)) {
  48. nlz += 2;
  49. x <<= 2;
  50. }
  51. if (0 == (x & 0x80000000)) {
  52. nlz++;
  53. }
  54. }
  55. return nlz;
  56. }
  57. /// Bit size of bit number representated as array of Ipp32u.
  58. #define BNU_BITSIZE(bnu, len) \
  59. ((len) * sizeof(Ipp32u) * 8 - Nlz32((bnu)[(len)-1]))
  60. /// Convert bit size to byte size
  61. #define BIT2BYTE_SIZE(bits) (((bits) + 7) >> 3)
  62. EpidStatus NewFiniteField(BigNumStr const* prime, FiniteField** ff) {
  63. EpidStatus result = kEpidErr;
  64. IppsGFpState* ipp_finitefield_ctx = NULL;
  65. FiniteField* finitefield_ptr = NULL;
  66. BigNum* prime_bn = NULL;
  67. do {
  68. EpidStatus status = kEpidErr;
  69. IppStatus sts = ippStsNoErr;
  70. Ipp32u bnu[sizeof(BigNumStr) / sizeof(Ipp32u)];
  71. int bnu_size;
  72. int bit_size = CHAR_BIT * sizeof(BigNumStr);
  73. int state_size_in_bytes = 0;
  74. if (!prime || !ff) {
  75. result = kEpidBadArgErr;
  76. break;
  77. }
  78. bit_size = (int)OctStrBitSize(prime->data.data, sizeof(prime->data.data));
  79. bnu_size = OctStr2Bnu(bnu, prime, sizeof(*prime));
  80. if (bnu_size < 0) {
  81. result = kEpidMathErr;
  82. break;
  83. }
  84. // skip high order zeros from BNU
  85. while (bnu_size > 1 && 0 == bnu[bnu_size - 1]) {
  86. bnu_size--;
  87. }
  88. // Determine the memory requirement for finite field context
  89. sts = ippsGFpGetSize(bit_size, &state_size_in_bytes);
  90. if (ippStsNoErr != sts) {
  91. if (ippStsSizeErr == sts) {
  92. result = kEpidBadArgErr;
  93. } else {
  94. result = kEpidMathErr;
  95. }
  96. break;
  97. }
  98. // Allocate space for ipp bignum context
  99. ipp_finitefield_ctx = (IppsGFpState*)SAFE_ALLOC(state_size_in_bytes);
  100. if (!ipp_finitefield_ctx) {
  101. result = kEpidMemAllocErr;
  102. break;
  103. }
  104. status = NewBigNum(sizeof(BigNumStr), &prime_bn);
  105. if (kEpidNoErr != status) {
  106. result = kEpidMathErr;
  107. break;
  108. }
  109. status = ReadBigNum(prime, sizeof(BigNumStr), prime_bn);
  110. if (kEpidNoErr != status) {
  111. result = kEpidMathErr;
  112. break;
  113. }
  114. // Initialize ipp finite field context
  115. sts = ippsGFpInit(prime_bn->ipp_bn, bit_size, ippsGFpMethod_pArb(),
  116. ipp_finitefield_ctx);
  117. if (ippStsNoErr != sts) {
  118. if (ippStsSizeErr == sts) {
  119. result = kEpidBadArgErr;
  120. } else {
  121. result = kEpidMathErr;
  122. }
  123. break;
  124. }
  125. finitefield_ptr = (FiniteField*)SAFE_ALLOC(sizeof(FiniteField));
  126. if (!finitefield_ptr) {
  127. result = kEpidMemAllocErr;
  128. break;
  129. }
  130. finitefield_ptr->element_strlen_required =
  131. BIT2BYTE_SIZE(BNU_BITSIZE(bnu, bnu_size));
  132. finitefield_ptr->modulus_0 = prime_bn;
  133. finitefield_ptr->basic_degree = 1;
  134. finitefield_ptr->ground_degree = 1;
  135. finitefield_ptr->element_len = bnu_size;
  136. finitefield_ptr->ground_ff = NULL;
  137. finitefield_ptr->ipp_ff = ipp_finitefield_ctx;
  138. *ff = finitefield_ptr;
  139. result = kEpidNoErr;
  140. } while (0);
  141. if (kEpidNoErr != result) {
  142. SAFE_FREE(finitefield_ptr);
  143. SAFE_FREE(prime_bn);
  144. SAFE_FREE(ipp_finitefield_ctx);
  145. }
  146. return result;
  147. }
  148. EpidStatus NewFiniteFieldViaBinomalExtension(FiniteField const* ground_field,
  149. FfElement const* ground_element,
  150. int degree, FiniteField** ff) {
  151. EpidStatus result = kEpidErr;
  152. IppsGFpState* ipp_finitefield_ctx = NULL;
  153. IppOctStr ff_elem_str = NULL;
  154. FiniteField* finitefield_ptr = NULL;
  155. BigNum* modulus_0 = NULL;
  156. do {
  157. EpidStatus status = kEpidErr;
  158. IppStatus sts = ippStsNoErr;
  159. int state_size_in_bytes = 0;
  160. if (!ground_field || !ground_element || !ff) {
  161. result = kEpidBadArgErr;
  162. break;
  163. } else if (degree < 2 || !ground_field->ipp_ff ||
  164. !ground_element->ipp_ff_elem) {
  165. result = kEpidBadArgErr;
  166. break;
  167. }
  168. // Determine the memory requirement for finite field context
  169. sts = ippsGFpxGetSize(ground_field->ipp_ff, degree, &state_size_in_bytes);
  170. if (ippStsNoErr != sts) {
  171. if (ippStsSizeErr == sts) {
  172. result = kEpidBadArgErr;
  173. } else {
  174. result = kEpidMathErr;
  175. }
  176. break;
  177. }
  178. // Allocate space for ipp finite field context
  179. ipp_finitefield_ctx = (IppsGFpState*)SAFE_ALLOC(state_size_in_bytes);
  180. if (!ipp_finitefield_ctx) {
  181. result = kEpidMemAllocErr;
  182. break;
  183. }
  184. // Initialize ipp binomial extension finite field context
  185. sts = ippsGFpxInitBinomial(
  186. ground_field->ipp_ff, degree, ground_element->ipp_ff_elem,
  187. 2 == degree
  188. ? (3 == ground_field->basic_degree ? ippsGFpxMethod_binom2()
  189. : ippsGFpxMethod_binom2_epid2())
  190. : ippsGFpxMethod_binom3_epid2(),
  191. ipp_finitefield_ctx);
  192. if (ippStsNoErr != sts) {
  193. if (ippStsSizeErr == sts) {
  194. result = kEpidBadArgErr;
  195. } else {
  196. result = kEpidMathErr;
  197. }
  198. break;
  199. }
  200. finitefield_ptr = (FiniteField*)SAFE_ALLOC(sizeof(FiniteField));
  201. if (!finitefield_ptr) {
  202. result = kEpidMemAllocErr;
  203. break;
  204. }
  205. finitefield_ptr->element_strlen_required =
  206. ground_field->element_strlen_required * degree;
  207. ff_elem_str =
  208. (IppOctStr)SAFE_ALLOC(ground_field->element_len * sizeof(Ipp32u));
  209. if (!ff_elem_str) {
  210. result = kEpidMemAllocErr;
  211. break;
  212. }
  213. status = NewBigNum(ground_field->element_len * sizeof(Ipp32u), &modulus_0);
  214. if (kEpidNoErr != status) {
  215. break;
  216. }
  217. if (kEpidNoErr != status) {
  218. result = kEpidMathErr;
  219. break;
  220. }
  221. result =
  222. WriteFfElement((FiniteField*)ground_field, ground_element, ff_elem_str,
  223. ground_field->element_len * sizeof(Ipp32u));
  224. if (kEpidNoErr != result) break;
  225. status = ReadBigNum(ff_elem_str, ground_field->element_len * sizeof(Ipp32u),
  226. modulus_0);
  227. if (kEpidNoErr != status) {
  228. result = kEpidMathErr;
  229. break;
  230. }
  231. finitefield_ptr->basic_degree = ground_field->basic_degree * degree;
  232. finitefield_ptr->ground_degree = degree;
  233. finitefield_ptr->element_len = ground_field->element_len * degree;
  234. finitefield_ptr->modulus_0 = modulus_0;
  235. // Warning: once assigned ground field must never be modified. this was not
  236. // made const
  237. // to allow the FiniteField structure to be used in context when we want to
  238. // modify the parameters.
  239. finitefield_ptr->ground_ff = (FiniteField*)ground_field;
  240. finitefield_ptr->ipp_ff = ipp_finitefield_ctx;
  241. *ff = finitefield_ptr;
  242. result = kEpidNoErr;
  243. } while (0);
  244. SAFE_FREE(ff_elem_str);
  245. if (kEpidNoErr != result) {
  246. SAFE_FREE(finitefield_ptr);
  247. SAFE_FREE(modulus_0);
  248. SAFE_FREE(ipp_finitefield_ctx);
  249. }
  250. return result;
  251. }
  252. EpidStatus NewFiniteFieldViaPolynomialExtension(FiniteField const* ground_field,
  253. BigNumStr const* irr_polynomial,
  254. int degree, FiniteField** ff) {
  255. EpidStatus result = kEpidErr;
  256. IppsGFpState* ipp_finitefield_ctx = NULL;
  257. FiniteField* finitefield_ptr = NULL;
  258. FfElement** ff_elems = NULL;
  259. IppsGFpElement** ff_elems_state = NULL;
  260. BigNum* modulus_0 = NULL;
  261. int i;
  262. do {
  263. EpidStatus status = kEpidErr;
  264. IppStatus sts = ippStsNoErr;
  265. int state_size_in_bytes = 0;
  266. if (!ground_field || !irr_polynomial || !ff) {
  267. result = kEpidBadArgErr;
  268. break;
  269. }
  270. if (degree < 1 || degree > (int)(INT_MAX / sizeof(BigNumStr)) ||
  271. !ground_field->ipp_ff) {
  272. result = kEpidBadArgErr;
  273. break;
  274. }
  275. // Determine the memory requirement for finite field context
  276. sts = ippsGFpxGetSize(ground_field->ipp_ff, degree, &state_size_in_bytes);
  277. if (ippStsNoErr != sts) {
  278. if (ippStsSizeErr == sts) {
  279. result = kEpidBadArgErr;
  280. } else {
  281. result = kEpidMathErr;
  282. }
  283. break;
  284. }
  285. // Allocate space for ipp finite field context
  286. ipp_finitefield_ctx = (IppsGFpState*)SAFE_ALLOC(state_size_in_bytes);
  287. if (!ipp_finitefield_ctx) {
  288. result = kEpidMemAllocErr;
  289. break;
  290. }
  291. ff_elems = (FfElement**)SAFE_ALLOC(sizeof(FfElement*) * degree);
  292. if (!ff_elems) {
  293. result = kEpidMemAllocErr;
  294. break;
  295. }
  296. ff_elems_state =
  297. (IppsGFpElement**)SAFE_ALLOC(sizeof(IppsGFpElement*) * degree);
  298. if (!ff_elems_state) {
  299. result = kEpidMemAllocErr;
  300. break;
  301. }
  302. for (i = 0; i < degree; ++i) {
  303. status = NewFfElement(ground_field, &ff_elems[i]);
  304. if (kEpidNoErr != status) {
  305. result = kEpidMathErr;
  306. break;
  307. }
  308. status = ReadFfElement((FiniteField*)ground_field, &irr_polynomial[i],
  309. sizeof(BigNumStr), ff_elems[i]);
  310. if (kEpidNoErr != status) {
  311. result = kEpidMathErr;
  312. break;
  313. }
  314. ff_elems_state[i] = ff_elems[i]->ipp_ff_elem;
  315. }
  316. // Initialize ipp binomial extension finite field context
  317. sts = ippsGFpxInit(ground_field->ipp_ff, degree,
  318. (const IppsGFpElement* const*)ff_elems_state, degree,
  319. ippsGFpxMethod_com(), ipp_finitefield_ctx);
  320. if (ippStsNoErr != sts) {
  321. if (ippStsSizeErr == sts) {
  322. result = kEpidBadArgErr;
  323. } else {
  324. result = kEpidMathErr;
  325. }
  326. break;
  327. }
  328. status = NewBigNum(sizeof(irr_polynomial[0]), &modulus_0);
  329. if (kEpidNoErr != status) {
  330. break;
  331. }
  332. status =
  333. ReadBigNum(&irr_polynomial[0], sizeof(irr_polynomial[0]), modulus_0);
  334. if (kEpidNoErr != status) {
  335. break;
  336. }
  337. finitefield_ptr = (FiniteField*)SAFE_ALLOC(sizeof(FiniteField));
  338. if (!finitefield_ptr) {
  339. result = kEpidMemAllocErr;
  340. break;
  341. }
  342. finitefield_ptr->element_strlen_required =
  343. ground_field->element_len * sizeof(Ipp32u) * degree;
  344. finitefield_ptr->modulus_0 = modulus_0;
  345. finitefield_ptr->basic_degree = ground_field->basic_degree * degree;
  346. finitefield_ptr->ground_degree = degree;
  347. finitefield_ptr->element_len = ground_field->element_len * degree;
  348. // Warning: once assigned ground field must never be modified. this was not
  349. // made const
  350. // to allow the FiniteField structure to be used in context when we want to
  351. // modify the parameters.
  352. finitefield_ptr->ground_ff = (FiniteField*)ground_field;
  353. finitefield_ptr->ipp_ff = ipp_finitefield_ctx;
  354. *ff = finitefield_ptr;
  355. result = kEpidNoErr;
  356. } while (0);
  357. if (ff_elems != NULL) {
  358. for (i = 0; i < degree; i++) {
  359. DeleteFfElement(&ff_elems[i]);
  360. }
  361. }
  362. SAFE_FREE(ff_elems);
  363. SAFE_FREE(ff_elems_state);
  364. if (kEpidNoErr != result) {
  365. SAFE_FREE(finitefield_ptr);
  366. SAFE_FREE(modulus_0)
  367. SAFE_FREE(ipp_finitefield_ctx);
  368. }
  369. return result;
  370. }
  371. void DeleteFiniteField(FiniteField** ff) {
  372. if (ff) {
  373. if (*ff) {
  374. SAFE_FREE((*ff)->ipp_ff);
  375. DeleteBigNum(&(*ff)->modulus_0);
  376. }
  377. SAFE_FREE((*ff));
  378. }
  379. }
  380. EpidStatus NewFfElement(FiniteField const* ff, FfElement** new_ff_elem) {
  381. EpidStatus result = kEpidErr;
  382. IppsGFpElement* ipp_ff_elem = NULL;
  383. FfElement* ff_elem = NULL;
  384. do {
  385. IppStatus sts = ippStsNoErr;
  386. unsigned int ctxsize = 0;
  387. Ipp32u zero = 0;
  388. // check parameters
  389. if (!ff || !new_ff_elem) {
  390. result = kEpidBadArgErr;
  391. break;
  392. } else if (!ff->ipp_ff) {
  393. result = kEpidBadArgErr;
  394. break;
  395. }
  396. // Determine the memory requirement for finite field element context
  397. sts = ippsGFpElementGetSize(ff->ipp_ff, (int*)&ctxsize);
  398. if (ippStsNoErr != sts) {
  399. result = kEpidMathErr;
  400. break;
  401. }
  402. // Allocate space for ipp bignum context
  403. ipp_ff_elem = (IppsGFpElement*)SAFE_ALLOC(ctxsize);
  404. if (!ipp_ff_elem) {
  405. result = kEpidMemAllocErr;
  406. break;
  407. }
  408. // Initialize ipp bignum context
  409. // initialize state
  410. sts = ippsGFpElementInit(&zero, 1, ipp_ff_elem, ff->ipp_ff);
  411. if (ippStsNoErr != sts) {
  412. result = kEpidMathErr;
  413. break;
  414. }
  415. ff_elem = (FfElement*)SAFE_ALLOC(sizeof(FfElement));
  416. if (!ff_elem) {
  417. result = kEpidMemAllocErr;
  418. break;
  419. }
  420. ff_elem->ipp_ff_elem = ipp_ff_elem;
  421. ff_elem->element_len = ff->element_len;
  422. ff_elem->degree = ff->ground_degree;
  423. *new_ff_elem = ff_elem;
  424. result = kEpidNoErr;
  425. } while (0);
  426. if (kEpidNoErr != result) {
  427. SAFE_FREE(ipp_ff_elem);
  428. SAFE_FREE(ff_elem);
  429. }
  430. return result;
  431. }
  432. void DeleteFfElement(FfElement** ff_elem) {
  433. if (ff_elem) {
  434. if (*ff_elem) {
  435. SAFE_FREE((*ff_elem)->ipp_ff_elem);
  436. }
  437. SAFE_FREE(*ff_elem);
  438. }
  439. }
  440. EpidStatus IsValidFfElemOctString(ConstOctStr ff_elem_str, int strlen,
  441. FiniteField const* ff) {
  442. int i;
  443. EpidStatus result = kEpidNoErr;
  444. IppStatus sts = ippStsNoErr;
  445. FiniteField const* basic_ff;
  446. BigNum* pData = NULL;
  447. int prime_length;
  448. IppOctStr ff_elem_str_p;
  449. Ipp32u cmp_res;
  450. int tmp_strlen = strlen;
  451. if (!ff || !ff_elem_str) {
  452. return kEpidBadArgErr;
  453. }
  454. basic_ff = ff;
  455. while (basic_ff->ground_ff != NULL) {
  456. basic_ff = basic_ff->ground_ff;
  457. }
  458. prime_length = basic_ff->element_len * sizeof(Ipp32u);
  459. ff_elem_str_p = (IppOctStr)ff_elem_str;
  460. for (i = 0; (i < ff->basic_degree) && (tmp_strlen > 0); i++) {
  461. int length;
  462. length = MIN(prime_length, tmp_strlen);
  463. result = NewBigNum(length, &pData);
  464. if (kEpidNoErr != result) {
  465. break;
  466. }
  467. result = ReadBigNum(ff_elem_str_p, length, pData);
  468. if (kEpidNoErr != result) {
  469. break;
  470. }
  471. sts = ippsCmp_BN(basic_ff->modulus_0->ipp_bn, pData->ipp_bn, &cmp_res);
  472. // check return codes
  473. if (ippStsNoErr != sts) {
  474. if (ippStsContextMatchErr == sts)
  475. result = kEpidBadArgErr;
  476. else
  477. result = kEpidMathErr;
  478. break;
  479. }
  480. if (cmp_res != IPP_IS_GT) {
  481. result = kEpidBadArgErr;
  482. break;
  483. }
  484. DeleteBigNum(&pData);
  485. tmp_strlen -= length;
  486. ff_elem_str_p += length;
  487. }
  488. DeleteBigNum(&pData);
  489. return result;
  490. }
  491. EpidStatus SetFfElementOctString(ConstOctStr ff_elem_str, int strlen,
  492. FfElement* ff_elem, FiniteField* ff) {
  493. EpidStatus result = kEpidErr;
  494. IppOctStr extended_ff_elem_str = NULL;
  495. if (!ff || !ff_elem || !ff_elem_str) {
  496. return kEpidBadArgErr;
  497. }
  498. do {
  499. IppStatus sts;
  500. // Ipp2017u2 contians a bug in ippsGFpSetElementOctString, does not check
  501. // whether ff_elem_str < modulus
  502. result = IsValidFfElemOctString(ff_elem_str, strlen, ff);
  503. if (kEpidNoErr != result) {
  504. break;
  505. }
  506. // workaround because of bug in ipp2017u2
  507. if (strlen < (int)(ff->element_len * sizeof(Ipp32u))) {
  508. int length = ff->element_len * sizeof(Ipp32u);
  509. extended_ff_elem_str = (IppOctStr)SAFE_ALLOC(length);
  510. if (!extended_ff_elem_str) {
  511. result = kEpidMemAllocErr;
  512. break;
  513. }
  514. memset(extended_ff_elem_str, 0, length);
  515. memcpy_S(extended_ff_elem_str, length, ff_elem_str, strlen);
  516. strlen = length;
  517. sts = ippsGFpSetElementOctString(extended_ff_elem_str, strlen,
  518. ff_elem->ipp_ff_elem, ff->ipp_ff);
  519. } else {
  520. sts = ippsGFpSetElementOctString(ff_elem_str, strlen,
  521. ff_elem->ipp_ff_elem, ff->ipp_ff);
  522. }
  523. if (ippStsNoErr != sts) {
  524. if (ippStsContextMatchErr == sts || ippStsOutOfRangeErr == sts) {
  525. result = kEpidBadArgErr;
  526. } else {
  527. result = kEpidMathErr;
  528. }
  529. break;
  530. }
  531. } while (0);
  532. SAFE_FREE(extended_ff_elem_str);
  533. return result;
  534. }
  535. EpidStatus ReadFfElement(FiniteField* ff, ConstOctStr ff_elem_str,
  536. size_t strlen, FfElement* ff_elem) {
  537. size_t strlen_required = 0;
  538. int ipp_str_size = 0;
  539. EpidStatus result = kEpidNoErr;
  540. ConstIppOctStr str = (ConstIppOctStr)ff_elem_str;
  541. if (!ff || !ff_elem_str || !ff_elem) {
  542. return kEpidBadArgErr;
  543. }
  544. if (!ff_elem->ipp_ff_elem || !ff->ipp_ff) {
  545. return kEpidBadArgErr;
  546. }
  547. if (ff->element_len != ff_elem->element_len) {
  548. return kEpidBadArgErr;
  549. }
  550. strlen_required = ff->element_strlen_required;
  551. // Remove leading zeros when de-serializing finite field of degree 1.
  552. // This takes care of serialization chunk size adjustments when importing
  553. // a big numbers.
  554. if (1 == ff->basic_degree) {
  555. while (strlen_required < strlen && 0 == *str) {
  556. str++;
  557. strlen--;
  558. }
  559. }
  560. // Check if serialized value does not exceed ippsGFpSetElementOctString
  561. // expected size.
  562. if (strlen_required < strlen) {
  563. return kEpidBadArgErr;
  564. }
  565. ipp_str_size = (int)strlen;
  566. if (ipp_str_size <= 0) {
  567. return kEpidBadArgErr;
  568. }
  569. result = SetFfElementOctString(str, ipp_str_size, ff_elem, ff);
  570. return result;
  571. }
  572. /// Gets the prime value of a finite field
  573. /*!
  574. This function returns a reference to the bignum containing the field's prime
  575. value.
  576. This function only works with non-composite fields.
  577. \param[in] ff
  578. The field.
  579. \param[out] bn
  580. The target BigNum.
  581. \returns ::EpidStatus
  582. */
  583. EpidStatus GetFiniteFieldPrime(FiniteField* ff, BigNum** bn) {
  584. if (!ff || !bn) {
  585. return kEpidBadArgErr;
  586. }
  587. if (!ff->ipp_ff) {
  588. return kEpidBadArgErr;
  589. }
  590. if (ff->basic_degree != 1 || ff->ground_degree != 1) {
  591. return kEpidBadArgErr;
  592. }
  593. *bn = ff->modulus_0;
  594. return kEpidNoErr;
  595. }
  596. EpidStatus InitFfElementFromBn(FiniteField* ff, BigNum* bn,
  597. FfElement* ff_elem) {
  598. EpidStatus result = kEpidErr;
  599. BigNum* prime_bn = NULL; // non-owning reference
  600. BigNum* mod_bn = NULL;
  601. BNU mod_str = NULL;
  602. if (!ff || !bn || !ff_elem) {
  603. return kEpidBadArgErr;
  604. }
  605. if (!ff_elem->ipp_ff_elem || !ff->ipp_ff) {
  606. return kEpidBadArgErr;
  607. }
  608. if (ff->basic_degree != 1 || ff->ground_degree != 1) {
  609. return kEpidBadArgErr;
  610. }
  611. if (ff->element_len != ff_elem->element_len) {
  612. return kEpidBadArgErr;
  613. }
  614. do {
  615. size_t elem_size = ff->element_len * sizeof(Ipp32u);
  616. result = NewBigNum(elem_size, &mod_bn);
  617. if (kEpidNoErr != result) {
  618. break;
  619. }
  620. result = GetFiniteFieldPrime(ff, &prime_bn);
  621. if (kEpidNoErr != result) {
  622. break;
  623. }
  624. result = BigNumMod(bn, prime_bn, mod_bn);
  625. if (kEpidNoErr != result) {
  626. break;
  627. }
  628. mod_str = (BNU)SAFE_ALLOC(elem_size);
  629. if (NULL == mod_str) {
  630. result = kEpidMemAllocErr;
  631. break;
  632. }
  633. result = WriteBigNum(mod_bn, elem_size, mod_str);
  634. if (kEpidNoErr != result) {
  635. break;
  636. }
  637. result = ReadFfElement(ff, mod_str, elem_size, ff_elem);
  638. if (kEpidNoErr != result) {
  639. break;
  640. }
  641. result = kEpidNoErr;
  642. } while (0);
  643. SAFE_FREE(mod_str);
  644. prime_bn = NULL;
  645. DeleteBigNum(&mod_bn);
  646. return result;
  647. }
  648. EpidStatus WriteFfElement(FiniteField* ff, FfElement const* ff_elem,
  649. OctStr ff_elem_str, size_t strlen) {
  650. IppStatus sts;
  651. size_t strlen_required = 0;
  652. size_t pad = 0;
  653. IppOctStr str = (IppOctStr)ff_elem_str;
  654. if (!ff || !ff_elem_str || !ff_elem) {
  655. return kEpidBadArgErr;
  656. }
  657. if (!ff_elem->ipp_ff_elem || !ff->ipp_ff) {
  658. return kEpidBadArgErr;
  659. }
  660. if (INT_MAX < strlen) {
  661. return kEpidBadArgErr;
  662. }
  663. if (ff->element_len != ff_elem->element_len) {
  664. return kEpidBadArgErr;
  665. }
  666. strlen_required = ff->element_strlen_required;
  667. // add zero padding for extension of a degree 1 (a prime field)
  668. // so it can be deserialized into big number correctly.
  669. if (1 == ff->basic_degree && strlen_required < strlen) {
  670. pad = strlen - strlen_required;
  671. memset(str, 0, pad);
  672. strlen -= pad;
  673. str += pad;
  674. }
  675. // Check if output buffer meets ippsGFpGetElementOctString expectations.
  676. if (strlen_required != strlen) return kEpidBadArgErr;
  677. // get the data
  678. sts = ippsGFpGetElementOctString(ff_elem->ipp_ff_elem, str, (int)strlen,
  679. ff->ipp_ff);
  680. if (ippStsNoErr != sts) {
  681. if (ippStsContextMatchErr == sts) {
  682. return kEpidBadArgErr;
  683. } else {
  684. return kEpidMathErr;
  685. }
  686. }
  687. return kEpidNoErr;
  688. }
  689. EpidStatus FfNeg(FiniteField* ff, FfElement const* a, FfElement* r) {
  690. IppStatus sts = ippStsNoErr;
  691. if (!ff || !a || !r) {
  692. return kEpidBadArgErr;
  693. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !r->ipp_ff_elem) {
  694. return kEpidBadArgErr;
  695. }
  696. if (ff->element_len != a->element_len || ff->element_len != r->element_len) {
  697. return kEpidBadArgErr;
  698. }
  699. sts = ippsGFpNeg(a->ipp_ff_elem, r->ipp_ff_elem, ff->ipp_ff);
  700. if (ippStsNoErr != sts) {
  701. if (ippStsContextMatchErr == sts) {
  702. return kEpidBadArgErr;
  703. } else {
  704. return kEpidMathErr;
  705. }
  706. }
  707. return kEpidNoErr;
  708. }
  709. EpidStatus FfInv(FiniteField* ff, FfElement const* a, FfElement* r) {
  710. IppStatus sts = ippStsNoErr;
  711. // Check required parametersWriteFfElement
  712. if (!ff || !a || !r) {
  713. return kEpidBadArgErr;
  714. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !r->ipp_ff_elem) {
  715. return kEpidBadArgErr;
  716. }
  717. if (ff->element_len != a->element_len || ff->element_len != r->element_len) {
  718. return kEpidBadArgErr;
  719. }
  720. // Invert the element
  721. sts = ippsGFpInv(a->ipp_ff_elem, r->ipp_ff_elem, ff->ipp_ff);
  722. // Check return codes
  723. if (ippStsNoErr != sts) {
  724. if (ippStsContextMatchErr == sts)
  725. return kEpidBadArgErr;
  726. else if (ippStsDivByZeroErr == sts)
  727. return kEpidDivByZeroErr;
  728. else
  729. return kEpidMathErr;
  730. }
  731. return kEpidNoErr;
  732. }
  733. EpidStatus FfAdd(FiniteField* ff, FfElement const* a, FfElement const* b,
  734. FfElement* r) {
  735. IppStatus sts = ippStsNoErr;
  736. if (!ff || !a || !b || !r) {
  737. return kEpidBadArgErr;
  738. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !b->ipp_ff_elem ||
  739. !r->ipp_ff_elem) {
  740. return kEpidBadArgErr;
  741. }
  742. if (ff->element_len != a->element_len || ff->element_len != b->element_len ||
  743. ff->element_len != r->element_len) {
  744. return kEpidBadArgErr;
  745. }
  746. sts = ippsGFpAdd(a->ipp_ff_elem, b->ipp_ff_elem, r->ipp_ff_elem, ff->ipp_ff);
  747. if (ippStsContextMatchErr == sts) {
  748. return kEpidBadArgErr;
  749. } else if (ippStsNoErr != sts) {
  750. return kEpidMathErr;
  751. }
  752. return kEpidNoErr;
  753. }
  754. EpidStatus FfSub(FiniteField* ff, FfElement const* a, FfElement const* b,
  755. FfElement* r) {
  756. IppStatus sts = ippStsNoErr;
  757. if (!ff || !a || !b || !r) {
  758. return kEpidBadArgErr;
  759. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !b->ipp_ff_elem ||
  760. !r->ipp_ff_elem) {
  761. return kEpidBadArgErr;
  762. }
  763. if (ff->element_len != a->element_len || ff->element_len != b->element_len ||
  764. ff->element_len != r->element_len) {
  765. return kEpidBadArgErr;
  766. }
  767. sts = ippsGFpSub(a->ipp_ff_elem, b->ipp_ff_elem, r->ipp_ff_elem, ff->ipp_ff);
  768. if (ippStsContextMatchErr == sts) {
  769. return kEpidBadArgErr;
  770. } else if (ippStsNoErr != sts) {
  771. return kEpidMathErr;
  772. }
  773. return kEpidNoErr;
  774. }
  775. EpidStatus FfMul(FiniteField* ff, FfElement const* a, FfElement const* b,
  776. FfElement* r) {
  777. IppStatus sts = ippStsNoErr;
  778. // Check required parametersWriteFfElement
  779. if (!ff || !a || !b || !r) {
  780. return kEpidBadArgErr;
  781. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !b->ipp_ff_elem ||
  782. !r->ipp_ff_elem) {
  783. return kEpidBadArgErr;
  784. }
  785. // Multiplies elements
  786. if (a->element_len != b->element_len &&
  787. a->element_len == a->degree * b->element_len) {
  788. sts = ippsGFpMul_PE(a->ipp_ff_elem, b->ipp_ff_elem, r->ipp_ff_elem,
  789. ff->ipp_ff);
  790. } else {
  791. if (ff->element_len != a->element_len ||
  792. ff->element_len != b->element_len ||
  793. ff->element_len != r->element_len) {
  794. return kEpidBadArgErr;
  795. }
  796. sts =
  797. ippsGFpMul(a->ipp_ff_elem, b->ipp_ff_elem, r->ipp_ff_elem, ff->ipp_ff);
  798. }
  799. // Check return codes
  800. if (ippStsNoErr != sts) {
  801. if (ippStsContextMatchErr == sts)
  802. return kEpidBadArgErr;
  803. else
  804. return kEpidMathErr;
  805. }
  806. return kEpidNoErr;
  807. }
  808. EpidStatus FfIsZero(FiniteField* ff, FfElement const* a, bool* is_zero) {
  809. IppStatus sts = ippStsNoErr;
  810. int ipp_result = IPP_IS_NE;
  811. // Check required parameters
  812. if (!ff || !a || !is_zero) {
  813. return kEpidBadArgErr;
  814. } else if (!ff->ipp_ff || !a->ipp_ff_elem) {
  815. return kEpidBadArgErr;
  816. }
  817. if (ff->element_len != a->element_len) {
  818. return kEpidBadArgErr;
  819. }
  820. // Check if the element is zero
  821. sts = ippsGFpIsZeroElement(a->ipp_ff_elem, &ipp_result, ff->ipp_ff);
  822. // Check return codes
  823. if (ippStsNoErr != sts) {
  824. if (ippStsContextMatchErr == sts)
  825. return kEpidBadArgErr;
  826. else
  827. return kEpidMathErr;
  828. }
  829. if (IPP_IS_EQ == ipp_result) {
  830. *is_zero = true;
  831. } else {
  832. *is_zero = false;
  833. }
  834. return kEpidNoErr;
  835. }
  836. EpidStatus FfExp(FiniteField* ff, FfElement const* a, BigNum const* b,
  837. FfElement* r) {
  838. EpidStatus result = kEpidErr;
  839. OctStr scratch_buffer = NULL;
  840. int exp_bit_size = 0;
  841. int element_size = 0;
  842. do {
  843. IppStatus sts = ippStsNoErr;
  844. // Check required parameters
  845. if (!ff || !a || !b || !r) {
  846. result = kEpidBadArgErr;
  847. break;
  848. } else if (!ff->ipp_ff || !a->ipp_ff_elem || !r->ipp_ff_elem) {
  849. result = kEpidBadArgErr;
  850. break;
  851. }
  852. if (ff->element_len != a->element_len ||
  853. ff->element_len != r->element_len) {
  854. return kEpidBadArgErr;
  855. }
  856. sts = ippsRef_BN(0, &exp_bit_size, 0, b->ipp_bn);
  857. if (ippStsNoErr != sts) {
  858. result = kEpidMathErr;
  859. break;
  860. }
  861. sts = ippsGFpScratchBufferSize(1, exp_bit_size, ff->ipp_ff, &element_size);
  862. if (ippStsNoErr != sts) {
  863. result = kEpidMathErr;
  864. break;
  865. }
  866. scratch_buffer = (OctStr)SAFE_ALLOC(element_size);
  867. if (!scratch_buffer) {
  868. result = kEpidMemAllocErr;
  869. break;
  870. }
  871. sts = ippsGFpExp(a->ipp_ff_elem, b->ipp_bn, r->ipp_ff_elem, ff->ipp_ff,
  872. scratch_buffer);
  873. // Check return codes
  874. if (ippStsNoErr != sts) {
  875. if (ippStsContextMatchErr == sts || ippStsRangeErr == sts)
  876. result = kEpidBadArgErr;
  877. else
  878. result = kEpidMathErr;
  879. break;
  880. }
  881. result = kEpidNoErr;
  882. } while (0);
  883. SAFE_FREE(scratch_buffer);
  884. return result;
  885. }
  886. EpidStatus FfMultiExp(FiniteField* ff, FfElement const** p, BigNumStr const** b,
  887. size_t m, FfElement* r) {
  888. EpidStatus result = kEpidErr;
  889. IppsGFpElement** ipp_p = NULL;
  890. IppsBigNumState** ipp_b = NULL;
  891. BigNum** bignums = NULL;
  892. OctStr scratch_buffer = NULL;
  893. int i = 0;
  894. int ipp_m = 0;
  895. // Check required parameters
  896. if (!ff || !p || !b || !r) {
  897. return kEpidBadArgErr;
  898. } else if (!ff->ipp_ff || !r->ipp_ff_elem || m <= 0) {
  899. return kEpidBadArgErr;
  900. }
  901. // because we use ipp function with number of items parameter
  902. // defined as "int" we need to verify that input length
  903. // do not exceed INT_MAX to avoid overflow
  904. if (m > INT_MAX) {
  905. return kEpidBadArgErr;
  906. }
  907. ipp_m = (int)m;
  908. for (i = 0; i < ipp_m; i++) {
  909. if (!p[i]) {
  910. return kEpidBadArgErr;
  911. }
  912. if (!p[i]->ipp_ff_elem) {
  913. return kEpidBadArgErr;
  914. }
  915. if (ff->element_len != p[i]->element_len) {
  916. return kEpidBadArgErr;
  917. }
  918. }
  919. if (ff->element_len != r->element_len) {
  920. return kEpidBadArgErr;
  921. }
  922. do {
  923. IppStatus sts = ippStsNoErr;
  924. int scratch_buffer_size = 0;
  925. const int exp_bit_size = CHAR_BIT * sizeof(BigNumStr);
  926. // Allocate memory for finite field elements for ipp call
  927. ipp_p = (IppsGFpElement**)SAFE_ALLOC(ipp_m * sizeof(IppsGFpElement*));
  928. if (!ipp_p) {
  929. result = kEpidMemAllocErr;
  930. break;
  931. }
  932. for (i = 0; i < ipp_m; i++) {
  933. ipp_p[i] = p[i]->ipp_ff_elem;
  934. }
  935. // Create big number elements for ipp call
  936. // Allocate memory for finite field elements for ipp call
  937. bignums = (BigNum**)SAFE_ALLOC(ipp_m * sizeof(BigNum*));
  938. if (!bignums) {
  939. result = kEpidMemAllocErr;
  940. break;
  941. }
  942. ipp_b = (IppsBigNumState**)SAFE_ALLOC(ipp_m * sizeof(IppsBigNumState*));
  943. if (!ipp_b) {
  944. result = kEpidMemAllocErr;
  945. break;
  946. }
  947. // Initialize BigNum and fill ipp array for ipp call
  948. for (i = 0; i < ipp_m; i++) {
  949. result = NewBigNum(sizeof(BigNumStr), &bignums[i]);
  950. if (kEpidNoErr != result) break;
  951. result = ReadBigNum(b[i], sizeof(BigNumStr), bignums[i]);
  952. if (kEpidNoErr != result) break;
  953. ipp_b[i] = bignums[i]->ipp_bn;
  954. }
  955. if (kEpidNoErr != result) break;
  956. // calculate scratch buffer size
  957. sts = ippsGFpScratchBufferSize(ipp_m, exp_bit_size, ff->ipp_ff,
  958. &scratch_buffer_size);
  959. if (sts != ippStsNoErr) {
  960. result = kEpidMathErr;
  961. break;
  962. }
  963. // allocate memory for scratch buffer
  964. scratch_buffer = (OctStr)SAFE_ALLOC(scratch_buffer_size);
  965. if (!scratch_buffer) {
  966. result = kEpidMemAllocErr;
  967. break;
  968. }
  969. sts = ippsGFpMultiExp((const IppsGFpElement* const*)ipp_p,
  970. (const IppsBigNumState* const*)ipp_b, ipp_m,
  971. r->ipp_ff_elem, ff->ipp_ff, scratch_buffer);
  972. if (ippStsNoErr != sts) {
  973. if (ippStsContextMatchErr == sts || ippStsRangeErr == sts)
  974. result = kEpidBadArgErr;
  975. else
  976. result = kEpidMathErr;
  977. break;
  978. }
  979. result = kEpidNoErr;
  980. } while (0);
  981. if (NULL != bignums) { // delete big nums only if it was really allocated
  982. for (i = 0; i < ipp_m; i++) {
  983. DeleteBigNum(&bignums[i]);
  984. }
  985. }
  986. SAFE_FREE(bignums);
  987. SAFE_FREE(ipp_p);
  988. SAFE_FREE(ipp_b);
  989. SAFE_FREE(scratch_buffer);
  990. return result;
  991. }
  992. EpidStatus FfMultiExpBn(FiniteField* ff, FfElement const** p, BigNum const** b,
  993. size_t m, FfElement* r) {
  994. IppStatus sts = ippStsNoErr;
  995. EpidStatus result = kEpidErr;
  996. IppsGFpElement** ipp_p = NULL;
  997. IppsBigNumState** ipp_b = NULL;
  998. OctStr scratch_buffer = NULL;
  999. int exp_bit_size = 0;
  1000. size_t i = 0;
  1001. int ipp_m = 0;
  1002. // Check required parameters
  1003. if (!ff || !p || !b || !r) {
  1004. return kEpidBadArgErr;
  1005. } else if (!ff->ipp_ff || !r->ipp_ff_elem || m <= 0) {
  1006. return kEpidBadArgErr;
  1007. } else if (ff->element_len != r->element_len) {
  1008. return kEpidBadArgErr;
  1009. }
  1010. // because we use ipp function with number of items parameter
  1011. // defined as "int" we need to verify that input length
  1012. // do not exceed INT_MAX to avoid overflow
  1013. if (m > INT_MAX) {
  1014. return kEpidBadArgErr;
  1015. }
  1016. ipp_m = (int)m;
  1017. for (i = 0; i < m; i++) {
  1018. int b_size = 0;
  1019. if (!p[i] || !p[i]->ipp_ff_elem || !b[i] || !b[i]->ipp_bn) {
  1020. return kEpidBadArgErr;
  1021. }
  1022. if (ff->element_len != p[i]->element_len) {
  1023. return kEpidBadArgErr;
  1024. }
  1025. sts = ippsGetSize_BN(b[i]->ipp_bn, &b_size);
  1026. if (ippStsNoErr != sts) {
  1027. return kEpidBadArgErr;
  1028. }
  1029. b_size *= (sizeof(Ipp32u) * CHAR_BIT);
  1030. if (b_size > exp_bit_size) {
  1031. exp_bit_size = b_size;
  1032. }
  1033. }
  1034. do {
  1035. int scratch_buffer_size = 0;
  1036. // Allocate memory for finite field elements for ipp call
  1037. ipp_p = (IppsGFpElement**)SAFE_ALLOC(m * sizeof(IppsGFpElement*));
  1038. if (!ipp_p) {
  1039. result = kEpidMemAllocErr;
  1040. break;
  1041. }
  1042. for (i = 0; i < m; i++) {
  1043. ipp_p[i] = p[i]->ipp_ff_elem;
  1044. }
  1045. ipp_b = (IppsBigNumState**)SAFE_ALLOC(m * sizeof(IppsBigNumState*));
  1046. if (!ipp_b) {
  1047. result = kEpidMemAllocErr;
  1048. break;
  1049. }
  1050. // fill ipp array for ipp call
  1051. for (i = 0; i < m; i++) {
  1052. ipp_b[i] = b[i]->ipp_bn;
  1053. }
  1054. // calculate scratch buffer size
  1055. sts = ippsGFpScratchBufferSize(ipp_m, exp_bit_size, ff->ipp_ff,
  1056. &scratch_buffer_size);
  1057. if (sts != ippStsNoErr) {
  1058. result = kEpidMathErr;
  1059. break;
  1060. }
  1061. // allocate memory for scratch buffer
  1062. scratch_buffer = (OctStr)SAFE_ALLOC(scratch_buffer_size);
  1063. if (!scratch_buffer) {
  1064. result = kEpidMemAllocErr;
  1065. break;
  1066. }
  1067. sts = ippsGFpMultiExp((const IppsGFpElement* const*)ipp_p,
  1068. (const IppsBigNumState* const*)ipp_b, ipp_m,
  1069. r->ipp_ff_elem, ff->ipp_ff, scratch_buffer);
  1070. if (ippStsNoErr != sts) {
  1071. if (ippStsContextMatchErr == sts || ippStsRangeErr == sts)
  1072. result = kEpidBadArgErr;
  1073. else
  1074. result = kEpidMathErr;
  1075. break;
  1076. }
  1077. result = kEpidNoErr;
  1078. } while (0);
  1079. SAFE_FREE(scratch_buffer);
  1080. SAFE_FREE(ipp_b);
  1081. SAFE_FREE(ipp_p);
  1082. return result;
  1083. }
  1084. EpidStatus FfSscmMultiExp(FiniteField* ff, FfElement const** p,
  1085. BigNumStr const** b, size_t m, FfElement* r) {
  1086. // call EcMultiExp directly because its implementation is side channel
  1087. // mitigated already
  1088. return FfMultiExp(ff, p, b, m, r);
  1089. }
  1090. EpidStatus FfIsEqual(FiniteField* ff, FfElement const* a, FfElement const* b,
  1091. bool* is_equal) {
  1092. IppStatus sts;
  1093. int result;
  1094. if (!ff || !a || !b || !is_equal) {
  1095. return kEpidBadArgErr;
  1096. }
  1097. if (!ff->ipp_ff || !a->ipp_ff_elem || !b->ipp_ff_elem) {
  1098. return kEpidBadArgErr;
  1099. }
  1100. if (ff->element_len != a->element_len || ff->element_len != b->element_len) {
  1101. return kEpidBadArgErr;
  1102. }
  1103. sts = ippsGFpCmpElement(a->ipp_ff_elem, b->ipp_ff_elem, &result, ff->ipp_ff);
  1104. if (ippStsNoErr != sts) {
  1105. if (ippStsContextMatchErr == sts) {
  1106. return kEpidBadArgErr;
  1107. } else {
  1108. return kEpidMathErr;
  1109. }
  1110. }
  1111. *is_equal = IPP_IS_EQ == result;
  1112. return kEpidNoErr;
  1113. }
  1114. EpidStatus FfHash(FiniteField* ff, ConstOctStr msg, size_t msg_len,
  1115. HashAlg hash_alg, FfElement* r) {
  1116. EpidStatus result = kEpidErr;
  1117. do {
  1118. IppStatus sts = ippStsNoErr;
  1119. IppHashAlgId hash_id;
  1120. int ipp_msg_len = 0;
  1121. if (!ff || !msg || !r) {
  1122. result = kEpidBadArgErr;
  1123. break;
  1124. } else if (!ff->ipp_ff || !r->ipp_ff_elem || msg_len <= 0) {
  1125. result = kEpidBadArgErr;
  1126. break;
  1127. }
  1128. // because we use ipp function with message length parameter
  1129. // defined as "int" we need to verify that input length
  1130. // do not exceed INT_MAX to avoid overflow
  1131. if (msg_len > INT_MAX) {
  1132. result = kEpidBadArgErr;
  1133. break;
  1134. }
  1135. ipp_msg_len = (int)msg_len;
  1136. if (kSha256 == hash_alg) {
  1137. hash_id = ippHashAlg_SHA256;
  1138. } else if (kSha384 == hash_alg) {
  1139. hash_id = ippHashAlg_SHA384;
  1140. } else if (kSha512 == hash_alg) {
  1141. hash_id = ippHashAlg_SHA512;
  1142. } else if (kSha512_256 == hash_alg) {
  1143. hash_id = ippHashAlg_SHA512_256;
  1144. } else {
  1145. result = kEpidHashAlgorithmNotSupported;
  1146. break;
  1147. }
  1148. if (ff->element_len != r->element_len) {
  1149. return kEpidBadArgErr;
  1150. }
  1151. sts = ippsGFpSetElementHash(msg, ipp_msg_len, r->ipp_ff_elem, ff->ipp_ff,
  1152. hash_id);
  1153. if (ippStsNoErr != sts) {
  1154. if (ippStsContextMatchErr == sts || ippStsBadArgErr == sts ||
  1155. ippStsLengthErr == sts) {
  1156. return kEpidBadArgErr;
  1157. } else {
  1158. return kEpidMathErr;
  1159. }
  1160. }
  1161. result = kEpidNoErr;
  1162. } while (0);
  1163. return result;
  1164. }
  1165. /// Number of tries for RNG
  1166. #define RNG_WATCHDOG (10)
  1167. EpidStatus FfGetRandom(FiniteField* ff, BigNumStr const* low_bound,
  1168. BitSupplier rnd_func, void* rnd_param, FfElement* r) {
  1169. EpidStatus result = kEpidErr;
  1170. FfElement* low = NULL;
  1171. do {
  1172. IppStatus sts = ippStsNoErr;
  1173. unsigned int rngloopCount = RNG_WATCHDOG;
  1174. if (!ff || !low_bound || !rnd_func || !r) {
  1175. result = kEpidBadArgErr;
  1176. break;
  1177. }
  1178. if (!ff->ipp_ff || !r->ipp_ff_elem) {
  1179. result = kEpidBadArgErr;
  1180. break;
  1181. }
  1182. if (ff->element_len != r->element_len) {
  1183. return kEpidBadArgErr;
  1184. }
  1185. // create a new FfElement to hold low_bound
  1186. result = NewFfElement(ff, &low);
  1187. if (kEpidNoErr != result) {
  1188. break;
  1189. }
  1190. result = ReadFfElement(ff, low_bound, sizeof(*low_bound), low);
  1191. if (kEpidNoErr != result) {
  1192. break;
  1193. }
  1194. do {
  1195. int cmpResult = IPP_IS_NE;
  1196. sts = ippsGFpSetElementRandom(r->ipp_ff_elem, ff->ipp_ff,
  1197. (IppBitSupplier)rnd_func, rnd_param);
  1198. if (ippStsNoErr != sts) {
  1199. result = kEpidMathErr;
  1200. break;
  1201. }
  1202. sts = ippsGFpCmpElement(r->ipp_ff_elem, low->ipp_ff_elem, &cmpResult,
  1203. ff->ipp_ff);
  1204. if (ippStsNoErr != sts) {
  1205. result = kEpidMathErr;
  1206. break;
  1207. }
  1208. if (IPP_IS_LT != cmpResult) {
  1209. // we have a valid value, proceed
  1210. result = kEpidNoErr;
  1211. break;
  1212. } else {
  1213. result = kEpidRandMaxIterErr;
  1214. continue;
  1215. }
  1216. } while (--rngloopCount);
  1217. } while (0);
  1218. DeleteFfElement(&low);
  1219. return result;
  1220. }
  1221. EpidStatus FfSqrt(FiniteField* ff, FfElement const* a, FfElement* r) {
  1222. EpidStatus result = kEpidErr;
  1223. BigNum* qm1 = NULL;
  1224. BigNum* one = NULL;
  1225. FfElement* qm1_ffe = NULL;
  1226. BigNum* two = NULL;
  1227. BigNum* qm1d2 = NULL;
  1228. BigNum* remainder = NULL;
  1229. FfElement* g = NULL;
  1230. FfElement* gg = NULL;
  1231. BigNum* t = NULL;
  1232. BigNum* e = NULL;
  1233. BigNum* j = NULL;
  1234. BigNum* qm1dj = NULL;
  1235. FfElement* ge = NULL;
  1236. FfElement* h = NULL;
  1237. FfElement* temp = NULL;
  1238. FfElement* one_ffe = NULL;
  1239. BigNum* ed2 = NULL;
  1240. FfElement* ged2 = NULL;
  1241. BigNum* tp1d2 = NULL;
  1242. FfElement* gtp1d2 = NULL;
  1243. FfElement* dd = NULL;
  1244. if (!ff || !a || !r) {
  1245. return kEpidBadArgErr;
  1246. }
  1247. do {
  1248. BigNum* prime = NULL; // non-owning reference
  1249. bool is_equal = false;
  1250. unsigned int s;
  1251. bool is_even = false;
  1252. unsigned int i;
  1253. Ipp8u one_str = 1;
  1254. BigNumStr qm1_str;
  1255. const BigNumStr zero_str = {0};
  1256. result = GetFiniteFieldPrime(ff, &prime);
  1257. if (kEpidNoErr != result) {
  1258. break;
  1259. }
  1260. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &qm1);
  1261. if (kEpidNoErr != result) {
  1262. break;
  1263. }
  1264. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &one);
  1265. if (kEpidNoErr != result) {
  1266. break;
  1267. }
  1268. result = NewFfElement(ff, &qm1_ffe);
  1269. if (kEpidNoErr != result) {
  1270. break;
  1271. }
  1272. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &two);
  1273. if (kEpidNoErr != result) {
  1274. break;
  1275. }
  1276. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &qm1d2);
  1277. if (kEpidNoErr != result) {
  1278. break;
  1279. }
  1280. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &remainder);
  1281. if (kEpidNoErr != result) {
  1282. break;
  1283. }
  1284. result = NewFfElement(ff, &g);
  1285. if (kEpidNoErr != result) {
  1286. break;
  1287. }
  1288. result = NewFfElement(ff, &gg);
  1289. if (kEpidNoErr != result) {
  1290. break;
  1291. }
  1292. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &t);
  1293. if (kEpidNoErr != result) {
  1294. break;
  1295. }
  1296. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &e);
  1297. if (kEpidNoErr != result) {
  1298. break;
  1299. }
  1300. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &j);
  1301. if (kEpidNoErr != result) {
  1302. break;
  1303. }
  1304. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &qm1dj);
  1305. if (kEpidNoErr != result) {
  1306. break;
  1307. }
  1308. result = NewFfElement(ff, &ge);
  1309. if (kEpidNoErr != result) {
  1310. break;
  1311. }
  1312. result = NewFfElement(ff, &h);
  1313. if (kEpidNoErr != result) {
  1314. break;
  1315. }
  1316. result = NewFfElement(ff, &temp);
  1317. if (kEpidNoErr != result) {
  1318. break;
  1319. }
  1320. result = NewFfElement(ff, &one_ffe);
  1321. if (kEpidNoErr != result) {
  1322. break;
  1323. }
  1324. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &ed2);
  1325. if (kEpidNoErr != result) {
  1326. break;
  1327. }
  1328. result = NewFfElement(ff, &ged2);
  1329. if (kEpidNoErr != result) {
  1330. break;
  1331. }
  1332. result = NewBigNum(sizeof(BigNumStr) * CHAR_BIT, &tp1d2);
  1333. if (kEpidNoErr != result) {
  1334. break;
  1335. }
  1336. result = NewFfElement(ff, &gtp1d2);
  1337. if (kEpidNoErr != result) {
  1338. break;
  1339. }
  1340. result = NewFfElement(ff, &dd);
  1341. if (kEpidNoErr != result) {
  1342. break;
  1343. }
  1344. result = ReadBigNum(&one_str, sizeof(one_str), one);
  1345. if (kEpidNoErr != result) {
  1346. break;
  1347. }
  1348. result = BigNumSub(prime, one, qm1);
  1349. if (kEpidNoErr != result) {
  1350. break;
  1351. }
  1352. result = BigNumAdd(one, one, two);
  1353. if (kEpidNoErr != result) {
  1354. break;
  1355. }
  1356. result = InitFfElementFromBn(ff, one, one_ffe);
  1357. if (kEpidNoErr != result) {
  1358. break;
  1359. }
  1360. result = WriteBigNum(qm1, sizeof(qm1_str), &qm1_str);
  1361. if (kEpidNoErr != result) {
  1362. break;
  1363. }
  1364. result = InitFfElementFromBn(ff, qm1, qm1_ffe);
  1365. if (kEpidNoErr != result) {
  1366. break;
  1367. }
  1368. result = BigNumDiv(qm1, two, qm1d2, remainder);
  1369. if (kEpidNoErr != result) {
  1370. break;
  1371. }
  1372. // 1. Choose an element g in Fq.
  1373. result = ReadFfElement(ff, &one_str, sizeof(one_str), g);
  1374. if (kEpidNoErr != result) {
  1375. break;
  1376. }
  1377. // try small values for g starting from 2 until
  1378. // it meets the requirements from the step 2
  1379. do {
  1380. result = FfAdd(ff, g, one_ffe, g);
  1381. if (kEpidNoErr != result) {
  1382. break;
  1383. }
  1384. // 2. Check whether g^((q-1)/2) mod q = q-1. If not, go to step 1.
  1385. result = FfExp(ff, g, qm1d2, gg);
  1386. if (kEpidNoErr != result) {
  1387. break;
  1388. }
  1389. result = FfIsEqual(ff, gg, qm1_ffe, &is_equal);
  1390. if (kEpidNoErr != result) {
  1391. break;
  1392. }
  1393. } while (!is_equal);
  1394. if (kEpidNoErr != result) {
  1395. break;
  1396. }
  1397. // 3. Set t = q-1, s = 0.
  1398. result = ReadBigNum(&qm1_str, sizeof(qm1_str), t);
  1399. if (kEpidNoErr != result) {
  1400. break;
  1401. }
  1402. s = 0;
  1403. // 4. While (t is even number)
  1404. // t = t/2, s = s+1.
  1405. result = BigNumIsEven(t, &is_even);
  1406. if (kEpidNoErr != result) {
  1407. break;
  1408. }
  1409. while (is_even) {
  1410. result = BigNumDiv(t, two, t, remainder);
  1411. if (kEpidNoErr != result) {
  1412. break;
  1413. }
  1414. s = s + 1;
  1415. result = BigNumIsEven(t, &is_even);
  1416. if (kEpidNoErr != result) {
  1417. break;
  1418. }
  1419. }
  1420. // 5. Note that g, s, t can be pre-computed and used for all
  1421. // future computations.
  1422. // Also note that q-1 = (2^s)*t where t is an odd integer.
  1423. // 6. e = 0.
  1424. result = ReadBigNum(&zero_str, sizeof(zero_str), e);
  1425. if (kEpidNoErr != result) {
  1426. break;
  1427. }
  1428. // 7. For i = 2, ..., s
  1429. // j = 2^i,
  1430. // if (a ? g^(-e))^((q-1)/j) mod q != 1, then set e = e + j/2.
  1431. for (i = 2; i <= s; i++) {
  1432. result = BigNumPow2N(i, j);
  1433. if (kEpidNoErr != result) {
  1434. break;
  1435. }
  1436. result = BigNumDiv(qm1, j, qm1dj, remainder);
  1437. if (kEpidNoErr != result) {
  1438. break;
  1439. }
  1440. result = FfExp(ff, g, e, ge);
  1441. if (kEpidNoErr != result) {
  1442. break;
  1443. }
  1444. // 8. Compute h = (a * g^(-e)) mod q.
  1445. result = FfInv(ff, ge, ge);
  1446. if (kEpidNoErr != result) {
  1447. break;
  1448. }
  1449. result = FfMul(ff, a, ge, h);
  1450. if (kEpidNoErr != result) {
  1451. break;
  1452. }
  1453. result = FfExp(ff, h, qm1dj, temp);
  1454. if (kEpidNoErr != result) {
  1455. break;
  1456. }
  1457. result = FfIsEqual(ff, temp, one_ffe, &is_equal);
  1458. if (!is_equal) {
  1459. result = BigNumDiv(j, two, j, remainder);
  1460. if (kEpidNoErr != result) {
  1461. break;
  1462. }
  1463. result = BigNumAdd(e, j, e);
  1464. if (kEpidNoErr != result) {
  1465. break;
  1466. }
  1467. }
  1468. }
  1469. // 8. Compute h = (a * g^(-e)) mod q.
  1470. result = FfExp(ff, g, e, ge);
  1471. if (kEpidNoErr != result) {
  1472. break;
  1473. }
  1474. result = FfInv(ff, ge, ge);
  1475. if (kEpidNoErr != result) {
  1476. break;
  1477. }
  1478. result = FfMul(ff, a, ge, h);
  1479. if (kEpidNoErr != result) {
  1480. break;
  1481. }
  1482. // 9. Compute r = d = (g^(e/2) * h^((t+1)/2)) mod q.
  1483. result = BigNumDiv(e, two, ed2, remainder);
  1484. if (kEpidNoErr != result) {
  1485. break;
  1486. }
  1487. result = FfExp(ff, g, ed2, ged2);
  1488. if (kEpidNoErr != result) {
  1489. break;
  1490. }
  1491. result = BigNumAdd(t, one, tp1d2);
  1492. if (kEpidNoErr != result) {
  1493. break;
  1494. }
  1495. result = BigNumDiv(tp1d2, two, tp1d2, remainder);
  1496. if (kEpidNoErr != result) {
  1497. break;
  1498. }
  1499. result = FfExp(ff, h, tp1d2, gtp1d2);
  1500. if (kEpidNoErr != result) {
  1501. break;
  1502. }
  1503. result = FfMul(ff, ged2, gtp1d2, r);
  1504. if (kEpidNoErr != result) {
  1505. break;
  1506. }
  1507. // 10. Verify whether a = d^2 mod q. If so, return r, otherwise, return
  1508. // fail.
  1509. result = FfMul(ff, r, r, dd);
  1510. if (kEpidNoErr != result) {
  1511. break;
  1512. }
  1513. result = FfIsEqual(ff, dd, a, &is_equal);
  1514. if (kEpidNoErr != result) {
  1515. break;
  1516. }
  1517. if (!is_equal) {
  1518. result = kEpidMathQuadraticNonResidueError;
  1519. break;
  1520. }
  1521. result = kEpidNoErr;
  1522. prime = NULL;
  1523. } while (0);
  1524. DeleteFfElement(&dd);
  1525. DeleteFfElement(&gtp1d2);
  1526. DeleteBigNum(&tp1d2);
  1527. DeleteFfElement(&ged2);
  1528. DeleteBigNum(&ed2);
  1529. DeleteFfElement(&one_ffe);
  1530. DeleteFfElement(&temp);
  1531. DeleteFfElement(&h);
  1532. DeleteFfElement(&ge);
  1533. DeleteBigNum(&qm1dj);
  1534. DeleteBigNum(&j);
  1535. DeleteBigNum(&e);
  1536. DeleteBigNum(&t);
  1537. DeleteFfElement(&gg);
  1538. DeleteFfElement(&g);
  1539. DeleteBigNum(&remainder);
  1540. DeleteBigNum(&qm1d2);
  1541. DeleteBigNum(&two);
  1542. DeleteFfElement(&qm1_ffe);
  1543. DeleteBigNum(&one);
  1544. DeleteBigNum(&qm1);
  1545. return result;
  1546. }