X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fstatem_srvr.c;h=66743c37ad1224ed774e222bd1522abca245627c;hp=cb080aa10f4a1ae194385324627d894b1426f426;hb=aff9929b43cba794e5b99a9be5c8ca47873154d1;hpb=c7f47786a5e5f68dc33091ffb2a42e51a73de3a1 diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index cb080aa10f..66743c37ad 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -62,6 +62,7 @@ #include static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt); +static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt); static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, PACKET *cipher_suites, STACK_OF(SSL_CIPHER) @@ -81,11 +82,6 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt) { 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 is no case for TLS_ST_BEFORE because at that stage we have * not negotiated TLSv1.3 yet, so that case is handled by @@ -95,6 +91,13 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt) default: break; + case TLS_ST_SW_HELLO_RETRY_REQUEST: + if (mt == SSL3_MT_CLIENT_HELLO) { + st->hand_state = TLS_ST_SR_CLNT_HELLO; + return 1; + } + break; + case TLS_ST_SW_FINISHED: if (s->s3->tmp.cert_request) { if (mt == SSL3_MT_CERTIFICATE) { @@ -406,9 +409,15 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) return WRITE_TRAN_ERROR; case TLS_ST_SR_CLNT_HELLO: - st->hand_state = TLS_ST_SW_SRVR_HELLO; + if (s->hello_retry_request) + st->hand_state = TLS_ST_SW_HELLO_RETRY_REQUEST; + else + st->hand_state = TLS_ST_SW_SRVR_HELLO; return WRITE_TRAN_CONTINUE; + case TLS_ST_SW_HELLO_RETRY_REQUEST: + return WRITE_TRAN_FINISHED; + case TLS_ST_SW_SRVR_HELLO: st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS; return WRITE_TRAN_CONTINUE; @@ -439,6 +448,18 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) return WRITE_TRAN_FINISHED; case TLS_ST_SR_FINISHED: + /* + * Technically we have finished the handshake at this point, but we're + * going to remain "in_init" for now and write out the session ticket + * immediately. + * TODO(TLS1.3): Perhaps we need to be able to control this behaviour + * and give the application the opportunity to delay sending the + * session ticket? + */ + st->hand_state = TLS_ST_SW_SESSION_TICKET; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: st->hand_state = TLS_ST_OK; ossl_statem_set_in_init(s, 0); return WRITE_TRAN_CONTINUE; @@ -626,7 +647,14 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) return WORK_FINISHED_CONTINUE; case TLS_ST_SW_SESSION_TICKET: - if (SSL_IS_DTLS(s)) { + if (SSL_IS_TLS13(s)) { + /* + * Actually this is the end of the handshake, but we're going + * straight into writing the session ticket out. So we finish off + * the handshake, but keep the various buffers active. + */ + return tls_finish_handshake(s, wst, 0); + } if (SSL_IS_DTLS(s)) { /* * We're into the last flight. We don't retransmit the last flight * unless we need to, so we don't use the timer @@ -653,7 +681,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) return WORK_FINISHED_CONTINUE; case TLS_ST_OK: - return tls_finish_handshake(s, wst); + return tls_finish_handshake(s, wst, 1); } return WORK_FINISHED_CONTINUE; @@ -674,6 +702,11 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) /* No post work to be done */ break; + case TLS_ST_SW_HELLO_RETRY_REQUEST: + if (statem_flush(s) != 1) + return WORK_MORE_A; + break; + case TLS_ST_SW_HELLO_REQ: if (statem_flush(s) != 1) return WORK_MORE_A; @@ -781,13 +814,18 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) #endif if (SSL_IS_TLS13(s)) { if (!s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, s->handshake_secret, 0, + s->master_secret, s->handshake_secret, 0, &s->session->master_key_length) || !s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE)) return WORK_ERROR; } break; + + case TLS_ST_SW_SESSION_TICKET: + if (SSL_IS_TLS13(s) && statem_flush(s) != 1) + return WORK_MORE_A; + break; } return WORK_FINISHED_CONTINUE; @@ -880,6 +918,11 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt, *confunc = tls_construct_encrypted_extensions; *mt = SSL3_MT_ENCRYPTED_EXTENSIONS; break; + + case TLS_ST_SW_HELLO_RETRY_REQUEST: + *confunc = tls_construct_hello_retry_request; + *mt = SSL3_MT_HELLO_RETRY_REQUEST; + break; } return 1; @@ -1176,6 +1219,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) if (clienthello.isv2) { unsigned int mt; + if (!SSL_IS_FIRST_HANDSHAKE(s) || s->hello_retry_request) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + /*- * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 * header is sent directly on the wire, not wrapped as a TLS @@ -1378,7 +1427,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) if (protverr) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr); - if ((!s->enc_write_ctx && !s->write_hash)) { + if (SSL_IS_FIRST_HANDSHAKE(s)) { /* like ssl3_get_record, send alert using remote version number */ s->version = s->client_version = clienthello.legacy_version; } @@ -1451,21 +1500,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) if (!ssl_get_new_session(s, 1)) goto err; } else { - i = ssl_get_prev_session(s, &clienthello); - /* - * Only resume if the session's version matches the negotiated - * version. - * RFC 5246 does not provide much useful advice on resumption - * with a different protocol version. It doesn't forbid it but - * the sanity of such behaviour would be questionable. - * In practice, clients do not accept a version mismatch and - * will abort the handshake with an error. - */ - if (i == 1 && s->version == s->session->ssl_version) { + i = ssl_get_prev_session(s, &clienthello, &al); + if (i == 1) { /* previous session */ s->hit = 1; } else if (i == -1) { - goto err; + goto f_err; } else { /* i == 0 */ if (!ssl_get_new_session(s, 1)) @@ -1533,15 +1573,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 @@ -1578,12 +1609,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) ciphers = NULL; /* check if some cipher was preferred by call back */ - pref_cipher = - pref_cipher ? pref_cipher : ssl3_choose_cipher(s, - s-> - session->ciphers, - SSL_get_ciphers - (s)); + if (pref_cipher == NULL) + pref_cipher = ssl3_choose_cipher(s, s->session->ciphers, + SSL_get_ciphers(s)); if (pref_cipher == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER); @@ -1794,6 +1822,12 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) goto f_err; } s->s3->tmp.new_cipher = cipher; + if (!tls_choose_sigalg(s)) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); + goto f_err; + } /* check whether we should disable session resumption */ if (s->not_resumable_session_cb != NULL) s->session->not_resumable = @@ -1808,13 +1842,6 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) s->s3->tmp.new_cipher = s->session->cipher; } - if (!(s->verify_mode & SSL_VERIFY_PEER)) { - if (!ssl3_digest_cached_records(s, 0)) { - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - } - /*- * we now have the following setup. * client_random @@ -1941,6 +1968,12 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt) goto err; } + if (!(s->verify_mode & SSL_VERIFY_PEER) + && !ssl3_digest_cached_records(s, 0)) { + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + return 1; err: ssl3_send_alert(s, SSL3_AL_FATAL, al); @@ -2268,8 +2301,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) if (ispss) { 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) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB); goto f_err; @@ -2327,7 +2359,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } if (SSL_USE_SIGALGS(s)) { - const unsigned int *psigs; + const uint16_t *psigs; size_t nl = tls12_get_psigalgs(s, 1, &psigs); if (!WPACKET_start_sub_packet_u16(pkt) @@ -2457,7 +2489,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al) unsigned char *rsa_decrypt = NULL; int ret = 0; - rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey); + rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey); if (rsa == NULL) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE); @@ -3216,11 +3248,21 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) int len, slen_full, slen, lenfinal; SSL_SESSION *sess; unsigned int hlen; - SSL_CTX *tctx = s->initial_ctx; + SSL_CTX *tctx = s->session_ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; - int iv_len; + int iv_len, al = SSL_AD_INTERNAL_ERROR; size_t macoffset, macendoffset; + union { + unsigned char age_add_c[sizeof(uint32_t)]; + uint32_t age_add; + } age_add_u; + + if (SSL_IS_TLS13(s)) { + if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) + goto err; + s->session->ext.tick_age_add = age_add_u.age_add; + } /* get session encoding length */ slen_full = i2d_SSL_SESSION(s->session, NULL); @@ -3319,6 +3361,8 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) * new sessions will live as long as their sessions. */ if (!WPACKET_put_bytes_u32(pkt, s->hit ? 0 : s->session->timeout) + || (SSL_IS_TLS13(s) + && !WPACKET_put_bytes_u32(pkt, age_add_u.age_add)) /* Now the actual ticket data */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_get_total_written(pkt, &macoffset) @@ -3345,7 +3389,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) || hlen > EVP_MAX_MD_SIZE || !WPACKET_allocate_bytes(pkt, hlen, &macdata2) || macdata1 != macdata2 - || !WPACKET_close(pkt)) { + || !WPACKET_close(pkt) + || (SSL_IS_TLS13(s) + && !tls_construct_extensions(s, pkt, + EXT_TLS1_3_NEW_SESSION_TICKET, + NULL, 0, &al))) { SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR); goto err; } @@ -3478,6 +3526,10 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, return NULL; } + OPENSSL_free(s->s3->tmp.ciphers_raw); + s->s3->tmp.ciphers_raw = NULL; + s->s3->tmp.ciphers_rawlen = 0; + if (sslv2format) { size_t numciphers = PACKET_remaining(cipher_suites) / n; PACKET sslv2ciphers = *cipher_suites; @@ -3583,3 +3635,28 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, sk_SSL_CIPHER_free(sk); return NULL; } + +static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt) +{ + int al; + + /* + * TODO(TLS1.3): Remove the DRAFT version before release + * (should be s->version) + */ + if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) + || !tls_construct_extensions(s, pkt, EXT_TLS1_3_HELLO_RETRY_REQUEST, + NULL, 0, &al)) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); + SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; + } + + /* Ditch the session. We'll create a new one next time around */ + SSL_SESSION_free(s->session); + s->session = NULL; + s->hit = 0; + + return 1; +}