15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <blapi.h> // Implement CalculateChainFingerprint() with NSS. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h" 135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/capi_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_capi_types.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "crypt32.lib") 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef crypto::ScopedCAPIHandle< 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HCERTSTORE, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::CAPIDestroyerWithFlags<HCERTSTORE, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertCloseStore, 0> > ScopedHCERTSTORE; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME* system_time) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wYear = exploded.year; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wMonth = exploded.month; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wDayOfWeek = exploded.day_of_week; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wDay = exploded.day_of_month; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wHour = exploded.hour; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wMinute = exploded.minute; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wSecond = exploded.second; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_time->wMilliseconds = exploded.millisecond; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// structure and stores it in *output. 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GetCertSubjectAltName( 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PCCERT_CONTEXT cert, 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter>* output) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->pCertInfo->cExtension, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->pCertInfo->rgExtension); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRYPT_DECODE_PARA decode_para; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_para.cbSize = sizeof(decode_para); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_para.pfnAlloc = crypto::CryptAlloc; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_para.pfnFree = crypto::CryptFree; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_ALT_NAME_INFO* alt_name_info = NULL; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD alt_name_info_size = 0; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL rv; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) szOID_SUBJECT_ALT_NAME2, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension->Value.pbData, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension->Value.cbData, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &decode_para, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &alt_name_info, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &alt_name_info_size); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->reset(alt_name_info); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddCertsFromStore(HCERTSTORE store, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandles* results) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCCERT_CONTEXT cert = NULL; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCCERT_CONTEXT to_add = NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CertAddCertificateContextToStore( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // The cert won't be persisted in any cert store. This breaks 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any association the context currently has to |store|, which 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allows us, the caller, to safely close |store| without 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // releasing the cert handles. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_ADD_USE_EXISTING, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &to_add) && to_add != NULL) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When processing stores generated from PKCS#7/PKCS#12 files, it 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears that the order returned is the inverse of the order that it 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appeared in the file. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rsleevi): Ensure this order is consistent across all Win 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // versions 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->insert(results->begin(), to_add); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandles results; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_BLOB data_blob; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_blob.cbData = length; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HCERTSTORE out_store = NULL; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &out_store, NULL, NULL) || out_store == NULL) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return results; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddCertsFromStore(out_store, &results); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return results; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Given a CERT_NAME_BLOB, returns true if it appears in a given list, 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// formatted as a vector of strings holding DER-encoded X.509 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DistinguishedName entries. 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsCertNameBlobInIssuerList( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERT_NAME_BLOB* name_blob, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& issuer_names) { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<std::string>::const_iterator it = issuer_names.begin(); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != issuer_names.end(); ++it) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERT_NAME_BLOB issuer_blob; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) issuer_blob.pbData = 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<BYTE*>(const_cast<char*>(it->data())); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) issuer_blob.cbData = static_cast<DWORD>(it->length()); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BOOL rb = CertCompareCertificateName( 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rb) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::Initialize() { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_handle_); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle_->pCertInfo->Subject.cbData); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle_->pCertInfo->Issuer.cbData); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fingerprint_ = CalculateFingerprint(cert_handle_); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0; i < serial->cbData; i++) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serial_bytes[i] = serial->pbData[serial->cbData - i - 1]; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serial_number_ = std::string( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetSubjectAltName( 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* dns_names, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* ip_addrs) const { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dns_names) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dns_names->clear(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ip_addrs) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip_addrs->clear(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cert_handle_) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCertSubjectAltName(cert_handle_, &alt_name_info); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alt_name) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_entries = alt_name->cAltEntry; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_entries; i++) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dNSName is an ASN.1 IA5String representing a string of ASCII 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // characters, so we can use UTF16ToASCII here. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i]; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) { 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName)); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ip_addrs && 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip_addrs->push_back(std::string( 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(entry.IPAddress.pbData), 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.IPAddress.cbData)); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an in-memory certificate store to hold this certificate and 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any intermediate certificates in |intermediate_ca_certs_|. The store 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be referenced in the returned PCCERT_CONTEXT, and will not be freed 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // until the PCCERT_CONTEXT is freed. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedHCERTSTORE store(CertOpenStore( 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_PROV_MEMORY, 0, NULL, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!store.get()) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This preserves all of the properties of |os_cert_handle()| except 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // properties that hold access to already-opened private keys. If a handle 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has already been unlocked (eg: PIN prompt), then the first time that the 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // identity is used for client auth, it may prompt the user again. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCCERT_CONTEXT primary_cert; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(), 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_ADD_ALWAYS, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &primary_cert); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ok || !primary_cert) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i], 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_ADD_ALWAYS, NULL); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: |store| is explicitly not released, as the call to CertCloseStore() 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when |store| goes out of scope will not actually free the store. Instead, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the store will be freed when |primary_cert| is freed. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return primary_cert; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* encoded) { 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cert_handle || !cert_handle->pbCertEncoded || 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !cert_handle->cbCertEncoded) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded), 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle->cbCertEncoded); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandle b) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(a && b); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a == b) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a->cbCertEncoded == b->cbCertEncoded && 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, int length) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert_handle = NULL; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CertAddEncodedCertificateToStore( 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data), 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length, CERT_STORE_ADD_USE_EXISTING, &cert_handle)) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert_handle; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, int length, Format format) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandles results; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (format) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FORMAT_SINGLE_CERTIFICATE: { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle != NULL) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results.push_back(handle); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FORMAT_PKCS7: 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results = ParsePKCS7(data, length); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Certificate format " << format << " unimplemented"; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return results; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert_handle) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CertDuplicateCertificateContext(cert_handle); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertFreeCertificateContext(cert_handle); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateFingerprint( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(NULL != cert->pbCertEncoded); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL rv; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue sha1; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD sha1_size = sizeof(sha1.data); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->cbCertEncoded, sha1.data, &sha1_size); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(rv && sha1_size == sizeof(sha1.data)); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rv) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sha1.data, 0, sizeof(sha1.data)); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(wtc): This function is implemented with NSS low-level hash 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions to ensure it is fast. Reimplement this function with 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateCAFingerprint( 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OSCertHandles& intermediates) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue sha1; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sha1.data, 0, sizeof(sha1.data)); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1Context* sha1_ctx = SHA1_NewContext(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sha1_ctx) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1_Begin(sha1_ctx); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < intermediates.size(); ++i) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCCERT_CONTEXT ca_cert = intermediates[i]; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int result_len; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1_DestroyContext(sha1_ctx, PR_TRUE); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pickle_iter->ReadData(&data, &length)) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Legacy serialized certificates were serialized with extended attributes, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rather than as DER only. As a result, these serialized certificates are 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not portable across platforms and may have side-effects on Windows due 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to extended attributes being serialized/deserialized - 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/118706. To avoid deserializing these attributes, write 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the deserialized cert into a temporary cert store and then create a new 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert from the DER - that is, without attributes. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedHCERTSTORE store( 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!store.get()) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert_handle = NULL; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CertAddSerializedElementToStore( 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store.get(), reinterpret_cast<const BYTE*>(data), length, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, reinterpret_cast<const void **>(&cert_handle))) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = GetDEREncoded(cert_handle, &encoded); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeOSCertHandle(cert_handle); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle = NULL; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size()); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert_handle; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pickle* pickle) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pickle->WriteData( 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(cert_handle->pbCertEncoded), 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle->cbCertEncoded); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* size_bits, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PublicKeyType* type) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeUnknown; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size_bits = 0; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo( 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRYPT_OID_INFO_OID_KEY, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRYPT_PUBKEY_ALG_OID_GROUP_ID); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!oid_info) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(oid_info->dwGroupId, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID)); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size_bits = CertGetPublicKeyLength( 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert_handle->pCertInfo->SubjectPublicKeyInfo); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) { 410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS 411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // (0xFFFFFFFE). Need to handle it as a special case. 412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) { 413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *type = kPublicKeyTypeECDSA; 414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) NOTREACHED(); 416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (oid_info->Algid) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CALG_RSA_SIGN: 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CALG_RSA_KEYX: 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeRSA; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CALG_DSS_SIGN: 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeDSA; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CALG_ECDSA: 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeECDSA; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CALG_ECDH: 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeECDH; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool X509Certificate::IsIssuedByEncoded( 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& valid_issuers) { 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the certificate's issuer in the list? 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer, 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) valid_issuers)) { 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, is any of the intermediate CA subjects in the list? 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != intermediate_ca_certs_.end(); ++it) { 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer, 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) valid_issuers)) { 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 457