/*
 * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <openssl/ssl.h>

#include <assert.h>
#include <string.h>

#include <algorithm>

#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/rand.h>

#include "../crypto/internal.h"
#include "internal.h"


BSSL_NAMESPACE_BEGIN

ssl_open_record_t dtls1_process_ack(SSL *ssl, uint8_t *out_alert,
                                    DTLSRecordNumber ack_record_number,
                                    Span<const uint8_t> data) {
  // As a DTLS-1.3-capable client, it is possible to receive an ACK before we
  // receive ServerHello and learned the server picked DTLS 1.3. Thus, tolerate
  // but ignore ACKs before the version is set.
  if (!ssl_has_final_version(ssl)) {
    return ssl_open_record_discard;
  }

  // ACKs are only allowed in DTLS 1.3. Reject them if we've negotiated a
  // version and it's not 1.3.
  if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
    *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
    return ssl_open_record_error;
  }

  CBS cbs = data, record_numbers;
  if (!CBS_get_u16_length_prefixed(&cbs, &record_numbers) ||
      CBS_len(&cbs) != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    *out_alert = SSL_AD_DECODE_ERROR;
    return ssl_open_record_error;
  }

  while (CBS_len(&record_numbers) != 0) {
    uint64_t epoch, seq;
    if (!CBS_get_u64(&record_numbers, &epoch) ||
        !CBS_get_u64(&record_numbers, &seq)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
      *out_alert = SSL_AD_DECODE_ERROR;
      return ssl_open_record_error;
    }

    // During the handshake, records must be ACKed at the same or higher epoch.
    // See https://www.rfc-editor.org/errata/eid8108. Additionally, if the
    // record does not fit in DTLSRecordNumber, it is definitely not a record
    // number that we sent.
    if ((ack_record_number.epoch() < ssl_encryption_application &&
         epoch > ack_record_number.epoch()) ||
        epoch > UINT16_MAX || seq > DTLSRecordNumber::kMaxSequence) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
      return ssl_open_record_error;
    }

    // Find the sent record that matches this ACK.
    DTLSRecordNumber number(static_cast<uint16_t>(epoch), seq);
    DTLSSentRecord *sent_record = nullptr;
    if (ssl->d1->sent_records != nullptr) {
      for (size_t i = 0; i < ssl->d1->sent_records->size(); i++) {
        if ((*ssl->d1->sent_records)[i].number == number) {
          sent_record = &(*ssl->d1->sent_records)[i];
          break;
        }
      }
    }
    if (sent_record == nullptr) {
      // We may have sent this record and forgotten it, so this is not an error.
      continue;
    }

    // Mark each message as ACKed.
    if (sent_record->first_msg == sent_record->last_msg) {
      ssl->d1->outgoing_messages[sent_record->first_msg].acked.MarkRange(
          sent_record->first_msg_start, sent_record->last_msg_end);
    } else {
      ssl->d1->outgoing_messages[sent_record->first_msg].acked.MarkRange(
          sent_record->first_msg_start, SIZE_MAX);
      for (size_t i = size_t{sent_record->first_msg} + 1;
           i < sent_record->last_msg; i++) {
        ssl->d1->outgoing_messages[i].acked.MarkRange(0, SIZE_MAX);
      }
      if (sent_record->last_msg_end != 0) {
        ssl->d1->outgoing_messages[sent_record->last_msg].acked.MarkRange(
            0, sent_record->last_msg_end);
      }
    }

    // Clear the state so we don't bother re-marking the messages next time.
    sent_record->first_msg = 0;
    sent_record->first_msg_start = 0;
    sent_record->last_msg = 0;
    sent_record->last_msg_end = 0;
  }

  // If the outgoing flight is now fully ACKed, we are done retransmitting.
  if (std::all_of(ssl->d1->outgoing_messages.begin(),
                  ssl->d1->outgoing_messages.end(),
                  [](const auto &msg) { return msg.IsFullyAcked(); })) {
    dtls1_stop_timer(ssl);
    dtls_clear_outgoing_messages(ssl);

    // DTLS 1.3 defers the key update to when the message is ACKed.
    if (ssl->s3->key_update_pending) {
      if (!tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
        return ssl_open_record_error;
      }
      ssl->s3->key_update_pending = false;
    }

    // Check for deferred messages.
    if (ssl->d1->queued_key_update != QueuedKeyUpdate::kNone) {
      int request_type =
          ssl->d1->queued_key_update == QueuedKeyUpdate::kUpdateRequested
              ? SSL_KEY_UPDATE_REQUESTED
              : SSL_KEY_UPDATE_NOT_REQUESTED;
      ssl->d1->queued_key_update = QueuedKeyUpdate::kNone;
      if (!tls13_add_key_update(ssl, request_type)) {
        return ssl_open_record_error;
      }
    }
  } else {
    // We may still be able to drop unused write epochs.
    dtls_clear_unused_write_epochs(ssl);

    // TODO(crbug.com/42290594): Schedule a retransmit. The peer will have
    // waited before sending the ACK, so a partial ACK suggests packet loss.
  }

  ssl_do_msg_callback(ssl, /*is_write=*/0, SSL3_RT_ACK, data);
  return ssl_open_record_discard;
}

