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