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

Unified Diff: net/base/x509_certificate_win.cc

Issue 13006020: net: extract net/cert out of net/base (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/x509_certificate_unittest.cc ('k') | net/base/x509_util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/x509_certificate_win.cc
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
deleted file mode 100644
index 8a83e41a64e35a06f9feccf95e425aaaadbd5801..0000000000000000000000000000000000000000
--- a/net/base/x509_certificate_win.cc
+++ /dev/null
@@ -1,505 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/x509_certificate.h"
-
-#include <blapi.h> // Implement CalculateChainFingerprint() with NSS.
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/pickle.h"
-#include "base/sha1.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "crypto/capi_util.h"
-#include "crypto/rsa_private_key.h"
-#include "crypto/scoped_capi_types.h"
-#include "net/base/net_errors.h"
-
-#pragma comment(lib, "crypt32.lib")
-
-using base::Time;
-
-namespace net {
-
-namespace {
-
-typedef crypto::ScopedCAPIHandle<
- HCERTSTORE,
- crypto::CAPIDestroyerWithFlags<HCERTSTORE,
- CertCloseStore, 0> > ScopedHCERTSTORE;
-
-void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded,
- SYSTEMTIME* system_time) {
- system_time->wYear = exploded.year;
- system_time->wMonth = exploded.month;
- system_time->wDayOfWeek = exploded.day_of_week;
- system_time->wDay = exploded.day_of_month;
- system_time->wHour = exploded.hour;
- system_time->wMinute = exploded.minute;
- system_time->wSecond = exploded.second;
- system_time->wMilliseconds = exploded.millisecond;
-}
-
-//-----------------------------------------------------------------------------
-
-// Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
-// structure and stores it in *output.
-void GetCertSubjectAltName(PCCERT_CONTEXT cert,
- scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) {
- PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
- cert->pCertInfo->cExtension,
- cert->pCertInfo->rgExtension);
- if (!extension)
- return;
-
- CRYPT_DECODE_PARA decode_para;
- decode_para.cbSize = sizeof(decode_para);
- decode_para.pfnAlloc = crypto::CryptAlloc;
- decode_para.pfnFree = crypto::CryptFree;
- CERT_ALT_NAME_INFO* alt_name_info = NULL;
- DWORD alt_name_info_size = 0;
- BOOL rv;
- rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- szOID_SUBJECT_ALT_NAME2,
- extension->Value.pbData,
- extension->Value.cbData,
- CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
- &decode_para,
- &alt_name_info,
- &alt_name_info_size);
- if (rv)
- output->reset(alt_name_info);
-}
-
-void AddCertsFromStore(HCERTSTORE store,
- X509Certificate::OSCertHandles* results) {
- PCCERT_CONTEXT cert = NULL;
-
- while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) {
- PCCERT_CONTEXT to_add = NULL;
- if (CertAddCertificateContextToStore(
- NULL, // The cert won't be persisted in any cert store. This breaks
- // any association the context currently has to |store|, which
- // allows us, the caller, to safely close |store| without
- // releasing the cert handles.
- cert,
- CERT_STORE_ADD_USE_EXISTING,
- &to_add) && to_add != NULL) {
- // When processing stores generated from PKCS#7/PKCS#12 files, it
- // appears that the order returned is the inverse of the order that it
- // appeared in the file.
- // TODO(rsleevi): Ensure this order is consistent across all Win
- // versions
- results->insert(results->begin(), to_add);
- }
- }
-}
-
-X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) {
- X509Certificate::OSCertHandles results;
- CERT_BLOB data_blob;
- data_blob.cbData = length;
- data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data));
-
- HCERTSTORE out_store = NULL;
-
- DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
- CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
- CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED;
-
- if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types,
- CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
- &out_store, NULL, NULL) || out_store == NULL) {
- return results;
- }
-
- AddCertsFromStore(out_store, &results);
- CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG);
-
- return results;
-}
-
-// Given a CERT_NAME_BLOB, returns true if it appears in a given list,
-// formatted as a vector of strings holding DER-encoded X.509
-// DistinguishedName entries.
-bool IsCertNameBlobInIssuerList(
- CERT_NAME_BLOB* name_blob,
- const std::vector<std::string>& issuer_names) {
- for (std::vector<std::string>::const_iterator it = issuer_names.begin();
- it != issuer_names.end(); ++it) {
- CERT_NAME_BLOB issuer_blob;
- issuer_blob.pbData =
- reinterpret_cast<BYTE*>(const_cast<char*>(it->data()));
- issuer_blob.cbData = static_cast<DWORD>(it->length());
-
- BOOL rb = CertCompareCertificateName(
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob);
- if (rb)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-void X509Certificate::Initialize() {
- DCHECK(cert_handle_);
- subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData,
- cert_handle_->pCertInfo->Subject.cbData);
- issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData,
- cert_handle_->pCertInfo->Issuer.cbData);
-
- valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
- valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
-
- fingerprint_ = CalculateFingerprint(cert_handle_);
- ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
-
- const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber;
- scoped_array<uint8> serial_bytes(new uint8[serial->cbData]);
- for (unsigned i = 0; i < serial->cbData; i++)
- serial_bytes[i] = serial->pbData[serial->cbData - i - 1];
- serial_number_ = std::string(
- reinterpret_cast<char*>(serial_bytes.get()), serial->cbData);
-}
-
-// static
-X509Certificate* X509Certificate::CreateSelfSigned(
- crypto::RSAPrivateKey* key,
- const std::string& subject,
- uint32 serial_number,
- base::TimeDelta valid_duration) {
- // Get the ASN.1 encoding of the certificate subject.
- std::wstring w_subject = ASCIIToWide(subject);
- DWORD encoded_subject_length = 0;
- if (!CertStrToName(
- X509_ASN_ENCODING,
- w_subject.c_str(),
- CERT_X500_NAME_STR, NULL, NULL, &encoded_subject_length, NULL)) {
- return NULL;
- }
-
- scoped_array<BYTE> encoded_subject(new BYTE[encoded_subject_length]);
- if (!CertStrToName(
- X509_ASN_ENCODING,
- w_subject.c_str(),
- CERT_X500_NAME_STR, NULL,
- encoded_subject.get(),
- &encoded_subject_length, NULL)) {
- return NULL;
- }
-
- CERT_NAME_BLOB subject_name;
- memset(&subject_name, 0, sizeof(subject_name));
- subject_name.cbData = encoded_subject_length;
- subject_name.pbData = encoded_subject.get();
-
- CRYPT_ALGORITHM_IDENTIFIER sign_algo;
- memset(&sign_algo, 0, sizeof(sign_algo));
- sign_algo.pszObjId = szOID_RSA_SHA1RSA;
-
- base::Time not_before = base::Time::Now();
- base::Time not_after = not_before + valid_duration;
- base::Time::Exploded exploded;
-
- // Create the system time structs representing our exploded times.
- not_before.UTCExplode(&exploded);
- SYSTEMTIME start_time;
- ExplodedTimeToSystemTime(exploded, &start_time);
- not_after.UTCExplode(&exploded);
- SYSTEMTIME end_time;
- ExplodedTimeToSystemTime(exploded, &end_time);
-
- PCCERT_CONTEXT cert_handle =
- CertCreateSelfSignCertificate(key->provider(), &subject_name,
- CERT_CREATE_SELFSIGN_NO_KEY_INFO, NULL,
- &sign_algo, &start_time, &end_time, NULL);
- DCHECK(cert_handle) << "Failed to create self-signed certificate: "
- << GetLastError();
- if (!cert_handle)
- return NULL;
-
- X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
- FreeOSCertHandle(cert_handle);
- return cert;
-}
-
-void X509Certificate::GetSubjectAltName(
- std::vector<std::string>* dns_names,
- std::vector<std::string>* ip_addrs) const {
- if (dns_names)
- dns_names->clear();
- if (ip_addrs)
- ip_addrs->clear();
-
- if (!cert_handle_)
- return;
-
- scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info;
- GetCertSubjectAltName(cert_handle_, &alt_name_info);
- CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
- if (alt_name) {
- int num_entries = alt_name->cAltEntry;
- for (int i = 0; i < num_entries; i++) {
- // dNSName is an ASN.1 IA5String representing a string of ASCII
- // characters, so we can use WideToASCII here.
- const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i];
-
- if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) {
- dns_names->push_back(WideToASCII(entry.pwszDNSName));
- } else if (ip_addrs &&
- entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) {
- ip_addrs->push_back(std::string(
- reinterpret_cast<const char*>(entry.IPAddress.pbData),
- entry.IPAddress.cbData));
- }
- }
- }
-}
-
-PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const {
- // Create an in-memory certificate store to hold this certificate and
- // any intermediate certificates in |intermediate_ca_certs_|. The store
- // will be referenced in the returned PCCERT_CONTEXT, and will not be freed
- // until the PCCERT_CONTEXT is freed.
- ScopedHCERTSTORE store(CertOpenStore(
- CERT_STORE_PROV_MEMORY, 0, NULL,
- CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
- if (!store.get())
- return NULL;
-
- // NOTE: This preserves all of the properties of |os_cert_handle()| except
- // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
- // properties that hold access to already-opened private keys. If a handle
- // has already been unlocked (eg: PIN prompt), then the first time that the
- // identity is used for client auth, it may prompt the user again.
- PCCERT_CONTEXT primary_cert;
- BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(),
- CERT_STORE_ADD_ALWAYS,
- &primary_cert);
- if (!ok || !primary_cert)
- return NULL;
-
- for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
- CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i],
- CERT_STORE_ADD_ALWAYS, NULL);
- }
-
- // Note: |store| is explicitly not released, as the call to CertCloseStore()
- // when |store| goes out of scope will not actually free the store. Instead,
- // the store will be freed when |primary_cert| is freed.
- return primary_cert;
-}
-
-// static
-bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
- std::string* encoded) {
- if (!cert_handle->pbCertEncoded || !cert_handle->cbCertEncoded)
- return false;
- encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded),
- cert_handle->cbCertEncoded);
- return true;
-}
-
-// static
-bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
- X509Certificate::OSCertHandle b) {
- DCHECK(a && b);
- if (a == b)
- return true;
- return a->cbCertEncoded == b->cbCertEncoded &&
- memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
- const char* data, int length) {
- OSCertHandle cert_handle = NULL;
- if (!CertAddEncodedCertificateToStore(
- NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data),
- length, CERT_STORE_ADD_USE_EXISTING, &cert_handle))
- return NULL;
-
- return cert_handle;
-}
-
-X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
- const char* data, int length, Format format) {
- OSCertHandles results;
- switch (format) {
- case FORMAT_SINGLE_CERTIFICATE: {
- OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
- if (handle != NULL)
- results.push_back(handle);
- break;
- }
- case FORMAT_PKCS7:
- results = ParsePKCS7(data, length);
- break;
- default:
- NOTREACHED() << "Certificate format " << format << " unimplemented";
- break;
- }
-
- return results;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
- OSCertHandle cert_handle) {
- return CertDuplicateCertificateContext(cert_handle);
-}
-
-// static
-void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
- CertFreeCertificateContext(cert_handle);
-}
-
-// static
-SHA1HashValue X509Certificate::CalculateFingerprint(
- OSCertHandle cert) {
- DCHECK(NULL != cert->pbCertEncoded);
- DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded);
-
- BOOL rv;
- SHA1HashValue sha1;
- DWORD sha1_size = sizeof(sha1.data);
- rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
- cert->cbCertEncoded, sha1.data, &sha1_size);
- DCHECK(rv && sha1_size == sizeof(sha1.data));
- if (!rv)
- memset(sha1.data, 0, sizeof(sha1.data));
- return sha1;
-}
-
-// TODO(wtc): This function is implemented with NSS low-level hash
-// functions to ensure it is fast. Reimplement this function with
-// CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead.
-// static
-SHA1HashValue X509Certificate::CalculateCAFingerprint(
- const OSCertHandles& intermediates) {
- SHA1HashValue sha1;
- memset(sha1.data, 0, sizeof(sha1.data));
-
- SHA1Context* sha1_ctx = SHA1_NewContext();
- if (!sha1_ctx)
- return sha1;
- SHA1_Begin(sha1_ctx);
- for (size_t i = 0; i < intermediates.size(); ++i) {
- PCCERT_CONTEXT ca_cert = intermediates[i];
- SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded);
- }
- unsigned int result_len;
- SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH);
- SHA1_DestroyContext(sha1_ctx, PR_TRUE);
-
- return sha1;
-}
-
-// static
-X509Certificate::OSCertHandle
-X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) {
- const char* data;
- int length;
- if (!pickle_iter->ReadData(&data, &length))
- return NULL;
-
- // Legacy serialized certificates were serialized with extended attributes,
- // rather than as DER only. As a result, these serialized certificates are
- // not portable across platforms and may have side-effects on Windows due
- // to extended attributes being serialized/deserialized -
- // http://crbug.com/118706. To avoid deserializing these attributes, write
- // the deserialized cert into a temporary cert store and then create a new
- // cert from the DER - that is, without attributes.
- ScopedHCERTSTORE store(
- CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL));
- if (!store.get())
- return NULL;
-
- OSCertHandle cert_handle = NULL;
- if (!CertAddSerializedElementToStore(
- store.get(), reinterpret_cast<const BYTE*>(data), length,
- CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
- NULL, reinterpret_cast<const void **>(&cert_handle))) {
- return NULL;
- }
-
- std::string encoded;
- bool ok = GetDEREncoded(cert_handle, &encoded);
- FreeOSCertHandle(cert_handle);
- cert_handle = NULL;
-
- if (ok)
- cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size());
- return cert_handle;
-}
-
-// static
-bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
- Pickle* pickle) {
- return pickle->WriteData(
- reinterpret_cast<char*>(cert_handle->pbCertEncoded),
- cert_handle->cbCertEncoded);
-}
-
-// static
-void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
- size_t* size_bits,
- PublicKeyType* type) {
- *type = kPublicKeyTypeUnknown;
- *size_bits = 0;
-
- PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo(
- CRYPT_OID_INFO_OID_KEY,
- cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
- CRYPT_PUBKEY_ALG_OID_GROUP_ID);
- if (!oid_info)
- return;
-
- CHECK_EQ(oid_info->dwGroupId,
- static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID));
-
- *size_bits = CertGetPublicKeyLength(
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- &cert_handle->pCertInfo->SubjectPublicKeyInfo);
-
- switch (oid_info->Algid) {
- case CALG_RSA_SIGN:
- case CALG_RSA_KEYX:
- *type = kPublicKeyTypeRSA;
- break;
- case CALG_DSS_SIGN:
- *type = kPublicKeyTypeDSA;
- break;
- case CALG_ECDSA:
- *type = kPublicKeyTypeECDSA;
- break;
- case CALG_ECDH:
- *type = kPublicKeyTypeECDH;
- break;
- }
-}
-
-bool X509Certificate::IsIssuedByEncoded(
- const std::vector<std::string>& valid_issuers) {
-
- // If the certificate's issuer in the list?
- if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer,
- valid_issuers)) {
- return true;
- }
- // Otherwise, is any of the intermediate CA subjects in the list?
- for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
- it != intermediate_ca_certs_.end(); ++it) {
- if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer,
- valid_issuers)) {
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace net
« no previous file with comments | « net/base/x509_certificate_unittest.cc ('k') | net/base/x509_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698