s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / third_party / heimdal / lib / hcrypto / libtommath / bn_mp_mul_2d.c
1 #include "tommath_private.h"
2 #ifdef BN_MP_MUL_2D_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
5
6 /* shift left by a certain bit count */
7 mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
8 {
9    mp_digit d;
10    mp_err   err;
11
12    /* copy */
13    if (a != c) {
14       if ((err = mp_copy(a, c)) != MP_OKAY) {
15          return err;
16       }
17    }
18
19    if (c->alloc < (c->used + (b / MP_DIGIT_BIT) + 1)) {
20       if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) {
21          return err;
22       }
23    }
24
25    /* shift by as many digits in the bit count */
26    if (b >= MP_DIGIT_BIT) {
27       if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) {
28          return err;
29       }
30    }
31
32    /* shift any bit count < MP_DIGIT_BIT */
33    d = (mp_digit)(b % MP_DIGIT_BIT);
34    if (d != 0u) {
35       mp_digit *tmpc, shift, mask, r, rr;
36       int x;
37
38       /* bitmask for carries */
39       mask = ((mp_digit)1 << d) - (mp_digit)1;
40
41       /* shift for msbs */
42       shift = (mp_digit)MP_DIGIT_BIT - d;
43
44       /* alias */
45       tmpc = c->dp;
46
47       /* carry */
48       r    = 0;
49       for (x = 0; x < c->used; x++) {
50          /* get the higher bits of the current word */
51          rr = (*tmpc >> shift) & mask;
52
53          /* shift the current word and OR in the carry */
54          *tmpc = ((*tmpc << d) | r) & MP_MASK;
55          ++tmpc;
56
57          /* set the carry to the carry bits of the current word */
58          r = rr;
59       }
60
61       /* set final carry */
62       if (r != 0u) {
63          c->dp[(c->used)++] = r;
64       }
65    }
66    mp_clamp(c);
67    return MP_OKAY;
68 }
69 #endif