GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/bn/bn_word.c Lines: 66 89 74.2 %
Date: 2017-11-07 Branches: 46 68 67.6 %

Line Branch Exec Source
1
/* $OpenBSD: bn_word.c,v 1.13 2016/07/05 02:54:35 bcook Exp $ */
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
61
#include "bn_lcl.h"
62
63
BN_ULONG
64
BN_mod_word(const BIGNUM *a, BN_ULONG w)
65
{
66
#ifndef BN_LLONG
67
	BN_ULONG ret = 0;
68
#else
69
	BN_ULLONG ret = 0;
70
#endif
71
	int i;
72
73
226973364
	if (w == 0)
74
		return (BN_ULONG) - 1;
75
76
#ifndef BN_ULLONG
77
	/* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
78
	* to using |BN_div_word|. */
79
113486682
	if (w > ((BN_ULONG)1 << BN_BITS4)) {
80
578
		BIGNUM *tmp = BN_dup(a);
81
578
		if (tmp == NULL) {
82
			return (BN_ULONG)-1;
83
		}
84
578
		ret = BN_div_word(tmp, w);
85
578
		BN_free(tmp);
86
578
		return ret;
87
	}
88
#endif
89
90
	bn_check_top(a);
91
	w &= BN_MASK2;
92
4991673082
	for (i = a->top - 1; i >= 0; i--) {
93
#ifndef BN_LLONG
94
2382350437
		ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) &
95
2382350437
		    BN_MASK2l)) % w;
96
2382350437
		ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
97
#else
98
		ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) |
99
		    a->d[i]) % (BN_ULLONG)w);
100
#endif
101
	}
102
113486104
	return ((BN_ULONG)ret);
103
113486682
}
104
105
BN_ULONG
106
BN_div_word(BIGNUM *a, BN_ULONG w)
107
{
108
	BN_ULONG ret = 0;
109
	int i, j;
110
111
	bn_check_top(a);
112
	w &= BN_MASK2;
113
114
127656
	if (!w)
115
		/* actually this an error (division by zero) */
116
		return (BN_ULONG) - 1;
117
63828
	if (a->top == 0)
118
634
		return 0;
119
120
	/* normalize input (so bn_div_words doesn't complain) */
121
63194
	j = BN_BITS2 - BN_num_bits_word(w);
122
63194
	w <<= j;
123
63194
	if (!BN_lshift(a, a, j))
124
		return (BN_ULONG) - 1;
125
126
5794258
	for (i = a->top - 1; i >= 0; i--) {
127
		BN_ULONG l, d;
128
129
2833935
		l = a->d[i];
130
2833935
		d = bn_div_words(ret, l, w);
131
2833935
		ret = (l - ((d*w)&BN_MASK2))&BN_MASK2;
132
2833935
		a->d[i] = d;
133
	}
134

126388
	if ((a->top > 0) && (a->d[a->top - 1] == 0))
135
60899
		a->top--;
136
63194
	ret >>= j;
137
	bn_check_top(a);
138
63194
	return (ret);
139
63828
}
140
141
int
142
BN_add_word(BIGNUM *a, BN_ULONG w)
143
{
144
	BN_ULONG l;
145
	int i;
146
147
	bn_check_top(a);
148
	w &= BN_MASK2;
149
150
	/* degenerate case: w is zero */
151
1552278
	if (!w)
152
22039
		return 1;
153
	/* degenerate case: a is zero */
154
754100
	if (BN_is_zero(a))
155
33246
		return BN_set_word(a, w);
156
	/* handle 'a' when negative */
157
720854
	if (a->neg) {
158
		a->neg = 0;
159
		i = BN_sub_word(a, w);
160
		if (!BN_is_zero(a))
161
			a->neg=!(a->neg);
162
		return (i);
163
	}
164

3605494
	for (i = 0; w != 0 && i < a->top; i++) {
165
721262
		a->d[i] = l = (a->d[i] + w) & BN_MASK2;
166
721262
		w = (w > l) ? 1 : 0;
167
	}
168

720854
	if (w && i == a->top) {
169
		if (bn_wexpand(a, a->top + 1) == NULL)
170
			return 0;
171
		a->top++;
172
		a->d[i] = w;
173
	}
174
	bn_check_top(a);
175
720854
	return (1);
176
776139
}
177
178
int
179
BN_sub_word(BIGNUM *a, BN_ULONG w)
180
{
181
	int i;
182
183
	bn_check_top(a);
184
	w &= BN_MASK2;
185
186
	/* degenerate case: w is zero */
187
140632
	if (!w)
188
		return 1;
189
	/* degenerate case: a is zero */
190
70316
	if (BN_is_zero(a)) {
191
5
		i = BN_set_word(a, w);
192
5
		if (i != 0)
193
5
			BN_set_negative(a, 1);
194
5
		return i;
195
	}
196
	/* handle 'a' when negative */
197
70311
	if (a->neg) {
198
		a->neg = 0;
199
		i = BN_add_word(a, w);
200
		a->neg = 1;
201
		return (i);
202
	}
203
204

76546
	if ((a->top == 1) && (a->d[0] < w)) {
205
		a->d[0] = w - a->d[0];
206
		a->neg = 1;
207
		return (1);
208
	}
209
	i = 0;
210
111344
	for (;;) {
211
111344
		if (a->d[i] >= w) {
212
70311
			a->d[i] -= w;
213
			break;
214
		} else {
215
41033
			a->d[i] = (a->d[i] - w) & BN_MASK2;
216
41033
			i++;
217
			w = 1;
218
		}
219
	}
220

72171
	if ((a->d[i] == 0) && (i == (a->top - 1)))
221
1854
		a->top--;
222
	bn_check_top(a);
223
70311
	return (1);
224
70316
}
225
226
int
227
BN_mul_word(BIGNUM *a, BN_ULONG w)
228
{
229
	BN_ULONG ll;
230
231
	bn_check_top(a);
232
	w &= BN_MASK2;
233
233266
	if (a->top) {
234
76657
		if (w == 0)
235
			BN_zero(a);
236
		else {
237
76657
			ll = bn_mul_words(a->d, a->d, a->top, w);
238
76657
			if (ll) {
239

3416
				if (bn_wexpand(a, a->top + 1) == NULL)
240
					return (0);
241
1535
				a->d[a->top++] = ll;
242
1535
			}
243
		}
244
	}
245
	bn_check_top(a);
246
116633
	return (1);
247
116633
}