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 |