Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/mpi/mpi-add.c
Line
Count
Source (jump to first uncovered line)
1
/* mpi-add.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
31
#include "mpi-internal.h"
32
33
34
/****************
35
 * Add the unsigned integer V to the mpi-integer U and store the
36
 * result in W. U and V may be the same.
37
 */
38
void
39
_gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
40
4.59k
{
41
4.59k
    mpi_ptr_t wp, up;
42
4.59k
    mpi_size_t usize, wsize;
43
4.59k
    int usign, wsign;
44
45
4.59k
    usize = u->nlimbs;
46
4.59k
    usign = u->sign;
47
4.59k
    wsign = 0;
48
49
    /* If not space for W (and possible carry), increase space.  */
50
4.59k
    wsize = usize + 1;
51
4.59k
    if( w->alloced < wsize )
52
0
  mpi_resize(w, wsize);
53
54
    /* These must be after realloc (U may be the same as W).  */
55
4.59k
    up = u->d;
56
4.59k
    wp = w->d;
57
58
4.59k
    if( !usize ) {  /* simple */
59
0
  wp[0] = v;
60
0
  wsize = v? 1:0;
61
0
    }
62
4.59k
    else if( !usign ) {  /* mpi is not negative */
63
4.59k
  mpi_limb_t cy;
64
4.59k
  cy = _gcry_mpih_add_1(wp, up, usize, v);
65
4.59k
  wp[usize] = cy;
66
4.59k
  wsize = usize + cy;
67
4.59k
    }
68
0
    else {  /* The signs are different.  Need exact comparison to determine
69
       * which operand to subtract from which.  */
70
0
  if( usize == 1 && up[0] < v ) {
71
0
      wp[0] = v - up[0];
72
0
      wsize = 1;
73
0
  }
74
0
  else {
75
0
      _gcry_mpih_sub_1(wp, up, usize, v);
76
      /* Size can decrease with at most one limb. */
77
0
      wsize = usize - (wp[usize-1]==0);
78
0
      wsign = 1;
79
0
  }
80
0
    }
81
82
4.59k
    w->nlimbs = wsize;
83
4.59k
    w->sign   = wsign;
84
4.59k
}
85
86
87
void
88
_gcry_mpi_add(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
89
10.2M
{
90
10.2M
    mpi_ptr_t wp, up, vp;
91
10.2M
    mpi_size_t usize, vsize, wsize;
92
10.2M
    int usign, vsign, wsign;
93
94
10.2M
    if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
95
7.24k
  usize = v->nlimbs;
96
7.24k
  usign = v->sign;
97
7.24k
  vsize = u->nlimbs;
98
7.24k
  vsign = u->sign;
99
7.24k
  wsize = usize + 1;
100
7.24k
  RESIZE_IF_NEEDED(w, wsize);
101
  /* These must be after realloc (u or v may be the same as w).  */
102
7.24k
  up    = v->d;
103
7.24k
  vp    = u->d;
104
7.24k
    }
105
10.2M
    else {
106
10.2M
  usize = u->nlimbs;
107
10.2M
  usign = u->sign;
108
10.2M
  vsize = v->nlimbs;
109
10.2M
  vsign = v->sign;
110
10.2M
  wsize = usize + 1;
111
10.2M
  RESIZE_IF_NEEDED(w, wsize);
112
  /* These must be after realloc (u or v may be the same as w).  */
113
10.2M
  up    = u->d;
114
10.2M
  vp    = v->d;
115
10.2M
    }
116
10.2M
    wp = w->d;
117
10.2M
    wsign = 0;
118
119
10.2M
    if( !vsize ) {  /* simple */
120
304k
  MPN_COPY(wp, up, usize );
121
304k
  wsize = usize;
122
304k
  wsign = usign;
123
304k
    }
124
9.92M
    else if( usign != vsign ) { /* different sign */
125
  /* This test is right since USIZE >= VSIZE */
126
8.47M
  if( usize != vsize ) {
127
10.3k
      _gcry_mpih_sub(wp, up, usize, vp, vsize);
128
10.3k
      wsize = usize;
129
10.3k
      MPN_NORMALIZE(wp, wsize);
130
10.3k
      wsign = usign;
131
10.3k
  }
132
8.46M
  else if( _gcry_mpih_cmp(up, vp, usize) < 0 ) {
133
5.63M
      _gcry_mpih_sub_n(wp, vp, up, usize);
134
5.63M
      wsize = usize;
135
5.63M
      MPN_NORMALIZE(wp, wsize);
136
5.63M
      if( !usign )
137
2.81M
    wsign = 1;
138
5.63M
  }
139
2.83M
  else {
140
2.83M
      _gcry_mpih_sub_n(wp, up, vp, usize);
141
2.83M
      wsize = usize;
142
2.83M
      MPN_NORMALIZE(wp, wsize);
143
2.83M
      if( usign )
144
0
    wsign = 1;
145
2.83M
  }
146
8.47M
    }
147
1.45M
    else { /* U and V have same sign. Add them. */
148
1.45M
  mpi_limb_t cy = _gcry_mpih_add(wp, up, usize, vp, vsize);
149
1.45M
  wp[usize] = cy;
150
1.45M
  wsize = usize + cy;
151
1.45M
  if( usign )
152
0
      wsign = 1;
153
1.45M
    }
154
155
10.2M
    w->nlimbs = wsize;
156
10.2M
    w->sign = wsign;
157
10.2M
}
158
159
160
/****************
161
 * Subtract the unsigned integer V from the mpi-integer U and store the
162
 * result in W.
163
 */
