Disallow Ed448 signature malleability
[openssl.git] / test / verify_extra_test.c
1 /*
2  * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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 <openssl/crypto.h>
12 #include <openssl/bio.h>
13 #include <openssl/x509.h>
14 #include <openssl/pem.h>
15 #include <openssl/err.h>
16 #include "testutil.h"
17
18 static const char *roots_f;
19 static const char *untrusted_f;
20 static const char *bad_f;
21
22 static STACK_OF(X509) *load_certs_from_file(const char *filename)
23 {
24     STACK_OF(X509) *certs;
25     BIO *bio;
26     X509 *x;
27
28     bio = BIO_new_file(filename, "r");
29
30     if (bio == NULL) {
31         return NULL;
32     }
33
34     certs = sk_X509_new_null();
35     if (certs == NULL) {
36         BIO_free(bio);
37         return NULL;
38     }
39
40     ERR_set_mark();
41     do {
42         x = PEM_read_bio_X509(bio, NULL, 0, NULL);
43         if (x != NULL && !sk_X509_push(certs, x)) {
44             sk_X509_pop_free(certs, X509_free);
45             BIO_free(bio);
46             return NULL;
47         } else if (x == NULL) {
48             /*
49              * We probably just ran out of certs, so ignore any errors
50              * generated
51              */
52             ERR_pop_to_mark();
53         }
54     } while (x != NULL);
55
56     BIO_free(bio);
57
58     return certs;
59 }
60
61 /*
62  * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery)
63  *
64  * Chain is as follows:
65  *
66  * rootCA (self-signed)
67  *   |
68  * interCA
69  *   |
70  * subinterCA       subinterCA (self-signed)
71  *   |                   |
72  * leaf ------------------
73  *   |
74  * bad
75  *
76  * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE
77  * leaf and bad have CA=FALSE
78  *
79  * subinterCA and subinterCA (ss) have the same subject name and keys
80  *
81  * interCA (but not rootCA) and subinterCA (ss) are in the trusted store
82  * (roots.pem)
83  * leaf and subinterCA are in the untrusted list (untrusted.pem)
84  * bad is the certificate being verified (bad.pem)
85  *
86  * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has
87  * CA=FALSE, and will therefore incorrectly verify bad
88  *
89  */
90 static int test_alt_chains_cert_forgery(void)
91 {
92     int ret = 0;
93     int i;
94     X509 *x = NULL;
95     STACK_OF(X509) *untrusted = NULL;
96     BIO *bio = NULL;
97     X509_STORE_CTX *sctx = NULL;
98     X509_STORE *store = NULL;
99     X509_LOOKUP *lookup = NULL;
100
101     store = X509_STORE_new();
102     if (store == NULL)
103         goto err;
104
105     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
106     if (lookup == NULL)
107         goto err;
108     if (!X509_LOOKUP_load_file(lookup, roots_f, X509_FILETYPE_PEM))
109         goto err;
110
111     untrusted = load_certs_from_file(untrusted_f);
112
113     if ((bio = BIO_new_file(bad_f, "r")) == NULL)
114         goto err;
115
116     if ((x = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL)
117         goto err;
118
119     sctx = X509_STORE_CTX_new();
120     if (sctx == NULL)
121         goto err;
122
123     if (!X509_STORE_CTX_init(sctx, store, x, untrusted))
124         goto err;
125
126     i = X509_verify_cert(sctx);
127
128     if (i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) {
129         /* This is the result we were expecting: Test passed */
130         ret = 1;
131     }
132  err:
133     X509_STORE_CTX_free(sctx);
134     X509_free(x);
135     BIO_free(bio);
136     sk_X509_pop_free(untrusted, X509_free);
137     X509_STORE_free(store);
138     return ret;
139 }
140
141 static int test_store_ctx(void)
142 {
143     X509_STORE_CTX *sctx = NULL;
144     X509 *x = NULL;
145     BIO *bio = NULL;
146     int testresult = 0, ret;
147
148     bio = BIO_new_file(bad_f, "r");
149     if (bio == NULL)
150         goto err;
151
152     x = PEM_read_bio_X509(bio, NULL, 0, NULL);
153     if (x == NULL)
154         goto err;
155
156     sctx = X509_STORE_CTX_new();
157     if (sctx == NULL)
158         goto err;
159
160     if (!X509_STORE_CTX_init(sctx, NULL, x, NULL))
161         goto err;
162
163     /* Verifying a cert where we have no trusted certs should fail */
164     ret = X509_verify_cert(sctx);
165
166     if (ret == 0) {
167         /* This is the result we were expecting: Test passed */
168         testresult = 1;
169     }
170
171  err:
172     X509_STORE_CTX_free(sctx);
173     X509_free(x);
174     BIO_free(bio);
175     return testresult;
176 }
177
178 int setup_tests(void)
179 {
180     if (!TEST_ptr(roots_f = test_get_argument(0))
181             || !TEST_ptr(untrusted_f = test_get_argument(1))
182             || !TEST_ptr(bad_f = test_get_argument(2))) {
183         TEST_error("usage: verify_extra_test roots.pem untrusted.pem bad.pem\n");
184         return 0;
185     }
186
187     ADD_TEST(test_alt_chains_cert_forgery);
188     ADD_TEST(test_store_ctx);
189     return 1;
190 }