15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_ios.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cert.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CommonCrypto/CommonDigest.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <prtypes.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_cftyperef.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_nss.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::ScopedCFTypeRef; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace x509_util_ios { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates an NSS certificate handle from |data|, which is |length| bytes in 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// size. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificate* CreateNSSCertHandleFromBytes(const char* data, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length < 0) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::EnsureNSSInit(); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!NSS_IsInitialized()) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem der_cert; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_cert.len = length; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_cert.type = siDERCertBuffer; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse into a certificate structure. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PR_FALSE, PR_TRUE); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificate* CreateNSSCertHandleFromOSHandle( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecCertificateRef cert_handle) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateNSSCertHandleFromBytes( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFDataGetLength(cert_data)); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SecCertificateRef CreateOSCertHandleFromNSSHandle( 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* nss_cert_handle) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return X509Certificate::CreateOSCertHandleFromBytes( 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(nss_cert_handle->derCert.data), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_cert_handle->derCert.len); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate* CreateCertFromNSSHandles( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<CERTCertificate*>& intermediates) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCFTypeRef<SecCertificateRef> os_server_cert( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateOSCertHandleFromNSSHandle(cert_handle)); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!os_server_cert) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<SecCertificateRef> os_intermediates; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < intermediates.size(); ++i) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecCertificateRef intermediate = 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateOSCertHandleFromNSSHandle(intermediates[i]); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!intermediate) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_intermediates.push_back(intermediate); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate* cert = NULL; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (intermediates.size() == os_intermediates.size()) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert = X509Certificate::CreateFromHandle(os_server_cert, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_intermediates); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < os_intermediates.size(); ++i) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease(os_intermediates[i]); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert->derCert.data); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(0U, cert->derCert.len); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue sha1; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sha1.data, 0, sizeof(sha1.data)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSSCertificate implementation. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG_IF(INFO, cert_handle && !nss_cert_handle_) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Could not convert SecCertificateRef to CERTCertificate*"; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertificate::~NSSCertificate() { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificate(nss_cert_handle_); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificate* NSSCertificate::cert_handle() const { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nss_cert_handle_; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSSCertChain implementation 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertChain::NSSCertChain(X509Certificate* certificate) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(certificate); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs_.push_back(CreateNSSCertHandleFromOSHandle( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certificate->os_cert_handle())); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate::OSCertHandles& cert_intermediates = 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certificate->GetIntermediateCertificates(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < cert_intermediates.size(); ++i) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i])); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertChain::~NSSCertChain() { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < certs_.size(); ++i) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificate(certs_[i]); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificate* NSSCertChain::cert_handle() const { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return certs_.empty() ? NULL : certs_.front(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<CERTCertificate*>& NSSCertChain::cert_chain() const { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return certs_; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace x509_util_ios 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 142