Index: net/base/x509_certificate_nss.cc |
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc |
index 8eb337f7353507394cf379ccd1233ff98ec3cdb5..07bfeb3e0cac2e82131fbb0e738772c34c937d70 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 |