EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (!s->ext.status_expected) return EXT_RETURN_NOT_SENT; if (SSL_IS_TLS13(s) && chainidx != 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } /* * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we * send back an empty extension, with the certificate status appearing as a * separate message */ if ((SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { /* * MUST only be sent if we've requested a status * request message. In TLS <= 1.2 it must also be empty. */ if (s->ext.status_type == TLSEXT_STATUSTYPE_nothing || (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0)) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } if (SSL_IS_TLS13(s)) { /* We only know how to handle this if it's for the first Certificate in * the chain. We ignore any other repsonses. */ if (chainidx != 0) return 1; return tls_process_cert_status_body(s, pkt, al); } /* Set flag to expect CertificateStatus message */ s->ext.status_expected = 1; return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!PACKET_memdup(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!tls1_save_u16(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
int ssl_get_new_session(SSL *s, int session) { /* This gets used by clients and servers. */ SSL_SESSION *ss = NULL; if ((ss = SSL_SESSION_new()) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); return 0; } /* If the context has a default timeout, use it */ if (s->session_ctx->session_timeout == 0) ss->timeout = SSL_get_default_timeout(s); else ss->timeout = s->session_ctx->session_timeout; SSL_SESSION_free(s->session); s->session = NULL; if (session) { if (SSL_IS_TLS13(s)) { /* * We generate the session id while constructing the * NewSessionTicket in TLSv1.3. */ ss->session_id_length = 0; } else if (!ssl_generate_session_id(s, ss)) { /* SSLfatal() already called */ SSL_SESSION_free(ss); return 0; } } else { ss->session_id_length = 0; } if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); SSL_SESSION_free(ss); return 0; } memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); ss->sid_ctx_length = s->sid_ctx_length; s->session = ss; ss->ssl_version = s->version; ss->verify_result = X509_V_OK; /* If client supports extended master secret set it in session */ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) ss->flags |= SSL_SESS_FLAG_EXTMS; return 1; }
/*- * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this * connection. It is only called by servers. * * hello: The parsed ClientHello data * * Returns: * -1: fatal error * 0: no session found * 1: a session may have been found. * * Side effects: * - If a session is found then s->session is pointed at it (after freeing an * existing session if need be) and s->verify_result is set from the session. * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 * if the server should issue a new session ticket (to 0 otherwise). */ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al) { /* This is used only by servers. */ SSL_SESSION *ret = NULL; int fatal = 0; int try_session_cache = 0; TICKET_RETURN r; if (SSL_IS_TLS13(s)) { if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, NULL, 0, al) || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, NULL, 0, al)) return -1; ret = s->session; } else { /* sets s->ext.ticket_expected */ r = tls_get_ticket_from_client(s, hello, &ret); switch (r) { case TICKET_FATAL_ERR_MALLOC: case TICKET_FATAL_ERR_OTHER: fatal = 1; goto err; case TICKET_NONE: case TICKET_EMPTY: try_session_cache = 1; break; case TICKET_NO_DECRYPT: case TICKET_SUCCESS: case TICKET_SUCCESS_RENEW: break; } } if (try_session_cache && ret == NULL && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { SSL_SESSION data; data.ssl_version = s->version; memcpy(data.session_id, hello->session_id, hello->session_id_len); data.session_id_length = hello->session_id_len; CRYPTO_THREAD_read_lock(s->session_ctx->lock); ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); if (ret != NULL) { /* don't allow other threads to steal it: */ SSL_SESSION_up_ref(ret); } CRYPTO_THREAD_unlock(s->session_ctx->lock); if (ret == NULL) s->session_ctx->stats.sess_miss++; } if (try_session_cache && ret == NULL && s->session_ctx->get_session_cb != NULL) { int copy = 1; ret = s->session_ctx->get_session_cb(s, hello->session_id, hello->session_id_len, ©); if (ret != NULL) { s->session_ctx->stats.sess_cb_hit++; /* * Increment reference count now if the session callback asks us * to do so (note that if the session structures returned by the * callback are shared between threads, it must handle the * reference count itself [i.e. copy == 0], or things won't be * thread-safe). */ if (copy) SSL_SESSION_up_ref(ret); /* * Add the externally cached session to the internal cache as * well if and only if we are supposed to. */ if (! (s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE)) { /* * The following should not return 1, otherwise, things are * very strange */ if (SSL_CTX_add_session(s->session_ctx, ret)) goto err; } } } if (ret == NULL) goto err; /* Now ret is non-NULL and we own one of its reference counts. */ /* Check TLS version consistency */ if (ret->ssl_version != s->version) goto err; if (ret->sid_ctx_length != s->sid_ctx_length || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { /* * We have the session requested by the client, but we don't want to * use it in this context. */ goto err; /* treat like cache miss */ } if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { /* * We can't be sure if this session is being used out of context, * which is especially important for SSL_VERIFY_PEER. The application * should have used SSL[_CTX]_set_session_id_context. For this error * case, we generate an error instead of treating the event like a * cache miss (otherwise it would be easy for applications to * effectively disable the session cache by accident without anyone * noticing). */ SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); fatal = 1; goto err; } if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ s->session_ctx->stats.sess_timeout++; if (try_session_cache) { /* session was from the cache, so remove it */ SSL_CTX_remove_session(s->session_ctx, ret); } goto err; } /* Check extended master secret extension consistency */ if (ret->flags & SSL_SESS_FLAG_EXTMS) { /* If old session includes extms, but new does not: abort handshake */ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); fatal = 1; goto err; } } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { /* If new session includes extms, but old does not: do not resume */ goto err; } if (!SSL_IS_TLS13(s)) { /* We already did this for TLS1.3 */ SSL_SESSION_free(s->session); s->session = ret; } s->session_ctx->stats.sess_hit++; s->verify_result = s->session->verify_result; return 1; err: if (ret != NULL) { SSL_SESSION_free(ret); /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ if (SSL_IS_TLS13(s)) s->session = NULL; if (!try_session_cache) { /* * The session was from a ticket, so we should issue a ticket for * the new session */ s->ext.ticket_expected = 1; } } if (fatal) { *al = SSL_AD_INTERNAL_ERROR; return -1; } return 0; }
MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) { int al = SSL_AD_INTERNAL_ERROR; size_t md_len; /* If this occurs, we have missed a message */ if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; md_len = s->s3->tmp.peer_finish_md_len; if (md_len != PACKET_remaining(pkt)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, md_len) != 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* * Copy the finished so we can use it for renegotiation checks */ if (s->server) { OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, md_len); s->s3->previous_client_finished_len = md_len; } else { OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, md_len); s->s3->previous_server_finished_len = md_len; } /* * In TLS1.3 we also have to change cipher state and do any final processing * of the initial server flight (if we are a client) */ if (SSL_IS_TLS13(s)) { if (s->server) { if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } } else { if (!s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, s->handshake_secret, 0, &s->session->master_key_length)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } if (!tls_process_initial_server_flight(s, &al)) goto f_err; } } return MSG_PROCESS_FINISHED_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }
/*- * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this * connection. It is only called by servers. * * hello: The parsed ClientHello data * * Returns: * -1: fatal error * 0: no session found * 1: a session may have been found. * * Side effects: * - If a session is found then s->session is pointed at it (after freeing an * existing session if need be) and s->verify_result is set from the session. * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 * if the server should issue a new session ticket (to 0 otherwise). */ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) { /* This is used only by servers. */ SSL_SESSION *ret = NULL; int fatal = 0; int try_session_cache = 0; SSL_TICKET_STATUS r; if (SSL_IS_TLS13(s)) { /* * By default we will send a new ticket. This can be overridden in the * ticket processing. */ s->ext.ticket_expected = 1; if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, NULL, 0) || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, NULL, 0)) return -1; ret = s->session; } else { /* sets s->ext.ticket_expected */ r = tls_get_ticket_from_client(s, hello, &ret); switch (r) { case SSL_TICKET_FATAL_ERR_MALLOC: case SSL_TICKET_FATAL_ERR_OTHER: fatal = 1; SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, ERR_R_INTERNAL_ERROR); goto err; case SSL_TICKET_NONE: case SSL_TICKET_EMPTY: if (hello->session_id_len > 0) { try_session_cache = 1; ret = lookup_sess_in_cache(s, hello->session_id, hello->session_id_len); } break; case SSL_TICKET_NO_DECRYPT: case SSL_TICKET_SUCCESS: case SSL_TICKET_SUCCESS_RENEW: break; } } if (ret == NULL) goto err; /* Now ret is non-NULL and we own one of its reference counts. */ /* Check TLS version consistency */ if (ret->ssl_version != s->version) goto err; if (ret->sid_ctx_length != s->sid_ctx_length || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { /* * We have the session requested by the client, but we don't want to * use it in this context. */ goto err; /* treat like cache miss */ } if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { /* * We can't be sure if this session is being used out of context, * which is especially important for SSL_VERIFY_PEER. The application * should have used SSL[_CTX]_set_session_id_context. For this error * case, we generate an error instead of treating the event like a * cache miss (otherwise it would be easy for applications to * effectively disable the session cache by accident without anyone * noticing). */ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); fatal = 1; goto err; } if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ tsan_counter(&s->session_ctx->stats.sess_timeout); if (try_session_cache) { /* session was from the cache, so remove it */ SSL_CTX_remove_session(s->session_ctx, ret); } goto err; } /* Check extended master secret extension consistency */ if (ret->flags & SSL_SESS_FLAG_EXTMS) { /* If old session includes extms, but new does not: abort handshake */ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS); fatal = 1; goto err; } } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { /* If new session includes extms, but old does not: do not resume */ goto err; } if (!SSL_IS_TLS13(s)) { /* We already did this for TLS1.3 */ SSL_SESSION_free(s->session); s->session = ret; } tsan_counter(&s->session_ctx->stats.sess_hit); s->verify_result = s->session->verify_result; return 1; err: if (ret != NULL) { SSL_SESSION_free(ret); /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ if (SSL_IS_TLS13(s)) s->session = NULL; if (!try_session_cache) { /* * The session was from a ticket, so we should issue a ticket for * the new session */ s->ext.ticket_expected = 1; } } if (fatal) return -1; return 0; }