Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(569)

Side by Side Diff: net/base/x509_certificate_win.cc

Issue 9358080: Properly parse UTF8Strings in certificates on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698