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

Unified Diff: net/base/x509_certificate_mac.cc

Issue 2819018: Add support for parsing certificate formats other than raw, DER-encoded cert... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Fixup some variables/comments per wtc Created 10 years, 5 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.cc ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/x509_certificate_mac.cc
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index ed46adc3789cee966583214b9f1d2d07fcf21034..1b464f97a271bbfe118a84787ba5beaa5310b178 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -8,9 +8,9 @@
#include <Security/Security.h>
#include <time.h>
-#include "base/scoped_cftyperef.h"
#include "base/logging.h"
#include "base/pickle.h"
+#include "base/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verify_result.h"
@@ -372,6 +372,44 @@ bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
return false;
}
+// Parses |data| of length |length|, attempting to decode it as the specified
+// |format|. If |data| is in the specified format, any certificates contained
+// within are stored into |output|.
+void AddCertificatesFromBytes(const char* data, size_t length,
+ SecExternalFormat format,
+ X509Certificate::OSCertHandles* output) {
+ SecExternalFormat input_format = format;
+ scoped_cftyperef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
+ length, kCFAllocatorNull));
+
+ CFArrayRef items = NULL;
+ OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format,
+ NULL, 0, NULL, NULL, &items);
+ if (status) {
+ DLOG(WARNING) << status << " Unable to import items from data of length "
+ << length;
+ return;
+ }
+
+ scoped_cftyperef<CFArrayRef> scoped_items(items);
+ CFTypeID cert_type_id = SecCertificateGetTypeID();
+
+ for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) {
+ SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(items, i)));
+
+ // While inputFormat implies only certificates will be imported, if/when
+ // other formats (eg: PKCS#12) are supported, this may also include
+ // private keys or other items types, so filter appropriately.
+ if (CFGetTypeID(item) == cert_type_id) {
+ SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item);
+ CFRetain(cert);
+ output->push_back(cert);
+ }
+ }
+}
+
} // namespace
void X509Certificate::Initialize() {
@@ -669,15 +707,53 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
OSCertHandle cert_handle = NULL;
OSStatus status = SecCertificateCreateFromData(&cert_data,
CSSM_CERT_X_509v3,
- CSSM_CERT_ENCODING_BER,
+ CSSM_CERT_ENCODING_DER,
&cert_handle);
if (status)
return NULL;
+ // SecCertificateCreateFromData() unfortunately will not return any
+ // errors, as long as simply all pointers are present. The actual decoding
+ // of the certificate does not happen until an API that requires a CDSA
+ // handle is called. While SecCertificateGetCLHandle is the most likely
+ // candidate, as it initializes the parsing, it does not check whether the
+ // parsing was successful. Instead, SecCertificateGetSubject is used
+ // (supported since 10.3), as a means to double-check that the parsed
+ // certificate is valid.
+ const CSSM_X509_NAME* sanity_check = NULL;
+ status = SecCertificateGetSubject(cert_handle, &sanity_check);
+ if (status || !sanity_check) {
+ CFRelease(cert_handle);
+ return NULL;
+ }
+
return cert_handle;
}
// static
+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)
+ results.push_back(handle);
+ break;
+ }
+ case FORMAT_PKCS7:
+ AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results);
+ break;
+ default:
+ NOTREACHED() << "Certificate format " << format << " unimplemented";
+ break;
+ }
+
+ return results;
+}
+
+// static
X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
OSCertHandle handle) {
if (!handle)
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698