summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/x509/x509_name_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/x509/x509_name_test.c')
-rw-r--r--src/regress/lib/libcrypto/x509/x509_name_test.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/x509/x509_name_test.c b/src/regress/lib/libcrypto/x509/x509_name_test.c
new file mode 100644
index 0000000000..24e62cc766
--- /dev/null
+++ b/src/regress/lib/libcrypto/x509/x509_name_test.c
@@ -0,0 +1,420 @@
1/* $OpenBSD: x509_name_test.c,v 1.3 2025/05/05 06:33:34 tb Exp $ */
2
3/*
4 * Copyright (c) 2025 Theo Buehler <tb@openbsd.org>
5 * Copyright (c) 2025 Kenjiro Nakayama <nakayamakenjiro@gmail.com>
6 * Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <err.h>
22#include <stdio.h>
23#include <string.h>
24
25#include <openssl/x509.h>
26
27static const struct x509_name_legacy {
28 const char *compat;
29 const char *oneline;
30 const uint8_t der[255];
31 size_t der_len;
32} x509_name_legacy_test[] = {
33 {
34 .compat =
35 "C=HU, "
36 "L=Budapest, "
37 "O=Microsec Ltd., "
38 "CN=Microsec e-Szigno Root CA 2009, "
39 "emailAddress=info@e-szigno.hu",
40 .oneline =
41 "/C=HU"
42 "/L=Budapest"
43 "/O=Microsec Ltd."
44 "/CN=Microsec e-Szigno Root CA 2009"
45 "/emailAddress=info@e-szigno.hu",
46 .der = {
47 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06,
48 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55,
49 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
50 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70,
51 0x65, 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06,
52 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69,
53 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c,
54 0x74, 0x64, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06,
55 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x4d, 0x69,
56 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x65,
57 0x2d, 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20,
58 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20,
59 0x32, 0x30, 0x30, 0x39, 0x31, 0x1f, 0x30, 0x1d,
60 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
61 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66,
62 0x6f, 0x40, 0x65, 0x2d, 0x73, 0x7a, 0x69, 0x67,
63 0x6e, 0x6f, 0x2e, 0x68, 0x75,
64 },
65 .der_len = 133,
66 },
67
68 {
69 .compat =
70 "serialNumber=G63287510, "
71 "C=ES, "
72 "O=ANF Autoridad de Certificacion, "
73 "OU=ANF CA Raiz, "
74 "CN=ANF Secure Server Root CA",
75 .oneline =
76 "/serialNumber=G63287510"
77 "/C=ES"
78 "/O=ANF Autoridad de Certificacion"
79 "/OU=ANF CA Raiz"
80 "/CN=ANF Secure Server Root CA",
81 .der = {
82 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06,
83 0x03, 0x55, 0x04, 0x05, 0x13, 0x09, 0x47, 0x36,
84 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31,
85 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
86 0x13, 0x02, 0x45, 0x53, 0x31, 0x27, 0x30, 0x25,
87 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x41,
88 0x4e, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x72,
89 0x69, 0x64, 0x61, 0x64, 0x20, 0x64, 0x65, 0x20,
90 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
91 0x61, 0x63, 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30,
92 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
93 0x41, 0x4e, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52,
94 0x61, 0x69, 0x7a, 0x31, 0x22, 0x30, 0x20, 0x06,
95 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, 0x4e,
96 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65,
97 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
98 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
99 },
100 .der_len = 135,
101 },
102
103 {
104 .compat =
105 "C=GB, "
106 "ST=Greater Manchester, "
107 "L=Salford, "
108 "O=COMODO CA Limited, "
109 "CN=COMODO Certification Authority",
110 .oneline =
111 "/C=GB"
112 "/ST=Greater Manchester"
113 "/L=Salford"
114 "/O=COMODO CA Limited"
115 "/CN=COMODO Certification Authority",
116 .der = {
117 0x30, 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06,
118 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42,
119 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
120 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74,
121 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68,
122 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30,
123 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07,
124 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31,
125 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a,
126 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f,
127 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69,
128 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06,
129 0x03, 0x55, 0x04, 0x03, 0x13, 0x1e, 0x43, 0x4f,
130 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x65, 0x72,
131 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
132 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
133 0x72, 0x69, 0x74, 0x79,
134 },
135 .der_len = 132,
136 },
137
138 {
139 .compat =
140 "C=HU, "
141 "L=Budapest, "
142 "O=Microsec Ltd., "
143 "2.5.4.97=VATHU-23584497, "
144 "CN=e-Szigno Root CA 2017",
145 .oneline =
146 "/C=HU"
147 "/L=Budapest"
148 "/O=Microsec Ltd."
149 "/2.5.4.97=VATHU-23584497"
150 "/CN=e-Szigno Root CA 2017",
151 .der = {
152 0x30, 0x71, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
153 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, 0x31,
154 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
155 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
156 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03,
157 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69, 0x63,
158 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c, 0x74,
159 0x64, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
160 0x55, 0x04, 0x61, 0x0c, 0x0e, 0x56, 0x41, 0x54,
161 0x48, 0x55, 0x2d, 0x32, 0x33, 0x35, 0x38, 0x34,
162 0x34, 0x39, 0x37, 0x31, 0x1e, 0x30, 0x1c, 0x06,
163 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x65, 0x2d,
164 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20, 0x52,
165 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32,
166 0x30, 0x31, 0x37,
167 },
168 .der_len = 115,
169 },
170
171 {
172
173 .compat =
174 "C=ES, "
175 "O=FNMT-RCM, "
176 "OU=Ceres, "
177 "2.5.4.97=VATES-Q2826004J, "
178 "CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS",
179 .oneline =
180 "/C=ES"
181 "/O=FNMT-RCM"
182 "/OU=Ceres"
183 "/2.5.4.97=VATES-Q2826004J"
184 "/CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS",
185 .der = {
186 0x30, 0x78, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
187 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31,
188 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a,
189 0x0c, 0x08, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52,
190 0x43, 0x4d, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03,
191 0x55, 0x04, 0x0b, 0x0c, 0x05, 0x43, 0x65, 0x72,
192 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
193 0x55, 0x04, 0x61, 0x0c, 0x0f, 0x56, 0x41, 0x54,
194 0x45, 0x53, 0x2d, 0x51, 0x32, 0x38, 0x32, 0x36,
195 0x30, 0x30, 0x34, 0x4a, 0x31, 0x2c, 0x30, 0x2a,
196 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x41,
197 0x43, 0x20, 0x52, 0x41, 0x49, 0x5a, 0x20, 0x46,
198 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x20,
199 0x53, 0x45, 0x52, 0x56, 0x49, 0x44, 0x4f, 0x52,
200 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52,
201 0x4f, 0x53
202 },
203 .der_len = 122,
204 },
205};
206
207#define N_X509_NAME_COMPAT \
208 (sizeof(x509_name_legacy_test) / sizeof(x509_name_legacy_test[0]))
209
210static int
211x509_name_compat_testcase(const struct x509_name_legacy *test)
212{
213 const uint8_t *p;
214 X509_NAME *name = NULL;
215 unsigned char *der = NULL;
216 int der_len = 0;
217 BIO *bio = NULL;
218 char *got;
219 int got_len;
220 char *buf = NULL;
221 int failed = 1;
222
223 p = test->der;
224 if ((name = d2i_X509_NAME(NULL, &p, test->der_len)) == NULL)
225 errx(1, "d2i_X509_NAME");
226
227 if ((der_len = i2d_X509_NAME(name, &der)) <= 0) {
228 fprintf(stderr, "FAIL: %s: i2d_X509_NAME", __func__);
229 der_len = 0;
230 goto err;
231 }
232
233 if (test->der_len != (size_t)der_len) {
234 fprintf(stderr, "FAIL: %s: der len: want %zu, got %d\n",
235 __func__, test->der_len, der_len);
236 goto err;
237 }
238
239 if (memcmp(test->der, der, test->der_len) != 0) {
240 fprintf(stderr, "FAIL: %s: DER mismatch\n", __func__);
241 goto err;
242 }
243
244 if ((bio = BIO_new(BIO_s_mem())) == NULL)
245 errx(1, "BIO_new");
246
247 if (!X509_NAME_print_ex(bio, name, 0, XN_FLAG_COMPAT)) {
248 fprintf(stderr, "FAIL: %s: X509_NAME_print_ex", __func__);
249 goto err;
250 }
251
252 if ((got_len = BIO_get_mem_data(bio, &got)) < 0)
253 errx(1, "BIO_get_mem_data");
254
255 if (strcmp(test->compat, got) != 0) {
256 fprintf(stderr, "FAIL: %s compat:\nwant: \"%s\",\ngot: \"%s\"\n",
257 __func__, test->compat, got);
258 goto err;
259 }
260
261 if ((buf = X509_NAME_oneline(name, NULL, 0)) == NULL)
262 errx(1, "X509_NAME_oneline");
263
264 if (strcmp(test->oneline, buf) != 0) {
265 fprintf(stderr, "FAIL: %s oneline:\nwant: \"%s\",\ngot: \"%s\"\n",
266 __func__, test->compat, got);
267 goto err;
268 }
269
270 failed = 0;
271
272 err:
273 BIO_free(bio);
274 free(buf);
275 X509_NAME_free(name);
276 freezero(der, der_len);
277
278 return failed;
279}
280
281static int
282x509_name_compat_test(void)
283{
284 size_t i;
285 int failed = 0;
286
287 for (i = 0; i < N_X509_NAME_COMPAT; i++)
288 failed |= x509_name_compat_testcase(&x509_name_legacy_test[i]);
289
290 return failed;
291}
292
293static const struct x509_name_entry_test {
294 const char *field;
295 const char *value;
296 int loc;
297 int set;
298 const char *expected_str;
299 const int expected_set[4];
300 const int expected_count;
301} entry_tests[] = {
302 {
303 .field = "ST",
304 .value = "BaWue",
305 .loc = -1,
306 .set = 0,
307 .expected_str = "ST=BaWue",
308 .expected_set = { 0 },
309 .expected_count = 1,
310 },
311 {
312 .field = "O",
313 .value = "KIT",
314 .loc = -1,
315 .set = 0,
316 .expected_str = "ST=BaWue, O=KIT",
317 .expected_set = { 0, 1 },
318 .expected_count = 2,
319 },
320 {
321 .field = "L",
322 .value = "Karlsruhe",
323 .loc = 1,
324 .set = 0,
325 .expected_str = "ST=BaWue, L=Karlsruhe, O=KIT",
326 .expected_set = { 0, 1, 2 },
327 .expected_count = 3,
328 },
329 {
330 .field = "C",
331 .value = "DE",
332 .loc = 0,
333 .set = 1,
334 .expected_str = "C=DE + ST=BaWue, L=Karlsruhe, O=KIT",
335 .expected_set = { 0, 0, 1, 2 },
336 .expected_count = 4,
337 },
338};
339
340#define N_ENTRY_TESTS (sizeof(entry_tests) / sizeof(entry_tests[0]))
341
342static int
343verify_x509_name_output(X509_NAME *name, const struct x509_name_entry_test *tc)
344{
345 BIO *bio;
346 char *got;
347 long got_len;
348 int loc, ret;
349 int failed = 1;
350
351 if ((bio = BIO_new(BIO_s_mem())) == NULL)
352 goto fail;
353
354 if ((ret = X509_NAME_print_ex(bio, name, 0, XN_FLAG_SEP_CPLUS_SPC)) == -1)
355 goto fail;
356
357 if ((got_len = BIO_get_mem_data(bio, &got)) < 0)
358 goto fail;
359
360 if (ret != got_len || strlen(tc->expected_str) != (size_t)ret)
361 goto fail;
362
363 if (strncmp(tc->expected_str, got, got_len) != 0)
364 goto fail;
365
366 if (X509_NAME_entry_count(name) != tc->expected_count)
367 goto fail;
368
369 for (loc = 0; loc < X509_NAME_entry_count(name); loc++) {
370 X509_NAME_ENTRY *e = X509_NAME_get_entry(name, loc);
371 if (e == NULL || X509_NAME_ENTRY_set(e) != tc->expected_set[loc])
372 goto fail;
373 }
374
375 failed = 0;
376
377 fail:
378 BIO_free(bio);
379
380 return failed;
381}
382
383static int
384x509_name_add_entry_test(void)
385{
386 X509_NAME *name;
387 int failed = 1;
388
389 if ((name = X509_NAME_new()) == NULL)
390 goto done;
391
392 for (size_t i = 0; i < N_ENTRY_TESTS; i++) {
393 const struct x509_name_entry_test *t = &entry_tests[i];
394
395 if (!X509_NAME_add_entry_by_txt(name, t->field, MBSTRING_ASC,
396 (const unsigned char *)t->value, -1, t->loc, t->set))
397 goto done;
398
399 if (verify_x509_name_output(name, t))
400 goto done;
401 }
402
403 failed = 0;
404
405 done:
406 X509_NAME_free(name);
407
408 return failed;
409}
410
411int
412main(void)
413{
414 int failed = 0;
415
416 failed |= x509_name_compat_test();
417 failed |= x509_name_add_entry_test();
418
419 return failed;
420}