pcpbnca.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  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 "pcpbn.h"
  34. #include "pcptool.h"
  35. /* BN(1) and reference */
  36. static IppsBigNumStateChunk cpChunk_BN1 = {
  37. {
  38. idCtxBigNum,
  39. ippBigNumPOS,
  40. 1,1,
  41. &cpChunk_BN1.value,&cpChunk_BN1.temporary
  42. },
  43. 1,0
  44. };
  45. IppsBigNumState* cpBN_OneRef(void)
  46. { return &cpChunk_BN1.bn; };
  47. /* BN(2) and reference */
  48. static IppsBigNumStateChunk cpChunk_BN2 = {
  49. {
  50. idCtxBigNum,
  51. ippBigNumPOS,
  52. 1,1,
  53. &cpChunk_BN2.value,&cpChunk_BN2.temporary
  54. },
  55. 2,0
  56. };
  57. IppsBigNumState* cpBN_TwoRef(void)
  58. { return &cpChunk_BN2.bn; };
  59. /* BN(3) and reference */
  60. static IppsBigNumStateChunk cpChunk_BN3 = {
  61. {
  62. idCtxBigNum,
  63. ippBigNumPOS,
  64. 1,1,
  65. &cpChunk_BN3.value,&cpChunk_BN3.temporary
  66. },
  67. 3,0
  68. };
  69. IppsBigNumState* cpBN_ThreeRef(void)
  70. { return &cpChunk_BN3.bn; };
  71. /*F*
  72. // Name: ippsBigNumGetSize
  73. //
  74. // Purpose: Returns size of BigNum ctx (bytes).
  75. //
  76. // Returns: Reason:
  77. // ippStsNullPtrErr pCtxSize == NULL
  78. // ippStsLengthErr len32 < 1
  79. // len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
  80. // ippStsNoErr no errors
  81. //
  82. // Parameters:
  83. // pCtxSize pointer BigNum ctx size
  84. //
  85. *F*/
  86. IPPFUN(IppStatus, ippsBigNumGetSize, (cpSize len32, cpSize *pCtxSize))
  87. {
  88. IPP_BAD_PTR1_RET(pCtxSize);
  89. IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
  90. {
  91. /* convert length to the number of BNU_CHUNK_T */
  92. cpSize len = INTERNAL_BNU_LENGTH(len32);
  93. /* reserve one BNU_CHUNK_T more for cpDiv_BNU,
  94. mul, mont exp operations */
  95. len++;
  96. *pCtxSize = sizeof(IppsBigNumState)
  97. + len*sizeof(BNU_CHUNK_T)
  98. + len*sizeof(BNU_CHUNK_T)
  99. + BN_ALIGNMENT-1;
  100. return ippStsNoErr;
  101. }
  102. }
  103. /*F*
  104. // Name: ippsBigNumInit
  105. //
  106. // Purpose: Init BigNum spec for future usage.
  107. //
  108. // Returns: Reason:
  109. // ippStsNullPtrErr pBN == NULL
  110. // ippStsLengthErr len32<1
  111. // len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
  112. // ippStsNoErr no errors
  113. //
  114. // Parameters:
  115. // len32 max BN length (32-bits segments)
  116. // pBN BigNum ctx
  117. //
  118. *F*/
  119. IPPFUN(IppStatus, ippsBigNumInit, (cpSize len32, IppsBigNumState* pBN))
  120. {
  121. IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
  122. IPP_BAD_PTR1_RET(pBN);
  123. pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
  124. {
  125. Ipp8u* ptr = (Ipp8u*)pBN;
  126. /* convert length to the number of BNU_CHUNK_T */
  127. cpSize len = INTERNAL_BNU_LENGTH(len32);
  128. BN_ID(pBN) = idCtxUnknown;
  129. BN_SIGN(pBN) = ippBigNumPOS;
  130. BN_SIZE(pBN) = 1; /* initial valie is zero */
  131. BN_ROOM(pBN) = len; /* close to what has been passed by user */
  132. /* reserve one BNU_CHUNK_T more for cpDiv_BNU,
  133. mul, mont exp operations */
  134. len++;
  135. /* allocate buffers */
  136. BN_NUMBER(pBN) = (BNU_CHUNK_T*)(ptr += sizeof(IppsBigNumState));
  137. BN_BUFFER(pBN) = (BNU_CHUNK_T*)(ptr += len*sizeof(BNU_CHUNK_T)); /* use expanded length here */
  138. /* set BN value and buffer to zero */
  139. ZEXPAND_BNU(BN_NUMBER(pBN), 0, len);
  140. ZEXPAND_BNU(BN_BUFFER(pBN), 0, len);
  141. BN_ID(pBN) = idCtxBigNum;
  142. return ippStsNoErr;
  143. }
  144. }
  145. /*F*
  146. // Name: ippsCmpZero_BN
  147. //
  148. // Purpose: Test BigNum value.
  149. //
  150. // Returns: Reason:
  151. // ippStsNullPtrErr pBN == NULL
  152. // pResult == NULL
  153. // ippStsContextMatchErr BN_VALID_ID()
  154. // ippStsNoErr no errors
  155. //
  156. // Parameters:
  157. // pBN BigNum ctx
  158. // pResult result of comparison
  159. //
  160. *F*/
  161. IPPFUN(IppStatus, ippsCmpZero_BN, (const IppsBigNumState* pBN, Ipp32u* pResult))
  162. {
  163. IPP_BAD_PTR2_RET(pBN, pResult);
  164. pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
  165. IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
  166. if(BN_SIZE(pBN)==1 && BN_NUMBER(pBN)[0]==0)
  167. *pResult = IS_ZERO;
  168. else if (BN_SIGN(pBN)==ippBigNumPOS)
  169. *pResult = GREATER_THAN_ZERO;
  170. else if (BN_SIGN(pBN)==ippBigNumNEG)
  171. *pResult = LESS_THAN_ZERO;
  172. return ippStsNoErr;
  173. }
  174. /*F*
  175. // Name: ippsCmp_BN
  176. //
  177. // Purpose: Compare two BigNums.
  178. //
  179. // Returns: Reason:
  180. // ippStsNullPtrErr pA == NULL
  181. // pB == NULL
  182. // pResult == NULL
  183. // ippStsContextMatchErr BN_VALID_ID(pA)
  184. // BN_VALID_ID(pB)
  185. // ippStsNoErr no errors
  186. //
  187. // Parameters:
  188. // pA BigNum ctx
  189. // pB BigNum ctx
  190. // pResult result of comparison
  191. //
  192. *F*/
  193. IPPFUN(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u *pResult))
  194. {
  195. IPP_BAD_PTR3_RET(pA, pB, pResult);
  196. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  197. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  198. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  199. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  200. {
  201. int res;
  202. if(BN_SIGN(pA)==BN_SIGN(pB)) {
  203. res = cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB));
  204. if(ippBigNumNEG==BN_SIGN(pA))
  205. res = -res;
  206. }
  207. else
  208. res = (ippBigNumPOS==BN_SIGN(pA))? 1 :-1;
  209. *pResult = (1==res)? IPP_IS_GT : (-1==res)? IPP_IS_LT : IPP_IS_EQ;
  210. return ippStsNoErr;
  211. }
  212. }
  213. /*F*
  214. // Name: ippsSet_BN
  215. //
  216. // Purpose: Set BigNum.
  217. //
  218. // Returns: Reason:
  219. // ippStsNullPtrErr pBN == NULL
  220. // pData == NULL
  221. // ippStsContextMatchErr BN_VALID_ID(pBN)
  222. // ippStsLengthErr len32 < 1
  223. // ippStsOutOfRangeErr len32 > BN_ROOM()
  224. // ippStsNoErr no errors
  225. //
  226. // Parameters:
  227. // sgn sign
  228. // len32 data size (in Ipp32u chunks)
  229. // pData source data pointer
  230. // pBn BigNum ctx
  231. //
  232. *F*/
  233. IPPFUN(IppStatus, ippsSet_BN, (IppsBigNumSGN sgn, cpSize len32, const Ipp32u* pData,
  234. IppsBigNumState* pBN))
  235. {
  236. IPP_BAD_PTR2_RET(pData, pBN);
  237. pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
  238. IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
  239. IPP_BADARG_RET(len32<1, ippStsLengthErr);
  240. /* compute real size */
  241. FIX_BNU(pData, len32);
  242. {
  243. cpSize len = INTERNAL_BNU_LENGTH(len32);
  244. IPP_BADARG_RET(len > BN_ROOM(pBN), ippStsOutOfRangeErr);
  245. ZEXPAND_COPY_BNU((Ipp32u*)BN_NUMBER(pBN), BN_ROOM(pBN)*(int)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), pData, len32);
  246. BN_SIZE(pBN) = len;
  247. if(len32==1 && pData[0] == 0)
  248. sgn = ippBigNumPOS; /* consider zero value as positive */
  249. BN_SIGN(pBN) = sgn;
  250. return ippStsNoErr;
  251. }
  252. }
  253. /*F*
  254. // Name: ippsRef_BN
  255. //
  256. // Purpose: Get BigNum info.
  257. //
  258. // Returns: Reason:
  259. // ippStsNullPtrErr pBN == NULL
  260. // ippStsContextMatchErr BN_VALID_ID(pBN)
  261. // ippStsNoErr no errors
  262. //
  263. // Parameters:
  264. // pSgn pointer to the sign
  265. // pBitSize pointer to the data size (in bits)
  266. // ppData pointer to the data buffer
  267. // pBN BigNum ctx
  268. //
  269. *F*/
  270. IPPFUN(IppStatus, ippsRef_BN, (IppsBigNumSGN* pSgn, cpSize* pBitSize, Ipp32u** const ppData,
  271. const IppsBigNumState *pBN))
  272. {
  273. IPP_BAD_PTR1_RET(pBN);
  274. pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
  275. IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
  276. if(pSgn)
  277. *pSgn = BN_SIGN(pBN);
  278. if(pBitSize) {
  279. cpSize bitLen = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN));
  280. *pBitSize = bitLen? bitLen : 1;
  281. }
  282. if(ppData)
  283. *ppData = (Ipp32u*)BN_NUMBER(pBN);
  284. return ippStsNoErr;
  285. }
  286. /*F*
  287. // Name: ippsAdd_BN
  288. //
  289. // Purpose: Add BigNum.
  290. //
  291. // Returns: Reason:
  292. // ippStsNullPtrErr pA == NULL
  293. // pB == NULL
  294. // pR == NULL
  295. // ippStsContextMatchErr BN_VALID_ID(pA)
  296. // BN_VALID_ID(pB)
  297. // BN_VALID_ID(pR)
  298. // ippStsOutOfRangeErr pR can not hold result
  299. // ippStsNoErr no errors
  300. //
  301. // Parameters:
  302. // pA source BigNum
  303. // pB source BigNum
  304. // pR resultant BigNum
  305. //
  306. *F*/
  307. IPPFUN(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
  308. {
  309. IPP_BAD_PTR3_RET(pA, pB, pR);
  310. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  311. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  312. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  313. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  314. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  315. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  316. {
  317. cpSize nsA = BN_SIZE(pA);
  318. cpSize nsB = BN_SIZE(pB);
  319. cpSize nsR = BN_ROOM(pR);
  320. IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr);
  321. {
  322. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  323. IppsBigNumSGN sgnA = BN_SIGN(pA);
  324. IppsBigNumSGN sgnB = BN_SIGN(pB);
  325. BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
  326. BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
  327. BNU_CHUNK_T carry;
  328. if(sgnA==sgnB) {
  329. if(nsA < nsB) {
  330. SWAP(nsA, nsB);
  331. SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
  332. }
  333. carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB);
  334. if(nsA>nsB)
  335. carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
  336. if(carry) {
  337. if(nsR>nsA)
  338. pDataR[nsA++] = carry;
  339. else
  340. IPP_ERROR_RET(ippStsOutOfRangeErr);
  341. }
  342. BN_SIGN(pR) = sgnA;
  343. }
  344. else {
  345. int cmpRes = cpCmp_BNU(pDataA, nsA, pDataB, nsB);
  346. if(0==cmpRes) {
  347. pDataR[0] = 0;
  348. BN_SIZE(pR) = 1;
  349. BN_SIGN(pR) = ippBigNumPOS;
  350. return ippStsNoErr;
  351. }
  352. if(0>cmpRes) {
  353. SWAP(nsA, nsB);
  354. SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
  355. }
  356. carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB);
  357. if(nsA>nsB)
  358. cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
  359. BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA);
  360. }
  361. FIX_BNU(pDataR, nsA);
  362. BN_SIZE(pR) = nsA;
  363. return ippStsNoErr;
  364. }
  365. }
  366. }
  367. /*F*
  368. // Name: ippsSub_BN
  369. //
  370. // Purpose: Subtcrac BigNum.
  371. //
  372. // Returns: Reason:
  373. // ippStsNullPtrErr pA == NULL
  374. // pB == NULL
  375. // pR == NULL
  376. // ippStsContextMatchErr BN_VALID_ID(pA)
  377. // BN_VALID_ID(pB)
  378. // BN_VALID_ID(pR)
  379. // ippStsOutOfRangeErr pR can not hold result
  380. // ippStsNoErr no errors
  381. //
  382. // Parameters:
  383. // pA source BigNum
  384. // pB source BigNum
  385. // pR resultant BigNum
  386. //
  387. *F*/
  388. IPPFUN(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
  389. {
  390. IPP_BAD_PTR3_RET(pA, pB, pR);
  391. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  392. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  393. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  394. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  395. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  396. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  397. {
  398. cpSize nsA = BN_SIZE(pA);
  399. cpSize nsB = BN_SIZE(pB);
  400. cpSize nsR = BN_ROOM(pR);
  401. IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr);
  402. {
  403. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  404. IppsBigNumSGN sgnA = BN_SIGN(pA);
  405. IppsBigNumSGN sgnB = BN_SIGN(pB);
  406. BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
  407. BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
  408. BNU_CHUNK_T carry;
  409. if(sgnA!=sgnB) {
  410. if(nsA < nsB) {
  411. SWAP(nsA, nsB);
  412. SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
  413. }
  414. carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB);
  415. if(nsA>nsB)
  416. carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
  417. if(carry) {
  418. if(nsR > nsA)
  419. pDataR[nsA++] = carry;
  420. else
  421. IPP_ERROR_RET(ippStsOutOfRangeErr);
  422. }
  423. BN_SIGN(pR) = sgnA;
  424. }
  425. else {
  426. int cmpRes= cpCmp_BNU(pDataA, nsA, pDataB, nsB);
  427. if(0==cmpRes) {
  428. ZEXPAND_BNU(pDataR,0, nsR);
  429. BN_SIZE(pR) = 1;
  430. BN_SIGN(pR) = ippBigNumPOS;
  431. return ippStsNoErr;
  432. }
  433. if(0>cmpRes) {
  434. SWAP(nsA, nsB);
  435. SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
  436. }
  437. carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB);
  438. if(nsA>nsB)
  439. cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
  440. BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA);
  441. }
  442. FIX_BNU(pDataR, nsA);
  443. BN_SIZE(pR) = nsA;
  444. return ippStsNoErr;
  445. }
  446. }
  447. }
  448. /*F*
  449. // Name: ippsMul_BN
  450. //
  451. // Purpose: Multiply BigNum.
  452. //
  453. // Returns: Reason:
  454. // ippStsNullPtrErr pA == NULL
  455. // pB == NULL
  456. // pR == NULL
  457. // ippStsContextMatchErr BN_VALID_ID(pA)
  458. // BN_VALID_ID(pB)
  459. // BN_VALID_ID(pR)
  460. // ippStsOutOfRangeErr pR can not hold result
  461. // ippStsNoErr no errors
  462. //
  463. // Parameters:
  464. // pA source BigNum
  465. // pB source BigNum
  466. // pR resultant BigNum
  467. //
  468. *F*/
  469. IPPFUN(IppStatus, ippsMul_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
  470. {
  471. IPP_BAD_PTR3_RET(pA, pB, pR);
  472. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  473. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  474. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  475. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  476. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  477. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  478. {
  479. BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
  480. BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
  481. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  482. cpSize nsA = BN_SIZE(pA);
  483. cpSize nsB = BN_SIZE(pB);
  484. cpSize nsR = BN_ROOM(pR);
  485. cpSize bitSizeA = BITSIZE_BNU(pDataA, nsA);
  486. cpSize bitSizeB = BITSIZE_BNU(pDataB, nsB);
  487. /* test if multiplicant/multiplier is zero */
  488. if(!bitSizeA || !bitSizeB) {
  489. BN_SIZE(pR) = 1;
  490. BN_SIGN(pR) = IppsBigNumPOS;
  491. pDataR[0] = 0;
  492. return ippStsNoErr;
  493. }
  494. /* test if even low estimation of product A*B exceeded */
  495. IPP_BADARG_RET(nsR*BNU_CHUNK_BITS < (bitSizeA+bitSizeB-1), ippStsOutOfRangeErr);
  496. {
  497. BNU_CHUNK_T* aData = pDataA;
  498. BNU_CHUNK_T* bData = pDataB;
  499. if(pA == pR) {
  500. aData = BN_BUFFER(pR);
  501. COPY_BNU(aData, pDataA, nsA);
  502. }
  503. if((pB == pR) && (pA != pB)) {
  504. bData = BN_BUFFER(pR);
  505. COPY_BNU(bData, pDataB, nsB);
  506. }
  507. /* clear result */
  508. ZEXPAND_BNU(pDataR, 0, nsR+1);
  509. cpMul_BNU_school(pDataR, aData, nsA, bData, nsB);
  510. nsR = (bitSizeA + bitSizeB + BNU_CHUNK_BITS - 1) /BNU_CHUNK_BITS;
  511. FIX_BNU(pDataR, nsR);
  512. IPP_BADARG_RET(nsR>BN_ROOM(pR), ippStsOutOfRangeErr);
  513. BN_SIZE(pR) = nsR;
  514. BN_SIGN(pR) = (BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG);
  515. return ippStsNoErr;
  516. }
  517. }
  518. }
  519. /*F*
  520. // Name: ippsDiv_BN
  521. //
  522. // Purpose: Divide BigNum.
  523. //
  524. // Returns: Reason:
  525. // ippStsNullPtrErr pA == NULL
  526. // pB == NULL
  527. // pQ == NULL
  528. // pR == NULL
  529. // ippStsContextMatchErr BN_VALID_ID(pA)
  530. // BN_VALID_ID(pB)
  531. // BN_VALID_ID(pQ)
  532. // BN_VALID_ID(pR)
  533. // ippStsOutOfRangeErr pQ and/or pR can not hold result
  534. // ippStsNoErr no errors
  535. //
  536. // Parameters:
  537. // pA source BigNum
  538. // pB source BigNum
  539. // pQ quotient BigNum
  540. // pR reminder BigNum
  541. //
  542. // A = Q*B + R, 0 <= val(R) < val(B), sgn(A)==sgn(R)
  543. //
  544. *F*/
  545. IPPFUN(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR))
  546. {
  547. IPP_BAD_PTR4_RET(pA, pB, pQ, pR);
  548. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  549. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  550. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  551. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  552. pQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pQ, BN_ALIGNMENT) );
  553. IPP_BADARG_RET(!BN_VALID_ID(pQ), ippStsContextMatchErr);
  554. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  555. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  556. IPP_BADARG_RET(BN_SIZE(pB)== 1 && BN_NUMBER(pB)[0]==0, ippStsDivByZeroErr);
  557. IPP_BADARG_RET(BN_ROOM(pR)<BN_SIZE(pB), ippStsOutOfRangeErr);
  558. IPP_BADARG_RET((int)BN_ROOM(pQ)<(int)(BN_SIZE(pA)-BN_SIZE(pB)), ippStsOutOfRangeErr);
  559. {
  560. BNU_CHUNK_T* pDataA = BN_BUFFER(pA);
  561. cpSize nsA = BN_SIZE(pA);
  562. BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
  563. cpSize nsB = BN_SIZE(pB);
  564. BNU_CHUNK_T* pDataQ = BN_NUMBER(pQ);
  565. cpSize nsQ;
  566. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  567. cpSize nsR;
  568. COPY_BNU(pDataA, BN_NUMBER(pA), nsA);
  569. nsR = cpDiv_BNU(pDataQ, &nsQ, pDataA, nsA, pDataB, nsB);
  570. COPY_BNU(pDataR, pDataA, nsR);
  571. BN_SIGN(pQ) = BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG;
  572. FIX_BNU(pDataQ, nsQ);
  573. BN_SIZE(pQ) = nsQ;
  574. if(nsQ==1 && pDataQ[0]==0) BN_SIGN(pQ) = ippBigNumPOS;
  575. BN_SIGN(pR) = BN_SIGN(pA);
  576. FIX_BNU(pDataR, nsR);
  577. BN_SIZE(pR) = nsR;
  578. if(nsR==1 && pDataR[0]==0) BN_SIGN(pR) = ippBigNumPOS;
  579. return ippStsNoErr;
  580. }
  581. }
  582. /*F*
  583. // Name: ippsMod_BN
  584. //
  585. // Purpose: reduction BigNum.
  586. //
  587. // Returns: Reason:
  588. // ippStsNullPtrErr pA == NULL
  589. // pM == NULL
  590. // pR == NULL
  591. // ippStsContextMatchErr BN_VALID_ID(pA)
  592. // BN_VALID_ID(pM)
  593. // BN_VALID_ID(pR)
  594. // ippStsOutOfRangeErr pR can not hold result
  595. // ippStsNoErr no errors
  596. //
  597. // Parameters:
  598. // pA source BigNum
  599. // pB source BigNum
  600. // pR reminder BigNum
  601. //
  602. // A = Q*M + R, 0 <= R < B
  603. //
  604. *F*/
  605. IPPFUN(IppStatus, ippsMod_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR))
  606. {
  607. IPP_BAD_PTR3_RET(pA, pM, pR);
  608. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  609. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  610. pM = (IppsBigNumState*)( IPP_ALIGNED_PTR(pM, BN_ALIGNMENT) );
  611. IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr);
  612. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  613. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  614. IPP_BADARG_RET(BN_NEGATIVE(pM), ippStsBadModulusErr);
  615. IPP_BADARG_RET(BN_SIZE(pM)== 1 && BN_NUMBER(pM)[0]==0, ippStsBadModulusErr);
  616. IPP_BADARG_RET(BN_ROOM(pR)<BN_SIZE(pM), ippStsOutOfRangeErr);
  617. if(cpEqu_BNU_CHUNK(BN_NUMBER(pA), BN_SIZE(pA), 0)) {
  618. BN_SIGN(pR) = ippBigNumPOS;
  619. BN_SIZE(pR) = 1;
  620. BN_NUMBER(pR)[0] = 0;
  621. }
  622. else {
  623. BNU_CHUNK_T* pDataM = BN_NUMBER(pM);
  624. cpSize nsM = BN_SIZE(pM);
  625. BNU_CHUNK_T* pBuffA = BN_BUFFER(pA);
  626. cpSize nsA = BN_SIZE(pA);
  627. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  628. cpSize nsR;
  629. COPY_BNU(pBuffA, BN_NUMBER(pA), nsA);
  630. nsR = cpMod_BNU(pBuffA, nsA, pDataM, nsM);
  631. COPY_BNU(pDataR, pBuffA, nsR);
  632. BN_SIZE(pR) = nsR;
  633. BN_SIGN(pR) = ippBigNumPOS;
  634. if(BN_NEGATIVE(pA) && !(nsR==1 && pDataR[0]==0)) {
  635. ZEXPAND_BNU(pDataR, nsR, nsM);
  636. cpSub_BNU(pDataR, pDataM, pDataR, nsM);
  637. FIX_BNU(pDataR, nsM);
  638. BN_SIZE(pR) = nsM;
  639. }
  640. }
  641. return ippStsNoErr;
  642. }
  643. /*F*
  644. // Name: ippsGcd_BN
  645. //
  646. // Purpose: compute GCD value.
  647. //
  648. // Returns: Reason:
  649. // ippStsNullPtrErr pA == NULL
  650. // pB == NULL
  651. // pG == NULL
  652. // ippStsContextMatchErr BN_VALID_ID(pA)
  653. // BN_VALID_ID(pB)
  654. // BN_VALID_ID(pG)
  655. // ippStsBadArgErr A==B==0
  656. // ippStsOutOfRangeErr pG can not hold result
  657. // ippStsNoErr no errors
  658. //
  659. // Parameters:
  660. // pA source BigNum
  661. // pB source BigNum
  662. // pG GCD value
  663. //
  664. *F*/
  665. IPPFUN(IppStatus, ippsGcd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pG))
  666. {
  667. IPP_BAD_PTR3_RET(pA, pB, pG);
  668. pA = (IppsBigNumState*)(IPP_ALIGNED_PTR(pA, BN_ALIGNMENT));
  669. pB = (IppsBigNumState*)(IPP_ALIGNED_PTR(pB, BN_ALIGNMENT));
  670. pG = (IppsBigNumState*)(IPP_ALIGNED_PTR(pG, BN_ALIGNMENT));
  671. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  672. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  673. IPP_BADARG_RET(!BN_VALID_ID(pG), ippStsContextMatchErr);
  674. IPP_BADARG_RET(BN_ROOM(pG) < IPP_MIN(BN_SIZE(pA), BN_SIZE(pB)), ippStsOutOfRangeErr);
  675. {
  676. IppsBigNumState* x = pA;
  677. IppsBigNumState* y = pB;
  678. IppsBigNumState* g = pG;
  679. int aIsZero = BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0;
  680. int bIsZero = BN_SIZE(pB)==1 && BN_NUMBER(pB)[0]==0;
  681. if(aIsZero && bIsZero)
  682. return ippStsBadArgErr;
  683. if(aIsZero && !bIsZero) {
  684. COPY_BNU(BN_NUMBER(g), BN_NUMBER(pB), BN_SIZE(pB));
  685. BN_SIZE(g) = BN_SIZE(pB);
  686. BN_SIGN(g) = ippBigNumPOS;
  687. return ippStsNoErr;
  688. }
  689. if(bIsZero && !aIsZero) {
  690. COPY_BNU(BN_NUMBER(g), BN_NUMBER(pA), BN_SIZE(pB));
  691. BN_SIZE(g) = BN_SIZE(pA);
  692. BN_SIGN(g) = ippBigNumPOS;
  693. return ippStsNoErr;
  694. }
  695. /*
  696. // Lehmer's algorithm requres that first number must be greater than second
  697. // x is the first, y is the second
  698. */
  699. {
  700. int cmpRes = cpCmp_BNU(BN_NUMBER(x), BN_SIZE(x), BN_NUMBER(y), BN_SIZE(y));
  701. if(0>cmpRes)
  702. SWAP_PTR(IppsBigNumState, x, y);
  703. if(0==cmpRes) {
  704. COPY_BNU(BN_NUMBER(g), BN_NUMBER(x), BN_SIZE(x));
  705. BN_SIGN(g) = ippBigNumPOS;
  706. BN_SIZE(g) = BN_SIZE(x);
  707. return ippStsNoErr;
  708. }
  709. if(BN_SIZE(x)==1) {
  710. BNU_CHUNK_T gcd = cpGcd_BNU(BN_NUMBER(x)[0], BN_NUMBER(y)[0]);
  711. BN_NUMBER(g)[0] = gcd;
  712. BN_SIZE(g) = 1;
  713. return ippStsNoErr;
  714. }
  715. }
  716. {
  717. Ipp32u* xBuffer = (Ipp32u*)BN_BUFFER(x);
  718. Ipp32u* yBuffer = (Ipp32u*)BN_BUFFER(y);
  719. Ipp32u* gBuffer = (Ipp32u*)BN_BUFFER(g);
  720. Ipp32u* xData = (Ipp32u*)BN_NUMBER(x);
  721. Ipp32u* yData = (Ipp32u*)BN_NUMBER(y);
  722. Ipp32u* gData = (Ipp32u*)BN_NUMBER(g);
  723. cpSize nsXmax = BN_ROOM(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
  724. cpSize nsYmax = BN_ROOM(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
  725. cpSize nsGmax = BN_ROOM(g)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
  726. cpSize nsX = BN_SIZE(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
  727. cpSize nsY = BN_SIZE(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
  728. Ipp32u* T;
  729. Ipp32u* u;
  730. FIX_BNU(xData, nsX);
  731. FIX_BNU(yData, nsY);
  732. /* init buffers */
  733. ZEXPAND_COPY_BNU(xBuffer, nsX, xData, nsXmax);
  734. ZEXPAND_COPY_BNU(yBuffer, nsY, yData, nsYmax);
  735. T = gBuffer;
  736. u = gData;
  737. ZEXPAND_BNU(T, 0, nsGmax);
  738. ZEXPAND_BNU(u, 0, nsGmax);
  739. while(nsX > (cpSize)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) {
  740. /* xx and yy is the high-order digits of x and y (yy could be 0) */
  741. Ipp64u xx = (Ipp64u)(xBuffer[nsX-1]);
  742. Ipp64u yy = (nsY < nsX)? 0 : (Ipp64u)(yBuffer[nsY-1]);
  743. Ipp64s AA = 1;
  744. Ipp64s BB = 0;
  745. Ipp64s CC = 0;
  746. Ipp64s DD = 1;
  747. Ipp64s t;
  748. while((yy+CC)!=0 && (yy+DD)!=0) {
  749. Ipp64u q = ( xx + AA ) / ( yy + CC );
  750. Ipp64u q1 = ( xx + BB ) / ( yy + DD );
  751. if(q!=q1)
  752. break;
  753. t = AA - q*CC;
  754. AA = CC;
  755. CC = t;
  756. t = BB - q*DD;
  757. BB = DD;
  758. DD = t;
  759. t = xx - q*yy;
  760. xx = yy;
  761. yy = t;
  762. }
  763. if(BB == 0) {
  764. /* T = x mod y */
  765. cpSize nsT = cpMod_BNU32(xBuffer, nsX, yBuffer, nsY);
  766. ZEXPAND_BNU(T, 0, nsGmax);
  767. COPY_BNU(T, xBuffer, nsT);
  768. /* a = b; b = T; */
  769. ZEXPAND_BNU(xBuffer, 0, nsXmax);
  770. COPY_BNU(xBuffer, yBuffer, nsY);
  771. ZEXPAND_BNU(yBuffer, 0, nsYmax);
  772. COPY_BNU(yBuffer, T, nsY);
  773. }
  774. else {
  775. Ipp32u carry;
  776. /*
  777. // T = AA*x + BB*y;
  778. // u = CC*x + DD*y;
  779. // b = u; a = T;
  780. */
  781. if((AA <= 0)&&(BB>=0)) {
  782. Ipp32u a1 = (Ipp32u)(-AA);
  783. carry = cpMulDgt_BNU32(T, yBuffer, nsY, (Ipp32u)BB);
  784. carry = cpMulDgt_BNU32(u, xBuffer, nsY, a1);
  785. /* T = BB*y - AA*x; */
  786. carry = cpSub_BNU32(T, T, u, nsY);
  787. }
  788. else {
  789. if((AA >= 0)&&(BB<=0)) {
  790. Ipp32u b1 = (Ipp32u)(-BB);
  791. carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA);
  792. carry = cpMulDgt_BNU32(u, yBuffer, nsY, b1);
  793. /* T = AA*x - BB*y; */
  794. carry = cpSub_BNU32(T, T, u, nsY);
  795. }
  796. else {
  797. /*AA*BB>=0 */
  798. carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA);
  799. carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)BB);
  800. /* T = AA*x + BB*y; */
  801. carry = cpAdd_BNU32(T, T, u, nsY);
  802. }
  803. }
  804. /* Now T is reserved. We use only u for intermediate results. */
  805. if((CC <= 0)&&(DD>=0)){
  806. Ipp32u c1 = (Ipp32u)(-CC);
  807. /* u = x*CC; x = u; */
  808. carry = cpMulDgt_BNU32(u, xBuffer, nsY, c1);
  809. COPY_BNU(xBuffer, u, nsY);
  810. /* u = y*DD; */
  811. carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD);
  812. /* u = DD*y - CC*x; */
  813. carry = cpSub_BNU32(u, u, xBuffer, nsY);
  814. }
  815. else {
  816. if((CC >= 0)&&(DD<=0)){
  817. Ipp32u d1 = (Ipp32u)(-DD);
  818. /* u = y*DD; y = u */
  819. carry = cpMulDgt_BNU32(u, yBuffer, nsY, d1);
  820. COPY_BNU(yBuffer, u, nsY);
  821. /* u = CC*x; */
  822. carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC);
  823. /* u = CC*x - DD*y; */
  824. carry = cpSub_BNU32(u, u, yBuffer, nsY);
  825. }
  826. else {
  827. /*CC*DD>=0 */
  828. /* y = y*DD */
  829. carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD);
  830. COPY_BNU(yBuffer, u, nsY);
  831. /* u = x*CC */
  832. carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC);
  833. /* u = x*CC + y*DD */
  834. carry = cpAdd_BNU32(u, u, yBuffer, nsY);
  835. }
  836. }
  837. /* y = u; x = T; */
  838. COPY_BNU(yBuffer, u, nsY);
  839. COPY_BNU(xBuffer, T, nsY);
  840. }
  841. FIX_BNU(xBuffer, nsX);
  842. FIX_BNU(yBuffer, nsY);
  843. if (nsY > nsX) {
  844. SWAP_PTR(IppsBigNumState, x, y);
  845. SWAP(nsX, nsY);
  846. }
  847. if (nsY==1 && yBuffer[nsY-1]==0) {
  848. /* End evaluation */
  849. ZEXPAND_BNU(gData, 0, nsGmax);
  850. COPY_BNU(gData, xBuffer, nsX);
  851. BN_SIZE(g) = INTERNAL_BNU_LENGTH(nsX);
  852. BN_SIGN(g) = ippBigNumPOS;
  853. return ippStsNoErr;
  854. }
  855. }
  856. BN_NUMBER(g)[0] = cpGcd_BNU(((BNU_CHUNK_T*)xBuffer)[0], ((BNU_CHUNK_T*)yBuffer)[0]);
  857. BN_SIZE(g) = 1;
  858. BN_SIGN(g) = ippBigNumPOS;
  859. return ippStsNoErr;
  860. }
  861. }
  862. }
  863. /*F*
  864. // Name: ippsModInv_BN
  865. //
  866. // Purpose: Multiplicative Inversion BigNum.
  867. //
  868. // Returns: Reason:
  869. // ippStsNullPtrErr pA == NULL
  870. // pM == NULL
  871. // pR == NULL
  872. // ippStsContextMatchErr BN_VALID_ID(pA)
  873. // BN_VALID_ID(pM)
  874. // BN_VALID_ID(pR)
  875. // ippStsBadArgErr A<=0
  876. // ippStsBadModulusErr M<=0
  877. // ippStsScaleRangeErr A>=M
  878. // ippStsOutOfRangeErr pR can not hold result
  879. // ippStsNoErr no errors
  880. // ippStsBadModulusErr inversion not found
  881. //
  882. // Parameters:
  883. // pA source (value) BigNum
  884. // pM source (modulus) BigNum
  885. // pR reminder BigNum
  886. //
  887. *F*/
  888. IPPFUN(IppStatus, ippsModInv_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR) )
  889. {
  890. IPP_BAD_PTR3_RET(pA, pM, pR);
  891. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  892. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  893. pM = (IppsBigNumState*)( IPP_ALIGNED_PTR(pM, BN_ALIGNMENT) );
  894. IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr);
  895. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  896. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  897. IPP_BADARG_RET(BN_ROOM(pR) < BN_SIZE(pM), ippStsOutOfRangeErr);
  898. IPP_BADARG_RET(BN_NEGATIVE(pA) || (BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0), ippStsBadArgErr);
  899. IPP_BADARG_RET(BN_NEGATIVE(pM) || (BN_SIZE(pM)==1 && BN_NUMBER(pM)[0]==0), ippStsBadModulusErr);
  900. IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pM), BN_SIZE(pM)) >= 0, ippStsScaleRangeErr);
  901. {
  902. cpSize nsR = cpModInv_BNU(BN_NUMBER(pR),
  903. BN_NUMBER(pA), BN_SIZE(pA),
  904. BN_NUMBER(pM), BN_SIZE(pM),
  905. BN_BUFFER(pR), BN_BUFFER(pA), BN_BUFFER(pM));
  906. if(nsR) {
  907. BN_SIGN(pR) = ippBigNumPOS;
  908. BN_SIZE(pR) = nsR;
  909. return ippStsNoErr;
  910. }
  911. else
  912. return ippStsBadModulusErr;
  913. }
  914. }