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 |