Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/bn/bn_add.c
Line
Count
Source (jump to first uncovered line)
1
/* crypto/bn/bn_add.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3
 * All rights reserved.
4
 *
5
 * This package is an SSL implementation written
6
 * by Eric Young (eay@cryptsoft.com).
7
 * The implementation was written so as to conform with Netscapes SSL.
8
 *
9
 * This library is free for commercial and non-commercial use as long as
10
 * the following conditions are aheared to.  The following conditions
11
 * apply to all code found in this distribution, be it the RC4, RSA,
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13
 * included with this distribution is covered by the same copyright terms
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15
 *
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
17
 * the code are not to be removed.
18
 * If this package is used in a product, Eric Young should be given attribution
19
 * as the author of the parts of the library used.
20
 * This can be in the form of a textual message at program startup or
21
 * in documentation (online or textual) provided with the package.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 * 1. Redistributions of source code must retain the copyright
27
 *    notice, this list of conditions and the following disclaimer.
28
 * 2. Redistributions in binary form must reproduce the above copyright
29
 *    notice, this list of conditions and the following disclaimer in the
30
 *    documentation and/or other materials provided with the distribution.
31
 * 3. All advertising materials mentioning features or use of this software
32
 *    must display the following acknowledgement:
33
 *    "This product includes cryptographic software written by
34
 *     Eric Young (eay@cryptsoft.com)"
35
 *    The word 'cryptographic' can be left out if the rouines from the library
36
 *    being used are not cryptographic related :-).
37
 * 4. If you include any Windows specific code (or a derivative thereof) from
38
 *    the apps directory (application code) you must include an acknowledgement:
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 *
53
 * The licence and distribution terms for any publically available version or
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55
 * copied and put under another distribution licence
56
 * [including the GNU Public Licence.]
57
 */
58
59
#include <stdio.h>
60
#include "cryptlib.h"
61
#include "bn_lcl.h"
62
63
/* r can == a or b */
64
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
65
0
{
66
0
    const BIGNUM *tmp;
67
0
    int a_neg = a->neg, ret;
68
69
0
    bn_check_top(a);
70
0
    bn_check_top(b);
71
72
    /*-
73
     *  a +  b      a+b
74
     *  a + -b      a-b
75
     * -a +  b      b-a
76
     * -a + -b      -(a+b)
77
     */
78
0
    if (a_neg ^ b->neg) {
79
        /* only one is negative */
80
0
        if (a_neg) {
81
0
            tmp = a;
82
0
            a = b;
83
0
            b = tmp;
84
0
        }
85
86
        /* we are now a - b */
87
88
0
        if (BN_ucmp(a, b) < 0) {
89
0
            if (!BN_usub(r, b, a))
90
0
                return (0);
91
0
            r->neg = 1;
92
0
        } else {
93
0
            if (!BN_usub(r, a, b))
94
0
                return (0);
95
0
            r->neg = 0;
96
0
        }
97
0
        return (1);
98
0
    }
99
100
0
    ret = BN_uadd(r, a, b);
101
0
    r->neg = a_neg;
102
0
    bn_check_top(r);
103
0
    return ret;
104
0
}
105
106
/* unsigned add of b to a */
107
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
108
0
{
109
0
    int max, min, dif;
110
0
    BN_ULONG *ap, *bp, *rp, carry, t1, t2;
111
0
    const BIGNUM *tmp;
112
113
0
    bn_check_top(a);
114
0
    bn_check_top(b);
115
116
0
    if (a->top < b->top) {
117
0
        tmp = a;
118
0
        a = b;
119
0
        b = tmp;
120
0
    }
121
0
    max = a->top;
122
0
    min = b->top;
123
0
    dif = max - min;
124
125
0
    if (bn_wexpand(r, max + 1) == NULL)
126
0
        return 0;
127
128
0
    r->top = max;
129
130
0
    ap = a->d;
131
0
    bp = b->d;
132
0
    rp = r->d;
133
134
0
    carry = bn_add_words(rp, ap, bp, min);
135
0
    rp += min;
136
0
    ap += min;
137
0
    bp += min;
138
139
0
    if (carry) {
140
0
        while (dif) {
141
0
            dif--;
142
0
            t1 = *(ap++);
143
0
            t2 = (t1 + 1) & BN_MASK2;
144
0
            *(rp++) = t2;
145
0
            if (t2) {
146
0
                carry = 0;
147
0
                break;
148
0
            }
149
0
        }
150
0
        if (carry) {
151
            /* carry != 0 => dif == 0 */
152
0
            *rp = 1;
153
0
            r->top++;
154
0
        }
155
0
    }
156
0
    if (dif && rp != ap)
157
0
        while (dif--)
158
            /* copy remaining words if ap != rp */
159
0
            *(rp++) = *(ap++);
160
0
    r->neg = 0;
161
0
    bn_check_top(r);
162
0
    return 1;
163
0
}
164
165
/* unsigned subtraction of b from a, a must be larger than b. */
166
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
167
0
{
168
0
    int max, min, dif;
169
0
    register BN_ULONG t1, t2, *ap, *bp, *rp;
170
0
    int i, carry;
171
#if defined(IRIX_CC_BUG) && !defined(LINT)
172
    int dummy;
173
#endif
174
175
0
    bn_check_top(a);
176
0
    bn_check_top(b);
177
178
0
    max = a->top;
179
0
    min = b->top;
180
0
    dif = max - min;
181
182
0
    if (dif < 0) {              /* hmm... should not be happening */
183
0
        BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3);
184
0
        return (0);
185
0
    }
