xref: /openbsd-src/regress/lib/libcrypto/bn/bn_print.c (revision 6971d2f98a81eea59cb815ada7271c03b5ea93da)
1 /*	$OpenBSD: bn_print.c,v 1.5 2023/07/27 06:41:39 tb Exp $ */
2 
3 /*
4  * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <err.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include <openssl/asn1.h>
24 #include <openssl/bio.h>
25 #include <openssl/bn.h>
26 
27 #include "bn_local.h"
28 
29 #define BATIHDIDIDI "mana mana"
30 #define BUF_MEM_LEN 1024
31 
32 static const char *pk = "040d305e1b159d03d0a17935b73a3c927aca151ccd62f39c"
33 			"265c073de554faa3d6cc12eaf4145fe88e19ab2f2e48e6ac"
34 			"184378acd037c3bdb2cd2ce647e21ae663b83d2e2f78c44f"
35 			"dbf40fa4684c55726b951d4e18429578cc373c91e29b652b"
36 			"29";
37 
38 const struct print_test {
39 	const char *desc;
40 	const char *want;
41 } bn_print_tests[] = {
42 	{
43 		.desc = "zero",
44 		.want = "    mana mana 0\n",
45 	},
46 	{
47 		.desc = "minus one",
48 		.want = "    mana mana 1 (0x1)\n",
49 	},
50 	{
51 		.desc = "minus one",
52 		.want = "    mana mana -1 (-0x1)\n",
53 	},
54 #ifdef _LP64
55 	{
56 		.desc = "largest word",
57 		.want = "    mana mana 18446744073709551615 "
58 			"(0xffffffffffffffff)\n",
59 	},
60 	{
61 		.desc = "smallest word",
62 		.want = "    mana mana -18446744073709551615 "
63 			"(-0xffffffffffffffff)\n",
64 	},
65 	{
66 		.desc = "largest negative non-word",
67 		.want = "    mana mana (Negative)\n"
68 			"        01:00:00:00:00:00:00:00:00\n",
69 	},
70 	{
71 		.desc = "smallest positive non-word",
72 		.want = "    mana mana\n"
73 			"        01:00:00:00:00:00:00:00:00\n",
74 	},
75 #else
76 	{
77 		.desc = "largest word",
78 		.want = "    mana mana 4294967295 (0xffffffff)\n",
79 	},
80 	{
81 		.desc = "smallest word",
82 		.want = "    mana mana -4294967295 (-0xffffffff)\n",
83 	},
84 	{
85 		.desc = "largest negative non-word",
86 		.want = "    mana mana (Negative)\n"
87 			"        01:00:00:00:00\n",
88 	},
89 	{
90 		.desc = "smallest positive non-word",
91 		.want = "    mana mana\n"
92 			"        01:00:00:00:00\n",
93 	},
94 #endif
95 	{
96 		.desc = "some pubkey",
97 		.want = "    mana mana\n"
98 			"        04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n"
99 			"        92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n"
100 			"        fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n"
101 			"        48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n"
102 			"        47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n"
103 			"        a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37:\n"
104 			"        3c:91:e2:9b:65:2b:29\n",
105 	},
106 	{
107 		.desc = "negated pubkey",
108 		.want = "    mana mana (Negative)\n"
109 			"        04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n"
110 			"        92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n"
111 			"        fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n"
112 			"        48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n"
113 			"        47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n"
114 			"        a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37:\n"
115 			"        3c:91:e2:9b:65:2b:29\n",
116 	},
117 	{
118 		.desc = "shifted negated pubkey",
119 		.want = "    mana mana (Negative)\n"
120 			"        04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n"
121 			"        92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n"
122 			"        fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n"
123 			"        48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n"
124 			"        47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n"
125 			"        a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37\n",
126 	},
127 	{
128 		.desc = "shifted pubkey",
129 		.want = "    mana mana\n"
130 			"        04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n"
131 			"        92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n"
132 			"        fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n"
133 			"        48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n"
134 			"        47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n"
135 			"        a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37\n",
136 	},
137 	{
138 		.desc = "high bit of first nibble is set",
139 		.want = "    mana mana\n"
140 			"        00:80:00:00:00:00:00:00:00:00\n",
141 	},
142 	{
143 		/* XXX - this is incorrect and should be fixed. */
144 		.desc = "high bit of first nibble is set for negative number",
145 		.want = "    mana mana (Negative)\n"
146 			"        00:80:00:00:00:00:00:00:00:00\n",
147 	},
148 };
149 
150 #define N_TESTCASES	(sizeof(bn_print_tests) / sizeof(bn_print_tests[0]))
151 
152 static int
bn_print_testcase(const BIGNUM * bn,const struct print_test * test)153 bn_print_testcase(const BIGNUM *bn, const struct print_test *test)
154 {
155 	BIO *bio;
156 	char *got;
157 	size_t want_len;
158 	long got_len;
159 	int failed = 1;
160 
161 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
162 		errx(1, "BIO_new");
163 
164 	if (!bn_printf(bio, bn, 4, "%s", BATIHDIDIDI))
165 		errx(1, "bn_printf");
166 
167 	if ((got_len = BIO_get_mem_data(bio, &got)) < 0)
168 		errx(1, "BIO_get_mem_data");
169 
170 	if ((want_len = strlen(test->want)) != (size_t)got_len) {
171 		fprintf(stderr, "%s: want: %zu, got %ld\n",
172 		    test->desc, want_len, got_len);
173 		goto err;
174 	}
175 
176 	if (strncmp(got, test->want, want_len) != 0) {
177 		fprintf(stderr, "%s: strings differ\n", test->desc);
178 		fprintf(stderr, "want: \"%s\"\ngot : \"%*s\"\n",
179 		    test->want, (int)got_len, got);
180 		goto err;
181 	}
182 
183 	failed = 0;
184  err:
185 	BIO_free(bio);
186 
187 	return failed;
188 }
189 
190 int
main(void)191 main(void)
192 {
193 	const struct print_test *test;
194 	size_t testcase = 0;
195 	BIGNUM *bn;
196 	int failed = 0;
197 
198 	/* zero */
199 	if ((bn = BN_new()) == NULL)
200 		errx(1, "BN_new");
201 	if (testcase >= N_TESTCASES)
202 		errx(1, "Too many tests");
203 	test = &bn_print_tests[testcase++];
204 	failed |= bn_print_testcase(bn, test);
205 
206 	/* one */
207 	if (!BN_set_word(bn, 1))
208 		errx(1, "BIO_set_word");
209 	if (testcase >= N_TESTCASES)
210 		errx(1, "Too many tests");
211 	test = &bn_print_tests[testcase++];
212 	failed |= bn_print_testcase(bn, test);
213 
214 	/* minus one */
215 	BN_set_negative(bn, 1);
216 	if (testcase >= N_TESTCASES)
217 		errx(1, "Too many tests");
218 	test = &bn_print_tests[testcase++];
219 	failed |= bn_print_testcase(bn, test);
220 
221 	/* largest word */
222 	if (!BN_set_word(bn, ~0))
223 		errx(1, "BN_set_word");
224 	if (testcase >= N_TESTCASES)
225 		errx(1, "Too many tests");
226 	test = &bn_print_tests[testcase++];
227 	failed |= bn_print_testcase(bn, test);
228 
229 	/* smallest word */
230 	BN_set_negative(bn, 1);
231 	if (testcase >= N_TESTCASES)
232 		errx(1, "Too many tests");
233 	test = &bn_print_tests[testcase++];
234 	failed |= bn_print_testcase(bn, test);
235 
236 	/* largest negative non-word */
237 	if (!BN_sub_word(bn, 1))
238 		errx(1, "ASN1_bn_print");
239 	if (testcase >= N_TESTCASES)
240 		errx(1, "Too many tests");
241 	test = &bn_print_tests[testcase++];
242 	failed |= bn_print_testcase(bn, test);
243 
244 	/* smallest positive non-word */
245 	BN_set_negative(bn, 0);
246 	if (testcase >= N_TESTCASES)
247 		errx(1, "Too many tests");
248 	test = &bn_print_tests[testcase++];
249 	failed |= bn_print_testcase(bn, test);
250 
251 	/* some pubkey */
252 	if (BN_hex2bn(&bn, pk) == 0)
253 		errx(1, "BN_hex2bn");
254 	if (testcase >= N_TESTCASES)
255 		errx(1, "Too many tests");
256 	test = &bn_print_tests[testcase++];
257 	failed |= bn_print_testcase(bn, test);
258 
259 	/* negated pubkey */
260 	BN_set_negative(bn, 1);
261 	if (testcase >= N_TESTCASES)
262 		errx(1, "Too many tests");
263 	test = &bn_print_tests[testcase++];
264 	failed |= bn_print_testcase(bn, test);
265 
266 	/* shifted negated pubkey */
267 	if (!BN_rshift(bn, bn, 7 * 8))
268 		errx(1, "BN_rshift");
269 	if (testcase >= N_TESTCASES)
270 		errx(1, "Too many tests");
271 	test = &bn_print_tests[testcase++];
272 	failed |= bn_print_testcase(bn, test);
273 
274 	/* shifted pubkey */
275 	BN_set_negative(bn, 0);
276 	if (testcase >= N_TESTCASES)
277 		errx(1, "Too many tests");
278 	test = &bn_print_tests[testcase++];
279 	failed |= bn_print_testcase(bn, test);
280 
281 	/* high bit of first nibble is set. */
282 	BN_zero(bn);
283 	if (!BN_set_bit(bn, 71))
284 		errx(1, "BN_set_bit");
285 	if (testcase >= N_TESTCASES)
286 		errx(1, "Too many tests");
287 	test = &bn_print_tests[testcase++];
288 	failed |= bn_print_testcase(bn, test);
289 
290 	/* high bit of first nibble is set for negative number. */
291 	BN_set_negative(bn, 1);
292 	if (testcase >= N_TESTCASES)
293 		errx(1, "Too many tests");
294 	test = &bn_print_tests[testcase++];
295 	failed |= bn_print_testcase(bn, test);
296 
297 	if (testcase != N_TESTCASES) {
298 		warnx("Not all tests run");
299 		failed |= 1;
300 	}
301 
302 	BN_free(bn);
303 
304 	return failed;
305 }
306