Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 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/base/dnssec_keyset.h"
      6 
      7 #include <cryptohi.h>
      8 #include <cryptoht.h>
      9 #include <keyhi.h>
     10 
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/time.h"
     14 #include "crypto/nss_util.h"
     15 #include "net/base/dns_util.h"
     16 
     17 namespace {
     18 
     19 // These are encoded AlgorithmIdentifiers for the given signature algorithm.
     20 const unsigned char kRSAWithSHA1[] = {
     21   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 5, 0
     22 };
     23 
     24 const unsigned char kRSAWithSHA256[] = {
     25   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 5, 0
     26 };
     27 
     28 }  // namespace
     29 
     30 namespace net {
     31 
     32 DNSSECKeySet::DNSSECKeySet()
     33     : ignore_timestamps_(false) {
     34 }
     35 
     36 DNSSECKeySet::~DNSSECKeySet() {
     37 }
     38 
     39 bool DNSSECKeySet::AddKey(const base::StringPiece& dnskey) {
     40   uint16 keyid = DNSKEYToKeyID(dnskey);
     41   std::string der_encoded = ASN1WrapDNSKEY(dnskey);
     42   if (der_encoded.empty())
     43     return false;
     44 
     45   keyids_.push_back(keyid);
     46   public_keys_.push_back(der_encoded);
     47   return true;
     48 }
     49 
     50 bool DNSSECKeySet::CheckSignature(
     51     const base::StringPiece& name,
     52     const base::StringPiece& zone,
     53     const base::StringPiece& signature,
     54     uint16 rrtype,
     55     const std::vector<base::StringPiece>& rrdatas) {
     56   // signature has this format:
     57   //   algorithm uint8
     58   //   labels uint8
     59   //   ttl uint32
     60   //   expires uint32
     61   //   begins uint32
     62   //   keyid uint16
     63   //
     64   //   followed by the actual signature.
     65   if (signature.size() < 16)
     66     return false;
     67   const unsigned char* sigdata =
     68       reinterpret_cast<const unsigned char*>(signature.data());
     69 
     70   uint8 algorithm = sigdata[0];
     71   uint32 expires = static_cast<uint32>(sigdata[6]) << 24 |
     72                    static_cast<uint32>(sigdata[7]) << 16 |
     73                    static_cast<uint32>(sigdata[8]) << 8 |
     74                    static_cast<uint32>(sigdata[9]);
     75   uint32 begins = static_cast<uint32>(sigdata[10]) << 24 |
     76                   static_cast<uint32>(sigdata[11]) << 16 |
     77                   static_cast<uint32>(sigdata[12]) << 8 |
     78                   static_cast<uint32>(sigdata[13]);
     79   uint16 keyid = static_cast<uint16>(sigdata[14]) << 8 |
     80                  static_cast<uint16>(sigdata[15]);
     81 
     82   if (!ignore_timestamps_) {
     83     uint32 now = static_cast<uint32>(base::Time::Now().ToTimeT());
     84     if (now < begins || now >= expires)
     85       return false;
     86   }
     87 
     88   base::StringPiece sig(signature.data() + 16, signature.size() - 16);
     89 
     90   // You should have RFC 4034, 3.1.8.1 open when reading this code.
     91   unsigned signed_data_len = 0;
     92   signed_data_len += 2;  // rrtype
     93   signed_data_len += 16;  // (see signature format, above)
     94   signed_data_len += zone.size();
     95 
     96   for (std::vector<base::StringPiece>::const_iterator
     97        i = rrdatas.begin(); i != rrdatas.end(); i++) {
     98     signed_data_len += name.size();
     99     signed_data_len += 2;  // rrtype
    100     signed_data_len += 2;  // class
    101     signed_data_len += 4;  // ttl
    102     signed_data_len += 2;  // RRDATA length
    103     signed_data_len += i->size();
    104   }
    105 
    106   scoped_array<unsigned char> signed_data(new unsigned char[signed_data_len]);
    107   unsigned j = 0;
    108 
    109   signed_data[j++] = static_cast<uint8>(rrtype >> 8);
    110   signed_data[j++] = static_cast<uint8>(rrtype);
    111   memcpy(&signed_data[j], sigdata, 16);
    112   j += 16;
    113   memcpy(&signed_data[j], zone.data(), zone.size());
    114   j += zone.size();
    115 
    116   for (std::vector<base::StringPiece>::const_iterator
    117        i = rrdatas.begin(); i != rrdatas.end(); i++) {
    118     memcpy(&signed_data[j], name.data(), name.size());
    119     j += name.size();
    120     signed_data[j++] = static_cast<uint8>(rrtype >> 8);
    121     signed_data[j++] = static_cast<uint8>(rrtype);
    122     signed_data[j++] = 0;  // CLASS (always IN = 1)
    123     signed_data[j++] = 1;
    124     // Copy the TTL from |signature|.
    125     memcpy(&signed_data[j], signature.data() + 2, sizeof(uint32));
    126     j += sizeof(uint32);
    127     unsigned rrdata_len = i->size();
    128     signed_data[j++] = rrdata_len >> 8;
    129     signed_data[j++] = rrdata_len;
    130     memcpy(&signed_data[j], i->data(), i->size());
    131     j += i->size();
    132   }
    133 
    134   DCHECK_EQ(j, signed_data_len);
    135 
    136   base::StringPiece signature_algorithm;
    137   if (algorithm == kDNSSEC_RSA_SHA1 ||
    138       algorithm == kDNSSEC_RSA_SHA1_NSEC3) {
    139     signature_algorithm = base::StringPiece(
    140         reinterpret_cast<const char*>(kRSAWithSHA1),
    141         sizeof(kRSAWithSHA1));
    142   } else if (algorithm == kDNSSEC_RSA_SHA256) {
    143     signature_algorithm = base::StringPiece(
    144         reinterpret_cast<const char*>(kRSAWithSHA256),
    145         sizeof(kRSAWithSHA256));
    146   } else {
    147     // Unknown algorithm.
    148     return false;
    149   }
    150 
    151   // Check the signature with each trusted key which has a matching keyid.
    152   DCHECK_EQ(public_keys_.size(), keyids_.size());
    153   for (unsigned i = 0; i < public_keys_.size(); i++) {
    154     if (keyids_[i] != keyid)
    155       continue;
    156 
    157     if (VerifySignature(
    158             signature_algorithm, sig, public_keys_[i],
    159             base::StringPiece(reinterpret_cast<const char*>(signed_data.get()),
    160                               signed_data_len))) {
    161       return true;
    162     }
    163   }
    164 
    165   return false;
    166 }
    167 
    168 // static
    169 uint16 DNSSECKeySet::DNSKEYToKeyID(const base::StringPiece& dnskey) {
    170   const unsigned char* data =
    171       reinterpret_cast<const unsigned char*>(dnskey.data());
    172 
    173   // RFC 4043: App B
    174   uint32 ac = 0;
    175   for (unsigned i = 0; i < dnskey.size(); i++) {
    176     if (i & 1) {
    177       ac += data[i];
    178     } else {
    179       ac += static_cast<uint32>(data[i]) << 8;
    180     }
    181   }
    182   ac += (ac >> 16) & 0xffff;
    183   return ac;
    184 }
    185 
    186 void DNSSECKeySet::IgnoreTimestamps() {
    187   ignore_timestamps_ = true;
    188 }
    189 
    190 bool DNSSECKeySet::VerifySignature(
    191     base::StringPiece signature_algorithm,
    192     base::StringPiece signature,
    193     base::StringPiece public_key,
    194     base::StringPiece signed_data) {
    195   // This code is largely a copy-and-paste from
    196   // crypto/signature_verifier_nss.cc. We can't change
    197   // crypto::SignatureVerifier to always use NSS because we want the ability to
    198   // be FIPS 140-2 compliant. However, we can't use crypto::SignatureVerifier
    199   // here because some platforms don't support SHA256 signatures. Therefore, we
    200   // use NSS directly.
    201 
    202   crypto::EnsureNSSInit();
    203 
    204   CERTSubjectPublicKeyInfo* spki = NULL;
    205   SECItem spki_der;
    206   spki_der.type = siBuffer;
    207   spki_der.data = (uint8*) public_key.data();
    208   spki_der.len = public_key.size();
    209   spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
    210   if (!spki)
    211     return false;
    212   SECKEYPublicKey* pub_key = SECKEY_ExtractPublicKey(spki);
    213   SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
    214   if (!pub_key)
    215     return false;
    216 
    217   PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    218   if (!arena) {
    219     SECKEY_DestroyPublicKey(pub_key);
    220     return false;
    221   }
    222 
    223   SECItem sig_alg_der;
    224   sig_alg_der.type = siBuffer;
    225   sig_alg_der.data = (uint8*) signature_algorithm.data();
    226   sig_alg_der.len = signature_algorithm.size();
    227   SECAlgorithmID sig_alg_id;
    228   SECStatus rv;
    229   rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate,
    230                               &sig_alg_der);
    231   if (rv != SECSuccess) {
    232     SECKEY_DestroyPublicKey(pub_key);
    233     PORT_FreeArena(arena, PR_TRUE);
    234     return false;
    235   }
    236 
    237   SECItem sig;
    238   sig.type = siBuffer;
    239   sig.data = (uint8*) signature.data();
    240   sig.len = signature.size();
    241   SECOidTag hash_alg_tag;
    242   VFYContext* vfy_context =
    243       VFY_CreateContextWithAlgorithmID(pub_key, &sig,
    244                                        &sig_alg_id, &hash_alg_tag,
    245                                        NULL);
    246   SECKEY_DestroyPublicKey(pub_key);
    247   PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
    248   if (!vfy_context) {
    249     // A corrupted RSA signature could be detected without the data, so
    250     // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
    251     // (-8182).
    252     return false;
    253   }
    254 
    255   rv = VFY_Begin(vfy_context);
    256   if (rv != SECSuccess) {
    257     NOTREACHED();
    258     return false;
    259   }
    260   rv = VFY_Update(vfy_context, (uint8*) signed_data.data(), signed_data.size());
    261   if (rv != SECSuccess) {
    262     NOTREACHED();
    263     return false;
    264   }
    265   rv = VFY_End(vfy_context);
    266   VFY_DestroyContext(vfy_context, PR_TRUE);
    267 
    268   return rv == SECSuccess;
    269 }
    270 
    271 // This is an ASN.1 encoded AlgorithmIdentifier for RSA
    272 static const unsigned char kASN1AlgorithmIdentifierRSA[] = {
    273   0x30,  //   SEQUENCE
    274   0x0d,  //   length (11 bytes)
    275   0x06,  //     OBJECT IDENTIFER
    276   0x09,  //     length (9 bytes)
    277   //              OID 1.2.840.113549.1.1.1 (RSA)
    278   0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
    279   //            NULL of length 0
    280   0x05, 0x00,
    281 };
    282 
    283 // EncodeASN1Length assumes that |*length| contains the number of DER-encoded,
    284 // length-prefixed ASN.1 bytes to follow and serialises the length to |out[*j]|
    285 // and updates |j| and |length| accordingly.
    286 static void EncodeASN1Length(unsigned char* out, unsigned* j,
    287                              unsigned* length) {
    288   if ((*length - 1) < 128) {
    289     (*length) -= 1;
    290     out[(*j)++] = *length;
    291   } else if ((*length - 2) < 256) {
    292     (*length) -= 2;
    293     out[(*j)++] = 0x80 | 1;
    294     out[(*j)++] = *length;
    295   } else {
    296     (*length) -= 3;
    297     out[(*j)++] = 0x80 | 2;
    298     out[(*j)++] = *length >> 8;
    299     out[(*j)++] = *length;
    300   }
    301 }
    302 
    303 // AdvanceForASN1Length returns the number of bytes required to encode a ASN1
    304 // DER length value of |remaining|.
    305 static unsigned AdvanceForASN1Length(unsigned remaining) {
    306   if (remaining < 128) {
    307     return 1;
    308   } else if (remaining < 256) {
    309     return 2;
    310   } else if (remaining < 65536) {
    311     return 3;
    312   } else {
    313     NOTREACHED();
    314     return 3;
    315   }
    316 }
    317 
    318 // ASN1WrapDNSKEY converts the DNSKEY RDATA in |dnskey| into the ASN.1 wrapped
    319 // format expected by NSS. To wit:
    320 //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
    321 //       algorithm            AlgorithmIdentifier,
    322 //       subjectPublicKey     BIT STRING  }
    323 std::string DNSSECKeySet::ASN1WrapDNSKEY(const base::StringPiece& dnskey) {
    324   const unsigned char* data =
    325     reinterpret_cast<const unsigned char*>(dnskey.data());
    326 
    327   if (dnskey.size() < 5 || dnskey.size() > 32767)
    328     return "";
    329   const uint8 algorithm = data[3];
    330   if (algorithm != kDNSSEC_RSA_SHA1 &&
    331       algorithm != kDNSSEC_RSA_SHA1_NSEC3 &&
    332       algorithm != kDNSSEC_RSA_SHA256) {
    333     return "";
    334   }
    335 
    336   unsigned exp_length;
    337   unsigned exp_offset;
    338   // First we extract the public exponent.
    339   if (data[4] == 0) {
    340     if (dnskey.size() < 7)
    341       return "";
    342     exp_length = static_cast<unsigned>(data[5]) << 8 |
    343                  static_cast<unsigned>(data[6]);
    344     exp_offset = 7;
    345   } else {
    346     exp_length = static_cast<unsigned>(data[4]);
    347     exp_offset = 5;
    348   }
    349 
    350   // We refuse to deal with large public exponents.
    351   if (exp_length > 3)
    352     return "";
    353   if (dnskey.size() < exp_offset + exp_length)
    354     return "";
    355 
    356   unsigned exp = 0;
    357   for (unsigned i = 0; i < exp_length; i++) {
    358     exp <<= 8;
    359     exp |= static_cast<unsigned>(data[exp_offset + i]);
    360   }
    361 
    362   unsigned n_offset = exp_offset + exp_length;
    363   unsigned n_length = dnskey.size() - n_offset;
    364 
    365   // Anything smaller than 512 bits is too weak to be trusted.
    366   if (n_length < 64)
    367     return "";
    368 
    369   // If the MSB of exp is true then we need to prefix a zero byte to stop the
    370   // ASN.1 encoding from being negative.
    371   if (exp & (1 << ((8 * exp_length) - 1)))
    372     exp_length++;
    373 
    374   // Likewise with the modulus
    375   unsigned n_padding = data[n_offset] & 0x80 ? 1 : 0;
    376 
    377   // We now calculate the length of the full ASN.1 encoded public key. We're
    378   // working backwards from the end of the structure. Keep in mind that it's:
    379   //   SEQUENCE
    380   //     AlgorithmIdentifier
    381   //     BITSTRING
    382   //       SEQUENCE
    383   //         INTEGER
    384   //         INTEGER
    385   unsigned length = 0;
    386   length += exp_length;  // exponent data
    387   length++;  // we know that |exp_length| < 128
    388   length++;  // INTEGER tag for exponent
    389   length += n_length + n_padding;
    390   length += AdvanceForASN1Length(n_length + n_padding);
    391   length++;  // INTEGER tag for modulus
    392   length += AdvanceForASN1Length(length); // SEQUENCE length
    393   length++;  // SEQUENCE tag
    394   length++;  // BITSTRING unused bits
    395   length += AdvanceForASN1Length(length); // BITSTRING length
    396   length++;  // BITSTRING tag
    397   length += sizeof(kASN1AlgorithmIdentifierRSA);
    398   length += AdvanceForASN1Length(length); // SEQUENCE length
    399   length++;  // SEQUENCE tag
    400 
    401   scoped_array<unsigned char> out(new unsigned char[length]);
    402 
    403   // Now we walk forwards and serialise the ASN.1, undoing the steps above.
    404   unsigned j = 0;
    405   out[j++] = 0x30;  // SEQUENCE
    406   length--;
    407   EncodeASN1Length(out.get(), &j, &length);
    408   memcpy(&out[j], kASN1AlgorithmIdentifierRSA,
    409          sizeof(kASN1AlgorithmIdentifierRSA));
    410   j += sizeof(kASN1AlgorithmIdentifierRSA);
    411   length -= sizeof(kASN1AlgorithmIdentifierRSA);
    412   out[j++] = 3;  // BITSTRING tag
    413   length--;
    414   EncodeASN1Length(out.get(), &j, &length);
    415   out[j++] = 0;  // BITSTRING unused bits
    416   length--;
    417   out[j++] = 0x30;  // SEQUENCE
    418   length--;
    419   EncodeASN1Length(out.get(), &j, &length);
    420   out[j++] = 2;  // INTEGER
    421   length--;
    422   unsigned l = n_length + n_padding;
    423   if (l < 128) {
    424     out[j++] = l;
    425     length--;
    426   } else if (l < 256) {
    427     out[j++] = 0x80 | 1;
    428     out[j++] = l;
    429     length -= 2;
    430   } else if (l < 65536) {
    431     out[j++] = 0x80 | 2;
    432     out[j++] = l >> 8;
    433     out[j++] = l;
    434     length -= 3;
    435   } else {
    436     NOTREACHED();
    437   }
    438 
    439   if (n_padding) {
    440     out[j++] = 0;
    441     length--;
    442   }
    443   memcpy(&out[j], &data[n_offset], n_length);
    444   j += n_length;
    445   length -= n_length;
    446   out[j++] = 2;  // INTEGER
    447   length--;
    448   out[j++] = exp_length;
    449   length--;
    450   for (unsigned i = exp_length - 1; i < exp_length; i--) {
    451     out[j++] = exp >> (8 * i);
    452     length--;
    453   }
    454 
    455   DCHECK_EQ(0u, length);
    456 
    457   return std::string(reinterpret_cast<char*>(out.get()), j);
    458 }
    459 
    460 }  // namespace net
    461