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