1285327Sjkim/* 2285327Sjkim * Written by Matt Caswell for the OpenSSL project. 3285327Sjkim */ 4285327Sjkim/* ==================================================================== 5285327Sjkim * Copyright (c) 1998-2015 The OpenSSL Project. All rights reserved. 6285327Sjkim * 7285327Sjkim * Redistribution and use in source and binary forms, with or without 8285327Sjkim * modification, are permitted provided that the following conditions 9285327Sjkim * are met: 10285327Sjkim * 11285327Sjkim * 1. Redistributions of source code must retain the above copyright 12285327Sjkim * notice, this list of conditions and the following disclaimer. 13285327Sjkim * 14285327Sjkim * 2. Redistributions in binary form must reproduce the above copyright 15285327Sjkim * notice, this list of conditions and the following disclaimer in 16285327Sjkim * the documentation and/or other materials provided with the 17285327Sjkim * distribution. 18285327Sjkim * 19285327Sjkim * 3. All advertising materials mentioning features or use of this 20285327Sjkim * software must display the following acknowledgment: 21285327Sjkim * "This product includes software developed by the OpenSSL Project 22285327Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 23285327Sjkim * 24285327Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25285327Sjkim * endorse or promote products derived from this software without 26285327Sjkim * prior written permission. For written permission, please contact 27285327Sjkim * openssl-core@openssl.org. 28285327Sjkim * 29285327Sjkim * 5. Products derived from this software may not be called "OpenSSL" 30285327Sjkim * nor may "OpenSSL" appear in their names without prior written 31285327Sjkim * permission of the OpenSSL Project. 32285327Sjkim * 33285327Sjkim * 6. Redistributions of any form whatsoever must retain the following 34285327Sjkim * acknowledgment: 35285327Sjkim * "This product includes software developed by the OpenSSL Project 36285327Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 37285327Sjkim * 38285327Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39285327Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40285327Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41285327Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42285327Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43285327Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44285327Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45285327Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46285327Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47285327Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48285327Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49285327Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 50285327Sjkim * ==================================================================== 51285327Sjkim * 52285327Sjkim * This product includes cryptographic software written by Eric Young 53285327Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 54285327Sjkim * Hudson (tjh@cryptsoft.com). 55285327Sjkim * 56285327Sjkim */ 57285327Sjkim 58285327Sjkim#include <stdio.h> 59285327Sjkim#include <openssl/crypto.h> 60285327Sjkim#include <openssl/bio.h> 61285327Sjkim#include <openssl/x509.h> 62285327Sjkim#include <openssl/pem.h> 63285327Sjkim#include <openssl/err.h> 64285327Sjkim 65285327Sjkimstatic STACK_OF(X509) *load_certs_from_file(const char *filename) 66285327Sjkim{ 67285327Sjkim STACK_OF(X509) *certs; 68285327Sjkim BIO *bio; 69285327Sjkim X509 *x; 70285327Sjkim 71285327Sjkim bio = BIO_new_file(filename, "r"); 72285327Sjkim 73285327Sjkim if (bio == NULL) { 74285327Sjkim return NULL; 75285327Sjkim } 76285327Sjkim 77285327Sjkim certs = sk_X509_new_null(); 78285327Sjkim if (certs == NULL) { 79285327Sjkim BIO_free(bio); 80285327Sjkim return NULL; 81285327Sjkim } 82285327Sjkim 83285327Sjkim ERR_set_mark(); 84285327Sjkim do { 85285327Sjkim x = PEM_read_bio_X509(bio, NULL, 0, NULL); 86285327Sjkim if (x != NULL && !sk_X509_push(certs, x)) { 87285327Sjkim sk_X509_pop_free(certs, X509_free); 88285327Sjkim BIO_free(bio); 89285327Sjkim return NULL; 90285327Sjkim } else if (x == NULL) { 91285327Sjkim /* 92285327Sjkim * We probably just ran out of certs, so ignore any errors 93285327Sjkim * generated 94285327Sjkim */ 95285327Sjkim ERR_pop_to_mark(); 96285327Sjkim } 97285327Sjkim } while (x != NULL); 98285327Sjkim 99285327Sjkim BIO_free(bio); 100285327Sjkim 101285327Sjkim return certs; 102285327Sjkim} 103285327Sjkim 104285327Sjkim/* 105285327Sjkim * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery) 106285327Sjkim * 107285327Sjkim * Chain is as follows: 108285327Sjkim * 109285327Sjkim * rootCA (self-signed) 110285327Sjkim * | 111285327Sjkim * interCA 112285327Sjkim * | 113285327Sjkim * subinterCA subinterCA (self-signed) 114285327Sjkim * | | 115285327Sjkim * leaf ------------------ 116285327Sjkim * | 117285327Sjkim * bad 118285327Sjkim * 119285327Sjkim * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE 120285327Sjkim * leaf and bad have CA=FALSE 121285327Sjkim * 122285327Sjkim * subinterCA and subinterCA (ss) have the same subject name and keys 123285327Sjkim * 124285327Sjkim * interCA (but not rootCA) and subinterCA (ss) are in the trusted store 125285327Sjkim * (roots.pem) 126285327Sjkim * leaf and subinterCA are in the untrusted list (untrusted.pem) 127285327Sjkim * bad is the certificate being verified (bad.pem) 128285327Sjkim * 129285327Sjkim * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has 130285327Sjkim * CA=FALSE, and will therefore incorrectly verify bad 131285327Sjkim * 132285327Sjkim */ 133285327Sjkimstatic int test_alt_chains_cert_forgery(void) 134285327Sjkim{ 135285327Sjkim int ret = 0; 136285327Sjkim int i; 137285327Sjkim X509 *x = NULL; 138285327Sjkim STACK_OF(X509) *untrusted = NULL; 139285327Sjkim BIO *bio = NULL; 140285327Sjkim X509_STORE_CTX *sctx = NULL; 141285327Sjkim X509_STORE *store = NULL; 142285327Sjkim X509_LOOKUP *lookup = NULL; 143285327Sjkim 144285327Sjkim store = X509_STORE_new(); 145285327Sjkim if (store == NULL) 146285327Sjkim goto err; 147285327Sjkim 148285327Sjkim lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 149285327Sjkim if (lookup == NULL) 150285327Sjkim goto err; 151285327Sjkim if(!X509_LOOKUP_load_file(lookup, "certs/roots.pem", X509_FILETYPE_PEM)) 152285327Sjkim goto err; 153285327Sjkim 154285327Sjkim untrusted = load_certs_from_file("certs/untrusted.pem"); 155285327Sjkim 156285327Sjkim if ((bio = BIO_new_file("certs/bad.pem", "r")) == NULL) 157285327Sjkim goto err; 158285327Sjkim 159285327Sjkim if((x = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL) 160285327Sjkim goto err; 161285327Sjkim 162285327Sjkim sctx = X509_STORE_CTX_new(); 163285327Sjkim if (sctx == NULL) 164285327Sjkim goto err; 165285327Sjkim 166285327Sjkim if (!X509_STORE_CTX_init(sctx, store, x, untrusted)) 167285327Sjkim goto err; 168285327Sjkim 169285327Sjkim i = X509_verify_cert(sctx); 170285327Sjkim 171285327Sjkim if(i == 0 && X509_STORE_CTX_get_error(sctx) 172285327Sjkim == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) { 173285327Sjkim /* This is the result we were expecting: Test passed */ 174285327Sjkim ret = 1; 175285327Sjkim } 176285327Sjkim err: 177285327Sjkim X509_STORE_CTX_free(sctx); 178285327Sjkim X509_free(x); 179285327Sjkim BIO_free(bio); 180285327Sjkim sk_X509_pop_free(untrusted, X509_free); 181285327Sjkim X509_STORE_free(store); 182285327Sjkim if (ret != 1) 183285327Sjkim ERR_print_errors_fp(stderr); 184285327Sjkim return ret; 185285327Sjkim} 186285327Sjkim 187285327Sjkimint main(void) 188285327Sjkim{ 189285327Sjkim CRYPTO_malloc_debug_init(); 190285327Sjkim CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); 191285327Sjkim CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 192285327Sjkim 193285327Sjkim ERR_load_crypto_strings(); 194285327Sjkim OpenSSL_add_all_digests(); 195285327Sjkim 196285327Sjkim if (!test_alt_chains_cert_forgery()) { 197285327Sjkim fprintf(stderr, "Test alt chains cert forgery failed\n"); 198285327Sjkim return 1; 199285327Sjkim } 200285327Sjkim 201285327Sjkim EVP_cleanup(); 202285327Sjkim CRYPTO_cleanup_all_ex_data(); 203285327Sjkim ERR_remove_thread_state(NULL); 204285327Sjkim ERR_free_strings(); 205285327Sjkim CRYPTO_mem_leaks_fp(stderr); 206285327Sjkim 207285327Sjkim printf("PASS\n"); 208285327Sjkim return 0; 209285327Sjkim} 210