/src/dropbear/libtommath/bn_mp_div_2d.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "tommath_private.h" |
2 | | #ifdef BN_MP_DIV_2D_C |
3 | | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 | | /* SPDX-License-Identifier: Unlicense */ |
5 | | |
6 | | /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ |
7 | | mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) |
8 | 3.23M | { |
9 | 3.23M | mp_digit D, r, rr; |
10 | 3.23M | int x; |
11 | 3.23M | mp_err err; |
12 | | |
13 | | /* if the shift count is <= 0 then we do no work */ |
14 | 3.23M | if (b <= 0) { |
15 | 3 | err = mp_copy(a, c); |
16 | 3 | if (d != NULL) { |
17 | 0 | mp_zero(d); |
18 | 0 | } |
19 | 3 | return err; |
20 | 3 | } |
21 | | |
22 | | /* copy */ |
23 | 3.23M | if ((err = mp_copy(a, c)) != MP_OKAY) { |
24 | 0 | return err; |
25 | 0 | } |
26 | | /* 'a' should not be used after here - it might be the same as d */ |
27 | | |
28 | | /* get the remainder */ |
29 | 3.23M | if (d != NULL) { |
30 | 3.10M | if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) { |
31 | 0 | return err; |
32 | 0 | } |
33 | 3.10M | } |
34 | | |
35 | | /* shift by as many digits in the bit count */ |
36 | 3.23M | if (b >= MP_DIGIT_BIT) { |
37 | 3.10M | mp_rshd(c, b / MP_DIGIT_BIT); |
38 | 3.10M | } |
39 | | |
40 | | /* shift any bit count < MP_DIGIT_BIT */ |
41 | 3.23M | D = (mp_digit)(b % MP_DIGIT_BIT); |
42 | 3.23M | if (D != 0u) { |
43 | 3.15M | mp_digit *tmpc, mask, shift; |
44 | | |
45 | | /* mask */ |
46 | 3.15M | mask = ((mp_digit)1 << D) - 1uL; |
47 | | |
48 | | /* shift for lsb */ |
49 | 3.15M | shift = (mp_digit)MP_DIGIT_BIT - D; |
50 | | |
51 | | /* alias */ |
52 | 3.15M | tmpc = c->dp + (c->used - 1); |
53 | | |
54 | | /* carry */ |
55 | 3.15M | r = 0; |
56 | 33.6M | for (x = c->used - 1; x >= 0; x--) { |
57 | | /* get the lower bits of this word in a temp */ |
58 | 30.4M | rr = *tmpc & mask; |
59 | | |
60 | | /* shift the current word and mix in the carry bits from the previous word */ |
61 | 30.4M | *tmpc = (*tmpc >> D) | (r << shift); |
62 | 30.4M | --tmpc; |
63 | | |
64 | | /* set the carry to the carry bits of the current word found above */ |
65 | 30.4M | r = rr; |
66 | 30.4M | } |
67 | 3.15M | } |
68 | 3.23M | mp_clamp(c); |
69 | 3.23M | return MP_OKAY; |
70 | 3.23M | } |
71 | | #endif |