Home | History | Annotate | Download | only in crypto
      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