| Index: net/base/x509_certificate_win.cc
|
| ===================================================================
|
| --- net/base/x509_certificate_win.cc (revision 49024)
|
| +++ net/base/x509_certificate_win.cc (working copy)
|
| @@ -434,6 +434,99 @@
|
| }
|
| }
|
|
|
| +X509Certificate::OSCertHandle HandleFromBytes(const BYTE* data, DWORD length) {
|
| + X509Certificate::OSCertHandle cert_handle = NULL;
|
| +
|
| + if (!CertAddEncodedCertificateToStore(
|
| + NULL, // the cert won't be persisted in any cert store
|
| + X509_ASN_ENCODING,
|
| + reinterpret_cast<const BYTE*>(data), length,
|
| + CERT_STORE_ADD_USE_EXISTING,
|
| + &cert_handle))
|
| + return NULL;
|
| +
|
| + return cert_handle;
|
| +}
|
| +
|
| +void AddCertsFromStore(HCERTSTORE store,
|
| + X509Certificate::OSCertHandles* results) {
|
| + PCCERT_CONTEXT cur_cert = NULL;
|
| +
|
| + while ((cur_cert = CertEnumCertificatesInStore(store, cur_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.
|
| + cur_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 flavours of
|
| + // Windows.
|
| + 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;
|
| +}
|
| +
|
| +X509Certificate::OSCertHandles ParseNetscapeSequence(const char* data,
|
| + size_t length) {
|
| + X509Certificate::OSCertHandles results;
|
| + CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY* certs = NULL;
|
| + DWORD certs_size = 0;
|
| +
|
| + CRYPT_DECODE_PARA decode_para;
|
| + decode_para.cbSize = sizeof(decode_para);
|
| + decode_para.pfnAlloc = MyCryptAlloc;
|
| + decode_para.pfnFree = MyCryptFree;
|
| +
|
| + DWORD size = 0;
|
| + BOOL rv = CryptDecodeObjectEx(
|
| + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
| + PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
|
| + reinterpret_cast<const BYTE*>(data), length,
|
| + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
|
| + &decode_para, &certs, &certs_size);
|
| + if (rv) {
|
| + scoped_ptr_malloc<CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY> scoped_certs(certs);
|
| + for (DWORD i = 0; i < certs->cValue; ++i) {
|
| + X509Certificate::OSCertHandle handle =
|
| + HandleFromBytes(certs->rgValue[i].pbData, certs->rgValue[i].cbData);
|
| + if (handle)
|
| + results.push_back(handle);
|
| + }
|
| + }
|
| +
|
| + return results;
|
| +}
|
| +
|
| } // namespace
|
|
|
| void X509Certificate::Initialize() {
|
| @@ -737,17 +830,34 @@
|
|
|
| // static
|
| X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
|
| - const char* data, int length) {
|
| - OSCertHandle cert_handle = NULL;
|
| - if (!CertAddEncodedCertificateToStore(
|
| - NULL, // the cert won't be persisted in any cert store
|
| - X509_ASN_ENCODING,
|
| - reinterpret_cast<const BYTE*>(data), length,
|
| - CERT_STORE_ADD_USE_EXISTING,
|
| - &cert_handle))
|
| - return NULL;
|
| + const char* data, size_t length) {
|
| + return HandleFromBytes(reinterpret_cast<const BYTE*>(data), length);
|
| +}
|
|
|
| - return cert_handle;
|
| +// static
|
| +X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
|
| + const char *data, size_t length, CertificateFormat format) {
|
| + OSCertHandles results;
|
| + switch (format) {
|
| + case FORMAT_DER:
|
| + {
|
| + OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
|
| + if (handle != NULL)
|
| + results.push_back(handle);
|
| + }
|
| + break;
|
| + case FORMAT_PKCS7:
|
| + results = ParsePKCS7(data, length);
|
| + break;
|
| + case FORMAT_LEGACY_NETSCAPE:
|
| + results = ParseNetscapeSequence(data, length);
|
| + break;
|
| + default:
|
| + NOTREACHED() << "Certificate format " << format << " unimplemented";
|
| + break;
|
| + }
|
| +
|
| + return results;
|
| }
|
|
|
|
|
|
|