// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"

#include <cstddef>

#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"

namespace quic {

namespace common_cert_set_2 {
#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set_2.c"
}

namespace common_cert_set_3 {
#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set_3.c"
}

namespace {

struct CertSet {
  // num_certs contains the number of certificates in this set.
  size_t num_certs;
  // certs is an array of |num_certs| pointers to the DER encoded certificates.
  const unsigned char* const* certs;
  // lens is an array of |num_certs| integers describing the length, in bytes,
  // of each certificate.
  const size_t* lens;
  // hash contains the 64-bit, FNV-1a hash of this set.
  uint64_t hash;
};

const CertSet kSets[] = {
    {
        common_cert_set_2::kNumCerts,
        common_cert_set_2::kCerts,
        common_cert_set_2::kLens,
        common_cert_set_2::kHash,
    },
    {
        common_cert_set_3::kNumCerts,
        common_cert_set_3::kCerts,
        common_cert_set_3::kLens,
        common_cert_set_3::kHash,
    },
};

const uint64_t kSetHashes[] = {
    common_cert_set_2::kHash,
    common_cert_set_3::kHash,
};

// Compare returns a value less than, equal to or greater than zero if |a| is
// lexicographically less than, equal to or greater than |b|, respectively.
int Compare(QuicStringPiece a, const unsigned char* b, size_t b_len) {
  size_t len = a.size();
  if (len > b_len) {
    len = b_len;
  }
  int n = memcmp(a.data(), b, len);
  if (n != 0) {
    return n;
  }

  if (a.size() < b_len) {
    return -1;
  } else if (a.size() > b_len) {
    return 1;
  }
  return 0;
}

// CommonCertSetsQUIC implements the CommonCertSets interface using the default
// certificate sets.
class CommonCertSetsQUIC : public CommonCertSets {
 public:
  // CommonCertSets interface.
  QuicStringPiece GetCommonHashes() const override {
    return QuicStringPiece(reinterpret_cast<const char*>(kSetHashes),
                           sizeof(uint64_t) * QUIC_ARRAYSIZE(kSetHashes));
  }

  QuicStringPiece GetCert(uint64_t hash, uint32_t index) const override {
    for (size_t i = 0; i < QUIC_ARRAYSIZE(kSets); i++) {
      if (kSets[i].hash == hash) {
        if (index < kSets[i].num_certs) {
          return QuicStringPiece(
              reinterpret_cast<const char*>(kSets[i].certs[index]),
              kSets[i].lens[index]);
        }
        break;
      }
    }

    return QuicStringPiece();
  }

  bool MatchCert(QuicStringPiece cert,
                 QuicStringPiece common_set_hashes,
                 uint64_t* out_hash,
                 uint32_t* out_index) const override {
    if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
      return false;
    }

    for (size_t i = 0; i < common_set_hashes.size() / sizeof(uint64_t); i++) {
      uint64_t hash;
      memcpy(&hash, common_set_hashes.data() + i * sizeof(uint64_t),
             sizeof(uint64_t));

      for (size_t j = 0; j < QUIC_ARRAYSIZE(kSets); j++) {
        if (kSets[j].hash != hash) {
          continue;
        }

        if (kSets[j].num_certs == 0) {
          continue;
        }

        // Binary search for a matching certificate.
        size_t min = 0;
        size_t max = kSets[j].num_certs - 1;
        while (max >= min) {
          size_t mid = min + ((max - min) / 2);
          int n = Compare(cert, kSets[j].certs[mid], kSets[j].lens[mid]);
          if (n < 0) {
            if (mid == 0) {
              break;
            }
            max = mid - 1;
          } else if (n > 0) {
            min = mid + 1;
          } else {
            *out_hash = hash;
            *out_index = mid;
            return true;
          }
        }
      }
    }

    return false;
  }

  CommonCertSetsQUIC() {}
  CommonCertSetsQUIC(const CommonCertSetsQUIC&) = delete;
  CommonCertSetsQUIC& operator=(const CommonCertSetsQUIC&) = delete;
  ~CommonCertSetsQUIC() override {}
};

}  // anonymous namespace

CommonCertSets::~CommonCertSets() {}

// static
const CommonCertSets* CommonCertSets::GetInstanceQUIC() {
  static CommonCertSetsQUIC* certs = new CommonCertSetsQUIC();
  return certs;
}

}  // namespace quic
