1 1.1 christos /* 2 1.1 christos * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <openssl/crypto.h> 11 1.1 christos #include <string.h> 12 1.1 christos 13 1.1 christos #include "crypto/punycode.h" 14 1.1 christos #include "internal/nelem.h" 15 1.1 christos #include "testutil.h" 16 1.1 christos 17 1.1 christos 18 1.1 christos static const struct puny_test { 19 1.1 christos unsigned int raw[50]; 20 1.1 christos const char *encoded; 21 1.1 christos } puny_cases[] = { 22 1.1 christos /* Test cases from RFC 3492 */ 23 1.1 christos { /* Arabic (Egyptian) */ 24 1.1 christos { 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644, 25 1.1 christos 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F 26 1.1 christos }, 27 1.1 christos "egbpdaj6bu4bxfgehfvwxn" 28 1.1 christos }, 29 1.1 christos { /* Chinese (simplified) */ 30 1.1 christos { 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587 31 1.1 christos }, 32 1.1 christos "ihqwcrb4cv8a8dqg056pqjye" 33 1.1 christos }, 34 1.1 christos { /* Chinese (traditional) */ 35 1.1 christos { 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587 36 1.1 christos }, 37 1.1 christos "ihqwctvzc91f659drss3x8bo0yb" 38 1.1 christos }, 39 1.1 christos { /* Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky */ 40 1.1 christos { 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 0x0074, 41 1.1 christos 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 0x00ED, 0x010D, 42 1.1 christos 0x0065, 0x0073, 0x006B, 0x0079 43 1.1 christos }, 44 1.1 christos "Proprostnemluvesky-uyb24dma41a" 45 1.1 christos }, 46 1.1 christos { /* Hebrew */ 47 1.1 christos { 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 0x05D8, 48 1.1 christos 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 0x05DD, 0x05E2, 49 1.1 christos 0x05D1, 0x05E8, 0x05D9, 0x05EA 50 1.1 christos }, 51 1.1 christos "4dbcagdahymbxekheh6e0a7fei0b" 52 1.1 christos }, 53 1.1 christos { /* Hindi (Devanagari) */ 54 1.1 christos { 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 0x094D, 55 1.1 christos 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 0x0928, 0x0939, 56 1.1 christos 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 0x0915, 0x0924, 0x0947, 57 1.1 christos 0x0939, 0x0948, 0x0902 58 1.1 christos }, 59 1.1 christos "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd" 60 1.1 christos }, 61 1.1 christos { /* Japanese (kanji and hiragana) */ 62 1.1 christos { 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 0x3092, 63 1.1 christos 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 0x306E, 0x304B 64 1.1 christos }, 65 1.1 christos "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa" 66 1.1 christos }, 67 1.1 christos { /* Korean (Hangul syllables) */ 68 1.1 christos { 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774, 69 1.1 christos 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C, 0xB2E4, 0xBA74, 70 1.1 christos 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 0xAE4C 71 1.1 christos }, 72 1.1 christos "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c" 73 1.1 christos }, 74 1.1 christos { /* Russian (Cyrillic) */ 75 1.1 christos { 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 0x043E, 76 1.1 christos 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 0x043E, 0x0440, 77 1.1 christos 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 0x0441, 0x0441, 0x043A, 78 1.1 christos 0x0438 79 1.1 christos }, 80 1.1 christos "b1abfaaepdrnnbgefbaDotcwatmq2g4l" 81 1.1 christos }, 82 1.1 christos { /* Spanish */ 83 1.1 christos { 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 0x0070, 84 1.1 christos 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 0x006D, 0x0070, 85 1.1 christos 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 0x0065, 0x0068, 0x0061, 86 1.1 christos 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 0x006E, 0x0045, 0x0073, 0x0070, 87 1.1 christos 0x0061, 0x00F1, 0x006F, 0x006C 88 1.1 christos }, 89 1.1 christos "PorqunopuedensimplementehablarenEspaol-fmd56a" 90 1.1 christos }, 91 1.1 christos { /* Vietnamese */ 92 1.1 christos { 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 0x006B, 93 1.1 christos 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 0x0063, 0x0068, 94 1.1 christos 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 0x1EBF, 0x006E, 0x0067, 95 1.1 christos 0x0056, 0x0069, 0x1EC7, 0x0074 96 1.1 christos }, 97 1.1 christos "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g" 98 1.1 christos }, 99 1.1 christos { /* Japanese: 3<nen>B<gumi><kinpachi><sensei> */ 100 1.1 christos { 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F 101 1.1 christos }, 102 1.1 christos "3B-ww4c5e180e575a65lsy2b" 103 1.1 christos }, 104 1.1 christos { /* Japanese: <amuro><namie>-with-SUPER-MONKEYS */ 105 1.1 christos { 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 0x0074, 106 1.1 christos 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 0x002D, 0x004D, 107 1.1 christos 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053 108 1.1 christos }, 109 1.1 christos "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n" 110 1.1 christos }, 111 1.1 christos { /* Japanese: Hello-Another-Way-<sorezore><no><basho> */ 112 1.1 christos { 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 0x006F, 113 1.1 christos 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 0x0079, 0x002D, 114 1.1 christos 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 0x6240 115 1.1 christos }, 116 1.1 christos "Hello-Another-Way--fc4qua05auwb3674vfr0b" 117 1.1 christos }, 118 1.1 christos { /* Japanese: <hitotsu><yane><no><shita>2 */ 119 1.1 christos { 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032 120 1.1 christos }, 121 1.1 christos "2-u9tlzr9756bt3uc0v" 122 1.1 christos }, 123 1.1 christos { /* Japanese: Maji<de>Koi<suru>5<byou><mae> */ 124 1.1 christos { 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 0x3059, 125 1.1 christos 0x308B, 0x0035, 0x79D2, 0x524D 126 1.1 christos }, 127 1.1 christos "MajiKoi5-783gue6qz075azm5e" 128 1.1 christos }, 129 1.1 christos { /* Japanese: <pafii>de<runba> */ 130 1.1 christos { 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0 131 1.1 christos }, 132 1.1 christos "de-jg4avhby1noc0d" 133 1.1 christos }, 134 1.1 christos { /* Japanese: <sono><supiido><de> */ 135 1.1 christos { 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 136 1.1 christos }, 137 1.1 christos "d9juau41awczczp" 138 1.1 christos }, 139 1.1 christos { /* -> $1.00 <- */ 140 1.1 christos { 0x002D, 0x003E, 0x0020, 0x0024, 0x0031, 0x002E, 0x0030, 0x0030, 0x0020, 141 1.1 christos 0x003C, 0x002D 142 1.1 christos }, 143 1.1 christos "-> $1.00 <--" 144 1.1 christos } 145 1.1 christos }; 146 1.1 christos 147 1.1 christos static int test_punycode(int n) 148 1.1 christos { 149 1.1 christos const struct puny_test *tc = puny_cases + n; 150 1.1 christos unsigned int buffer[50]; 151 1.1 christos unsigned int bsize = OSSL_NELEM(buffer); 152 1.1 christos size_t i; 153 1.1 christos 154 1.1 christos if (!TEST_true(ossl_punycode_decode(tc->encoded, strlen(tc->encoded), 155 1.1 christos buffer, &bsize))) 156 1.1 christos return 0; 157 1.1 christos for (i = 0; i < OSSL_NELEM(tc->raw); i++) 158 1.1 christos if (tc->raw[i] == 0) 159 1.1 christos break; 160 1.1 christos if (!TEST_mem_eq(buffer, bsize * sizeof(*buffer), 161 1.1 christos tc->raw, i * sizeof(*tc->raw))) 162 1.1 christos return 0; 163 1.1 christos return 1; 164 1.1 christos } 165 1.1 christos 166 1.1 christos static int test_a2ulabel(void) 167 1.1 christos { 168 1.1 christos char out[50]; 169 1.1 christos size_t outlen; 170 1.1 christos 171 1.1 christos /* 172 1.1 christos * Test that no buffer correctly returns the true length. 173 1.1 christos * The punycode being passed in and parsed is malformed but we're not 174 1.1 christos * verifying that behaviour here. 175 1.1 christos */ 176 1.1 christos if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", NULL, &outlen), 0) 177 1.1 christos || !TEST_size_t_eq(outlen, 7) 178 1.1 christos || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1)) 179 1.1 christos return 0; 180 1.1 christos /* Test that a short input length returns the true length */ 181 1.1 christos outlen = 1; 182 1.1 christos if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 0) 183 1.1 christos || !TEST_size_t_eq(outlen, 7) 184 1.1 christos || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1) 185 1.1 christos || !TEST_str_eq(out,"\xc2\x80.b.c")) 186 1.1 christos return 0; 187 1.1 christos /* Test for an off by one on the buffer size works */ 188 1.1 christos outlen = 6; 189 1.1 christos if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 0) 190 1.1 christos || !TEST_size_t_eq(outlen, 7) 191 1.1 christos || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1) 192 1.1 christos || !TEST_str_eq(out,"\xc2\x80.b.c")) 193 1.1 christos return 0; 194 1.1 christos return 1; 195 1.1 christos } 196 1.1 christos 197 1.1 christos static int test_puny_overrun(void) 198 1.1 christos { 199 1.1 christos static const unsigned int out[] = { 200 1.1 christos 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F 201 1.1 christos }; 202 1.1 christos static const char *in = "3B-ww4c5e180e575a65lsy2b"; 203 1.1 christos unsigned int buf[OSSL_NELEM(out)]; 204 1.1 christos unsigned int bsize = OSSL_NELEM(buf) - 1; 205 1.1 christos 206 1.1 christos if (!TEST_false(ossl_punycode_decode(in, strlen(in), buf, &bsize))) { 207 1.1 christos if (TEST_mem_eq(buf, bsize * sizeof(*buf), out, sizeof(out))) 208 1.1 christos TEST_error("CRITICAL: buffer overrun detected!"); 209 1.1 christos return 0; 210 1.1 christos } 211 1.1 christos return 1; 212 1.1 christos } 213 1.1 christos 214 1.1 christos int setup_tests(void) 215 1.1 christos { 216 1.1 christos ADD_ALL_TESTS(test_punycode, OSSL_NELEM(puny_cases)); 217 1.1 christos ADD_TEST(test_a2ulabel); 218 1.1 christos ADD_TEST(test_puny_overrun); 219 1.1 christos return 1; 220 1.1 christos } 221