static int SSL3_STATE_to_bytes()

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);
}