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 |