Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/mpi/mpi-mul.c
Line
Count
Source (jump to first uncovered line)
1
/* mpi-mul.c  -  MPI functions
2
 * Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
3
 *
4
 * This file is part of Libgcrypt.
5
 *
6
 * Libgcrypt is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * Libgcrypt is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19
 *
20
 * Note: This code is heavily based on the GNU MP Library.
21
 *   Actually it's the same code with only minor changes in the
22
 *   way the data is stored; this is to support the abstraction
23
 *   of an optional secure memory allocation which may be used
24
 *   to avoid revealing of sensitive data due to paging etc.
25
 */
26
27
#include <config.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include "mpi-internal.h"
31
32
33
void
34
_gcry_mpi_mul_ui (gcry_mpi_t prod, gcry_mpi_t mult, unsigned long small_mult)
35
0
{
36
0
    mpi_size_t size, prod_size;
37
0
    mpi_ptr_t  prod_ptr;
38
0
    mpi_limb_t cy;
39
0
    int sign;
40
41
0
    size = mult->nlimbs;
42
0
    sign = mult->sign;
43
44
0
    if( !size || !small_mult ) {
45
0
  prod->nlimbs = 0;
46
0
  prod->sign = 0;
47
0
  return;
48
0
    }
49
50
0
    prod_size = size + 1;
51
0
    if( prod->alloced < prod_size )
52
0
  mpi_resize( prod, prod_size );
53
0
    prod_ptr = prod->d;
54
55
0
    cy = _gcry_mpih_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult );
56
0
    if( cy )
57
0
  prod_ptr[size++] = cy;
58
0
    prod->nlimbs = size;
59
0
    prod->sign = sign;
60
0
}
61
62
63
void
64
_gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt)
65
0
{
66
0
    mpi_size_t usize, wsize, limb_cnt;
67
0
    mpi_ptr_t wp;
68
0
    mpi_limb_t wlimb;
69
0
    int usign, wsign;
70
71
0
    usize = u->nlimbs;
72
0
    usign = u->sign;
73
74
0
    if( !usize ) {
75
0
  w->nlimbs = 0;
76
0
  w->sign = 0;
77
0
  return;
78
0
    }
79
80
0
    limb_cnt = cnt / BITS_PER_MPI_LIMB;
81
0
    wsize = usize + limb_cnt + 1;
82
0
    if( w->alloced < wsize )
83
0
  mpi_resize(w, wsize );
84
0
    wp = w->d;
85
0
    wsize = usize + limb_cnt;
86
0
    wsign = usign;
87
88
0
    cnt %= BITS_PER_MPI_LIMB;
89
0
    if( cnt ) {
90
0
  wlimb = _gcry_mpih_lshift( wp + limb_cnt, u->d, usize, cnt );
91
0
  if( wlimb ) {
92
0
      wp[wsize] = wlimb;
93
0
      wsize++;
94
0
  }
95
0
    }
96
0
    else {
97
0
  MPN_COPY_DECR( wp + limb_cnt, u->d, usize );
98
0
    }
99
100
    /* Zero all whole limbs at low end.  Do it here and not before calling
101
     * mpn_lshift, not to lose for U == W.  */
102
0
    MPN_ZERO( wp, limb_cnt );
103
104
0
    w->nlimbs = wsize;
105
0
    w->sign = wsign;
106
0
}
107
108
109
void
110
_gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
111
17.8M
{
112
17.8M
    mpi_size_t usize, vsize, wsize;
113
17.8M
    mpi_ptr_t up, vp, wp;
114
17.8M
    mpi_limb_t cy;
115
17.8M
    int usign, vsign, usecure, vsecure, sign_product;
116
17.8M
    int assign_wp=0;
117
17.8M
    mpi_ptr_t tmp_limb=NULL;
118
17.8M
    unsigned int tmp_limb_nlimbs = 0;
119
120
17.8M
    if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
121
688k
  usize = v->nlimbs;
122
688k
  usign = v->sign;
123
688k
  usecure = mpi_is_secure(v);
124
688k
  up    = v->d;
125
688k
  vsize = u->nlimbs;
126
688k
  vsign = u->sign;
127
688k
  vsecure = mpi_is_secure(u);
128
688k
  vp    = u->d;
129
688k
    }
