1/* $OpenBSD: asn1oct.c,v 1.4 2023/05/13 07:17:32 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 <assert.h> 20#include <err.h> 21#include <string.h> 22 23#include <openssl/asn1.h> 24#include <openssl/x509v3.h> 25 26#define TESTBUFFER_SIZE 20 27 28static const struct i2s_asn1_octet_string_test { 29 const char *desc; 30 const uint8_t buf[TESTBUFFER_SIZE]; 31 long len; 32 const char *want; 33} i2s_test[] = { 34 { 35 .desc = "Empty buffer gives empty string", 36 .buf = { 0x00, }, 37 .len = 0, 38 .want = "", 39 }, 40 { 41 .desc = "all hex digits", 42 .buf = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }, 43 .len = 8, 44 .want = "01:23:45:67:89:AB:CD:EF", 45 }, 46 { 47 .desc = "all hex digits, scrambled", 48 .buf = { 0x98, 0x24, 0xbf, 0x3a, 0xc7, 0xd6, 0x01, 0x5e, }, 49 .len = 8, 50 .want = "98:24:BF:3A:C7:D6:01:5E", 51 }, 52 { 53 .desc = "Embedded 0 byte", 54 .buf = { 0x7a, 0x00, 0xbb, }, 55 .len = 3, 56 .want = "7A:00:BB", 57 }, 58 { 59 .desc = "All zeroes", 60 .buf = { 0x00, 0x00, 0x00, 0x00, 0x00, }, 61 .len = 4, 62 .want = "00:00:00:00", 63 }, 64 { 65 .desc = "All bits set", 66 .buf = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, 67 .len = 8, 68 .want = "FF:FF:FF:FF:FF:FF:FF:FF", 69 }, 70 { 71 .desc = "negative length", 72 .buf = { 0x00, }, 73 .len = -1, 74 }, 75}; 76 77#define N_I2S_TESTS (sizeof(i2s_test) / sizeof(i2s_test[0])) 78 79static int 80test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test *test) 81{ 82 ASN1_OCTET_STRING *aos = NULL; 83 int should_fail = test->want == NULL; 84 char *got = NULL; 85 int failed = 0; 86 87 if ((aos = ASN1_OCTET_STRING_new()) == NULL) 88 errx(1, "ASN1_OCTET_STRING_new"); 89 90 if (!ASN1_STRING_set(aos, (void *)test->buf, test->len)) 91 errx(1, "ASN1_STRING_set"); 92 93 if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) { 94 if (!should_fail) 95 errx(1, "i2s_ASN1_OCTET_STRING"); 96 } 97 98 if (!should_fail && strcmp(test->want, got) != 0) { 99 fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n", 100 __func__, test->desc, test->want, got); 101 failed |= 1; 102 } 103 104 ASN1_OCTET_STRING_free(aos); 105 free(got); 106 107 return failed; 108} 109 110static int 111test_new_ASN1_OCTET_STRING(void) 112{ 113 ASN1_OCTET_STRING *aos = NULL; 114 char *got; 115 int failed = 0; 116 117 if ((aos = ASN1_OCTET_STRING_new()) == NULL) 118 errx(1, "%s: ASN1_OCTET_STRING_new", __func__); 119 if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) 120 errx(1, "%s: i2s_ASN1_OCTET_STRING", __func__); 121 122 if (strcmp("", got) != 0) { 123 fprintf(stderr, "%s failed: want \"\", got \"%s\"\n", 124 __func__, got); 125 failed |= 1; 126 } 127 128 ASN1_OCTET_STRING_free(aos); 129 free(got); 130 131 return failed; 132} 133 134static int 135run_i2s_ASN1_OCTET_STRING_tests(void) 136{ 137 size_t i; 138 int failed = 0; 139 140 failed |= test_new_ASN1_OCTET_STRING(); 141 142 for (i = 0; i < N_I2S_TESTS; i++) 143 failed |= test_i2s_ASN1_OCTET_STRING(&i2s_test[i]); 144 145 return failed; 146} 147 148static const struct s2i_asn1_octet_string_test { 149 const char *desc; 150 const char *in; 151 const char *want; 152} s2i_test[] = { 153 /* Tests that should succeed. */ 154 { 155 .desc = "empty string", 156 .in = "", 157 .want = "", 158 }, 159 { 160 .desc = "only colons", 161 .in = ":::::::", 162 .want = "", 163 }, 164 { 165 .desc = "a 0 octet", 166 .in = "00", 167 .want = "00", 168 }, 169 { 170 .desc = "a 0 octet with stupid colons", 171 .in = ":::00:::::", 172 .want = "00", 173 }, 174 { 175 .desc = "more stupid colons", 176 .in = ":::C0fF::Ee:::::", 177 .want = "C0:FF:EE", 178 }, 179 { 180 .desc = "all hex digits", 181 .in = "0123456789abcdef", 182 .want = "01:23:45:67:89:AB:CD:EF", 183 }, 184 185 /* Tests that should fail. */ 186 { 187 .desc = "colons between hex digits", 188 .in = "A:F", 189 }, 190 { 191 .desc = "more colons between hex digits", 192 .in = "5:7", 193 }, 194 { 195 .desc = "one hex digit", 196 .in = "1", 197 }, 198 { 199 .desc = "three hex digits", 200 .in = "bad", 201 }, 202 { 203 .desc = "three hex digits, colon after first digit", 204 .in = "b:ad", 205 }, 206 { 207 .desc = "three hex digits, colon after second digit", 208 .in = "ba:d", 209 }, 210 { 211 .desc = "non-hex digit", 212 .in = "g00d", 213 }, 214 { 215 .desc = "non-hex digits", 216 .in = "d0gged", 217 }, 218 { 219 .desc = "trailing non-hex digit", 220 .in = "d00der", 221 }, 222}; 223 224#define N_S2I_TESTS (sizeof(s2i_test) / sizeof(s2i_test[0])) 225 226static int 227test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test *test) 228{ 229 ASN1_OCTET_STRING *aos = NULL; 230 char *got = NULL; 231 int should_fail = test->want == NULL; 232 int failed = 0; 233 234 if ((aos = s2i_ASN1_OCTET_STRING(NULL, NULL, test->in)) == NULL) { 235 if (!should_fail) 236 errx(1, "%s: s2i_ASN1_OCTET_STRING", test->desc); 237 goto done; 238 } 239 240 if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) 241 errx(1, "%s: i2s_ASN1_OCTET_STRING", test->desc); 242 243 assert(test->want != NULL); 244 if (strcmp(test->want, got) != 0) { 245 fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n", 246 __func__, test->desc, test->want, got); 247 failed |= 1; 248 } 249 250 done: 251 ASN1_OCTET_STRING_free(aos); 252 free(got); 253 254 return failed; 255} 256 257static int 258run_s2i_ASN1_OCTET_STRING_tests(void) 259{ 260 size_t i; 261 int failed = 0; 262 263 failed |= test_new_ASN1_OCTET_STRING(); 264 265 for (i = 0; i < N_S2I_TESTS; i++) 266 failed |= test_s2i_ASN1_OCTET_STRING(&s2i_test[i]); 267 268 return failed; 269} 270 271int 272main(void) 273{ 274 int failed = 0; 275 276 failed |= run_i2s_ASN1_OCTET_STRING_tests(); 277 failed |= run_s2i_ASN1_OCTET_STRING_tests(); 278 279 return failed; 280} 281