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 32static const char *pk = "040d305e1b159d03d0a17935b73a3c927aca151ccd62f39c" 33 "265c073de554faa3d6cc12eaf4145fe88e19ab2f2e48e6ac" 34 "184378acd037c3bdb2cd2ce647e21ae663b83d2e2f78c44f" 35 "dbf40fa4684c55726b951d4e18429578cc373c91e29b652b" 36 "29"; 37 38const 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 152static int 153bn_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 190int 191main(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