• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 namespace net {
27 
Initialize()28 void 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
CreateFromBytesWithNickname(const char * data,int length,const char * nickname)42 X509Certificate* 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 
GetDefaultNickname(CertType type) const61 std::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 
GetSubjectAltName(std::vector<std::string> * dns_names,std::vector<std::string> * ip_addrs) const116 void 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 
IsIssuedByEncoded(const std::vector<std::string> & valid_issuers)122 bool 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
GetDEREncoded(X509Certificate::OSCertHandle cert_handle,std::string * encoded)142 bool 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
IsSameOSCert(X509Certificate::OSCertHandle a,X509Certificate::OSCertHandle b)152 bool 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
CreateOSCertHandleFromBytes(const char * data,int length)162 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
163     const char* data, int length) {
164   return CreateOSCertHandleFromBytesWithNickname(data, length, NULL);
165 }
166 
167 // static
168 X509Certificate::OSCertHandle
CreateOSCertHandleFromBytesWithNickname(const char * data,int length,const char * nickname)169 X509Certificate::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
CreateOSCertHandlesFromBytes(const char * data,int length,Format format)193 X509Certificate::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
DupOSCertHandle(OSCertHandle cert_handle)201 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
202     OSCertHandle cert_handle) {
203   return CERT_DupCertificate(cert_handle);
204 }
205 
206 // static
FreeOSCertHandle(OSCertHandle cert_handle)207 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
208   CERT_DestroyCertificate(cert_handle);
209 }
210 
211 // static
CalculateFingerprint(OSCertHandle cert)212 SHA1HashValue 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
CalculateCAFingerprint(const OSCertHandles & intermediates)228 SHA1HashValue 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
249 X509Certificate::OSCertHandle
ReadOSCertHandleFromPickle(PickleIterator * pickle_iter)250 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) {
251   return x509_util::ReadOSCertHandleFromPickle(pickle_iter);
252 }
253 
254 // static
WriteOSCertHandleToPickle(OSCertHandle cert_handle,Pickle * pickle)255 bool 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
GetPublicKeyInfo(OSCertHandle cert_handle,size_t * size_bits,PublicKeyType * type)263 void 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