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

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

Issue 2668005: Bring the handling of <keygen> and support for the application/x-x509-user-ce... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Whitespace/style Created 10 years, 6 months 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
« no previous file with comments | « net/base/cert_database_mac.cc ('k') | net/base/cert_database_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/cert_database.h" 5 #include "net/base/cert_database.h"
6 6
7 #include <cert.h>
8 #include <certdb.h>
7 #include <pk11pub.h> 9 #include <pk11pub.h>
8 #include <secmod.h> 10 #include <secmod.h>
9 #include <ssl.h> 11 #include <ssl.h>
10 #include <nssb64.h> // NSSBase64_EncodeItem() 12 #include <nssb64.h> // NSSBase64_EncodeItem()
11 #include <secder.h> // DER_Encode() 13 #include <secder.h> // DER_Encode()
14 #include <secerr.h>
12 #include <cryptohi.h> // SEC_DerSignData() 15 #include <cryptohi.h> // SEC_DerSignData()
13 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() 16 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
14 17
15 #include "base/logging.h" 18 #include "base/logging.h"
16 #include "base/scoped_ptr.h" 19 #include "base/scoped_ptr.h"
17 #include "base/nss_util.h" 20 #include "base/nss_util.h"
21 #include "base/crypto/scoped_nss_types.h"
18 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
19 #include "net/base/x509_certificate.h" 23 #include "net/base/x509_certificate.h"
20 24
21 namespace net { 25 namespace net {
22 26
27 namespace {
28
29 typedef scoped_ptr_malloc<CERTCertList,
30 base::NSSDestroyer<CERTCertList,
31 CERT_DestroyCertList> > ScopedCERTCertList;
32
33 typedef scoped_ptr_malloc<CERTCertificateList,
34 base::NSSDestroyer<CERTCertificateList,
35 CERT_DestroyCertificateList> > ScopedCERTCertificateList;
36
37 // From an arbitrary, unordered list of certificate, attempt to import every
38 // certificate that:
39 // 1) Is a CA
40 // 2) Results in a valid certificate chain
41 // It is adapted from the PSM logic located in
42 // security/manager/ssl/src/nsNSSCertificateDB.cpp
43 void ImportValidIntermediates(
44 const X509Certificate::OSCertHandles& intermediates) {
45 if (intermediates.empty())
46 return;
47
48 ScopedCERTCertList os_intermediates(CERT_NewCertList());
49 if (os_intermediates == NULL)
50 return;
51
52 for (X509Certificate::OSCertHandles::const_iterator it =
53 intermediates.begin(); it != intermediates.end(); ++it) {
54 // CERTCertList will free each certificate when it's destroyed, so we must
55 // duplicate each cert prior to adding to the list, as we do not own the
56 // intermediates (see x509_certificate.h)
57 CERTCertificate* cert = CERT_DupCertificate(
58 const_cast<CERTCertificate*>(*it));
59 if (cert)
60 CERT_AddCertToListTail(os_intermediates.get(), cert);
61 }
62
63 // Filter out any certificates which are not valid CA certificates
64 SECStatus rv = CERT_FilterCertListByUsage(os_intermediates.get(),
65 certUsageAnyCA,
66 PR_TRUE);
67 if (rv != SECSuccess)
68 return;
69
70 PRTime now = PR_Now();
71 size_t offset = 0;
72 for (CERTCertListNode* node = CERT_LIST_HEAD(os_intermediates);
73 !CERT_LIST_END(node, os_intermediates);
74 node = CERT_LIST_NEXT(node), ++offset) {
75 // Validate the certificate
76 SECStatus verify_result = CERT_VerifyCert(CERT_GetDefaultCertDB(),
77 node->cert, PR_TRUE,
78 certUsageVerifyCA, now, NULL,
79 NULL);
80 if (verify_result != SECSuccess) {
81 DLOG(WARNING) << "Unable to validate the intermediate at " << offset
82 << ". Skipping import of this certificate. Result was "
83 << verify_result;
84 continue;
85 }
86
87 // Attempt to construct a chain. The presumption here is that if
88 // construction of chain depends on other certificates that were part of
89 // |intermediates|, they will all be available in the same
90 // CERTCertDBHandle. This is true if they were created via
91 // X509Certificate::CreateFromBytes(), since under the hood that creates
92 // temporary objects in CERT_GetDefaultCertDB(), but that may not be true
93 // if they were obtained by other means.
94 //
95 // Note: If multiple CertDBs are ever supported, this chain building logic
96 // will need to be adjusted accordingly.
97 ScopedCERTCertificateList chain(
98 CERT_CertChainFromCert(node->cert, certUsageAnyCA, PR_FALSE));
99 if (chain == NULL) {
100 DLOG(WARNING) << "Unable to construct certificate chain for"
101 << "intermediate " << offset << ". Skipping import of "
102 << "this certificate.";
103 continue;
104 }
105
106 // CertChainFromCert returns an array of SECItems, but ImportCerts
107 // requires an array of SECItem pointers, so convert.
108 scoped_array<SECItem*> items(new SECItem*[chain->len]);
109 if (items == NULL)
110 continue;
111
112 for (int i = 0; i < chain->len; i++) {
113 items[i] = &chain->certs[i];
114 }
115 CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, chain->len,
116 items.get(), NULL, PR_TRUE, PR_TRUE, NULL);
117 }
118 }
119
120 } // namespace
121
23 CertDatabase::CertDatabase() { 122 CertDatabase::CertDatabase() {
24 base::EnsureNSSInit(); 123 base::EnsureNSSInit();
25 } 124 }
26 125
27 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { 126 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) {
28 if (!cert_obj) 127 if (!cert_obj)
29 return ERR_CERT_INVALID; 128 return ERR_CERT_INVALID;
30 if (cert_obj->HasExpired()) 129 if (cert_obj->HasExpired())
31 return ERR_CERT_DATE_INVALID; 130 return ERR_CERT_DATE_INVALID;
32 131
33 // Check if the private key corresponding to the certificate exist 132 // Check if the private key corresponding to the certificate exist. We
34 // We shouldn't accept any random client certificate sent by a CA. 133 // shouldn't accept any random client certificate sent by a CA.
35 134 //
36 // Note: The NSS source documentation wrongly suggests that this 135 // Note: The NSS source documentation wrongly suggests that this also
37 // also imports the certificate if the private key exists. This 136 // imports the certificate if the private key exists. This doesn't seem to
38 // doesn't seem to be the case. 137 // be the case.
39
40 CERTCertificate* cert = cert_obj->os_cert_handle(); 138 CERTCertificate* cert = cert_obj->os_cert_handle();
41 PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL); 139 PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL);
42 if (!slot) { 140 if (!slot) {
43 LOG(ERROR) << "No corresponding private key in store"; 141 LOG(ERROR) << "No corresponding private key in store";
44 return ERR_NO_PRIVATE_KEY_FOR_CERT; 142 return ERR_NO_PRIVATE_KEY_FOR_CERT;
45 } 143 }
46 PK11_FreeSlot(slot); 144 PK11_FreeSlot(slot);
47 145
48 return OK; 146 return OK;
49 } 147 }
(...skipping 21 matching lines...) Expand all
71 nickname = username + "'s " + ca_name + " ID"; 169 nickname = username + "'s " + ca_name + " ID";
72 170
73 slot = PK11_ImportCertForKey(cert, 171 slot = PK11_ImportCertForKey(cert,
74 const_cast<char*>(nickname.c_str()), 172 const_cast<char*>(nickname.c_str()),
75 NULL); 173 NULL);
76 if (!slot) { 174 if (!slot) {
77 LOG(ERROR) << "Couldn't import user certificate."; 175 LOG(ERROR) << "Couldn't import user certificate.";
78 return ERR_ADD_USER_CERT_FAILED; 176 return ERR_ADD_USER_CERT_FAILED;
79 } 177 }
80 PK11_FreeSlot(slot); 178 PK11_FreeSlot(slot);
179
180 ImportValidIntermediates(cert_obj->GetIntermediateCertificates());
81 return OK; 181 return OK;
82 } 182 }
83 183
84 } // namespace net 184 } // namespace net
OLDNEW
« no previous file with comments | « net/base/cert_database_mac.cc ('k') | net/base/cert_database_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698