• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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/quic/crypto/common_cert_set.h"
6 
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/memory/singleton.h"
10 #include "net/quic/quic_utils.h"
11 
12 using base::StringPiece;
13 
14 namespace net {
15 
16 namespace common_cert_set_0 {
17 #include "net/quic/crypto/common_cert_set_0.c"
18 }
19 
20 namespace {
21 
22 struct CertSet {
23   // num_certs contains the number of certificates in this set.
24   size_t num_certs;
25   // certs is an array of |num_certs| pointers to the DER encoded certificates.
26   const unsigned char* const* certs;
27   // lens is an array of |num_certs| integers describing the length, in bytes,
28   // of each certificate.
29   const size_t* lens;
30   // hash contains the 64-bit, FNV-1a hash of this set.
31   uint64 hash;
32 };
33 
34 const CertSet kSets[] = {
35   {
36     common_cert_set_0::kNumCerts,
37     common_cert_set_0::kCerts,
38     common_cert_set_0::kLens,
39     common_cert_set_0::kHash,
40   },
41 };
42 
43 const uint64 kSetHashes[] = {
44   common_cert_set_0::kHash,
45 };
46 
47 // Compare returns a value less than, equal to or greater than zero if |a| is
48 // lexicographically less than, equal to or greater than |b|, respectively.
Compare(StringPiece a,const unsigned char * b,size_t b_len)49 int Compare(StringPiece a, const unsigned char* b, size_t b_len) {
50   size_t len = a.size();
51   if (len > b_len) {
52     len = b_len;
53   }
54   int n = memcmp(a.data(), b, len);
55   if (n != 0) {
56     return n;
57   }
58 
59   if (a.size() < b_len) {
60     return -1;
61   } else if (a.size() > b_len) {
62     return 1;
63   }
64   return 0;
65 }
66 
67 // CommonCertSetsQUIC implements the CommonCertSets interface using the default
68 // certificate sets.
69 class CommonCertSetsQUIC : public CommonCertSets {
70  public:
71   // CommonCertSets interface.
GetCommonHashes() const72   virtual StringPiece GetCommonHashes() const OVERRIDE {
73     return StringPiece(reinterpret_cast<const char*>(kSetHashes),
74                        sizeof(uint64) * arraysize(kSetHashes));
75   }
76 
GetCert(uint64 hash,uint32 index) const77   virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
78     for (size_t i = 0; i < arraysize(kSets); i++) {
79       if (kSets[i].hash == hash) {
80         if (index < kSets[i].num_certs) {
81           return StringPiece(
82               reinterpret_cast<const char*>(kSets[i].certs[index]),
83               kSets[i].lens[index]);
84         }
85         break;
86       }
87     }
88 
89     return StringPiece();
90   }
91 
MatchCert(StringPiece cert,StringPiece common_set_hashes,uint64 * out_hash,uint32 * out_index) const92   virtual bool MatchCert(StringPiece cert, StringPiece common_set_hashes,
93                          uint64* out_hash, uint32* out_index) const OVERRIDE {
94     if (common_set_hashes.size() % sizeof(uint64) != 0) {
95       return false;
96     }
97 
98     for (size_t i = 0; i < common_set_hashes.size() / sizeof(uint64); i++) {
99       uint64 hash;
100       memcpy(&hash, common_set_hashes.data() + i * sizeof(uint64),
101              sizeof(uint64));
102 
103       for (size_t j = 0; j < arraysize(kSets); j++) {
104         if (kSets[j].hash != hash) {
105           continue;
106         }
107 
108         if (kSets[j].num_certs == 0) {
109           continue;
110         }
111 
112         // Binary search for a matching certificate.
113         size_t min = 0;
114         size_t max = kSets[j].num_certs - 1;
115         while (max >= min) {
116           size_t mid = min + ((max - min) / 2);
117           int n = Compare(cert, kSets[j].certs[mid], kSets[j].lens[mid]);
118           if (n < 0) {
119             if (mid == 0) {
120               break;
121             }
122             max = mid - 1;
123           } else if (n > 0) {
124             min = mid + 1;
125           } else {
126             *out_hash = hash;
127             *out_index = mid;
128             return true;
129           }
130         }
131       }
132     }
133 
134     return false;
135   }
136 
GetInstance()137   static CommonCertSetsQUIC* GetInstance() {
138     return Singleton<CommonCertSetsQUIC>::get();
139   }
140 
141  private:
CommonCertSetsQUIC()142   CommonCertSetsQUIC() {}
~CommonCertSetsQUIC()143   virtual ~CommonCertSetsQUIC() {}
144 
145   friend struct DefaultSingletonTraits<CommonCertSetsQUIC>;
146   DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
147 };
148 
149 }  // anonymous namespace
150 
~CommonCertSets()151 CommonCertSets::~CommonCertSets() {}
152 
153 // static
GetInstanceQUIC()154 const CommonCertSets* CommonCertSets::GetInstanceQUIC() {
155   return CommonCertSetsQUIC::GetInstance();
156 }
157 
158 }  // namespace net
159