1 /* $OpenBSD: asn1_string_to_utf8.c,v 1.2 2022/11/23 08:51:05 tb Exp $ */ 2 /* 3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <string.h> 20 21 #include <openssl/asn1.h> 22 23 struct asn1_string_to_utf8_test_case { 24 const char *description; 25 const ASN1_ITEM *item; 26 const uint8_t der[32]; 27 size_t der_len; 28 const uint8_t want[32]; 29 int want_len; 30 }; 31 32 static const struct asn1_string_to_utf8_test_case tests[] = { 33 { 34 .description = "hello", 35 .item = &ASN1_PRINTABLESTRING_it, 36 .der = { 37 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 38 }, 39 .der_len = 7, 40 .want = { 41 0x68, 0x65, 0x6c, 0x6c, 0x6f, 42 }, 43 .want_len = 5, 44 }, 45 { 46 .description = "face with tears of joy", 47 .item = &ASN1_UTF8STRING_it, 48 .der = { 49 0x0c, 0x04, 0xF0, 0x9F, 0x98, 0x82, 50 }, 51 .der_len = 6, 52 .want = { 53 0xF0, 0x9F, 0x98, 0x82, 54 }, 55 .want_len = 4, 56 }, 57 { 58 .description = "hi", 59 .item = &ASN1_IA5STRING_it, 60 .der = { 61 0x16, 0x02, 0x68, 0x69, 62 }, 63 .der_len = 4, 64 .want = { 65 0x68, 0x69, 66 }, 67 .want_len = 2, 68 }, 69 }; 70 71 const size_t N_TESTS = sizeof(tests) / sizeof(tests[0]); 72 73 static int 74 asn1_string_to_utf8_test(const struct asn1_string_to_utf8_test_case *test) 75 { 76 ASN1_STRING *str = NULL; 77 const unsigned char *der; 78 unsigned char *out = NULL; 79 int ret; 80 int failed = 1; 81 82 der = test->der; 83 if ((str = (ASN1_STRING *)ASN1_item_d2i(NULL, &der, test->der_len, 84 test->item)) == NULL) { 85 warnx("ASN1_item_d2i failed"); 86 goto err; 87 } 88 89 if ((ret = ASN1_STRING_to_UTF8(&out, str)) < 0) { 90 warnx("ASN1_STRING_to_UTF8 failed: got %d, want %d", ret, 91 test->want_len); 92 goto err; 93 } 94 95 if (ret != test->want_len) { 96 warnx("ASN1_STRING_to_UTF8: got %d, want %d", ret, 97 test->want_len); 98 goto err; 99 } 100 101 if (memcmp(out, test->want, test->want_len) != 0) { 102 warnx("memcmp failed"); 103 goto err; 104 } 105 106 failed = 0; 107 err: 108 ASN1_STRING_free(str); 109 free(out); 110 111 return failed; 112 } 113 114 static int 115 asn1_string_to_utf8_tests(void) 116 { 117 size_t i; 118 int failed = 0; 119 120 for (i = 0; i < N_TESTS; i++) 121 failed |= asn1_string_to_utf8_test(&tests[i]); 122 123 return failed; 124 } 125 126 int 127 main(void) 128 { 129 int failed = 0; 130 131 failed |= asn1_string_to_utf8_tests(); 132 133 return failed; 134 } 135