/src/dropbear/libtommath/bn_s_mp_mul_digs.c
Line | Count | Source |
1 | | #include "tommath_private.h" |
2 | | #ifdef BN_S_MP_MUL_DIGS_C |
3 | | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 | | /* SPDX-License-Identifier: Unlicense */ |
5 | | |
6 | | /* multiplies |a| * |b| and only computes upto digs digits of result |
7 | | * HAC pp. 595, Algorithm 14.12 Modified so you can control how |
8 | | * many digits of output are created. |
9 | | */ |
10 | | mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) |
11 | 68.6k | { |
12 | 68.6k | mp_int t; |
13 | 68.6k | mp_err err; |
14 | 68.6k | int pa, pb, ix, iy; |
15 | 68.6k | mp_digit u; |
16 | 68.6k | mp_word r; |
17 | 68.6k | mp_digit tmpx, *tmpt, *tmpy; |
18 | | |
19 | 68.6k | if (digs < 0) { |
20 | 0 | return MP_VAL; |
21 | 0 | } |
22 | | |
23 | | /* can we use the fast multiplier? */ |
24 | 68.6k | if ((digs < MP_WARRAY) && |
25 | 68.6k | (MP_MIN(a->used, b->used) < MP_MAXFAST)) { |
26 | 68.6k | return s_mp_mul_digs_fast(a, b, c, digs); |
27 | 68.6k | } |
28 | | |
29 | 0 | if ((err = mp_init_size(&t, digs)) != MP_OKAY) { |
30 | 0 | return err; |
31 | 0 | } |
32 | 0 | t.used = digs; |
33 | | |
34 | | /* compute the digits of the product directly */ |
35 | 0 | pa = a->used; |
36 | 0 | for (ix = 0; ix < pa; ix++) { |
37 | | /* set the carry to zero */ |
38 | 0 | u = 0; |
39 | | |
40 | | /* limit ourselves to making digs digits of output */ |
41 | 0 | pb = MP_MIN(b->used, digs - ix); |
42 | | |
43 | | /* setup some aliases */ |
44 | | /* copy of the digit from a used within the nested loop */ |
45 | 0 | tmpx = a->dp[ix]; |
46 | | |
47 | | /* an alias for the destination shifted ix places */ |
48 | 0 | tmpt = t.dp + ix; |
49 | | |
50 | | /* an alias for the digits of b */ |
51 | 0 | tmpy = b->dp; |
52 | | |
53 | | /* compute the columns of the output and propagate the carry */ |
54 | 0 | for (iy = 0; iy < pb; iy++) { |
55 | | /* compute the column as a mp_word */ |
56 | 0 | r = (mp_word)*tmpt + |
57 | 0 | ((mp_word)tmpx * (mp_word)*tmpy++) + |
58 | 0 | (mp_word)u; |
59 | | |
60 | | /* the new column is the lower part of the result */ |
61 | 0 | *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK); |
62 | | |
63 | | /* get the carry word from the result */ |
64 | 0 | u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); |
65 | 0 | } |
66 | | /* set carry if it is placed below digs */ |
67 | 0 | if ((ix + iy) < digs) { |
68 | 0 | *tmpt = u; |
69 | 0 | } |
70 | 0 | } |
71 | |
|
72 | 0 | mp_clamp(&t); |
73 | 0 | mp_exch(&t, c); |
74 | |
|
75 | 0 | mp_clear(&t); |
76 | 0 | return MP_OKAY; |
77 | 0 | } |
78 | | #endif |