blob: 0ccbf2d3d0c2ea9184979d78c471046081bfe26d [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
6
7#include <cstddef>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/quic_utils.h"
bnc4e9283d2019-12-17 07:08:57 -080010#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardle904ef182019-12-13 08:34:33 -080011#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012
13namespace quic {
14
15namespace common_cert_set_2 {
16#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set_2.c"
17}
18
19namespace common_cert_set_3 {
20#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set_3.c"
21}
22
23namespace {
24
25struct CertSet {
26 // num_certs contains the number of certificates in this set.
27 size_t num_certs;
28 // certs is an array of |num_certs| pointers to the DER encoded certificates.
29 const unsigned char* const* certs;
30 // lens is an array of |num_certs| integers describing the length, in bytes,
31 // of each certificate.
32 const size_t* lens;
33 // hash contains the 64-bit, FNV-1a hash of this set.
34 uint64_t hash;
35};
36
37const CertSet kSets[] = {
38 {
39 common_cert_set_2::kNumCerts,
40 common_cert_set_2::kCerts,
41 common_cert_set_2::kLens,
42 common_cert_set_2::kHash,
43 },
44 {
45 common_cert_set_3::kNumCerts,
46 common_cert_set_3::kCerts,
47 common_cert_set_3::kLens,
48 common_cert_set_3::kHash,
49 },
50};
51
52const uint64_t kSetHashes[] = {
53 common_cert_set_2::kHash,
54 common_cert_set_3::kHash,
55};
56
57// Compare returns a value less than, equal to or greater than zero if |a| is
58// lexicographically less than, equal to or greater than |b|, respectively.
dmcardle904ef182019-12-13 08:34:33 -080059int Compare(quiche::QuicheStringPiece a, const unsigned char* b, size_t b_len) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 size_t len = a.size();
61 if (len > b_len) {
62 len = b_len;
63 }
64 int n = memcmp(a.data(), b, len);
65 if (n != 0) {
66 return n;
67 }
68
69 if (a.size() < b_len) {
70 return -1;
71 } else if (a.size() > b_len) {
72 return 1;
73 }
74 return 0;
75}
76
77// CommonCertSetsQUIC implements the CommonCertSets interface using the default
78// certificate sets.
79class CommonCertSetsQUIC : public CommonCertSets {
80 public:
81 // CommonCertSets interface.
dmcardle904ef182019-12-13 08:34:33 -080082 quiche::QuicheStringPiece GetCommonHashes() const override {
83 return quiche::QuicheStringPiece(
84 reinterpret_cast<const char*>(kSetHashes),
bnc4e9283d2019-12-17 07:08:57 -080085 sizeof(uint64_t) * QUICHE_ARRAYSIZE(kSetHashes));
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 }
87
dmcardle904ef182019-12-13 08:34:33 -080088 quiche::QuicheStringPiece GetCert(uint64_t hash,
89 uint32_t index) const override {
bnc4e9283d2019-12-17 07:08:57 -080090 for (size_t i = 0; i < QUICHE_ARRAYSIZE(kSets); i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 if (kSets[i].hash == hash) {
92 if (index < kSets[i].num_certs) {
dmcardle904ef182019-12-13 08:34:33 -080093 return quiche::QuicheStringPiece(
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 reinterpret_cast<const char*>(kSets[i].certs[index]),
95 kSets[i].lens[index]);
96 }
97 break;
98 }
99 }
100
dmcardle904ef182019-12-13 08:34:33 -0800101 return quiche::QuicheStringPiece();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500102 }
103
dmcardle904ef182019-12-13 08:34:33 -0800104 bool MatchCert(quiche::QuicheStringPiece cert,
105 quiche::QuicheStringPiece common_set_hashes,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106 uint64_t* out_hash,
107 uint32_t* out_index) const override {
108 if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
109 return false;
110 }
111
112 for (size_t i = 0; i < common_set_hashes.size() / sizeof(uint64_t); i++) {
113 uint64_t hash;
114 memcpy(&hash, common_set_hashes.data() + i * sizeof(uint64_t),
115 sizeof(uint64_t));
116
bnc4e9283d2019-12-17 07:08:57 -0800117 for (size_t j = 0; j < QUICHE_ARRAYSIZE(kSets); j++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500118 if (kSets[j].hash != hash) {
119 continue;
120 }
121
122 if (kSets[j].num_certs == 0) {
123 continue;
124 }
125
126 // Binary search for a matching certificate.
127 size_t min = 0;
128 size_t max = kSets[j].num_certs - 1;
129 while (max >= min) {
130 size_t mid = min + ((max - min) / 2);
131 int n = Compare(cert, kSets[j].certs[mid], kSets[j].lens[mid]);
132 if (n < 0) {
133 if (mid == 0) {
134 break;
135 }
136 max = mid - 1;
137 } else if (n > 0) {
138 min = mid + 1;
139 } else {
140 *out_hash = hash;
141 *out_index = mid;
142 return true;
143 }
144 }
145 }
146 }
147
148 return false;
149 }
150
151 CommonCertSetsQUIC() {}
152 CommonCertSetsQUIC(const CommonCertSetsQUIC&) = delete;
153 CommonCertSetsQUIC& operator=(const CommonCertSetsQUIC&) = delete;
154 ~CommonCertSetsQUIC() override {}
155};
156
157} // anonymous namespace
158
159CommonCertSets::~CommonCertSets() {}
160
161// static
162const CommonCertSets* CommonCertSets::GetInstanceQUIC() {
163 static CommonCertSetsQUIC* certs = new CommonCertSetsQUIC();
164 return certs;
165}
166
167} // namespace quic