1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/cert/x509_util_ios.h" 6 7 #include <cert.h> 8 #include <CommonCrypto/CommonDigest.h> 9 #include <nss.h> 10 #include <prtypes.h> 11 12 #include "base/mac/scoped_cftyperef.h" 13 #include "crypto/nss_util.h" 14 #include "net/cert/x509_certificate.h" 15 #include "net/cert/x509_util_nss.h" 16 17 using base::ScopedCFTypeRef; 18 19 namespace net { 20 namespace x509_util_ios { 21 22 namespace { 23 24 // Creates an NSS certificate handle from |data|, which is |length| bytes in 25 // size. 26 CERTCertificate* CreateNSSCertHandleFromBytes(const char* data, 27 int length) { 28 if (length < 0) 29 return NULL; 30 31 crypto::EnsureNSSInit(); 32 33 if (!NSS_IsInitialized()) 34 return NULL; 35 36 SECItem der_cert; 37 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); 38 der_cert.len = length; 39 der_cert.type = siDERCertBuffer; 40 41 // Parse into a certificate structure. 42 return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, 43 PR_FALSE, PR_TRUE); 44 } 45 46 } // namespace 47 48 CERTCertificate* CreateNSSCertHandleFromOSHandle( 49 SecCertificateRef cert_handle) { 50 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); 51 return CreateNSSCertHandleFromBytes( 52 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), 53 CFDataGetLength(cert_data)); 54 } 55 56 SecCertificateRef CreateOSCertHandleFromNSSHandle( 57 CERTCertificate* nss_cert_handle) { 58 return X509Certificate::CreateOSCertHandleFromBytes( 59 reinterpret_cast<const char*>(nss_cert_handle->derCert.data), 60 nss_cert_handle->derCert.len); 61 } 62 63 X509Certificate* CreateCertFromNSSHandles( 64 CERTCertificate* cert_handle, 65 const std::vector<CERTCertificate*>& intermediates) { 66 ScopedCFTypeRef<SecCertificateRef> os_server_cert( 67 CreateOSCertHandleFromNSSHandle(cert_handle)); 68 if (!os_server_cert) 69 return NULL; 70 std::vector<SecCertificateRef> os_intermediates; 71 for (size_t i = 0; i < intermediates.size(); ++i) { 72 SecCertificateRef intermediate = 73 CreateOSCertHandleFromNSSHandle(intermediates[i]); 74 if (!intermediate) 75 break; 76 os_intermediates.push_back(intermediate); 77 } 78 79 X509Certificate* cert = NULL; 80 if (intermediates.size() == os_intermediates.size()) { 81 cert = X509Certificate::CreateFromHandle(os_server_cert, 82 os_intermediates); 83 } 84 85 for (size_t i = 0; i < os_intermediates.size(); ++i) 86 CFRelease(os_intermediates[i]); 87 return cert; 88 } 89 90 SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) { 91 DCHECK(cert->derCert.data); 92 DCHECK_NE(0U, cert->derCert.len); 93 SHA1HashValue sha1; 94 memset(sha1.data, 0, sizeof(sha1.data)); 95 CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data); 96 return sha1; 97 } 98 99 // NSSCertificate implementation. 100 101 NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) { 102 nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle); 103 DLOG_IF(INFO, cert_handle && !nss_cert_handle_) 104 << "Could not convert SecCertificateRef to CERTCertificate*"; 105 } 106 107 NSSCertificate::~NSSCertificate() { 108 CERT_DestroyCertificate(nss_cert_handle_); 109 } 110 111 CERTCertificate* NSSCertificate::cert_handle() const { 112 return nss_cert_handle_; 113 } 114 115 // NSSCertChain implementation 116 117 NSSCertChain::NSSCertChain(X509Certificate* certificate) { 118 DCHECK(certificate); 119 certs_.push_back(CreateNSSCertHandleFromOSHandle( 120 certificate->os_cert_handle())); 121 const X509Certificate::OSCertHandles& cert_intermediates = 122 certificate->GetIntermediateCertificates(); 123 for (size_t i = 0; i < cert_intermediates.size(); ++i) 124 certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i])); 125 } 126 127 NSSCertChain::~NSSCertChain() { 128 for (size_t i = 0; i < certs_.size(); ++i) 129 CERT_DestroyCertificate(certs_[i]); 130 } 131 132 CERTCertificate* NSSCertChain::cert_handle() const { 133 return certs_.empty() ? NULL : certs_.front(); 134 } 135 136 const std::vector<CERTCertificate*>& NSSCertChain::cert_chain() const { 137 return certs_; 138 } 139 140 } // namespace x509_util_ios 141 } // namespace net 142