| 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 "crypto/ec_private_key.h" | 13 #include "crypto/ec_private_key.h" |
| 14 #include "crypto/openssl_util.h" | 14 #include "crypto/openssl_util.h" |
| 15 #include "crypto/rsa_private_key.h" | 15 #include "crypto/rsa_private_key.h" |
| 16 #include "crypto/scoped_openssl_types.h" |
| 16 #include "net/cert/x509_cert_types.h" | 17 #include "net/cert/x509_cert_types.h" |
| 17 #include "net/cert/x509_util.h" | 18 #include "net/cert/x509_util.h" |
| 18 | 19 |
| 19 namespace net { | 20 namespace net { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 24 typedef scoped_ptr<ASN1_INTEGER, |
| 25 crypto::OpenSSLDestroyer<ASN1_INTEGER, ASN1_INTEGER_free> > |
| 26 ScopedASN1_INTEGER; |
| 27 typedef scoped_ptr<ASN1_OCTET_STRING, |
| 28 crypto::OpenSSLDestroyer<ASN1_OCTET_STRING, |
| 29 ASN1_OCTET_STRING_free> > |
| 30 ScopedASN1_OCTET_STRING; |
| 31 typedef scoped_ptr<ASN1_STRING, |
| 32 crypto::OpenSSLDestroyer<ASN1_STRING, ASN1_STRING_free> > |
| 33 ScopedASN1_STRING; |
| 34 typedef scoped_ptr<ASN1_TIME, |
| 35 crypto::OpenSSLDestroyer<ASN1_TIME, ASN1_TIME_free> > |
| 36 ScopedASN1_TIME; |
| 37 typedef scoped_ptr<X509, crypto::OpenSSLDestroyer<X509, X509_free> > ScopedX509; |
| 38 typedef scoped_ptr<X509_EXTENSION, |
| 39 crypto::OpenSSLDestroyer<X509_EXTENSION, |
| 40 X509_EXTENSION_free> > |
| 41 ScopedX509_EXTENSION; |
| 42 typedef scoped_ptr<X509_NAME, |
| 43 crypto::OpenSSLDestroyer<X509_NAME, |
| 44 X509_NAME_free> > |
| 45 ScopedX509_NAME; |
| 46 |
| 23 const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) { | 47 const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) { |
| 24 switch (alg) { | 48 switch (alg) { |
| 25 case x509_util::DIGEST_SHA1: | 49 case x509_util::DIGEST_SHA1: |
| 26 return EVP_sha1(); | 50 return EVP_sha1(); |
| 27 case x509_util::DIGEST_SHA256: | 51 case x509_util::DIGEST_SHA256: |
| 28 return EVP_sha256(); | 52 return EVP_sha256(); |
| 29 } | 53 } |
| 30 return NULL; | 54 return NULL; |
| 31 } | 55 } |
| 32 | 56 |
| 33 } // namespace | 57 } // namespace |
| 34 | 58 |
| 35 namespace x509_util { | 59 namespace x509_util { |
| 36 | 60 |
| 37 namespace { | 61 namespace { |
| 38 | 62 |
| 39 X509* CreateCertificate(EVP_PKEY* key, | 63 X509* CreateCertificate(EVP_PKEY* key, |
| 40 DigestAlgorithm alg, | 64 DigestAlgorithm alg, |
| 41 const std::string& common_name, | 65 const std::string& common_name, |
| 42 uint32_t serial_number, | 66 uint32_t serial_number, |
| 43 base::Time not_valid_before, | 67 base::Time not_valid_before, |
| 44 base::Time not_valid_after) { | 68 base::Time not_valid_after) { |
| 45 // Put the serial number into an OpenSSL-friendly object. | 69 // Put the serial number into an OpenSSL-friendly object. |
| 46 crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free> asn1_serial( | 70 ScopedASN1_INTEGER asn1_serial(ASN1_INTEGER_new()); |
| 47 ASN1_INTEGER_new()); | |
| 48 if (!asn1_serial.get() || | 71 if (!asn1_serial.get() || |
| 49 !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) { | 72 !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) { |
| 50 LOG(ERROR) << "Invalid serial number " << serial_number; | 73 LOG(ERROR) << "Invalid serial number " << serial_number; |
| 51 return NULL; | 74 return NULL; |
| 52 } | 75 } |
| 53 | 76 |
| 54 // Do the same for the time stamps. | 77 // Do the same for the time stamps. |
| 55 crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_before_time( | 78 ScopedASN1_TIME asn1_not_before_time( |
| 56 ASN1_TIME_set(NULL, not_valid_before.ToTimeT())); | 79 ASN1_TIME_set(NULL, not_valid_before.ToTimeT())); |
| 57 if (!asn1_not_before_time.get()) { | 80 if (!asn1_not_before_time.get()) { |
| 58 LOG(ERROR) << "Invalid not_valid_before time: " | 81 LOG(ERROR) << "Invalid not_valid_before time: " |
| 59 << not_valid_before.ToTimeT(); | 82 << not_valid_before.ToTimeT(); |
| 60 return NULL; | 83 return NULL; |
| 61 } | 84 } |
| 62 | 85 |
| 63 crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_after_time( | 86 ScopedASN1_TIME asn1_not_after_time( |
| 64 ASN1_TIME_set(NULL, not_valid_after.ToTimeT())); | 87 ASN1_TIME_set(NULL, not_valid_after.ToTimeT())); |
| 65 if (!asn1_not_after_time.get()) { | 88 if (!asn1_not_after_time.get()) { |
| 66 LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT(); | 89 LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT(); |
| 67 return NULL; | 90 return NULL; |
| 68 } | 91 } |
| 69 | 92 |
| 70 // Because |common_name| only contains a common name and starts with 'CN=', | 93 // Because |common_name| only contains a common name and starts with 'CN=', |
| 71 // there is no need for a full RFC 2253 parser here. Do some sanity checks | 94 // there is no need for a full RFC 2253 parser here. Do some sanity checks |
| 72 // though. | 95 // though. |
| 73 static const char kCommonNamePrefix[] = "CN="; | 96 static const char kCommonNamePrefix[] = "CN="; |
| 74 const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1; | 97 const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1; |
| 75 if (common_name.size() < kCommonNamePrefixLen || | 98 if (common_name.size() < kCommonNamePrefixLen || |
| 76 strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) { | 99 strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) { |
| 77 LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix; | 100 LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix; |
| 78 return NULL; | 101 return NULL; |
| 79 } | 102 } |
| 80 if (common_name.size() > INT_MAX) { | 103 if (common_name.size() > INT_MAX) { |
| 81 LOG(ERROR) << "Common name too long"; | 104 LOG(ERROR) << "Common name too long"; |
| 82 return NULL; | 105 return NULL; |
| 83 } | 106 } |
| 84 unsigned char* common_name_str = | 107 unsigned char* common_name_str = |
| 85 reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) + | 108 reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) + |
| 86 kCommonNamePrefixLen; | 109 kCommonNamePrefixLen; |
| 87 int common_name_len = | 110 int common_name_len = |
| 88 static_cast<int>(common_name.size() - kCommonNamePrefixLen); | 111 static_cast<int>(common_name.size() - kCommonNamePrefixLen); |
| 89 | 112 |
| 90 crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free> name(X509_NAME_new()); | 113 ScopedX509_NAME name(X509_NAME_new()); |
| 91 if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(), | 114 if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(), |
| 92 NID_commonName, | 115 NID_commonName, |
| 93 MBSTRING_ASC, | 116 MBSTRING_ASC, |
| 94 common_name_str, | 117 common_name_str, |
| 95 common_name_len, | 118 common_name_len, |
| 96 -1, | 119 -1, |
| 97 0)) { | 120 0)) { |
| 98 LOG(ERROR) << "Can't parse common name: " << common_name.c_str(); | 121 LOG(ERROR) << "Can't parse common name: " << common_name.c_str(); |
| 99 return NULL; | 122 return NULL; |
| 100 } | 123 } |
| 101 | 124 |
| 102 // Now create certificate and populate it. | 125 // Now create certificate and populate it. |
| 103 crypto::ScopedOpenSSL<X509, X509_free> cert(X509_new()); | 126 ScopedX509 cert(X509_new()); |
| 104 if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ || | 127 if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ || |
| 105 !X509_set_pubkey(cert.get(), key) || | 128 !X509_set_pubkey(cert.get(), key) || |
| 106 !X509_set_serialNumber(cert.get(), asn1_serial.get()) || | 129 !X509_set_serialNumber(cert.get(), asn1_serial.get()) || |
| 107 !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) || | 130 !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) || |
| 108 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) || | 131 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) || |
| 109 !X509_set_subject_name(cert.get(), name.get()) || | 132 !X509_set_subject_name(cert.get(), name.get()) || |
| 110 !X509_set_issuer_name(cert.get(), name.get())) { | 133 !X509_set_issuer_name(cert.get(), name.get())) { |
| 111 LOG(ERROR) << "Could not create certificate"; | 134 LOG(ERROR) << "Could not create certificate"; |
| 112 return NULL; | 135 return NULL; |
| 113 } | 136 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 bool CreateDomainBoundCertEC( | 237 bool CreateDomainBoundCertEC( |
| 215 crypto::ECPrivateKey* key, | 238 crypto::ECPrivateKey* key, |
| 216 DigestAlgorithm alg, | 239 DigestAlgorithm alg, |
| 217 const std::string& domain, | 240 const std::string& domain, |
| 218 uint32 serial_number, | 241 uint32 serial_number, |
| 219 base::Time not_valid_before, | 242 base::Time not_valid_before, |
| 220 base::Time not_valid_after, | 243 base::Time not_valid_after, |
| 221 std::string* der_cert) { | 244 std::string* der_cert) { |
| 222 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 245 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 223 // Create certificate. | 246 // Create certificate. |
| 224 crypto::ScopedOpenSSL<X509, X509_free> cert( | 247 ScopedX509 cert(CreateCertificate(key->key(), |
| 225 CreateCertificate(key->key(), | 248 alg, |
| 226 alg, | 249 "CN=anonymous.invalid", |
| 227 "CN=anonymous.invalid", | 250 serial_number, |
| 228 serial_number, | 251 not_valid_before, |
| 229 not_valid_before, | 252 not_valid_after)); |
| 230 not_valid_after)); | |
| 231 if (!cert.get()) | 253 if (!cert.get()) |
| 232 return false; | 254 return false; |
| 233 | 255 |
| 234 // Add TLS-Channel-ID extension to the certificate before signing it. | 256 // Add TLS-Channel-ID extension to the certificate before signing it. |
| 235 // The value must be stored DER-encoded, as a ASN.1 IA5String. | 257 // The value must be stored DER-encoded, as a ASN.1 IA5String. |
| 236 crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free> domain_ia5( | 258 ScopedASN1_STRING domain_ia5(ASN1_IA5STRING_new()); |
| 237 ASN1_IA5STRING_new()); | |
| 238 if (!domain_ia5.get() || | 259 if (!domain_ia5.get() || |
| 239 !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size())) | 260 !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size())) |
| 240 return false; | 261 return false; |
| 241 | 262 |
| 242 std::string domain_der; | 263 std::string domain_der; |
| 243 int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL); | 264 int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL); |
| 244 if (domain_der_len < 0) | 265 if (domain_der_len < 0) |
| 245 return false; | 266 return false; |
| 246 | 267 |
| 247 domain_der.resize(domain_der_len); | 268 domain_der.resize(domain_der_len); |
| 248 unsigned char* domain_der_data = | 269 unsigned char* domain_der_data = |
| 249 reinterpret_cast<unsigned char*>(&domain_der[0]); | 270 reinterpret_cast<unsigned char*>(&domain_der[0]); |
| 250 if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0) | 271 if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0) |
| 251 return false; | 272 return false; |
| 252 | 273 |
| 253 crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free> domain_str( | 274 ScopedASN1_OCTET_STRING domain_str(ASN1_OCTET_STRING_new()); |
| 254 ASN1_OCTET_STRING_new()); | |
| 255 if (!domain_str.get() || | 275 if (!domain_str.get() || |
| 256 !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size())) | 276 !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size())) |
| 257 return false; | 277 return false; |
| 258 | 278 |
| 259 crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free> ext( | 279 ScopedX509_EXTENSION ext(X509_EXTENSION_create_by_OBJ( |
| 260 X509_EXTENSION_create_by_OBJ( | 280 NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get())); |
| 261 NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get())); | |
| 262 if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) { | 281 if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) { |
| 263 return false; | 282 return false; |
| 264 } | 283 } |
| 265 | 284 |
| 266 // Sign and encode it. | 285 // Sign and encode it. |
| 267 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert); | 286 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert); |
| 268 } | 287 } |
| 269 | 288 |
| 270 bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, | 289 bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, |
| 271 DigestAlgorithm alg, | 290 DigestAlgorithm alg, |
| 272 const std::string& common_name, | 291 const std::string& common_name, |
| 273 uint32 serial_number, | 292 uint32 serial_number, |
| 274 base::Time not_valid_before, | 293 base::Time not_valid_before, |
| 275 base::Time not_valid_after, | 294 base::Time not_valid_after, |
| 276 std::string* der_encoded) { | 295 std::string* der_encoded) { |
| 277 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 296 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 278 crypto::ScopedOpenSSL<X509, X509_free> cert( | 297 ScopedX509 cert(CreateCertificate(key->key(), |
| 279 CreateCertificate(key->key(), | 298 alg, |
| 280 alg, | 299 common_name, |
| 281 common_name, | 300 serial_number, |
| 282 serial_number, | 301 not_valid_before, |
| 283 not_valid_before, | 302 not_valid_after)); |
| 284 not_valid_after)); | |
| 285 if (!cert.get()) | 303 if (!cert.get()) |
| 286 return false; | 304 return false; |
| 287 | 305 |
| 288 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded); | 306 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded); |
| 289 } | 307 } |
| 290 | 308 |
| 291 bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY* entry, | 309 bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY* entry, |
| 292 std::string* key, | 310 std::string* key, |
| 293 std::string* value) { | 311 std::string* value) { |
| 294 if (key) { | 312 if (key) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 x509_time->length); | 363 x509_time->length); |
| 346 | 364 |
| 347 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ? | 365 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ? |
| 348 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; | 366 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; |
| 349 return ParseCertificateDate(str_date, format, time); | 367 return ParseCertificateDate(str_date, format, time); |
| 350 } | 368 } |
| 351 | 369 |
| 352 } // namespace x509_util | 370 } // namespace x509_util |
| 353 | 371 |
| 354 } // namespace net | 372 } // namespace net |
| OLD | NEW |