x509_certificate_nss.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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_certificate.h" 6 7#include <cert.h> 8#include <cryptohi.h> 9#include <keyhi.h> 10#include <nss.h> 11#include <pk11pub.h> 12#include <prtime.h> 13#include <seccomon.h> 14#include <secder.h> 15#include <sechash.h> 16 17#include "base/logging.h" 18#include "base/memory/scoped_ptr.h" 19#include "base/pickle.h" 20#include "base/strings/stringprintf.h" 21#include "base/time/time.h" 22#include "crypto/nss_util.h" 23#include "crypto/scoped_nss_types.h" 24#include "net/cert/x509_util_nss.h" 25 26namespace net { 27 28void X509Certificate::Initialize() { 29 x509_util::ParsePrincipal(&cert_handle_->subject, &subject_); 30 x509_util::ParsePrincipal(&cert_handle_->issuer, &issuer_); 31 32 x509_util::ParseDate(&cert_handle_->validity.notBefore, &valid_start_); 33 x509_util::ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); 34 35 fingerprint_ = CalculateFingerprint(cert_handle_); 36 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); 37 38 serial_number_ = x509_util::ParseSerialNumber(cert_handle_); 39} 40 41// static 42X509Certificate* X509Certificate::CreateFromBytesWithNickname( 43 const char* data, 44 int length, 45 const char* nickname) { 46 OSCertHandle cert_handle = CreateOSCertHandleFromBytesWithNickname(data, 47 length, 48 nickname); 49 if (!cert_handle) 50 return NULL; 51 52 X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles()); 53 FreeOSCertHandle(cert_handle); 54 55 if (nickname) 56 cert->default_nickname_ = nickname; 57 58 return cert; 59} 60 61std::string X509Certificate::GetDefaultNickname(CertType type) const { 62 if (!default_nickname_.empty()) 63 return default_nickname_; 64 65 std::string result; 66 if (type == USER_CERT && cert_handle_->slot) { 67 // Find the private key for this certificate and see if it has a 68 // nickname. If there is a private key, and it has a nickname, then 69 // return that nickname. 70 SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert( 71 cert_handle_->slot, 72 cert_handle_, 73 NULL); // wincx 74 if (private_key) { 75 char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key); 76 if (private_key_nickname) { 77 result = private_key_nickname; 78 PORT_Free(private_key_nickname); 79 SECKEY_DestroyPrivateKey(private_key); 80 return result; 81 } 82 SECKEY_DestroyPrivateKey(private_key); 83 } 84 } 85 86 switch (type) { 87 case CA_CERT: { 88 char* nickname = CERT_MakeCANickname(cert_handle_); 89 result = nickname; 90 PORT_Free(nickname); 91 break; 92 } 93 case USER_CERT: { 94 std::string subject_name = subject_.GetDisplayName(); 95 if (subject_name.empty()) { 96 const char* email = CERT_GetFirstEmailAddress(cert_handle_); 97 if (email) 98 subject_name = email; 99 } 100 // TODO(gspencer): Internationalize this. It's wrong to assume English 101 // here. 102 result = base::StringPrintf("%s's %s ID", subject_name.c_str(), 103 issuer_.GetDisplayName().c_str()); 104 break; 105 } 106 case SERVER_CERT: 107 result = subject_.GetDisplayName(); 108 break; 109 case OTHER_CERT: 110 default: 111 break; 112 } 113 return result; 114} 115 116void X509Certificate::GetSubjectAltName( 117 std::vector<std::string>* dns_names, 118 std::vector<std::string>* ip_addrs) const { 119 x509_util::GetSubjectAltName(cert_handle_, dns_names, ip_addrs); 120} 121 122bool X509Certificate::IsIssuedByEncoded( 123 const std::vector<std::string>& valid_issuers) { 124 // Get certificate chain as scoped list of CERTCertificate objects. 125 std::vector<CERTCertificate*> cert_chain; 126 cert_chain.push_back(cert_handle_); 127 for (size_t n = 0; n < intermediate_ca_certs_.size(); ++n) { 128 cert_chain.push_back(intermediate_ca_certs_[n]); 129 } 130 // Convert encoded issuers to scoped CERTName* list. 131 std::vector<CERTName*> issuers; 132 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 133 if (!x509_util::GetIssuersFromEncodedList(valid_issuers, 134 arena.get(), 135 &issuers)) { 136 return false; 137 } 138 return x509_util::IsCertificateIssuedBy(cert_chain, issuers); 139} 140 141// static 142bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, 143 std::string* encoded) { 144 if (!cert_handle || !cert_handle->derCert.len) 145 return false; 146 encoded->assign(reinterpret_cast<char*>(cert_handle->derCert.data), 147 cert_handle->derCert.len); 148 return true; 149} 150 151// static 152bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 153 X509Certificate::OSCertHandle b) { 154 DCHECK(a && b); 155 if (a == b) 156 return true; 157 return a->derCert.len == b->derCert.len && 158 memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; 159} 160 161// static 162X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 163 const char* data, int length) { 164 return CreateOSCertHandleFromBytesWithNickname(data, length, NULL); 165} 166 167// static 168X509Certificate::OSCertHandle 169X509Certificate::CreateOSCertHandleFromBytesWithNickname( 170 const char* data, 171 int length, 172 const char* nickname) { 173 if (length < 0) 174 return NULL; 175 176 crypto::EnsureNSSInit(); 177 178 if (!NSS_IsInitialized()) 179 return NULL; 180 181 SECItem der_cert; 182 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); 183 der_cert.len = length; 184 der_cert.type = siDERCertBuffer; 185 186 // Parse into a certificate structure. 187 return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, 188 const_cast<char*>(nickname), 189 PR_FALSE, PR_TRUE); 190} 191 192// static 193X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 194 const char* data, 195 int length, 196 Format format) { 197 return x509_util::CreateOSCertHandlesFromBytes(data, length, format); 198} 199 200// static 201X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 202 OSCertHandle cert_handle) { 203 return CERT_DupCertificate(cert_handle); 204} 205 206// static 207void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 208 CERT_DestroyCertificate(cert_handle); 209} 210 211// static 212SHA1HashValue X509Certificate::CalculateFingerprint( 213 OSCertHandle cert) { 214 SHA1HashValue sha1; 215 memset(sha1.data, 0, sizeof(sha1.data)); 216 217 DCHECK(NULL != cert->derCert.data); 218 DCHECK_NE(0U, cert->derCert.len); 219 220 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, 221 cert->derCert.data, cert->derCert.len); 222 DCHECK_EQ(SECSuccess, rv); 223 224 return sha1; 225} 226 227// static 228SHA1HashValue X509Certificate::CalculateCAFingerprint( 229 const OSCertHandles& intermediates) { 230 SHA1HashValue sha1; 231 memset(sha1.data, 0, sizeof(sha1.data)); 232 233 HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1); 234 if (!sha1_ctx) 235 return sha1; 236 HASH_Begin(sha1_ctx); 237 for (size_t i = 0; i < intermediates.size(); ++i) { 238 CERTCertificate* ca_cert = intermediates[i]; 239 HASH_Update(sha1_ctx, ca_cert->derCert.data, ca_cert->derCert.len); 240 } 241 unsigned int result_len; 242 HASH_End(sha1_ctx, sha1.data, &result_len, HASH_ResultLenContext(sha1_ctx)); 243 HASH_Destroy(sha1_ctx); 244 245 return sha1; 246} 247 248// static 249X509Certificate::OSCertHandle 250X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { 251 return x509_util::ReadOSCertHandleFromPickle(pickle_iter); 252} 253 254// static 255bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, 256 Pickle* pickle) { 257 return pickle->WriteData( 258 reinterpret_cast<const char*>(cert_handle->derCert.data), 259 cert_handle->derCert.len); 260} 261 262// static 263void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, 264 size_t* size_bits, 265 PublicKeyType* type) { 266 x509_util::GetPublicKeyInfo(cert_handle, size_bits, type); 267} 268 269} // namespace net 270