15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_openssl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <openssl/asn1.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/lazy_instance.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "crypto/ec_private_key.h"
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "crypto/openssl_util.h"
158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "crypto/rsa_private_key.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_cert_types.h"
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "net/cert/x509_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace {
220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  switch (alg) {
250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case x509_util::DIGEST_SHA1:
260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return EVP_sha1();
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case x509_util::DIGEST_SHA256:
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return EVP_sha256();
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return NULL;
310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace
340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace x509_util {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)X509* CreateCertificate(EVP_PKEY* key,
400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                        DigestAlgorithm alg,
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        const std::string& common_name,
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        uint32_t serial_number,
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        base::Time not_valid_before,
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        base::Time not_valid_after) {
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Put the serial number into an OpenSSL-friendly object.
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free> asn1_serial(
478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_INTEGER_new());
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!asn1_serial.get() ||
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) {
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Invalid serial number " << serial_number;
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Do the same for the time stamps.
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_before_time(
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_TIME_set(NULL, not_valid_before.ToTimeT()));
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!asn1_not_before_time.get()) {
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Invalid not_valid_before time: "
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               << not_valid_before.ToTimeT();
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_after_time(
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_TIME_set(NULL, not_valid_after.ToTimeT()));
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!asn1_not_after_time.get()) {
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT();
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Because |common_name| only contains a common name and starts with 'CN=',
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // there is no need for a full RFC 2253 parser here. Do some sanity checks
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // though.
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  static const char kCommonNamePrefix[] = "CN=";
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1;
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (common_name.size() < kCommonNamePrefixLen ||
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) {
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix;
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (common_name.size() > INT_MAX) {
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Common name too long";
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  unsigned char* common_name_str =
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) +
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      kCommonNamePrefixLen;
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int common_name_len =
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      static_cast<int>(common_name.size() - kCommonNamePrefixLen);
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free> name(X509_NAME_new());
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(),
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 NID_commonName,
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 MBSTRING_ASC,
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 common_name_str,
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 common_name_len,
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 -1,
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                 0)) {
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Can't parse common name: " << common_name.c_str();
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Now create certificate and populate it.
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<X509, X509_free> cert(X509_new());
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ ||
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_pubkey(cert.get(), key) ||
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_serialNumber(cert.get(), asn1_serial.get()) ||
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) ||
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_subject_name(cert.get(), name.get()) ||
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !X509_set_issuer_name(cert.get(), name.get())) {
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Could not create certificate";
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return cert.release();
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool SignAndDerEncodeCert(X509* cert,
1190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                          EVP_PKEY* key,
1200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                          DigestAlgorithm alg,
1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                          std::string* der_encoded) {
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Get the message digest algorithm
1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const EVP_MD* md = ToEVP(alg);
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!md) {
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    LOG(ERROR) << "Unrecognized hash algorithm.";
1260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return false;
1270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Sign it with the private key.
1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!X509_sign(cert, key, md)) {
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Could not sign certificate with key.";
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Convert it into a DER-encoded string copied to |der_encoded|.
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int der_data_length = i2d_X509(cert, NULL);
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (der_data_length < 0)
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  der_encoded->resize(der_data_length);
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  unsigned char* der_data =
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      reinterpret_cast<unsigned char*>(&(*der_encoded)[0]);
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (i2d_X509(cert, &der_data) < 0)
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return true;
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// so create a global ASN1_OBJECT lazily with the right parameters.
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class DomainBoundOid {
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public:
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ~DomainBoundOid() {
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (obj_)
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_OBJECT_free(obj_);
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASN1_OBJECT* obj() const { return obj_; }
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) private:
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  static const char kDomainBoundOidText[];
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASN1_OBJECT* obj_;
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)};
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// 1.3.6.1.4.1.11129.2.1.6
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// (iso.org.dod.internet.private.enterprises.google.googleSecurity.
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)//  certificateExtensions.originBoundCertificate)
1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ASN1_OBJECT* GetDomainBoundOid() {
1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      LAZY_INSTANCE_INITIALIZER;
1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return s_lazy.Get().obj();
1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsSupportedValidityRange(base::Time not_valid_before,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              base::Time not_valid_after) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (not_valid_before > not_valid_after)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The validity field of a certificate can only encode years 1-9999.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute the base::Time values corresponding to Jan 1st,0001 and
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // using the following Python script:
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     from datetime import date as D
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     print (D(1970,1,1)-D(1,1,1))        # -> 719162 days
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     print (D(9999,12,31)-D(1970,1,1))   # -> 2932896 days
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: This ignores leap seconds, but should be enough in practice.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 kDaysFromYear0001ToUnixEpoch = 719162;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 kDaysFromUnixEpochToYear10000 = 2932896 + 1;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Time kEpoch = base::Time::UnixEpoch();
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Time kYear0001 = kEpoch -
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Time kYear10000 = kEpoch +
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 ||
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      not_valid_after < kYear0001 || not_valid_after >= kYear10000)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateDomainBoundCertEC(
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::ECPrivateKey* key,
2160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    DigestAlgorithm alg,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& domain,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 serial_number,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time not_valid_before,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time not_valid_after,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* der_cert) {
2228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
2238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Create certificate.
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<X509, X509_free> cert(
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      CreateCertificate(key->key(),
2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                        alg,
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        "CN=anonymous.invalid",
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        serial_number,
2298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        not_valid_before,
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        not_valid_after));
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!cert.get())
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Add TLS-Channel-ID extension to the certificate before signing it.
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The value must be stored DER-encoded, as a ASN.1 IA5String.
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free> domain_ia5(
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_IA5STRING_new());
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!domain_ia5.get() ||
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size()))
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string domain_der;
2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL);
2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (domain_der_len < 0)
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  domain_der.resize(domain_der_len);
2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  unsigned char* domain_der_data =
2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      reinterpret_cast<unsigned char*>(&domain_der[0]);
2508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0)
2518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free> domain_str(
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ASN1_OCTET_STRING_new());
2558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!domain_str.get() ||
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size()))
2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free> ext(
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      X509_EXTENSION_create_by_OBJ(
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get()));
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) {
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Sign and encode it.
2670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
2710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                          DigestAlgorithm alg,
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          const std::string& common_name,
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          uint32 serial_number,
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          base::Time not_valid_before,
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          base::Time not_valid_after,
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          std::string* der_encoded) {
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  crypto::ScopedOpenSSL<X509, X509_free> cert(
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      CreateCertificate(key->key(),
2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                        alg,
2818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        common_name,
2828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        serial_number,
2838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        not_valid_before,
2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        not_valid_after));
2858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!cert.get())
2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
2878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded);
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int index,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* key,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* value) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char* buf = NULL;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = ASN1_STRING_to_UTF8(&buf, data);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len <= 0)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->assign(reinterpret_cast<const char*>(buf), len);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OPENSSL_free(buf);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParsePrincipalValueByIndex(X509_NAME* name,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int index,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                std::string* value) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = X509_NAME_get_index_by_NID(name, nid, -1);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < 0)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParsePrincipalValueByIndex(name, index, value);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!x509_time ||
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (x509_time->type != V_ASN1_UTCTIME &&
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       x509_time->type != V_ASN1_GENERALIZEDTIME))
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             x509_time->length);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParseCertificateDate(str_date, format, time);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace x509_util
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
349