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"
8 #include <openssl/asn1.h>
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
14 #include "crypto/ec_private_key.h"
15 #include "crypto/openssl_util.h"
16 #include "crypto/rsa_private_key.h"
17 #include "crypto/scoped_openssl_types.h"
18 #include "net/cert/x509_cert_types.h"
19 #include "net/cert/x509_util.h"
20 #include "net/ssl/scoped_openssl_types.h"
26 using ScopedASN1_INTEGER
=
27 crypto::ScopedOpenSSL
<ASN1_INTEGER
, ASN1_INTEGER_free
>;
28 using ScopedASN1_OCTET_STRING
=
29 crypto::ScopedOpenSSL
<ASN1_OCTET_STRING
, ASN1_OCTET_STRING_free
>;
30 using ScopedASN1_STRING
= crypto::ScopedOpenSSL
<ASN1_STRING
, ASN1_STRING_free
>;
31 using ScopedASN1_TIME
= crypto::ScopedOpenSSL
<ASN1_TIME
, ASN1_TIME_free
>;
32 using ScopedX509_EXTENSION
=
33 crypto::ScopedOpenSSL
<X509_EXTENSION
, X509_EXTENSION_free
>;
34 using ScopedX509_NAME
= crypto::ScopedOpenSSL
<X509_NAME
, X509_NAME_free
>;
36 const EVP_MD
* ToEVP(x509_util::DigestAlgorithm alg
) {
38 case x509_util::DIGEST_SHA1
:
40 case x509_util::DIGEST_SHA256
:
52 X509
* CreateCertificate(EVP_PKEY
* key
,
54 const std::string
& common_name
,
55 uint32_t serial_number
,
56 base::Time not_valid_before
,
57 base::Time not_valid_after
) {
58 // Put the serial number into an OpenSSL-friendly object.
59 ScopedASN1_INTEGER
asn1_serial(ASN1_INTEGER_new());
60 if (!asn1_serial
.get() ||
61 !ASN1_INTEGER_set(asn1_serial
.get(), static_cast<long>(serial_number
))) {
62 LOG(ERROR
) << "Invalid serial number " << serial_number
;
66 // Do the same for the time stamps.
67 ScopedASN1_TIME
asn1_not_before_time(
68 ASN1_TIME_set(NULL
, not_valid_before
.ToTimeT()));
69 if (!asn1_not_before_time
.get()) {
70 LOG(ERROR
) << "Invalid not_valid_before time: "
71 << not_valid_before
.ToTimeT();
75 ScopedASN1_TIME
asn1_not_after_time(
76 ASN1_TIME_set(NULL
, not_valid_after
.ToTimeT()));
77 if (!asn1_not_after_time
.get()) {
78 LOG(ERROR
) << "Invalid not_valid_after time: " << not_valid_after
.ToTimeT();
82 // Because |common_name| only contains a common name and starts with 'CN=',
83 // there is no need for a full RFC 2253 parser here. Do some sanity checks
85 static const char kCommonNamePrefix
[] = "CN=";
86 const size_t kCommonNamePrefixLen
= sizeof(kCommonNamePrefix
) - 1;
87 if (common_name
.size() < kCommonNamePrefixLen
||
88 strncmp(common_name
.c_str(), kCommonNamePrefix
, kCommonNamePrefixLen
)) {
89 LOG(ERROR
) << "Common name must begin with " << kCommonNamePrefix
;
92 if (common_name
.size() > INT_MAX
) {
93 LOG(ERROR
) << "Common name too long";
96 unsigned char* common_name_str
=
97 reinterpret_cast<unsigned char*>(const_cast<char*>(common_name
.data())) +
100 static_cast<int>(common_name
.size() - kCommonNamePrefixLen
);
102 ScopedX509_NAME
name(X509_NAME_new());
103 if (!name
.get() || !X509_NAME_add_entry_by_NID(name
.get(),
110 LOG(ERROR
) << "Can't parse common name: " << common_name
.c_str();
114 // Now create certificate and populate it.
115 ScopedX509
cert(X509_new());
116 if (!cert
.get() || !X509_set_version(cert
.get(), 2L) /* i.e. version 3 */ ||
117 !X509_set_pubkey(cert
.get(), key
) ||
118 !X509_set_serialNumber(cert
.get(), asn1_serial
.get()) ||
119 !X509_set_notBefore(cert
.get(), asn1_not_before_time
.get()) ||
120 !X509_set_notAfter(cert
.get(), asn1_not_after_time
.get()) ||
121 !X509_set_subject_name(cert
.get(), name
.get()) ||
122 !X509_set_issuer_name(cert
.get(), name
.get())) {
123 LOG(ERROR
) << "Could not create certificate";
127 return cert
.release();
130 // DER-encodes |x509|. On success, returns true and writes the
131 // encoding to |*out_der|.
132 bool DerEncodeCert(X509
* x509
, std::string
* out_der
) {
133 int len
= i2d_X509(x509
, NULL
);
137 uint8_t* ptr
= reinterpret_cast<uint8_t*>(WriteInto(out_der
, len
+ 1));
138 if (i2d_X509(x509
, &ptr
) < 0) {
146 bool SignAndDerEncodeCert(X509
* cert
,
149 std::string
* der_encoded
) {
150 // Get the message digest algorithm
151 const EVP_MD
* md
= ToEVP(alg
);
153 LOG(ERROR
) << "Unrecognized hash algorithm.";
157 // Sign it with the private key.
158 if (!X509_sign(cert
, key
, md
)) {
159 LOG(ERROR
) << "Could not sign certificate with key.";
163 // Convert it into a DER-encoded string copied to |der_encoded|.
164 return DerEncodeCert(cert
, der_encoded
);
167 // There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
168 // so create a global ASN1_OBJECT lazily with the right parameters.
169 class DomainBoundOid
{
171 DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText
, 1)) { CHECK(obj_
); }
175 ASN1_OBJECT_free(obj_
);
178 ASN1_OBJECT
* obj() const { return obj_
; }
181 static const char kDomainBoundOidText
[];
186 // 1.3.6.1.4.1.11129.2.1.6
187 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
188 // certificateExtensions.originBoundCertificate)
189 const char DomainBoundOid::kDomainBoundOidText
[] = "1.3.6.1.4.1.11129.2.1.6";
191 ASN1_OBJECT
* GetDomainBoundOid() {
192 static base::LazyInstance
<DomainBoundOid
>::Leaky s_lazy
=
193 LAZY_INSTANCE_INITIALIZER
;
194 return s_lazy
.Get().obj();
202 void DERCache_free(void* parent
, void* ptr
, CRYPTO_EX_DATA
* ad
, int idx
,
203 long argl
, void* argp
) {
204 DERCache
* der_cache
= static_cast<DERCache
*>(ptr
);
208 class DERCacheInitSingleton
{
210 DERCacheInitSingleton() {
211 crypto::EnsureOpenSSLInit();
212 der_cache_ex_index_
= X509_get_ex_new_index(0, 0, 0, 0, DERCache_free
);
213 DCHECK_NE(-1, der_cache_ex_index_
);
216 int der_cache_ex_index() const { return der_cache_ex_index_
; }
219 int der_cache_ex_index_
;
221 DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton
);
224 base::LazyInstance
<DERCacheInitSingleton
>::Leaky g_der_cache_singleton
=
225 LAZY_INSTANCE_INITIALIZER
;
229 bool IsSupportedValidityRange(base::Time not_valid_before
,
230 base::Time not_valid_after
) {
231 if (not_valid_before
> not_valid_after
)
234 // The validity field of a certificate can only encode years 1-9999.
236 // Compute the base::Time values corresponding to Jan 1st,0001 and
237 // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
238 // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
239 // using the following Python script:
241 // from datetime import date as D
242 // print (D(1970,1,1)-D(1,1,1)) # -> 719162 days
243 // print (D(9999,12,31)-D(1970,1,1)) # -> 2932896 days
245 // Note: This ignores leap seconds, but should be enough in practice.
247 const int64 kDaysFromYear0001ToUnixEpoch
= 719162;
248 const int64 kDaysFromUnixEpochToYear10000
= 2932896 + 1;
249 const base::Time kEpoch
= base::Time::UnixEpoch();
250 const base::Time kYear0001
= kEpoch
-
251 base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch
);
252 const base::Time kYear10000
= kEpoch
+
253 base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000
);
255 if (not_valid_before
< kYear0001
|| not_valid_before
>= kYear10000
||
256 not_valid_after
< kYear0001
|| not_valid_after
>= kYear10000
)
262 bool CreateChannelIDEC(
263 crypto::ECPrivateKey
* key
,
265 const std::string
& domain
,
266 uint32 serial_number
,
267 base::Time not_valid_before
,
268 base::Time not_valid_after
,
269 std::string
* der_cert
) {
270 crypto::OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
271 // Create certificate.
272 ScopedX509
cert(CreateCertificate(key
->key(),
274 "CN=anonymous.invalid",
281 // Add TLS-Channel-ID extension to the certificate before signing it.
282 // The value must be stored DER-encoded, as a ASN.1 IA5String.
283 ScopedASN1_STRING
domain_ia5(ASN1_IA5STRING_new());
284 if (!domain_ia5
.get() ||
285 !ASN1_STRING_set(domain_ia5
.get(), domain
.data(), domain
.size()))
288 std::string domain_der
;
289 int domain_der_len
= i2d_ASN1_IA5STRING(domain_ia5
.get(), NULL
);
290 if (domain_der_len
< 0)
293 domain_der
.resize(domain_der_len
);
294 unsigned char* domain_der_data
=
295 reinterpret_cast<unsigned char*>(&domain_der
[0]);
296 if (i2d_ASN1_IA5STRING(domain_ia5
.get(), &domain_der_data
) < 0)
299 ScopedASN1_OCTET_STRING
domain_str(ASN1_OCTET_STRING_new());
300 if (!domain_str
.get() ||
301 !ASN1_STRING_set(domain_str
.get(), domain_der
.data(), domain_der
.size()))
304 ScopedX509_EXTENSION
ext(X509_EXTENSION_create_by_OBJ(
305 NULL
, GetDomainBoundOid(), 1 /* critical */, domain_str
.get()));
306 if (!ext
.get() || !X509_add_ext(cert
.get(), ext
.get(), -1)) {
310 // Sign and encode it.
311 return SignAndDerEncodeCert(cert
.get(), key
->key(), alg
, der_cert
);
314 bool CreateSelfSignedCert(crypto::RSAPrivateKey
* key
,
316 const std::string
& common_name
,
317 uint32 serial_number
,
318 base::Time not_valid_before
,
319 base::Time not_valid_after
,
320 std::string
* der_encoded
) {
321 crypto::OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
322 ScopedX509
cert(CreateCertificate(key
->key(),
331 return SignAndDerEncodeCert(cert
.get(), key
->key(), alg
, der_encoded
);
334 bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY
* entry
,
336 std::string
* value
) {
338 ASN1_OBJECT
* object
= X509_NAME_ENTRY_get_object(entry
);
339 key
->assign(OBJ_nid2sn(OBJ_obj2nid(object
)));
342 ASN1_STRING
* data
= X509_NAME_ENTRY_get_data(entry
);
346 unsigned char* buf
= NULL
;
347 int len
= ASN1_STRING_to_UTF8(&buf
, data
);
351 value
->assign(reinterpret_cast<const char*>(buf
), len
);
356 bool ParsePrincipalKeyAndValueByIndex(X509_NAME
* name
,
359 std::string
* value
) {
360 X509_NAME_ENTRY
* entry
= X509_NAME_get_entry(name
, index
);
364 return ParsePrincipalKeyAndValue(entry
, key
, value
);
367 bool ParsePrincipalValueByIndex(X509_NAME
* name
,
369 std::string
* value
) {
370 return ParsePrincipalKeyAndValueByIndex(name
, index
, NULL
, value
);
373 bool ParsePrincipalValueByNID(X509_NAME
* name
, int nid
, std::string
* value
) {
374 int index
= X509_NAME_get_index_by_NID(name
, nid
, -1);
378 return ParsePrincipalValueByIndex(name
, index
, value
);
381 bool ParseDate(ASN1_TIME
* x509_time
, base::Time
* time
) {
383 (x509_time
->type
!= V_ASN1_UTCTIME
&&
384 x509_time
->type
!= V_ASN1_GENERALIZEDTIME
))
387 base::StringPiece
str_date(reinterpret_cast<const char*>(x509_time
->data
),
390 CertDateFormat format
= x509_time
->type
== V_ASN1_UTCTIME
?
391 CERT_DATE_FORMAT_UTC_TIME
: CERT_DATE_FORMAT_GENERALIZED_TIME
;
392 return ParseCertificateDate(str_date
, format
, time
);
395 // Returns true if |der_cache| points to valid data, false otherwise.
396 // (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
398 bool GetDER(X509
* x509
, base::StringPiece
* der_cache
) {
399 int x509_der_cache_index
=
400 g_der_cache_singleton
.Get().der_cache_ex_index();
402 // Re-encoding the DER data via i2d_X509 is an expensive operation,
403 // but it's necessary for comparing two certificates. Re-encode at
404 // most once per certificate and cache the data within the X509 cert
405 // using X509_set_ex_data.
406 DERCache
* internal_cache
= static_cast<DERCache
*>(
407 X509_get_ex_data(x509
, x509_der_cache_index
));
408 if (!internal_cache
) {
409 scoped_ptr
<DERCache
> new_cache(new DERCache
);
410 if (!DerEncodeCert(x509
, &new_cache
->data
))
412 internal_cache
= new_cache
.get();
413 X509_set_ex_data(x509
, x509_der_cache_index
, new_cache
.release());
415 *der_cache
= base::StringPiece(internal_cache
->data
);
419 } // namespace x509_util