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>
This commit is contained in:
David Benjamin
2014-08-29 00:39:33 +00:00
committed by Adam Langley
parent e098ec2460
commit 6c7aed048c
13 changed files with 135 additions and 414 deletions
+31 -18
View File
@@ -382,6 +382,7 @@ struct ssl_method_st
* Peer SHA256 [13] EXPLICIT OCTET STRING, -- optional SHA256 hash of Peer certifiate
* original handshake hash [14] EXPLICIT OCTET STRING, -- optional original handshake hash
* tlsext_signed_cert_timestamp_list [15] EXPLICIT OCTET STRING, -- optional signed cert timestamp list extension
* ocsp_response [16] EXPLICIT OCTET STRING, -- optional saved OCSP response from the server
* }
* Look in ssl/ssl_asn1.c for more details
* I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
@@ -449,8 +450,14 @@ struct ssl_session_st
uint8_t *tlsext_tick; /* Session ticket */
size_t tlsext_ticklen; /* Session ticket length */
uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
size_t tlsext_signed_cert_timestamp_list_length;
uint8_t *tlsext_signed_cert_timestamp_list; /* Server's list. */
/* The OCSP response that came with the session. */
size_t ocsp_response_length;
uint8_t *ocsp_response;
char peer_sha256_valid; /* Non-zero if peer_sha256 is valid */
unsigned char peer_sha256[SHA256_DIGEST_LENGTH]; /* SHA256 of peer certificate */
@@ -1023,6 +1030,9 @@ struct ssl_ctx_st
/* If true, a client will request certificate timestamps. */
char signed_cert_timestamps_enabled;
/* If true, a client will request a stapled OCSP response. */
char ocsp_stapling_enabled;
};
#endif
@@ -1099,6 +1109,15 @@ OPENSSL_EXPORT int SSL_enable_signed_cert_timestamps(SSL *ssl);
* client SSL objects created from |ctx|. */
OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx);
/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
* of a connection) to request a stapled OCSP response from the server. Returns
* 1 on success. */
OPENSSL_EXPORT int SSL_enable_ocsp_stapling(SSL *ssl);
/* SSL_CTX_enable_ocsp_stapling enables OCSP stapling on all client SSL objects
* created from |ctx|. */
OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx);
/* SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to
* |*out_len| bytes of SCT information from the server. This is only valid if
* |ssl| is a client. The SCT information is a SignedCertificateTimestampList
@@ -1109,6 +1128,13 @@ OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx);
* WARNING: the returned data is not guaranteed to be well formed. */
OPENSSL_EXPORT void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, uint8_t **out, size_t *out_len);
/* SSL_get0_ocsp_response sets |*out| and |*out_len| to point to |*out_len|
* bytes of an OCSP response from the server. This is the DER encoding of an
* OCSPResponse type as defined in RFC 2560.
*
* WARNING: the returned data is not guaranteed to be well formed. */
OPENSSL_EXPORT void SSL_get0_ocsp_response(const SSL *ssl, uint8_t **out, size_t *out_len);
OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
int (*cb) (SSL *ssl,
const unsigned char **out,
@@ -1354,17 +1380,6 @@ struct ssl_st
1 : prepare 2, allow last ack just after in server callback.
2 : don't call servername callback, no ack in server hello
*/
/* certificate status request info */
/* Status type or -1 if no status type */
int tlsext_status_type;
/* Expect OCSP CertificateStatus message */
int tlsext_status_expected;
/* OCSP status request only */
STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
X509_EXTENSIONS *tlsext_ocsp_exts;
/* OCSP response received or to be sent */
uint8_t *tlsext_ocsp_resp;
int tlsext_ocsp_resplen;
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
@@ -1409,6 +1424,11 @@ struct ssl_st
/* Enable signed certificate time stamps. Currently client only. */
char signed_cert_timestamps_enabled;
/* Enable OCSP stapling. Currently client only.
* TODO(davidben): Add a server-side implementation when it becomes
* necesary. */
char ocsp_stapling_enabled;
/* For a client, this contains the list of supported protocols in wire
* format. */
unsigned char* alpn_client_proto_list;
@@ -1648,13 +1668,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
+5
View File
@@ -469,6 +469,11 @@ typedef struct ssl3_state_st
/* Server-only: cert_request is true if a client certificate was
* requested. */
int cert_request;
/* certificate_status_expected is true if OCSP stapling was
* negotiated and the server is expected to send a
* CertificateStatus message. */
char certificate_status_expected;
} tmp;
/* Connection binding to prevent renegotiation attacks */
-21
View File
@@ -333,27 +333,6 @@ SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
#define SSL_set_tlsext_debug_arg(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
#define SSL_set_tlsext_status_type(ssl, type) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
#define SSL_get_tlsext_status_exts(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
#define SSL_set_tlsext_status_exts(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
#define SSL_get_tlsext_status_ids(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
#define SSL_set_tlsext_status_ids(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
+1 -1
View File
@@ -309,7 +309,7 @@ int dtls1_connect(SSL *s)
{
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;
+4 -2
View File
@@ -359,7 +359,7 @@ int dtls1_accept(SSL *s)
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 @@ int dtls1_accept(SSL *s)
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 @@ int dtls1_accept(SSL *s)
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:
+3 -25
View File
@@ -299,7 +299,7 @@ int ssl3_connect(SSL *s)
{
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 @@ int ssl3_get_cert_status(SSL *s)
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 @@ int ssl3_get_cert_status(SSL *s)
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);
-38
View File
@@ -1252,44 +1252,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
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,
+6 -11
View File
@@ -352,7 +352,7 @@ int ssl3_accept(SSL *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;
@@ -569,6 +569,8 @@ int ssl3_accept(SSL *s)
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 @@ int ssl3_accept(SSL *s)
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 @@ int ssl3_get_client_hello(SSL *s)
* 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 @@ int ssl3_send_new_session_ticket(SSL *s)
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 @@ int ssl3_send_cert_status(SSL *s)
/* 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 */
+25 -1
View File
@@ -120,12 +120,13 @@ typedef struct ssl_session_asn1_st
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 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
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 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
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 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
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 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
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);
}
+32 -17
View File
@@ -336,12 +336,6 @@ SSL *SSL_new(SSL_CTX *ctx)
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 @@ SSL *SSL_new(SSL_CTX *ctx)
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 @@ void SSL_free(SSL *s)
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 @@ void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx)
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 @@ int SSL_enable_signed_cert_timestamps(SSL *ssl)
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 @@ void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, uint8_t **out, size_t *
*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.
-1
View File
@@ -1069,7 +1069,6 @@ int tls1_shared_list(SSL *s,
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);
+2
View File
@@ -716,6 +716,8 @@ void SSL_SESSION_free(SSL_SESSION *ss)
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)
+26 -279
View File
@@ -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 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
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 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
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 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
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 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
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 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
}
}
/* 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 @@ int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs)
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 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
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 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
*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 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
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 @@ static int ssl_check_clienthello_tlsext_early(SSL *s)
}
}
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 @@ int ssl_check_serverhello_tlsext(SSL *s)
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: