Home | History | Annotate | Download | only in cert
      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 
     21 namespace net {
     22 
     23 namespace {
     24 
     25 typedef crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free>::Type
     26     ScopedASN1_INTEGER;
     27 typedef crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>::Type
     28     ScopedASN1_OCTET_STRING;
     29 typedef crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>::Type
     30     ScopedASN1_STRING;
     31 typedef crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>::Type ScopedASN1_TIME;
     32 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
     33 typedef crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>::Type
     34     ScopedX509_EXTENSION;
     35 typedef crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>::Type ScopedX509_NAME;
     36 
     37 const 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 
     49 namespace x509_util {
     50 
     51 namespace {
     52 
     53 X509* 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|.
    133 bool 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 
    147 bool 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.
    170 class 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)
    190 const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
    191 
    192 ASN1_OBJECT* GetDomainBoundOid() {
    193   static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
    194       LAZY_INSTANCE_INITIALIZER;
    195   return s_lazy.Get().obj();
    196 }
    197 
    198 
    199 struct DERCache {
    200   std::string data;
    201 };
    202 
    203 void 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 
    209 class 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 
    225 base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton =
    226     LAZY_INSTANCE_INITIALIZER;
    227 
    228 }  // namespace
    229 
    230 bool 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 
    263 bool 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 
    315 bool 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 
    335 bool 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 
    357 bool 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 
    368 bool ParsePrincipalValueByIndex(X509_NAME* name,
    369                                 int index,
    370                                 std::string* value) {
    371   return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
    372 }
    373 
    374 bool 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 
    382 bool 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).
    399 bool 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