ssl_cert.c revision 162911
133965Sjdp/*! \file ssl/ssl_cert.c */ 289857Sobrien/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3130561Sobrien * All rights reserved. 460484Sobrien * 533965Sjdp * This package is an SSL implementation written 6104834Sobrien * by Eric Young (eay@cryptsoft.com). 733965Sjdp * The implementation was written so as to conform with Netscapes SSL. 8104834Sobrien * 9104834Sobrien * This library is free for commercial and non-commercial use as long as 10104834Sobrien * the following conditions are aheared to. The following conditions 11104834Sobrien * apply to all code found in this distribution, be it the RC4, RSA, 1233965Sjdp * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13104834Sobrien * included with this distribution is covered by the same copyright terms 14104834Sobrien * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15104834Sobrien * 16104834Sobrien * Copyright remains Eric Young's, and as such any Copyright notices in 1733965Sjdp * the code are not to be removed. 18104834Sobrien * If this package is used in a product, Eric Young should be given attribution 19104834Sobrien * as the author of the parts of the library used. 20104834Sobrien * This can be in the form of a textual message at program startup or 2133965Sjdp * in documentation (online or textual) provided with the package. 2233965Sjdp * 2333965Sjdp * Redistribution and use in source and binary forms, with or without 2433965Sjdp * modification, are permitted provided that the following conditions 2533965Sjdp * are met: 2633965Sjdp * 1. Redistributions of source code must retain the copyright 27130561Sobrien * notice, this list of conditions and the following disclaimer. 28104834Sobrien * 2. Redistributions in binary form must reproduce the above copyright 2933965Sjdp * notice, this list of conditions and the following disclaimer in the 3033965Sjdp * documentation and/or other materials provided with the distribution. 3133965Sjdp * 3. All advertising materials mentioning features or use of this software 3233965Sjdp * must display the following acknowledgement: 3333965Sjdp * "This product includes cryptographic software written by 3433965Sjdp * Eric Young (eay@cryptsoft.com)" 3533965Sjdp * The word 'cryptographic' can be left out if the rouines from the library 3661843Sobrien * being used are not cryptographic related :-). 37104834Sobrien * 4. If you include any Windows specific code (or a derivative thereof) from 3833965Sjdp * the apps directory (application code) you must include an acknowledgement: 3933965Sjdp * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4033965Sjdp * 4133965Sjdp * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4233965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4333965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4433965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4533965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4660484Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4760484Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4860484Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4960484Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5060484Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5160484Sobrien * SUCH DAMAGE. 5233965Sjdp * 5333965Sjdp * The licence and distribution terms for any publically available version or 5433965Sjdp * derivative of this code cannot be changed. i.e. this code cannot simply be 5533965Sjdp * copied and put under another distribution licence 5633965Sjdp * [including the GNU Public Licence.] 57130561Sobrien */ 5833965Sjdp/* ==================================================================== 5933965Sjdp * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 6033965Sjdp * 61130561Sobrien * Redistribution and use in source and binary forms, with or without 62130561Sobrien * modification, are permitted provided that the following conditions 63130561Sobrien * are met: 64130561Sobrien * 65130561Sobrien * 1. Redistributions of source code must retain the above copyright 66130561Sobrien * notice, this list of conditions and the following disclaimer. 6733965Sjdp * 6833965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 69130561Sobrien * notice, this list of conditions and the following disclaimer in 70130561Sobrien * the documentation and/or other materials provided with the 7133965Sjdp * distribution. 7233965Sjdp * 73130561Sobrien * 3. All advertising materials mentioning features or use of this 74130561Sobrien * software must display the following acknowledgment: 75130561Sobrien * "This product includes software developed by the OpenSSL Project 76130561Sobrien * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77130561Sobrien * 78130561Sobrien * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79130561Sobrien * endorse or promote products derived from this software without 80130561Sobrien * prior written permission. For written permission, please contact 8133965Sjdp * openssl-core@openssl.org. 8233965Sjdp * 8333965Sjdp * 5. Products derived from this software may not be called "OpenSSL" 8433965Sjdp * nor may "OpenSSL" appear in their names without prior written 8533965Sjdp * permission of the OpenSSL Project. 8633965Sjdp * 8733965Sjdp * 6. Redistributions of any form whatsoever must retain the following 8833965Sjdp * acknowledgment: 8933965Sjdp * "This product includes software developed by the OpenSSL Project 9033965Sjdp * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 9133965Sjdp * 9233965Sjdp * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 9333965Sjdp * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9433965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 9533965Sjdp * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 9633965Sjdp * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 9733965Sjdp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 9833965Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 9933965Sjdp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 10033965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 10133965Sjdp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10233965Sjdp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 10333965Sjdp * OF THE POSSIBILITY OF SUCH DAMAGE. 10433965Sjdp * ==================================================================== 10533965Sjdp * 106130561Sobrien * This product includes cryptographic software written by Eric Young 10733965Sjdp * (eay@cryptsoft.com). This product includes software written by Tim 10833965Sjdp * Hudson (tjh@cryptsoft.com). 10933965Sjdp * 11033965Sjdp */ 11133965Sjdp/* ==================================================================== 11233965Sjdp * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 11333965Sjdp * ECC cipher suite support in OpenSSL originally developed by 11433965Sjdp * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 11533965Sjdp */ 11633965Sjdp 11733965Sjdp#include <stdio.h> 11833965Sjdp 11933965Sjdp#include "e_os.h" 12033965Sjdp#ifndef NO_SYS_TYPES_H 12133965Sjdp# include <sys/types.h> 12233965Sjdp#endif 12333965Sjdp 12433965Sjdp#include "o_dir.h" 12533965Sjdp#include <openssl/objects.h> 12633965Sjdp#include <openssl/bio.h> 127130561Sobrien#include <openssl/pem.h> 12833965Sjdp#include <openssl/x509v3.h> 129130561Sobrien#ifndef OPENSSL_NO_DH 13060484Sobrien#include <openssl/dh.h> 131130561Sobrien#endif 13260484Sobrien#include <openssl/bn.h> 13360484Sobrien#include "ssl_locl.h" 13433965Sjdp 135130561Sobrienint SSL_get_ex_data_X509_STORE_CTX_idx(void) 13633965Sjdp { 13760484Sobrien static volatile int ssl_x509_store_ctx_idx= -1; 13860484Sobrien int got_write_lock = 0; 13960484Sobrien 140130561Sobrien CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); 14160484Sobrien 14233965Sjdp if (ssl_x509_store_ctx_idx < 0) 14333965Sjdp { 14433965Sjdp CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); 145130561Sobrien CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); 14633965Sjdp got_write_lock = 1; 14733965Sjdp 14833965Sjdp if (ssl_x509_store_ctx_idx < 0) 14933965Sjdp { 15033965Sjdp ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( 15133965Sjdp 0,"SSL for verify callback",NULL,NULL,NULL); 15233965Sjdp } 15333965Sjdp } 15433965Sjdp 15533965Sjdp if (got_write_lock) 156130561Sobrien CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); 15733965Sjdp else 15833965Sjdp CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); 15960484Sobrien 16033965Sjdp return ssl_x509_store_ctx_idx; 16133965Sjdp } 16233965Sjdp 16333965SjdpCERT *ssl_cert_new(void) 16433965Sjdp { 16533965Sjdp CERT *ret; 16633965Sjdp 16733965Sjdp ret=(CERT *)OPENSSL_malloc(sizeof(CERT)); 16833965Sjdp if (ret == NULL) 16933965Sjdp { 17060484Sobrien SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE); 17133965Sjdp return(NULL); 17233965Sjdp } 17333965Sjdp memset(ret,0,sizeof(CERT)); 17433965Sjdp 17533965Sjdp ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); 17633965Sjdp ret->references=1; 17733965Sjdp 17833965Sjdp return(ret); 179130561Sobrien } 18033965Sjdp 18160484SobrienCERT *ssl_cert_dup(CERT *cert) 18233965Sjdp { 18333965Sjdp CERT *ret; 18433965Sjdp int i; 18533965Sjdp 18633965Sjdp ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); 18733965Sjdp if (ret == NULL) 18833965Sjdp { 18933965Sjdp SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); 19033965Sjdp return(NULL); 19133965Sjdp } 19233965Sjdp 19361843Sobrien memset(ret, 0, sizeof(CERT)); 19433965Sjdp 19560484Sobrien ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; 19660484Sobrien /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), 197104834Sobrien * if you find that more readable */ 19860484Sobrien 19960484Sobrien ret->valid = cert->valid; 20060484Sobrien ret->mask = cert->mask; 20160484Sobrien ret->export_mask = cert->export_mask; 20260484Sobrien 20360484Sobrien#ifndef OPENSSL_NO_RSA 204130561Sobrien if (cert->rsa_tmp != NULL) 20533965Sjdp { 20633965Sjdp RSA_up_ref(cert->rsa_tmp); 20733965Sjdp ret->rsa_tmp = cert->rsa_tmp; 20833965Sjdp } 20960484Sobrien ret->rsa_tmp_cb = cert->rsa_tmp_cb; 21060484Sobrien#endif 21133965Sjdp 21233965Sjdp#ifndef OPENSSL_NO_DH 21333965Sjdp if (cert->dh_tmp != NULL) 214130561Sobrien { 21533965Sjdp ret->dh_tmp = DHparams_dup(cert->dh_tmp); 21633965Sjdp if (ret->dh_tmp == NULL) 217130561Sobrien { 21833965Sjdp SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); 21933965Sjdp goto err; 22033965Sjdp } 22133965Sjdp if (cert->dh_tmp->priv_key) 222104834Sobrien { 22333965Sjdp BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); 22460484Sobrien if (!b) 22560484Sobrien { 226104834Sobrien SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); 22760484Sobrien goto err; 22860484Sobrien } 22960484Sobrien ret->dh_tmp->priv_key = b; 23060484Sobrien } 23160484Sobrien if (cert->dh_tmp->pub_key) 23260484Sobrien { 23360484Sobrien BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); 23460484Sobrien if (!b) 23560484Sobrien { 23660484Sobrien SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); 23760484Sobrien goto err; 23860484Sobrien } 23960484Sobrien ret->dh_tmp->pub_key = b; 24060484Sobrien } 24160484Sobrien } 24260484Sobrien ret->dh_tmp_cb = cert->dh_tmp_cb; 24360484Sobrien#endif 24460484Sobrien 24560484Sobrien#ifndef OPENSSL_NO_ECDH 24660484Sobrien if (cert->ecdh_tmp) 24760484Sobrien { 24860484Sobrien ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); 24960484Sobrien if (ret->ecdh_tmp == NULL) 25060484Sobrien { 25160484Sobrien SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB); 252104834Sobrien goto err; 253104834Sobrien } 25460484Sobrien } 25533965Sjdp ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; 25689857Sobrien#endif 257104834Sobrien 25889857Sobrien for (i = 0; i < SSL_PKEY_NUM; i++) 25989857Sobrien { 26089857Sobrien if (cert->pkeys[i].x509 != NULL) 26189857Sobrien { 26289857Sobrien ret->pkeys[i].x509 = cert->pkeys[i].x509; 26389857Sobrien CRYPTO_add(&ret->pkeys[i].x509->references, 1, 26433965Sjdp CRYPTO_LOCK_X509); 26533965Sjdp } 26633965Sjdp 26733965Sjdp if (cert->pkeys[i].privatekey != NULL) 26860484Sobrien { 26933965Sjdp ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; 27033965Sjdp CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, 27133965Sjdp CRYPTO_LOCK_EVP_PKEY); 27233965Sjdp 27333965Sjdp switch(i) 27433965Sjdp { 27533965Sjdp /* If there was anything special to do for 27633965Sjdp * certain types of keys, we'd do it here. 277130561Sobrien * (Nothing at the moment, I think.) */ 27833965Sjdp 27933965Sjdp case SSL_PKEY_RSA_ENC: 28033965Sjdp case SSL_PKEY_RSA_SIGN: 28160484Sobrien /* We have an RSA key. */ 28260484Sobrien break; 28360484Sobrien 28433965Sjdp case SSL_PKEY_DSA_SIGN: 28561843Sobrien /* We have a DSA key. */ 28661843Sobrien break; 28761843Sobrien 28861843Sobrien case SSL_PKEY_DH_RSA: 28977298Sobrien case SSL_PKEY_DH_DSA: 29061843Sobrien /* We have a DH key. */ 29161843Sobrien break; 29277298Sobrien 29361843Sobrien case SSL_PKEY_ECC: 29461843Sobrien /* We have an ECC key */ 29533965Sjdp break; 29633965Sjdp 29733965Sjdp default: 29833965Sjdp /* Can't happen. */ 29933965Sjdp SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG); 30033965Sjdp } 30133965Sjdp } 30233965Sjdp } 30333965Sjdp 30433965Sjdp /* ret->extra_certs *should* exist, but currently the own certificate 30533965Sjdp * chain is held inside SSL_CTX */ 30633965Sjdp 30733965Sjdp ret->references=1; 30833965Sjdp 30933965Sjdp return(ret); 31033965Sjdp 31133965Sjdp#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) 31233965Sjdperr: 31333965Sjdp#endif 31433965Sjdp#ifndef OPENSSL_NO_RSA 31533965Sjdp if (ret->rsa_tmp != NULL) 31633965Sjdp RSA_free(ret->rsa_tmp); 31733965Sjdp#endif 31860484Sobrien#ifndef OPENSSL_NO_DH 31933965Sjdp if (ret->dh_tmp != NULL) 32033965Sjdp DH_free(ret->dh_tmp); 32133965Sjdp#endif 32233965Sjdp#ifndef OPENSSL_NO_ECDH 323130561Sobrien if (ret->ecdh_tmp != NULL) 32433965Sjdp EC_KEY_free(ret->ecdh_tmp); 32533965Sjdp#endif 32633965Sjdp 327130561Sobrien for (i = 0; i < SSL_PKEY_NUM; i++) 328130561Sobrien { 32933965Sjdp if (ret->pkeys[i].x509 != NULL) 33033965Sjdp X509_free(ret->pkeys[i].x509); 33133965Sjdp if (ret->pkeys[i].privatekey != NULL) 33233965Sjdp EVP_PKEY_free(ret->pkeys[i].privatekey); 33333965Sjdp } 33433965Sjdp 33533965Sjdp return NULL; 33633965Sjdp } 33733965Sjdp 338130561Sobrien 33989857Sobrienvoid ssl_cert_free(CERT *c) 34033965Sjdp { 341130561Sobrien int i; 34233965Sjdp 34333965Sjdp if(c == NULL) 34433965Sjdp return; 34533965Sjdp 34633965Sjdp i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); 34733965Sjdp#ifdef REF_PRINT 34833965Sjdp REF_PRINT("CERT",c); 34933965Sjdp#endif 35033965Sjdp if (i > 0) return; 35133965Sjdp#ifdef REF_CHECK 35260484Sobrien if (i < 0) 35333965Sjdp { 35433965Sjdp fprintf(stderr,"ssl_cert_free, bad reference count\n"); 355104834Sobrien abort(); /* ok */ 356130561Sobrien } 35733965Sjdp#endif 35860484Sobrien 35960484Sobrien#ifndef OPENSSL_NO_RSA 36060484Sobrien if (c->rsa_tmp) RSA_free(c->rsa_tmp); 36189857Sobrien#endif 36289857Sobrien#ifndef OPENSSL_NO_DH 36389857Sobrien if (c->dh_tmp) DH_free(c->dh_tmp); 36460484Sobrien#endif 36560484Sobrien#ifndef OPENSSL_NO_ECDH 36660484Sobrien if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp); 36733965Sjdp#endif 36833965Sjdp 36933965Sjdp for (i=0; i<SSL_PKEY_NUM; i++) 37033965Sjdp { 37133965Sjdp if (c->pkeys[i].x509 != NULL) 37233965Sjdp X509_free(c->pkeys[i].x509); 37333965Sjdp if (c->pkeys[i].privatekey != NULL) 37433965Sjdp EVP_PKEY_free(c->pkeys[i].privatekey); 37561843Sobrien#if 0 376104834Sobrien if (c->pkeys[i].publickey != NULL) 377104834Sobrien EVP_PKEY_free(c->pkeys[i].publickey); 378104834Sobrien#endif 379104834Sobrien } 380104834Sobrien OPENSSL_free(c); 381104834Sobrien } 382104834Sobrien 383104834Sobrienint ssl_cert_inst(CERT **o) 38461843Sobrien { 38533965Sjdp /* Create a CERT if there isn't already one 38633965Sjdp * (which cannot really happen, as it is initially created in 38733965Sjdp * SSL_CTX_new; but the earlier code usually allows for that one 38833965Sjdp * being non-existant, so we follow that behaviour, as it might 38933965Sjdp * turn out that there actually is a reason for it -- but I'm 39061843Sobrien * not sure that *all* of the existing code could cope with 39133965Sjdp * s->cert being NULL, otherwise we could do without the 39233965Sjdp * initialization in SSL_CTX_new). 39333965Sjdp */ 39433965Sjdp 39533965Sjdp if (o == NULL) 39633965Sjdp { 39733965Sjdp SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER); 39833965Sjdp return(0); 39933965Sjdp } 40033965Sjdp if (*o == NULL) 40133965Sjdp { 40233965Sjdp if ((*o = ssl_cert_new()) == NULL) 40333965Sjdp { 40433965Sjdp SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE); 40533965Sjdp return(0); 40633965Sjdp } 40733965Sjdp } 40833965Sjdp return(1); 40933965Sjdp } 41033965Sjdp 41133965Sjdp 41233965SjdpSESS_CERT *ssl_sess_cert_new(void) 41333965Sjdp { 41433965Sjdp SESS_CERT *ret; 41533965Sjdp 41633965Sjdp ret = OPENSSL_malloc(sizeof *ret); 41733965Sjdp if (ret == NULL) 418104834Sobrien { 419104834Sobrien SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE); 420104834Sobrien return NULL; 421104834Sobrien } 422104834Sobrien 42377298Sobrien memset(ret, 0 ,sizeof *ret); 42433965Sjdp ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); 42533965Sjdp ret->references = 1; 426130561Sobrien 42733965Sjdp return ret; 42889857Sobrien } 42989857Sobrien 43089857Sobrienvoid ssl_sess_cert_free(SESS_CERT *sc) 43189857Sobrien { 43233965Sjdp int i; 43333965Sjdp 43433965Sjdp if (sc == NULL) 43533965Sjdp return; 43633965Sjdp 43733965Sjdp i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); 43833965Sjdp#ifdef REF_PRINT 43933965Sjdp REF_PRINT("SESS_CERT", sc); 44033965Sjdp#endif 441130561Sobrien if (i > 0) 44233965Sjdp return; 44333965Sjdp#ifdef REF_CHECK 44433965Sjdp if (i < 0) 44533965Sjdp { 44633965Sjdp fprintf(stderr,"ssl_sess_cert_free, bad reference count\n"); 44733965Sjdp abort(); /* ok */ 44833965Sjdp } 44933965Sjdp#endif 45033965Sjdp 45133965Sjdp /* i == 0 */ 45233965Sjdp if (sc->cert_chain != NULL) 45333965Sjdp sk_X509_pop_free(sc->cert_chain, X509_free); 45433965Sjdp for (i = 0; i < SSL_PKEY_NUM; i++) 45533965Sjdp { 45633965Sjdp if (sc->peer_pkeys[i].x509 != NULL) 45733965Sjdp X509_free(sc->peer_pkeys[i].x509); 45833965Sjdp#if 0 /* We don't have the peer's private key. These lines are just 45933965Sjdp * here as a reminder that we're still using a not-quite-appropriate 46033965Sjdp * data structure. */ 46133965Sjdp if (sc->peer_pkeys[i].privatekey != NULL) 46233965Sjdp EVP_PKEY_free(sc->peer_pkeys[i].privatekey); 463130561Sobrien#endif 464130561Sobrien } 46533965Sjdp 46633965Sjdp#ifndef OPENSSL_NO_RSA 467130561Sobrien if (sc->peer_rsa_tmp != NULL) 468130561Sobrien RSA_free(sc->peer_rsa_tmp); 469130561Sobrien#endif 470130561Sobrien#ifndef OPENSSL_NO_DH 471130561Sobrien if (sc->peer_dh_tmp != NULL) 472130561Sobrien DH_free(sc->peer_dh_tmp); 47333965Sjdp#endif 474130561Sobrien#ifndef OPENSSL_NO_ECDH 47533965Sjdp if (sc->peer_ecdh_tmp != NULL) 476130561Sobrien EC_KEY_free(sc->peer_ecdh_tmp); 47733965Sjdp#endif 47833965Sjdp 47933965Sjdp OPENSSL_free(sc); 48033965Sjdp } 48133965Sjdp 48233965Sjdpint ssl_set_peer_cert_type(SESS_CERT *sc,int type) 48333965Sjdp { 48433965Sjdp sc->peer_cert_type = type; 48533965Sjdp return(1); 48633965Sjdp } 487130561Sobrien 488130561Sobrienint ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) 489130561Sobrien { 490130561Sobrien X509 *x; 491130561Sobrien int i; 492130561Sobrien X509_STORE_CTX ctx; 493130561Sobrien 494130561Sobrien if ((sk == NULL) || (sk_X509_num(sk) == 0)) 495130561Sobrien return(0); 496130561Sobrien 497130561Sobrien x=sk_X509_value(sk,0); 498130561Sobrien if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) 499130561Sobrien { 500130561Sobrien SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); 501130561Sobrien return(0); 502130561Sobrien } 503130561Sobrien if (s->param) 504130561Sobrien X509_VERIFY_PARAM_inherit(X509_STORE_CTX_get0_param(&ctx), 505130561Sobrien s->param); 506130561Sobrien#if 0 507130561Sobrien if (SSL_get_verify_depth(s) >= 0) 508130561Sobrien X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); 509130561Sobrien#endif 510130561Sobrien X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); 511130561Sobrien 512130561Sobrien /* We need to inherit the verify parameters. These can be determined by 513130561Sobrien * the context: if its a server it will verify SSL client certificates 514130561Sobrien * or vice versa. 515130561Sobrien */ 516130561Sobrien 517130561Sobrien X509_STORE_CTX_set_default(&ctx, 51833965Sjdp s->server ? "ssl_client" : "ssl_server"); 519130561Sobrien 520130561Sobrien if (s->verify_callback) 521130561Sobrien X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); 522130561Sobrien 523130561Sobrien if (s->ctx->app_verify_callback != NULL) 524130561Sobrien#if 1 /* new with OpenSSL 0.9.7 */ 525130561Sobrien i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); 526130561Sobrien#else 527130561Sobrien i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ 528130561Sobrien#endif 529130561Sobrien else 530130561Sobrien { 531130561Sobrien#ifndef OPENSSL_NO_X509_VERIFY 532130561Sobrien i=X509_verify_cert(&ctx); 533130561Sobrien#else 534130561Sobrien i=0; 535130561Sobrien ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; 536130561Sobrien SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK); 537130561Sobrien#endif 538130561Sobrien } 539130561Sobrien 540130561Sobrien s->verify_result=ctx.error; 541130561Sobrien X509_STORE_CTX_cleanup(&ctx); 542130561Sobrien 543130561Sobrien return(i); 544130561Sobrien } 545130561Sobrien 546130561Sobrienstatic void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list) 547130561Sobrien { 548130561Sobrien if (*ca_list != NULL) 549130561Sobrien sk_X509_NAME_pop_free(*ca_list,X509_NAME_free); 550130561Sobrien 551130561Sobrien *ca_list=name_list; 552130561Sobrien } 553130561Sobrien 554130561SobrienSTACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) 555130561Sobrien { 556130561Sobrien int i; 557130561Sobrien STACK_OF(X509_NAME) *ret; 558130561Sobrien X509_NAME *name; 559130561Sobrien 560130561Sobrien ret=sk_X509_NAME_new_null(); 561130561Sobrien for (i=0; i<sk_X509_NAME_num(sk); i++) 562130561Sobrien { 563130561Sobrien name=X509_NAME_dup(sk_X509_NAME_value(sk,i)); 564130561Sobrien if ((name == NULL) || !sk_X509_NAME_push(ret,name)) 56533965Sjdp { 56633965Sjdp sk_X509_NAME_pop_free(ret,X509_NAME_free); 567130561Sobrien return(NULL); 568130561Sobrien } 569130561Sobrien } 570130561Sobrien return(ret); 571130561Sobrien } 572130561Sobrien 573130561Sobrienvoid SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list) 57433965Sjdp { 575130561Sobrien set_client_CA_list(&(s->client_CA),name_list); 57633965Sjdp } 57733965Sjdp 57833965Sjdpvoid SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list) 57933965Sjdp { 580130561Sobrien set_client_CA_list(&(ctx->client_CA),name_list); 581130561Sobrien } 58233965Sjdp 58333965SjdpSTACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) 58433965Sjdp { 58533965Sjdp return(ctx->client_CA); 58633965Sjdp } 58733965Sjdp 58833965SjdpSTACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) 58933965Sjdp { 59033965Sjdp if (s->type == SSL_ST_CONNECT) 59133965Sjdp { /* we are in the client */ 59233965Sjdp if (((s->version>>8) == SSL3_VERSION_MAJOR) && 59333965Sjdp (s->s3 != NULL)) 59433965Sjdp return(s->s3->tmp.ca_names); 59533965Sjdp else 59633965Sjdp return(NULL); 59733965Sjdp } 59833965Sjdp else 59933965Sjdp { 600130561Sobrien if (s->client_CA != NULL) 60133965Sjdp return(s->client_CA); 60233965Sjdp else 60333965Sjdp return(s->ctx->client_CA); 60433965Sjdp } 60560484Sobrien } 60633965Sjdp 60733965Sjdpstatic int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x) 60860484Sobrien { 60933965Sjdp X509_NAME *name; 61033965Sjdp 61133965Sjdp if (x == NULL) return(0); 61233965Sjdp if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL)) 613104834Sobrien return(0); 61460484Sobrien 615104834Sobrien if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) 61660484Sobrien return(0); 61760484Sobrien 618104834Sobrien if (!sk_X509_NAME_push(*sk,name)) 61960484Sobrien { 62060484Sobrien X509_NAME_free(name); 62160484Sobrien return(0); 62233965Sjdp } 62333965Sjdp return(1); 62433965Sjdp } 62560484Sobrien 62633965Sjdpint SSL_add_client_CA(SSL *ssl,X509 *x) 62733965Sjdp { 62833965Sjdp return(add_client_CA(&(ssl->client_CA),x)); 62933965Sjdp } 63033965Sjdp 63133965Sjdpint SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) 63233965Sjdp { 63333965Sjdp return(add_client_CA(&(ctx->client_CA),x)); 63433965Sjdp } 63533965Sjdp 63633965Sjdpstatic int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) 63733965Sjdp { 63833965Sjdp return(X509_NAME_cmp(*a,*b)); 63933965Sjdp } 64033965Sjdp 64133965Sjdp#ifndef OPENSSL_NO_STDIO 64233965Sjdp/*! 64333965Sjdp * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; 64433965Sjdp * it doesn't really have anything to do with clients (except that a common use 64533965Sjdp * for a stack of CAs is to send it to the client). Actually, it doesn't have 64633965Sjdp * much to do with CAs, either, since it will load any old cert. 64733965Sjdp * \param file the file containing one or more certs. 64833965Sjdp * \return a ::STACK containing the certs. 64933965Sjdp */ 65033965SjdpSTACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) 65133965Sjdp { 65233965Sjdp BIO *in; 65333965Sjdp X509 *x=NULL; 654104834Sobrien X509_NAME *xn=NULL; 65533965Sjdp STACK_OF(X509_NAME) *ret = NULL,*sk; 65633965Sjdp 65733965Sjdp sk=sk_X509_NAME_new(xname_cmp); 65833965Sjdp 65933965Sjdp in=BIO_new(BIO_s_file_internal()); 66033965Sjdp 66133965Sjdp if ((sk == NULL) || (in == NULL)) 66233965Sjdp { 66333965Sjdp SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE); 66433965Sjdp goto err; 66533965Sjdp } 66660484Sobrien 66733965Sjdp if (!BIO_read_filename(in,file)) 66833965Sjdp goto err; 66933965Sjdp 67060484Sobrien for (;;) 67133965Sjdp { 67233965Sjdp if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) 67333965Sjdp break; 67460484Sobrien if (ret == NULL) 67533965Sjdp { 67633965Sjdp ret = sk_X509_NAME_new_null(); 67733965Sjdp if (ret == NULL) 67833965Sjdp { 67933965Sjdp SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE); 68060484Sobrien goto err; 68160484Sobrien } 68233965Sjdp } 68333965Sjdp if ((xn=X509_get_subject_name(x)) == NULL) goto err; 68433965Sjdp /* check for duplicates */ 68533965Sjdp xn=X509_NAME_dup(xn); 68633965Sjdp if (xn == NULL) goto err; 68760484Sobrien if (sk_X509_NAME_find(sk,xn) >= 0) 68860484Sobrien X509_NAME_free(xn); 68933965Sjdp else 69033965Sjdp { 69133965Sjdp sk_X509_NAME_push(sk,xn); 69233965Sjdp sk_X509_NAME_push(ret,xn); 69333965Sjdp } 69433965Sjdp } 69560484Sobrien 69660484Sobrien if (0) 69733965Sjdp { 69833965Sjdperr: 69933965Sjdp if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); 70033965Sjdp ret=NULL; 70160484Sobrien } 70260484Sobrien if (sk != NULL) sk_X509_NAME_free(sk); 70333965Sjdp if (in != NULL) BIO_free(in); 70433965Sjdp if (x != NULL) X509_free(x); 70533965Sjdp if (ret != NULL) 70633965Sjdp ERR_clear_error(); 70733965Sjdp return(ret); 70833965Sjdp } 70933965Sjdp#endif 71033965Sjdp 71133965Sjdp/*! 71233965Sjdp * Add a file of certs to a stack. 713130561Sobrien * \param stack the stack to add to. 71433965Sjdp * \param file the file to add from. All certs in this file that are not 71533965Sjdp * already in the stack will be added. 71633965Sjdp * \return 1 for success, 0 for failure. Note that in the case of failure some 71733965Sjdp * certs may have been added to \c stack. 71833965Sjdp */ 71933965Sjdp 72033965Sjdpint SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, 72133965Sjdp const char *file) 72233965Sjdp { 72333965Sjdp BIO *in; 72433965Sjdp X509 *x=NULL; 72533965Sjdp X509_NAME *xn=NULL; 72633965Sjdp int ret=1; 72733965Sjdp int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); 72861843Sobrien 72933965Sjdp oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp); 73061843Sobrien 73161843Sobrien in=BIO_new(BIO_s_file_internal()); 73261843Sobrien 73361843Sobrien if (in == NULL) 73461843Sobrien { 73533965Sjdp SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE); 73661843Sobrien goto err; 73733965Sjdp } 73833965Sjdp 73933965Sjdp if (!BIO_read_filename(in,file)) 74033965Sjdp goto err; 74133965Sjdp 74233965Sjdp for (;;) 74333965Sjdp { 74433965Sjdp if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) 74533965Sjdp break; 74633965Sjdp if ((xn=X509_get_subject_name(x)) == NULL) goto err; 74733965Sjdp xn=X509_NAME_dup(xn); 74833965Sjdp if (xn == NULL) goto err; 74933965Sjdp if (sk_X509_NAME_find(stack,xn) >= 0) 75033965Sjdp X509_NAME_free(xn); 75133965Sjdp else 75233965Sjdp sk_X509_NAME_push(stack,xn); 75333965Sjdp } 75433965Sjdp 75533965Sjdp if (0) 75633965Sjdp { 75733965Sjdperr: 75833965Sjdp ret=0; 75933965Sjdp } 76033965Sjdp if(in != NULL) 76133965Sjdp BIO_free(in); 76233965Sjdp if(x != NULL) 76333965Sjdp X509_free(x); 76433965Sjdp 76533965Sjdp sk_X509_NAME_set_cmp_func(stack,oldcmp); 76633965Sjdp 76733965Sjdp return ret; 76833965Sjdp } 76933965Sjdp 770130561Sobrien/*! 771130561Sobrien * Add a directory of certs to a stack. 77260484Sobrien * \param stack the stack to append to. 77360484Sobrien * \param dir the directory to append from. All files in this directory will be 77460484Sobrien * examined as potential certs. Any that are acceptable to 77533965Sjdp * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be 77633965Sjdp * included. 77733965Sjdp * \return 1 for success, 0 for failure. Note that in the case of failure some 77833965Sjdp * certs may have been added to \c stack. 77933965Sjdp */ 78033965Sjdp 78133965Sjdpint SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, 78233965Sjdp const char *dir) 78333965Sjdp { 78433965Sjdp OPENSSL_DIR_CTX *d = NULL; 78533965Sjdp const char *filename; 78633965Sjdp int ret = 0; 78733965Sjdp 78833965Sjdp CRYPTO_w_lock(CRYPTO_LOCK_READDIR); 78933965Sjdp 79033965Sjdp /* Note that a side effect is that the CAs will be sorted by name */ 79133965Sjdp 79233965Sjdp while((filename = OPENSSL_DIR_read(&d, dir))) 79333965Sjdp { 79433965Sjdp char buf[1024]; 79533965Sjdp int r; 79633965Sjdp 79733965Sjdp if(strlen(dir)+strlen(filename)+2 > sizeof buf) 79833965Sjdp { 79933965Sjdp SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); 80033965Sjdp goto err; 80133965Sjdp } 80233965Sjdp 80333965Sjdp#ifdef OPENSSL_SYS_VMS 80433965Sjdp r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename); 80533965Sjdp#else 80633965Sjdp r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename); 80733965Sjdp#endif 80833965Sjdp if (r <= 0 || r >= (int)sizeof(buf)) 80933965Sjdp goto err; 81033965Sjdp if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) 81133965Sjdp goto err; 812130561Sobrien } 81333965Sjdp 81433965Sjdp if (errno) 81533965Sjdp { 81633965Sjdp SYSerr(SYS_F_OPENDIR, get_last_sys_error()); 81733965Sjdp ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); 81833965Sjdp SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); 81960484Sobrien goto err; 82060484Sobrien } 82133965Sjdp 82233965Sjdp ret = 1; 82377298Sobrien 824130561Sobrienerr: 82533965Sjdp if (d) OPENSSL_DIR_end(&d); 82689857Sobrien CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); 82733965Sjdp return ret; 82833965Sjdp } 82933965Sjdp 83033965Sjdp