No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

378 líneas
7.9 KiB

  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.] */
  56. #include <openssl/bn.h>
  57. #include <string.h>
  58. #include <openssl/err.h>
  59. #include <openssl/mem.h>
  60. #include "internal.h"
  61. int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  62. const BIGNUM *tmp;
  63. int a_neg = a->neg, ret;
  64. /* a + b a+b
  65. * a + -b a-b
  66. * -a + b b-a
  67. * -a + -b -(a+b)
  68. */
  69. if (a_neg ^ b->neg) {
  70. /* only one is negative */
  71. if (a_neg) {
  72. tmp = a;
  73. a = b;
  74. b = tmp;
  75. }
  76. /* we are now a - b */
  77. if (BN_ucmp(a, b) < 0) {
  78. if (!BN_usub(r, b, a)) {
  79. return 0;
  80. }
  81. r->neg = 1;
  82. } else {
  83. if (!BN_usub(r, a, b)) {
  84. return 0;
  85. }
  86. r->neg = 0;
  87. }
  88. return 1;
  89. }
  90. ret = BN_uadd(r, a, b);
  91. r->neg = a_neg;
  92. return ret;
  93. }
  94. int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  95. int max, min, dif;
  96. BN_ULONG *ap, *bp, *rp, carry, t1, t2;
  97. const BIGNUM *tmp;
  98. if (a->top < b->top) {
  99. tmp = a;
  100. a = b;
  101. b = tmp;
  102. }
  103. max = a->top;
  104. min = b->top;
  105. dif = max - min;
  106. if (bn_wexpand(r, max + 1) == NULL) {
  107. return 0;
  108. }
  109. r->top = max;
  110. ap = a->d;
  111. bp = b->d;
  112. rp = r->d;
  113. carry = bn_add_words(rp, ap, bp, min);
  114. rp += min;
  115. ap += min;
  116. bp += min;
  117. if (carry) {
  118. while (dif) {
  119. dif--;
  120. t1 = *(ap++);
  121. t2 = (t1 + 1) & BN_MASK2;
  122. *(rp++) = t2;
  123. if (t2) {
  124. carry = 0;
  125. break;
  126. }
  127. }
  128. if (carry) {
  129. /* carry != 0 => dif == 0 */
  130. *rp = 1;
  131. r->top++;
  132. }
  133. }
  134. if (dif && rp != ap) {
  135. while (dif--) {
  136. /* copy remaining words if ap != rp */
  137. *(rp++) = *(ap++);
  138. }
  139. }
  140. r->neg = 0;
  141. return 1;
  142. }
  143. int BN_add_word(BIGNUM *a, BN_ULONG w) {
  144. BN_ULONG l;
  145. int i;
  146. w &= BN_MASK2;
  147. /* degenerate case: w is zero */
  148. if (!w) {
  149. return 1;
  150. }
  151. /* degenerate case: a is zero */
  152. if (BN_is_zero(a)) {
  153. return BN_set_word(a, w);
  154. }
  155. /* handle 'a' when negative */
  156. if (a->neg) {
  157. a->neg = 0;
  158. i = BN_sub_word(a, w);
  159. if (!BN_is_zero(a)) {
  160. a->neg = !(a->neg);
  161. }
  162. return i;
  163. }
  164. for (i = 0; w != 0 && i < a->top; i++) {
  165. a->d[i] = l = (a->d[i] + w) & BN_MASK2;
  166. w = (w > l) ? 1 : 0;
  167. }
  168. if (w && i == a->top) {
  169. if (bn_wexpand(a, a->top + 1) == NULL) {
  170. return 0;
  171. }
  172. a->top++;
  173. a->d[i] = w;
  174. }
  175. return 1;
  176. }
  177. int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  178. int max;
  179. int add = 0, neg = 0;
  180. const BIGNUM *tmp;
  181. /* a - b a-b
  182. * a - -b a+b
  183. * -a - b -(a+b)
  184. * -a - -b b-a
  185. */
  186. if (a->neg) {
  187. if (b->neg) {
  188. tmp = a;
  189. a = b;
  190. b = tmp;
  191. } else {
  192. add = 1;
  193. neg = 1;
  194. }
  195. } else {
  196. if (b->neg) {
  197. add = 1;
  198. neg = 0;
  199. }
  200. }
  201. if (add) {
  202. if (!BN_uadd(r, a, b)) {
  203. return 0;
  204. }
  205. r->neg = neg;
  206. return 1;
  207. }
  208. /* We are actually doing a - b :-) */
  209. max = (a->top > b->top) ? a->top : b->top;
  210. if (bn_wexpand(r, max) == NULL) {
  211. return 0;
  212. }
  213. if (BN_ucmp(a, b) < 0) {
  214. if (!BN_usub(r, b, a)) {
  215. return 0;
  216. }
  217. r->neg = 1;
  218. } else {
  219. if (!BN_usub(r, a, b)) {
  220. return 0;
  221. }
  222. r->neg = 0;
  223. }
  224. return 1;
  225. }
  226. int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  227. int max, min, dif;
  228. register BN_ULONG t1, t2, *ap, *bp, *rp;
  229. int i, carry;
  230. max = a->top;
  231. min = b->top;
  232. dif = max - min;
  233. if (dif < 0) /* hmm... should not be happening */
  234. {
  235. OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3);
  236. return 0;
  237. }
  238. if (bn_wexpand(r, max) == NULL) {
  239. return 0;
  240. }
  241. ap = a->d;
  242. bp = b->d;
  243. rp = r->d;
  244. carry = 0;
  245. for (i = min; i != 0; i--) {
  246. t1 = *(ap++);
  247. t2 = *(bp++);
  248. if (carry) {
  249. carry = (t1 <= t2);
  250. t1 = (t1 - t2 - 1) & BN_MASK2;
  251. } else {
  252. carry = (t1 < t2);
  253. t1 = (t1 - t2) & BN_MASK2;
  254. }
  255. *(rp++) = t1 & BN_MASK2;
  256. }
  257. if (carry) /* subtracted */
  258. {
  259. if (!dif) {
  260. /* error: a < b */
  261. return 0;
  262. }
  263. while (dif) {
  264. dif--;
  265. t1 = *(ap++);
  266. t2 = (t1 - 1) & BN_MASK2;
  267. *(rp++) = t2;
  268. if (t1) {
  269. break;
  270. }
  271. }
  272. }
  273. if (dif > 0 && rp != ap) {
  274. memcpy(rp, ap, sizeof(*rp) * dif);
  275. }
  276. r->top = max;
  277. r->neg = 0;
  278. bn_correct_top(r);
  279. return 1;
  280. }
  281. int BN_sub_word(BIGNUM *a, BN_ULONG w) {
  282. int i;
  283. w &= BN_MASK2;
  284. /* degenerate case: w is zero */
  285. if (!w) {
  286. return 1;
  287. }
  288. /* degenerate case: a is zero */
  289. if (BN_is_zero(a)) {
  290. i = BN_set_word(a, w);
  291. if (i != 0) {
  292. BN_set_negative(a, 1);
  293. }
  294. return i;
  295. }
  296. /* handle 'a' when negative */
  297. if (a->neg) {
  298. a->neg = 0;
  299. i = BN_add_word(a, w);
  300. a->neg = 1;
  301. return i;
  302. }
  303. if ((a->top == 1) && (a->d[0] < w)) {
  304. a->d[0] = w - a->d[0];
  305. a->neg = 1;
  306. return 1;
  307. }
  308. i = 0;
  309. for (;;) {
  310. if (a->d[i] >= w) {
  311. a->d[i] -= w;
  312. break;
  313. } else {
  314. a->d[i] = (a->d[i] - w) & BN_MASK2;
  315. i++;
  316. w = 1;
  317. }
  318. }
  319. if ((a->d[i] == 0) && (i == (a->top - 1))) {
  320. a->top--;
  321. }
  322. return 1;
  323. }