Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(998)

Side by Side Diff: net/base/x509_util_nss.cc

Issue 8566056: This applies GUIDs to certificate and key nicknames when (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More review changes Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/x509_util.h" 5 #include "net/base/x509_util.h"
6 #include "net/base/x509_util_nss.h" 6 #include "net/base/x509_util_nss.h"
7 7
8 #include <cert.h> 8 #include <cert.h>
9 #include <cryptohi.h> 9 #include <cryptohi.h>
10 #include <pk11pub.h> 10 #include <pk11pub.h>
11 #include <prerror.h> 11 #include <prerror.h>
12 #include <secmod.h> 12 #include <secmod.h>
13 #include <secport.h> 13 #include <secport.h>
14 14
15 #include "base/debug/leak_annotations.h" 15 #include "base/debug/leak_annotations.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/singleton.h" 18 #include "base/memory/singleton.h"
19 #include "crypto/nss_util.h" 19 #include "crypto/nss_util.h"
20 #include "crypto/nss_util_internal.h" 20 #include "crypto/nss_util_internal.h"
21 #include "crypto/rsa_private_key.h" 21 #include "crypto/rsa_private_key.h"
22 #include "crypto/scoped_nss_types.h" 22 #include "crypto/scoped_nss_types.h"
23 #include "net/base/x509_certificate.h"
24 #include "net/third_party/mozilla_security_manager/nsNSSCertTrust.h"
25
26 namespace msm = mozilla_security_manager;
23 27
24 namespace { 28 namespace {
25 29
26 class ObCertOIDWrapper { 30 class ObCertOIDWrapper {
27 public: 31 public:
28 static ObCertOIDWrapper* GetInstance() { 32 static ObCertOIDWrapper* GetInstance() {
29 // Instantiated as a leaky singleton to allow the singleton to be 33 // Instantiated as a leaky singleton to allow the singleton to be
30 // constructed on a worker thead that is not joined when a process 34 // constructed on a worker thead that is not joined when a process
31 // shuts down. 35 // shuts down.
32 return Singleton<ObCertOIDWrapper, 36 return Singleton<ObCertOIDWrapper,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // Sign the ASN1 encoded cert and save it to |result|. 163 // Sign the ASN1 encoded cert and save it to |result|.
160 rv = SEC_DerSignData(arena, result, der.data, der.len, key, algo_id); 164 rv = SEC_DerSignData(arena, result, der.data, der.len, key, algo_id);
161 if (rv != SECSuccess) 165 if (rv != SECSuccess)
162 return false; 166 return false;
163 167
164 // Save the signed result to the cert. 168 // Save the signed result to the cert.
165 cert->derCert = *result; 169 cert->derCert = *result;
166 170
167 return true; 171 return true;
168 } 172 }
169
wtc 2011/12/08 00:07:43 Nit: keep this blank line. This blank line matche
Greg Spencer (Chromium) 2011/12/09 18:51:38 Done.
170 } // namespace 173 } // namespace
171 174
172 namespace net { 175 namespace net {
173 176
174 namespace x509_util { 177 namespace x509_util {
175 178
176 CERTCertificate* CreateSelfSignedCert( 179 CERTCertificate* CreateSelfSignedCert(
177 SECKEYPublicKey* public_key, 180 SECKEYPublicKey* public_key,
178 SECKEYPrivateKey* private_key, 181 SECKEYPrivateKey* private_key,
179 const std::string& subject, 182 const std::string& subject,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 309
307 DCHECK(cert->derCert.len); 310 DCHECK(cert->derCert.len);
308 // XXX copied from X509Certificate::GetDEREncoded 311 // XXX copied from X509Certificate::GetDEREncoded
309 der_cert->clear(); 312 der_cert->clear();
310 der_cert->append(reinterpret_cast<char*>(cert->derCert.data), 313 der_cert->append(reinterpret_cast<char*>(cert->derCert.data),
311 cert->derCert.len); 314 cert->derCert.len);
312 CERT_DestroyCertificate(cert); 315 CERT_DestroyCertificate(cert);
313 return true; 316 return true;
314 } 317 }
315 318
319 CertType GetCertType(const X509Certificate* cert) {
320 DCHECK(cert);
321 msm::nsNSSCertTrust trust(cert->os_cert_handle()->trust);
322 if (trust.HasAnyUser())
323 return USER_CERT;
324 if (trust.HasAnyCA() || CERT_IsCACert(cert->os_cert_handle(), NULL))
325 return CA_CERT;
326 if (trust.HasPeer(PR_TRUE, PR_FALSE, PR_FALSE))
327 return SERVER_CERT;
328 return UNKNOWN_CERT;
329 }
330
331 std::string GetDefaultCertificateLabel(const X509Certificate* cert) {
332 DCHECK(cert);
333 std::string result;
334
335 #if defined(OS_CHROMEOS)
336 // When we have label support, we want to keep any existing label by default.
337 result = GetLabel(cert);
338 if (!result.empty())
339 return result;
340 #endif
wtc 2011/12/08 00:07:43 This behavior (lines 335-340) is difficult to docu
Greg Spencer (Chromium) 2011/12/09 18:51:38 We talked about this: I've removed this from the f
341
342 switch (GetCertType(cert)) {
343 case CA_CERT: {
344 char *nickname = CERT_MakeCANickname(cert->os_cert_handle());
wtc 2011/12/08 00:07:43 Nit: put '*' next to 'char'.
Greg Spencer (Chromium) 2011/12/09 18:51:38 Done.
345 result = nickname;
346 PORT_Free(nickname);
347 break;
348 }
349 case USER_CERT: {
350 // Create a nickname for this user certificate.
351 // We use the scheme used by Firefox:
wtc 2011/12/08 00:07:43 Nit: extraneous space before "We".
Greg Spencer (Chromium) 2011/12/09 18:51:38 Fixed.
352 // --> <subject's common name>'s <issuer's common name> ID.
353 // TODO(gspencer): internationalize this: it's wrong to
354 // hard code English.
355
356 std::string username, ca_name;
357 char* temp_username = CERT_GetCommonName(
358 &cert->os_cert_handle()->subject);
359 char* temp_ca_name = CERT_GetCommonName(&cert->os_cert_handle()->issuer);
360 if (temp_username) {
361 username = temp_username;
362 PORT_Free(temp_username);
363 }
364 if (temp_ca_name) {
365 ca_name = temp_ca_name;
366 PORT_Free(temp_ca_name);
367 }
368 result = username + "'s " + ca_name + " ID";
369 break;
370 }
371 case SERVER_CERT: {
372 result = cert->subject().GetDisplayName();
373 break;
374 }
wtc 2011/12/08 00:07:43 Nit: this case doesn't need curly braces because i
Greg Spencer (Chromium) 2011/12/09 18:51:38 Done.
375 case UNKNOWN_CERT:
376 default:
377 break;
378 }
379 return result;
380 }
381
382 #if defined(OS_CHROMEOS)
383 bool SetLabel(X509Certificate* cert, const std::string& label) {
384 DCHECK(cert);
385 // If the slot isn't initialized, then do nothing.
386 if (!cert->os_cert_handle()->slot)
387 return true;
388
389 // First we set the nickname on the cert itself. This doesn't
390 // work on production NSS yet (it's not implemented), but ChromeOS
391 // has a patched version that it will work on.
392 SECItem sec_label;
393 sec_label.type = siUTF8String;
wtc 2011/12/08 00:07:43 PK11_WriteRawAttribute does not use the 'type' fie
Greg Spencer (Chromium) 2011/12/09 18:51:38 Done.
394 sec_label.data = reinterpret_cast<unsigned char*>(
395 const_cast<char*>(label.c_str()));
396 sec_label.len = label.size();
397 SECStatus srv = PK11_WriteRawAttribute(PK11_TypeCert,
398 cert->os_cert_handle(),
399 CKA_LABEL,
400 &sec_label);
wtc 2011/12/08 00:07:43 IMPORTANT: my concern about this solution is that
Greg Spencer (Chromium) 2011/12/09 18:51:38 I've stopped trying to set the nickname later, and
401 if (srv != SECSuccess)
402 LOG(WARNING) << "Unable to set certificate label to "
403 << label;
wtc 2011/12/08 00:07:43 Nit: please add curly braces because the statement
Greg Spencer (Chromium) 2011/12/09 18:51:38 Done.
404
405 // As far as I can tell, there is no API for PKCS11 that allows one
406 // to get the valid public key (that has a valid PKCS11 slot and id)
407 // associated with a certificate. So, instead, I extract the public
408 // key using CERT_ExtractPublicKey (which returns a key that has no
409 // slot or pkcs11 id set), and then we iterate through all of the
410 // existing public keys (which do have this information), and look
411 // for one that has the same DER encoding as the public key
412 // extracted from this certificate. I then set that key's nickname
413 // to the given label.
414 SECKEYPublicKey* public_key = CERT_ExtractPublicKey(cert->os_cert_handle());
415 if (!public_key)
416 return false;
417
418 SECKEYPublicKeyList* pubkey_list =
419 PK11_ListPublicKeysInSlot(cert->os_cert_handle()->slot, NULL);
420
421 // If there are no public keys, that's OK.
422 if (pubkey_list) {
423 for (SECKEYPublicKeyListNode* node = PUBKEY_LIST_HEAD(pubkey_list);
424 !PUBKEY_LIST_END(node, pubkey_list);
425 node = PUBKEY_LIST_NEXT(node)) {
426 SECItem* der_encoded = PK11_DEREncodePublicKey(node->key);
427 if (SECITEM_CompareItem(
428 der_encoded,
429 &cert->os_cert_handle()->derPublicKey) == SECEqual)
430 PK11_SetPublicKeyNickname(node->key, label.c_str());
431 SECITEM_FreeItem(der_encoded, PR_TRUE);
432 }
433 SECKEY_DestroyPublicKeyList(pubkey_list);
434 }
435 SECKEY_DestroyPublicKey(public_key);
436
437 // Now set the nickname on the private key (if there is one)
438 SECKEYPrivateKey* private_key =
439 PK11_FindPrivateKeyFromCert(cert->os_cert_handle()->slot,
440 cert->os_cert_handle(),
441 NULL);
442 if (private_key) {
443 PK11_SetPrivateKeyNickname(private_key, label.c_str());
444 SECKEY_DestroyPrivateKey(private_key);
445 }
446 return true;
447 }
448
449 std::string GetLabel(const X509Certificate* cert) {
450 std::string result;
451 // This doesn't work on production NSS yet (it's not implemented), but
452 // ChromeOS has a patched version that it will work on.
453 SECItem sec_label;
454 SECStatus srv = PK11_ReadRawAttribute(PK11_TypeCert,
455 cert->os_cert_handle(),
456 CKA_LABEL,
457 &sec_label);
wtc 2011/12/08 00:07:43 Why don't you just use the 'nickname' field of the
Greg Spencer (Chromium) 2011/12/09 18:51:38 For server and CA certs, this works because I can
458 if (srv != SECSuccess) {
459 return result;
460 }
461
462 result = std::string(reinterpret_cast<char *>(sec_label.data), sec_label.len);
463 PORT_Free(sec_label.data);
464 return result;
465 }
466 #endif // OS_CHROMEOS
467
468
316 } // namespace x509_util 469 } // namespace x509_util
317 470
318 } // namespace net 471 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698