164
void
165
_gcry_mpi_sub_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
166
6.53k
{
167
6.53k
    mpi_ptr_t wp, up;
168
6.53k
    mpi_size_t usize, wsize;
169
6.53k
    int usign, wsign;
170
171
6.53k
    usize = u->nlimbs;
172
6.53k
    usign = u->sign;
173
6.53k
    wsign = 0;
174
175
    /* If not space for W (and possible carry), increase space.  */
176
6.53k
    wsize = usize + 1;
177
6.53k
    if( w->alloced < wsize )
178
1.94k
  mpi_resize(w, wsize);
179
180
    /* These must be after realloc (U may be the same as W).  */
181
6.53k
    up = u->d;
182
6.53k
    wp = w->d;
183
184
6.53k
    if( !usize ) {  /* simple */
185
0
  wp[0] = v;
186
0
  wsize = v? 1:0;
187
0
  wsign = 1;
188
0
    }
189
6.53k
    else if( usign ) { /* mpi and v are negative */
190
0
  mpi_limb_t cy;
191
0
  cy = _gcry_mpih_add_1(wp, up, usize, v);
192
0
  wp[usize] = cy;
193
0
  wsize = usize + cy;
194
0
  wsign = 1;
195
0
    }
196
6.53k
    else {  /* The signs are different.  Need exact comparison to determine
197
       * which operand to subtract from which.  */
198
6.53k
  if( usize == 1 && up[0] < v ) {
199
0
      wp[0] = v - up[0];
200
0
      wsize = 1;
201
0
      wsign = 1;
202
0
  }
203
6.53k
  else {
204
6.53k
      _gcry_mpih_sub_1(wp, up, usize, v);
205
      /* Size can decrease with at most one limb. */
206
6.53k
      wsize = usize - (wp[usize-1]==0);
207
6.53k
  }
208
6.53k
    }
209
210
6.53k
    w->nlimbs = wsize;
211
6.53k
    w->sign   = wsign;
212
6.53k
}
213
214
void
215
_gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
216
5.65M
{
217
5.65M
  gcry_mpi_t vv = mpi_copy (v);
218
5.65M
  vv->sign = ! vv->sign;
219
5.65M
  mpi_add (w, u, vv);
220
5.65M
  mpi_free (vv);
221
5.65M
}
222
223
224
void
225
_gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
226
0
{
227
0
  mpi_add (w, u, v);
228
0
  mpi_mod (w, w, m);
229
0
}
230
231
void
232
_gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
233
0
{
234
0
  mpi_sub (w, u, v);
235
0
  mpi_mod (w, w, m);
236
0
}