/* * Written by Matt Caswell for the OpenSSL project. */ /* ==================================================================== * Copyright (c) 1998-2015 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ #include #include #include #include #include #include static STACK_OF(X509) *load_certs_from_file(const char *filename) { STACK_OF(X509) *certs; BIO *bio; X509 *x; bio = BIO_new_file(filename, "r"); if (bio == NULL) { return NULL; } certs = sk_X509_new_null(); if (certs == NULL) { BIO_free(bio); return NULL; } ERR_set_mark(); do { x = PEM_read_bio_X509(bio, NULL, 0, NULL); if (x != NULL && !sk_X509_push(certs, x)) { sk_X509_pop_free(certs, X509_free); BIO_free(bio); return NULL; } else if (x == NULL) { /* * We probably just ran out of certs, so ignore any errors * generated */ ERR_pop_to_mark(); } } while (x != NULL); BIO_free(bio); return certs; } /* * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery) * * Chain is as follows: * * rootCA (self-signed) * | * interCA * | * subinterCA subinterCA (self-signed) * | | * leaf ------------------ * | * bad * * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE * leaf and bad have CA=FALSE * * subinterCA and subinterCA (ss) have the same subject name and keys * * interCA (but not rootCA) and subinterCA (ss) are in the trusted store * (roots.pem) * leaf and subinterCA are in the untrusted list (untrusted.pem) * bad is the certificate being verified (bad.pem) * * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has * CA=FALSE, and will therefore incorrectly verify bad * */ static int test_alt_chains_cert_forgery(void) { int ret = 0; int i; X509 *x = NULL; STACK_OF(X509) *untrusted = NULL; BIO *bio = NULL; X509_STORE_CTX *sctx = NULL; X509_STORE *store = NULL; X509_LOOKUP *lookup = NULL; store = X509_STORE_new(); if (store == NULL) goto err; lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto err; if(!X509_LOOKUP_load_file(lookup, "certs/roots.pem", X509_FILETYPE_PEM)) goto err; untrusted = load_certs_from_file("certs/untrusted.pem"); if ((bio = BIO_new_file("certs/bad.pem", "r")) == NULL) goto err; if((x = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL) goto err; sctx = X509_STORE_CTX_new(); if (sctx == NULL) goto err; if (!X509_STORE_CTX_init(sctx, store, x, untrusted)) goto err; i = X509_verify_cert(sctx); if(i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) { /* This is the result we were expecting: Test passed */ ret = 1; } err: X509_STORE_CTX_free(sctx); X509_free(x); BIO_free(bio); sk_X509_pop_free(untrusted, X509_free); X509_STORE_free(store); if (ret != 1) ERR_print_errors_fp(stderr); return ret; } int main(void) { CRYPTO_malloc_debug_init(); CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); ERR_load_crypto_strings(); OpenSSL_add_all_digests(); if (!test_alt_chains_cert_forgery()) { fprintf(stderr, "Test alt chains cert forgery failed\n"); return 1; } EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); ERR_free_strings(); CRYPTO_mem_leaks_fp(stderr); printf("PASS\n"); return 0; }