130
17.1M
    else {
131
17.1M
  usize = u->nlimbs;
132
17.1M
  usign = u->sign;
133
17.1M
  usecure = mpi_is_secure(u);
134
17.1M
  up    = u->d;
135
17.1M
  vsize = v->nlimbs;
136
17.1M
  vsign = v->sign;
137
17.1M
  vsecure = mpi_is_secure(v);
138
17.1M
  vp    = v->d;
139
17.1M
    }
140
17.8M
    sign_product = usign ^ vsign;
141
17.8M
    wp = w->d;
142
143
    /* Ensure W has space enough to store the result.  */
144
17.8M
    wsize = usize + vsize;
145
17.8M
    if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) {
146
        /* w is not allocated in secure space but u or v is.  To make sure
147
         * that no temporray results are stored in w, we temporary use
148
         * a newly allocated limb space for w */
149
0
        wp = mpi_alloc_limb_space( wsize, 1 );
150
0
        assign_wp = 2; /* mark it as 2 so that we can later copy it back to
151
                        * mormal memory */
152
0
    }
153
17.8M
    else if( w->alloced < wsize ) {
154
69.8k
  if( wp == up || wp == vp ) {
155
17.7k
      wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) );
156
17.7k
      assign_wp = 1;
157
17.7k
  }
158
52.0k
  else {
159
52.0k
      mpi_resize(w, wsize );
160
52.0k
      wp = w->d;
161
52.0k
  }
162
69.8k
    }
163
17.7M
    else { /* Make U and V not overlap with W. */
164
17.7M
  if( wp == up ) {
165
      /* W and U are identical.  Allocate temporary space for U.  */
166
7.65M
            tmp_limb_nlimbs = usize;
167
7.65M
      up = tmp_limb = mpi_alloc_limb_space( usize, usecure  );
168
      /* Is V identical too?  Keep it identical with U.  */
169
7.65M
      if( wp == vp )
170
1.04M
    vp = up;
171
      /* Copy to the temporary space.  */
172
7.65M
      MPN_COPY( up, wp, usize );
173
7.65M
  }
174
10.1M
  else if( wp == vp ) {
175
      /* W and V are identical.  Allocate temporary space for V.  */
176
1.38M
            tmp_limb_nlimbs = vsize;
177
1.38M
      vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure );
178
      /* Copy to the temporary space.  */
179
1.38M
      MPN_COPY( vp, wp, vsize );
180
1.38M
  }
181
17.7M
    }
182
183
17.8M
    if( !vsize )
184
1.10M
  wsize = 0;
185
16.7M
    else {
186
16.7M
  cy = _gcry_mpih_mul( wp, up, usize, vp, vsize );
187
16.7M
  wsize -= cy? 0:1;
188
16.7M
    }
189
190
17.8M
    if( assign_wp ) {
191
17.7k
        if (assign_wp == 2) {
192
            /* copy the temp wp from secure memory back to normal memory */
193
0
      mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0);
194
0
      MPN_COPY (tmp_wp, wp, wsize);
195
0
            _gcry_mpi_free_limb_space (wp, 0);
196
0
            wp = tmp_wp;
197
0
        }
198
17.7k
  _gcry_mpi_assign_limb_space( w, wp, wsize );
199
17.7k
    }
200
17.8M
    w->nlimbs = wsize;
201
17.8M
    w->sign = sign_product;
202
17.8M
    if( tmp_limb )
203
9.03M
  _gcry_mpi_free_limb_space (tmp_limb, tmp_limb_nlimbs);
204
17.8M
}
205
206
207
void
208
_gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
209
2.18M
{
210
2.18M
  mpi_mul (w, u, v);
211
2.18M
  _gcry_mpi_tdiv_r (w, w, m);
212
2.18M
}