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. 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. 72 virtual StringPiece GetCommonHashes() const OVERRIDE { 73 return StringPiece(reinterpret_cast<const char*>(kSetHashes), 74 sizeof(uint64) * arraysize(kSetHashes)); 75 } 76 77 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 92 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 137 static CommonCertSetsQUIC* GetInstance() { 138 return Singleton<CommonCertSetsQUIC>::get(); 139 } 140 141 private: 142 CommonCertSetsQUIC() {} 143 virtual ~CommonCertSetsQUIC() {} 144 145 friend struct DefaultSingletonTraits<CommonCertSetsQUIC>; 146 DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC); 147 }; 148 149 } // anonymous namespace 150 151 CommonCertSets::~CommonCertSets() {} 152 153 // static 154 const CommonCertSets* CommonCertSets::GetInstanceQUIC() { 155 return CommonCertSetsQUIC::GetInstance(); 156 } 157 158 } // namespace net 159