| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |