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