1/*	$NetBSD: test_bn.c,v 1.1.1.1 2011/04/13 18:14:51 elric Exp $	*/
2
3/*
4 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <config.h>
37
38#include <sys/types.h>
39#include <limits.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include <bn.h>
45#include <rand.h>
46
47static int
48set_get(unsigned long num)
49{
50    BIGNUM *bn;
51
52    bn = BN_new();
53    if (!BN_set_word(bn, num))
54	return 1;
55
56    if (BN_get_word(bn) != num)
57	return 1;
58
59    BN_free(bn);
60    return 0;
61}
62
63#define CHECK(x) do { ret += x; } while(0)
64
65static int
66test_BN_set_get(void)
67{
68    int ret = 0;
69    CHECK(set_get(0));
70    CHECK(set_get(1));
71    CHECK(set_get(0xff));
72    CHECK(set_get(0x1ff));
73    CHECK(set_get(0xffff));
74    CHECK(set_get(0xf000));
75    CHECK(set_get(ULONG_MAX / 2));
76    CHECK(set_get(ULONG_MAX - 1));
77
78    return ret;
79}
80
81static int
82test_BN_bit(void)
83{
84    BIGNUM *bn;
85    int ret = 0;
86
87    bn = BN_new();
88
89    /* test setting and getting of "word" */
90    if (!BN_set_word(bn, 1))
91	return 1;
92    if (!BN_is_bit_set(bn, 0))
93	ret += 1;
94    if (!BN_is_bit_set(bn, 0))
95	ret += 1;
96
97    if (!BN_set_word(bn, 2))
98	return 1;
99    if (!BN_is_bit_set(bn, 1))
100	ret += 1;
101
102    if (!BN_set_word(bn, 3))
103	return 1;
104    if (!BN_is_bit_set(bn, 0))
105	ret += 1;
106    if (!BN_is_bit_set(bn, 1))
107	ret += 1;
108
109    if (!BN_set_word(bn, 0x100))
110	return 1;
111    if (!BN_is_bit_set(bn, 8))
112	ret += 1;
113
114    if (!BN_set_word(bn, 0x1000))
115	return 1;
116    if (!BN_is_bit_set(bn, 12))
117	ret += 1;
118
119    /* test bitsetting */
120    if (!BN_set_word(bn, 1))
121	return 1;
122    if (!BN_set_bit(bn, 1))
123	return 1;
124    if (BN_get_word(bn) != 3)
125	return 1;
126    if (!BN_clear_bit(bn, 0))
127	return 1;
128    if (BN_get_word(bn) != 2)
129	return 1;
130
131    /* test bitsetting past end of current end */
132    BN_clear(bn);
133    if (!BN_set_bit(bn, 12))
134	return 1;
135    if (BN_get_word(bn) != 0x1000)
136	return 1;
137
138    /* test bit and byte counting functions */
139    if (BN_num_bits(bn) != 13)
140	return 1;
141    if (BN_num_bytes(bn) != 2)
142	return 1;
143
144    BN_free(bn);
145    return ret;
146}
147
148struct ietest {
149    char *data;
150    size_t len;
151    unsigned long num;
152} ietests[] = {
153    { "", 0, 0 },
154    { "\x01", 1, 1 },
155    { "\x02", 1, 2 },
156    { "\xf2", 1, 0xf2 },
157    { "\x01\x00", 2, 256 }
158};
159
160static int
161test_BN_import_export(void)
162{
163    BIGNUM *bn;
164    int ret = 0;
165    int i;
166
167    bn = BN_new();
168
169    for (i = 0; i < sizeof(ietests)/sizeof(ietests[0]); i++) {
170	size_t len;
171	unsigned char *p;
172	if (!BN_bin2bn((unsigned char*)ietests[i].data, ietests[i].len, bn))
173	    return 1;
174	if (BN_get_word(bn) != ietests[i].num)
175	    return 1;
176	len = BN_num_bytes(bn);
177	if (len != ietests[i].len)
178	    return 1;
179	p = malloc(len + 1);
180	p[len] = 0xf4;
181	BN_bn2bin(bn, p);
182	if (p[len] != 0xf4)
183	    return 1;
184	if (memcmp(p, ietests[i].data, ietests[i].len) != 0)
185	    return 1;
186	free(p);
187    }
188
189    BN_free(bn);
190    return ret;
191}
192
193static int
194test_BN_uadd(void)
195{
196    BIGNUM *a, *b, *c;
197    char *p;
198
199    a = BN_new();
200    b = BN_new();
201    c = BN_new();
202
203    BN_set_word(a, 1);
204    BN_set_word(b, 2);
205
206    BN_uadd(c, a, b);
207
208    if (BN_get_word(c) != 3)
209	return 1;
210
211    BN_uadd(c, b, a);
212
213    if (BN_get_word(c) != 3)
214	return 1;
215
216    BN_set_word(b, 0xff);
217
218    BN_uadd(c, a, b);
219    if (BN_get_word(c) != 0x100)
220	return 1;
221
222    BN_uadd(c, b, a);
223    if (BN_get_word(c) != 0x100)
224	return 1;
225
226    BN_set_word(a, 0xff);
227
228    BN_uadd(c, a, b);
229    if (BN_get_word(c) != 0x1fe)
230	return 1;
231
232    BN_uadd(c, b, a);
233    if (BN_get_word(c) != 0x1fe)
234	return 1;
235
236
237    BN_free(a);
238    BN_free(b);
239
240    BN_hex2bn(&a, "50212A3B611D46642C825A16A354CE0FD4D85DD2");
241    BN_hex2bn(&b, "84B6C7E8D28ACA1614954DA");
242
243    BN_uadd(c, b, a);
244    p = BN_bn2hex(c);
245    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
246	free(p);
247	return 1;
248    }
249    free(p);
250
251    BN_uadd(c, a, b);
252    p = BN_bn2hex(c);
253    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
254	free(p);
255	return 1;
256    }
257    free(p);
258
259    BN_free(a);
260    BN_free(b);
261    BN_free(c);
262
263    return 0;
264}
265
266static int
267test_BN_cmp(void)
268{
269    BIGNUM *a, *b;
270
271    a = BN_new();
272    b = BN_new();
273
274    if (!BN_set_word(a, 1))
275	return 1;
276    if (!BN_set_word(b, 1))
277	return 1;
278
279    if (BN_cmp(a, b) != 0)
280	return 1;
281    if (BN_cmp(b, a) != 0)
282	return 1;
283
284    if (!BN_set_word(b, 2))
285	return 1;
286
287    if (BN_cmp(a, b) >= 0)
288	return 1;
289    if (BN_cmp(b, a) <= 0)
290	return 1;
291
292    BN_set_negative(b, 1);
293
294    if (BN_cmp(a, b) <= 0)
295	return 1;
296    if (BN_cmp(b, a) >= 0)
297	return 1;
298
299    BN_free(a);
300    BN_free(b);
301
302    BN_hex2bn(&a, "50212A3B611D46642C825A16A354CE0FD4D85DD1");
303    BN_hex2bn(&b, "50212A3B611D46642C825A16A354CE0FD4D85DD2");
304
305    if (BN_cmp(a, b) >= 0)
306	return 1;
307    if (BN_cmp(b, a) <= 0)
308	return 1;
309
310    BN_set_negative(b, 1);
311
312    if (BN_cmp(a, b) <= 0)
313	return 1;
314    if (BN_cmp(b, a) >= 0)
315	return 1;
316
317    BN_free(a);
318    BN_free(b);
319    return 0;
320}
321
322static int
323test_BN_rand(void)
324{
325    BIGNUM *bn;
326
327    if (RAND_status() != 1)
328	return 0;
329
330    bn = BN_new();
331    if (bn == NULL)
332	return 1;
333
334    if (!BN_rand(bn, 1024, 0, 0))
335	return 1;
336
337    BN_free(bn);
338    return 0;
339}
340
341#define testnum 100
342#define testnum2 10
343
344static int
345test_BN_CTX(void)
346{
347    unsigned int i, j;
348    BIGNUM *bn;
349    BN_CTX *c;
350
351    if ((c = BN_CTX_new()) == NULL)
352	return 1;
353
354    for (i = 0; i < testnum; i++) {
355	BN_CTX_start(c);
356	BN_CTX_end(c);
357    }
358
359    for (i = 0; i < testnum; i++)
360	BN_CTX_start(c);
361    for (i = 0; i < testnum; i++)
362	BN_CTX_end(c);
363
364    for (i = 0; i < testnum; i++) {
365	BN_CTX_start(c);
366	if ((bn = BN_CTX_get(c)) == NULL)
367	    return 1;
368	BN_CTX_end(c);
369    }
370
371    for (i = 0; i < testnum; i++) {
372	BN_CTX_start(c);
373	for (j = 0; j < testnum2; j++)
374	    if ((bn = BN_CTX_get(c)) == NULL)
375		return 1;
376    }
377    for (i = 0; i < testnum; i++)
378	BN_CTX_end(c);
379
380    BN_CTX_free(c);
381    return 0;
382}
383
384
385int
386main(int argc, char **argv)
387{
388    int ret = 0;
389
390    ret += test_BN_set_get();
391    ret += test_BN_bit();
392    ret += test_BN_import_export();
393    ret += test_BN_uadd();
394    ret += test_BN_cmp();
395    ret += test_BN_rand();
396    ret += test_BN_CTX();
397
398    return ret;
399}
400