pcpbnuarith.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 "owncp.h"
  32. #include "pcpbnuarith.h"
  33. #include "pcpbnumisc.h"
  34. /* Function cpAdd_BNU - addition of 2 BigNumbers */
  35. BNU_CHUNK_T cpAdd_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)
  36. {
  37. BNU_CHUNK_T carry = 0;
  38. cpSize i;
  39. for(i=0; i<ns; i++) {
  40. ADD_ABC(carry, pR[i], pA[i],pB[i], carry);
  41. }
  42. return carry;
  43. }
  44. /* Function cpSub_BNU - subtraction of 2 BigNumbers */
  45. BNU_CHUNK_T cpSub_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)
  46. {
  47. BNU_CHUNK_T borrow = 0;
  48. cpSize i;
  49. for(i=0; i<ns; i++) {
  50. SUB_ABC(borrow, pR[i], pA[i], pB[i], borrow);
  51. }
  52. return borrow;
  53. }
  54. /* Function cpInc_BNU - increment BigNumber */
  55. BNU_CHUNK_T cpInc_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)
  56. {
  57. cpSize i;
  58. for(i=0; i<ns && val; i++) {
  59. BNU_CHUNK_T carry;
  60. ADD_AB(carry, pR[i], pA[i], val);
  61. val = carry;
  62. }
  63. if(pR!=pA)
  64. for(; i<ns; i++)
  65. pR[i] = pA[i];
  66. return val;
  67. }
  68. BNU_CHUNK_T cpDec_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)
  69. {
  70. cpSize i;
  71. for(i=0; i<ns && val; i++) {
  72. BNU_CHUNK_T borrow;
  73. SUB_AB(borrow, pR[i], pA[i], val);
  74. val = borrow;
  75. }
  76. if(pR!=pA)
  77. for(; i<ns; i++)
  78. pR[i] = pA[i];
  79. return val;
  80. }
  81. BNU_CHUNK_T cpAddMulDgt_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)
  82. {
  83. BNU_CHUNK_T extension = 0;
  84. cpSize i;
  85. for(i=0; i<ns; i++) {
  86. BNU_CHUNK_T rH, rL;
  87. MUL_AB(rH, rL, pA[i], val);
  88. ADD_ABC(extension, pR[i], pR[i], rL, extension);
  89. extension += rH;
  90. }
  91. return extension;
  92. }
  93. BNU_CHUNK_T cpMulAdc_BNU_school(BNU_CHUNK_T* pR,
  94. const BNU_CHUNK_T* pA, cpSize nsA,
  95. const BNU_CHUNK_T* pB, cpSize nsB)
  96. {
  97. const BNU_CHUNK_T* pa = (BNU_CHUNK_T*)pA;
  98. const BNU_CHUNK_T* pb = (BNU_CHUNK_T*)pB;
  99. BNU_CHUNK_T* pr = (BNU_CHUNK_T*)pR;
  100. BNU_CHUNK_T extension = 0;
  101. cpSize i, j;
  102. ZEXPAND_BNU(pr, 0, nsA+nsB);
  103. for(i=0; i<nsB; i++ ) {
  104. BNU_CHUNK_T b = pb[i];
  105. for(j=0, extension=0; j<nsA; j++ ) {
  106. BNU_CHUNK_T rH, rL;
  107. MUL_AB(rH, rL, pa[j], b);
  108. ADD_ABC(extension, pr[i+j], pr[i+j], rL, extension);
  109. extension += rH;
  110. }
  111. pr[i+j] = extension;
  112. }
  113. return extension;
  114. }
  115. BNU_CHUNK_T cpSqrAdc_BNU_school(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA)
  116. {
  117. cpSize i;
  118. BNU_CHUNK_T extension;
  119. BNU_CHUNK_T rH, rL;
  120. /* init result */
  121. pR[0] = 0;
  122. for(i=1, extension=0; i<nsA; i++) {
  123. MUL_AB(rH, rL, pA[i], pA[0]);
  124. ADD_AB(extension, pR[i], rL, extension);
  125. extension += rH;
  126. }
  127. pR[i] = extension;
  128. /* add other a[i]*a[j] */
  129. for(i=1; i<nsA-1; i++) {
  130. BNU_CHUNK_T a = pA[i];
  131. cpSize j;
  132. for(j=i+1, extension=0; j<nsA; j++) {
  133. MUL_AB(rH, rL, pA[j], a);
  134. ADD_ABC(extension, pR[i+j], rL, pR[i+j], extension);
  135. extension += rH;
  136. }
  137. pR[i+j] = extension;
  138. }
  139. /* double a[i]*a[j] */
  140. for(i=1, extension=0; i<(2*nsA-1); i++) {
  141. ADD_ABC(extension, pR[i], pR[i], pR[i], extension);
  142. }
  143. pR[i] = extension;
  144. /* add a[i]^2 */
  145. for(i=0, extension=0; i<nsA; i++) {
  146. MUL_AB(rH, rL, pA[i], pA[i]);
  147. ADD_ABC(extension, pR[2*i], pR[2*i], rL, extension);
  148. ADD_ABC(extension, pR[2*i+1], pR[2*i+1], rH, extension);
  149. }
  150. return pR[2*nsA-1];
  151. }
  152. BNU_CHUNK_T cpGcd_BNU(BNU_CHUNK_T a, BNU_CHUNK_T b)
  153. {
  154. BNU_CHUNK_T gcd, t, r;
  155. if(a > b){
  156. gcd = a;
  157. t = b;
  158. } else {
  159. t = a;
  160. gcd = b;
  161. }
  162. while (t != 0) {
  163. r = gcd % t;
  164. gcd = t;
  165. t = r;
  166. }
  167. return gcd;
  168. }
  169. /*
  170. // cpMAC_BNU
  171. //
  172. // Multiply with ACcumulation
  173. // Computes r <- r + a * b, returns real size of the r in the size_r variable
  174. // Returns 0 if there are no enought buffer size to write to r[MAX(size_r + 1, size_a + size_b) - 1]
  175. // Returns 1 if no error
  176. //
  177. // Note:
  178. // DO NOT run in inplace mode
  179. // The minimum buffer size for the r must be (size_a + size_b - 1)
  180. // the maximum buffer size for the r is MAX(size_r + 1, size_a + size_b)
  181. */
  182. static int cpMac_BNU(BNU_CHUNK_T* pR, cpSize nsR,
  183. const BNU_CHUNK_T* pA, cpSize nsA,
  184. const BNU_CHUNK_T* pB, cpSize nsB)
  185. {
  186. /* cleanup the rest of destination buffer */
  187. ZEXPAND_BNU(pR, nsR, nsA+nsB-1);
  188. {
  189. BNU_CHUNK_T expansion = 0;
  190. cpSize i;
  191. for(i=0; i<nsB && !expansion; i++) {
  192. expansion = cpAddMulDgt_BNU(pR+i, pA, nsA, pB[i]);
  193. if(expansion)
  194. expansion = cpInc_BNU(pR+i+nsA, pR+i+nsA, nsR-i-nsA, expansion);
  195. }
  196. if(expansion)
  197. return 0;
  198. else { /* compute real size */
  199. FIX_BNU(pR, nsR);
  200. return nsR;
  201. }
  202. }
  203. }
  204. int cpModInv_BNU(BNU_CHUNK_T* pInv,
  205. const BNU_CHUNK_T* pA, cpSize nsA,
  206. const BNU_CHUNK_T* pM, cpSize nsM,
  207. BNU_CHUNK_T* bufInv, BNU_CHUNK_T* bufA, BNU_CHUNK_T* bufM)
  208. {
  209. FIX_BNU(pA, nsA);
  210. FIX_BNU(pM, nsM);
  211. /* inv(1) = 1 */
  212. if(nsA==1 && pA[0]==1) {
  213. pInv[0] = 1;
  214. return 1;
  215. }
  216. {
  217. cpSize moduloSize = nsM;
  218. BNU_CHUNK_T* X1 = pInv;
  219. BNU_CHUNK_T* X2 = bufM;
  220. BNU_CHUNK_T* Q = bufInv;
  221. cpSize nsX1 = 1;
  222. cpSize nsX2 = 1;
  223. cpSize nsQ;
  224. COPY_BNU(bufA, pA, nsA);
  225. ZEXPAND_BNU(X1, 0, moduloSize);
  226. ZEXPAND_BNU(X2, 0, moduloSize);
  227. X2[0] = 1;
  228. for(;;) {
  229. nsM = cpDiv_BNU(Q, &nsQ, (BNU_CHUNK_T*)pM, nsM, bufA, nsA);
  230. nsX1 = cpMac_BNU(X1,moduloSize, Q,nsQ, X2,nsX2);
  231. if (nsM==1 && pM[0]==1) {
  232. ////ZEXPAND_BNU(X2, nsX2, moduloSize);
  233. nsX2 = cpMac_BNU(X2,moduloSize, X1,nsX1, bufA, nsA);
  234. COPY_BNU((BNU_CHUNK_T*)pM, X2, moduloSize);
  235. cpSub_BNU(pInv, pM, X1, moduloSize);
  236. FIX_BNU(pInv, moduloSize);
  237. return moduloSize;
  238. }
  239. else if (nsM==1 && pM[0]==0) {
  240. cpMul_BNU_school((BNU_CHUNK_T*)pM, X1,nsX1, bufA, nsA);
  241. /* gcd = buf_a */
  242. return 0;
  243. }
  244. nsA = cpDiv_BNU(Q, &nsQ, bufA, nsA, (BNU_CHUNK_T*)pM, nsM);
  245. nsX2 = cpMac_BNU(X2,moduloSize, Q,nsQ, X1,nsX1);
  246. if(nsA==1 && bufA[0]==1) {
  247. ////ZEXPAND_BNU(X1, nsX1, moduloSize);
  248. nsX1 = cpMac_BNU(X1, moduloSize, X2, nsX2, pM, nsM);
  249. COPY_BNU((BNU_CHUNK_T*)pM, X1, moduloSize);
  250. COPY_BNU(pInv, X2, nsX2);
  251. return nsX2;
  252. }
  253. else if (nsA==1 && bufA[0]==0) {
  254. /* gcd = m */
  255. COPY_BNU(X1, pM, nsM);
  256. cpMul_BNU_school((BNU_CHUNK_T*)pM, X2, nsX2, X1, nsM);
  257. return 0;
  258. }
  259. }
  260. }
  261. }