ssl_open_record_t dtls1_open_app_data(SSL *ssl, Span<uint8_t> *out,
                                      size_t *out_consumed, uint8_t *out_alert,
                                      Span<uint8_t> in) {
  assert(!SSL_in_init(ssl));

  uint8_t type;
  DTLSRecordNumber record_number;
  Span<uint8_t> record;
  auto ret = dtls_open_record(ssl, &type, &record_number, &record, out_consumed,
                              out_alert, in);
  if (ret != ssl_open_record_success) {
    return ret;
  }

  if (type == SSL3_RT_HANDSHAKE) {
    // Process handshake fragments for DTLS 1.3 post-handshake messages.
    if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
      if (!dtls1_process_handshake_fragments(ssl, out_alert, record_number,
                                             record)) {
        return ssl_open_record_error;
      }
      return ssl_open_record_discard;
    }

    // Parse the first fragment header to determine if this is a pre-CCS or
    // post-CCS handshake record. DTLS resets handshake message numbers on each
    // handshake, so renegotiations and retransmissions are ambiguous.
    //
    // TODO(crbug.com/42290594): Move this logic into
    // |dtls1_process_handshake_fragments| and integrate it into DTLS 1.3
    // retransmit conditions.
    CBS cbs, body;
    struct hm_header_st msg_hdr;
    CBS_init(&cbs, record.data(), record.size());
    if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
      *out_alert = SSL_AD_DECODE_ERROR;
      return ssl_open_record_error;
    }

    if (msg_hdr.type == SSL3_MT_FINISHED &&
        msg_hdr.seq == ssl->d1->handshake_read_seq - 1) {
      if (!ssl->d1->sending_flight && msg_hdr.frag_off == 0) {
        // Retransmit our last flight of messages. If the peer sends the second
        // Finished, they may not have received ours. Only do this for the
        // first fragment, in case the Finished was fragmented.
        //
        // This is not really a timeout, but increment the timeout count so we
        // eventually give up.
        ssl->d1->num_timeouts++;
        ssl->d1->sending_flight = true;
      }
      return ssl_open_record_discard;
    }

    // Otherwise, this is a pre-CCS handshake message from an unsupported
    // renegotiation attempt. Fall through to the error path.
  }

  if (type == SSL3_RT_ACK) {
    return dtls1_process_ack(ssl, out_alert, record_number, record);
  }

  if (type != SSL3_RT_APPLICATION_DATA) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
    *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
    return ssl_open_record_error;
  }

  if (record.empty()) {
    return ssl_open_record_discard;
  }

  *out = record;
  return ssl_open_record_success;
}

int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake,
                         size_t *out_bytes_written, Span<const uint8_t> in) {
  assert(!SSL_in_init(ssl));
  *out_needs_handshake = false;

  if (ssl->s3->write_shutdown != ssl_shutdown_none) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
    return -1;
  }

  // DTLS does not split the input across records.
  if (in.size() > SSL3_RT_MAX_PLAIN_LENGTH) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
    return -1;
  }

  if (in.empty()) {
    *out_bytes_written = 0;
    return 1;
  }

  // TODO(crbug.com/381113363): Use the 0-RTT epoch if writing 0-RTT.
  int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in,
                               ssl->d1->write_epoch.epoch());
  if (ret <= 0) {
    return ret;
  }
  *out_bytes_written = in.size();
  return 1;
}

int dtls1_write_record(SSL *ssl, int type, Span<const uint8_t> in,
                       uint16_t epoch) {
  SSLBuffer *buf = &ssl->s3->write_buffer;
  assert(in.size() <= SSL3_RT_MAX_PLAIN_LENGTH);
  // There should never be a pending write buffer in DTLS. One can't write half
  // a datagram, so the write buffer is always dropped in
  // |ssl_write_buffer_flush|.
  assert(buf->empty());

  if (in.size() > SSL3_RT_MAX_PLAIN_LENGTH) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return -1;
  }

  DTLSRecordNumber record_number;
  size_t ciphertext_len;
  if (!buf->EnsureCap(dtls_seal_prefix_len(ssl, epoch),
                      in.size() + SSL_max_seal_overhead(ssl)) ||
      !dtls_seal_record(ssl, &record_number, buf->remaining().data(),
                        &ciphertext_len, buf->remaining().size(), type,
                        in.data(), in.size(), epoch)) {
    buf->Clear();
    return -1;
  }
  buf->DidWrite(ciphertext_len);

  int ret = ssl_write_buffer_flush(ssl);
  if (ret <= 0) {
    return ret;
  }
  return 1;
}

int dtls1_dispatch_alert(SSL *ssl) {
  int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, ssl->s3->send_alert,
                               ssl->d1->write_epoch.epoch());
  if (ret <= 0) {
    return ret;
  }
  ssl->s3->alert_dispatch = false;

  // If the alert is fatal, flush the BIO now.
  if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
    BIO_flush(ssl->wbio.get());
  }

  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);

  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);

  return 1;
}

BSSL_NAMESPACE_END
