LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hcrypto/libtommath - bn_s_mp_exptmod.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 0 96 0.0 %
Date: 2024-04-13 12:30:31 Functions: 0 1 0.0 %

          Line data    Source code
       1             : #include "tommath_private.h"
       2             : #ifdef BN_S_MP_EXPTMOD_C
       3             : /* LibTomMath, multiple-precision integer library -- Tom St Denis */
       4             : /* SPDX-License-Identifier: Unlicense */
       5             : 
       6             : #ifdef MP_LOW_MEM
       7             : #   define TAB_SIZE 32
       8             : #   define MAX_WINSIZE 5
       9             : #else
      10             : #   define TAB_SIZE 256
      11             : #   define MAX_WINSIZE 0
      12             : #endif
      13             : 
      14           0 : mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
      15             : {
      16           0 :    mp_int  M[TAB_SIZE], res, mu;
      17           0 :    mp_digit buf;
      18           0 :    mp_err   err;
      19           0 :    int      bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
      20           0 :    mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu);
      21             : 
      22             :    /* find window size */
      23           0 :    x = mp_count_bits(X);
      24           0 :    if (x <= 7) {
      25           0 :       winsize = 2;
      26           0 :    } else if (x <= 36) {
      27           0 :       winsize = 3;
      28           0 :    } else if (x <= 140) {
      29           0 :       winsize = 4;
      30           0 :    } else if (x <= 450) {
      31           0 :       winsize = 5;
      32           0 :    } else if (x <= 1303) {
      33           0 :       winsize = 6;
      34           0 :    } else if (x <= 3529) {
      35           0 :       winsize = 7;
      36             :    } else {
      37           0 :       winsize = 8;
      38             :    }
      39             : 
      40           0 :    winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize;
      41             : 
      42             :    /* init M array */
      43             :    /* init first cell */
      44           0 :    if ((err = mp_init(&M[1])) != MP_OKAY) {
      45           0 :       return err;
      46             :    }
      47             : 
      48             :    /* now init the second half of the array */
      49           0 :    for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
      50           0 :       if ((err = mp_init(&M[x])) != MP_OKAY) {
      51           0 :          for (y = 1<<(winsize-1); y < x; y++) {
      52           0 :             mp_clear(&M[y]);
      53             :          }
      54           0 :          mp_clear(&M[1]);
      55           0 :          return err;
      56             :       }
      57             :    }
      58             : 
      59             :    /* create mu, used for Barrett reduction */
      60           0 :    if ((err = mp_init(&mu)) != MP_OKAY)                           goto LBL_M;
      61             : 
      62           0 :    if (redmode == 0) {
      63           0 :       if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY)             goto LBL_MU;
      64           0 :       redux = mp_reduce;
      65             :    } else {
      66           0 :       if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY)        goto LBL_MU;
      67           0 :       redux = mp_reduce_2k_l;
      68             :    }
      69             : 
      70             :    /* create M table
      71             :     *
      72             :     * The M table contains powers of the base,
      73             :     * e.g. M[x] = G**x mod P
      74             :     *
      75             :     * The first half of the table is not
      76             :     * computed though accept for M[0] and M[1]
      77             :     */
      78           0 :    if ((err = mp_mod(G, P, &M[1])) != MP_OKAY)                    goto LBL_MU;
      79             : 
      80             :    /* compute the value at M[1<<(winsize-1)] by squaring
      81             :     * M[1] (winsize-1) times
      82             :     */
      83           0 :    if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
      84             : 
      85           0 :    for (x = 0; x < (winsize - 1); x++) {
      86             :       /* square it */
      87           0 :       if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)],
      88           0 :                         &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
      89             : 
      90             :       /* reduce modulo P */
      91           0 :       if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, &mu)) != MP_OKAY) goto LBL_MU;
      92             :    }
      93             : 
      94             :    /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
      95             :     * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
      96             :     */
      97           0 :    for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
      98           0 :       if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY)     goto LBL_MU;
      99           0 :       if ((err = redux(&M[x], P, &mu)) != MP_OKAY)                goto LBL_MU;
     100             :    }
     101             : 
     102             :    /* setup result */
     103           0 :    if ((err = mp_init(&res)) != MP_OKAY)                          goto LBL_MU;
     104           0 :    mp_set(&res, 1uL);
     105             : 
     106             :    /* set initial mode and bit cnt */
     107           0 :    mode   = 0;
     108           0 :    bitcnt = 1;
     109           0 :    buf    = 0;
     110           0 :    digidx = X->used - 1;
     111           0 :    bitcpy = 0;
     112           0 :    bitbuf = 0;
     113             : 
     114           0 :    for (;;) {
     115             :       /* grab next digit as required */
     116           0 :       if (--bitcnt == 0) {
     117             :          /* if digidx == -1 we are out of digits */
     118           0 :          if (digidx == -1) {
     119           0 :             break;
     120             :          }
     121             :          /* read next digit and reset the bitcnt */
     122           0 :          buf    = X->dp[digidx--];
     123           0 :          bitcnt = (int)MP_DIGIT_BIT;
     124             :       }
     125             : 
     126             :       /* grab the next msb from the exponent */
     127           0 :       y     = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL;
     128           0 :       buf <<= (mp_digit)1;
     129             : 
     130             :       /* if the bit is zero and mode == 0 then we ignore it
     131             :        * These represent the leading zero bits before the first 1 bit
     132             :        * in the exponent.  Technically this opt is not required but it
     133             :        * does lower the # of trivial squaring/reductions used
     134             :        */
     135           0 :       if ((mode == 0) && (y == 0)) {
     136           0 :          continue;
     137             :       }
     138             : 
     139             :       /* if the bit is zero and mode == 1 then we square */
     140           0 :       if ((mode == 1) && (y == 0)) {
     141           0 :          if ((err = mp_sqr(&res, &res)) != MP_OKAY)               goto LBL_RES;
     142           0 :          if ((err = redux(&res, P, &mu)) != MP_OKAY)              goto LBL_RES;
     143           0 :          continue;
     144             :       }
     145             : 
     146             :       /* else we add it to the window */
     147           0 :       bitbuf |= (y << (winsize - ++bitcpy));
     148           0 :       mode    = 2;
     149             : 
     150           0 :       if (bitcpy == winsize) {
     151             :          /* ok window is filled so square as required and multiply  */
     152             :          /* square first */
     153           0 :          for (x = 0; x < winsize; x++) {
     154           0 :             if ((err = mp_sqr(&res, &res)) != MP_OKAY)            goto LBL_RES;
     155           0 :             if ((err = redux(&res, P, &mu)) != MP_OKAY)           goto LBL_RES;
     156             :          }
     157             : 
     158             :          /* then multiply */
     159           0 :          if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY)  goto LBL_RES;
     160           0 :          if ((err = redux(&res, P, &mu)) != MP_OKAY)             goto LBL_RES;
     161             : 
     162             :          /* empty window and reset */
     163           0 :          bitcpy = 0;
     164           0 :          bitbuf = 0;
     165           0 :          mode   = 1;
     166             :       }
     167             :    }
     168             : 
     169             :    /* if bits remain then square/multiply */
     170           0 :    if ((mode == 2) && (bitcpy > 0)) {
     171             :       /* square then multiply if the bit is set */
     172           0 :       for (x = 0; x < bitcpy; x++) {
     173           0 :          if ((err = mp_sqr(&res, &res)) != MP_OKAY)               goto LBL_RES;
     174           0 :          if ((err = redux(&res, P, &mu)) != MP_OKAY)              goto LBL_RES;
     175             : 
     176           0 :          bitbuf <<= 1;
     177           0 :          if ((bitbuf & (1 << winsize)) != 0) {
     178             :             /* then multiply */
     179           0 :             if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY)     goto LBL_RES;
     180           0 :             if ((err = redux(&res, P, &mu)) != MP_OKAY)           goto LBL_RES;
     181             :          }
     182             :       }
     183             :    }
     184             : 
     185           0 :    mp_exch(&res, Y);
     186           0 :    err = MP_OKAY;
     187           0 : LBL_RES:
     188           0 :    mp_clear(&res);
     189           0 : LBL_MU:
     190           0 :    mp_clear(&mu);
     191           0 : LBL_M:
     192           0 :    mp_clear(&M[1]);
     193           0 :    for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
     194           0 :       mp_clear(&M[x]);
     195             :    }
     196           0 :    return err;
     197             : }
     198             : #endif

Generated by: LCOV version 1.14