xref: /freebsd/crypto/openssl/test/verify_extra_test.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1*e0c4386eSCy Schubert /*
2*e0c4386eSCy Schubert  * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
3*e0c4386eSCy Schubert  *
4*e0c4386eSCy Schubert  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e0c4386eSCy Schubert  * this file except in compliance with the License.  You can obtain a copy
6*e0c4386eSCy Schubert  * in the file LICENSE in the source distribution or at
7*e0c4386eSCy Schubert  * https://www.openssl.org/source/license.html
8*e0c4386eSCy Schubert  */
9*e0c4386eSCy Schubert 
10*e0c4386eSCy Schubert #include <stdio.h>
11*e0c4386eSCy Schubert #include <string.h>
12*e0c4386eSCy Schubert #include <openssl/crypto.h>
13*e0c4386eSCy Schubert #include <openssl/bio.h>
14*e0c4386eSCy Schubert #include <openssl/x509.h>
15*e0c4386eSCy Schubert #include <openssl/x509v3.h>
16*e0c4386eSCy Schubert #include <openssl/pem.h>
17*e0c4386eSCy Schubert #include <openssl/err.h>
18*e0c4386eSCy Schubert #include "testutil.h"
19*e0c4386eSCy Schubert 
20*e0c4386eSCy Schubert static const char *certs_dir;
21*e0c4386eSCy Schubert static char *root_f = NULL;
22*e0c4386eSCy Schubert static char *roots_f = NULL;
23*e0c4386eSCy Schubert static char *untrusted_f = NULL;
24*e0c4386eSCy Schubert static char *bad_f = NULL;
25*e0c4386eSCy Schubert static char *req_f = NULL;
26*e0c4386eSCy Schubert static char *sroot_cert = NULL;
27*e0c4386eSCy Schubert static char *ca_cert = NULL;
28*e0c4386eSCy Schubert static char *ee_cert = NULL;
29*e0c4386eSCy Schubert 
30*e0c4386eSCy Schubert #define load_cert_from_file(file) load_cert_pem(file, NULL)
31*e0c4386eSCy Schubert 
32*e0c4386eSCy Schubert /*-
33*e0c4386eSCy Schubert  * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery)
34*e0c4386eSCy Schubert  *
35*e0c4386eSCy Schubert  * Chain is as follows:
36*e0c4386eSCy Schubert  *
37*e0c4386eSCy Schubert  * rootCA (self-signed)
38*e0c4386eSCy Schubert  *   |
39*e0c4386eSCy Schubert  * interCA
40*e0c4386eSCy Schubert  *   |
41*e0c4386eSCy Schubert  * subinterCA       subinterCA (self-signed)
42*e0c4386eSCy Schubert  *   |                   |
43*e0c4386eSCy Schubert  * leaf ------------------
44*e0c4386eSCy Schubert  *   |
45*e0c4386eSCy Schubert  * bad
46*e0c4386eSCy Schubert  *
47*e0c4386eSCy Schubert  * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE
48*e0c4386eSCy Schubert  * leaf and bad have CA=FALSE
49*e0c4386eSCy Schubert  *
50*e0c4386eSCy Schubert  * subinterCA and subinterCA (ss) have the same subject name and keys
51*e0c4386eSCy Schubert  *
52*e0c4386eSCy Schubert  * interCA (but not rootCA) and subinterCA (ss) are in the trusted store
53*e0c4386eSCy Schubert  * (roots.pem)
54*e0c4386eSCy Schubert  * leaf and subinterCA are in the untrusted list (untrusted.pem)
55*e0c4386eSCy Schubert  * bad is the certificate being verified (bad.pem)
56*e0c4386eSCy Schubert  *
57*e0c4386eSCy Schubert  * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has
58*e0c4386eSCy Schubert  * CA=FALSE, and will therefore incorrectly verify bad
59*e0c4386eSCy Schubert  *
60*e0c4386eSCy Schubert  */
test_alt_chains_cert_forgery(void)61*e0c4386eSCy Schubert static int test_alt_chains_cert_forgery(void)
62*e0c4386eSCy Schubert {
63*e0c4386eSCy Schubert     int ret = 0;
64*e0c4386eSCy Schubert     int i;
65*e0c4386eSCy Schubert     X509 *x = NULL;
66*e0c4386eSCy Schubert     STACK_OF(X509) *untrusted = NULL;
67*e0c4386eSCy Schubert     X509_STORE_CTX *sctx = NULL;
68*e0c4386eSCy Schubert     X509_STORE *store = NULL;
69*e0c4386eSCy Schubert     X509_LOOKUP *lookup = NULL;
70*e0c4386eSCy Schubert 
71*e0c4386eSCy Schubert     store = X509_STORE_new();
72*e0c4386eSCy Schubert     if (store == NULL)
73*e0c4386eSCy Schubert         goto err;
74*e0c4386eSCy Schubert 
75*e0c4386eSCy Schubert     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
76*e0c4386eSCy Schubert     if (lookup == NULL)
77*e0c4386eSCy Schubert         goto err;
78*e0c4386eSCy Schubert     if (!X509_LOOKUP_load_file(lookup, roots_f, X509_FILETYPE_PEM))
79*e0c4386eSCy Schubert         goto err;
80*e0c4386eSCy Schubert 
81*e0c4386eSCy Schubert     untrusted = load_certs_pem(untrusted_f);
82*e0c4386eSCy Schubert 
83*e0c4386eSCy Schubert     if ((x = load_cert_from_file(bad_f)) == NULL)
84*e0c4386eSCy Schubert         goto err;
85*e0c4386eSCy Schubert 
86*e0c4386eSCy Schubert     sctx = X509_STORE_CTX_new();
87*e0c4386eSCy Schubert     if (sctx == NULL)
88*e0c4386eSCy Schubert         goto err;
89*e0c4386eSCy Schubert 
90*e0c4386eSCy Schubert     if (!X509_STORE_CTX_init(sctx, store, x, untrusted))
91*e0c4386eSCy Schubert         goto err;
92*e0c4386eSCy Schubert 
93*e0c4386eSCy Schubert     i = X509_verify_cert(sctx);
94*e0c4386eSCy Schubert 
95*e0c4386eSCy Schubert     if (i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) {
96*e0c4386eSCy Schubert         /* This is the result we were expecting: Test passed */
97*e0c4386eSCy Schubert         ret = 1;
98*e0c4386eSCy Schubert     }
99*e0c4386eSCy Schubert  err:
100*e0c4386eSCy Schubert     X509_STORE_CTX_free(sctx);
101*e0c4386eSCy Schubert     X509_free(x);
102*e0c4386eSCy Schubert     sk_X509_pop_free(untrusted, X509_free);
103*e0c4386eSCy Schubert     X509_STORE_free(store);
104*e0c4386eSCy Schubert     return ret;
105*e0c4386eSCy Schubert }
106*e0c4386eSCy Schubert 
test_distinguishing_id(void)107*e0c4386eSCy Schubert static int test_distinguishing_id(void)
108*e0c4386eSCy Schubert {
109*e0c4386eSCy Schubert     X509 *x = NULL;
110*e0c4386eSCy Schubert     int ret = 0;
111*e0c4386eSCy Schubert     ASN1_OCTET_STRING *v = NULL, *v2 = NULL;
112*e0c4386eSCy Schubert     char *distid = "this is an ID";
113*e0c4386eSCy Schubert 
114*e0c4386eSCy Schubert     x = load_cert_from_file(bad_f);
115*e0c4386eSCy Schubert     if (x == NULL)
116*e0c4386eSCy Schubert         goto err;
117*e0c4386eSCy Schubert 
118*e0c4386eSCy Schubert     v = ASN1_OCTET_STRING_new();
119*e0c4386eSCy Schubert     if (v == NULL)
120*e0c4386eSCy Schubert         goto err;
121*e0c4386eSCy Schubert 
122*e0c4386eSCy Schubert     if (!ASN1_OCTET_STRING_set(v, (unsigned char *)distid,
123*e0c4386eSCy Schubert                                (int)strlen(distid))) {
124*e0c4386eSCy Schubert         ASN1_OCTET_STRING_free(v);
125*e0c4386eSCy Schubert         goto err;
126*e0c4386eSCy Schubert     }
127*e0c4386eSCy Schubert 
128*e0c4386eSCy Schubert     X509_set0_distinguishing_id(x, v);
129*e0c4386eSCy Schubert 
130*e0c4386eSCy Schubert     v2 = X509_get0_distinguishing_id(x);
131*e0c4386eSCy Schubert     if (!TEST_ptr(v2)
132*e0c4386eSCy Schubert             || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0))
133*e0c4386eSCy Schubert         goto err;
134*e0c4386eSCy Schubert 
135*e0c4386eSCy Schubert     ret = 1;
136*e0c4386eSCy Schubert  err:
137*e0c4386eSCy Schubert     X509_free(x);
138*e0c4386eSCy Schubert     return ret;
139*e0c4386eSCy Schubert }
140*e0c4386eSCy Schubert 
test_req_distinguishing_id(void)141*e0c4386eSCy Schubert static int test_req_distinguishing_id(void)
142*e0c4386eSCy Schubert {
143*e0c4386eSCy Schubert     X509_REQ *x = NULL;
144*e0c4386eSCy Schubert     BIO *bio = NULL;
145*e0c4386eSCy Schubert     int ret = 0;
146*e0c4386eSCy Schubert     ASN1_OCTET_STRING *v = NULL, *v2 = NULL;
147*e0c4386eSCy Schubert     char *distid = "this is an ID";
148*e0c4386eSCy Schubert 
149*e0c4386eSCy Schubert     bio = BIO_new_file(req_f, "r");
150*e0c4386eSCy Schubert     if (bio == NULL)
151*e0c4386eSCy Schubert         goto err;
152*e0c4386eSCy Schubert 
153*e0c4386eSCy Schubert     x = PEM_read_bio_X509_REQ(bio, NULL, 0, NULL);
154*e0c4386eSCy Schubert     if (x == NULL)
155*e0c4386eSCy Schubert         goto err;
156*e0c4386eSCy Schubert 
157*e0c4386eSCy Schubert     v = ASN1_OCTET_STRING_new();
158*e0c4386eSCy Schubert     if (v == NULL)
159*e0c4386eSCy Schubert         goto err;
160*e0c4386eSCy Schubert 
161*e0c4386eSCy Schubert     if (!ASN1_OCTET_STRING_set(v, (unsigned char *)distid,
162*e0c4386eSCy Schubert                                (int)strlen(distid))) {
163*e0c4386eSCy Schubert         ASN1_OCTET_STRING_free(v);
164*e0c4386eSCy Schubert         goto err;
165*e0c4386eSCy Schubert     }
166*e0c4386eSCy Schubert 
167*e0c4386eSCy Schubert     X509_REQ_set0_distinguishing_id(x, v);
168*e0c4386eSCy Schubert 
169*e0c4386eSCy Schubert     v2 = X509_REQ_get0_distinguishing_id(x);
170*e0c4386eSCy Schubert     if (!TEST_ptr(v2)
171*e0c4386eSCy Schubert             || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0))
172*e0c4386eSCy Schubert         goto err;
173*e0c4386eSCy Schubert 
174*e0c4386eSCy Schubert     ret = 1;
175*e0c4386eSCy Schubert  err:
176*e0c4386eSCy Schubert     X509_REQ_free(x);
177*e0c4386eSCy Schubert     BIO_free(bio);
178*e0c4386eSCy Schubert     return ret;
179*e0c4386eSCy Schubert }
180*e0c4386eSCy Schubert 
test_self_signed(const char * filename,int use_trusted,int expected)181*e0c4386eSCy Schubert static int test_self_signed(const char *filename, int use_trusted, int expected)
182*e0c4386eSCy Schubert {
183*e0c4386eSCy Schubert     X509 *cert = load_cert_from_file(filename); /* may result in NULL */
184*e0c4386eSCy Schubert     STACK_OF(X509) *trusted = sk_X509_new_null();
185*e0c4386eSCy Schubert     X509_STORE_CTX *ctx = X509_STORE_CTX_new();
186*e0c4386eSCy Schubert     int ret;
187*e0c4386eSCy Schubert 
188*e0c4386eSCy Schubert     ret = TEST_int_eq(X509_self_signed(cert, 1), expected);
189*e0c4386eSCy Schubert 
190*e0c4386eSCy Schubert     if (cert != NULL) {
191*e0c4386eSCy Schubert         if (use_trusted)
192*e0c4386eSCy Schubert             ret = ret && TEST_true(sk_X509_push(trusted, cert));
193*e0c4386eSCy Schubert         ret = ret && TEST_true(X509_STORE_CTX_init(ctx, NULL, cert, NULL));
194*e0c4386eSCy Schubert         X509_STORE_CTX_set0_trusted_stack(ctx, trusted);
195*e0c4386eSCy Schubert         ret = ret && TEST_int_eq(X509_verify_cert(ctx), expected);
196*e0c4386eSCy Schubert     }
197*e0c4386eSCy Schubert 
198*e0c4386eSCy Schubert     X509_STORE_CTX_free(ctx);
199*e0c4386eSCy Schubert     sk_X509_free(trusted);
200*e0c4386eSCy Schubert     X509_free(cert);
201*e0c4386eSCy Schubert     return ret;
202*e0c4386eSCy Schubert }
203*e0c4386eSCy Schubert 
test_self_signed_good(void)204*e0c4386eSCy Schubert static int test_self_signed_good(void)
205*e0c4386eSCy Schubert {
206*e0c4386eSCy Schubert     return test_self_signed(root_f, 1, 1);
207*e0c4386eSCy Schubert }
208*e0c4386eSCy Schubert 
test_self_signed_bad(void)209*e0c4386eSCy Schubert static int test_self_signed_bad(void)
210*e0c4386eSCy Schubert {
211*e0c4386eSCy Schubert     return test_self_signed(bad_f, 1, 0);
212*e0c4386eSCy Schubert }
213*e0c4386eSCy Schubert 
test_self_signed_error(void)214*e0c4386eSCy Schubert static int test_self_signed_error(void)
215*e0c4386eSCy Schubert {
216*e0c4386eSCy Schubert     return test_self_signed("nonexistent file name", 1, -1);
217*e0c4386eSCy Schubert }
218*e0c4386eSCy Schubert 
test_store_ctx(void)219*e0c4386eSCy Schubert static int test_store_ctx(void)
220*e0c4386eSCy Schubert {
221*e0c4386eSCy Schubert     /* Verifying a cert where we have no trusted certs should fail */
222*e0c4386eSCy Schubert     return test_self_signed(bad_f, 0, 0);
223*e0c4386eSCy Schubert }
224*e0c4386eSCy Schubert 
do_test_purpose(int purpose,int expected)225*e0c4386eSCy Schubert static int do_test_purpose(int purpose, int expected)
226*e0c4386eSCy Schubert {
227*e0c4386eSCy Schubert     X509 *eecert = load_cert_from_file(ee_cert); /* may result in NULL */
228*e0c4386eSCy Schubert     X509 *untrcert = load_cert_from_file(ca_cert);
229*e0c4386eSCy Schubert     X509 *trcert = load_cert_from_file(sroot_cert);
230*e0c4386eSCy Schubert     STACK_OF(X509) *trusted = sk_X509_new_null();
231*e0c4386eSCy Schubert     STACK_OF(X509) *untrusted = sk_X509_new_null();
232*e0c4386eSCy Schubert     X509_STORE_CTX *ctx = X509_STORE_CTX_new();
233*e0c4386eSCy Schubert     int testresult = 0;
234*e0c4386eSCy Schubert 
235*e0c4386eSCy Schubert     if (!TEST_ptr(eecert)
236*e0c4386eSCy Schubert             || !TEST_ptr(untrcert)
237*e0c4386eSCy Schubert             || !TEST_ptr(trcert)
238*e0c4386eSCy Schubert             || !TEST_ptr(trusted)
239*e0c4386eSCy Schubert             || !TEST_ptr(untrusted)
240*e0c4386eSCy Schubert             || !TEST_ptr(ctx))
241*e0c4386eSCy Schubert         goto err;
242*e0c4386eSCy Schubert 
243*e0c4386eSCy Schubert 
244*e0c4386eSCy Schubert     if (!TEST_true(sk_X509_push(trusted, trcert)))
245*e0c4386eSCy Schubert         goto err;
246*e0c4386eSCy Schubert     trcert = NULL;
247*e0c4386eSCy Schubert     if (!TEST_true(sk_X509_push(untrusted, untrcert)))
248*e0c4386eSCy Schubert         goto err;
249*e0c4386eSCy Schubert     untrcert = NULL;
250*e0c4386eSCy Schubert 
251*e0c4386eSCy Schubert     if (!TEST_true(X509_STORE_CTX_init(ctx, NULL, eecert, untrusted)))
252*e0c4386eSCy Schubert         goto err;
253*e0c4386eSCy Schubert 
254*e0c4386eSCy Schubert     if (!TEST_true(X509_STORE_CTX_set_purpose(ctx, purpose)))
255*e0c4386eSCy Schubert         goto err;
256*e0c4386eSCy Schubert 
257*e0c4386eSCy Schubert     /*
258*e0c4386eSCy Schubert      * X509_STORE_CTX_set0_trusted_stack() is bady named. Despite the set0 name
259*e0c4386eSCy Schubert      * we are still responsible for freeing trusted after we have finished with
260*e0c4386eSCy Schubert      * it.
261*e0c4386eSCy Schubert      */
262*e0c4386eSCy Schubert     X509_STORE_CTX_set0_trusted_stack(ctx, trusted);
263*e0c4386eSCy Schubert 
264*e0c4386eSCy Schubert     if (!TEST_int_eq(X509_verify_cert(ctx), expected))
265*e0c4386eSCy Schubert         goto err;
266*e0c4386eSCy Schubert 
267*e0c4386eSCy Schubert     testresult = 1;
268*e0c4386eSCy Schubert  err:
269*e0c4386eSCy Schubert     sk_X509_pop_free(trusted, X509_free);
270*e0c4386eSCy Schubert     sk_X509_pop_free(untrusted, X509_free);
271*e0c4386eSCy Schubert     X509_STORE_CTX_free(ctx);
272*e0c4386eSCy Schubert     X509_free(eecert);
273*e0c4386eSCy Schubert     X509_free(untrcert);
274*e0c4386eSCy Schubert     X509_free(trcert);
275*e0c4386eSCy Schubert     return testresult;
276*e0c4386eSCy Schubert }
277*e0c4386eSCy Schubert 
test_purpose_ssl_client(void)278*e0c4386eSCy Schubert static int test_purpose_ssl_client(void)
279*e0c4386eSCy Schubert {
280*e0c4386eSCy Schubert     return do_test_purpose(X509_PURPOSE_SSL_CLIENT, 0);
281*e0c4386eSCy Schubert }
282*e0c4386eSCy Schubert 
test_purpose_ssl_server(void)283*e0c4386eSCy Schubert static int test_purpose_ssl_server(void)
284*e0c4386eSCy Schubert {
285*e0c4386eSCy Schubert     return do_test_purpose(X509_PURPOSE_SSL_SERVER, 1);
286*e0c4386eSCy Schubert }
287*e0c4386eSCy Schubert 
test_purpose_any(void)288*e0c4386eSCy Schubert static int test_purpose_any(void)
289*e0c4386eSCy Schubert {
290*e0c4386eSCy Schubert     return do_test_purpose(X509_PURPOSE_ANY, 1);
291*e0c4386eSCy Schubert }
292*e0c4386eSCy Schubert 
293*e0c4386eSCy Schubert OPT_TEST_DECLARE_USAGE("certs-dir\n")
294*e0c4386eSCy Schubert 
setup_tests(void)295*e0c4386eSCy Schubert int setup_tests(void)
296*e0c4386eSCy Schubert {
297*e0c4386eSCy Schubert     if (!test_skip_common_options()) {
298*e0c4386eSCy Schubert         TEST_error("Error parsing test options\n");
299*e0c4386eSCy Schubert         return 0;
300*e0c4386eSCy Schubert     }
301*e0c4386eSCy Schubert 
302*e0c4386eSCy Schubert     if (!TEST_ptr(certs_dir = test_get_argument(0)))
303*e0c4386eSCy Schubert         return 0;
304*e0c4386eSCy Schubert 
305*e0c4386eSCy Schubert     if (!TEST_ptr(root_f = test_mk_file_path(certs_dir, "rootCA.pem"))
306*e0c4386eSCy Schubert             || !TEST_ptr(roots_f = test_mk_file_path(certs_dir, "roots.pem"))
307*e0c4386eSCy Schubert             || !TEST_ptr(untrusted_f = test_mk_file_path(certs_dir, "untrusted.pem"))
308*e0c4386eSCy Schubert             || !TEST_ptr(bad_f = test_mk_file_path(certs_dir, "bad.pem"))
309*e0c4386eSCy Schubert             || !TEST_ptr(req_f = test_mk_file_path(certs_dir, "sm2-csr.pem"))
310*e0c4386eSCy Schubert             || !TEST_ptr(sroot_cert = test_mk_file_path(certs_dir, "sroot-cert.pem"))
311*e0c4386eSCy Schubert             || !TEST_ptr(ca_cert = test_mk_file_path(certs_dir, "ca-cert.pem"))
312*e0c4386eSCy Schubert             || !TEST_ptr(ee_cert = test_mk_file_path(certs_dir, "ee-cert.pem")))
313*e0c4386eSCy Schubert         goto err;
314*e0c4386eSCy Schubert 
315*e0c4386eSCy Schubert     ADD_TEST(test_alt_chains_cert_forgery);
316*e0c4386eSCy Schubert     ADD_TEST(test_store_ctx);
317*e0c4386eSCy Schubert     ADD_TEST(test_distinguishing_id);
318*e0c4386eSCy Schubert     ADD_TEST(test_req_distinguishing_id);
319*e0c4386eSCy Schubert     ADD_TEST(test_self_signed_good);
320*e0c4386eSCy Schubert     ADD_TEST(test_self_signed_bad);
321*e0c4386eSCy Schubert     ADD_TEST(test_self_signed_error);
322*e0c4386eSCy Schubert     ADD_TEST(test_purpose_ssl_client);
323*e0c4386eSCy Schubert     ADD_TEST(test_purpose_ssl_server);
324*e0c4386eSCy Schubert     ADD_TEST(test_purpose_any);
325*e0c4386eSCy Schubert     return 1;
326*e0c4386eSCy Schubert  err:
327*e0c4386eSCy Schubert     cleanup_tests();
328*e0c4386eSCy Schubert     return 0;
329*e0c4386eSCy Schubert }
330*e0c4386eSCy Schubert 
cleanup_tests(void)331*e0c4386eSCy Schubert void cleanup_tests(void)
332*e0c4386eSCy Schubert {
333*e0c4386eSCy Schubert     OPENSSL_free(root_f);
334*e0c4386eSCy Schubert     OPENSSL_free(roots_f);
335*e0c4386eSCy Schubert     OPENSSL_free(untrusted_f);
336*e0c4386eSCy Schubert     OPENSSL_free(bad_f);
337*e0c4386eSCy Schubert     OPENSSL_free(req_f);
338*e0c4386eSCy Schubert     OPENSSL_free(sroot_cert);
339*e0c4386eSCy Schubert     OPENSSL_free(ca_cert);
340*e0c4386eSCy Schubert     OPENSSL_free(ee_cert);
341*e0c4386eSCy Schubert }
342