Fix some malloc failure crashes.
EVP_MD_CTX_copy_ex was implemented with a memcpy, which doesn't work well when
some of the pointers need to be copied, and ssl_verify_cert_chain didn't
account for set_ex_data failing.
Change-Id: Ieb556aeda6ab2e4c810f27012fefb1e65f860023
Reviewed-on: https://boringssl-review.googlesource.com/5911
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/digest/digest.c b/crypto/digest/digest.c
index ada1166..eb71b07 100644
--- a/crypto/digest/digest.c
+++ b/crypto/digest/digest.c
@@ -129,8 +129,8 @@
}
EVP_MD_CTX_cleanup(out);
- memcpy(out, in, sizeof(EVP_MD_CTX));
+ out->digest = in->digest;
if (in->md_data && in->digest->ctx_size) {
if (tmp_buf) {
out->md_data = tmp_buf;
@@ -145,6 +145,7 @@
}
assert(in->pctx == NULL || in->pctx_ops != NULL);
+ out->pctx_ops = in->pctx_ops;
if (in->pctx && in->pctx_ops) {
out->pctx = in->pctx_ops->dup(in->pctx);
if (!out->pctx) {
diff --git a/ssl/internal.h b/ssl/internal.h
index a788b6e..8f477bc 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -994,7 +994,7 @@
void ssl_cert_set_cert_cb(CERT *cert,
int (*cb)(SSL *ssl, void *arg), void *arg);
-int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk);
+int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
int ssl_add_cert_chain(SSL *s, unsigned long *l);
void ssl_update_cache(SSL *s, int mode);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 46cb4c0..1506f63 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -293,44 +293,46 @@
c->cert_cb_arg = arg;
}
-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) {
+int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) {
+ if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
return 0;
}
- x = sk_X509_value(sk, 0);
- if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) {
+ X509 *leaf = sk_X509_value(cert_chain, 0);
+ int ret = 0;
+ X509_STORE_CTX ctx;
+ if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, cert_chain)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
return 0;
}
- X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
+ if (!X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(),
+ ssl)) {
+ goto err;
+ }
/* 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");
+ X509_STORE_CTX_set_default(&ctx, ssl->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);
+ X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), ssl->param);
- if (s->verify_callback) {
- X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
+ if (ssl->verify_callback) {
+ X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback);
}
- if (s->ctx->app_verify_callback != NULL) {
- i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
+ if (ssl->ctx->app_verify_callback != NULL) {
+ ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
} else {
- i = X509_verify_cert(&ctx);
+ ret = X509_verify_cert(&ctx);
}
- s->verify_result = ctx.error;
- X509_STORE_CTX_cleanup(&ctx);
+ ssl->verify_result = ctx.error;
- return i;
+err:
+ X509_STORE_CTX_cleanup(&ctx);
+ return ret;
}
static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,