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 "net/cert/x509_cert_types.h" | 16 #include "net/cert/x509_cert_types.h" |
17 #include "net/cert/x509_util.h" | 17 #include "net/cert/x509_util.h" |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
| 21 namespace { |
| 22 |
| 23 const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) { |
| 24 switch (alg) { |
| 25 case x509_util::DIGEST_SHA1: |
| 26 return EVP_sha1(); |
| 27 case x509_util::DIGEST_SHA256: |
| 28 return EVP_sha256(); |
| 29 } |
| 30 return NULL; |
| 31 } |
| 32 |
| 33 } // namespace |
| 34 |
21 namespace x509_util { | 35 namespace x509_util { |
22 | 36 |
23 namespace { | 37 namespace { |
24 | 38 |
25 X509* CreateCertificate(EVP_PKEY* key, | 39 X509* CreateCertificate(EVP_PKEY* key, |
| 40 DigestAlgorithm alg, |
26 const std::string& common_name, | 41 const std::string& common_name, |
27 uint32_t serial_number, | 42 uint32_t serial_number, |
28 base::Time not_valid_before, | 43 base::Time not_valid_before, |
29 base::Time not_valid_after) { | 44 base::Time not_valid_after) { |
30 // Put the serial number into an OpenSSL-friendly object. | 45 // Put the serial number into an OpenSSL-friendly object. |
31 crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free> asn1_serial( | 46 crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free> asn1_serial( |
32 ASN1_INTEGER_new()); | 47 ASN1_INTEGER_new()); |
33 if (!asn1_serial.get() || | 48 if (!asn1_serial.get() || |
34 !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) { | 49 !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) { |
35 LOG(ERROR) << "Invalid serial number " << serial_number; | 50 LOG(ERROR) << "Invalid serial number " << serial_number; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) || | 108 !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) || |
94 !X509_set_subject_name(cert.get(), name.get()) || | 109 !X509_set_subject_name(cert.get(), name.get()) || |
95 !X509_set_issuer_name(cert.get(), name.get())) { | 110 !X509_set_issuer_name(cert.get(), name.get())) { |
96 LOG(ERROR) << "Could not create certificate"; | 111 LOG(ERROR) << "Could not create certificate"; |
97 return NULL; | 112 return NULL; |
98 } | 113 } |
99 | 114 |
100 return cert.release(); | 115 return cert.release(); |
101 } | 116 } |
102 | 117 |
103 bool SignAndDerEncodeCert(X509* cert, EVP_PKEY* key, std::string* der_encoded) { | 118 bool SignAndDerEncodeCert(X509* cert, |
| 119 EVP_PKEY* key, |
| 120 DigestAlgorithm alg, |
| 121 std::string* der_encoded) { |
| 122 // Get the message digest algorithm |
| 123 const EVP_MD* md = ToEVP(alg); |
| 124 if (!md) { |
| 125 LOG(ERROR) << "Unrecognized hash algorithm."; |
| 126 return false; |
| 127 } |
| 128 |
104 // Sign it with the private key. | 129 // Sign it with the private key. |
105 if (!X509_sign(cert, key, EVP_sha1())) { | 130 if (!X509_sign(cert, key, md)) { |
106 LOG(ERROR) << "Could not sign certificate with key."; | 131 LOG(ERROR) << "Could not sign certificate with key."; |
107 return false; | 132 return false; |
108 } | 133 } |
109 | 134 |
110 // Convert it into a DER-encoded string copied to |der_encoded|. | 135 // Convert it into a DER-encoded string copied to |der_encoded|. |
111 int der_data_length = i2d_X509(cert, NULL); | 136 int der_data_length = i2d_X509(cert, NULL); |
112 if (der_data_length < 0) | 137 if (der_data_length < 0) |
113 return false; | 138 return false; |
114 | 139 |
115 der_encoded->resize(der_data_length); | 140 der_encoded->resize(der_data_length); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 | 206 |
182 if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 || | 207 if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 || |
183 not_valid_after < kYear0001 || not_valid_after >= kYear10000) | 208 not_valid_after < kYear0001 || not_valid_after >= kYear10000) |
184 return false; | 209 return false; |
185 | 210 |
186 return true; | 211 return true; |
187 } | 212 } |
188 | 213 |
189 bool CreateDomainBoundCertEC( | 214 bool CreateDomainBoundCertEC( |
190 crypto::ECPrivateKey* key, | 215 crypto::ECPrivateKey* key, |
| 216 DigestAlgorithm alg, |
191 const std::string& domain, | 217 const std::string& domain, |
192 uint32 serial_number, | 218 uint32 serial_number, |
193 base::Time not_valid_before, | 219 base::Time not_valid_before, |
194 base::Time not_valid_after, | 220 base::Time not_valid_after, |
195 std::string* der_cert) { | 221 std::string* der_cert) { |
196 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 222 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
197 // Create certificate. | 223 // Create certificate. |
198 crypto::ScopedOpenSSL<X509, X509_free> cert( | 224 crypto::ScopedOpenSSL<X509, X509_free> cert( |
199 CreateCertificate(key->key(), | 225 CreateCertificate(key->key(), |
| 226 alg, |
200 "CN=anonymous.invalid", | 227 "CN=anonymous.invalid", |
201 serial_number, | 228 serial_number, |
202 not_valid_before, | 229 not_valid_before, |
203 not_valid_after)); | 230 not_valid_after)); |
204 if (!cert.get()) | 231 if (!cert.get()) |
205 return false; | 232 return false; |
206 | 233 |
207 // Add TLS-Channel-ID extension to the certificate before signing it. | 234 // Add TLS-Channel-ID extension to the certificate before signing it. |
208 // The value must be stored DER-encoded, as a ASN.1 IA5String. | 235 // The value must be stored DER-encoded, as a ASN.1 IA5String. |
209 crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free> domain_ia5( | 236 crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free> domain_ia5( |
(...skipping 20 matching lines...) Expand all Loading... |
230 return false; | 257 return false; |
231 | 258 |
232 crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free> ext( | 259 crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free> ext( |
233 X509_EXTENSION_create_by_OBJ( | 260 X509_EXTENSION_create_by_OBJ( |
234 NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get())); | 261 NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get())); |
235 if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) { | 262 if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) { |
236 return false; | 263 return false; |
237 } | 264 } |
238 | 265 |
239 // Sign and encode it. | 266 // Sign and encode it. |
240 return SignAndDerEncodeCert(cert.get(), key->key(), der_cert); | 267 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert); |
241 } | 268 } |
242 | 269 |
243 bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, | 270 bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, |
| 271 DigestAlgorithm alg, |
244 const std::string& common_name, | 272 const std::string& common_name, |
245 uint32 serial_number, | 273 uint32 serial_number, |
246 base::Time not_valid_before, | 274 base::Time not_valid_before, |
247 base::Time not_valid_after, | 275 base::Time not_valid_after, |
248 std::string* der_encoded) { | 276 std::string* der_encoded) { |
249 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 277 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
250 crypto::ScopedOpenSSL<X509, X509_free> cert( | 278 crypto::ScopedOpenSSL<X509, X509_free> cert( |
251 CreateCertificate(key->key(), | 279 CreateCertificate(key->key(), |
| 280 alg, |
252 common_name, | 281 common_name, |
253 serial_number, | 282 serial_number, |
254 not_valid_before, | 283 not_valid_before, |
255 not_valid_after)); | 284 not_valid_after)); |
256 if (!cert.get()) | 285 if (!cert.get()) |
257 return false; | 286 return false; |
258 | 287 |
259 return SignAndDerEncodeCert(cert.get(), key->key(), der_encoded); | 288 return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded); |
260 } | 289 } |
261 | 290 |
262 bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name, | 291 bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name, |
263 int index, | 292 int index, |
264 std::string* key, | 293 std::string* key, |
265 std::string* value) { | 294 std::string* value) { |
266 X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index); | 295 X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index); |
267 if (!entry) | 296 if (!entry) |
268 return false; | 297 return false; |
269 | 298 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 x509_time->length); | 339 x509_time->length); |
311 | 340 |
312 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ? | 341 CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ? |
313 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; | 342 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; |
314 return ParseCertificateDate(str_date, format, time); | 343 return ParseCertificateDate(str_date, format, time); |
315 } | 344 } |
316 | 345 |
317 } // namespace x509_util | 346 } // namespace x509_util |
318 | 347 |
319 } // namespace net | 348 } // namespace net |
OLD | NEW |