in ssl/ssl_transfer_asn1.cc [450:837]
static int SSL3_STATE_from_bytes(SSL *ssl, CBS *cbs, const SSL_CTX *ctx) {
// We expect the caller to have configured |ssl| with the protocol
// version prior to calling us.
uint16_t protocol_version;
if (!ssl_protocol_version_from_wire(&protocol_version, ssl->version)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
bool is_tls13 = protocol_version >= TLS1_3_VERSION;
SSL3_STATE *out = ssl->s3;
CBS s3, read_seq, write_seq, server_random, client_random, send_alert,
pending_app_data, read_buffer;
CBS previous_client_finished, previous_server_finished;
int session_reused, channel_id_valid, send_connection_binding, not_resumable;
uint64_t serde_version, early_data_reason, previous_client_finished_len,
previous_server_finished_len;
uint64_t empty_record_count, warning_alert_count, total_renegotiations;
int64_t rwstate;
int pending_app_data_present, read_buffer_present;
if (!CBS_get_asn1(cbs, &s3, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&s3, &serde_version) ||
serde_version > SSL3_STATE_SERDE_VERSION_TWO ||
(is_tls13 && serde_version < SSL3_STATE_SERDE_VERSION_TWO) ||
!CBS_get_asn1(&s3, &read_seq, CBS_ASN1_OCTETSTRING) ||
CBS_len(&read_seq) != TLS_SEQ_NUM_SIZE ||
!CBS_get_asn1(&s3, &write_seq, CBS_ASN1_OCTETSTRING) ||
CBS_len(&write_seq) != TLS_SEQ_NUM_SIZE ||
!CBS_get_asn1(&s3, &server_random, CBS_ASN1_OCTETSTRING) ||
CBS_len(&server_random) != SSL3_RANDOM_SIZE ||
!CBS_get_asn1(&s3, &client_random, CBS_ASN1_OCTETSTRING) ||
CBS_len(&client_random) != SSL3_RANDOM_SIZE ||
!CBS_get_asn1(&s3, &send_alert, CBS_ASN1_OCTETSTRING) ||
CBS_len(&send_alert) != SSL3_SEND_ALERT_SIZE ||
!CBS_get_asn1_int64(&s3, &rwstate) ||
!CBS_get_asn1_uint64(&s3, &early_data_reason) ||
early_data_reason > ssl_early_data_reason_max_value ||
!CBS_get_asn1(&s3, &previous_client_finished, CBS_ASN1_OCTETSTRING) ||
CBS_len(&previous_client_finished) > PREV_FINISHED_MAX_SIZE ||
!CBS_get_asn1_uint64(&s3, &previous_client_finished_len) ||
previous_client_finished_len > PREV_FINISHED_MAX_SIZE ||
!CBS_get_asn1(&s3, &previous_server_finished, CBS_ASN1_OCTETSTRING) ||
CBS_len(&previous_server_finished) > PREV_FINISHED_MAX_SIZE ||
!CBS_get_asn1_uint64(&s3, &previous_server_finished_len) ||
previous_server_finished_len > PREV_FINISHED_MAX_SIZE ||
!CBS_get_asn1_uint64(&s3, &empty_record_count) ||
!CBS_get_asn1_uint64(&s3, &warning_alert_count) ||
!CBS_get_asn1_uint64(&s3, &total_renegotiations) ||
!SSL3_STATE_parse_session(&s3, &(out->established_session), ctx) ||
!CBS_get_optional_asn1_bool(&s3, &session_reused, kS3SessionReusedTag,
0 /* default to false */) ||
!parse_optional_string(&s3, &(out->hostname), kS3HostNameTag,
SSL_R_SERIALIZATION_INVALID_SSL3_STATE) ||
!SSL3_STATE_parse_octet_string(&s3, &(out->alpn_selected),
kS3ALPNSelectedTag) ||
!SSL3_STATE_parse_octet_string(&s3, &(out->next_proto_negotiated),
kS3NextProtoNegotiatedTag) ||
!CBS_get_optional_asn1_bool(&s3, &channel_id_valid, kS3ChannelIdValidTag,
0 /* default to false */) ||
!SSL3_STATE_get_optional_octet_string(
&s3, out->channel_id, kS3ChannelIdTag, SSL3_CHANNEL_ID_SIZE) ||
!CBS_get_optional_asn1_bool(&s3, &send_connection_binding,
kS3SendConnectionBindingTag,
0 /* default to false */) ||
!CBS_get_optional_asn1(&s3, &pending_app_data, &pending_app_data_present,
kS3PendingAppDataTag) ||
!CBS_get_optional_asn1(&s3, &read_buffer, &read_buffer_present,
kS3ReadBufferTag) ||
!CBS_get_optional_asn1_bool(&s3, ¬_resumable, kS3NotResumableTag,
0 /* default to false */)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
bool is_v2 = (serde_version == SSL3_STATE_SERDE_VERSION_TWO);
// We should have no more data at this point if we are deserializing v1
// encoding.
if (!is_v2 && CBS_len(&s3) > 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t early_data_skipped;
if (!CBS_get_optional_asn1_uint64(&s3, &early_data_skipped,
kS3EarlyDataSkippedTag,
0 /* default to 0 */) ||
early_data_skipped > UINT16_MAX) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->early_data_skipped = static_cast<uint16_t>(early_data_skipped);
int delegated_credential_used;
if (!CBS_get_optional_asn1_bool(&s3, &delegated_credential_used,
kS3DelegatedCredentialUsedTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->delegated_credential_used = delegated_credential_used != 0;
int early_data_accepted;
if (!CBS_get_optional_asn1_bool(&s3, &early_data_accepted,
kS3EarlyDataAcceptedTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->early_data_accepted = early_data_accepted != 0;
int used_hello_retry_request;
if (!CBS_get_optional_asn1_bool(&s3, &used_hello_retry_request,
kS3UsedHelloRetryRequestTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->used_hello_retry_request = used_hello_retry_request != 0;
int64_t ticket_age_skew;
if (!CBS_get_optional_asn1_int64(&s3, &ticket_age_skew, kS3TicketAgeSkewTag,
0) ||
ticket_age_skew > INT32_MAX) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->ticket_age_skew = static_cast<int32_t>(ticket_age_skew);
CBS write_traffic_secret;
int write_traffic_secret_present;
if (!CBS_get_optional_asn1_octet_string(&s3, &write_traffic_secret,
&write_traffic_secret_present,
kS3WriteTrafficSecretTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t write_traffic_secret_len;
if (!CBS_get_optional_asn1_uint64(&s3, &write_traffic_secret_len,
kS3WriteTrafficSecretLenTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS read_traffic_secret;
int read_traffic_secret_present;
if (!CBS_get_optional_asn1_octet_string(&s3, &read_traffic_secret,
&read_traffic_secret_present,
kS3ReadTrafficSecretTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t read_traffic_secret_len;
if (!CBS_get_optional_asn1_uint64(&s3, &read_traffic_secret_len,
kS3ReadTrafficSecretLenTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS exporter_secret;
int exporter_secret_present;
if (!CBS_get_optional_asn1_octet_string(&s3, &exporter_secret,
&exporter_secret_present,
kS3ExporterSecretTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t exporter_secret_len;
if (!CBS_get_optional_asn1_uint64(&s3, &exporter_secret_len,
kS3ExporterSecretLenTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS hs_buf;
int hs_buf_present;
if (!CBS_get_optional_asn1_octet_string(&s3, &hs_buf, &hs_buf_present,
kS3HandshakeBufferTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t ech_status;
if (!CBS_get_optional_asn1_uint64(&s3, &ech_status, kS3EchStatusTag,
ssl_ech_none)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS pending_hs_data;
int pending_hs_data_present;
if (!CBS_get_optional_asn1_octet_string(&s3, &pending_hs_data,
&pending_hs_data_present,
kS3PendingHsDataTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS pending_flight;
int pending_flight_present;
if (!CBS_get_optional_asn1_octet_string(
&s3, &pending_flight, &pending_flight_present, kS3PendingFlightTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS aead_read_ctx;
int aead_read_ctx_present;
if (!CBS_get_optional_asn1(&s3, &aead_read_ctx, &aead_read_ctx_present,
kS3AeadReadCtxTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS aead_write_ctx;
int aead_write_ctx_present;
if (!CBS_get_optional_asn1(&s3, &aead_write_ctx, &aead_write_ctx_present,
kS3AeadWriteCtxTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
if (is_tls13) {
if (!write_traffic_secret_present ||
CBS_len(&write_traffic_secret) != SSL_MAX_MD_SIZE ||
!write_traffic_secret_len || write_traffic_secret_len > UINT8_MAX ||
!read_traffic_secret_present ||
CBS_len(&read_traffic_secret) != SSL_MAX_MD_SIZE ||
!read_traffic_secret_len || read_traffic_secret_len > UINT8_MAX ||
!exporter_secret_present ||
CBS_len(&exporter_secret) != SSL_MAX_MD_SIZE || !exporter_secret_len ||
exporter_secret_len > UINT8_MAX || ech_status > ssl_ech_rejected ||
!aead_read_ctx_present || !aead_write_ctx_present) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
OPENSSL_memcpy(out->exporter_secret, CBS_data(&exporter_secret),
SSL_MAX_MD_SIZE);
out->exporter_secret_len = exporter_secret_len;
out->hs_buf.reset(BUF_MEM_new());
if (hs_buf_present) {
if (!BUF_MEM_append(out->hs_buf.get(), CBS_data(&hs_buf),
CBS_len(&hs_buf))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
out->ech_status = static_cast<ssl_ech_status_t>(ech_status);
} else if (write_traffic_secret_present || write_traffic_secret_len ||
read_traffic_secret_present || read_traffic_secret_len ||
exporter_secret_present || exporter_secret_len || hs_buf_present ||
ech_status || pending_hs_data_present || pending_flight_present) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
if (read_buffer_present &&
!out->read_buffer.DoDeserialization(&read_buffer)) {
return 0;
}
// If |pending_app_data_size| is not zero, it needs to point to |read_buffer|.
if (pending_app_data_present) {
if (!read_buffer_present) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
CBS app_seq;
uint64_t pending_app_data_offset, pending_app_data_size;
if (!CBS_get_asn1(&pending_app_data, &app_seq, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&app_seq, &pending_app_data_offset) ||
!CBS_get_asn1_uint64(&app_seq, &pending_app_data_size)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
if (pending_app_data_size > out->read_buffer.buf_size()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
out->pending_app_data =
MakeSpan(out->read_buffer.buf_ptr() + pending_app_data_offset,
pending_app_data_size);
}
if (CBS_len(&s3)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
// Initialize some states before call |tls1_configure_aead|.
// Below comment is copied from |SSL_do_handshake|.
// Destroy the handshake object if the handshake has completely finished.
out->hs.reset();
// have_version is true if the connection's final version is known. Otherwise
// the version has not been negotiated yet.
out->have_version = true;
OPENSSL_memcpy(out->server_random, CBS_data(&server_random),
SSL3_RANDOM_SIZE);
OPENSSL_memcpy(out->client_random, CBS_data(&client_random),
SSL3_RANDOM_SIZE);
SSL_SESSION *session = out->established_session.get();
if (is_tls13) {
if (!tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_seal,
session,
MakeSpan(CBS_data(&write_traffic_secret),
write_traffic_secret_len))) {
return 0;
}
if (!tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_open,
session,
MakeSpan(CBS_data(&read_traffic_secret),
read_traffic_secret_len))) {
return 0;
}
// !! We set pending_hs_data and pending_hs_flight after as to avoid
// tls13_set_traffic_key from trying to flush their contents if they are not
// empty !!
out->pending_hs_data.reset(BUF_MEM_new());
if (pending_hs_data_present) {
if (!BUF_MEM_append(out->pending_hs_data.get(),
CBS_data(&pending_hs_data),
CBS_len(&pending_hs_data))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
out->pending_flight.reset(BUF_MEM_new());
if (pending_flight_present) {
if (!BUF_MEM_append(out->pending_flight.get(), CBS_data(&pending_flight),
CBS_len(&pending_flight))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
} else {
// the impl of |SSL_serialize_handback|, which only fetch IV when it's
// TLS 1.
Array<uint8_t> key_block1, key_block2;
if (!tls1_configure_aead(ssl, evp_aead_seal, &key_block1, session, {})) {
return 0;
}
if (!tls1_configure_aead(ssl, evp_aead_open, &key_block2, session, {})) {
return 0;
}
}
if (aead_read_ctx_present &&
!out->aead_read_ctx->DeserializeState(&aead_read_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
if (aead_write_ctx_present &&
!out->aead_write_ctx->DeserializeState(&aead_write_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
// read_sequence & write_sequence must be set AFTER setting the traffic keys,
// otherwise would be reset back to zero.
OPENSSL_memcpy(out->read_sequence, CBS_data(&read_seq), TLS_SEQ_NUM_SIZE);
OPENSSL_memcpy(out->write_sequence, CBS_data(&write_seq), TLS_SEQ_NUM_SIZE);
OPENSSL_memcpy(out->send_alert, CBS_data(&send_alert), SSL3_SEND_ALERT_SIZE);
OPENSSL_memcpy(out->previous_client_finished,
CBS_data(&previous_client_finished), PREV_FINISHED_MAX_SIZE);
OPENSSL_memcpy(out->previous_server_finished,
CBS_data(&previous_server_finished), PREV_FINISHED_MAX_SIZE);
out->early_data_reason =
static_cast<ssl_early_data_reason_t>(early_data_reason);
out->rwstate = rwstate;
out->session_reused = !!session_reused;
if (out->session_reused) {
ssl->session = UpRef(out->established_session);
}
out->channel_id_valid = !!channel_id_valid;
out->previous_client_finished_len = previous_client_finished_len;
out->previous_server_finished_len = previous_server_finished_len;
out->v2_hello_done = true;
out->initial_handshake_complete = true;
out->empty_record_count = empty_record_count;
out->warning_alert_count = warning_alert_count;
out->total_renegotiations = total_renegotiations;
out->send_connection_binding = !!send_connection_binding;
out->established_session.get()->not_resumable = !!not_resumable;
return 1;
}