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.
4
5#include "net/cert/x509_util_openssl.h"
6
7#include <algorithm>
8#include <openssl/asn1.h>
9
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
21namespace net {
22
23namespace {
24
25typedef crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free>::Type
26    ScopedASN1_INTEGER;
27typedef crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>::Type
28    ScopedASN1_OCTET_STRING;
29typedef crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>::Type
30    ScopedASN1_STRING;
31typedef crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>::Type ScopedASN1_TIME;
32typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
33typedef crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>::Type
34    ScopedX509_EXTENSION;
35typedef crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>::Type ScopedX509_NAME;
36
37const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
38  switch (alg) {
39    case x509_util::DIGEST_SHA1:
40      return EVP_sha1();
41    case x509_util::DIGEST_SHA256:
42      return EVP_sha256();
43  }
44  return NULL;
45}
46
47}  // namespace
48
49namespace x509_util {
50
51namespace {
52
53X509* CreateCertificate(EVP_PKEY* key,
54                        DigestAlgorithm alg,
55                        const std::string& common_name,
56                        uint32_t serial_number,
57                        base::Time not_valid_before,
58                        base::Time not_valid_after) {
59  // Put the serial number into an OpenSSL-friendly object.
60  ScopedASN1_INTEGER asn1_serial(ASN1_INTEGER_new());
61  if (!asn1_serial.get() ||
62      !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) {
63    LOG(ERROR) << "Invalid serial number " << serial_number;
64    return NULL;
65  }
66
67  // Do the same for the time stamps.
68  ScopedASN1_TIME asn1_not_before_time(
69      ASN1_TIME_set(NULL, not_valid_before.ToTimeT()));
70  if (!asn1_not_before_time.get()) {
71    LOG(ERROR) << "Invalid not_valid_before time: "
72               << not_valid_before.ToTimeT();
73    return NULL;
74  }
75
76  ScopedASN1_TIME asn1_not_after_time(
77      ASN1_TIME_set(NULL, not_valid_after.ToTimeT()));
78  if (!asn1_not_after_time.get()) {
79    LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT();
80    return NULL;
81  }
82
83  // Because |common_name| only contains a common name and starts with 'CN=',
84  // there is no need for a full RFC 2253 parser here. Do some sanity checks
85  // though.
86  static const char kCommonNamePrefix[] = "CN=";
87  const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1;
88  if (common_name.size() < kCommonNamePrefixLen ||
89      strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) {
90    LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix;
91    return NULL;
92  }
93  if (common_name.size() > INT_MAX) {
94    LOG(ERROR) << "Common name too long";
95    return NULL;
96  }
97  unsigned char* common_name_str =
98      reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) +
99      kCommonNamePrefixLen;
100  int common_name_len =
101      static_cast<int>(common_name.size() - kCommonNamePrefixLen);
102
103  ScopedX509_NAME name(X509_NAME_new());
104  if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(),
105                                                 NID_commonName,
106                                                 MBSTRING_ASC,
107                                                 common_name_str,
108                                                 common_name_len,
109                                                 -1,
110                                                 0)) {
111    LOG(ERROR) << "Can't parse common name: " << common_name.c_str();
112    return NULL;
113  }
114
115  // Now create certificate and populate it.
116  ScopedX509 cert(X509_new());
117  if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ ||
118      !X509_set_pubkey(cert.get(), key) ||
119      !X509_set_serialNumber(cert.get(), asn1_serial.get()) ||
120      !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) ||
121      !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
122      !X509_set_subject_name(cert.get(), name.get()) ||
123      !X509_set_issuer_name(cert.get(), name.get())) {
124    LOG(ERROR) << "Could not create certificate";
125    return NULL;
126  }
127
128  return cert.release();
129}
130
131// DER-encodes |x509|. On success, returns true and writes the
132// encoding to |*out_der|.
133bool DerEncodeCert(X509* x509, std::string* out_der) {
134  int len = i2d_X509(x509, NULL);
135  if (len < 0)
136    return false;
137
138  uint8_t* ptr = reinterpret_cast<uint8_t*>(WriteInto(out_der, len + 1));
139  if (i2d_X509(x509, &ptr) < 0) {
140    NOTREACHED();
141    out_der->clear();
142    return false;
143  }
144  return true;
145}
146
147bool SignAndDerEncodeCert(X509* cert,
148                          EVP_PKEY* key,
149                          DigestAlgorithm alg,
150                          std::string* der_encoded) {
151  // Get the message digest algorithm
152  const EVP_MD* md = ToEVP(alg);
153  if (!md) {
154    LOG(ERROR) << "Unrecognized hash algorithm.";
155    return false;
156  }
157
158  // Sign it with the private key.
159  if (!X509_sign(cert, key, md)) {
160    LOG(ERROR) << "Could not sign certificate with key.";
161    return false;
162  }
163
164  // Convert it into a DER-encoded string copied to |der_encoded|.
165  return DerEncodeCert(cert, der_encoded);
166}
167
168// There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
169// so create a global ASN1_OBJECT lazily with the right parameters.
170class DomainBoundOid {
171 public:
172  DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }
173
174  ~DomainBoundOid() {
175    if (obj_)
176      ASN1_OBJECT_free(obj_);
177  }
178
179  ASN1_OBJECT* obj() const { return obj_; }
180
181 private:
182  static const char kDomainBoundOidText[];
183
184  ASN1_OBJECT* obj_;
185};
186
187// 1.3.6.1.4.1.11129.2.1.6
188// (iso.org.dod.internet.private.enterprises.google.googleSecurity.
189//  certificateExtensions.originBoundCertificate)
190const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
191
192ASN1_OBJECT* GetDomainBoundOid() {
193  static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
194      LAZY_INSTANCE_INITIALIZER;
195  return s_lazy.Get().obj();
196}
197
198
199struct DERCache {
200  std::string data;
201};
202
203void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
204                   long argl, void* argp) {
205  DERCache* der_cache = static_cast<DERCache*>(ptr);
206  delete der_cache;
207}
208
209class DERCacheInitSingleton {
210 public:
211  DERCacheInitSingleton() {
212    crypto::EnsureOpenSSLInit();
213    der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
214    DCHECK_NE(-1, der_cache_ex_index_);
215  }
216
217  int der_cache_ex_index() const { return der_cache_ex_index_; }
218
219 private:
220  int der_cache_ex_index_;
221
222  DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton);
223};
224
225base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton =
226    LAZY_INSTANCE_INITIALIZER;
227
228}  // namespace
229
230bool IsSupportedValidityRange(base::Time not_valid_before,
231                              base::Time not_valid_after) {
232  if (not_valid_before > not_valid_after)
233    return false;
234
235  // The validity field of a certificate can only encode years 1-9999.
236
237  // Compute the base::Time values corresponding to Jan 1st,0001 and
238  // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
239  // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
240  // using the following Python script:
241  //
242  //     from datetime import date as D
243  //     print (D(1970,1,1)-D(1,1,1))        # -> 719162 days
244  //     print (D(9999,12,31)-D(1970,1,1))   # -> 2932896 days
245  //
246  // Note: This ignores leap seconds, but should be enough in practice.
247  //
248  const int64 kDaysFromYear0001ToUnixEpoch = 719162;
249  const int64 kDaysFromUnixEpochToYear10000 = 2932896 + 1;
250  const base::Time kEpoch = base::Time::UnixEpoch();
251  const base::Time kYear0001 = kEpoch -
252      base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch);
253  const base::Time kYear10000 = kEpoch +
254      base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000);
255
256  if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 ||
257      not_valid_after < kYear0001 || not_valid_after >= kYear10000)
258    return false;
259
260  return true;
261}
262
263bool CreateChannelIDEC(
264    crypto::ECPrivateKey* key,
265    DigestAlgorithm alg,
266    const std::string& domain,
267    uint32 serial_number,
268    base::Time not_valid_before,
269    base::Time not_valid_after,
270    std::string* der_cert) {
271  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
272  // Create certificate.
273  ScopedX509 cert(CreateCertificate(key->key(),
274                                    alg,
275                                    "CN=anonymous.invalid",
276                                    serial_number,
277                                    not_valid_before,
278                                    not_valid_after));
279  if (!cert.get())
280    return false;
281
282  // Add TLS-Channel-ID extension to the certificate before signing it.
283  // The value must be stored DER-encoded, as a ASN.1 IA5String.
284  ScopedASN1_STRING domain_ia5(ASN1_IA5STRING_new());
285  if (!domain_ia5.get() ||
286      !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size()))
287    return false;
288
289  std::string domain_der;
290  int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL);
291  if (domain_der_len < 0)
292    return false;
293
294  domain_der.resize(domain_der_len);
295  unsigned char* domain_der_data =
296      reinterpret_cast<unsigned char*>(&domain_der[0]);
297  if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0)
298    return false;
299
300  ScopedASN1_OCTET_STRING domain_str(ASN1_OCTET_STRING_new());
301  if (!domain_str.get() ||
302      !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size()))
303    return false;
304
305  ScopedX509_EXTENSION ext(X509_EXTENSION_create_by_OBJ(
306      NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get()));
307  if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) {
308    return false;
309  }
310
311  // Sign and encode it.
312  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert);
313}
314
315bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
316                          DigestAlgorithm alg,
317                          const std::string& common_name,
318                          uint32 serial_number,
319                          base::Time not_valid_before,
320                          base::Time not_valid_after,
321                          std::string* der_encoded) {
322  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
323  ScopedX509 cert(CreateCertificate(key->key(),
324                                    alg,
325                                    common_name,
326                                    serial_number,
327                                    not_valid_before,
328                                    not_valid_after));
329  if (!cert.get())
330    return false;
331
332  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded);
333}
334
335bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY* entry,
336                               std::string* key,
337                               std::string* value) {
338  if (key) {
339    ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
340    key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
341  }
342
343  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
344  if (!data)
345    return false;
346
347  unsigned char* buf = NULL;
348  int len = ASN1_STRING_to_UTF8(&buf, data);
349  if (len <= 0)
350    return false;
351
352  value->assign(reinterpret_cast<const char*>(buf), len);
353  OPENSSL_free(buf);
354  return true;
355}
356
357bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
358                                      int index,
359                                      std::string* key,
360                                      std::string* value) {
361  X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
362  if (!entry)
363    return false;
364
365  return ParsePrincipalKeyAndValue(entry, key, value);
366}
367
368bool ParsePrincipalValueByIndex(X509_NAME* name,
369                                int index,
370                                std::string* value) {
371  return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
372}
373
374bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
375  int index = X509_NAME_get_index_by_NID(name, nid, -1);
376  if (index < 0)
377    return false;
378
379  return ParsePrincipalValueByIndex(name, index, value);
380}
381
382bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
383  if (!x509_time ||
384      (x509_time->type != V_ASN1_UTCTIME &&
385       x509_time->type != V_ASN1_GENERALIZEDTIME))
386    return false;
387
388  base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
389                             x509_time->length);
390
391  CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
392      CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
393  return ParseCertificateDate(str_date, format, time);
394}
395
396// Returns true if |der_cache| points to valid data, false otherwise.
397// (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
398// not free it).
399bool GetDER(X509* x509, base::StringPiece* der_cache) {
400  int x509_der_cache_index =
401      g_der_cache_singleton.Get().der_cache_ex_index();
402
403  // Re-encoding the DER data via i2d_X509 is an expensive operation,
404  // but it's necessary for comparing two certificates. Re-encode at
405  // most once per certificate and cache the data within the X509 cert
406  // using X509_set_ex_data.
407  DERCache* internal_cache = static_cast<DERCache*>(
408      X509_get_ex_data(x509, x509_der_cache_index));
409  if (!internal_cache) {
410    scoped_ptr<DERCache> new_cache(new DERCache);
411    if (!DerEncodeCert(x509, &new_cache->data))
412      return false;
413    internal_cache = new_cache.get();
414    X509_set_ex_data(x509, x509_der_cache_index, new_cache.release());
415  }
416  *der_cache = base::StringPiece(internal_cache->data);
417  return true;
418}
419
420}  // namespace x509_util
421
422}  // namespace net
423