Hold certificates in an SSL_SESSION as CRYPTO_BUFFERSs as well.
This change adds a STACK_OF(CRYPTO_BUFFER) to an SSL_SESSION which
contains the raw form of the received certificates. The X509-based
members still exist, but their |enc| buffer will alias the
CRYPTO_BUFFERs.
(This is a second attempt at
https://boringssl-review.googlesource.com/#/c/12163/.)
BUG=chromium:671420
Change-Id: I508a8a46cab89a5a3fcc0c1224185d63e3d59cb8
Reviewed-on: https://boringssl-review.googlesource.com/12705
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 041895c..3d88017 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3690,6 +3690,11 @@
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
char *psk_identity;
+
+ /* certs contains the certificate chain from the peer, starting with the leaf
+ * certificate. */
+ STACK_OF(CRYPTO_BUFFER) *certs;
+
/* x509_peer is the peer's certificate. */
X509 *x509_peer;
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 59fefc4..dc806e0 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -1041,39 +1041,30 @@
CBS cbs;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+
uint8_t alert;
- STACK_OF(X509) *chain = ssl_parse_cert_chain(ssl, &alert, NULL, &cbs);
- if (chain == NULL) {
+ sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
+ ssl->s3->new_session->certs = ssl_parse_cert_chain(&alert, NULL, &cbs);
+ if (ssl->s3->new_session->certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return -1;
}
- if (sk_X509_num(chain) == 0 || CBS_len(&cbs) != 0) {
+ if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0 ||
+ CBS_len(&cbs) != 0 ||
+ !ssl_session_x509_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
- X509 *leaf = sk_X509_value(chain, 0);
+ X509 *leaf = sk_X509_value(ssl->s3->new_session->x509_chain, 0);
if (!ssl_check_leaf_certificate(ssl, leaf)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- goto err;
+ return -1;
}
- sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
- ssl->s3->new_session->x509_chain = chain;
- sk_X509_pop_free(ssl->s3->new_session->x509_chain_without_leaf, X509_free);
- ssl->s3->new_session->x509_chain_without_leaf = NULL;
-
- X509_free(ssl->s3->new_session->x509_peer);
- X509_up_ref(leaf);
- ssl->s3->new_session->x509_peer = leaf;
-
return 1;
-
-err:
- sk_X509_pop_free(chain, X509_free);
- return -1;
}
static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index cca9bd6..9b13023 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -1466,26 +1466,27 @@
CBS certificate_msg;
CBS_init(&certificate_msg, ssl->init_msg, ssl->init_num);
+
+ sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
uint8_t alert;
- STACK_OF(X509) *chain = ssl_parse_cert_chain(
- ssl, &alert, ssl->retain_only_sha256_of_client_certs
- ? ssl->s3->new_session->peer_sha256
- : NULL,
- &certificate_msg);
- if (chain == NULL) {
+ ssl->s3->new_session->certs =
+ ssl_parse_cert_chain(&alert, ssl->retain_only_sha256_of_client_certs
+ ? ssl->s3->new_session->peer_sha256
+ : NULL,
+ &certificate_msg);
+ if (ssl->s3->new_session->certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return -1;
}
- if (CBS_len(&certificate_msg) != 0) {
+ if (CBS_len(&certificate_msg) != 0 ||
+ !ssl_session_x509_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
- X509 *leaf = NULL;
-
- if (sk_X509_num(chain) == 0) {
+ if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
/* No client certificate so the handshake buffer may be discarded. */
ssl3_free_handshake_buffer(ssl);
@@ -1494,48 +1495,32 @@
if (ssl->version == SSL3_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
+ return -1;
}
if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
/* Fail for TLS only if we required a certificate */
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
+ return -1;
}
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
ssl->s3->new_session->verify_result = X509_V_OK;
- } else {
- leaf = sk_X509_value(chain, 0);
- /* The hash would have been filled in. */
- if (ssl->retain_only_sha256_of_client_certs) {
- ssl->s3->new_session->peer_sha256_valid = 1;
- }
-
- if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
- chain)) {
- goto err;
- }
+ return 1;
}
- sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
- ssl->s3->new_session->x509_chain = chain;
- sk_X509_pop_free(ssl->s3->new_session->x509_chain_without_leaf, X509_free);
- ssl->s3->new_session->x509_chain_without_leaf = NULL;
-
- X509_free(ssl->s3->new_session->x509_peer);
- if (leaf) {
- X509_up_ref(leaf);
+ /* The hash will have been filled in. */
+ if (ssl->retain_only_sha256_of_client_certs) {
+ ssl->s3->new_session->peer_sha256_valid = 1;
}
- ssl->s3->new_session->x509_peer = leaf;
+ if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
+ ssl->s3->new_session->x509_chain)) {
+ return -1;
+ }
return 1;
-
-err:
- sk_X509_pop_free(chain, X509_free);
- return -1;
}
static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
diff --git a/ssl/internal.h b/ssl/internal.h
index 3b2f194..cd5db9e 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -748,14 +748,21 @@
* on error. */
X509 *ssl_parse_x509(CBS *cbs);
+/* ssl_session_x509_cache_objects fills out |sess->x509_peer| and
+ * |sess->x509_chain| from |sess->certs| and erases
+ * |sess->x509_chain_without_leaf|. It returns one on success or zero on
+ * error. */
+int ssl_session_x509_cache_objects(SSL_SESSION *sess);
+
/* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
* by a TLS Certificate message. On success, it returns a newly-allocated
- * |X509| list and advances |cbs|. Otherwise, it returns NULL and sets
+ * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
* |*out_alert| to an alert to send to the peer. If the list is non-empty and
* |out_leaf_sha256| is non-NULL, it writes the SHA-256 hash of the leaf to
* |out_leaf_sha256|. */
-STACK_OF(X509) *ssl_parse_cert_chain(SSL *ssl, uint8_t *out_alert,
- uint8_t *out_leaf_sha256, CBS *cbs);
+STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
+ uint8_t *out_leaf_sha256,
+ CBS *cbs);
/* ssl_add_cert_to_cbb adds |x509| to |cbb|. It returns one on success and zero
* on error. */
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 67d9df8..fa2fbc0 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -223,14 +223,14 @@
/* The peer certificate is only serialized if the SHA-256 isn't
* serialized instead. */
- if (in->x509_peer && !in->peer_sha256_valid) {
- if (!CBB_add_asn1(&session, &child, kPeerTag)) {
+ if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) {
+ const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0);
+ if (!CBB_add_asn1(&session, &child, kPeerTag) ||
+ !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
+ CRYPTO_BUFFER_len(buffer))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!ssl_add_cert_to_cbb(&child, in->x509_peer)) {
- goto err;
- }
}
/* Although it is OPTIONAL and usually empty, OpenSSL has
@@ -343,14 +343,18 @@
/* The certificate chain is only serialized if the leaf's SHA-256 isn't
* serialized instead. */
- if (in->x509_chain != NULL && !in->peer_sha256_valid &&
- sk_X509_num(in->x509_chain) >= 2) {
+ if (in->certs != NULL &&
+ !in->peer_sha256_valid &&
+ sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- for (size_t i = 1; i < sk_X509_num(in->x509_chain); i++) {
- if (!ssl_add_cert_to_cbb(&child, sk_X509_value(in->x509_chain, i))) {
+ for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) {
+ const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i);
+ if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
+ CRYPTO_BUFFER_len(buffer))) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -585,22 +589,12 @@
CBS peer;
int has_peer;
- if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag)) {
+ if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
+ (has_peer && CBS_len(&peer) == 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
- X509_free(ret->x509_peer);
- ret->x509_peer = NULL;
- if (has_peer) {
- ret->x509_peer = ssl_parse_x509(&peer);
- if (ret->x509_peer == NULL) {
- goto err;
- }
- if (CBS_len(&peer) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
- }
- }
+ /* |peer| is processed with the certificate chain. */
if (!SSL_SESSION_parse_bounded_octet_string(
&session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
@@ -663,43 +657,56 @@
}
CBS cert_chain;
+ CBS_init(&cert_chain, NULL, 0);
int has_cert_chain;
if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
- kCertChainTag)) {
+ kCertChainTag) ||
+ (has_cert_chain && CBS_len(&cert_chain) == 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
- sk_X509_pop_free(ret->x509_chain, X509_free);
- ret->x509_chain = NULL;
- if (ret->x509_peer != NULL) {
- ret->x509_chain = sk_X509_new_null();
- if (ret->x509_chain == NULL ||
- !sk_X509_push(ret->x509_chain, ret->x509_peer)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- X509_up_ref(ret->x509_peer);
+ if (has_cert_chain && !has_peer) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ goto err;
}
- if (has_cert_chain) {
- if (ret->x509_peer == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
- }
- if (ret->x509_chain == NULL) {
+ if (has_peer || has_cert_chain) {
+ ret->certs = sk_CRYPTO_BUFFER_new_null();
+ if (ret->certs == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- while (CBS_len(&cert_chain) > 0) {
- X509 *x509 = ssl_parse_x509(&cert_chain);
- if (x509 == NULL) {
- goto err;
- }
- if (!sk_X509_push(ret->x509_chain, x509)) {
+
+ if (has_peer) {
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, NULL);
+ if (buffer == NULL ||
+ !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
+ CRYPTO_BUFFER_free(buffer);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- X509_free(x509);
goto err;
}
}
+
+ while (CBS_len(&cert_chain) > 0) {
+ CBS cert;
+ if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
+ CBS_len(&cert) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, NULL);
+ if (buffer == NULL ||
+ !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
+ CRYPTO_BUFFER_free(buffer);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ }
+
+ if (!ssl_session_x509_cache_objects(ret)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ goto err;
}
CBS age_add;
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index d1ad4ec..66ee068 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -462,16 +462,16 @@
return ret;
}
-STACK_OF(X509) *ssl_parse_cert_chain(SSL *ssl, uint8_t *out_alert,
- uint8_t *out_leaf_sha256, CBS *cbs) {
- STACK_OF(X509) *ret = sk_X509_new_null();
+STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
+ uint8_t *out_leaf_sha256,
+ CBS *cbs) {
+ STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null();
if (ret == NULL) {
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- X509 *x = NULL;
CBS certificate_list;
if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) {
*out_alert = SSL_AD_DECODE_ERROR;
@@ -481,35 +481,36 @@
while (CBS_len(&certificate_list) > 0) {
CBS certificate;
- if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
+ CBS_len(&certificate) == 0) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
/* Retain the hash of the leaf certificate if requested. */
- if (sk_X509_num(ret) == 0 && out_leaf_sha256 != NULL) {
+ if (sk_CRYPTO_BUFFER_num(ret) == 0 && out_leaf_sha256 != NULL) {
SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256);
}
- x = ssl_parse_x509(&certificate);
- if (x == NULL || CBS_len(&certificate) != 0) {
+ CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, NULL);
+ if (buf == NULL) {
*out_alert = SSL_AD_DECODE_ERROR;
goto err;
}
- if (!sk_X509_push(ret, x)) {
+
+ if (!sk_CRYPTO_BUFFER_push(ret, buf)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
+ CRYPTO_BUFFER_free(buf);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- x = NULL;
}
return ret;
err:
- X509_free(x);
- sk_X509_pop_free(ret, X509_free);
+ sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free);
return NULL;
}
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index b0951ac..c1bfcd7 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -200,6 +200,19 @@
goto err;
}
}
+ if (session->certs != NULL) {
+ new_session->certs = sk_CRYPTO_BUFFER_new_null();
+ if (new_session->certs == NULL) {
+ goto err;
+ }
+ for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
+ CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
+ if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
+ goto err;
+ }
+ CRYPTO_BUFFER_up_ref(buffer);
+ }
+ }
if (session->x509_peer != NULL) {
X509_up_ref(session->x509_peer);
new_session->x509_peer = session->x509_peer;
@@ -326,6 +339,7 @@
OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
+ sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
X509_free(session->x509_peer);
sk_X509_pop_free(session->x509_chain, X509_free);
sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
@@ -518,6 +532,53 @@
return 0;
}
+int ssl_session_x509_cache_objects(SSL_SESSION *sess) {
+ STACK_OF(X509) *chain = NULL;
+ const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);
+
+ if (num_certs > 0) {
+ chain = sk_X509_new_null();
+ if (chain == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ X509 *leaf = NULL;
+ for (size_t i = 0; i < num_certs; i++) {
+ X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
+ if (x509 == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+ if (!sk_X509_push(chain, x509)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ X509_free(x509);
+ goto err;
+ }
+ if (i == 0) {
+ leaf = x509;
+ }
+ }
+
+ sk_X509_pop_free(sess->x509_chain, X509_free);
+ sess->x509_chain = chain;
+ sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
+ sess->x509_chain_without_leaf = NULL;
+
+ X509_free(sess->x509_peer);
+ if (leaf != NULL) {
+ X509_up_ref(leaf);
+ }
+ sess->x509_peer = leaf;
+
+ return 1;
+
+err:
+ sk_X509_pop_free(chain, X509_free);
+ return 0;
+}
+
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
int ret = 0;
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 939e530..a47dd26 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -177,8 +177,8 @@
ssl->server && ssl->retain_only_sha256_of_client_certs;
int ret = 0;
- STACK_OF(X509) *chain = sk_X509_new_null();
- if (chain == NULL) {
+ STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null();
+ if (certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
@@ -193,28 +193,25 @@
while (CBS_len(&certificate_list) > 0) {
CBS certificate, extensions;
if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
- !CBS_get_u16_length_prefixed(&certificate_list, &extensions)) {
+ !CBS_get_u16_length_prefixed(&certificate_list, &extensions) ||
+ CBS_len(&certificate) == 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
/* Retain the hash of the leaf certificate if requested. */
- if (sk_X509_num(chain) == 0 && retain_sha256) {
+ if (sk_CRYPTO_BUFFER_num(certs) == 0 && retain_sha256) {
SHA256(CBS_data(&certificate), CBS_len(&certificate),
ssl->s3->new_session->peer_sha256);
}
- X509 *x = ssl_parse_x509(&certificate);
- if (x == NULL || CBS_len(&certificate) != 0) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- X509_free(x);
- goto err;
- }
- if (!sk_X509_push(chain, x)) {
+ CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, NULL);
+ if (buf == NULL ||
+ !sk_CRYPTO_BUFFER_push(certs, buf)) {
+ CRYPTO_BUFFER_free(buf);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- X509_free(x);
goto err;
}
@@ -253,7 +250,7 @@
goto err;
}
- if (sk_X509_num(chain) == 1 &&
+ if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
!CBS_stow(&ocsp_response, &ssl->s3->new_session->ocsp_response,
&ssl->s3->new_session->ocsp_response_length)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
@@ -274,7 +271,7 @@
goto err;
}
- if (sk_X509_num(chain) == 1 &&
+ if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
!CBS_stow(&sct,
&ssl->s3->new_session->tlsext_signed_cert_timestamp_list,
&ssl->s3->new_session
@@ -291,7 +288,17 @@
goto err;
}
- if (sk_X509_num(chain) == 0) {
+ sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
+ ssl->s3->new_session->certs = certs;
+ certs = NULL;
+
+ if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
+ }
+
+ if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
if (!allow_anonymous) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
@@ -310,25 +317,14 @@
ssl->s3->new_session->peer_sha256_valid = retain_sha256;
if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
- chain)) {
+ ssl->s3->new_session->x509_chain)) {
goto err;
}
- X509_free(ssl->s3->new_session->x509_peer);
- X509 *leaf = sk_X509_value(chain, 0);
- X509_up_ref(leaf);
- ssl->s3->new_session->x509_peer = leaf;
-
- sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
- ssl->s3->new_session->x509_chain = chain;
- chain = NULL;
- sk_X509_pop_free(ssl->s3->new_session->x509_chain_without_leaf, X509_free);
- ssl->s3->new_session->x509_chain_without_leaf = NULL;
-
ret = 1;
err:
- sk_X509_pop_free(chain, X509_free);
+ sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free);
return ret;
}