2 * Copyright 2012-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #include <openssl/e_os2.h>
13 #include <openssl/x509.h>
14 #include <openssl/x509v3.h>
15 #include "internal/nelem.h"
18 static const char *const names
[] = {
19 "a", "b", ".", "*", "@",
20 ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
21 "-example.com", "example-.com",
22 "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
23 "*@example.com", "test@*.example.com", "example.com", "www.example.com",
24 "test.www.example.com", "*.example.com", "*.www.example.com",
25 "test.*.example.com", "www.*.com",
26 ".www.example.com", "*www.example.com",
27 "example.net", "xn--rger-koa.example.com",
28 "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
29 "*.good--example.com", "www.good--example.com",
30 "*.xn--bar.com", "xn--foo.xn--bar.com",
31 "a.example.com", "b.example.com",
32 "postmaster@example.com", "Postmaster@example.com",
33 "postmaster@EXAMPLE.COM",
37 static const char *const exceptions
[] = {
38 "set CN: host: [*.example.com] matches [a.example.com]",
39 "set CN: host: [*.example.com] matches [b.example.com]",
40 "set CN: host: [*.example.com] matches [www.example.com]",
41 "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
42 "set CN: host: [*.www.example.com] matches [test.www.example.com]",
43 "set CN: host: [*.www.example.com] matches [.www.example.com]",
44 "set CN: host: [*www.example.com] matches [www.example.com]",
45 "set CN: host: [test.www.example.com] matches [.www.example.com]",
46 "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
47 "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
48 "set CN: host: [*.good--example.com] matches [www.good--example.com]",
49 "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
50 "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
51 "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
52 "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
53 "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
54 "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
55 "set dnsName: host: [*.example.com] matches [www.example.com]",
56 "set dnsName: host: [*.example.com] matches [a.example.com]",
57 "set dnsName: host: [*.example.com] matches [b.example.com]",
58 "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
59 "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
60 "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
61 "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
62 "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
63 "set dnsName: host: [*www.example.com] matches [www.example.com]",
64 "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
65 "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
66 "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
67 "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
68 "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
69 "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
70 "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
71 "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
75 static int is_exception(const char *msg
)
79 for (p
= exceptions
; *p
; ++p
)
80 if (strcmp(msg
, *p
) == 0)
85 static int set_cn(X509
*crt
, ...)
100 nid
= va_arg(ap
, int);
103 name
= va_arg(ap
, const char *);
104 if (!X509_NAME_add_entry_by_NID(n
, nid
, MBSTRING_ASC
,
105 (unsigned char *)name
, -1, -1, 1))
108 if (!X509_set_subject_name(crt
, n
))
118 int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
119 X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
120 int nid, int crit, ASN1_OCTET_STRING *data);
121 int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
124 static int set_altname(X509
*crt
, ...)
127 GENERAL_NAMES
*gens
= NULL
;
128 GENERAL_NAME
*gen
= NULL
;
129 ASN1_IA5STRING
*ia5
= NULL
;
132 gens
= sk_GENERAL_NAME_new_null();
138 type
= va_arg(ap
, int);
141 name
= va_arg(ap
, const char *);
143 gen
= GENERAL_NAME_new();
146 ia5
= ASN1_IA5STRING_new();
149 if (!ASN1_STRING_set(ia5
, name
, -1))
154 GENERAL_NAME_set0_value(gen
, type
, ia5
);
160 sk_GENERAL_NAME_push(gens
, gen
);
163 if (!X509_add1_ext_i2d(crt
, NID_subject_alt_name
, gens
, 0, 0))
167 ASN1_IA5STRING_free(ia5
);
168 GENERAL_NAME_free(gen
);
169 GENERAL_NAMES_free(gens
);
174 static int set_cn1(X509
*crt
, const char *name
)
176 return set_cn(crt
, NID_commonName
, name
, 0);
179 static int set_cn_and_email(X509
*crt
, const char *name
)
181 return set_cn(crt
, NID_commonName
, name
,
182 NID_pkcs9_emailAddress
, "dummy@example.com", 0);
185 static int set_cn2(X509
*crt
, const char *name
)
187 return set_cn(crt
, NID_commonName
, "dummy value",
188 NID_commonName
, name
, 0);
191 static int set_cn3(X509
*crt
, const char *name
)
193 return set_cn(crt
, NID_commonName
, name
,
194 NID_commonName
, "dummy value", 0);
197 static int set_email1(X509
*crt
, const char *name
)
199 return set_cn(crt
, NID_pkcs9_emailAddress
, name
, 0);
202 static int set_email2(X509
*crt
, const char *name
)
204 return set_cn(crt
, NID_pkcs9_emailAddress
, "dummy@example.com",
205 NID_pkcs9_emailAddress
, name
, 0);
208 static int set_email3(X509
*crt
, const char *name
)
210 return set_cn(crt
, NID_pkcs9_emailAddress
, name
,
211 NID_pkcs9_emailAddress
, "dummy@example.com", 0);
214 static int set_email_and_cn(X509
*crt
, const char *name
)
216 return set_cn(crt
, NID_pkcs9_emailAddress
, name
,
217 NID_commonName
, "www.example.org", 0);
220 static int set_altname_dns(X509
*crt
, const char *name
)
222 return set_altname(crt
, GEN_DNS
, name
, 0);
225 static int set_altname_email(X509
*crt
, const char *name
)
227 return set_altname(crt
, GEN_EMAIL
, name
, 0);
231 int (*fn
) (X509
*, const char *);
237 static const struct set_name_fn name_fns
[] = {
238 {set_cn1
, "set CN", 1, 0},
239 {set_cn2
, "set CN", 1, 0},
240 {set_cn3
, "set CN", 1, 0},
241 {set_cn_and_email
, "set CN", 1, 0},
242 {set_email1
, "set emailAddress", 0, 1},
243 {set_email2
, "set emailAddress", 0, 1},
244 {set_email3
, "set emailAddress", 0, 1},
245 {set_email_and_cn
, "set emailAddress", 0, 1},
246 {set_altname_dns
, "set dnsName", 1, 0},
247 {set_altname_email
, "set rfc822Name", 0, 1},
250 static X509
*make_cert(void)
254 if (!TEST_ptr(crt
= X509_new()))
256 if (!TEST_true(X509_set_version(crt
, X509_VERSION_3
))) {
263 static int check_message(const struct set_name_fn
*fn
, const char *op
,
264 const char *nameincert
, int match
, const char *name
)
270 BIO_snprintf(msg
, sizeof(msg
), "%s: %s: [%s] %s [%s]",
271 fn
->name
, op
, nameincert
,
272 match
? "matches" : "does not match", name
);
273 if (is_exception(msg
))
275 TEST_error("%s", msg
);
279 static int run_cert(X509
*crt
, const char *nameincert
,
280 const struct set_name_fn
*fn
)
282 const char *const *pname
= names
;
285 for (; *pname
!= NULL
; ++pname
) {
286 int samename
= OPENSSL_strcasecmp(nameincert
, *pname
) == 0;
287 size_t namelen
= strlen(*pname
);
288 char *name
= OPENSSL_malloc(namelen
+ 1);
293 memcpy(name
, *pname
, namelen
+ 1);
296 if (!TEST_int_ge(ret
= X509_check_host(crt
, name
, namelen
, 0, NULL
),
299 } else if (fn
->host
) {
300 if (ret
== 1 && !samename
)
302 if (ret
== 0 && samename
)
306 if (!TEST_true(check_message(fn
, "host", nameincert
, match
, *pname
)))
310 if (!TEST_int_ge(ret
= X509_check_host(crt
, name
, namelen
,
311 X509_CHECK_FLAG_NO_WILDCARDS
,
314 } else if (fn
->host
) {
315 if (ret
== 1 && !samename
)
317 if (ret
== 0 && samename
)
321 if (!TEST_true(check_message(fn
, "host-no-wildcards",
322 nameincert
, match
, *pname
)))
326 ret
= X509_check_email(crt
, name
, namelen
, 0);
328 if (ret
&& !samename
)
330 if (!ret
&& samename
&& strchr(nameincert
, '@') != NULL
)
334 if (!TEST_true(check_message(fn
, "email", nameincert
, match
, *pname
)))
342 static int call_run_cert(int i
)
345 const struct set_name_fn
*pfn
= &name_fns
[i
];
347 const char *const *pname
;
349 TEST_info("%s", pfn
->name
);
350 for (pname
= names
; *pname
!= NULL
; pname
++) {
351 if (!TEST_ptr(crt
= make_cert())
352 || !TEST_true(pfn
->fn(crt
, *pname
))
353 || !run_cert(crt
, *pname
, pfn
))
360 static struct gennamedata
{
361 const unsigned char der
[22];
367 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
374 0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
375 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x30, 0x00
381 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
388 0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
389 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x60, 0x00
395 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
402 0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
403 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x61
409 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.2 }
416 0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
417 0x01, 0x84, 0xb7, 0x09, 0x02, 0x02, 0xa0, 0x03, 0x0c, 0x01, 0x61
423 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
430 0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
431 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x62
437 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
444 0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
445 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0xff
451 * OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
458 0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
459 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0x00
463 /* [1 PRIMITIVE] { "a" } */
469 /* [1 PRIMITIVE] { "b" } */
475 /* [2 PRIMITIVE] { "a" } */
481 /* [2 PRIMITIVE] { "b" } */
493 * OBJECT_IDENTIFIER { 2.5.4.3 }
501 0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55,
502 0x04, 0x03, 0x0c, 0x01, 0x61
512 * OBJECT_IDENTIFIER { 2.5.4.3 }
520 0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55,
521 0x04, 0x03, 0x0c, 0x01, 0x62
533 0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x61
545 0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x62
560 0xa5, 0x09, 0xa0, 0x02, 0x0c, 0x00, 0xa1, 0x03, 0x0c, 0x01, 0x61
575 0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x61, 0xa1, 0x03, 0x0c, 0x01,
591 0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x62, 0xa1, 0x03, 0x0c, 0x01,
596 /* [6 PRIMITIVE] { "a" } */
602 /* [6 PRIMITIVE] { "b" } */
608 /* [7 PRIMITIVE] { `11111111` } */
610 0x87, 0x04, 0x11, 0x11, 0x11, 0x11
614 /* [7 PRIMITIVE] { `22222222`} */
616 0x87, 0x04, 0x22, 0x22, 0x22, 0x22
620 /* [7 PRIMITIVE] { `11111111111111111111111111111111` } */
622 0x87, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
623 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
627 /* [7 PRIMITIVE] { `22222222222222222222222222222222` } */
629 0x87, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
630 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
634 /* [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.1 } */
636 0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
637 0xb7, 0x09, 0x02, 0x01
641 /* [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.2 } */
643 0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
644 0xb7, 0x09, 0x02, 0x02
649 * Regression test for CVE-2023-0286.
658 static int test_GENERAL_NAME_cmp(void)
661 GENERAL_NAME
**namesa
= OPENSSL_malloc(sizeof(*namesa
)
662 * OSSL_NELEM(gennames
));
663 GENERAL_NAME
**namesb
= OPENSSL_malloc(sizeof(*namesb
)
664 * OSSL_NELEM(gennames
));
667 if (!TEST_ptr(namesa
) || !TEST_ptr(namesb
))
670 for (i
= 0; i
< OSSL_NELEM(gennames
); i
++) {
671 const unsigned char *derp
= gennames
[i
].der
;
674 * We create two versions of each GENERAL_NAME so that we ensure when
675 * we compare them they are always different pointers.
677 namesa
[i
] = d2i_GENERAL_NAME(NULL
, &derp
, gennames
[i
].derlen
);
678 derp
= gennames
[i
].der
;
679 namesb
[i
] = d2i_GENERAL_NAME(NULL
, &derp
, gennames
[i
].derlen
);
680 if (!TEST_ptr(namesa
[i
]) || !TEST_ptr(namesb
[i
]))
684 /* Every name should be equal to itself and not equal to any others. */
685 for (i
= 0; i
< OSSL_NELEM(gennames
); i
++) {
686 for (j
= 0; j
< OSSL_NELEM(gennames
); j
++) {
688 if (!TEST_int_eq(GENERAL_NAME_cmp(namesa
[i
], namesb
[j
]), 0))
691 if (!TEST_int_ne(GENERAL_NAME_cmp(namesa
[i
], namesb
[j
]), 0))
699 for (i
= 0; i
< OSSL_NELEM(gennames
); i
++) {
701 GENERAL_NAME_free(namesa
[i
]);
703 GENERAL_NAME_free(namesb
[i
]);
705 OPENSSL_free(namesa
);
706 OPENSSL_free(namesb
);
711 int setup_tests(void)
713 ADD_ALL_TESTS(call_run_cert
, OSSL_NELEM(name_fns
));
714 ADD_TEST(test_GENERAL_NAME_cmp
);