in ssl/ssl_transfer_asn1.cc [186:420]
static int SSL3_STATE_to_bytes(SSL3_STATE *in, uint16_t protocol_version,
CBB *cbb) {
if (in == NULL || cbb == NULL) {
return 0;
}
CBB s3, child, child2;
if (!CBB_add_asn1(cbb, &s3, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&s3, SSL3_STATE_SERDE_VERSION_TWO) ||
!CBB_add_asn1_octet_string(&s3, in->read_sequence, TLS_SEQ_NUM_SIZE) ||
!CBB_add_asn1_octet_string(&s3, in->write_sequence, TLS_SEQ_NUM_SIZE) ||
!CBB_add_asn1_octet_string(&s3, in->server_random, SSL3_RANDOM_SIZE) ||
!CBB_add_asn1_octet_string(&s3, in->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_asn1_octet_string(&s3, in->send_alert, SSL3_SEND_ALERT_SIZE) ||
!CBB_add_asn1_int64(&s3, in->rwstate) ||
!CBB_add_asn1_int64(&s3, in->early_data_reason) ||
!CBB_add_asn1_octet_string(&s3, in->previous_client_finished,
PREV_FINISHED_MAX_SIZE) ||
!CBB_add_asn1_uint64(&s3, in->previous_client_finished_len) ||
!CBB_add_asn1_octet_string(&s3, in->previous_server_finished,
PREV_FINISHED_MAX_SIZE) ||
!CBB_add_asn1_uint64(&s3, in->previous_server_finished_len) ||
!CBB_add_asn1_uint64(&s3, in->empty_record_count) ||
!CBB_add_asn1_uint64(&s3, in->warning_alert_count) ||
!CBB_add_asn1_uint64(&s3, in->total_renegotiations)) {
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3EstablishedSessionTag) ||
!ssl_session_serialize(in->established_session.get(), &child)) {
return 0;
}
if (in->session_reused) {
if (!CBB_add_asn1(&s3, &child, kS3SessionReusedTag) ||
!CBB_add_asn1_bool(&child, true)) {
return 0;
}
}
if (in->hostname) {
if (!CBB_add_asn1(&s3, &child, kS3HostNameTag) ||
!CBB_add_asn1_octet_string(&child,
(const uint8_t *)(in->hostname.get()),
strlen(in->hostname.get()))) {
return 0;
}
}
if (!in->alpn_selected.empty()) {
if (!CBB_add_asn1(&s3, &child, kS3ALPNSelectedTag) ||
!CBB_add_asn1_octet_string(&child, in->alpn_selected.data(),
in->alpn_selected.size())) {
return 0;
}
}
if (!in->next_proto_negotiated.empty()) {
if (!CBB_add_asn1(&s3, &child, kS3NextProtoNegotiatedTag) ||
!CBB_add_asn1_octet_string(&child, in->next_proto_negotiated.data(),
in->next_proto_negotiated.size())) {
return 0;
}
}
if (in->channel_id_valid) {
if (!CBB_add_asn1(&s3, &child, kS3ChannelIdValidTag) ||
!CBB_add_asn1_bool(&child, true)) {
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3ChannelIdTag) ||
!CBB_add_asn1_octet_string(&child, in->channel_id,
SSL3_CHANNEL_ID_SIZE)) {
return 0;
}
}
if (in->send_connection_binding) {
if (!CBB_add_asn1(&s3, &child, kS3SendConnectionBindingTag) ||
!CBB_add_asn1_bool(&child, true)) {
return 0;
}
}
if (!in->pending_app_data.empty()) {
// This should never happen because pending_app_data is just a span and
// points to read_buffer.
if (!in->read_buffer.buf_ptr() ||
in->read_buffer.buf_ptr() > in->pending_app_data.data()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERIALIZATION_INVALID_SSL3_STATE);
return 0;
}
uint64_t offset = in->pending_app_data.data() - in->read_buffer.buf_ptr();
if (!CBB_add_asn1(&s3, &child, kS3PendingAppDataTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&child2, offset) ||
!CBB_add_asn1_uint64(&child2, in->pending_app_data.size())) {
return 0;
}
}
if (!in->pending_app_data.empty() || !in->read_buffer.empty()) {
if (!CBB_add_asn1(&s3, &child, kS3ReadBufferTag) ||
!in->read_buffer.DoSerialization(&child)) {
return 0;
}
}
// serialization of |not_resumable| is not added in |ssl_session_serialize|
// because the function is used to serialize a session for resumption.
if (in->established_session.get()->not_resumable) {
if (!CBB_add_asn1(&s3, &child, kS3NotResumableTag) ||
!CBB_add_asn1_bool(&child, true)) {
return 0;
}
}
// Version 2 extensions starts below, all which are optional as they are
// TLS 1.3 specific.
if (protocol_version >= TLS1_3_VERSION) {
if (!CBB_add_asn1(&s3, &child, kS3EarlyDataSkippedTag) ||
!CBB_add_asn1_uint64(&child, in->early_data_skipped)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3DelegatedCredentialUsedTag) ||
!CBB_add_asn1_bool(&child, in->delegated_credential_used)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3EarlyDataAcceptedTag) ||
!CBB_add_asn1_bool(&child, in->early_data_accepted)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3UsedHelloRetryRequestTag) ||
!CBB_add_asn1_bool(&child, in->used_hello_retry_request)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3TicketAgeSkewTag) ||
!CBB_add_asn1_int64(&child, in->ticket_age_skew)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3WriteTrafficSecretTag) ||
!CBB_add_asn1_octet_string(&child, in->write_traffic_secret,
SSL_MAX_MD_SIZE)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3WriteTrafficSecretLenTag) ||
!CBB_add_asn1_uint64(&child, in->write_traffic_secret_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3ReadTrafficSecretTag) ||
!CBB_add_asn1_octet_string(&child, in->read_traffic_secret,
SSL_MAX_MD_SIZE)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3ReadTrafficSecretLenTag) ||
!CBB_add_asn1_uint64(&child, in->read_traffic_secret_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3ExporterSecretTag) ||
!CBB_add_asn1_octet_string(&child, in->exporter_secret,
SSL_MAX_MD_SIZE)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!CBB_add_asn1(&s3, &child, kS3ExporterSecretLenTag) ||
!CBB_add_asn1_uint64(&child, in->exporter_secret_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (in->hs_buf && in->hs_buf->length > 0) {
if (!CBB_add_asn1(&s3, &child, kS3HandshakeBufferTag) ||
!CBB_add_asn1_octet_string(
&child, reinterpret_cast<uint8_t *>(in->hs_buf->data),
in->hs_buf->length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (in->ech_status) {
if (!CBB_add_asn1(&s3, &child, kS3EchStatusTag) ||
!CBB_add_asn1_uint64(&child, in->ech_status)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (in->pending_hs_data && in->pending_hs_data->length > 0) {
if (!CBB_add_asn1(&s3, &child, kS3PendingHsDataTag) ||
!CBB_add_asn1_octet_string(
&child, reinterpret_cast<uint8_t *>(in->pending_hs_data->data),
in->pending_hs_data->length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (in->aead_read_ctx) {
if (!CBB_add_asn1(&s3, &child, kS3AeadReadCtxTag) ||
!in->aead_read_ctx.get()->SerializeState(&child)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (in->aead_write_ctx) {
if (!CBB_add_asn1(&s3, &child, kS3AeadWriteCtxTag) ||
!in->aead_write_ctx.get()->SerializeState(&child)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
}
return CBB_flush(cbb);
}