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
3 // found in the LICENSE file.
5 #include "net/cert/x509_util_openssl.h"
7 #include <openssl/asn1.h>
8 #include <openssl/mem.h>
12 #include "base/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/strings/string_piece.h"
15 #include "base/strings/string_util.h"
16 #include "crypto/ec_private_key.h"
17 #include "crypto/openssl_util.h"
18 #include "crypto/rsa_private_key.h"
19 #include "crypto/scoped_openssl_types.h"
20 #include "net/cert/x509_cert_types.h"
21 #include "net/cert/x509_util.h"
22 #include "net/ssl/scoped_openssl_types.h"
28 using ScopedASN1_INTEGER
=
29 crypto::ScopedOpenSSL
<ASN1_INTEGER
, ASN1_INTEGER_free
>;
30 using ScopedASN1_OCTET_STRING
=
31 crypto::ScopedOpenSSL
<ASN1_OCTET_STRING
, ASN1_OCTET_STRING_free
>;
32 using ScopedASN1_STRING
= crypto::ScopedOpenSSL
<ASN1_STRING
, ASN1_STRING_free
>;
33 using ScopedASN1_TIME
= crypto::ScopedOpenSSL
<ASN1_TIME
, ASN1_TIME_free
>;
34 using ScopedX509_EXTENSION
=
35 crypto::ScopedOpenSSL
<X509_EXTENSION
, X509_EXTENSION_free
>;
36 using ScopedX509_NAME
= crypto::ScopedOpenSSL
<X509_NAME
, X509_NAME_free
>;
38 const EVP_MD
* ToEVP(x509_util::DigestAlgorithm alg
) {
40 case x509_util::DIGEST_SHA1
:
42 case x509_util::DIGEST_SHA256
:
54 X509
* CreateCertificate(EVP_PKEY
* key
,
56 const std::string
& common_name
,
57 uint32_t serial_number
,
58 base::Time not_valid_before
,
59 base::Time not_valid_after
) {
60 // Put the serial number into an OpenSSL-friendly object.
61 ScopedASN1_INTEGER
asn1_serial(ASN1_INTEGER_new());
62 if (!asn1_serial
.get() ||
63 !ASN1_INTEGER_set(asn1_serial
.get(), static_cast<long>(serial_number
))) {
64 LOG(ERROR
) << "Invalid serial number " << serial_number
;
68 // Do the same for the time stamps.
69 ScopedASN1_TIME
asn1_not_before_time(
70 ASN1_TIME_set(NULL
, not_valid_before
.ToTimeT()));
71 if (!asn1_not_before_time
.get()) {
72 LOG(ERROR
) << "Invalid not_valid_before time: "
73 << not_valid_before
.ToTimeT();
77 ScopedASN1_TIME
asn1_not_after_time(
78 ASN1_TIME_set(NULL
, not_valid_after
.ToTimeT()));
79 if (!asn1_not_after_time
.get()) {
80 LOG(ERROR
) << "Invalid not_valid_after time: " << not_valid_after
.ToTimeT();
84 // Because |common_name| only contains a common name and starts with 'CN=',
85 // there is no need for a full RFC 2253 parser here. Do some sanity checks
87 static const char kCommonNamePrefix
[] = "CN=";
88 const size_t kCommonNamePrefixLen
= sizeof(kCommonNamePrefix
) - 1;
89 if (common_name
.size() < kCommonNamePrefixLen
||
90 strncmp(common_name
.c_str(), kCommonNamePrefix
, kCommonNamePrefixLen
)) {
91 LOG(ERROR
) << "Common name must begin with " << kCommonNamePrefix
;
94 if (common_name
.size() > INT_MAX
) {
95 LOG(ERROR
) << "Common name too long";
98 unsigned char* common_name_str
=
99 reinterpret_cast<unsigned char*>(const_cast<char*>(common_name
.data())) +
100 kCommonNamePrefixLen
;
101 int common_name_len
=
102 static_cast<int>(common_name
.size() - kCommonNamePrefixLen
);
104 ScopedX509_NAME
name(X509_NAME_new());
105 if (!name
.get() || !X509_NAME_add_entry_by_NID(name
.get(),
112 LOG(ERROR
) << "Can't parse common name: " << common_name
.c_str();
116 // Now create certificate and populate it.
117 ScopedX509
cert(X509_new());
118 if (!cert
.get() || !X509_set_version(cert
.get(), 2L) /* i.e. version 3 */ ||
119 !X509_set_pubkey(cert
.get(), key
) ||
120 !X509_set_serialNumber(cert
.get(), asn1_serial
.get()) ||
121 !X509_set_notBefore(cert
.get(), asn1_not_before_time
.get()) ||
122 !X509_set_notAfter(cert
.get(), asn1_not_after_time
.get()) ||
123 !X509_set_subject_name(cert
.get(), name
.get()) ||
124 !X509_set_issuer_name(cert
.get(), name
.get())) {
125 LOG(ERROR
) << "Could not create certificate";
129 return cert
.release();
132 // DER-encodes |x509|. On success, returns true and writes the
133 // encoding to |*out_der|.
134 bool DerEncodeCert(X509
* x509
, std::string
* out_der
) {
135 int len
= i2d_X509(x509
, NULL
);
139 uint8_t* ptr
= reinterpret_cast<uint8_t*>(WriteInto(out_der
, len
+ 1));
140 if (i2d_X509(x509
, &ptr
) < 0) {
148 bool SignAndDerEncodeCert(X509
* cert
,
151 std::string
* der_encoded
) {
152 // Get the message digest algorithm
153 const EVP_MD
* md
= ToEVP(alg
);
155 LOG(ERROR
) << "Unrecognized hash algorithm.";
159 // Sign it with the private key.
160 if (!X509_sign(cert
, key
, md
)) {
161 LOG(ERROR
) << "Could not sign certificate with key.";
165 // Convert it into a DER-encoded string copied to |der_encoded|.
166 return DerEncodeCert(cert
, der_encoded
);
173 void DERCache_free(void* parent
, void* ptr
, CRYPTO_EX_DATA
* ad
, int idx
,
174 long argl
, void* argp
) {
175 DERCache
* der_cache
= static_cast<DERCache
*>(ptr
);
179 class DERCacheInitSingleton
{
181 DERCacheInitSingleton() {
182 crypto::EnsureOpenSSLInit();
183 der_cache_ex_index_
= X509_get_ex_new_index(0, 0, 0, 0, DERCache_free
);
184 DCHECK_NE(-1, der_cache_ex_index_
);
187 int der_cache_ex_index() const { return der_cache_ex_index_
; }
190 int der_cache_ex_index_
;
192 DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton
);
195 base::LazyInstance
<DERCacheInitSingleton
>::Leaky g_der_cache_singleton
=
196 LAZY_INSTANCE_INITIALIZER
;
200 bool IsSupportedValidityRange(base::Time not_valid_before
,
201 base::Time not_valid_after
) {
202 if (not_valid_before
> not_valid_after
)
205 // The validity field of a certificate can only encode years 1-9999.
207 // Compute the base::Time values corresponding to Jan 1st,0001 and
208 // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
209 // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
210 // using the following Python script:
212 // from datetime import date as D
213 // print (D(1970,1,1)-D(1,1,1)) # -> 719162 days
214 // print (D(9999,12,31)-D(1970,1,1)) # -> 2932896 days
216 // Note: This ignores leap seconds, but should be enough in practice.
218 const int64_t kDaysFromYear0001ToUnixEpoch
= 719162;
219 const int64_t kDaysFromUnixEpochToYear10000
= 2932896 + 1;
220 const base::Time kEpoch
= base::Time::UnixEpoch();
221 const base::Time kYear0001
= kEpoch
-
222 base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch
);
223 const base::Time kYear10000
= kEpoch
+
224 base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000
);
226 if (not_valid_before
< kYear0001
|| not_valid_before
>= kYear10000
||
227 not_valid_after
< kYear0001
|| not_valid_after
>= kYear10000
)
233 bool CreateSelfSignedCert(crypto::RSAPrivateKey
* key
,
235 const std::string
& common_name
,
236 uint32_t serial_number
,
237 base::Time not_valid_before
,
238 base::Time not_valid_after
,
239 std::string
* der_encoded
) {
240 crypto::OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
241 ScopedX509
cert(CreateCertificate(key
->key(),
250 return SignAndDerEncodeCert(cert
.get(), key
->key(), alg
, der_encoded
);
253 bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY
* entry
,
255 std::string
* value
) {
257 ASN1_OBJECT
* object
= X509_NAME_ENTRY_get_object(entry
);
258 key
->assign(OBJ_nid2sn(OBJ_obj2nid(object
)));
261 ASN1_STRING
* data
= X509_NAME_ENTRY_get_data(entry
);
265 unsigned char* buf
= NULL
;
266 int len
= ASN1_STRING_to_UTF8(&buf
, data
);
270 value
->assign(reinterpret_cast<const char*>(buf
), len
);
275 bool ParsePrincipalKeyAndValueByIndex(X509_NAME
* name
,
278 std::string
* value
) {
279 X509_NAME_ENTRY
* entry
= X509_NAME_get_entry(name
, index
);
283 return ParsePrincipalKeyAndValue(entry
, key
, value
);
286 bool ParsePrincipalValueByIndex(X509_NAME
* name
,
288 std::string
* value
) {
289 return ParsePrincipalKeyAndValueByIndex(name
, index
, NULL
, value
);
292 bool ParsePrincipalValueByNID(X509_NAME
* name
, int nid
, std::string
* value
) {
293 int index
= X509_NAME_get_index_by_NID(name
, nid
, -1);
297 return ParsePrincipalValueByIndex(name
, index
, value
);
300 bool ParseDate(ASN1_TIME
* x509_time
, base::Time
* time
) {
302 (x509_time
->type
!= V_ASN1_UTCTIME
&&
303 x509_time
->type
!= V_ASN1_GENERALIZEDTIME
))
306 base::StringPiece
str_date(reinterpret_cast<const char*>(x509_time
->data
),
309 CertDateFormat format
= x509_time
->type
== V_ASN1_UTCTIME
?
310 CERT_DATE_FORMAT_UTC_TIME
: CERT_DATE_FORMAT_GENERALIZED_TIME
;
311 return ParseCertificateDate(str_date
, format
, time
);
314 // Returns true if |der_cache| points to valid data, false otherwise.
315 // (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
317 bool GetDER(X509
* x509
, base::StringPiece
* der_cache
) {
318 int x509_der_cache_index
=
319 g_der_cache_singleton
.Get().der_cache_ex_index();
321 // Re-encoding the DER data via i2d_X509 is an expensive operation,
322 // but it's necessary for comparing two certificates. Re-encode at
323 // most once per certificate and cache the data within the X509 cert
324 // using X509_set_ex_data.
325 DERCache
* internal_cache
= static_cast<DERCache
*>(
326 X509_get_ex_data(x509
, x509_der_cache_index
));
327 if (!internal_cache
) {
328 scoped_ptr
<DERCache
> new_cache(new DERCache
);
329 if (!DerEncodeCert(x509
, &new_cache
->data
))
331 internal_cache
= new_cache
.get();
332 X509_set_ex_data(x509
, x509_der_cache_index
, new_cache
.release());
334 *der_cache
= base::StringPiece(internal_cache
->data
);
338 } // namespace x509_util