]>
Commit | Line | Data |
---|---|---|
d02b48c6 | 1 | /* crypto/bn/exptest.c */ |
58964a49 | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
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. | |
0f113f3e | 8 | * |
d02b48c6 RE |
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). | |
0f113f3e | 15 | * |
d02b48c6 RE |
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. | |
0f113f3e | 22 | * |
d02b48c6 RE |
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 :-). | |
0f113f3e | 37 | * 4. If you include any Windows specific code (or a derivative thereof) from |
d02b48c6 RE |
38 | * the apps directory (application code) you must include an acknowledgement: |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
0f113f3e | 40 | * |
d02b48c6 RE |
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. | |
0f113f3e | 52 | * |
d02b48c6 RE |
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 <stdlib.h> | |
61 | #include <string.h> | |
55f78baf RL |
62 | |
63 | #include "../e_os.h" | |
64 | ||
ec577822 BM |
65 | #include <openssl/bio.h> |
66 | #include <openssl/bn.h> | |
67 | #include <openssl/rand.h> | |
68 | #include <openssl/err.h> | |
d02b48c6 | 69 | |
0f113f3e MC |
70 | #define NUM_BITS (BN_BITS*2) |
71 | ||
72 | static const char rnd_seed[] = | |
73 | "string to make the random number generator think it has entropy"; | |
74 | ||
d911097d EK |
75 | /* |
76 | * Test that r == 0 in test_exp_mod_zero(). Returns one on success, | |
77 | * returns zero and prints debug output otherwise. | |
78 | */ | |
79 | static int a_is_zero_mod_one(const char *method, const BIGNUM *r, | |
80 | const BIGNUM *a) { | |
81 | if (!BN_is_zero(r)) { | |
82 | fprintf(stderr, "%s failed:\n", method); | |
83 | fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n"); | |
84 | fprintf(stderr, "a = "); | |
85 | BN_print_fp(stderr, a); | |
86 | fprintf(stderr, "\nr = "); | |
87 | BN_print_fp(stderr, r); | |
88 | fprintf(stderr, "\n"); | |
89 | return 0; | |
90 | } | |
91 | return 1; | |
92 | } | |
93 | ||
0f113f3e MC |
94 | /* |
95 | * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. | |
96 | */ | |
97 | static int test_exp_mod_zero() | |
98 | { | |
99 | BIGNUM *a = NULL, *p = NULL, *m = NULL; | |
100 | BIGNUM *r = NULL; | |
d911097d | 101 | BN_ULONG one_word = 1; |
0f113f3e | 102 | BN_CTX *ctx = BN_CTX_new(); |
d911097d | 103 | int ret = 1, failed = 0; |
0f113f3e MC |
104 | |
105 | m = BN_new(); | |
106 | if (!m) | |
107 | goto err; | |
108 | BN_one(m); | |
109 | ||
110 | a = BN_new(); | |
111 | if (!a) | |
112 | goto err; | |
113 | BN_one(a); | |
114 | ||
115 | p = BN_new(); | |
116 | if (!p) | |
117 | goto err; | |
118 | BN_zero(p); | |
119 | ||
120 | r = BN_new(); | |
121 | if (!r) | |
122 | goto err; | |
0f113f3e | 123 | |
d911097d EK |
124 | if (!BN_rand(a, 1024, 0, 0)) |
125 | goto err; | |
126 | ||
127 | if (!BN_mod_exp(r, a, p, m, ctx)) | |
128 | goto err; | |
129 | ||
130 | if (!a_is_zero_mod_one("BN_mod_exp", r, a)) | |
131 | failed = 1; | |
132 | ||
133 | if (!BN_mod_exp_recp(r, a, p, m, ctx)) | |
134 | goto err; | |
135 | ||
136 | if (!a_is_zero_mod_one("BN_mod_exp_recp", r, a)) | |
137 | failed = 1; | |
138 | ||
139 | if (!BN_mod_exp_simple(r, a, p, m, ctx)) | |
140 | goto err; | |
141 | ||
142 | if (!a_is_zero_mod_one("BN_mod_exp_simple", r, a)) | |
143 | failed = 1; | |
144 | ||
145 | if (!BN_mod_exp_mont(r, a, p, m, ctx, NULL)) | |
146 | goto err; | |
147 | ||
148 | if (!a_is_zero_mod_one("BN_mod_exp_mont", r, a)) | |
149 | failed = 1; | |
150 | ||
151 | if (!BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL)) { | |
152 | goto err; | |
0f113f3e MC |
153 | } |
154 | ||
d911097d EK |
155 | if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a)) |
156 | failed = 1; | |
157 | ||
158 | /* | |
159 | * A different codepath exists for single word multiplication | |
160 | * in non-constant-time only. | |
161 | */ | |
162 | if (!BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL)) | |
163 | goto err; | |
164 | ||
165 | if (!BN_is_zero(r)) { | |
166 | fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); | |
167 | fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); | |
168 | fprintf(stderr, "r = "); | |
169 | BN_print_fp(stderr, r); | |
170 | fprintf(stderr, "\n"); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | ret = failed; | |
175 | ||
0f113f3e MC |
176 | err: |
177 | BN_free(r); | |
178 | BN_free(a); | |
179 | BN_free(p); | |
180 | BN_free(m); | |
d911097d | 181 | BN_CTX_free(ctx); |
0f113f3e MC |
182 | |
183 | return ret; | |
2b0180c3 AL |
184 | } |
185 | ||
6b691a5c | 186 | int main(int argc, char *argv[]) |
0f113f3e MC |
187 | { |
188 | BN_CTX *ctx; | |
189 | BIO *out = NULL; | |
190 | int i, ret; | |
191 | unsigned char c; | |
192 | BIGNUM *r_mont, *r_mont_const, *r_recp, *r_simple, *a, *b, *m; | |
193 | ||
194 | RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we | |
195 | * don't even check its return | |
196 | * value (which we should) */ | |
197 | ||
198 | ERR_load_BN_strings(); | |
199 | ||
200 | ctx = BN_CTX_new(); | |
201 | if (ctx == NULL) | |
202 | EXIT(1); | |
203 | r_mont = BN_new(); | |
204 | r_mont_const = BN_new(); | |
205 | r_recp = BN_new(); | |
206 | r_simple = BN_new(); | |
207 | a = BN_new(); | |
208 | b = BN_new(); | |
209 | m = BN_new(); | |
210 | if ((r_mont == NULL) || (r_recp == NULL) || (a == NULL) || (b == NULL)) | |
211 | goto err; | |
212 | ||
213 | out = BIO_new(BIO_s_file()); | |
214 | ||
215 | if (out == NULL) | |
216 | EXIT(1); | |
0f81f5f7 | 217 | BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); |
0f113f3e MC |
218 | |
219 | for (i = 0; i < 200; i++) { | |
220 | RAND_bytes(&c, 1); | |
221 | c = (c % BN_BITS) - BN_BITS2; | |
222 | BN_rand(a, NUM_BITS + c, 0, 0); | |
223 | ||
224 | RAND_bytes(&c, 1); | |
225 | c = (c % BN_BITS) - BN_BITS2; | |
226 | BN_rand(b, NUM_BITS + c, 0, 0); | |
227 | ||
228 | RAND_bytes(&c, 1); | |
229 | c = (c % BN_BITS) - BN_BITS2; | |
230 | BN_rand(m, NUM_BITS + c, 0, 1); | |
231 | ||
232 | BN_mod(a, a, m, ctx); | |
233 | BN_mod(b, b, m, ctx); | |
234 | ||
235 | ret = BN_mod_exp_mont(r_mont, a, b, m, ctx, NULL); | |
236 | if (ret <= 0) { | |
237 | printf("BN_mod_exp_mont() problems\n"); | |
238 | ERR_print_errors(out); | |
239 | EXIT(1); | |
240 | } | |
241 | ||
242 | ret = BN_mod_exp_recp(r_recp, a, b, m, ctx); | |
243 | if (ret <= 0) { | |
244 | printf("BN_mod_exp_recp() problems\n"); | |
245 | ERR_print_errors(out); | |
246 | EXIT(1); | |
247 | } | |
248 | ||
249 | ret = BN_mod_exp_simple(r_simple, a, b, m, ctx); | |
250 | if (ret <= 0) { | |
251 | printf("BN_mod_exp_simple() problems\n"); | |
252 | ERR_print_errors(out); | |
253 | EXIT(1); | |
254 | } | |
255 | ||
256 | ret = BN_mod_exp_mont_consttime(r_mont_const, a, b, m, ctx, NULL); | |
257 | if (ret <= 0) { | |
258 | printf("BN_mod_exp_mont_consttime() problems\n"); | |
259 | ERR_print_errors(out); | |
260 | EXIT(1); | |
261 | } | |
262 | ||
263 | if (BN_cmp(r_simple, r_mont) == 0 | |
264 | && BN_cmp(r_simple, r_recp) == 0 | |
265 | && BN_cmp(r_simple, r_mont_const) == 0) { | |
266 | printf("."); | |
267 | fflush(stdout); | |
268 | } else { | |
269 | if (BN_cmp(r_simple, r_mont) != 0) | |
270 | printf("\nsimple and mont results differ\n"); | |
271 | if (BN_cmp(r_simple, r_mont_const) != 0) | |
272 | printf("\nsimple and mont const time results differ\n"); | |
273 | if (BN_cmp(r_simple, r_recp) != 0) | |
274 | printf("\nsimple and recp results differ\n"); | |
275 | ||
276 | printf("a (%3d) = ", BN_num_bits(a)); | |
277 | BN_print(out, a); | |
278 | printf("\nb (%3d) = ", BN_num_bits(b)); | |
279 | BN_print(out, b); | |
280 | printf("\nm (%3d) = ", BN_num_bits(m)); | |
281 | BN_print(out, m); | |
282 | printf("\nsimple ="); | |
283 | BN_print(out, r_simple); | |
284 | printf("\nrecp ="); | |
285 | BN_print(out, r_recp); | |
286 | printf("\nmont ="); | |
287 | BN_print(out, r_mont); | |
288 | printf("\nmont_ct ="); | |
289 | BN_print(out, r_mont_const); | |
290 | printf("\n"); | |
291 | EXIT(1); | |
292 | } | |
293 | } | |
294 | BN_free(r_mont); | |
295 | BN_free(r_mont_const); | |
296 | BN_free(r_recp); | |
297 | BN_free(r_simple); | |
298 | BN_free(a); | |
299 | BN_free(b); | |
300 | BN_free(m); | |
301 | BN_CTX_free(ctx); | |
302 | ERR_remove_thread_state(NULL); | |
7644a9ae | 303 | #ifdef CRYPTO_MDEBUG |
0f113f3e | 304 | CRYPTO_mem_leaks(out); |
7644a9ae | 305 | #endif |
0f113f3e MC |
306 | BIO_free(out); |
307 | printf("\n"); | |
308 | ||
309 | if (test_exp_mod_zero() != 0) | |
310 | goto err; | |
311 | ||
312 | printf("done\n"); | |
313 | ||
314 | EXIT(0); | |
315 | err: | |
316 | ERR_load_crypto_strings(); | |
317 | ERR_print_errors(out); | |
4d8743f4 RL |
318 | #ifdef OPENSSL_SYS_NETWARE |
319 | printf("ERROR\n"); | |
320 | #endif | |
0f113f3e | 321 | EXIT(1); |
0f113f3e | 322 | } |