2 * Copyright 2015-2022 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/crypto.h>
13 #include <openssl/bio.h>
14 #include <openssl/x509.h>
15 #include <openssl/x509v3.h>
16 #include <openssl/pem.h>
17 #include <openssl/err.h>
20 static const char *certs_dir
;
21 static char *root_f
= NULL
;
22 static char *roots_f
= NULL
;
23 static char *untrusted_f
= NULL
;
24 static char *bad_f
= NULL
;
25 static char *req_f
= NULL
;
26 static char *sroot_cert
= NULL
;
27 static char *ca_cert
= NULL
;
28 static char *ee_cert
= NULL
;
30 #define load_cert_from_file(file) load_cert_pem(file, NULL)
33 * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery)
35 * Chain is as follows:
37 * rootCA (self-signed)
41 * subinterCA subinterCA (self-signed)
43 * leaf ------------------
47 * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE
48 * leaf and bad have CA=FALSE
50 * subinterCA and subinterCA (ss) have the same subject name and keys
52 * interCA (but not rootCA) and subinterCA (ss) are in the trusted store
54 * leaf and subinterCA are in the untrusted list (untrusted.pem)
55 * bad is the certificate being verified (bad.pem)
57 * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has
58 * CA=FALSE, and will therefore incorrectly verify bad
61 static int test_alt_chains_cert_forgery(void)
66 STACK_OF(X509
) *untrusted
= NULL
;
67 X509_STORE_CTX
*sctx
= NULL
;
68 X509_STORE
*store
= NULL
;
69 X509_LOOKUP
*lookup
= NULL
;
71 store
= X509_STORE_new();
75 lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file());
78 if (!X509_LOOKUP_load_file(lookup
, roots_f
, X509_FILETYPE_PEM
))
81 untrusted
= load_certs_pem(untrusted_f
);
83 if ((x
= load_cert_from_file(bad_f
)) == NULL
)
86 sctx
= X509_STORE_CTX_new();
90 if (!X509_STORE_CTX_init(sctx
, store
, x
, untrusted
))
93 i
= X509_verify_cert(sctx
);
95 if (i
== 0 && X509_STORE_CTX_get_error(sctx
) == X509_V_ERR_INVALID_CA
) {
96 /* This is the result we were expecting: Test passed */
100 X509_STORE_CTX_free(sctx
);
102 OSSL_STACK_OF_X509_free(untrusted
);
103 X509_STORE_free(store
);
107 static int test_distinguishing_id(void)
111 ASN1_OCTET_STRING
*v
= NULL
, *v2
= NULL
;
112 char *distid
= "this is an ID";
114 x
= load_cert_from_file(bad_f
);
118 v
= ASN1_OCTET_STRING_new();
122 if (!ASN1_OCTET_STRING_set(v
, (unsigned char *)distid
,
123 (int)strlen(distid
))) {
124 ASN1_OCTET_STRING_free(v
);
128 X509_set0_distinguishing_id(x
, v
);
130 v2
= X509_get0_distinguishing_id(x
);
132 || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v
, v2
), 0))
141 static int test_req_distinguishing_id(void)
146 ASN1_OCTET_STRING
*v
= NULL
, *v2
= NULL
;
147 char *distid
= "this is an ID";
149 bio
= BIO_new_file(req_f
, "r");
153 x
= PEM_read_bio_X509_REQ(bio
, NULL
, 0, NULL
);
157 v
= ASN1_OCTET_STRING_new();
161 if (!ASN1_OCTET_STRING_set(v
, (unsigned char *)distid
,
162 (int)strlen(distid
))) {
163 ASN1_OCTET_STRING_free(v
);
167 X509_REQ_set0_distinguishing_id(x
, v
);
169 v2
= X509_REQ_get0_distinguishing_id(x
);
171 || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v
, v2
), 0))
181 static int test_self_signed(const char *filename
, int use_trusted
, int expected
)
183 X509
*cert
= load_cert_from_file(filename
); /* may result in NULL */
184 STACK_OF(X509
) *trusted
= sk_X509_new_null();
185 X509_STORE_CTX
*ctx
= X509_STORE_CTX_new();
188 ret
= TEST_int_eq(X509_self_signed(cert
, 1), expected
);
192 ret
= ret
&& TEST_true(sk_X509_push(trusted
, cert
));
193 ret
= ret
&& TEST_true(X509_STORE_CTX_init(ctx
, NULL
, cert
, NULL
));
194 X509_STORE_CTX_set0_trusted_stack(ctx
, trusted
);
195 ret
= ret
&& TEST_int_eq(X509_verify_cert(ctx
), expected
);
198 X509_STORE_CTX_free(ctx
);
199 sk_X509_free(trusted
);
204 static int test_self_signed_good(void)
206 return test_self_signed(root_f
, 1, 1);
209 static int test_self_signed_bad(void)
211 return test_self_signed(bad_f
, 1, 0);
214 static int test_self_signed_error(void)
216 return test_self_signed("nonexistent file name", 1, -1);
219 static int test_store_ctx(void)
221 /* Verifying a cert where we have no trusted certs should fail */
222 return test_self_signed(bad_f
, 0, 0);
225 static int do_test_purpose(int purpose
, int expected
)
227 X509
*eecert
= load_cert_from_file(ee_cert
); /* may result in NULL */
228 X509
*untrcert
= load_cert_from_file(ca_cert
);
229 X509
*trcert
= load_cert_from_file(sroot_cert
);
230 STACK_OF(X509
) *trusted
= sk_X509_new_null();
231 STACK_OF(X509
) *untrusted
= sk_X509_new_null();
232 X509_STORE_CTX
*ctx
= X509_STORE_CTX_new();
235 if (!TEST_ptr(eecert
)
236 || !TEST_ptr(untrcert
)
238 || !TEST_ptr(trusted
)
239 || !TEST_ptr(untrusted
)
244 if (!TEST_true(sk_X509_push(trusted
, trcert
)))
247 if (!TEST_true(sk_X509_push(untrusted
, untrcert
)))
251 if (!TEST_true(X509_STORE_CTX_init(ctx
, NULL
, eecert
, untrusted
)))
254 if (!TEST_true(X509_STORE_CTX_set_purpose(ctx
, purpose
)))
258 * X509_STORE_CTX_set0_trusted_stack() is bady named. Despite the set0 name
259 * we are still responsible for freeing trusted after we have finished with
262 X509_STORE_CTX_set0_trusted_stack(ctx
, trusted
);
264 if (!TEST_int_eq(X509_verify_cert(ctx
), expected
))
269 OSSL_STACK_OF_X509_free(trusted
);
270 OSSL_STACK_OF_X509_free(untrusted
);
271 X509_STORE_CTX_free(ctx
);
278 static int test_purpose_ssl_client(void)
280 return do_test_purpose(X509_PURPOSE_SSL_CLIENT
, 0);
283 static int test_purpose_ssl_server(void)
285 return do_test_purpose(X509_PURPOSE_SSL_SERVER
, 1);
288 static int test_purpose_any(void)
290 return do_test_purpose(X509_PURPOSE_ANY
, 1);
293 OPT_TEST_DECLARE_USAGE("certs-dir\n")
295 int setup_tests(void)
297 if (!test_skip_common_options()) {
298 TEST_error("Error parsing test options\n");
302 if (!TEST_ptr(certs_dir
= test_get_argument(0)))
305 if (!TEST_ptr(root_f
= test_mk_file_path(certs_dir
, "rootCA.pem"))
306 || !TEST_ptr(roots_f
= test_mk_file_path(certs_dir
, "roots.pem"))
307 || !TEST_ptr(untrusted_f
= test_mk_file_path(certs_dir
, "untrusted.pem"))
308 || !TEST_ptr(bad_f
= test_mk_file_path(certs_dir
, "bad.pem"))
309 || !TEST_ptr(req_f
= test_mk_file_path(certs_dir
, "sm2-csr.pem"))
310 || !TEST_ptr(sroot_cert
= test_mk_file_path(certs_dir
, "sroot-cert.pem"))
311 || !TEST_ptr(ca_cert
= test_mk_file_path(certs_dir
, "ca-cert.pem"))
312 || !TEST_ptr(ee_cert
= test_mk_file_path(certs_dir
, "ee-cert.pem")))
315 ADD_TEST(test_alt_chains_cert_forgery
);
316 ADD_TEST(test_store_ctx
);
317 ADD_TEST(test_distinguishing_id
);
318 ADD_TEST(test_req_distinguishing_id
);
319 ADD_TEST(test_self_signed_good
);
320 ADD_TEST(test_self_signed_bad
);
321 ADD_TEST(test_self_signed_error
);
322 ADD_TEST(test_purpose_ssl_client
);
323 ADD_TEST(test_purpose_ssl_server
);
324 ADD_TEST(test_purpose_any
);
331 void cleanup_tests(void)
333 OPENSSL_free(root_f
);
334 OPENSSL_free(roots_f
);
335 OPENSSL_free(untrusted_f
);
338 OPENSSL_free(sroot_cert
);
339 OPENSSL_free(ca_cert
);
340 OPENSSL_free(ee_cert
);