/src/dropbear/libtommath/bn_s_mp_invmod_slow.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "tommath_private.h" |
2 | | #ifdef BN_S_MP_INVMOD_SLOW_C |
3 | | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 | | /* SPDX-License-Identifier: Unlicense */ |
5 | | |
6 | | /* hac 14.61, pp608 */ |
7 | | mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) |
8 | 131 | { |
9 | 131 | mp_int x, y, u, v, A, B, C, D; |
10 | 131 | mp_err err; |
11 | | |
12 | | /* b cannot be negative */ |
13 | 131 | if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) { |
14 | 0 | return MP_VAL; |
15 | 0 | } |
16 | | |
17 | | /* init temps */ |
18 | 131 | if ((err = mp_init_multi(&x, &y, &u, &v, |
19 | 131 | &A, &B, &C, &D, NULL)) != MP_OKAY) { |
20 | 0 | return err; |
21 | 0 | } |
22 | | |
23 | | /* x = a, y = b */ |
24 | 131 | if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR; |
25 | 131 | if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR; |
26 | | |
27 | | /* 2. [modified] if x,y are both even then return an error! */ |
28 | 131 | if (MP_IS_EVEN(&x) && MP_IS_EVEN(&y)) { |
29 | 2 | err = MP_VAL; |
30 | 2 | goto LBL_ERR; |
31 | 2 | } |
32 | | |
33 | | /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ |
34 | 129 | if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; |
35 | 129 | if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; |
36 | 129 | mp_set(&A, 1uL); |
37 | 129 | mp_set(&D, 1uL); |
38 | | |
39 | 10.7k | top: |
40 | | /* 4. while u is even do */ |
41 | 20.1k | while (MP_IS_EVEN(&u)) { |
42 | | /* 4.1 u = u/2 */ |
43 | 9.38k | if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; |
44 | | |
45 | | /* 4.2 if A or B is odd then */ |
46 | 9.38k | if (MP_IS_ODD(&A) || MP_IS_ODD(&B)) { |
47 | | /* A = (A+y)/2, B = (B-x)/2 */ |
48 | 3.95k | if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR; |
49 | 3.95k | if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; |
50 | 3.95k | } |
51 | | /* A = A/2, B = B/2 */ |
52 | 9.38k | if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR; |
53 | 9.38k | if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; |
54 | 9.38k | } |
55 | | |
56 | | /* 5. while v is even do */ |
57 | 26.1k | while (MP_IS_EVEN(&v)) { |
58 | | /* 5.1 v = v/2 */ |
59 | 15.3k | if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; |
60 | | |
61 | | /* 5.2 if C or D is odd then */ |
62 | 15.3k | if (MP_IS_ODD(&C) || MP_IS_ODD(&D)) { |
63 | | /* C = (C+y)/2, D = (D-x)/2 */ |
64 | 6.83k | if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR; |
65 | 6.83k | if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; |
66 | 6.83k | } |
67 | | /* C = C/2, D = D/2 */ |
68 | 15.3k | if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR; |
69 | 15.3k | if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR; |
70 | 15.3k | } |
71 | | |
72 | | /* 6. if u >= v then */ |
73 | 10.7k | if (mp_cmp(&u, &v) != MP_LT) { |
74 | | /* u = u - v, A = A - C, B = B - D */ |
75 | 4.80k | if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; |
76 | | |
77 | 4.80k | if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR; |
78 | | |
79 | 4.80k | if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; |
80 | 5.99k | } else { |
81 | | /* v - v - u, C = C - A, D = D - B */ |
82 | 5.99k | if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; |
83 | | |
84 | 5.99k | if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR; |
85 | | |
86 | 5.99k | if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; |
87 | 5.99k | } |
88 | | |
89 | | /* if not zero goto step 4 */ |
90 | 10.7k | if (!MP_IS_ZERO(&u)) { |
91 | 10.6k | goto top; |
92 | 10.6k | } |
93 | | |
94 | | /* now a = C, b = D, gcd == g*v */ |
95 | | |
96 | | /* if v != 1 then there is no inverse */ |
97 | 129 | if (mp_cmp_d(&v, 1uL) != MP_EQ) { |
98 | 17 | err = MP_VAL; |
99 | 17 | goto LBL_ERR; |
100 | 17 | } |
101 | | |
102 | | /* if its too low */ |
103 | 169 | while (mp_cmp_d(&C, 0uL) == MP_LT) { |
104 | 57 | if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR; |
105 | 57 | } |
106 | | |
107 | | /* too big */ |
108 | 163 | while (mp_cmp_mag(&C, b) != MP_LT) { |
109 | 51 | if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR; |
110 | 51 | } |
111 | | |
112 | | /* C is now the inverse */ |
113 | 112 | mp_exch(&C, c); |
114 | 112 | err = MP_OKAY; |
115 | 131 | LBL_ERR: |
116 | 131 | mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); |
117 | 131 | return err; |
118 | 112 | } |
119 | | #endif |