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/base/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/time.h" | |
21 #include "crypto/nss_util.h" | |
22 #include "crypto/rsa_private_key.h" | |
23 #include "crypto/scoped_nss_types.h" | |
24 #include "net/base/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 // we 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 // Create a nickname for a user certificate. | |
95 // We use the scheme used by Firefox: | |
96 // --> <subject's common name>'s <issuer's common name> ID. | |
97 // TODO(gspencer): internationalize this: it's wrong to | |
98 // hard code English. | |
99 | |
100 std::string username, ca_name; | |
101 char* temp_username = CERT_GetCommonName( | |
102 &cert_handle_->subject); | |
103 char* temp_ca_name = CERT_GetCommonName(&cert_handle_->issuer); | |
104 if (temp_username) { | |
105 username = temp_username; | |
106 PORT_Free(temp_username); | |
107 } | |
108 if (temp_ca_name) { | |
109 ca_name = temp_ca_name; | |
110 PORT_Free(temp_ca_name); | |
111 } | |
112 result = username + "'s " + ca_name + " ID"; | |
113 break; | |
114 } | |
115 case SERVER_CERT: | |
116 result = subject_.GetDisplayName(); | |
117 break; | |
118 case UNKNOWN_CERT: | |
119 default: | |
120 break; | |
121 } | |
122 return result; | |
123 } | |
124 | |
125 // static | |
126 X509Certificate* X509Certificate::CreateSelfSigned( | |
127 crypto::RSAPrivateKey* key, | |
128 const std::string& subject, | |
129 uint32 serial_number, | |
130 base::TimeDelta valid_duration) { | |
131 DCHECK(key); | |
132 base::Time not_valid_before = base::Time::Now(); | |
133 base::Time not_valid_after = not_valid_before + valid_duration; | |
134 CERTCertificate* cert = x509_util::CreateSelfSignedCert(key->public_key(), | |
135 key->key(), | |
136 subject, | |
137 serial_number, | |
138 not_valid_before, | |
139 not_valid_after); | |
140 if (!cert) | |
141 return NULL; | |
142 | |
143 X509Certificate* x509_cert = X509Certificate::CreateFromHandle( | |
144 cert, X509Certificate::OSCertHandles()); | |
145 CERT_DestroyCertificate(cert); | |
146 return x509_cert; | |
147 } | |
148 | |
149 void X509Certificate::GetSubjectAltName( | |
150 std::vector<std::string>* dns_names, | |
151 std::vector<std::string>* ip_addrs) const { | |
152 x509_util::GetSubjectAltName(cert_handle_, dns_names, ip_addrs); | |
153 } | |
154 | |
155 bool X509Certificate::VerifyNameMatch(const std::string& hostname) const { | |
156 return CERT_VerifyCertName(cert_handle_, hostname.c_str()) == SECSuccess; | |
157 } | |
158 | |
159 bool X509Certificate::IsIssuedByEncoded( | |
160 const std::vector<std::string>& valid_issuers) { | |
161 // Get certificate chain as scoped list of CERTCertificate objects. | |
162 std::vector<CERTCertificate*> cert_chain; | |
163 cert_chain.push_back(cert_handle_); | |
164 for (size_t n = 0; n < intermediate_ca_certs_.size(); ++n) { | |
165 cert_chain.push_back(intermediate_ca_certs_[n]); | |
166 } | |
167 // Convert encoded issuers to scoped CERTName* list. | |
168 std::vector<CERTName*> issuers; | |
169 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); | |
170 if (!x509_util::GetIssuersFromEncodedList(valid_issuers, | |
171 arena.get(), | |
172 &issuers)) { | |
173 return false; | |
174 } | |
175 return x509_util::IsCertificateIssuedBy(cert_chain, issuers); | |
176 } | |
177 | |
178 // static | |
179 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | |
180 std::string* encoded) { | |
181 if (!cert_handle->derCert.len) | |
182 return false; | |
183 encoded->assign(reinterpret_cast<char*>(cert_handle->derCert.data), | |
184 cert_handle->derCert.len); | |
185 return true; | |
186 } | |
187 | |
188 // static | |
189 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | |
190 X509Certificate::OSCertHandle b) { | |
191 DCHECK(a && b); | |
192 if (a == b) | |
193 return true; | |
194 return a->derCert.len == b->derCert.len && | |
195 memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; | |
196 } | |
197 | |
198 // static | |
199 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | |
200 const char* data, int length) { | |
201 return CreateOSCertHandleFromBytesWithNickname(data, length, NULL); | |
202 } | |
203 | |
204 // static | |
205 X509Certificate::OSCertHandle | |
206 X509Certificate::CreateOSCertHandleFromBytesWithNickname( | |
207 const char* data, | |
208 int length, | |
209 const char* nickname) { | |
210 if (length < 0) | |
211 return NULL; | |
212 | |
213 crypto::EnsureNSSInit(); | |
214 | |
215 if (!NSS_IsInitialized()) | |
216 return NULL; | |
217 | |
218 SECItem der_cert; | |
219 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); | |
220 der_cert.len = length; | |
221 der_cert.type = siDERCertBuffer; | |
222 | |
223 // Parse into a certificate structure. | |
224 return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, | |
225 const_cast<char*>(nickname), | |
226 PR_FALSE, PR_TRUE); | |
227 } | |
228 | |
229 // static | |
230 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | |
231 const char* data, | |
232 int length, | |
233 Format format) { | |
234 return x509_util::CreateOSCertHandlesFromBytes(data, length, format); | |
235 } | |
236 | |
237 // static | |
238 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | |
239 OSCertHandle cert_handle) { | |
240 return CERT_DupCertificate(cert_handle); | |
241 } | |
242 | |
243 // static | |
244 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | |
245 CERT_DestroyCertificate(cert_handle); | |
246 } | |
247 | |
248 // static | |
249 SHA1HashValue X509Certificate::CalculateFingerprint( | |
250 OSCertHandle cert) { | |
251 SHA1HashValue sha1; | |
252 memset(sha1.data, 0, sizeof(sha1.data)); | |
253 | |
254 DCHECK(NULL != cert->derCert.data); | |
255 DCHECK_NE(0U, cert->derCert.len); | |
256 | |
257 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, | |
258 cert->derCert.data, cert->derCert.len); | |
259 DCHECK_EQ(SECSuccess, rv); | |
260 | |
261 return sha1; | |
262 } | |
263 | |
264 // static | |
265 SHA1HashValue X509Certificate::CalculateCAFingerprint( | |
266 const OSCertHandles& intermediates) { | |
267 SHA1HashValue sha1; | |
268 memset(sha1.data, 0, sizeof(sha1.data)); | |
269 | |
270 HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1); | |
271 if (!sha1_ctx) | |
272 return sha1; | |
273 HASH_Begin(sha1_ctx); | |
274 for (size_t i = 0; i < intermediates.size(); ++i) { | |
275 CERTCertificate* ca_cert = intermediates[i]; | |
276 HASH_Update(sha1_ctx, ca_cert->derCert.data, ca_cert->derCert.len); | |
277 } | |
278 unsigned int result_len; | |
279 HASH_End(sha1_ctx, sha1.data, &result_len, HASH_ResultLenContext(sha1_ctx)); | |
280 HASH_Destroy(sha1_ctx); | |
281 | |
282 return sha1; | |
283 } | |
284 | |
285 // static | |
286 X509Certificate::OSCertHandle | |
287 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { | |
288 return x509_util::ReadOSCertHandleFromPickle(pickle_iter); | |
289 } | |
290 | |
291 // static | |
292 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | |
293 Pickle* pickle) { | |
294 return pickle->WriteData( | |
295 reinterpret_cast<const char*>(cert_handle->derCert.data), | |
296 cert_handle->derCert.len); | |
297 } | |
298 | |
299 // static | |
300 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | |
301 size_t* size_bits, | |
302 PublicKeyType* type) { | |
303 x509_util::GetPublicKeyInfo(cert_handle, size_bits, type); | |
304 } | |
305 | |
306 } // namespace net | |
OLD | NEW |