OLD | NEW |
| (Empty) |
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 | |
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 | |
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 | |
61 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 | |
116 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 | |
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 | |
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 | |
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 | |
162 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | |
163 const char* data, int length) { | |
164 return CreateOSCertHandleFromBytesWithNickname(data, length, NULL); | |
165 } | |
166 | |
167 // static | |
168 X509Certificate::OSCertHandle | |
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 | |
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 | |
201 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | |
202 OSCertHandle cert_handle) { | |
203 return CERT_DupCertificate(cert_handle); | |
204 } | |
205 | |
206 // static | |
207 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | |
208 CERT_DestroyCertificate(cert_handle); | |
209 } | |
210 | |
211 // static | |
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 | |
228 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { | |
229 SHA256HashValue sha256; | |
230 memset(sha256.data, 0, sizeof(sha256.data)); | |
231 | |
232 DCHECK(NULL != cert->derCert.data); | |
233 DCHECK_NE(0U, cert->derCert.len); | |
234 | |
235 SECStatus rv = HASH_HashBuf( | |
236 HASH_AlgSHA256, sha256.data, cert->derCert.data, cert->derCert.len); | |
237 DCHECK_EQ(SECSuccess, rv); | |
238 | |
239 return sha256; | |
240 } | |
241 | |
242 // static | |
243 SHA1HashValue X509Certificate::CalculateCAFingerprint( | |
244 const OSCertHandles& intermediates) { | |
245 SHA1HashValue sha1; | |
246 memset(sha1.data, 0, sizeof(sha1.data)); | |
247 | |
248 HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1); | |
249 if (!sha1_ctx) | |
250 return sha1; | |
251 HASH_Begin(sha1_ctx); | |
252 for (size_t i = 0; i < intermediates.size(); ++i) { | |
253 CERTCertificate* ca_cert = intermediates[i]; | |
254 HASH_Update(sha1_ctx, ca_cert->derCert.data, ca_cert->derCert.len); | |
255 } | |
256 unsigned int result_len; | |
257 HASH_End(sha1_ctx, sha1.data, &result_len, HASH_ResultLenContext(sha1_ctx)); | |
258 HASH_Destroy(sha1_ctx); | |
259 | |
260 return sha1; | |
261 } | |
262 | |
263 // static | |
264 X509Certificate::OSCertHandle | |
265 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { | |
266 return x509_util::ReadOSCertHandleFromPickle(pickle_iter); | |
267 } | |
268 | |
269 // static | |
270 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | |
271 Pickle* pickle) { | |
272 return pickle->WriteData( | |
273 reinterpret_cast<const char*>(cert_handle->derCert.data), | |
274 cert_handle->derCert.len); | |
275 } | |
276 | |
277 // static | |
278 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | |
279 size_t* size_bits, | |
280 PublicKeyType* type) { | |
281 x509_util::GetPublicKeyInfo(cert_handle, size_bits, type); | |
282 } | |
283 | |
284 // static | |
285 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { | |
286 crypto::ScopedSECKEYPublicKey public_key(CERT_ExtractPublicKey(cert_handle)); | |
287 if (!public_key.get()) | |
288 return false; | |
289 return SECSuccess == CERT_VerifySignedDataWithPublicKey( | |
290 &cert_handle->signatureWrap, public_key.get(), NULL); | |
291 } | |
292 | |
293 } // namespace net | |
OLD | NEW |