Fix safestack issues in x509.h
[openssl.git] / test / verify_extra_test.c
1 /*
2  * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <openssl/crypto.h>
13 #include <openssl/bio.h>
14 #include <openssl/x509.h>
15 #include <openssl/pem.h>
16 #include <openssl/err.h>
17 #include "testutil.h"
18
19 static const char *root_f;
20 static const char *roots_f;
21 static const char *untrusted_f;
22 static const char *bad_f;
23 static const char *req_f;
24
25 static X509 *load_cert_from_file(const char *filename)
26 {
27     X509 *cert = NULL;
28     BIO *bio;
29
30     bio = BIO_new_file(filename, "r");
31     if (bio != NULL)
32         cert = PEM_read_bio_X509(bio, NULL, 0, NULL);
33     BIO_free(bio);
34     return cert;
35 }
36
37 static STACK_OF(X509) *load_certs_from_file(const char *filename)
38 {
39     STACK_OF(X509) *certs;
40     BIO *bio;
41     X509 *x;
42
43     bio = BIO_new_file(filename, "r");
44
45     if (bio == NULL) {
46         return NULL;
47     }
48
49     certs = sk_X509_new_null();
50     if (certs == NULL) {
51         BIO_free(bio);
52         return NULL;
53     }
54
55     ERR_set_mark();
56     do {
57         x = PEM_read_bio_X509(bio, NULL, 0, NULL);
58         if (x != NULL && !sk_X509_push(certs, x)) {
59             sk_X509_pop_free(certs, X509_free);
60             BIO_free(bio);
61             return NULL;
62         } else if (x == NULL) {
63             /*
64              * We probably just ran out of certs, so ignore any errors
65              * generated
66              */
67             ERR_pop_to_mark();
68         }
69     } while (x != NULL);
70
71     BIO_free(bio);
72
73     return certs;
74 }
75
76 /*
77  * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery)
78  *
79  * Chain is as follows:
80  *
81  * rootCA (self-signed)
82  *   |
83  * interCA
84  *   |
85  * subinterCA       subinterCA (self-signed)
86  *   |                   |
87  * leaf ------------------
88  *   |
89  * bad
90  *
91  * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE
92  * leaf and bad have CA=FALSE
93  *
94  * subinterCA and subinterCA (ss) have the same subject name and keys
95  *
96  * interCA (but not rootCA) and subinterCA (ss) are in the trusted store
97  * (roots.pem)
98  * leaf and subinterCA are in the untrusted list (untrusted.pem)
99  * bad is the certificate being verified (bad.pem)
100  *
101  * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has
102  * CA=FALSE, and will therefore incorrectly verify bad
103  *
104  */
105 static int test_alt_chains_cert_forgery(void)
106 {
107     int ret = 0;
108     int i;
109     X509 *x = NULL;
110     STACK_OF(X509) *untrusted = NULL;
111     X509_STORE_CTX *sctx = NULL;
112     X509_STORE *store = NULL;
113     X509_LOOKUP *lookup = NULL;
114
115     store = X509_STORE_new();
116     if (store == NULL)
117         goto err;
118
119     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
120     if (lookup == NULL)
121         goto err;
122     if (!X509_LOOKUP_load_file(lookup, roots_f, X509_FILETYPE_PEM))
123         goto err;
124
125     untrusted = load_certs_from_file(untrusted_f);
126
127     if ((x = load_cert_from_file(bad_f)) == NULL)
128         goto err;
129
130     sctx = X509_STORE_CTX_new();
131     if (sctx == NULL)
132         goto err;
133
134     if (!X509_STORE_CTX_init(sctx, store, x, untrusted))
135         goto err;
136
137     i = X509_verify_cert(sctx);
138
139     if (i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) {
140         /* This is the result we were expecting: Test passed */
141         ret = 1;
142     }
143  err:
144     X509_STORE_CTX_free(sctx);
145     X509_free(x);
146     sk_X509_pop_free(untrusted, X509_free);
147     X509_STORE_free(store);
148     return ret;
149 }
150
151 static int test_store_ctx(void)
152 {
153     X509_STORE_CTX *sctx = NULL;
154     X509 *x = NULL;
155     int testresult = 0, ret;
156
157     x = load_cert_from_file(bad_f);
158     if (x == NULL)
159         goto err;
160
161     sctx = X509_STORE_CTX_new();
162     if (sctx == NULL)
163         goto err;
164
165     if (!X509_STORE_CTX_init(sctx, NULL, x, NULL))
166         goto err;
167
168     /* Verifying a cert where we have no trusted certs should fail */
169     ret = X509_verify_cert(sctx);
170
171     if (ret == 0) {
172         /* This is the result we were expecting: Test passed */
173         testresult = 1;
174     }
175
176  err:
177     X509_STORE_CTX_free(sctx);
178     X509_free(x);
179     return testresult;
180 }
181
182 OPT_TEST_DECLARE_USAGE("roots.pem untrusted.pem bad.pem\n")
183
184 static int test_distinguishing_id(void)
185 {
186     X509 *x = NULL;
187     int ret = 0;
188     ASN1_OCTET_STRING *v = NULL, *v2 = NULL;
189     char *distid = "this is an ID";
190
191     x = load_cert_from_file(bad_f);
192     if (x == NULL)
193         goto err;
194
195     v = ASN1_OCTET_STRING_new();
196     if (v == NULL)
197         goto err;
198
199     if (!ASN1_OCTET_STRING_set(v, (unsigned char *)distid,
200                                (int)strlen(distid))) {
201         ASN1_OCTET_STRING_free(v);
202         goto err;
203     }
204
205     X509_set0_distinguishing_id(x, v);
206
207     v2 = X509_get0_distinguishing_id(x);
208     if (!TEST_ptr(v2)
209             || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0))
210         goto err;
211
212     ret = 1;
213  err:
214     X509_free(x);
215     return ret;
216 }
217
218 static int test_req_distinguishing_id(void)
219 {
220     X509_REQ *x = NULL;
221     BIO *bio = NULL;
222     int ret = 0;
223     ASN1_OCTET_STRING *v = NULL, *v2 = NULL;
224     char *distid = "this is an ID";
225
226     bio = BIO_new_file(req_f, "r");
227     if (bio == NULL)
228         goto err;
229
230     x = PEM_read_bio_X509_REQ(bio, NULL, 0, NULL);
231     if (x == NULL)
232         goto err;
233
234     v = ASN1_OCTET_STRING_new();
235     if (v == NULL)
236         goto err;
237
238     if (!ASN1_OCTET_STRING_set(v, (unsigned char *)distid,
239                                (int)strlen(distid))) {
240         ASN1_OCTET_STRING_free(v);
241         goto err;
242     }
243
244     X509_REQ_set0_distinguishing_id(x, v);
245
246     v2 = X509_REQ_get0_distinguishing_id(x);
247     if (!TEST_ptr(v2)
248             || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0))
249         goto err;
250
251     ret = 1;
252  err:
253     X509_REQ_free(x);
254     BIO_free(bio);
255     return ret;
256 }
257
258 static int test_self_signed(const char *filename, int expected)
259 {
260     X509 *cert;
261     int ret;
262
263     cert = load_cert_from_file(filename); /* may result in NULL */
264     ret = TEST_int_eq(X509_self_signed(cert, 1), expected);
265     X509_free(cert);
266     return ret;
267 }
268
269 static int test_self_signed_good(void)
270 {
271     return test_self_signed(root_f, 1);
272 }
273
274 static int test_self_signed_bad(void)
275 {
276     return test_self_signed(bad_f, 0);
277 }
278
279 static int test_self_signed_error(void)
280 {
281     return test_self_signed("nonexistent file name", -1);
282 }
283
284 int setup_tests(void)
285 {
286     if (!test_skip_common_options()) {
287         TEST_error("Error parsing test options\n");
288         return 0;
289     }
290
291     if (!TEST_ptr(root_f = test_get_argument(0))
292             || !TEST_ptr(roots_f = test_get_argument(1))
293             || !TEST_ptr(untrusted_f = test_get_argument(2))
294             || !TEST_ptr(bad_f = test_get_argument(3))
295             || !TEST_ptr(req_f = test_get_argument(4)))
296         return 0;
297
298     ADD_TEST(test_alt_chains_cert_forgery);
299     ADD_TEST(test_store_ctx);
300     ADD_TEST(test_distinguishing_id);
301     ADD_TEST(test_req_distinguishing_id);
302     ADD_TEST(test_self_signed_good);
303     ADD_TEST(test_self_signed_bad);
304     ADD_TEST(test_self_signed_error);
305     return 1;
306 }