| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
| 6 | 6 |
| 7 #define PRArenaPool PLArenaPool // Required by <blapi.h>. | 7 #define PRArenaPool PLArenaPool // Required by <blapi.h>. |
| 8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. | 8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. |
| 9 | 9 |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/pickle.h" | 13 #include "base/pickle.h" |
| 14 #include "base/sha1.h" | 14 #include "base/sha1.h" |
| 15 #include "base/string_tokenizer.h" | 15 #include "base/string_tokenizer.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 18 #include "crypto/capi_util.h" |
| 18 #include "crypto/rsa_private_key.h" | 19 #include "crypto/rsa_private_key.h" |
| 19 #include "crypto/scoped_capi_types.h" | 20 #include "crypto/scoped_capi_types.h" |
| 20 #include "crypto/sha2.h" | 21 #include "crypto/sha2.h" |
| 21 #include "net/base/asn1_util.h" | 22 #include "net/base/asn1_util.h" |
| 22 #include "net/base/cert_status_flags.h" | 23 #include "net/base/cert_status_flags.h" |
| 23 #include "net/base/cert_verify_result.h" | 24 #include "net/base/cert_verify_result.h" |
| 24 #include "net/base/crl_set.h" | 25 #include "net/base/crl_set.h" |
| 25 #include "net/base/ev_root_ca_metadata.h" | 26 #include "net/base/ev_root_ca_metadata.h" |
| 26 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
| 27 #include "net/base/test_root_certs.h" | 28 #include "net/base/test_root_certs.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 system_time->wDayOfWeek = exploded.day_of_week; | 182 system_time->wDayOfWeek = exploded.day_of_week; |
| 182 system_time->wDay = exploded.day_of_month; | 183 system_time->wDay = exploded.day_of_month; |
| 183 system_time->wHour = exploded.hour; | 184 system_time->wHour = exploded.hour; |
| 184 system_time->wMinute = exploded.minute; | 185 system_time->wMinute = exploded.minute; |
| 185 system_time->wSecond = exploded.second; | 186 system_time->wSecond = exploded.second; |
| 186 system_time->wMilliseconds = exploded.millisecond; | 187 system_time->wMilliseconds = exploded.millisecond; |
| 187 } | 188 } |
| 188 | 189 |
| 189 //----------------------------------------------------------------------------- | 190 //----------------------------------------------------------------------------- |
| 190 | 191 |
| 191 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the | |
| 192 // WINAPI calling convention. | |
| 193 void* WINAPI MyCryptAlloc(size_t size) { | |
| 194 return malloc(size); | |
| 195 } | |
| 196 | |
| 197 void WINAPI MyCryptFree(void* p) { | |
| 198 free(p); | |
| 199 } | |
| 200 | |
| 201 // Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO | 192 // Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO |
| 202 // structure and stores it in *output. | 193 // structure and stores it in *output. |
| 203 void GetCertSubjectAltName(PCCERT_CONTEXT cert, | 194 void GetCertSubjectAltName(PCCERT_CONTEXT cert, |
| 204 scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) { | 195 scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) { |
| 205 PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2, | 196 PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2, |
| 206 cert->pCertInfo->cExtension, | 197 cert->pCertInfo->cExtension, |
| 207 cert->pCertInfo->rgExtension); | 198 cert->pCertInfo->rgExtension); |
| 208 if (!extension) | 199 if (!extension) |
| 209 return; | 200 return; |
| 210 | 201 |
| 211 CRYPT_DECODE_PARA decode_para; | 202 CRYPT_DECODE_PARA decode_para; |
| 212 decode_para.cbSize = sizeof(decode_para); | 203 decode_para.cbSize = sizeof(decode_para); |
| 213 decode_para.pfnAlloc = MyCryptAlloc; | 204 decode_para.pfnAlloc = crypto::CryptAllocFunction; |
| 214 decode_para.pfnFree = MyCryptFree; | 205 decode_para.pfnFree = crypto::CryptFreeFunction; |
| 215 CERT_ALT_NAME_INFO* alt_name_info = NULL; | 206 CERT_ALT_NAME_INFO* alt_name_info = NULL; |
| 216 DWORD alt_name_info_size = 0; | 207 DWORD alt_name_info_size = 0; |
| 217 BOOL rv; | 208 BOOL rv; |
| 218 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 209 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 219 szOID_SUBJECT_ALT_NAME2, | 210 szOID_SUBJECT_ALT_NAME2, |
| 220 extension->Value.pbData, | 211 extension->Value.pbData, |
| 221 extension->Value.cbData, | 212 extension->Value.cbData, |
| 222 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, | 213 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, |
| 223 &decode_para, | 214 &decode_para, |
| 224 &alt_name_info, | 215 &alt_name_info, |
| 225 &alt_name_info_size); | 216 &alt_name_info_size); |
| 226 if (rv) | 217 if (rv) |
| 227 output->reset(alt_name_info); | 218 output->reset(alt_name_info); |
| 228 } | 219 } |
| 229 | 220 |
| 230 // Returns true if any common name in the certificate's Subject field contains | 221 // Returns true if any common name in the certificate's Subject field contains |
| 231 // a NULL character. | 222 // a NULL character. |
| 232 bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) { | 223 bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) { |
| 233 CRYPT_DECODE_PARA decode_para; | 224 CRYPT_DECODE_PARA decode_para; |
| 234 decode_para.cbSize = sizeof(decode_para); | 225 decode_para.cbSize = sizeof(decode_para); |
| 235 decode_para.pfnAlloc = MyCryptAlloc; | 226 decode_para.pfnAlloc = crypto::CryptAllocFunction; |
| 236 decode_para.pfnFree = MyCryptFree; | 227 decode_para.pfnFree = crypto::CryptFreeFunction; |
| 237 CERT_NAME_INFO* name_info = NULL; | 228 CERT_NAME_INFO* name_info = NULL; |
| 238 DWORD name_info_size = 0; | 229 DWORD name_info_size = 0; |
| 239 BOOL rv; | 230 BOOL rv; |
| 240 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 231 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 241 X509_NAME, | 232 X509_NAME, |
| 242 cert->pCertInfo->Subject.pbData, | 233 cert->pCertInfo->Subject.pbData, |
| 243 cert->pCertInfo->Subject.cbData, | 234 cert->pCertInfo->Subject.cbData, |
| 244 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, | 235 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, |
| 245 &decode_para, | 236 &decode_para, |
| 246 &name_info, | 237 &name_info, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 void GetCertPoliciesInfo(PCCERT_CONTEXT cert, | 377 void GetCertPoliciesInfo(PCCERT_CONTEXT cert, |
| 387 scoped_ptr_malloc<CERT_POLICIES_INFO>* output) { | 378 scoped_ptr_malloc<CERT_POLICIES_INFO>* output) { |
| 388 PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES, | 379 PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES, |
| 389 cert->pCertInfo->cExtension, | 380 cert->pCertInfo->cExtension, |
| 390 cert->pCertInfo->rgExtension); | 381 cert->pCertInfo->rgExtension); |
| 391 if (!extension) | 382 if (!extension) |
| 392 return; | 383 return; |
| 393 | 384 |
| 394 CRYPT_DECODE_PARA decode_para; | 385 CRYPT_DECODE_PARA decode_para; |
| 395 decode_para.cbSize = sizeof(decode_para); | 386 decode_para.cbSize = sizeof(decode_para); |
| 396 decode_para.pfnAlloc = MyCryptAlloc; | 387 decode_para.pfnAlloc = crypto::CryptAllocFunction; |
| 397 decode_para.pfnFree = MyCryptFree; | 388 decode_para.pfnFree = crypto::CryptFreeFunction; |
| 398 CERT_POLICIES_INFO* policies_info = NULL; | 389 CERT_POLICIES_INFO* policies_info = NULL; |
| 399 DWORD policies_info_size = 0; | 390 DWORD policies_info_size = 0; |
| 400 BOOL rv; | 391 BOOL rv; |
| 401 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 392 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 402 szOID_CERT_POLICIES, | 393 szOID_CERT_POLICIES, |
| 403 extension->Value.pbData, | 394 extension->Value.pbData, |
| 404 extension->Value.cbData, | 395 extension->Value.cbData, |
| 405 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, | 396 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, |
| 406 &decode_para, | 397 &decode_para, |
| 407 &policies_info, | 398 &policies_info, |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) | 528 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) |
| 538 continue; | 529 continue; |
| 539 | 530 |
| 540 SHA1Fingerprint hash; | 531 SHA1Fingerprint hash; |
| 541 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), | 532 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), |
| 542 spki_bytes.size(), hash.data); | 533 spki_bytes.size(), hash.data); |
| 543 hashes->push_back(hash); | 534 hashes->push_back(hash); |
| 544 } | 535 } |
| 545 } | 536 } |
| 546 | 537 |
| 547 // A list of OIDs to decode. Any OID not on this list will be ignored for | |
| 548 // purposes of parsing. | |
| 549 const char* kOIDs[] = { | |
| 550 szOID_COMMON_NAME, | |
| 551 szOID_LOCALITY_NAME, | |
| 552 szOID_STATE_OR_PROVINCE_NAME, | |
| 553 szOID_COUNTRY_NAME, | |
| 554 szOID_STREET_ADDRESS, | |
| 555 szOID_ORGANIZATION_NAME, | |
| 556 szOID_ORGANIZATIONAL_UNIT_NAME, | |
| 557 szOID_DOMAIN_COMPONENT | |
| 558 }; | |
| 559 | |
| 560 // Converts the value for |attribute| to an ASCII string, storing the result | |
| 561 // in |value|. Returns false if the string cannot be converted. | |
| 562 bool GetAttributeValue(PCERT_RDN_ATTR attribute, | |
| 563 std::string* value) { | |
| 564 DWORD bytes_needed = CertRDNValueToStrA(attribute->dwValueType, | |
| 565 &attribute->Value, NULL, 0); | |
| 566 if (bytes_needed == 0) | |
| 567 return false; | |
| 568 if (bytes_needed == 1) { | |
| 569 // The value is actually an empty string (bytes_needed includes a single | |
| 570 // byte for a NULL value). Don't bother converting - just clear the | |
| 571 // string. | |
| 572 value->clear(); | |
| 573 return true; | |
| 574 } | |
| 575 DWORD bytes_written = CertRDNValueToStrA( | |
| 576 attribute->dwValueType, &attribute->Value, | |
| 577 WriteInto(value, bytes_needed), bytes_needed); | |
| 578 if (bytes_written <= 1) | |
| 579 return false; | |
| 580 return true; | |
| 581 } | |
| 582 | |
| 583 // Adds a type+value pair to the appropriate vector from a C array. | |
| 584 // The array is keyed by the matching OIDs from kOIDS[]. | |
| 585 bool AddTypeValuePair(PCERT_RDN_ATTR attribute, | |
| 586 std::vector<std::string>* values[]) { | |
| 587 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { | |
| 588 if (strcmp(attribute->pszObjId, kOIDs[oid]) == 0) { | |
| 589 std::string value; | |
| 590 if (!GetAttributeValue(attribute, &value)) | |
| 591 return false; | |
| 592 values[oid]->push_back(value); | |
| 593 break; | |
| 594 } | |
| 595 } | |
| 596 return true; | |
| 597 } | |
| 598 | |
| 599 // Stores the first string of the vector, if any, to *single_value. | |
| 600 void SetSingle(const std::vector<std::string>& values, | |
| 601 std::string* single_value) { | |
| 602 // We don't expect to have more than one CN, L, S, and C. | |
| 603 LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values"; | |
| 604 if (!values.empty()) | |
| 605 *single_value = values[0]; | |
| 606 } | |
| 607 | |
| 608 bool ParsePrincipal(CERT_NAME_BLOB* name, CertPrincipal* principal) { | |
| 609 CRYPT_DECODE_PARA decode_para; | |
| 610 decode_para.cbSize = sizeof(decode_para); | |
| 611 decode_para.pfnAlloc = MyCryptAlloc; | |
| 612 decode_para.pfnFree = MyCryptFree; | |
| 613 CERT_NAME_INFO* name_info = NULL; | |
| 614 DWORD name_info_size = 0; | |
| 615 BOOL rv; | |
| 616 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | |
| 617 X509_NAME, name->pbData, name->cbData, | |
| 618 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, | |
| 619 &decode_para, | |
| 620 &name_info, &name_info_size); | |
| 621 if (!rv) | |
| 622 return false; | |
| 623 scoped_ptr_malloc<CERT_NAME_INFO> scoped_name_info(name_info); | |
| 624 | |
| 625 std::vector<std::string> common_names, locality_names, state_names, | |
| 626 country_names; | |
| 627 | |
| 628 std::vector<std::string>* values[] = { | |
| 629 &common_names, &locality_names, | |
| 630 &state_names, &country_names, | |
| 631 &(principal->street_addresses), | |
| 632 &(principal->organization_names), | |
| 633 &(principal->organization_unit_names), | |
| 634 &(principal->domain_components) | |
| 635 }; | |
| 636 DCHECK(arraysize(kOIDs) == arraysize(values)); | |
| 637 | |
| 638 for (DWORD cur_rdn = 0; cur_rdn < name_info->cRDN; ++cur_rdn) { | |
| 639 PCERT_RDN rdn = &name_info->rgRDN[cur_rdn]; | |
| 640 for (DWORD cur_ava = 0; cur_ava < rdn->cRDNAttr; ++cur_ava) { | |
| 641 PCERT_RDN_ATTR ava = &rdn->rgRDNAttr[cur_ava]; | |
| 642 if (!AddTypeValuePair(ava, values)) | |
| 643 return false; | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 SetSingle(common_names, &principal->common_name); | |
| 648 SetSingle(locality_names, &principal->locality_name); | |
| 649 SetSingle(state_names, &principal->state_or_province_name); | |
| 650 SetSingle(country_names, &principal->country_name); | |
| 651 return true; | |
| 652 } | |
| 653 | 538 |
| 654 } // namespace | 539 } // namespace |
| 655 | 540 |
| 656 void X509Certificate::Initialize() { | 541 void X509Certificate::Initialize() { |
| 657 DCHECK(cert_handle_); | 542 DCHECK(cert_handle_); |
| 658 ParsePrincipal(&cert_handle_->pCertInfo->Subject, &subject_); | 543 subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, |
| 659 ParsePrincipal(&cert_handle_->pCertInfo->Issuer, &issuer_); | 544 cert_handle_->pCertInfo->Subject.cbData); |
| 545 issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, |
| 546 cert_handle_->pCertInfo->Issuer.cbData); |
| 660 | 547 |
| 661 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); | 548 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); |
| 662 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); | 549 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); |
| 663 | 550 |
| 664 fingerprint_ = CalculateFingerprint(cert_handle_); | 551 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 665 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | 552 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); |
| 666 | 553 |
| 667 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; | 554 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; |
| 668 scoped_array<uint8> serial_bytes(new uint8[serial->cbData]); | 555 scoped_array<uint8> serial_bytes(new uint8[serial->cbData]); |
| 669 for (unsigned i = 0; i < serial->cbData; i++) | 556 for (unsigned i = 0; i < serial->cbData; i++) |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 *type = kPublicKeyTypeECDH; | 1152 *type = kPublicKeyTypeECDH; |
| 1266 break; | 1153 break; |
| 1267 default: | 1154 default: |
| 1268 *type = kPublicKeyTypeUnknown; | 1155 *type = kPublicKeyTypeUnknown; |
| 1269 *size_bits = 0; | 1156 *size_bits = 0; |
| 1270 break; | 1157 break; |
| 1271 } | 1158 } |
| 1272 } | 1159 } |
| 1273 | 1160 |
| 1274 } // namespace net | 1161 } // namespace net |
| OLD | NEW |