186
187
0
    if (bn_wexpand(r, max) == NULL)
188
0
        return (0);
189
190
0
    ap = a->d;
191
0
    bp = b->d;
192
0
    rp = r->d;
193
194
0
#if 1
195
0
    carry = 0;
196
0
    for (i = min; i != 0; i--) {
197
0
        t1 = *(ap++);
198
0
        t2 = *(bp++);
199
0
        if (carry) {
200
0
            carry = (t1 <= t2);
201
0
            t1 = (t1 - t2 - 1) & BN_MASK2;
202
0
        } else {
203
0
            carry = (t1 < t2);
204
0
            t1 = (t1 - t2) & BN_MASK2;
205
0
        }
206
# if defined(IRIX_CC_BUG) && !defined(LINT)
207
        dummy = t1;
208
# endif
209
0
        *(rp++) = t1 & BN_MASK2;
210
0
    }
211
#else
212
    carry = bn_sub_words(rp, ap, bp, min);
213
    ap += min;
214
    bp += min;
215
    rp += min;
216
#endif
217
0
    if (carry) {                /* subtracted */
218
0
        if (!dif)
219
            /* error: a < b */
220
0
            return 0;
221
0
        while (dif) {
222
0
            dif--;
223
0
            t1 = *(ap++);
224
0
            t2 = (t1 - 1) & BN_MASK2;
225
0
            *(rp++) = t2;
226
0
            if (t1)
227
0
                break;
228
0
        }
229
0
    }
230
#if 0
231
    memcpy(rp, ap, sizeof(*rp) * (max - i));
232
#else
233
0
    if (rp != ap) {
234
0
        for (;;) {
235
0
            if (!dif--)
236
0
                break;
237
0
            rp[0] = ap[0];
238
0
            if (!dif--)
239
0
                break;
240
0
            rp[1] = ap[1];
241
0
            if (!dif--)
242
0
                break;
243
0
            rp[2] = ap[2];
244
0
            if (!dif--)
245
0
                break;
246
0
            rp[3] = ap[3];
247
0
            rp += 4;
248
0
            ap += 4;
249
0
        }
250
0
    }
251
0
#endif
252
253
0
    r->top = max;
254
0
    r->neg = 0;
255
0
    bn_correct_top(r);
256
0
    return (1);
257
0
}
258
259
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
260
0
{
261
0
    int max;
262
0
    int add = 0, neg = 0;
263
0
    const BIGNUM *tmp;
264
265
0
    bn_check_top(a);
266
0
    bn_check_top(b);
267
268
    /*-
269
     *  a -  b      a-b
270
     *  a - -b      a+b
271
     * -a -  b      -(a+b)
272
     * -a - -b      b-a
273
     */
274
0
    if (a->neg) {
275
0
        if (b->neg) {
276
0
            tmp = a;
277
0
            a = b;
278
0
            b = tmp;
279
0
        } else {
280
0
            add = 1;
281
0
            neg = 1;
282
0
        }
283
0
    } else {
284
0
        if (b->neg) {
285
0
            add = 1;
286
0
            neg = 0;
287
0
        }
288
0
    }
289
290
0
    if (add) {
291
0
        if (!BN_uadd(r, a, b))
292
0
            return (0);
293
0
        r->neg = neg;
294
0
        return (1);
295
0
    }
296
297
    /* We are actually doing a - b :-) */
298
299
0
    max = (a->top > b->top) ? a->top : b->top;
300
0
    if (bn_wexpand(r, max) == NULL)
301
0
        return (0);
302
0
    if (BN_ucmp(a, b) < 0) {
303
0
        if (!BN_usub(r, b, a))
304
0
            return (0);
305
0
        r->neg = 1;
306
0
    } else {
307
0
        if (!BN_usub(r, a, b))
308
0
            return (0);
309
0
        r->neg = 0;
310
0
    }
311
0
    bn_check_top(r);
312
0
    return (1);
313
0
}