X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fstatem_clnt.c;h=abddc0ace375f7da3b69c3cc50785b28937d1ad4;hp=80ae480b12103e12b4f8010110ad6b7762c78957;hb=c19602b543562104b756aa6adec9bd5081207574;hpb=2faa1b48fd6864f6bb8f992fd638378202fdd416 diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 80ae480b12..abddc0ace3 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -48,6 +48,7 @@ */ #include +#include #include "../ssl_locl.h" #include "statem_locl.h" #include @@ -59,6 +60,7 @@ #include #include +static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt); static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt); static ossl_inline int cert_req_allowed(SSL *s); @@ -136,6 +138,17 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt) default: break; + case TLS_ST_CW_CLNT_HELLO: + /* + * This must a ClientHello following a HelloRetryRequest, so the only + * thing we can get now is a ServerHello. + */ + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + break; + case TLS_ST_CR_SRVR_HELLO: if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) { st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS; @@ -181,6 +194,17 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt) return 1; } break; + + case TLS_ST_OK: + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + if (mt == SSL3_MT_KEY_UPDATE) { + st->hand_state = TLS_ST_CR_KEY_UPDATE; + return 1; + } + break; } /* No valid transition found */ @@ -202,8 +226,8 @@ int ossl_statem_client_read_transition(SSL *s, int mt) int ske_expected; /* - * Note that after a ClientHello we don't know what version we are going - * to negotiate yet, so we don't take this branch until later + * Note that after writing the first ClientHello we don't know what version + * we are going to negotiate yet, so we don't take this branch until later. */ if (SSL_IS_TLS13(s)) { if (!ossl_statem_client13_read_transition(s, mt)) @@ -226,6 +250,11 @@ int ossl_statem_client_read_transition(SSL *s, int mt) st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST; return 1; } + } else { + if (mt == SSL3_MT_HELLO_RETRY_REQUEST) { + st->hand_state = TLS_ST_CR_HELLO_RETRY_REQUEST; + return 1; + } } break; @@ -351,6 +380,13 @@ int ossl_statem_client_read_transition(SSL *s, int mt) return 1; } break; + + case TLS_ST_OK: + if (mt == SSL3_MT_HELLO_REQUEST) { + st->hand_state = TLS_ST_CR_HELLO_REQ; + return 1; + } + break; } err: @@ -370,20 +406,23 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s) OSSL_STATEM *st = &s->statem; /* - * TODO(TLS1.3): This is still based on the TLSv1.2 state machine. Over time - * we will update this to look more like real TLSv1.3 - */ - - /* - * Note: There are no cases for TLS_ST_BEFORE or TLS_ST_CW_CLNT_HELLO, - * because we haven't negotiated TLSv1.3 yet at that point. They are - * handled by ossl_statem_client_write_transition(). + * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated + * TLSv1.3 yet at that point. They are handled by + * ossl_statem_client_write_transition(). */ switch (st->hand_state) { default: /* Shouldn't happen */ return WRITE_TRAN_ERROR; + case TLS_ST_CW_CLNT_HELLO: + /* We only hit this in the case of HelloRetryRequest */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_CR_HELLO_RETRY_REQUEST: + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + case TLS_ST_CR_FINISHED: st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT : TLS_ST_CW_FINISHED; @@ -399,10 +438,28 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s) st->hand_state = TLS_ST_CW_FINISHED; return WRITE_TRAN_CONTINUE; + case TLS_ST_CR_KEY_UPDATE: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_CW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_CW_KEY_UPDATE: + case TLS_ST_CR_SESSION_TICKET: case TLS_ST_CW_FINISHED: st->hand_state = TLS_ST_OK; ossl_statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; + + case TLS_ST_OK: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_CW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + + /* Try to read from the server instead */ + return WRITE_TRAN_FINISHED; } } @@ -428,6 +485,13 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s) return WRITE_TRAN_ERROR; case TLS_ST_OK: + if (!s->renegotiate) { + /* + * We haven't requested a renegotiation ourselves so we must have + * received a message from the server. Better read it. + */ + return WRITE_TRAN_FINISHED; + } /* Renegotiation - fall through */ case TLS_ST_BEFORE: st->hand_state = TLS_ST_CW_CLNT_HELLO; @@ -515,6 +579,23 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s) ossl_statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; } + + case TLS_ST_CR_HELLO_REQ: + /* + * If we can renegotiate now then do so, otherwise wait for a more + * convenient time. + */ + if (ssl3_renegotiate_check(s, 1)) { + if (!tls_setup_handshake(s)) { + ossl_statem_set_error(s); + return WRITE_TRAN_ERROR; + } + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + } + st->hand_state = TLS_ST_OK; + ossl_statem_set_in_init(s, 0); + return WRITE_TRAN_CONTINUE; } } @@ -559,7 +640,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst) break; case TLS_ST_OK: - return tls_finish_handshake(s, wst); + return tls_finish_handshake(s, wst, 1); } return WORK_FINISHED_CONTINUE; @@ -568,8 +649,6 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst) /* * Perform any work that needs to be done after sending a message from the * client to the server. - case TLS_ST_SR_CERT_VRFY: - return SSL3_RT_MAX_PLAIN_LENGTH; */ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst) { @@ -650,6 +729,13 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst) return WORK_ERROR; } break; + + case TLS_ST_CW_KEY_UPDATE: + if (statem_flush(s) != 1) + return WORK_MORE_A; + if (!tls13_update_key(s, 1)) + return WORK_ERROR; + break; } return WORK_FINISHED_CONTINUE; @@ -711,6 +797,11 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt, *confunc = tls_construct_finished; *mt = SSL3_MT_FINISHED; break; + + case TLS_ST_CW_KEY_UPDATE: + *confunc = tls_construct_key_update; + *mt = SSL3_MT_KEY_UPDATE; + break; } return 1; @@ -735,6 +826,9 @@ size_t ossl_statem_client_max_message_size(SSL *s) case DTLS_ST_CR_HELLO_VERIFY_REQUEST: return HELLO_VERIFY_REQUEST_MAX_LENGTH; + case TLS_ST_CR_HELLO_RETRY_REQUEST: + return HELLO_RETRY_REQUEST_MAX_LENGTH; + case TLS_ST_CR_CERT: return s->max_cert_list; @@ -771,6 +865,9 @@ size_t ossl_statem_client_max_message_size(SSL *s) case TLS_ST_CR_ENCRYPTED_EXTENSIONS: return ENCRYPTED_EXTENSIONS_MAX_LENGTH; + + case TLS_ST_CR_KEY_UPDATE: + return KEY_UPDATE_MAX_LENGTH; } } @@ -792,6 +889,9 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt) case DTLS_ST_CR_HELLO_VERIFY_REQUEST: return dtls_process_hello_verify(s, pkt); + case TLS_ST_CR_HELLO_RETRY_REQUEST: + return tls_process_hello_retry_request(s, pkt); + case TLS_ST_CR_CERT: return tls_process_server_certificate(s, pkt); @@ -819,8 +919,14 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt) case TLS_ST_CR_FINISHED: return tls_process_finished(s, pkt); + case TLS_ST_CR_HELLO_REQ: + return tls_process_hello_req(s, pkt); + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: return tls_process_encrypted_extensions(s, pkt); + + case TLS_ST_CR_KEY_UPDATE: + return tls_process_key_update(s, pkt); } } @@ -893,6 +999,9 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) } /* else use the pre-loaded session */ + /* This is a real handshake so make sure we clean it up at the end */ + s->statem.cleanuphand = 1; + p = s->s3->client_random; /* @@ -954,7 +1063,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) } /* Session ID */ - if (s->new_session) + if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) sess_id_len = 0; else sess_id_len = s->session->session_id_length; @@ -996,7 +1105,9 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) return 0; } #ifndef OPENSSL_NO_COMP - if (ssl_allow_compression(s) && s->ctx->comp_methods) { + if (ssl_allow_compression(s) + && s->ctx->comp_methods + && (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) { int compnum = sk_SSL_COMP_num(s->ctx->comp_methods); for (i = 0; i < compnum; i++) { comp = sk_SSL_COMP_value(s->ctx->comp_methods, i); @@ -1080,6 +1191,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) goto f_err; } + /* We do this immediately so we know what format the ServerHello is in */ protverr = ssl_choose_client_version(s, sversion); if (protverr != 0) { al = SSL_AD_PROTOCOL_VERSION; @@ -1095,8 +1207,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) goto f_err; } - s->hit = 0; - /* Get the session-id. */ if (!SSL_IS_TLS13(s)) { if (!PACKET_get_length_prefixed_1(pkt, &session_id)) { @@ -1123,63 +1233,103 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) goto f_err; } - /* - * Check if we can resume the session based on external pre-shared secret. - * EAP-FAST (RFC 4851) supports two types of session resumption. - * Resumption based on server-side state works with session IDs. - * Resumption based on pre-shared Protected Access Credentials (PACs) - * works by overriding the SessionTicket extension at the application - * layer, and does not send a session ID. (We do not know whether EAP-FAST - * servers would honour the session ID.) Therefore, the session ID alone - * is not a reliable indicator of session resumption, so we first check if - * we can resume, and later peek at the next handshake message to see if the - * server wants to resume. - */ - if (s->version >= TLS1_VERSION && !SSL_IS_TLS13(s) - && s->ext.session_secret_cb != NULL && s->session->ext.tick) { - const SSL_CIPHER *pref_cipher = NULL; + if (!SSL_IS_TLS13(s)) { + if (!PACKET_get_1(pkt, &compression)) { + SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + } else { + compression = 0; + } + + /* TLS extensions */ + if (PACKET_remaining(pkt) == 0) { + PACKET_null_init(&extpkt); + } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_LENGTH); + goto f_err; + } + + context = SSL_IS_TLS13(s) ? EXT_TLS1_3_SERVER_HELLO + : EXT_TLS1_2_SERVER_HELLO; + if (!tls_collect_extensions(s, &extpkt, context, &extensions, &al, NULL)) + goto f_err; + + s->hit = 0; + + if (SSL_IS_TLS13(s)) { + /* This will set s->hit if we are resuming */ + if (!tls_parse_extension(s, TLSEXT_IDX_psk, + EXT_TLS1_3_SERVER_HELLO, + extensions, NULL, 0, &al)) + goto f_err; + } else { /* - * s->session->master_key_length is a size_t, but this is an int for - * backwards compat reasons + * Check if we can resume the session based on external pre-shared + * secret. EAP-FAST (RFC 4851) supports two types of session resumption. + * Resumption based on server-side state works with session IDs. + * Resumption based on pre-shared Protected Access Credentials (PACs) + * works by overriding the SessionTicket extension at the application + * layer, and does not send a session ID. (We do not know whether + * EAP-FAST servers would honour the session ID.) Therefore, the session + * ID alone is not a reliable indicator of session resumption, so we + * first check if we can resume, and later peek at the next handshake + * message to see if the server wants to resume. */ - int master_key_length; - master_key_length = sizeof(s->session->master_key); - if (s->ext.session_secret_cb(s, s->session->master_key, - &master_key_length, - NULL, &pref_cipher, - s->ext.session_secret_cb_arg) - && master_key_length > 0) { - s->session->master_key_length = master_key_length; - s->session->cipher = pref_cipher ? - pref_cipher : ssl_get_cipher_by_char(s, cipherchars); - } else { - SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; + if (s->version >= TLS1_VERSION + && s->ext.session_secret_cb != NULL && s->session->ext.tick) { + const SSL_CIPHER *pref_cipher = NULL; + /* + * s->session->master_key_length is a size_t, but this is an int for + * backwards compat reasons + */ + int master_key_length; + master_key_length = sizeof(s->session->master_key); + if (s->ext.session_secret_cb(s, s->session->master_key, + &master_key_length, + NULL, &pref_cipher, + s->ext.session_secret_cb_arg) + && master_key_length > 0) { + s->session->master_key_length = master_key_length; + s->session->cipher = pref_cipher ? + pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0); + } else { + SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } } + + if (session_id_len != 0 + && session_id_len == s->session->session_id_length + && memcmp(PACKET_data(&session_id), s->session->session_id, + session_id_len) == 0) + s->hit = 1; } - if (session_id_len != 0 && session_id_len == s->session->session_id_length - && memcmp(PACKET_data(&session_id), s->session->session_id, - session_id_len) == 0) { + if (s->hit) { if (s->sid_ctx_length != s->session->sid_ctx_length - || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { + || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { /* actually a client application bug */ al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); goto f_err; } - s->hit = 1; } else { /* * If we were trying for session-id reuse but the server - * didn't echo the ID, make a new SSL_SESSION. + * didn't resume, make a new SSL_SESSION. * In the case of EAP-FAST and PAC, we do not send a session ID, * so the PAC-based session secret is always preserved. It'll be * overwritten if the server refuses resumption. */ - if (s->session->session_id_length > 0) { + if (s->session->session_id_length > 0 + || (SSL_IS_TLS13(s) + && s->session->ext.tick_identity + != TLSEXT_PSK_BAD_IDENTITY)) { s->ctx->stats.sess_miss++; if (!ssl_get_new_session(s, 0)) { goto f_err; @@ -1203,7 +1353,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) goto f_err; } - c = ssl_get_cipher_by_char(s, cipherchars); + c = ssl_get_cipher_by_char(s, cipherchars, 0); if (c == NULL) { /* unknown cipher */ al = SSL_AD_ILLEGAL_PARAMETER; @@ -1249,17 +1399,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) goto f_err; } s->s3->tmp.new_cipher = c; - /* lets get the compression algorithm */ - /* COMPRESSION */ - if (!SSL_IS_TLS13(s)) { - if (!PACKET_get_1(pkt, &compression)) { - SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - } else { - compression = 0; - } #ifdef OPENSSL_NO_COMP if (compression != 0) { @@ -1303,19 +1442,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) } #endif - /* TLS extensions */ - if (PACKET_remaining(pkt) == 0) { - PACKET_null_init(&extpkt); - } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_LENGTH); - goto f_err; - } - - context = SSL_IS_TLS13(s) ? EXT_TLS1_3_SERVER_HELLO - : EXT_TLS1_2_SERVER_HELLO; - if (!tls_collect_extensions(s, &extpkt, context, &extensions, &al) - || !tls_parse_all_extensions(s, context, extensions, NULL, 0, &al)) + if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, &al)) goto f_err; #ifndef OPENSSL_NO_SCTP @@ -1366,6 +1493,52 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) return MSG_PROCESS_ERROR; } +static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt) +{ + unsigned int sversion; + int errorcode; + RAW_EXTENSION *extensions = NULL; + int al; + PACKET extpkt; + + if (!PACKET_get_net_2(pkt, &sversion)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + + s->hello_retry_request = 1; + + /* This will fail if it doesn't choose TLSv1.3+ */ + errorcode = ssl_choose_client_version(s, sversion); + if (errorcode != 0) { + al = SSL_AD_PROTOCOL_VERSION; + SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, errorcode); + goto f_err; + } + + if (!PACKET_as_length_prefixed_2(pkt, &extpkt)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_BAD_LENGTH); + goto f_err; + } + + if (!tls_collect_extensions(s, &extpkt, EXT_TLS1_3_HELLO_RETRY_REQUEST, + &extensions, &al, NULL) + || !tls_parse_all_extensions(s, EXT_TLS1_3_HELLO_RETRY_REQUEST, + extensions, NULL, 0, &al)) + goto f_err; + + OPENSSL_free(extensions); + + return MSG_PROCESS_FINISHED_READING; + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + ossl_statem_set_error(s); + OPENSSL_free(extensions); + return MSG_PROCESS_ERROR; +} + MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt) { int al, i, ret = MSG_PROCESS_ERROR, exp_idx; @@ -1423,10 +1596,13 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt) goto f_err; } if (!tls_collect_extensions(s, &extensions, EXT_TLS1_3_CERTIFICATE, - &rawexts, &al) + &rawexts, &al, NULL) || !tls_parse_all_extensions(s, EXT_TLS1_3_CERTIFICATE, - rawexts, x, chainidx, &al)) + rawexts, x, chainidx, &al)) { + OPENSSL_free(rawexts); goto f_err; + } + OPENSSL_free(rawexts); } if (!sk_X509_push(sk, x)) { @@ -1493,17 +1669,23 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt) SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto f_err; } - - exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); - if (exp_idx >= 0 && i != exp_idx - && (exp_idx != SSL_PKEY_GOST_EC || - (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256 - && i != SSL_PKEY_GOST01))) { - x = NULL; - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, - SSL_R_WRONG_CERTIFICATE_TYPE); - goto f_err; + /* + * Check certificate type is consistent with ciphersuite. For TLS 1.3 + * skip check since TLS 1.3 ciphersuites can be used with any certificate + * type. + */ + if (!SSL_IS_TLS13(s)) { + exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (exp_idx >= 0 && i != exp_idx + && (exp_idx != SSL_PKEY_GOST_EC || + (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256 + && i != SSL_PKEY_GOST01))) { + x = NULL; + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto f_err; + } } s->session->peer_type = i; @@ -1637,6 +1819,8 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) DH *dh = NULL; BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL; + int check_bits = 0; + if (!PACKET_get_length_prefixed_2(pkt, &prime) || !PACKET_get_length_prefixed_2(pkt, &generator) || !PACKET_get_length_prefixed_2(pkt, &pub_key)) { @@ -1666,7 +1850,8 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) goto err; } - if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) { + /* test non-zero pupkey */ + if (BN_is_zero(bnpub_key)) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE); goto err; @@ -1679,6 +1864,12 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) } p = g = NULL; + if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) { + *al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE); + goto err; + } + if (!DH_set0_key(dh, bnpub_key, NULL)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB); @@ -1824,7 +2015,7 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al) MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) { - int al = -1, ispss = 0; + int al = -1; long alg_k; EVP_PKEY *pkey = NULL; EVP_MD_CTX *md_ctx = NULL; @@ -1889,7 +2080,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto err; } - rv = tls12_check_peer_sigalg(&md, s, sigalg, pkey); + rv = tls12_check_peer_sigalg(s, sigalg, pkey); if (rv == -1) { al = SSL_AD_INTERNAL_ERROR; goto err; @@ -1897,16 +2088,16 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) al = SSL_AD_DECODE_ERROR; goto err; } - ispss = SIGID_IS_PSS(sigalg); #ifdef SSL_DEBUG fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); #endif - } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { - md = EVP_md5_sha1(); - } else { - md = EVP_sha1(); + } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { + al = SSL_AD_INTERNAL_ERROR; + goto err; } + md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx); + if (!PACKET_get_length_prefixed_2(pkt, &signature) || PACKET_remaining(pkt) != 0) { al = SSL_AD_DECODE_ERROR; @@ -1943,10 +2134,10 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB); goto err; } - if (ispss) { + if (SSL_USE_PSS(s)) { if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 - /* -1 here means set saltlen to the digest len */ - || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0) { + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB); goto err; @@ -2005,39 +2196,46 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) { int ret = MSG_PROCESS_ERROR; - unsigned int list_len, ctype_num, i, name_len; + unsigned int i, name_len; X509_NAME *xn = NULL; - const unsigned char *data; const unsigned char *namestart, *namebytes; STACK_OF(X509_NAME) *ca_sk = NULL; + PACKET cadns; if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) { SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); goto err; } - /* get the certificate types */ - if (!PACKET_get_1(pkt, &ctype_num) - || !PACKET_get_bytes(pkt, &data, ctype_num)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); - goto err; - } - OPENSSL_free(s->cert->ctypes); - s->cert->ctypes = NULL; - if (ctype_num > SSL3_CT_NUMBER) { - /* If we exceed static buffer copy all to cert structure */ - s->cert->ctypes = OPENSSL_malloc(ctype_num); - if (s->cert->ctypes == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); + if (SSL_IS_TLS13(s)) { + PACKET reqctx; + + /* Free and zero certificate types: it is not present in TLS 1.3 */ + OPENSSL_free(s->s3->tmp.ctype); + s->s3->tmp.ctype = NULL; + s->s3->tmp.ctype_len = 0; + /* TODO(TLS1.3) need to process request context, for now ignore */ + if (!PACKET_get_length_prefixed_1(pkt, &reqctx)) { + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } else { + PACKET ctypes; + + /* get the certificate types */ + if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) { + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); goto err; } - memcpy(s->cert->ctypes, data, ctype_num); - s->cert->ctype_num = ctype_num; - ctype_num = SSL3_CT_NUMBER; } - for (i = 0; i < ctype_num; i++) - s->s3->tmp.ctype[i] = data[i]; if (SSL_USE_SIGALGS(s)) { PACKET sigalgs; @@ -2049,11 +2247,9 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) goto err; } - /* Clear certificate digests and validity flags */ - for (i = 0; i < SSL_PKEY_NUM; i++) { - s->s3->tmp.md[i] = NULL; + /* Clear certificate validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) s->s3->tmp.valid_flags[i] = 0; - } if (!tls1_save_sigalgs(s, &sigalgs)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, @@ -2065,21 +2261,18 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); goto err; } - } else { - ssl_set_default_md(s); } /* get the CA RDNs */ - if (!PACKET_get_net_2(pkt, &list_len) - || PACKET_remaining(pkt) != list_len) { + if (!PACKET_get_length_prefixed_2(pkt, &cadns)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); goto err; } - while (PACKET_remaining(pkt)) { - if (!PACKET_get_net_2(pkt, &name_len) - || !PACKET_get_bytes(pkt, &namebytes, name_len)) { + while (PACKET_remaining(&cadns)) { + if (!PACKET_get_net_2(&cadns, &name_len) + || !PACKET_get_bytes(&cadns, &namebytes, name_len)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); @@ -2107,10 +2300,26 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) } xn = NULL; } + /* TODO(TLS1.3) need to parse and process extensions, for now ignore */ + if (SSL_IS_TLS13(s)) { + PACKET reqexts; + + if (!PACKET_get_length_prefixed_2(pkt, &reqexts)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_EXT_LENGTH_MISMATCH); + goto err; + } + } + + if (PACKET_remaining(pkt) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); + goto err; + } /* we should setup a certificate to return.... */ s->s3->tmp.cert_req = 1; - s->s3->tmp.ctype_num = ctype_num; sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); s->s3->tmp.ca_names = ca_sk; ca_sk = NULL; @@ -2132,23 +2341,31 @@ static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b) MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt) { - int al; + int al = SSL_AD_DECODE_ERROR; unsigned int ticklen; - unsigned long ticket_lifetime_hint; + unsigned long ticket_lifetime_hint, age_add = 0; unsigned int sess_len; + RAW_EXTENSION *exts = NULL; if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint) + || (SSL_IS_TLS13(s) && !PACKET_get_net_4(pkt, &age_add)) || !PACKET_get_net_2(pkt, &ticklen) - || PACKET_remaining(pkt) != ticklen) { - al = SSL_AD_DECODE_ERROR; + || (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) != ticklen) + || (SSL_IS_TLS13(s) + && (ticklen == 0 || PACKET_remaining(pkt) < ticklen))) { SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH); goto f_err; } - /* Server is allowed to change its mind and send an empty ticket. */ + /* + * Server is allowed to change its mind (in <=TLSv1.2) and send an empty + * ticket. We already checked this TLSv1.3 case above, so it should never + * be 0 here in that instance + */ if (ticklen == 0) return MSG_PROCESS_CONTINUE_READING; + /* TODO(TLS1.3): Is this a suitable test for TLS1.3? */ if (s->session->session_id_length > 0) { int i = s->session_ctx->session_cache_mode; SSL_SESSION *new_sess; @@ -2173,6 +2390,12 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt) s->session = new_sess; } + /* + * Technically the cast to long here is not guaranteed by the C standard - + * but we use it elsewhere, so this should be ok. + */ + s->session->time = (long)time(NULL); + OPENSSL_free(s->session->ext.tick); s->session->ext.tick = NULL; s->session->ext.ticklen = 0; @@ -2189,7 +2412,23 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt) } s->session->ext.tick_lifetime_hint = ticket_lifetime_hint; + s->session->ext.tick_age_add = age_add; s->session->ext.ticklen = ticklen; + + if (SSL_IS_TLS13(s)) { + PACKET extpkt; + + if (!PACKET_as_length_prefixed_2(pkt, &extpkt) + || !tls_collect_extensions(s, &extpkt, + EXT_TLS1_3_NEW_SESSION_TICKET, + &exts, &al, NULL) + || !tls_parse_all_extensions(s, EXT_TLS1_3_NEW_SESSION_TICKET, + exts, NULL, 0, &al)) { + SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_BAD_EXTENSION); + goto f_err; + } + } + /* * There are two ways to detect a resumed ticket session. One is to set * an appropriate session ID and then the server must return a match in @@ -2212,11 +2451,20 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt) goto err; } s->session->session_id_length = sess_len; + + /* This is a standalone message in TLSv1.3, so there is no more to read */ + if (SSL_IS_TLS13(s)) { + OPENSSL_free(exts); + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + return MSG_PROCESS_FINISHED_READING; + } + return MSG_PROCESS_CONTINUE_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: ossl_statem_set_error(s); + OPENSSL_free(exts); return MSG_PROCESS_ERROR; } @@ -2506,12 +2754,6 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al) } EVP_PKEY_CTX_free(pctx); pctx = NULL; -# ifdef PKCS1_CHECK - if (s->options & SSL_OP_PKCS1_CHECK_1) - (*p)[1]++; - if (s->options & SSL_OP_PKCS1_CHECK_2) - tmp_buf[0] = 0x70; -# endif /* Fix buf for TLS and beyond */ if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) { @@ -2890,10 +3132,8 @@ int tls_client_key_exchange_post_work(SSL *s) */ static int ssl3_check_client_certificate(SSL *s) { - if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey) - return 0; /* If no suitable signature algorithm can't use certificate */ - if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys]) + if (!tls_choose_sigalg(s, NULL) || s->s3->tmp.sigalg == NULL) return 0; /* * If strict mode check suitability of chain before using it. This also @@ -3100,6 +3340,31 @@ int tls_construct_next_proto(SSL *s, WPACKET *pkt) } #endif +MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) > 0) { + /* should contain no data */ + SSLerr(SSL_F_TLS_PROCESS_HELLO_REQ, SSL_R_LENGTH_MISMATCH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + ossl_statem_set_error(s); + return MSG_PROCESS_ERROR; + } + + /* + * This is a historical discrepancy (not in the RFC) maintained for + * compatibility reasons. If a TLS client receives a HelloRequest it will + * attempt an abbreviated handshake. However if a DTLS client receives a + * HelloRequest it will do a full handshake. Either behaviour is reasonable + * but doing one for TLS and another for DTLS is odd. + */ + if (SSL_IS_DTLS(s)) + SSL_renegotiate(s); + else + SSL_renegotiate_abbreviated(s); + + return MSG_PROCESS_FINISHED_READING; +} + static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt) { int al = SSL_AD_INTERNAL_ERROR; @@ -3113,7 +3378,7 @@ static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt) } if (!tls_collect_extensions(s, &extensions, EXT_TLS1_3_ENCRYPTED_EXTENSIONS, - &rawexts, &al) + &rawexts, &al, NULL) || !tls_parse_all_extensions(s, EXT_TLS1_3_ENCRYPTED_EXTENSIONS, rawexts, NULL, 0, &al)) goto err;