Fix the cookie/key_share extensions for use with SSL_stateless()

Fixes some bugs identified during testing.

Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4435)
This commit is contained in:
Matt Caswell 2017-09-28 13:25:23 +01:00
parent d6bb50a5f9
commit dd77962e09

View file

@ -696,7 +696,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx) size_t chainidx)
{ {
unsigned int format, version, key_share; unsigned int format, version, key_share, group_id;
EVP_MD_CTX *hctx; EVP_MD_CTX *hctx;
EVP_PKEY *pkey; EVP_PKEY *pkey;
PACKET cookie, raw, chhash, appcookie; PACKET cookie, raw, chhash, appcookie;
@ -789,21 +789,27 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0; return 0;
} }
if (!PACKET_get_net_2(&cookie, &s->s3->group_id)) { if (!PACKET_get_net_2(&cookie, &group_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH); SSL_R_LENGTH_MISMATCH);
return 0; return 0;
} }
ciphdata = PACKET_data(&cookie); ciphdata = PACKET_data(&cookie);
if (!PACKET_forward(&cookie, 2)) { if (!PACKET_forward(&cookie, 2)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH); SSL_R_LENGTH_MISMATCH);
return 0; return 0;
} }
s->s3->tmp.new_cipher = ssl_get_cipher_by_char(s, ciphdata, 0); if (group_id != s->s3->group_id
if (s->s3->tmp.new_cipher == NULL) { || s->s3->tmp.new_cipher
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, != ssl_get_cipher_by_char(s, ciphdata, 0)) {
ERR_R_INTERNAL_ERROR); /*
* We chose a different cipher or group id this time around to what is
* in the cookie. Something must have changed.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_BAD_CIPHER);
return 0; return 0;
} }
@ -1497,23 +1503,26 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
size_t encoded_pt_len = 0; size_t encoded_pt_len = 0;
EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL; EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
if (ckey == NULL) { if (s->hello_retry_request == SSL_HRR_PENDING) {
/* No key_share received from client */ if (ckey != NULL) {
if (s->hello_retry_request == SSL_HRR_PENDING) { /* Original key_share was acceptable so don't ask for another one */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) return EXT_RETURN_NOT_SENT;
|| !WPACKET_start_sub_packet_u16(pkt) }
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id) if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_close(pkt)) { || !WPACKET_start_sub_packet_u16(pkt)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, || !WPACKET_close(pkt)) {
ERR_R_INTERNAL_ERROR); SSLfatal(s, SSL_AD_INTERNAL_ERROR,
return EXT_RETURN_FAIL; SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
} ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
return EXT_RETURN_SENT;
} }
/* Must be resuming. */ return EXT_RETURN_SENT;
}
if (ckey == NULL) {
/* No key_share received from client - must be resuming */
if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) { if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);