1 /* $OpenBSD: bn_lib.c,v 1.86 2023/04/30 19:15:48 tb Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <assert.h> 60 #include <limits.h> 61 #include <stdio.h> 62 #include <string.h> 63 64 #include <openssl/opensslconf.h> 65 66 #include <openssl/err.h> 67 68 #include "bn_local.h" 69 #include "bn_internal.h" 70 71 BIGNUM * 72 BN_new(void) 73 { 74 BIGNUM *bn; 75 76 if ((bn = calloc(1, sizeof(BIGNUM))) == NULL) { 77 BNerror(ERR_R_MALLOC_FAILURE); 78 return NULL; 79 } 80 bn->flags = BN_FLG_MALLOCED; 81 82 return bn; 83 } 84 85 void 86 BN_init(BIGNUM *a) 87 { 88 memset(a, 0, sizeof(BIGNUM)); 89 } 90 91 void 92 BN_clear(BIGNUM *a) 93 { 94 if (a->d != NULL) 95 explicit_bzero(a->d, a->dmax * sizeof(a->d[0])); 96 a->top = 0; 97 a->neg = 0; 98 } 99 100 void 101 BN_free(BIGNUM *bn) 102 { 103 if (bn == NULL) 104 return; 105 106 if (!BN_get_flags(bn, BN_FLG_STATIC_DATA)) 107 freezero(bn->d, bn->dmax * sizeof(bn->d[0])); 108 109 if (!BN_get_flags(bn, BN_FLG_MALLOCED)) { 110 explicit_bzero(bn, sizeof(*bn)); 111 return; 112 } 113 114 freezero(bn, sizeof(*bn)); 115 } 116 117 void 118 BN_clear_free(BIGNUM *bn) 119 { 120 BN_free(bn); 121 } 122 123 void 124 BN_set_flags(BIGNUM *b, int n) 125 { 126 b->flags |= n; 127 } 128 129 int 130 BN_get_flags(const BIGNUM *b, int n) 131 { 132 return b->flags & n; 133 } 134 135 void 136 BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags) 137 { 138 int dest_flags; 139 140 dest_flags = (dest->flags & BN_FLG_MALLOCED) | 141 (b->flags & ~BN_FLG_MALLOCED) | BN_FLG_STATIC_DATA | flags; 142 143 *dest = *b; 144 dest->flags = dest_flags; 145 } 146 147 static const BN_ULONG bn_value_one_data = 1; 148 static const BIGNUM bn_value_one = { 149 .d = (BN_ULONG *)&bn_value_one_data, 150 .top = 1, 151 .dmax = 1, 152 .neg = 0, 153 .flags = BN_FLG_STATIC_DATA, 154 }; 155 156 const BIGNUM * 157 BN_value_one(void) 158 { 159 return &bn_value_one; 160 } 161 162 #ifndef HAVE_BN_WORD_CLZ 163 int 164 bn_word_clz(BN_ULONG w) 165 { 166 BN_ULONG bits, mask, shift; 167 168 bits = shift = BN_BITS2; 169 mask = 0; 170 171 while ((shift >>= 1) != 0) { 172 bits += (shift & mask) - (shift & ~mask); 173 mask = bn_ct_ne_zero_mask(w >> bits); 174 } 175 bits += 1 & mask; 176 177 bits -= bn_ct_eq_zero(w); 178 179 return BN_BITS2 - bits; 180 } 181 #endif 182 183 int 184 BN_num_bits_word(BN_ULONG w) 185 { 186 return BN_BITS2 - bn_word_clz(w); 187 } 188 189 int 190 BN_num_bits(const BIGNUM *a) 191 { 192 int i = a->top - 1; 193 194 if (BN_is_zero(a)) 195 return 0; 196 return ((i * BN_BITS2) + BN_num_bits_word(a->d[i])); 197 } 198 199 void 200 bn_correct_top(BIGNUM *a) 201 { 202 while (a->top > 0 && a->d[a->top - 1] == 0) 203 a->top--; 204 } 205 206 static int 207 bn_expand_internal(BIGNUM *bn, int words) 208 { 209 BN_ULONG *d; 210 211 if (words < 0) { 212 BNerror(BN_R_BIGNUM_TOO_LONG); // XXX 213 return 0; 214 } 215 216 if (words > INT_MAX / (4 * BN_BITS2)) { 217 BNerror(BN_R_BIGNUM_TOO_LONG); 218 return 0; 219 } 220 if (BN_get_flags(bn, BN_FLG_STATIC_DATA)) { 221 BNerror(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); 222 return 0; 223 } 224 225 d = recallocarray(bn->d, bn->dmax, words, sizeof(BN_ULONG)); 226 if (d == NULL) { 227 BNerror(ERR_R_MALLOC_FAILURE); 228 return 0; 229 } 230 bn->d = d; 231 bn->dmax = words; 232 233 return 1; 234 } 235 236 int 237 bn_expand(BIGNUM *bn, int bits) 238 { 239 int words; 240 241 if (bits < 0) 242 return 0; 243 244 if (bits > (INT_MAX - BN_BITS2 + 1)) 245 return 0; 246 247 words = (bits + BN_BITS2 - 1) / BN_BITS2; 248 249 return bn_wexpand(bn, words); 250 } 251 252 int 253 bn_wexpand(BIGNUM *bn, int words) 254 { 255 if (words < 0) 256 return 0; 257 258 if (words <= bn->dmax) 259 return 1; 260 261 return bn_expand_internal(bn, words); 262 } 263 264 BIGNUM * 265 BN_dup(const BIGNUM *a) 266 { 267 BIGNUM *t; 268 269 if (a == NULL) 270 return NULL; 271 272 t = BN_new(); 273 if (t == NULL) 274 return NULL; 275 if (!bn_copy(t, a)) { 276 BN_free(t); 277 return NULL; 278 } 279 return t; 280 } 281 282 static inline void 283 bn_copy_words(BN_ULONG *ap, const BN_ULONG *bp, int n) 284 { 285 while (n > 0) { 286 ap[0] = bp[0]; 287 ap++; 288 bp++; 289 n--; 290 } 291 } 292 293 BIGNUM * 294 BN_copy(BIGNUM *a, const BIGNUM *b) 295 { 296 if (a == b) 297 return (a); 298 299 if (!bn_wexpand(a, b->top)) 300 return (NULL); 301 302 bn_copy_words(a->d, b->d, b->top); 303 304 /* Copy constant time flag from b, but make it sticky on a. */ 305 a->flags |= b->flags & BN_FLG_CONSTTIME; 306 307 a->top = b->top; 308 a->neg = b->neg; 309 310 return (a); 311 } 312 313 int 314 bn_copy(BIGNUM *dst, const BIGNUM *src) 315 { 316 return BN_copy(dst, src) != NULL; 317 } 318 319 void 320 BN_swap(BIGNUM *a, BIGNUM *b) 321 { 322 int flags_old_a, flags_old_b; 323 BN_ULONG *tmp_d; 324 int tmp_top, tmp_dmax, tmp_neg; 325 326 327 flags_old_a = a->flags; 328 flags_old_b = b->flags; 329 330 tmp_d = a->d; 331 tmp_top = a->top; 332 tmp_dmax = a->dmax; 333 tmp_neg = a->neg; 334 335 a->d = b->d; 336 a->top = b->top; 337 a->dmax = b->dmax; 338 a->neg = b->neg; 339 340 b->d = tmp_d; 341 b->top = tmp_top; 342 b->dmax = tmp_dmax; 343 b->neg = tmp_neg; 344 345 a->flags = (flags_old_a & BN_FLG_MALLOCED) | 346 (flags_old_b & BN_FLG_STATIC_DATA); 347 b->flags = (flags_old_b & BN_FLG_MALLOCED) | 348 (flags_old_a & BN_FLG_STATIC_DATA); 349 } 350 351 BN_ULONG 352 BN_get_word(const BIGNUM *a) 353 { 354 if (a->top > 1) 355 return BN_MASK2; 356 else if (a->top == 1) 357 return a->d[0]; 358 /* a->top == 0 */ 359 return 0; 360 } 361 362 int 363 BN_set_word(BIGNUM *a, BN_ULONG w) 364 { 365 if (!bn_wexpand(a, 1)) 366 return (0); 367 a->neg = 0; 368 a->d[0] = w; 369 a->top = (w ? 1 : 0); 370 return (1); 371 } 372 373 int 374 BN_ucmp(const BIGNUM *a, const BIGNUM *b) 375 { 376 int i; 377 378 if (a->top < b->top) 379 return -1; 380 if (a->top > b->top) 381 return 1; 382 383 for (i = a->top - 1; i >= 0; i--) { 384 if (a->d[i] != b->d[i]) 385 return (a->d[i] > b->d[i] ? 1 : -1); 386 } 387 388 return 0; 389 } 390 391 int 392 BN_cmp(const BIGNUM *a, const BIGNUM *b) 393 { 394 if (a == NULL || b == NULL) { 395 if (a != NULL) 396 return -1; 397 if (b != NULL) 398 return 1; 399 return 0; 400 } 401 402 if (a->neg != b->neg) 403 return b->neg - a->neg; 404 405 if (a->neg) 406 return BN_ucmp(b, a); 407 408 return BN_ucmp(a, b); 409 } 410 411 int 412 BN_set_bit(BIGNUM *a, int n) 413 { 414 int i, j, k; 415 416 if (n < 0) 417 return 0; 418 419 i = n / BN_BITS2; 420 j = n % BN_BITS2; 421 if (a->top <= i) { 422 if (!bn_wexpand(a, i + 1)) 423 return (0); 424 for (k = a->top; k < i + 1; k++) 425 a->d[k] = 0; 426 a->top = i + 1; 427 } 428 429 a->d[i] |= (((BN_ULONG)1) << j); 430 return (1); 431 } 432 433 int 434 BN_clear_bit(BIGNUM *a, int n) 435 { 436 int i, j; 437 438 if (n < 0) 439 return 0; 440 441 i = n / BN_BITS2; 442 j = n % BN_BITS2; 443 if (a->top <= i) 444 return (0); 445 446 a->d[i] &= (~(((BN_ULONG)1) << j)); 447 bn_correct_top(a); 448 return (1); 449 } 450 451 int 452 BN_is_bit_set(const BIGNUM *a, int n) 453 { 454 int i, j; 455 456 if (n < 0) 457 return 0; 458 i = n / BN_BITS2; 459 j = n % BN_BITS2; 460 if (a->top <= i) 461 return 0; 462 return (int)(((a->d[i]) >> j) & ((BN_ULONG)1)); 463 } 464 465 int 466 BN_mask_bits(BIGNUM *a, int n) 467 { 468 int b, w; 469 470 if (n < 0) 471 return 0; 472 473 w = n / BN_BITS2; 474 b = n % BN_BITS2; 475 if (w >= a->top) 476 return 0; 477 if (b == 0) 478 a->top = w; 479 else { 480 a->top = w + 1; 481 a->d[w] &= ~(BN_MASK2 << b); 482 } 483 bn_correct_top(a); 484 return (1); 485 } 486 487 void 488 BN_set_negative(BIGNUM *bn, int neg) 489 { 490 bn->neg = ~BN_is_zero(bn) & bn_ct_ne_zero(neg); 491 } 492 493 /* 494 * Constant-time conditional swap of a and b. 495 * a and b are swapped if condition is not 0. 496 * The code assumes that at most one bit of condition is set. 497 * nwords is the number of words to swap. 498 * The code assumes that at least nwords are allocated in both a and b, 499 * and that no more than nwords are used by either a or b. 500 * a and b cannot be the same number 501 */ 502 void 503 BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) 504 { 505 BN_ULONG t; 506 int i; 507 508 assert(a != b); 509 assert((condition & (condition - 1)) == 0); 510 assert(sizeof(BN_ULONG) >= sizeof(int)); 511 512 condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; 513 514 t = (a->top^b->top) & condition; 515 a->top ^= t; 516 b->top ^= t; 517 518 #define BN_CONSTTIME_SWAP(ind) \ 519 do { \ 520 t = (a->d[ind] ^ b->d[ind]) & condition; \ 521 a->d[ind] ^= t; \ 522 b->d[ind] ^= t; \ 523 } while (0) 524 525 526 switch (nwords) { 527 default: 528 for (i = 10; i < nwords; i++) 529 BN_CONSTTIME_SWAP(i); 530 /* Fallthrough */ 531 case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */ 532 case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */ 533 case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */ 534 case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */ 535 case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */ 536 case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */ 537 case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */ 538 case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */ 539 case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */ 540 case 1: 541 BN_CONSTTIME_SWAP(0); 542 } 543 #undef BN_CONSTTIME_SWAP 544 } 545 546 /* 547 * Constant-time conditional swap of a and b. 548 * a and b are swapped if condition is not 0. 549 * nwords is the number of words to swap. 550 */ 551 int 552 BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, size_t nwords) 553 { 554 BN_ULONG t; 555 int i, words; 556 557 if (a == b) 558 return 1; 559 if (nwords > INT_MAX) 560 return 0; 561 words = (int)nwords; 562 if (!bn_wexpand(a, words) || !bn_wexpand(b, words)) 563 return 0; 564 if (a->top > words || b->top > words) { 565 BNerror(BN_R_INVALID_LENGTH); 566 return 0; 567 } 568 569 /* Set condition to 0 (if it was zero) or all 1s otherwise. */ 570 condition = ((~condition & (condition - 1)) >> (BN_BITS2 - 1)) - 1; 571 572 /* swap top field */ 573 t = (a->top ^ b->top) & condition; 574 a->top ^= t; 575 b->top ^= t; 576 577 /* swap neg field */ 578 t = (a->neg ^ b->neg) & condition; 579 a->neg ^= t; 580 b->neg ^= t; 581 582 /* swap BN_FLG_CONSTTIME from flag field */ 583 t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition; 584 a->flags ^= t; 585 b->flags ^= t; 586 587 /* swap the data */ 588 for (i = 0; i < words; i++) { 589 t = (a->d[i] ^ b->d[i]) & condition; 590 a->d[i] ^= t; 591 b->d[i] ^= t; 592 } 593 594 return 1; 595 } 596 597 void 598 BN_zero(BIGNUM *a) 599 { 600 a->neg = 0; 601 a->top = 0; 602 } 603 604 int 605 BN_one(BIGNUM *a) 606 { 607 return BN_set_word(a, 1); 608 } 609 610 int 611 BN_abs_is_word(const BIGNUM *a, const BN_ULONG w) 612 { 613 return (a->top == 1 && a->d[0] == w) || (w == 0 && a->top == 0); 614 } 615 616 int 617 BN_is_zero(const BIGNUM *bn) 618 { 619 BN_ULONG bits = 0; 620 int i; 621 622 for (i = 0; i < bn->top; i++) 623 bits |= bn->d[i]; 624 625 return bits == 0; 626 } 627 628 int 629 BN_is_one(const BIGNUM *a) 630 { 631 return BN_abs_is_word(a, 1) && !a->neg; 632 } 633 634 int 635 BN_is_word(const BIGNUM *a, const BN_ULONG w) 636 { 637 return BN_abs_is_word(a, w) && (w == 0 || !a->neg); 638 } 639 640 int 641 BN_is_odd(const BIGNUM *a) 642 { 643 return a->top > 0 && (a->d[0] & 1); 644 } 645 646 int 647 BN_is_negative(const BIGNUM *a) 648 { 649 return a->neg != 0; 650 } 651 652 char * 653 BN_options(void) 654 { 655 static int init = 0; 656 static char data[16]; 657 658 if (!init) { 659 init++; 660 #ifdef BN_LLONG 661 snprintf(data,sizeof data, "bn(%d,%d)", 662 (int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8); 663 #else 664 snprintf(data,sizeof data, "bn(%d,%d)", 665 (int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8); 666 #endif 667 } 668 return (data); 669 } 670 671 /* 672 * Bits of security, see SP800-57, section 5.6.11, table 2. 673 */ 674 int 675 BN_security_bits(int L, int N) 676 { 677 int secbits, bits; 678 679 if (L >= 15360) 680 secbits = 256; 681 else if (L >= 7680) 682 secbits = 192; 683 else if (L >= 3072) 684 secbits = 128; 685 else if (L >= 2048) 686 secbits = 112; 687 else if (L >= 1024) 688 secbits = 80; 689 else 690 return 0; 691 692 if (N == -1) 693 return secbits; 694 695 bits = N / 2; 696 if (bits < 80) 697 return 0; 698 699 return bits >= secbits ? secbits : bits; 700 } 701 702 BN_GENCB * 703 BN_GENCB_new(void) 704 { 705 BN_GENCB *cb; 706 707 if ((cb = calloc(1, sizeof(*cb))) == NULL) 708 return NULL; 709 710 return cb; 711 } 712 713 void 714 BN_GENCB_free(BN_GENCB *cb) 715 { 716 if (cb == NULL) 717 return; 718 free(cb); 719 } 720 721 /* Populate a BN_GENCB structure with an "old"-style callback */ 722 void 723 BN_GENCB_set_old(BN_GENCB *gencb, void (*cb)(int, int, void *), void *cb_arg) 724 { 725 gencb->ver = 1; 726 gencb->cb.cb_1 = cb; 727 gencb->arg = cb_arg; 728 } 729 730 /* Populate a BN_GENCB structure with a "new"-style callback */ 731 void 732 BN_GENCB_set(BN_GENCB *gencb, int (*cb)(int, int, BN_GENCB *), void *cb_arg) 733 { 734 gencb->ver = 2; 735 gencb->cb.cb_2 = cb; 736 gencb->arg = cb_arg; 737 } 738 739 void * 740 BN_GENCB_get_arg(BN_GENCB *cb) 741 { 742 return cb->arg; 743 } 744