| 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 |