Index: net/base/x509_certificate_win.cc |
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc |
index 901c0a636f9360f0a1cb2a60738040d2996f03b9..03434bb0d586a85bc9a53f7b1e632b8850f94ae3 100644 |
--- a/net/base/x509_certificate_win.cc |
+++ b/net/base/x509_certificate_win.cc |
@@ -434,6 +434,54 @@ void ParsePrincipal(const std::string& description, |
} |
} |
+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; |
+} |
+ |
} // namespace |
void X509Certificate::Initialize() { |
@@ -753,6 +801,27 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
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( |