xref: /openbsd-src/lib/libcrypto/bn/bn_lib.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
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