From c4dd98d88736af0b479d3b17c8cc35646a2a1ea8 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Sun, 6 Dec 2015 13:27:27 -0500 Subject: [PATCH] Updates for OpenSSL 1.1.0-dev --- Danessl/Danessl.xs | 44 +++------------------- Danessl/t/Danessl.t | 7 ++-- Makefile | 10 +++-- connected.c | 3 ++ danessl.c | 70 +++++++++++++++++++++++------------ danessl.h | 1 + offline.c | 89 +++++++++++---------------------------------- test-offline.sh | 26 +++++++------ 8 files changed, 100 insertions(+), 150 deletions(-) diff --git a/Danessl/Danessl.xs b/Danessl/Danessl.xs index f397ebf..064f927 100644 --- a/Danessl/Danessl.xs +++ b/Danessl/Danessl.xs @@ -14,6 +14,7 @@ #include #include #include +#include #include #define PERL_constant_NOTFOUND 1 @@ -76,42 +77,6 @@ constant (pTHX_ const char *name, STRLEN len, IV *iv_return) { return PERL_constant_NOTFOUND; } -/* Cut/paste from OpenSSL 1.0.1: ssl/ssl_cert.c */ - -static int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) -{ - X509 *x; - int i; - X509_STORE_CTX ctx; - - if ((sk == NULL) || (sk_X509_num(sk) == 0)) - return(0); - - x=sk_X509_value(sk,0); - if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) { - SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); - - X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server"); - X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); - - if (s->verify_callback) - X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); - - if (s->ctx->app_verify_callback != NULL) - i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); - else { - i=X509_verify_cert(&ctx); - } - - s->verify_result=ctx.error; - X509_STORE_CTX_cleanup(&ctx); - - return(i); -} - static char *btox(unsigned char *data, size_t len) { static char hexdigit[] = "0123456789abcdef"; @@ -440,7 +405,8 @@ verify(uarg, sarg, m, d, ...) if (chain) { xs = load_chain(chain); SSL_set_connect_state(ssl); - if (ssl_verify_cert_chain(ssl, xs)) { + if (DANESSL_verify_chain(ssl, xs) != 0 + && SSL_get_verify_result(ssl) == X509_V_OK) { if (DANESSL_get_match_cert(ssl, 0, &mhost, &mdepth)) { EXTEND(SP, 2); mXPUSHi(mdepth); @@ -546,8 +512,8 @@ tlsagen(chain, dptharg, base, uarg, sarg, m) croak("error processing TLSA RR\n"); SSL_set_connect_state(ssl); - - if (ssl_verify_cert_chain(ssl, xs)) { + if (DANESSL_verify_chain(ssl, xs) != 0 + && SSL_get_verify_result(ssl) == X509_V_OK) { if (DANESSL_get_match_cert(ssl, 0, &mhost, &mdepth)) { EXTEND(SP, 3); mXPUSHi(mdepth); diff --git a/Danessl/t/Danessl.t b/Danessl/t/Danessl.t index f5b3697..30dea29 100644 --- a/Danessl/t/Danessl.t +++ b/Danessl/t/Danessl.t @@ -14,10 +14,9 @@ BEGIN { use_ok('Danessl') }; my $fail = 0; foreach my $constname (qw( - SSL_DANE_SELECTOR_CERT SSL_DANE_SELECTOR_LAST SSL_DANE_SELECTOR_SPKI - SSL_DANE_USAGE_FIXED_LEAF SSL_DANE_USAGE_LAST - SSL_DANE_USAGE_LIMIT_ISSUER SSL_DANE_USAGE_LIMIT_LEAF - SSL_DANE_USAGE_TRUSTED_CA)) { + USAGE_PKIX_TA USAGE_PKIX_EE USAGE_DANE_TA USAGE_DANE_EE + SELECTOR_CERT SELECTOR_SPKI + MATCHING_FULL MATCHING_2256 MATCHING_2512)) { next if (eval "my \$a = $constname; 1"); if ($@ =~ /^Your vendor has not defined Danessl macro $constname/) { print "# pass: $@"; diff --git a/Makefile b/Makefile index 301df7c..df488a3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ -CFLAGS = -fPIC -Wall -Werror -g -LDFLAGS = -lssl -lcrypto +CFLAGS = -I${OPENSSL}/include -fPIC -Wall -Werror -g +LDFLAGS = -L${OPENSSL}/lib -lssl -lcrypto +OPENSSL = /usr +PREFIX = /usr LIB = danessl PROG1 = connected PROG2 = offline @@ -24,5 +26,5 @@ clean: $(RM) ${SHLIB} ${PROG1} ${PROG2} *.o install: - cp danessl.h /usr/include/ - cp ${SHLIB} /usr/lib/ + cp danessl.h ${PREFIX}/include/ + cp ${SHLIB} ${PREFIX}/lib/ diff --git a/connected.c b/connected.c index 2d0c6b9..7ed365e 100644 --- a/connected.c +++ b/connected.c @@ -7,11 +7,14 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "danessl.h" diff --git a/danessl.c b/danessl.c index 4a853fb..0271030 100644 --- a/danessl.c +++ b/danessl.c @@ -14,11 +14,16 @@ #include #include #include +#include #if OPENSSL_VERSION_NUMBER < 0x1000000fL #error "OpenSSL 1.0.0 or higher required" #else +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) +#endif + #include "danessl.h" #define DANESSL_F_ADD_SKID 100 @@ -252,12 +257,8 @@ static int match(DANE_SELECTOR_LIST slist, X509 *cert, int depth) static int push_ext(X509 *cert, X509_EXTENSION *ext) { - X509_EXTENSIONS *exts; - if (ext) { - if ((exts = cert->cert_info->extensions) == 0) - exts = cert->cert_info->extensions = sk_X509_EXTENSION_new_null(); - if (exts && sk_X509_EXTENSION_push(exts, ext)) + if (X509_add_ext(cert, ext, -1)) return 1; X509_EXTENSION_free(ext); } @@ -382,7 +383,7 @@ static int grow_chain(SSL_DANE *dane, int trusted, X509 *cert) if (cert) { if (trusted && !X509_add1_trust_object(cert, serverAuth)) return 0; - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); if (!sk_X509_push(*xs, cert)) { X509_free(cert); DANEerr(DANESSL_F_GROW_CHAIN, ERR_R_MALLOC_FAILURE); @@ -645,11 +646,11 @@ static int check_end_entity(X509_STORE_CTX *ctx, SSL_DANE *dane, X509 *cert) if (matched > 0) { dane->mdpth = 0; dane->match = cert; - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); if (ctx->chain == 0) { if ((ctx->chain = sk_X509_new_null()) != 0 && sk_X509_push(ctx->chain, cert)) { - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); } else { DANEerr(DANESSL_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE); return -1; @@ -849,7 +850,7 @@ static int verify_chain(X509_STORE_CTX *ctx) dane->mdpth = dane->depth; dane->match = top; - CRYPTO_add(&top->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(top); #ifndef NO_CALLBACK_WORKAROUND @@ -895,7 +896,7 @@ static int verify_chain(X509_STORE_CTX *ctx) } else { dane->mdpth = n; dane->match = xn; - CRYPTO_add(&xn->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(xn); } } @@ -924,7 +925,8 @@ static void dane_reset(SSL_DANE *dane) dane->mdpth = -1; } -static int verify_cert(X509_STORE_CTX *ctx, void *unused_ctx) +static +int verify_cert(X509_STORE_CTX *ctx, void *unused_ctx) { static int ssl_idx = -1; SSL *ssl; @@ -1036,7 +1038,7 @@ static void list_free(void *list, void (*f)(void *)) static void dane_mtype_free(void *p) { - list_free(((dane_mtype) p)->data, OPENSSL_freeFunc); + list_free(((dane_mtype) p)->data, CRYPTO_free); OPENSSL_free(p); } @@ -1057,7 +1059,7 @@ void DANESSL_cleanup(SSL *ssl) dane_reset(dane); if (dane->hosts) - list_free(dane->hosts, OPENSSL_freeFunc); + list_free(dane->hosts, CRYPTO_free); for (u = 0; u <= DANESSL_USAGE_LAST; ++u) if (dane->selectors[u]) list_free(dane->selectors[u], dane_selector_free); @@ -1075,7 +1077,7 @@ static DANE_HOST_LIST host_list_init(const char **src) while (*src) { DANE_HOST_LIST elem = (DANE_HOST_LIST) OPENSSL_malloc(sizeof(*elem)); if (elem == 0) { - list_free(head, OPENSSL_freeFunc); + list_free(head, CRYPTO_free); return 0; } elem->value = OPENSSL_strdup(*src++); @@ -1106,6 +1108,36 @@ int DANESSL_get_match_cert(SSL *ssl, X509 **match, const char **mhost, int *dept return (dane->match != 0); } +int DANESSL_verify_chain(SSL *ssl, STACK_OF(X509) *chain) +{ + int ret; + X509 *cert; + X509_STORE_CTX store_ctx; + SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl); + X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); + int store_ctx_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); + + cert = sk_X509_value(chain, 0); + if (!X509_STORE_CTX_init(&store_ctx, store, cert, chain)) + return 0; + X509_STORE_CTX_set_ex_data(&store_ctx, store_ctx_idx, ssl); + + X509_STORE_CTX_set_default(&store_ctx, + SSL_is_server(ssl) ? "ssl_client" : "ssl_server"); + X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&store_ctx), + SSL_get0_param(ssl)); + + if (SSL_get_verify_callback(ssl)) + X509_STORE_CTX_set_verify_cb(&store_ctx, SSL_get_verify_callback(ssl)); + + ret = verify_cert(&store_ctx, NULL); + + SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(&store_ctx)); + X509_STORE_CTX_cleanup(&store_ctx); + + return (ret); +} + int DANESSL_add_tlsa( SSL *ssl, @@ -1236,7 +1268,7 @@ int DANESSL_add_tlsa( memcpy(d->value->data, data, dlen); if (!m) { if ((m = (DANE_MTYPE_LIST) list_alloc(sizeof(*m->value))) == 0) { - list_free(d, OPENSSL_freeFunc); + list_free(d, CRYPTO_free); xkfreeret(0); } m->value->data = 0; @@ -1267,19 +1299,11 @@ int DANESSL_init(SSL *ssl, const char *sni_domain, const char **hostnames) { SSL_DANE *dane; int i; -#ifdef OPENSSL_INTERNAL - SSL_CTX *sctx = SSL_get_SSL_CTX(ssl); - if (sctx->app_verify_callback != verify_cert) { - DANEerr(DANESSL_F_INIT, DANESSL_R_SCTX_INIT); - return -1; - } -#else if (dane_idx < 0) { DANEerr(DANESSL_F_INIT, DANESSL_R_LIBRARY_INIT); return -1; } -#endif if (sni_domain && !SSL_set_tlsext_host_name(ssl, sni_domain)) return 0; diff --git a/danessl.h b/danessl.h index ea0a3e3..1d6439e 100644 --- a/danessl.h +++ b/danessl.h @@ -42,5 +42,6 @@ extern void DANESSL_cleanup(SSL *); extern int DANESSL_add_tlsa(SSL *, uint8_t, uint8_t, const char *, unsigned const char *, size_t); extern int DANESSL_get_match_cert(SSL *, X509 **, const char **, int *); +extern int DANESSL_verify_chain(SSL *, STACK_OF(X509) *); #endif diff --git a/offline.c b/offline.c index 0302014..84ac5fb 100644 --- a/offline.c +++ b/offline.c @@ -2,71 +2,24 @@ * Author: Viktor Dukhovni * License: THIS CODE IS IN THE PUBLIC DOMAIN. */ + +#include +#include + #include #include +#include #include #include #include #include #include +#include +#include #include "danessl.h" -/* Cut/paste from OpenSSL 1.0.1: ssl/ssl_cert.c */ - -static int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) -{ - X509 *x; - int i; - X509_STORE_CTX ctx; - - if ((sk == NULL) || (sk_X509_num(sk) == 0)) - return(0); - - x=sk_X509_value(sk,0); - if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) { - SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); - - /* We need to inherit the verify parameters. These can be determined by - * the context: if its a server it will verify SSL client certificates - * or vice versa. - */ - - X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server"); - /* Anything non-default in "param" should overwrite anything in the - * ctx. - */ - X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); - - if (s->verify_callback) - X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); - - if (s->ctx->app_verify_callback != NULL) -#if 1 /* new with OpenSSL 0.9.7 */ - i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); -#else - i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ -#endif - else { -#ifndef OPENSSL_NO_X509_VERIFY - i=X509_verify_cert(&ctx); -#else - i=0; - ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; - SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK); -#endif - } - - s->verify_result=ctx.error; - X509_STORE_CTX_cleanup(&ctx); - - return(i); -} - static void print_errors(void) { unsigned long err; @@ -85,6 +38,19 @@ static void print_errors(void) } } +static void fatal(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "Fatal: "); + vfprintf(stderr, fmt, ap); + va_end(ap); + + print_errors(); + exit(1); +} + static int add_tlsa(SSL *ssl, const char *argv[]) { const EVP_MD *md = 0; @@ -267,19 +233,6 @@ static void usage(const char *progname) exit(1); } -static void fatal(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "Fatal: "); - vfprintf(stderr, fmt, ap); - va_end(ap); - - print_errors(); - exit(1); -} - int main(int argc, const char *argv[]) { STACK_OF(X509) *chain; @@ -316,7 +269,7 @@ int main(int argc, const char *argv[]) /* Verify saved server chain */ chain = load_chain(argv[6]); SSL_set_connect_state(ssl); - ssl_verify_cert_chain(ssl, chain); + DANESSL_verify_chain(ssl, chain); print_errors(); printf("verify status: %ld\n", ok = SSL_get_verify_result(ssl)); diff --git a/test-offline.sh b/test-offline.sh index 70bd42a..442bdb9 100755 --- a/test-offline.sh +++ b/test-offline.sh @@ -50,8 +50,8 @@ genroot() { local akid=$1; shift exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true") - req "$key" "$cn" | - cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days 30 + csr=$(req "$key" "$cn") + echo "$csr" | cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days 30 } genca() { @@ -64,8 +64,8 @@ genca() { local cakey=$1; shift exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true") - req "$key" "$cn" | - cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ + csr=$(req "$key" "$cn") + echo "$csr" | cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ -set_serial 2 -days 30 "$@" } @@ -82,8 +82,9 @@ genee() { "basicConstraints = CA:false" \ "extendedKeyUsage = serverAuth" \ "subjectAltName = @alts" "DNS=${cn}") - req "$key" "$cn" | - cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ + csr=$(req "$key" "$cn") + echo "$csr" | + cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ -set_serial 2 -days 30 "$@" } @@ -98,15 +99,16 @@ genss() { "basicConstraints = CA:true" \ "extendedKeyUsage = serverAuth" \ "subjectAltName = @alts" "DNS=${cn}") - req "$key" "$cn" | - cert "$cert" "$exts" -set_serial 1 -days 30 -signkey "${key}.pem" "$@" + csr=$(req "$key" "$cn") + echo "$csr" | cert "$cert" "$exts" -set_serial 1 -days 30 -signkey "${key}.pem" "$@" } gennocn() { local key=$1; shift local cert=$1; shift - req_nocn "$key" | + csr=$(req_nocn "$key") + echo "$csr" | cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@" } @@ -131,7 +133,7 @@ runtest() { if [ -n "$ca" ]; then ca="$ca.pem"; fi "$TEST" "$usage" "$selector" "$digest" "$tlsa.pem" "$ca" "$chain.pem" \ - "$@" > /dev/null + "$@" > /dev/null } checkpass() { runtest "$@" && { echo pass; } || { echo fail; exit 1; }; } @@ -220,13 +222,13 @@ for s in 0 1; do # checkpass "valid EE" 1 "$s" "$m" eecert rootcert chain1 "$HOST" checkpass "sub-domain match" 1 "$s" "$m" eecert rootcert chain1 \ - whatever ".$DOMAIN" + whatever ".$DOMAIN" checkfail "wrong name" 1 "$s" "$m" eecert rootcert chain1 whatever checkfail "null CA" 1 "$s" "$m" eecert "" chain1 "$HOST" checkfail "non-root CA" 1 "$s" "$m" eecert cacert1 chain1 "$HOST" checkpass "depth 0 ss-CA EE" 1 "$s" "$m" sscert sscert sscert "${HOST}" checkfail "depth 0 ss-CA EE namecheck" 1 "$s" "$m" sscert sscert sscert \ - whatever + whatever # Usage 3 tests: #