From 579d553464604832911c1eb08d014f487e54e0ff Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 23 Apr 2012 21:56:33 +0000 Subject: [PATCH] update NEWS --- NEWS | 18 +++++++++++++++ apps/s_cb.c | 13 +++++++++++ ssl/s3_clnt.c | 7 ++++++ ssl/s3_srvr.c | 8 +++++++ ssl/ssl.h | 4 ++++ ssl/ssl_cert.c | 62 ++++++++++++++++++++++++++++++-------------------- ssl/ssl_err.c | 1 + ssl/ssl_lib.c | 16 +++++++++++++ ssl/ssl_locl.h | 11 +++++++++ 9 files changed, 115 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index a46361198d..e70fcba092 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,12 @@ This file gives a brief overview of the major changes between each OpenSSL release. For more details please read the CHANGES file. + Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a: + + o Fix for ASN1 overflow bug CVE-2012-2110 + o Workarounds for some servers that hang on long client hellos. + o Fix SEGV in AES code. + Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1: o TLS/DTLS heartbeat support. @@ -18,6 +24,10 @@ o Preliminary FIPS capability for unvalidated 2.0 FIPS module. o SRP support. + Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.0i: + + o Fix for ASN1 overflow bug CVE-2012-2110 + Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h: o Fix for CMS/PKCS#7 MMA CVE-2012-0884 @@ -90,6 +100,14 @@ o Opaque PRF Input TLS extension support. o Updated time routines to avoid OS limitations. + Major changes between OpenSSL 0.9.8v and OpenSSL 0.9.8w: + + o Fix for CVE-2012-2131 (corrected fix for 0.9.8 and CVE-2012-2110) + + Major changes between OpenSSL 0.9.8u and OpenSSL 0.9.8v: + + o Fix for ASN1 overflow bug CVE-2012-2110 + Major changes between OpenSSL 0.9.8t and OpenSSL 0.9.8u: o Fix for CMS/PKCS#7 MMA CVE-2012-0884 diff --git a/apps/s_cb.c b/apps/s_cb.c index b21a4283df..0c5c39e4f0 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -285,6 +285,19 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, return 1; } +typedef struct + { + X509 *cert; + EVP_PKEY *key; + STACK_OF(X509) *chain; + struct ssl_excert_st *next; + } SSL_EXCERT; + +static int set_cert_cb(SSL *ssl, void *arg) + { + return 1; + } + int ssl_print_sigalgs(BIO *out, SSL *s) { int i, nsig; diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index ee8aeb05f8..3e6a9d4d4c 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -3161,6 +3161,13 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_A) { + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb + && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } if (ssl3_check_client_certificate(s)) s->state=SSL3_ST_CW_CERT_C; else diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 87678c181b..68920a72db 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -1341,6 +1341,14 @@ int ssl3_get_client_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED); goto f_err; } + /* Let cert callback update server certificates if required */ + if (s->cert->cert_cb + && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + { + al=SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); + goto f_err; + } ciphers=NULL; c=ssl3_choose_cipher(s,s->session->ciphers, SSL_get_ciphers(s)); diff --git a/ssl/ssl.h b/ssl/ssl.h index 708dc33d6b..23e79eaaae 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -1759,6 +1759,7 @@ int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *); void SSL_set_verify(SSL *s, int mode, int (*callback)(int ok,X509_STORE_CTX *ctx)); void SSL_set_verify_depth(SSL *s, int depth); +void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg); #ifndef OPENSSL_NO_RSA int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); #endif @@ -1837,6 +1838,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx,int mode, int (*callback)(int, X509_STORE_CTX *)); void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg), void *arg); #ifndef OPENSSL_NO_RSA int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); #endif @@ -1892,6 +1894,7 @@ char *SSL_get_srp_username(SSL *s); char *SSL_get_srp_userinfo(SSL *s); #endif +void SSL_certs_clear(SSL *s); void SSL_free(SSL *ssl); int SSL_accept(SSL *ssl); int SSL_connect(SSL *ssl); @@ -2387,6 +2390,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_CA_DN_TOO_LONG 132 #define SSL_R_CCS_RECEIVED_EARLY 133 #define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +#define SSL_R_CERT_CB_ERROR 371 #define SSL_R_CERT_LENGTH_MISMATCH 135 #define SSL_R_CHALLENGE_IS_DIFFERENT 136 #define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 222f703284..784300e26a 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -345,6 +345,9 @@ CERT *ssl_cert_dup(CERT *cert) ret->sigalgs = NULL; ret->sigalgslen = 0; + ret->cert_cb = cert->cert_cb; + ret->cert_cb_arg = cert->cert_cb_arg; + return(ret); #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) @@ -363,21 +366,36 @@ err: EC_KEY_free(ret->ecdh_tmp); #endif - for (i = 0; i < SSL_PKEY_NUM; i++) - { - CERT_PKEY *rpk = ret->pkeys + i; - if (rpk->x509 != NULL) - X509_free(rpk->x509); - if (rpk->privatekey != NULL) - EVP_PKEY_free(rpk->privatekey); - if (rpk->chain) - sk_X509_pop_free(rpk->chain, X509_free); - } - + ssl_cert_clear_certs(ret); return NULL; } +/* Free up and clear all certificates and chains */ + +void ssl_cert_clear_certs(CERT *c) + { + int i; + for (i = 0; ipkeys + i; + if (cpk->x509) + { + X509_free(cpk->x509); + cpk->x509 = NULL; + } + if (cpk->privatekey) + { + EVP_PKEY_free(cpk->privatekey); + cpk->privatekey = NULL; + } + if (cpk->chain) + { + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = NULL; + } + } + } void ssl_cert_free(CERT *c) { @@ -409,20 +427,8 @@ void ssl_cert_free(CERT *c) if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp); #endif - for (i=0; ipkeys + i; - if (cpk->x509 != NULL) - X509_free(cpk->x509); - if (cpk->privatekey != NULL) - EVP_PKEY_free(cpk->privatekey); - if (cpk->chain) - sk_X509_pop_free(cpk->chain, X509_free); -#if 0 - if (c->pkeys[i].publickey != NULL) - EVP_PKEY_free(c->pkeys[i].publickey); -#endif - } + ssl_cert_clear_certs(c); + if (c->sigalgs) OPENSSL_free(c->sigalgs); OPENSSL_free(c); @@ -510,6 +516,12 @@ int ssl_cert_add1_chain_cert(CERT *c, X509 *x) return 1; } +void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) + { + c->cert_cb = cb; + c->cert_cb_arg = arg; + } + SESS_CERT *ssl_sess_cert_new(void) { SESS_CERT *ret; diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index eec42fa54b..7bde072466 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -345,6 +345,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_CA_DN_TOO_LONG) ,"ca dn too long"}, {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY) ,"ccs received early"}, {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"}, +{ERR_REASON(SSL_R_CERT_CB_ERROR) ,"cert cb error"}, {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH) ,"cert length mismatch"}, {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"}, {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 679894cb3d..12a0448fe2 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -526,6 +526,12 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) return X509_VERIFY_PARAM_set1(ssl->param, vpm); } +void SSL_certs_clear(SSL *s) + { + if (s->cert) + ssl_cert_clear_certs(s->cert); + } + void SSL_free(SSL *s) { int i; @@ -2037,6 +2043,16 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) X509_VERIFY_PARAM_set_depth(ctx->param, depth); } +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg), void *arg) + { + ssl_cert_set_cert_cb(c->cert, cb, arg); + } + +void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg) + { + ssl_cert_set_cert_cb(s->cert, cb, arg); + } + void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) { CERT_PKEY *cpk; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index c340ac3ce7..cc15a5d411 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -512,6 +512,15 @@ typedef struct cert_st TLS_SIGALGS *sigalgs; /* Size of above array */ size_t sigalgslen; + /* Certificate setup callback: if set is called whenever a + * certificate may be required (client or server). the callback + * can then examine any appropriate parameters and setup any + * certificates required. This allows advanced applications + * to select certificates on the fly: for example based on + * supported signature algorithms or curves. + */ + int (*cert_cb)(SSL *ssl, void *arg); + void *cert_cb_arg; int references; /* >1 only if SSL_copy_session_id is used */ } CERT; @@ -822,6 +831,7 @@ int ssl_clear_bad_session(SSL *s); CERT *ssl_cert_new(void); CERT *ssl_cert_dup(CERT *cert); int ssl_cert_inst(CERT **o); +void ssl_cert_clear_certs(CERT *c); void ssl_cert_free(CERT *c); SESS_CERT *ssl_sess_cert_new(void); void ssl_sess_cert_free(SESS_CERT *sc); @@ -849,6 +859,7 @@ int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); int ssl_cert_add0_chain_cert(CERT *c, X509 *x); int ssl_cert_add1_chain_cert(CERT *c, X509 *x); +void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg); int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);