| 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
|
|
|