Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/crypto/common_cert_set.cc b/quic/core/crypto/common_cert_set.cc
new file mode 100644
index 0000000..f649619
--- /dev/null
+++ b/quic/core/crypto/common_cert_set.cc
@@ -0,0 +1,165 @@
+// 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 "base/macros.h"
+#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