GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/bn/bn_word.c Lines: 68 96 70.8 %
Date: 2016-12-06 Branches: 41 68 60.3 %

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
783637
{
66
#ifndef BN_LLONG
67
783637
	BN_ULONG ret = 0;
68
#else
69
	BN_ULLONG ret = 0;
70
#endif
71
	int i;
72
73
783637
	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
783637
	if (w > ((BN_ULONG)1 << BN_BITS4)) {
80
98
		BIGNUM *tmp = BN_dup(a);
81
98
		if (tmp == NULL) {
82
			return (BN_ULONG)-1;
83
		}
84
98
		ret = BN_div_word(tmp, w);
85
98
		BN_free(tmp);
86
98
		return ret;
87
	}
88
#endif
89
90
	bn_check_top(a);
91
783539
	w &= BN_MASK2;
92
3643595
	for (i = a->top - 1; i >= 0; i--) {
93
#ifndef BN_LLONG
94
2860056
		ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) &
95
		    BN_MASK2l)) % w;
96
2860056
		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
783539
	return ((BN_ULONG)ret);
103
}
104
105
BN_ULONG
106
BN_div_word(BIGNUM *a, BN_ULONG w)
107
198
{
108
198
	BN_ULONG ret = 0;
109
	int i, j;
110
111
	bn_check_top(a);
112
198
	w &= BN_MASK2;
113
114
198
	if (!w)
115
		/* actually this an error (division by zero) */
116
		return (BN_ULONG) - 1;
117
198
	if (a->top == 0)
118
		return 0;
119
120
	/* normalize input (so bn_div_words doesn't complain) */
121
198
	j = BN_BITS2 - BN_num_bits_word(w);
122
198
	w <<= j;
123
198
	if (!BN_lshift(a, a, j))
124
		return (BN_ULONG) - 1;
125
126
1850
	for (i = a->top - 1; i >= 0; i--) {
127
		BN_ULONG l, d;
128
129
1652
		l = a->d[i];
130
1652
		d = bn_div_words(ret, l, w);
131
1652
		ret = (l - ((d*w)&BN_MASK2))&BN_MASK2;
132
1652
		a->d[i] = d;
133
	}
134

198
	if ((a->top > 0) && (a->d[a->top - 1] == 0))
135
158
		a->top--;
136
198
	ret >>= j;
137
	bn_check_top(a);
138
198
	return (ret);
139
}
140
141
int
142
BN_add_word(BIGNUM *a, BN_ULONG w)
143
110826
{
144
	BN_ULONG l;
145
	int i;
146
147
	bn_check_top(a);
148
110826
	w &= BN_MASK2;
149
150
	/* degenerate case: w is zero */
151
110826
	if (!w)
152
3
		return 1;
153
	/* degenerate case: a is zero */
154
110823
	if (BN_is_zero(a))
155
20
		return BN_set_word(a, w);
156
	/* handle 'a' when negative */
157
110803
	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

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

110803
	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
110803
	return (1);
176
}
177
178
int
179
BN_sub_word(BIGNUM *a, BN_ULONG w)
180
3336
{
181
	int i;
182
183
	bn_check_top(a);
184
3336
	w &= BN_MASK2;
185
186
	/* degenerate case: w is zero */
187
3336
	if (!w)
188
		return 1;
189
	/* degenerate case: a is zero */
190
3336
	if (BN_is_zero(a)) {
191
		i = BN_set_word(a, w);
192
		if (i != 0)
193
			BN_set_negative(a, 1);
194
		return i;
195
	}
196
	/* handle 'a' when negative */
197
3336
	if (a->neg) {
198
		a->neg = 0;
199
		i = BN_add_word(a, w);
200
		a->neg = 1;
201
		return (i);
202
	}
203
204

3336
	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
3336
	i = 0;
210
	for (;;) {
211
5341
		if (a->d[i] >= w) {
212
3336
			a->d[i] -= w;
213
			break;
214
		} else {
215
2005
			a->d[i] = (a->d[i] - w) & BN_MASK2;
216
2005
			i++;
217
2005
			w = 1;
218
		}
219
2005
	}
220

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

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