Provide a key_share extension finaliser
This mops up various edge cases with key_shares and makes sure we still generate the handshake secret if we haven't been provided with one but we have a PSK. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2259)
This commit is contained in:
parent
4ff65f77b6
commit
f4bbb37c4c
5 changed files with 45 additions and 11 deletions
|
@ -2097,6 +2097,7 @@ int ERR_load_SSL_strings(void);
|
|||
# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 386
|
||||
# define SSL_F_FINAL_EC_PT_FORMATS 485
|
||||
# define SSL_F_FINAL_EMS 486
|
||||
# define SSL_F_FINAL_KEY_SHARE 503
|
||||
# define SSL_F_FINAL_RENEGOTIATE 483
|
||||
# define SSL_F_FINAL_SIG_ALGS 497
|
||||
# define SSL_F_NSS_KEYLOG_INT 500
|
||||
|
|
|
@ -51,6 +51,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
|
|||
{ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
|
||||
{ERR_FUNC(SSL_F_FINAL_EC_PT_FORMATS), "final_ec_pt_formats"},
|
||||
{ERR_FUNC(SSL_F_FINAL_EMS), "final_ems"},
|
||||
{ERR_FUNC(SSL_F_FINAL_KEY_SHARE), "final_key_share"},
|
||||
{ERR_FUNC(SSL_F_FINAL_RENEGOTIATE), "final_renegotiate"},
|
||||
{ERR_FUNC(SSL_F_FINAL_SIG_ALGS), "final_sig_algs"},
|
||||
{ERR_FUNC(SSL_F_NSS_KEYLOG_INT), "nss_keylog_int"},
|
||||
|
|
|
@ -36,6 +36,7 @@ static int init_etm(SSL *s, unsigned int context);
|
|||
static int init_ems(SSL *s, unsigned int context);
|
||||
static int final_ems(SSL *s, unsigned int context, int sent, int *al);
|
||||
static int init_psk_kex_modes(SSL *s, unsigned int context);
|
||||
static int final_key_share(SSL *s, unsigned int context, int sent, int *al);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
static int init_srtp(SSL *s, unsigned int context);
|
||||
#endif
|
||||
|
@ -252,7 +253,8 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
| EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| EXT_TLS1_3_ONLY,
|
||||
NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share,
|
||||
tls_construct_stoc_key_share, tls_construct_ctos_key_share, NULL
|
||||
tls_construct_stoc_key_share, tls_construct_ctos_key_share,
|
||||
final_key_share
|
||||
},
|
||||
{
|
||||
/*
|
||||
|
@ -955,6 +957,45 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
|
||||
{
|
||||
if (!SSL_IS_TLS13(s))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* If
|
||||
* we have no key_share
|
||||
* AND
|
||||
* (we are not resuming
|
||||
* OR the kex_mode doesn't allow non key_share resumes)
|
||||
* THEN
|
||||
* fail
|
||||
*/
|
||||
if (((s->server && s->s3->peer_tmp == NULL) || (!s->server && !sent))
|
||||
&& (!s->hit
|
||||
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
|
||||
/* No suitable share */
|
||||
/* TODO(TLS1.3): Send a HelloRetryRequest */
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a client side resumption with no key_share we need to generate
|
||||
* the handshake secret (otherwise this is done during key_share
|
||||
* processing).
|
||||
*/
|
||||
if (!sent && !s->server && !tls13_generate_handshake_secret(s, NULL, 0)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_psk_kex_modes(SSL *s, unsigned int context)
|
||||
{
|
||||
s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
|
||||
|
|
|
@ -523,7 +523,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
|
|||
int group_nid, found = 0;
|
||||
unsigned int curve_flags;
|
||||
|
||||
if (s->hit)
|
||||
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
|
||||
return 1;
|
||||
|
||||
/* Sanity check */
|
||||
|
|
|
@ -1557,15 +1557,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
|||
goto f_err;
|
||||
}
|
||||
|
||||
/* Check we've got a key_share for TLSv1.3 */
|
||||
if (SSL_IS_TLS13(s) && s->s3->peer_tmp == NULL && !s->hit) {
|
||||
/* No suitable share */
|
||||
/* TODO(TLS1.3): Send a HelloRetryRequest */
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SUITABLE_KEY_SHARE);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we want to use external pre-shared secret for this handshake
|
||||
* for not reused session only. We need to generate server_random before
|
||||
|
|
Loading…
Reference in a new issue