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