| // Copyright (c) 2012 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/x509_util_ios.h" |
| |
| #include <cert.h> |
| #include <CommonCrypto/CommonDigest.h> |
| #include <nss.h> |
| #include <prtypes.h> |
| |
| #include "base/mac/scoped_cftyperef.h" |
| #include "crypto/nss_util.h" |
| #include "net/base/x509_certificate.h" |
| |
| using base::mac::ScopedCFTypeRef; |
| |
| namespace net { |
| namespace x509_util_ios { |
| |
| namespace { |
| |
| // Creates an NSS certificate handle from |data|, which is |length| bytes in |
| // size. |
| CERTCertificate* CreateNSSCertHandleFromBytes(const char* data, |
| int length) { |
| if (length < 0) |
| return NULL; |
| |
| crypto::EnsureNSSInit(); |
| |
| if (!NSS_IsInitialized()) |
| return NULL; |
| |
| 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. |
| return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, |
| PR_FALSE, PR_TRUE); |
| } |
| |
| } // namespace |
| |
| CERTCertificate* CreateNSSCertHandleFromOSHandle( |
| SecCertificateRef cert_handle) { |
| ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); |
| return CreateNSSCertHandleFromBytes( |
| reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), |
| CFDataGetLength(cert_data)); |
| } |
| |
| SecCertificateRef CreateOSCertHandleFromNSSHandle( |
| CERTCertificate* nss_cert_handle) { |
| return X509Certificate::CreateOSCertHandleFromBytes( |
| reinterpret_cast<const char*>(nss_cert_handle->derCert.data), |
| nss_cert_handle->derCert.len); |
| } |
| |
| X509Certificate* CreateCertFromNSSHandles( |
| CERTCertificate* cert_handle, |
| const std::vector<CERTCertificate*>& intermediates) { |
| ScopedCFTypeRef<SecCertificateRef> os_server_cert( |
| CreateOSCertHandleFromNSSHandle(cert_handle)); |
| if (!os_server_cert) |
| return NULL; |
| std::vector<SecCertificateRef> os_intermediates; |
| for (size_t i = 0; i < intermediates.size(); ++i) { |
| SecCertificateRef intermediate = |
| CreateOSCertHandleFromNSSHandle(intermediates[i]); |
| if (!intermediate) |
| break; |
| os_intermediates.push_back(intermediate); |
| } |
| |
| X509Certificate* cert = NULL; |
| if (intermediates.size() == os_intermediates.size()) { |
| cert = X509Certificate::CreateFromHandle(os_server_cert, |
| os_intermediates); |
| } |
| |
| for (size_t i = 0; i < os_intermediates.size(); ++i) |
| CFRelease(os_intermediates[i]); |
| return cert; |
| } |
| |
| SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) { |
| DCHECK(cert->derCert.data); |
| DCHECK_NE(0U, cert->derCert.len); |
| SHA1HashValue sha1; |
| memset(sha1.data, 0, sizeof(sha1.data)); |
| CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data); |
| return sha1; |
| } |
| |
| // NSSCertificate implementation. |
| |
| NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) { |
| nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle); |
| DLOG_IF(INFO, cert_handle && !nss_cert_handle_) |
| << "Could not convert SecCertificateRef to CERTCertificate*"; |
| } |
| |
| NSSCertificate::~NSSCertificate() { |
| CERT_DestroyCertificate(nss_cert_handle_); |
| } |
| |
| CERTCertificate* NSSCertificate::cert_handle() const { |
| return nss_cert_handle_; |
| } |
| |
| // NSSCertChain implementation |
| |
| NSSCertChain::NSSCertChain(X509Certificate* certificate) { |
| DCHECK(certificate); |
| certs_.push_back(CreateNSSCertHandleFromOSHandle( |
| certificate->os_cert_handle())); |
| const X509Certificate::OSCertHandles& cert_intermediates = |
| certificate->GetIntermediateCertificates(); |
| for (size_t i = 0; i < cert_intermediates.size(); ++i) |
| certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i])); |
| } |
| |
| NSSCertChain::~NSSCertChain() { |
| for (size_t i = 0; i < certs_.size(); ++i) |
| CERT_DestroyCertificate(certs_[i]); |
| } |
| |
| CERTCertificate* NSSCertChain::cert_handle() const { |
| return certs_.empty() ? NULL : certs_.front(); |
| } |
| |
| } // namespace x509_util_ios |
| } // namespace net |
| |