summaryrefslogtreecommitdiffstats
path: root/net/base/x509_certificate_nss.cc
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-22 02:31:04 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-22 02:31:04 +0000
commite5a3eef63bed48a362ea5aa06b88559f7ad34d11 (patch)
tree137e336deffa52503326bfd77faa276523d2036e /net/base/x509_certificate_nss.cc
parent7349c6b146c267b7f634d518296f631642ef7095 (diff)
downloadchromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.zip
chromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.tar.gz
chromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.tar.bz2
Add support for parsing certificate formats other than raw, DER-encoded certificates - specifically formats that represent collections of certificates. The certificate format can now be specified as an explicit format, or as a bit-mask of formats that are acceptable/expected, with the first parsable format winning.
This is one half of a commit to address BUG #37142, with the second half involving connecting this through the X509UserCertHandler and the actual UI. R=wtc BUG=37142 TEST=X509CertificateParseTest* and PEMTokenizerTest.* Review URL: http://codereview.chromium.org/2819018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53298 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/x509_certificate_nss.cc')
-rw-r--r--net/base/x509_certificate_nss.cc71
1 files changed, 63 insertions, 8 deletions
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc
index 8eb337f..07bfeb3 100644
--- a/net/base/x509_certificate_nss.cc
+++ b/net/base/x509_certificate_nss.cc
@@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/pickle.h"
+#include "base/scoped_ptr.h"
#include "base/time.h"
#include "base/nss_util.h"
#include "net/base/cert_status_flags.h"
@@ -571,6 +572,22 @@ bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle,
return false;
}
+SECStatus PR_CALLBACK
+CollectCertsCallback(void* arg, SECItem** certs, int num_certs) {
+ X509Certificate::OSCertHandles* results =
+ reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
+
+ for (int i = 0; i < num_certs; ++i) {
+ X509Certificate::OSCertHandle handle =
+ X509Certificate::CreateOSCertHandleFromBytes(
+ reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
+ if (handle)
+ results->push_back(handle);
+ }
+
+ return SECSuccess;
+}
+
} // namespace
void X509Certificate::Initialize() {
@@ -721,21 +738,59 @@ bool X509Certificate::VerifyEV() const {
// static
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
const char* data, int length) {
+ if (length < 0)
+ return NULL;
+
base::EnsureNSSInit();
if (!NSS_IsInitialized())
return NULL;
- // Make a copy of |data| since CERT_DecodeCertPackage might modify it.
- char* data_copy = new char[length];
- memcpy(data_copy, data, length);
+ SECItem der_cert;
+ der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
+ der_cert.len = length;
+ der_cert.type = siDERCertBuffer;
// Parse into a certificate structure.
- CERTCertificate* cert = CERT_DecodeCertFromPackage(data_copy, length);
- delete [] data_copy;
- if (!cert)
- LOG(ERROR) << "Couldn't parse a certificate from " << length << " bytes";
- return cert;
+ return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
+ PR_FALSE, PR_TRUE);
+}
+
+// static
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+ const char* data, int length, Format format) {
+ OSCertHandles results;
+ if (length < 0)
+ return results;
+
+ base::EnsureNSSInit();
+
+ if (!NSS_IsInitialized())
+ return results;
+
+ switch (format) {
+ case FORMAT_SINGLE_CERTIFICATE: {
+ OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
+ if (handle)
+ results.push_back(handle);
+ break;
+ }
+ case FORMAT_PKCS7: {
+ // Make a copy since CERT_DecodeCertPackage may modify it
+ std::vector<char> data_copy(data, data + length);
+
+ SECStatus result = CERT_DecodeCertPackage(&data_copy[0],
+ length, CollectCertsCallback, &results);
+ if (result != SECSuccess)
+ results.clear();
+ break;
+ }
+ default:
+ NOTREACHED() << "Certificate format " << format << " unimplemented";
+ break;
+ }
+
+ return results;
}
// static