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
0
{
41
0
    mpi_ptr_t wp, up;
42
0
    mpi_size_t usize, wsize;
43
0
    int usign, wsign;
44
45
0
    usize = u->nlimbs;
46
0
    usign = u->sign;
47
0
    wsign = 0;
48
49
    /* If not space for W (and possible carry), increase space.  */
50
0
    wsize = usize + 1;
51
0
    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
0
    up = u->d;
56
0
    wp = w->d;
57
58
0
    if( !usize ) {  /* simple */
59
0
  wp[0] = v;
60
0
  wsize = v? 1:0;
61
0
    }
62
0
    else if( !usign ) {  /* mpi is not negative */
63
0
  mpi_limb_t cy;
64
0
  cy = _gcry_mpih_add_1(wp, up, usize, v);
65
0
  wp[usize] = cy;
66
0
  wsize = usize + cy;
67
0
    }
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
0
    w->nlimbs = wsize;
83
0
    w->sign   = wsign;
84
0
}
85
86
87
void
88
_gcry_mpi_add(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
89
84.7k
{
90
84.7k
    mpi_ptr_t wp, up, vp;
91
84.7k
    mpi_size_t usize, vsize, wsize;
92
84.7k
    int usign, vsign, wsign;
93
94
84.7k
    if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
95
0
  usize = v->nlimbs;
96
0
  usign = v->sign;
97
0
  vsize = u->nlimbs;
98
0
  vsign = u->sign;
99
0
  wsize = usize + 1;
100
0
  RESIZE_IF_NEEDED(w, wsize);
101
  /* These must be after realloc (u or v may be the same as w).  */
102
0
  up    = v->d;
103
0
  vp    = u->d;
104
0
    }
105
84.7k
    else {
106
84.7k
  usize = u->nlimbs;
107
84.7k
  usign = u->sign;
108
84.7k
  vsize = v->nlimbs;
109
84.7k
  vsign = v->sign;
110
84.7k
  wsize = usize + 1;
111
84.7k
  RESIZE_IF_NEEDED(w, wsize);
112
  /* These must be after realloc (u or v may be the same as w).  */
113
84.7k
  up    = u->d;
114
84.7k
  vp    = v->d;
115
84.7k
    }
116
84.7k
    wp = w->d;
117
84.7k
    wsign = 0;
118
119
84.7k
    if( !vsize ) {  /* simple */
120
0
  MPN_COPY(wp, up, usize );
121
0
  wsize = usize;
122
0
  wsign = usign;
123
0
    }
124
84.7k
    else if( usign != vsign ) { /* different sign */
125
  /* This test is right since USIZE >= VSIZE */
126
70.8k
  if( usize != vsize ) {
127
32
      _gcry_mpih_sub(wp, up, usize, vp, vsize);
128
32
      wsize = usize;
129
32
      MPN_NORMALIZE(wp, wsize);
130
32
      wsign = usign;
131
32
  }
132
70.8k
  else if( _gcry_mpih_cmp(up, vp, usize) < 0 ) {
133
48.1k
      _gcry_mpih_sub_n(wp, vp, up, usize);
134
48.1k
      wsize = usize;
135
48.1k
      MPN_NORMALIZE(wp, wsize);
136
48.1k
      if( !usign )
137
24.0k
    wsign = 1;
138
48.1k
  }
139
22.6k
  else {
140
22.6k
      _gcry_mpih_sub_n(wp, up, vp, usize);
141
22.6k
      wsize = usize;
142
22.6k
      MPN_NORMALIZE(wp, wsize);
143
22.6k
      if( usign )
144
0
    wsign = 1;
145
22.6k
  }
146
70.8k
    }
147
13.8k
    else { /* U and V have same sign. Add them. */
148
13.8k
  mpi_limb_t cy = _gcry_mpih_add(wp, up, usize, vp, vsize);
149
13.8k
  wp[usize] = cy;
150
13.8k
  wsize = usize + cy;
151
13.8k
  if( usign )
152
0
      wsign = 1;
153
13.8k
    }
154
155
84.7k
    w->nlimbs = wsize;
156
84.7k
    w->sign = wsign;
157
84.7k
}
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
16
{
167
16
    mpi_ptr_t wp, up;
168
16
    mpi_size_t usize, wsize;
169
16
    int usign, wsign;
170
171
16
    usize = u->nlimbs;
172
16
    usign = u->sign;
173
16
    wsign = 0;
174
175
    /* If not space for W (and possible carry), increase space.  */
176
16
    wsize = usize + 1;
177
16
    if( w->alloced < wsize )
178
16
  mpi_resize(w, wsize);
179
180
    /* These must be after realloc (U may be the same as W).  */
181
16
    up = u->d;
182
16
    wp = w->d;
183
184
16
    if( !usize ) {  /* simple */
185
0
  wp[0] = v;
186
0
  wsize = v? 1:0;
187
0
  wsign = 1;
188
0
    }
189
16
    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
16
    else {  /* The signs are different.  Need exact comparison to determine
197
       * which operand to subtract from which.  */
198
16
  if( usize == 1 && up[0] < v ) {
199
0
      wp[0] = v - up[0];
200
0
      wsize = 1;
201
0
      wsign = 1;
202
0
  }
203
16
  else {
204
16
      _gcry_mpih_sub_1(wp, up, usize, v);
205
      /* Size can decrease with at most one limb. */
206
16
      wsize = usize - (wp[usize-1]==0);
207
16
  }
208
16
    }
209
210
16
    w->nlimbs = wsize;
211
16
    w->sign   = wsign;
212
16
}
213
214
void
215
_gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
216
46.7k
{
217
46.7k
  gcry_mpi_t vv = mpi_copy (v);
218
46.7k
  vv->sign = ! vv->sign;
219
46.7k
  mpi_add (w, u, vv);
220
46.7k
  mpi_free (vv);
221
46.7k
}
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
}