// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/base/cert_test_util.h" #include "build/build_config.h" #if defined(USE_OPENSSL) #include #include #include #include "base/openssl_util.h" #elif defined(USE_NSS) #include #include "base/nss_util.h" #elif defined(OS_MACOSX) #include #include "base/mac/scoped_cftyperef.h" #endif #include "base/file_util.h" #include "base/logging.h" #include "base/path_service.h" #include "net/base/x509_certificate.h" namespace net { #if defined(USE_OPENSSL) X509Certificate* AddTemporaryRootCertToStore(X509* x509_cert) { if (!X509_STORE_add_cert(X509Certificate::cert_store(), x509_cert)) { unsigned long error_code = ERR_get_error(); if (ERR_GET_LIB(error_code) != ERR_LIB_X509 || ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { base::ClearOpenSSLERRStack(FROM_HERE); return NULL; } } return X509Certificate::CreateFromHandle( x509_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT, X509Certificate::OSCertHandles()); } X509Certificate* LoadTemporaryRootCert(const FilePath& filename) { base::EnsureOpenSSLInit(); std::string rawcert; if (!file_util::ReadFileToString(filename, &rawcert)) { LOG(ERROR) << "Can't load certificate " << filename.value(); return NULL; } base::ScopedOpenSSL cert_bio( BIO_new_mem_buf(const_cast(rawcert.c_str()), rawcert.length())); if (!cert_bio.get()) { LOG(ERROR) << "Can't create read-only BIO " << filename.value(); return NULL; } base::ScopedOpenSSL pem_cert(PEM_read_bio_X509( cert_bio.get(), NULL, NULL, NULL)); if (pem_cert.get()) return AddTemporaryRootCertToStore(pem_cert.get()); // File does not contain PEM data, let's try DER. const unsigned char* der_data = reinterpret_cast(rawcert.c_str()); int der_length = rawcert.length(); base::ScopedOpenSSL der_cert(d2i_X509( NULL, &der_data, der_length)); if (der_cert.get()) return AddTemporaryRootCertToStore(der_cert.get()); LOG(ERROR) << "Can't parse certificate " << filename.value(); return NULL; } #elif defined(USE_NSS) X509Certificate* LoadTemporaryRootCert(const FilePath& filename) { base::EnsureNSSInit(); std::string rawcert; if (!file_util::ReadFileToString(filename, &rawcert)) { LOG(ERROR) << "Can't load certificate " << filename.value(); return NULL; } CERTCertificate *cert; cert = CERT_DecodeCertFromPackage(const_cast(rawcert.c_str()), rawcert.length()); if (!cert) { LOG(ERROR) << "Can't convert certificate " << filename.value(); return NULL; } // TODO(port): remove this const_cast after NSS 3.12.3 is released CERTCertTrust trust; int rv = CERT_DecodeTrustString(&trust, const_cast("TCu,Cu,Tu")); if (rv != SECSuccess) { LOG(ERROR) << "Can't decode trust string"; CERT_DestroyCertificate(cert); return NULL; } rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); if (rv != SECSuccess) { LOG(ERROR) << "Can't change trust for certificate " << filename.value(); CERT_DestroyCertificate(cert); return NULL; } X509Certificate* result = X509Certificate::CreateFromHandle( cert, X509Certificate::SOURCE_LONE_CERT_IMPORT, X509Certificate::OSCertHandles()); CERT_DestroyCertificate(cert); return result; } #endif #if defined(OS_MACOSX) X509Certificate* LoadTemporaryRootCert(const FilePath& filename) { std::string rawcert; if (!file_util::ReadFileToString(filename, &rawcert)) { LOG(ERROR) << "Can't load certificate " << filename.value(); return NULL; } CFDataRef pem = CFDataCreate(kCFAllocatorDefault, reinterpret_cast(rawcert.data()), static_cast(rawcert.size())); if (!pem) return NULL; base::mac::ScopedCFTypeRef scoped_pem(pem); SecExternalFormat input_format = kSecFormatUnknown; SecExternalItemType item_type = kSecItemTypeUnknown; CFArrayRef cert_array = NULL; if (SecKeychainItemImport(pem, NULL, &input_format, &item_type, 0, NULL, NULL, &cert_array)) return NULL; base::mac::ScopedCFTypeRef scoped_cert_array(cert_array); if (!CFArrayGetCount(cert_array)) return NULL; SecCertificateRef cert_ref = static_cast( const_cast(CFArrayGetValueAtIndex(cert_array, 0))); return X509Certificate::CreateFromHandle(cert_ref, X509Certificate::SOURCE_LONE_CERT_IMPORT, X509Certificate::OSCertHandles()); } #endif } // namespace net