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

Side by Side Diff: net/cert/x509_util_openssl.cc

Issue 576233002: Only use the platform cert in verification in SSLClientSocketOpenSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: don't export two versions Created 6 years, 3 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
« no previous file with comments | « net/cert/x509_util_openssl.h ('k') | net/socket/ssl_client_socket_openssl.h » ('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) 2012 The Chromium Authors. All rights reserved. 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 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/cert/x509_util_openssl.h" 5 #include "net/cert/x509_util_openssl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <openssl/asn1.h> 8 #include <openssl/asn1.h>
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_piece.h" 12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
13 #include "crypto/ec_private_key.h" 14 #include "crypto/ec_private_key.h"
14 #include "crypto/openssl_util.h" 15 #include "crypto/openssl_util.h"
15 #include "crypto/rsa_private_key.h" 16 #include "crypto/rsa_private_key.h"
16 #include "crypto/scoped_openssl_types.h" 17 #include "crypto/scoped_openssl_types.h"
17 #include "net/cert/x509_cert_types.h" 18 #include "net/cert/x509_cert_types.h"
18 #include "net/cert/x509_util.h" 19 #include "net/cert/x509_util.h"
19 20
20 namespace net { 21 namespace net {
21 22
22 namespace { 23 namespace {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) || 121 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
121 !X509_set_subject_name(cert.get(), name.get()) || 122 !X509_set_subject_name(cert.get(), name.get()) ||
122 !X509_set_issuer_name(cert.get(), name.get())) { 123 !X509_set_issuer_name(cert.get(), name.get())) {
123 LOG(ERROR) << "Could not create certificate"; 124 LOG(ERROR) << "Could not create certificate";
124 return NULL; 125 return NULL;
125 } 126 }
126 127
127 return cert.release(); 128 return cert.release();
128 } 129 }
129 130
131 // DER-encodes |x509|. On success, returns true and writes the
132 // encoding to |*out_der|.
133 bool DerEncodeCert(X509* x509, std::string* out_der) {
134 int len = i2d_X509(x509, NULL);
135 if (len < 0)
136 return false;
137
138 uint8_t* ptr = reinterpret_cast<uint8_t*>(WriteInto(out_der, len + 1));
139 if (i2d_X509(x509, &ptr) < 0) {
140 NOTREACHED();
141 out_der->clear();
142 return false;
143 }
144 return true;
145 }
146
130 bool SignAndDerEncodeCert(X509* cert, 147 bool SignAndDerEncodeCert(X509* cert,
131 EVP_PKEY* key, 148 EVP_PKEY* key,
132 DigestAlgorithm alg, 149 DigestAlgorithm alg,
133 std::string* der_encoded) { 150 std::string* der_encoded) {
134 // Get the message digest algorithm 151 // Get the message digest algorithm
135 const EVP_MD* md = ToEVP(alg); 152 const EVP_MD* md = ToEVP(alg);
136 if (!md) { 153 if (!md) {
137 LOG(ERROR) << "Unrecognized hash algorithm."; 154 LOG(ERROR) << "Unrecognized hash algorithm.";
138 return false; 155 return false;
139 } 156 }
140 157
141 // Sign it with the private key. 158 // Sign it with the private key.
142 if (!X509_sign(cert, key, md)) { 159 if (!X509_sign(cert, key, md)) {
143 LOG(ERROR) << "Could not sign certificate with key."; 160 LOG(ERROR) << "Could not sign certificate with key.";
144 return false; 161 return false;
145 } 162 }
146 163
147 // Convert it into a DER-encoded string copied to |der_encoded|. 164 // Convert it into a DER-encoded string copied to |der_encoded|.
148 int der_data_length = i2d_X509(cert, NULL); 165 return DerEncodeCert(cert, der_encoded);
149 if (der_data_length < 0)
150 return false;
151
152 der_encoded->resize(der_data_length);
153 unsigned char* der_data =
154 reinterpret_cast<unsigned char*>(&(*der_encoded)[0]);
155 if (i2d_X509(cert, &der_data) < 0)
156 return false;
157
158 return true;
159 } 166 }
160 167
161 // There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet, 168 // There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
162 // so create a global ASN1_OBJECT lazily with the right parameters. 169 // so create a global ASN1_OBJECT lazily with the right parameters.
163 class DomainBoundOid { 170 class DomainBoundOid {
164 public: 171 public:
165 DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); } 172 DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }
166 173
167 ~DomainBoundOid() { 174 ~DomainBoundOid() {
168 if (obj_) 175 if (obj_)
(...skipping 12 matching lines...) Expand all
181 // (iso.org.dod.internet.private.enterprises.google.googleSecurity. 188 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
182 // certificateExtensions.originBoundCertificate) 189 // certificateExtensions.originBoundCertificate)
183 const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6"; 190 const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
184 191
185 ASN1_OBJECT* GetDomainBoundOid() { 192 ASN1_OBJECT* GetDomainBoundOid() {
186 static base::LazyInstance<DomainBoundOid>::Leaky s_lazy = 193 static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
187 LAZY_INSTANCE_INITIALIZER; 194 LAZY_INSTANCE_INITIALIZER;
188 return s_lazy.Get().obj(); 195 return s_lazy.Get().obj();
189 } 196 }
190 197
198
199 struct DERCache {
200 std::string data;
201 };
202
203 void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
204 long argl, void* argp) {
205 DERCache* der_cache = static_cast<DERCache*>(ptr);
206 delete der_cache;
207 }
208
209 class DERCacheInitSingleton {
210 public:
211 DERCacheInitSingleton() {
212 crypto::EnsureOpenSSLInit();
213 der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
214 DCHECK_NE(-1, der_cache_ex_index_);
215 }
216
217 int der_cache_ex_index() const { return der_cache_ex_index_; }
218
219 private:
220 int der_cache_ex_index_;
221
222 DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton);
223 };
224
225 base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton =
226 LAZY_INSTANCE_INITIALIZER;
227
191 } // namespace 228 } // namespace
192 229
193 bool IsSupportedValidityRange(base::Time not_valid_before, 230 bool IsSupportedValidityRange(base::Time not_valid_before,
194 base::Time not_valid_after) { 231 base::Time not_valid_after) {
195 if (not_valid_before > not_valid_after) 232 if (not_valid_before > not_valid_after)
196 return false; 233 return false;
197 234
198 // The validity field of a certificate can only encode years 1-9999. 235 // The validity field of a certificate can only encode years 1-9999.
199 236
200 // Compute the base::Time values corresponding to Jan 1st,0001 and 237 // Compute the base::Time values corresponding to Jan 1st,0001 and
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 return false; 386 return false;
350 387
351 base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data), 388 base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
352 x509_time->length); 389 x509_time->length);
353 390
354 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ? 391 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
355 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; 392 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
356 return ParseCertificateDate(str_date, format, time); 393 return ParseCertificateDate(str_date, format, time);
357 } 394 }
358 395
396 // Returns true if |der_cache| points to valid data, false otherwise.
397 // (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
398 // not free it).
399 bool GetDER(X509* x509, base::StringPiece* der_cache) {
400 int x509_der_cache_index =
401 g_der_cache_singleton.Get().der_cache_ex_index();
402
403 // Re-encoding the DER data via i2d_X509 is an expensive operation,
404 // but it's necessary for comparing two certificates. Re-encode at
405 // most once per certificate and cache the data within the X509 cert
406 // using X509_set_ex_data.
407 DERCache* internal_cache = static_cast<DERCache*>(
408 X509_get_ex_data(x509, x509_der_cache_index));
409 if (!internal_cache) {
410 scoped_ptr<DERCache> new_cache(new DERCache);
411 if (!DerEncodeCert(x509, &new_cache->data))
412 return false;
413 internal_cache = new_cache.get();
414 X509_set_ex_data(x509, x509_der_cache_index, new_cache.release());
415 }
416 *der_cache = base::StringPiece(internal_cache->data);
417 return true;
418 }
419
359 } // namespace x509_util 420 } // namespace x509_util
360 421
361 } // namespace net 422 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/x509_util_openssl.h ('k') | net/socket/ssl_client_socket_openssl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698