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 |