Client-side OCSP stapling support.
Remove the old implementation which was excessively general. This mirrors the
SCT support and adds a single boolean flag to request an OCSP response with no
responder IDs, extensions, or frills. The response, if received, is stored on
the SSL_SESSION so that it is available for (re)validation on session
resumption; Chromium revalidates the saved auth parameters on resume.
Server support is unimplemented for now. This API will also need to be adjusted
in the future if we implement RFC 6961.
Change-Id: I533c029b7f7ea622d814d05f934fdace2da85cb1
Reviewed-on: https://boringssl-review.googlesource.com/1671
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 4fcf0c3..b781d88 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -309,7 +309,7 @@
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_CR_CERT_STATUS_A;
else
s->state=SSL3_ST_CR_KEY_EXCH_A;
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 102d442..79da484 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -359,7 +359,7 @@
dtls1_start_timer(s);
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_SW_CERT_STATUS_A;
else
s->state=SSL3_ST_SW_KEY_EXCH_A;
@@ -522,6 +522,8 @@
s->init_num=0;
break;
+#if 0
+ // TODO(davidben): Implement OCSP stapling on the server.
case SSL3_ST_SW_CERT_STATUS_A:
case SSL3_ST_SW_CERT_STATUS_B:
ret=ssl3_send_cert_status(s);
@@ -529,7 +531,7 @@
s->state=SSL3_ST_SW_KEY_EXCH_A;
s->init_num=0;
break;
-
+#endif
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 63fbbeb..44d26a7 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -299,7 +299,7 @@
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_CR_CERT_STATUS_A;
else
s->state=SSL3_ST_CR_KEY_EXCH_A;
@@ -1798,7 +1798,6 @@
long n;
CBS certificate_status, ocsp_response;
uint8_t status_type;
- size_t resplen;
n=s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_STATUS_A,
@@ -1822,34 +1821,13 @@
goto f_err;
}
- /* TODO(davidben): Make tlsext_ocsp_resplen a
- * size_t. Currently it uses -1 to signal no response. The
- * spec does not allow ocsp_response to be zero-length, so
- * using 0 should be fine. */
- if (!CBS_stow(&ocsp_response, &s->tlsext_ocsp_resp, &resplen))
+ if (!CBS_stow(&ocsp_response,
+ &s->session->ocsp_response, &s->session->ocsp_response_length))
{
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE);
goto f_err;
}
- s->tlsext_ocsp_resplen = resplen;
- if (s->ctx->tlsext_status_cb)
- {
- int ret;
- ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- if (ret == 0)
- {
- al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_INVALID_STATUS_RESPONSE);
- goto f_err;
- }
- if (ret < 0)
- {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- }
return 1;
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 50aa4bd..479b6de 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1252,44 +1252,6 @@
ret = 1;
break;
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
- s->tlsext_status_type=larg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
- *(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts;
- ret = 1;
- break;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
- s->tlsext_ocsp_exts = parg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
- *(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids;
- ret = 1;
- break;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
- s->tlsext_ocsp_ids = parg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
- *(unsigned char **)parg = s->tlsext_ocsp_resp;
- return s->tlsext_ocsp_resplen;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = parg;
- s->tlsext_ocsp_resplen = larg;
- ret = 1;
- break;
-
-
case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(s->cert,
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 1017f4a..0e9c7d5 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -352,7 +352,7 @@
{
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_SW_CERT_STATUS_A;
else
s->state=SSL3_ST_SW_KEY_EXCH_A;
@@ -569,6 +569,8 @@
s->init_num=0;
break;
+#if 0
+ // TODO(davidben): Implement OCSP stapling on the server.
case SSL3_ST_SW_CERT_STATUS_A:
case SSL3_ST_SW_CERT_STATUS_B:
ret=ssl3_send_cert_status(s);
@@ -576,6 +578,7 @@
s->state=SSL3_ST_SW_KEY_EXCH_A;
s->init_num=0;
break;
+#endif
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
@@ -1137,16 +1140,6 @@
* s->tmp.new_cipher - the new cipher to use.
*/
- /* Handles TLS extensions that we couldn't check earlier */
- if (s->version >= SSL3_VERSION)
- {
- if (ssl_check_clienthello_tlsext_late(s) <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
- }
- }
-
if (ret < 0) ret=-ret;
if (0)
{
@@ -2651,6 +2644,7 @@
return ssl_do_write(s);
}
+#if 0
int ssl3_send_cert_status(SSL *s)
{
if (s->state == SSL3_ST_SW_CERT_STATUS_A)
@@ -2685,6 +2679,7 @@
/* SSL3_ST_SW_CERT_STATUS_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
+#endif
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 05c6462..8acd0eb 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -120,12 +120,13 @@
ASN1_OCTET_STRING peer_sha256;
ASN1_OCTET_STRING original_handshake_hash;
ASN1_OCTET_STRING tlsext_signed_cert_timestamp_list;
+ ASN1_OCTET_STRING ocsp_response;
} SSL_SESSION_ASN1;
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
{
#define LSIZE2 (sizeof(long)*2)
- int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0,v13=0,v14=0,v15=0;
+ int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0,v13=0,v14=0,v15=0,v16=0;
unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
int v6=0,v9=0,v10=0;
@@ -269,6 +270,13 @@
in->tlsext_signed_cert_timestamp_list;
}
+ if (in->ocsp_response_length > 0)
+ {
+ a.ocsp_response.length = in->ocsp_response_length;
+ a.ocsp_response.type = V_ASN1_OCTET_STRING;
+ a.ocsp_response.data = in->ocsp_response;
+ }
+
M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING);
@@ -303,6 +311,8 @@
if (in->tlsext_signed_cert_timestamp_list_length > 0)
M_ASN1_I2D_len_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
i2d_ASN1_OCTET_STRING, 15, v15);
+ if (in->ocsp_response_length > 0)
+ M_ASN1_I2D_len_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
M_ASN1_I2D_seq_total();
@@ -340,6 +350,8 @@
if (in->tlsext_signed_cert_timestamp_list_length > 0)
M_ASN1_I2D_put_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
i2d_ASN1_OCTET_STRING, 15, v15);
+ if (in->ocsp_response > 0)
+ M_ASN1_I2D_put_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
M_ASN1_I2D_finish();
}
@@ -600,6 +612,18 @@
os.data = NULL;
}
+ os.length = 0;
+ os.data = NULL;
+ M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 16);
+ if (os.data)
+ {
+ if (ret->ocsp_response)
+ OPENSSL_free(ret->ocsp_response);
+ ret->ocsp_response = os.data;
+ ret->ocsp_response_length = os.length;
+ os.data = NULL;
+ }
+
M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 01d59c4..58684b0 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -336,12 +336,6 @@
s->tlsext_debug_cb = 0;
s->tlsext_debug_arg = NULL;
s->tlsext_ticket_expected = 0;
- s->tlsext_status_type = -1;
- s->tlsext_status_expected = 0;
- s->tlsext_ocsp_ids = NULL;
- s->tlsext_ocsp_exts = NULL;
- s->tlsext_ocsp_resp = NULL;
- s->tlsext_ocsp_resplen = -1;
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->initial_ctx=ctx;
if (ctx->tlsext_ecpointformatlist)
@@ -401,7 +395,10 @@
s->psk_server_callback=ctx->psk_server_callback;
if (!s->server)
+ {
s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled;
+ s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled;
+ }
return(s);
err:
@@ -670,16 +667,6 @@
if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist);
if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist);
- if (s->tlsext_ocsp_exts)
- sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
- X509_EXTENSION_free);
- /* TODO(fork): OCSP support */
-#if 0
- if (s->tlsext_ocsp_ids)
- sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
-#endif
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
if (s->alpn_client_proto_list)
OPENSSL_free(s->alpn_client_proto_list);
if (s->tlsext_channel_id_private)
@@ -1677,7 +1664,7 @@
int SSL_enable_signed_cert_timestamps(SSL *ssl)
{
- /* Currently not implemented server side */
+ /* Currently not implemented server-side. */
if (ssl->server)
return 0;
@@ -1685,6 +1672,20 @@
return 1;
}
+void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx)
+ {
+ ctx->ocsp_stapling_enabled = 1;
+ }
+
+int SSL_enable_ocsp_stapling(SSL *ssl)
+ {
+ /* Currently not implemented server-side. */
+ if (ssl->server)
+ return 0;
+ ssl->ocsp_stapling_enabled = 1;
+ return 1;
+ }
+
void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, uint8_t **out, size_t *out_len)
{
SSL_SESSION *session = ssl->session;
@@ -1699,6 +1700,20 @@
*out_len = session->tlsext_signed_cert_timestamp_list_length;
}
+void SSL_get0_ocsp_response(const SSL *ssl, uint8_t **out, size_t *out_len)
+ {
+ SSL_SESSION *session = ssl->session;
+
+ *out_len = 0;
+ *out = NULL;
+ if (ssl->server)
+ return;
+ if (!session || !session->ocsp_response)
+ return;
+ *out = session->ocsp_response;
+ *out_len = session->ocsp_response_length;
+ }
+
/* SSL_select_next_proto implements the standard protocol selection. It is
* expected that this function is called from the callback set by
* SSL_CTX_set_next_proto_select_cb.
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 0aefaa4..ad2d843 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1069,7 +1069,6 @@
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, size_t header_len);
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit);
int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs);
-int ssl_check_clienthello_tlsext_late(SSL *s);
int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs);
int ssl_prepare_clienthello_tlsext(SSL *s);
int ssl_prepare_serverhello_tlsext(SSL *s);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index c48c64b..7fd1724 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -716,6 +716,8 @@
if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
if (ss->tlsext_signed_cert_timestamp_list != NULL)
OPENSSL_free(ss->tlsext_signed_cert_timestamp_list);
+ if (ss->ocsp_response != NULL)
+ OPENSSL_free(ss->ocsp_response);
if (ss->psk_identity_hint != NULL)
OPENSSL_free(ss->psk_identity_hint);
if (ss->psk_identity != NULL)
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index cafcfa2..8fdd813 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -121,8 +121,8 @@
static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
const unsigned char *sess_id, int sesslen,
SSL_SESSION **psess);
-static int ssl_check_clienthello_tlsext_early(SSL *s);
-int ssl_check_serverhello_tlsext(SSL *s);
+static int ssl_check_clienthello_tlsext(SSL *s);
+static int ssl_check_serverhello_tlsext(SSL *s);
SSL3_ENC_METHOD TLSv1_enc_data={
tls1_enc,
@@ -1025,56 +1025,23 @@
ret += salglen;
}
- /* TODO(fork): we probably want OCSP stapling, but it currently pulls in a lot of code. */
-#if 0
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ if (s->ocsp_stapling_enabled)
{
- int i;
- long extlen, idlen, itmp;
- OCSP_RESPID *id;
+ /* The status_request extension is excessively extensible at
+ * every layer. On the client, only support requesting OCSP
+ * responses with an empty responder_id_list and no
+ * extensions. */
+ if (limit - ret - 4 - 1 - 2 - 2 < 0) return NULL;
- idlen = 0;
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
- {
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- itmp = i2d_OCSP_RESPID(id, NULL);
- if (itmp <= 0)
- return NULL;
- idlen += itmp + 2;
- }
-
- if (s->tlsext_ocsp_exts)
- {
- extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
- if (extlen < 0)
- return NULL;
- }
- else
- extlen = 0;
-
- if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
s2n(TLSEXT_TYPE_status_request, ret);
- if (extlen + idlen > 0xFFF0)
- return NULL;
- s2n(extlen + idlen + 5, ret);
+ s2n(1 + 2 + 2, ret);
+ /* status_type */
*(ret++) = TLSEXT_STATUSTYPE_ocsp;
- s2n(idlen, ret);
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
- {
- /* save position of id len */
- unsigned char *q = ret;
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- /* skip over id len */
- ret += 2;
- itmp = i2d_OCSP_RESPID(id, &ret);
- /* write id len */
- s2n(itmp, q);
- }
- s2n(extlen, ret);
- if (extlen > 0)
- i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+ /* responder_id_list - empty */
+ s2n(0, ret);
+ /* request_extensions - empty */
+ s2n(0, ret);
}
-#endif
if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len)
{
@@ -1311,7 +1278,7 @@
s2n(0,ret);
}
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
{
if ((long)(limit - ret - 4) < 0) return NULL;
s2n(TLSEXT_TYPE_status_request,ret);
@@ -1452,8 +1419,8 @@
size_t i;
s->servername_done = 0;
- s->tlsext_status_type = -1;
s->s3->next_proto_neg_seen = 0;
+ s->s3->tmp.certificate_status_expected = 0;
if (s->s3->alpn_selected)
{
@@ -1480,23 +1447,6 @@
s->cert->pkeys[i].valid_flags = 0;
}
- /* TODO(fork): we probably want OCSP stapling support, but this pulls in
- * a lot of code. */
-#if 0
- /* Clear OCSP state. */
- s->tlsext_status_type = -1;
- if (s->tlsext_ocsp_ids)
- {
- sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
- s->tlsext_ocsp_ids = NULL;
- }
- if (s->tlsext_ocsp_exts)
- {
- sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, X509_EXTENSION_free);
- s->tlsext_ocsp_exts = NULL;
- }
-#endif
-
/* There may be no extensions. */
if (CBS_len(cbs) == 0)
{
@@ -1745,119 +1695,6 @@
}
}
- /* TODO(fork): we probably want OCSP stapling support, but this pulls in a lot of code. */
-#if 0
- else if (type == TLSEXT_TYPE_status_request)
- {
- uint8_t status_type;
- CBS responder_id_list;
- CBS request_extensions;
-
- if (!CBS_get_u8(&extension, &status_type))
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- /* Only OCSP is supported. */
- if (status_type != TLSEXT_STATUSTYPE_ocsp)
- continue;
-
- s->tlsext_status_type = status_type;
-
- /* Extension consists of a responder_id_list and
- * request_extensions. */
- if (!CBS_get_u16_length_prefixed(&extension, &responder_id_list) ||
- !CBS_get_u16_length_prefixed(&extension, &request_extensions) ||
- CBS_len(&extension) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- if (CBS_len(&responder_id_list) > 0)
- {
- s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
- if (s->tlsext_ocsp_ids == NULL)
- {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
- }
-
- /* Parse out the responder IDs. */
- while (CBS_len(&responder_id_list) > 0)
- {
- CBS responder_id;
- OCSP_RESPID *id;
- const uint8_t *data;
-
- /* Each ResponderID must have size at least 1. */
- if (!CBS_get_u16_length_prefixed(&responder_id_list, &responder_id) ||
- CBS_len(&responder_id) < 1)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- /* TODO(fork): Add CBS versions of d2i_FOO_BAR. */
- data = CBS_data(&responder_id);
- id = d2i_OCSP_RESPID(NULL, &data, CBS_len(&responder_id));
- if (!id)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!CBS_skip(&responder_id, data - CBS_data(&responder_id)))
- {
- /* This should never happen. */
- *out_alert = SSL_AD_INTERNAL_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
- if (CBS_len(&responder_id) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
-
- if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id))
- {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
- }
-
- /* Parse out request_extensions. */
- if (CBS_len(&request_extensions) > 0)
- {
- const uint8_t *data;
-
- data = CBS_data(&request_extensions);
- s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL,
- &data, CBS_len(&request_extensions));
- if (s->tlsext_ocsp_exts == NULL)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!CBS_skip(&request_extensions, data - CBS_data(&request_extensions)))
- {
- /* This should never happen. */
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
- if (CBS_len(&request_extensions) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- }
- }
-#endif
-
else if (type == TLSEXT_TYPE_next_proto_neg &&
s->s3->tmp.finish_md_len == 0 &&
s->s3->alpn_selected == NULL)
@@ -1960,7 +1797,7 @@
return 0;
}
- if (ssl_check_clienthello_tlsext_early(s) <= 0)
+ if (ssl_check_clienthello_tlsext(s) <= 0)
{
OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_tlsext, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
@@ -1993,9 +1830,13 @@
int renegotiate_seen = 0;
CBS extensions;
+ /* TODO(davidben): Move all of these to some per-handshake state that
+ * gets systematically reset on a new handshake; perhaps allocate it
+ * fresh each time so it's not even kept around post-handshake. */
s->s3->next_proto_neg_seen = 0;
- s->tlsext_ticket_expected = 0;
+ s->tlsext_ticket_expected = 0;
+ s->s3->tmp.certificate_status_expected = 0;
if (s->s3->alpn_selected)
{
@@ -2101,13 +1942,13 @@
*out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
- if (s->tlsext_status_type == -1)
+ if (!s->ocsp_stapling_enabled)
{
*out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
return 0;
}
/* Set a flag to expect a CertificateStatus message */
- s->tlsext_status_expected = 1;
+ s->s3->tmp.certificate_status_expected = 1;
}
else if (type == TLSEXT_TYPE_next_proto_neg && s->s3->tmp.finish_md_len == 0) {
unsigned char *selected;
@@ -2281,7 +2122,7 @@
return 1;
}
-static int ssl_check_clienthello_tlsext_early(SSL *s)
+static int ssl_check_clienthello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -2315,72 +2156,7 @@
}
}
-int ssl_check_clienthello_tlsext_late(SSL *s)
- {
- int ret = SSL_TLSEXT_ERR_OK;
- int al;
-
- /* If status request then ask callback what to do.
- * Note: this must be called after servername callbacks in case
- * the certificate has changed, and must be called after the cipher
- * has been chosen because this may influence which certificate is sent
- */
- if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- CERT_PKEY *certpkey;
- certpkey = ssl_get_server_send_pkey(s);
- /* If no certificate can't return certificate status */
- if (certpkey == NULL)
- {
- s->tlsext_status_expected = 0;
- return 1;
- }
- /* Set current certificate to one we will use so
- * SSL_get_certificate et al can pick it up.
- */
- s->cert->key = certpkey;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- switch (r)
- {
- /* We don't want to send a status request response */
- case SSL_TLSEXT_ERR_NOACK:
- s->tlsext_status_expected = 0;
- break;
- /* status request response should be sent */
- case SSL_TLSEXT_ERR_OK:
- if (s->tlsext_ocsp_resp)
- s->tlsext_status_expected = 1;
- else
- s->tlsext_status_expected = 0;
- break;
- /* something bad happened */
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- }
- else
- s->tlsext_status_expected = 0;
-
- err:
- switch (ret)
- {
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return -1;
-
- case SSL_TLSEXT_ERR_ALERT_WARNING:
- ssl3_send_alert(s, SSL3_AL_WARNING, al);
- return 1;
-
- default:
- return 1;
- }
- }
-
-int ssl_check_serverhello_tlsext(SSL *s)
+static int ssl_check_serverhello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -2421,35 +2197,6 @@
else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)
ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
- /* If we've requested certificate status and we wont get one
- * tell the callback
- */
- if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
- && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- /* Set resp to NULL, resplen to -1 so callback knows
- * there is no response.
- */
- if (s->tlsext_ocsp_resp)
- {
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = NULL;
- }
- s->tlsext_ocsp_resplen = -1;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- if (r == 0)
- {
- al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- if (r < 0)
- {
- al = SSL_AD_INTERNAL_ERROR;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- }
-
switch (ret)
{
case SSL_TLSEXT_ERR_ALERT_FATAL: