]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bn/bn_add.c
Update copyright year
[thirdparty/openssl.git] / crypto / bn / bn_add.c
CommitLineData
4f22f405 1/*
605856d7 2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
d02b48c6 3 *
367ace68 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
4f22f405
RS
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
d02b48c6
RE
8 */
9
b39fc560 10#include "internal/cryptlib.h"
706457b7 11#include "bn_local.h"
d02b48c6 12
55442b8a 13/* signed add of b to a. */
dd8dec69 14int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
0f113f3e 15{
55442b8a 16 int ret, r_neg, cmp_res;
0f113f3e
MC
17
18 bn_check_top(a);
19 bn_check_top(b);
20
55442b8a
DG
21 if (a->neg == b->neg) {
22 r_neg = a->neg;
23 ret = BN_uadd(r, a, b);
24 } else {
25 cmp_res = BN_ucmp(a, b);
26 if (cmp_res > 0) {
27 r_neg = a->neg;
28 ret = BN_usub(r, a, b);
29 } else if (cmp_res < 0) {
30 r_neg = b->neg;
31 ret = BN_usub(r, b, a);
32 } else {
33 r_neg = 0;
34 BN_zero(r);
35 ret = 1;
0f113f3e 36 }
55442b8a
DG
37 }
38
39 r->neg = r_neg;
40 bn_check_top(r);
41 return ret;
42}
43
44/* signed sub of b from a. */
45int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
46{
47 int ret, r_neg, cmp_res;
0f113f3e 48
55442b8a
DG
49 bn_check_top(a);
50 bn_check_top(b);
0f113f3e 51
55442b8a
DG
52 if (a->neg != b->neg) {
53 r_neg = a->neg;
54 ret = BN_uadd(r, a, b);
55 } else {
56 cmp_res = BN_ucmp(a, b);
57 if (cmp_res > 0) {
58 r_neg = a->neg;
59 ret = BN_usub(r, a, b);
60 } else if (cmp_res < 0) {
61 r_neg = !b->neg;
62 ret = BN_usub(r, b, a);
0f113f3e 63 } else {
55442b8a
DG
64 r_neg = 0;
65 BN_zero(r);
66 ret = 1;
0f113f3e 67 }
0f113f3e
MC
68 }
69
55442b8a 70 r->neg = r_neg;
0f113f3e
MC
71 bn_check_top(r);
72 return ret;
73}
d02b48c6 74
55442b8a 75/* unsigned add of b to a, r can be equal to a or b. */
84c15db5 76int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
0f113f3e
MC
77{
78 int max, min, dif;
79 const BN_ULONG *ap, *bp;
80 BN_ULONG *rp, carry, t1, t2;
0f113f3e
MC
81
82 bn_check_top(a);
83 bn_check_top(b);
84
85 if (a->top < b->top) {
7d628405
AP
86 const BIGNUM *tmp;
87
0f113f3e
MC
88 tmp = a;
89 a = b;
90 b = tmp;
91 }
92 max = a->top;
93 min = b->top;
94 dif = max - min;
95
96 if (bn_wexpand(r, max + 1) == NULL)
97 return 0;
98
99 r->top = max;
100
101 ap = a->d;
102 bp = b->d;
103 rp = r->d;
104
105 carry = bn_add_words(rp, ap, bp, min);
106 rp += min;
107 ap += min;
7d628405
AP
108
109 while (dif) {
110 dif--;
111 t1 = *(ap++);
112 t2 = (t1 + carry) & BN_MASK2;
113 *(rp++) = t2;
114 carry &= (t2 == 0);
0f113f3e 115 }
7d628405
AP
116 *rp = carry;
117 r->top += carry;
118
0f113f3e
MC
119 r->neg = 0;
120 bn_check_top(r);
121 return 1;
122}
dfeab068
RE
123
124/* unsigned subtraction of b from a, a must be larger than b. */
84c15db5 125int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
0f113f3e
MC
126{
127 int max, min, dif;
7d628405
AP
128 BN_ULONG t1, t2, borrow, *rp;
129 const BN_ULONG *ap, *bp;
dfeab068 130
0f113f3e
MC
131 bn_check_top(a);
132 bn_check_top(b);
dfeab068 133
0f113f3e
MC
134 max = a->top;
135 min = b->top;
136 dif = max - min;
380e145d 137
0f113f3e 138 if (dif < 0) { /* hmm... should not be happening */
9311d0c4 139 ERR_raise(ERR_LIB_BN, BN_R_ARG2_LT_ARG3);
7d628405 140 return 0;
0f113f3e 141 }
dfeab068 142
0f113f3e 143 if (bn_wexpand(r, max) == NULL)
7d628405 144 return 0;
dfeab068 145
0f113f3e
MC
146 ap = a->d;
147 bp = b->d;
148 rp = r->d;
dfeab068 149
7d628405 150 borrow = bn_sub_words(rp, ap, bp, min);
0f113f3e 151 ap += min;
0f113f3e 152 rp += min;
7d628405
AP
153
154 while (dif) {
155 dif--;
156 t1 = *(ap++);
157 t2 = (t1 - borrow) & BN_MASK2;
158 *(rp++) = t2;
159 borrow &= (t1 == 0);
0f113f3e 160 }
dfeab068 161
a78324d9
AP
162 while (max && *--rp == 0)
163 max--;
164
0f113f3e
MC
165 r->top = max;
166 r->neg = 0;
a78324d9
AP
167 bn_pollute(r);
168
7d628405 169 return 1;
0f113f3e 170}
dfeab068 171