| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "net/base/dnssec_keyset.h" | 5 #include "net/base/dnssec_keyset.h" | 
| 6 | 6 | 
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> | 
| 8 #include <cryptoht.h> | 8 #include <cryptoht.h> | 
| 9 #include <keyhi.h> | 9 #include <keyhi.h> | 
| 10 | 10 | 
| 11 #include "base/crypto/signature_verifier.h" | 11 #include "base/crypto/signature_verifier.h" | 
| 12 #include "base/logging.h" | 12 #include "base/logging.h" | 
| 13 #include "base/nss_util.h" | 13 #include "base/nss_util.h" | 
| 14 #include "base/scoped_ptr.h" | 14 #include "base/scoped_ptr.h" | 
| 15 #include "base/time.h" | 15 #include "base/time.h" | 
| 16 #include "net/base/dns_util.h" | 16 #include "net/base/dns_util.h" | 
| 17 | 17 | 
|  | 18 namespace { | 
|  | 19 | 
|  | 20 // These are encoded AlgorithmIdentifiers for the given signature algorithm. | 
|  | 21 const unsigned char kRSAWithSHA1[] = { | 
|  | 22   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 5, 0 | 
|  | 23 }; | 
|  | 24 | 
|  | 25 const unsigned char kRSAWithSHA256[] = { | 
|  | 26   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 5, 0 | 
|  | 27 }; | 
|  | 28 | 
|  | 29 }  // namespace | 
|  | 30 | 
| 18 namespace net { | 31 namespace net { | 
| 19 | 32 | 
| 20 DNSSECKeySet::DNSSECKeySet() | 33 DNSSECKeySet::DNSSECKeySet() | 
| 21     : ignore_timestamps_(false) { | 34     : ignore_timestamps_(false) { | 
| 22 } | 35 } | 
| 23 | 36 | 
| 24 DNSSECKeySet::~DNSSECKeySet() { | 37 DNSSECKeySet::~DNSSECKeySet() { | 
| 25 } | 38 } | 
| 26 | 39 | 
| 27 bool DNSSECKeySet::AddKey(const base::StringPiece& dnskey) { | 40 bool DNSSECKeySet::AddKey(const base::StringPiece& dnskey) { | 
| 28   uint16 keyid = DNSKEYToKeyID(dnskey); | 41   uint16 keyid = DNSKEYToKeyID(dnskey); | 
| 29   std::string der_encoded = ASN1WrapDNSKEY(dnskey); | 42   std::string der_encoded = ASN1WrapDNSKEY(dnskey); | 
| 30   if (der_encoded.empty()) | 43   if (der_encoded.empty()) | 
| 31     return false; | 44     return false; | 
| 32 | 45 | 
| 33   keyids_.push_back(keyid); | 46   keyids_.push_back(keyid); | 
| 34   public_keys_.push_back(der_encoded); | 47   public_keys_.push_back(der_encoded); | 
| 35   return true; | 48   return true; | 
| 36 } | 49 } | 
| 37 | 50 | 
| 38 // static |  | 
| 39 uint16 DNSSECKeySet::DNSKEYToKeyID(const base::StringPiece& dnskey) { |  | 
| 40   const unsigned char* data = |  | 
| 41       reinterpret_cast<const unsigned char*>(dnskey.data()); |  | 
| 42 |  | 
| 43   // RFC 4043: App B |  | 
| 44   uint32 ac = 0; |  | 
| 45   for (unsigned i = 0; i < dnskey.size(); i++) { |  | 
| 46     if (i & 1) { |  | 
| 47       ac += data[i]; |  | 
| 48     } else { |  | 
| 49       ac += static_cast<uint32>(data[i]) << 8; |  | 
| 50     } |  | 
| 51   } |  | 
| 52   ac += (ac >> 16) & 0xffff; |  | 
| 53   return ac; |  | 
| 54 } |  | 
| 55 |  | 
| 56 // These are encoded AlgorithmIdentifiers for the given signature algorithm. |  | 
| 57 static const unsigned char kRSAWithSHA1[] = { |  | 
| 58   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5, 5, 0 |  | 
| 59 }; |  | 
| 60 |  | 
| 61 static const unsigned char kRSAWithSHA256[] = { |  | 
| 62   0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 5, 0 |  | 
| 63 }; |  | 
| 64 |  | 
| 65 bool DNSSECKeySet::CheckSignature( | 51 bool DNSSECKeySet::CheckSignature( | 
| 66     const base::StringPiece& name, | 52     const base::StringPiece& name, | 
| 67     const base::StringPiece& zone, | 53     const base::StringPiece& zone, | 
| 68     const base::StringPiece& signature, | 54     const base::StringPiece& signature, | 
| 69     uint16 rrtype, | 55     uint16 rrtype, | 
| 70     const std::vector<base::StringPiece>& rrdatas) { | 56     const std::vector<base::StringPiece>& rrdatas) { | 
| 71   // signature has this format: | 57   // signature has this format: | 
| 72   //   algorithm uint8 | 58   //   algorithm uint8 | 
| 73   //   labels uint8 | 59   //   labels uint8 | 
| 74   //   ttl uint32 | 60   //   ttl uint32 | 
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 173             signature_algorithm, sig, public_keys_[i], | 159             signature_algorithm, sig, public_keys_[i], | 
| 174             base::StringPiece(reinterpret_cast<const char*>(signed_data.get()), | 160             base::StringPiece(reinterpret_cast<const char*>(signed_data.get()), | 
| 175                               signed_data_len))) { | 161                               signed_data_len))) { | 
| 176       return true; | 162       return true; | 
| 177     } | 163     } | 
| 178   } | 164   } | 
| 179 | 165 | 
| 180   return false; | 166   return false; | 
| 181 } | 167 } | 
| 182 | 168 | 
|  | 169 // static | 
|  | 170 uint16 DNSSECKeySet::DNSKEYToKeyID(const base::StringPiece& dnskey) { | 
|  | 171   const unsigned char* data = | 
|  | 172       reinterpret_cast<const unsigned char*>(dnskey.data()); | 
|  | 173 | 
|  | 174   // RFC 4043: App B | 
|  | 175   uint32 ac = 0; | 
|  | 176   for (unsigned i = 0; i < dnskey.size(); i++) { | 
|  | 177     if (i & 1) { | 
|  | 178       ac += data[i]; | 
|  | 179     } else { | 
|  | 180       ac += static_cast<uint32>(data[i]) << 8; | 
|  | 181     } | 
|  | 182   } | 
|  | 183   ac += (ac >> 16) & 0xffff; | 
|  | 184   return ac; | 
|  | 185 } | 
|  | 186 | 
| 183 void DNSSECKeySet::IgnoreTimestamps() { | 187 void DNSSECKeySet::IgnoreTimestamps() { | 
| 184   ignore_timestamps_ = true; | 188   ignore_timestamps_ = true; | 
| 185 } | 189 } | 
| 186 | 190 | 
|  | 191 bool DNSSECKeySet::VerifySignature( | 
|  | 192     base::StringPiece signature_algorithm, | 
|  | 193     base::StringPiece signature, | 
|  | 194     base::StringPiece public_key, | 
|  | 195     base::StringPiece signed_data) { | 
|  | 196   // This code is largely a copy-and-paste from | 
|  | 197   // base/crypto/signature_verifier_nss.cc. We can't change | 
|  | 198   // base::SignatureVerifier to always use NSS because we want the ability to | 
|  | 199   // be FIPS 140-2 compliant. However, we can't use base::SignatureVerifier | 
|  | 200   // here because some platforms don't support SHA256 signatures. Therefore, we | 
|  | 201   // use NSS directly. | 
|  | 202 | 
|  | 203   base::EnsureNSSInit(); | 
|  | 204 | 
|  | 205   CERTSubjectPublicKeyInfo* spki = NULL; | 
|  | 206   SECItem spki_der; | 
|  | 207   spki_der.type = siBuffer; | 
|  | 208   spki_der.data = (uint8*) public_key.data(); | 
|  | 209   spki_der.len = public_key.size(); | 
|  | 210   spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); | 
|  | 211   if (!spki) | 
|  | 212     return false; | 
|  | 213   SECKEYPublicKey* pub_key = SECKEY_ExtractPublicKey(spki); | 
|  | 214   SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki. | 
|  | 215   if (!pub_key) | 
|  | 216     return false; | 
|  | 217 | 
|  | 218   PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 
|  | 219   if (!arena) { | 
|  | 220     SECKEY_DestroyPublicKey(pub_key); | 
|  | 221     return false; | 
|  | 222   } | 
|  | 223 | 
|  | 224   SECItem sig_alg_der; | 
|  | 225   sig_alg_der.type = siBuffer; | 
|  | 226   sig_alg_der.data = (uint8*) signature_algorithm.data(); | 
|  | 227   sig_alg_der.len = signature_algorithm.size(); | 
|  | 228   SECAlgorithmID sig_alg_id; | 
|  | 229   SECStatus rv; | 
|  | 230   rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate, | 
|  | 231                               &sig_alg_der); | 
|  | 232   if (rv != SECSuccess) { | 
|  | 233     SECKEY_DestroyPublicKey(pub_key); | 
|  | 234     PORT_FreeArena(arena, PR_TRUE); | 
|  | 235     return false; | 
|  | 236   } | 
|  | 237 | 
|  | 238   SECItem sig; | 
|  | 239   sig.type = siBuffer; | 
|  | 240   sig.data = (uint8*) signature.data(); | 
|  | 241   sig.len = signature.size(); | 
|  | 242   SECOidTag hash_alg_tag; | 
|  | 243   VFYContext* vfy_context = | 
|  | 244       VFY_CreateContextWithAlgorithmID(pub_key, &sig, | 
|  | 245                                        &sig_alg_id, &hash_alg_tag, | 
|  | 246                                        NULL); | 
|  | 247   SECKEY_DestroyPublicKey(pub_key); | 
|  | 248   PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id. | 
|  | 249   if (!vfy_context) { | 
|  | 250     // A corrupted RSA signature could be detected without the data, so | 
|  | 251     // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE | 
|  | 252     // (-8182). | 
|  | 253     return false; | 
|  | 254   } | 
|  | 255 | 
|  | 256   rv = VFY_Begin(vfy_context); | 
|  | 257   if (rv != SECSuccess) { | 
|  | 258     NOTREACHED(); | 
|  | 259     return false; | 
|  | 260   } | 
|  | 261   rv = VFY_Update(vfy_context, (uint8*) signed_data.data(), signed_data.size()); | 
|  | 262   if (rv != SECSuccess) { | 
|  | 263     NOTREACHED(); | 
|  | 264     return false; | 
|  | 265   } | 
|  | 266   rv = VFY_End(vfy_context); | 
|  | 267   VFY_DestroyContext(vfy_context, PR_TRUE); | 
|  | 268 | 
|  | 269   return rv == SECSuccess; | 
|  | 270 } | 
|  | 271 | 
| 187 // This is an ASN.1 encoded AlgorithmIdentifier for RSA | 272 // This is an ASN.1 encoded AlgorithmIdentifier for RSA | 
| 188 static const unsigned char kASN1AlgorithmIdentifierRSA[] = { | 273 static const unsigned char kASN1AlgorithmIdentifierRSA[] = { | 
| 189   0x30,  //   SEQUENCE | 274   0x30,  //   SEQUENCE | 
| 190   0x0d,  //   length (11 bytes) | 275   0x0d,  //   length (11 bytes) | 
| 191   0x06,  //     OBJECT IDENTIFER | 276   0x06,  //     OBJECT IDENTIFER | 
| 192   0x09,  //     length (9 bytes) | 277   0x09,  //     length (9 bytes) | 
| 193   //              OID 1.2.840.113549.1.1.1 (RSA) | 278   //              OID 1.2.840.113549.1.1.1 (RSA) | 
| 194   0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, | 279   0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, | 
| 195   //            NULL of length 0 | 280   //            NULL of length 0 | 
| 196   0x05, 0x00, | 281   0x05, 0x00, | 
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 366   for (unsigned i = exp_length - 1; i < exp_length; i--) { | 451   for (unsigned i = exp_length - 1; i < exp_length; i--) { | 
| 367     out[j++] = exp >> (8 * i); | 452     out[j++] = exp >> (8 * i); | 
| 368     length--; | 453     length--; | 
| 369   } | 454   } | 
| 370 | 455 | 
| 371   DCHECK_EQ(0u, length); | 456   DCHECK_EQ(0u, length); | 
| 372 | 457 | 
| 373   return std::string(reinterpret_cast<char*>(out.get()), j); | 458   return std::string(reinterpret_cast<char*>(out.get()), j); | 
| 374 } | 459 } | 
| 375 | 460 | 
| 376 bool DNSSECKeySet::VerifySignature( |  | 
| 377     base::StringPiece signature_algorithm, |  | 
| 378     base::StringPiece signature, |  | 
| 379     base::StringPiece public_key, |  | 
| 380     base::StringPiece signed_data) { |  | 
| 381   // This code is largely a copy-and-paste from |  | 
| 382   // base/crypto/signature_verifier_nss.cc. We can't change |  | 
| 383   // base::SignatureVerifier to always use NSS because we want the ability to |  | 
| 384   // be FIPS 140-2 compliant. However, we can't use base::SignatureVerifier |  | 
| 385   // here because some platforms don't support SHA256 signatures. Therefore, we |  | 
| 386   // use NSS directly. |  | 
| 387 |  | 
| 388   base::EnsureNSSInit(); |  | 
| 389 |  | 
| 390   CERTSubjectPublicKeyInfo* spki = NULL; |  | 
| 391   SECItem spki_der; |  | 
| 392   spki_der.type = siBuffer; |  | 
| 393   spki_der.data = (uint8*) public_key.data(); |  | 
| 394   spki_der.len = public_key.size(); |  | 
| 395   spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); |  | 
| 396   if (!spki) |  | 
| 397     return false; |  | 
| 398   SECKEYPublicKey* pub_key = SECKEY_ExtractPublicKey(spki); |  | 
| 399   SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki. |  | 
| 400   if (!pub_key) |  | 
| 401     return false; |  | 
| 402 |  | 
| 403   PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |  | 
| 404   if (!arena) { |  | 
| 405     SECKEY_DestroyPublicKey(pub_key); |  | 
| 406     return false; |  | 
| 407   } |  | 
| 408 |  | 
| 409   SECItem sig_alg_der; |  | 
| 410   sig_alg_der.type = siBuffer; |  | 
| 411   sig_alg_der.data = (uint8*) signature_algorithm.data(); |  | 
| 412   sig_alg_der.len = signature_algorithm.size(); |  | 
| 413   SECAlgorithmID sig_alg_id; |  | 
| 414   SECStatus rv; |  | 
| 415   rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate, |  | 
| 416                               &sig_alg_der); |  | 
| 417   if (rv != SECSuccess) { |  | 
| 418     SECKEY_DestroyPublicKey(pub_key); |  | 
| 419     PORT_FreeArena(arena, PR_TRUE); |  | 
| 420     return false; |  | 
| 421   } |  | 
| 422 |  | 
| 423   SECItem sig; |  | 
| 424   sig.type = siBuffer; |  | 
| 425   sig.data = (uint8*) signature.data(); |  | 
| 426   sig.len = signature.size(); |  | 
| 427   SECOidTag hash_alg_tag; |  | 
| 428   VFYContext* vfy_context = |  | 
| 429       VFY_CreateContextWithAlgorithmID(pub_key, &sig, |  | 
| 430                                        &sig_alg_id, &hash_alg_tag, |  | 
| 431                                        NULL); |  | 
| 432   SECKEY_DestroyPublicKey(pub_key); |  | 
| 433   PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id. |  | 
| 434   if (!vfy_context) { |  | 
| 435     // A corrupted RSA signature could be detected without the data, so |  | 
| 436     // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE |  | 
| 437     // (-8182). |  | 
| 438     return false; |  | 
| 439   } |  | 
| 440 |  | 
| 441   rv = VFY_Begin(vfy_context); |  | 
| 442   if (rv != SECSuccess) { |  | 
| 443     NOTREACHED(); |  | 
| 444     return false; |  | 
| 445   } |  | 
| 446   rv = VFY_Update(vfy_context, (uint8*) signed_data.data(), signed_data.size()); |  | 
| 447   if (rv != SECSuccess) { |  | 
| 448     NOTREACHED(); |  | 
| 449     return false; |  | 
| 450   } |  | 
| 451   rv = VFY_End(vfy_context); |  | 
| 452   VFY_DestroyContext(vfy_context, PR_TRUE); |  | 
| 453 |  | 
| 454   return rv == SECSuccess; |  | 
| 455 } |  | 
| 456 |  | 
| 457 }  // namespace net | 461 }  // namespace net | 
| OLD | NEW | 
|---|