Skip to content

Commit

Permalink
Check if the system time is within the range NSS can handle before ad…
Browse files Browse the repository at this point in the history
…vertising TLS channel id support.

BUG=142388
TEST=set year to 1601, run with --enable-origin-bound-certs, try connecting to google https sites.


Review URL: https://chromiumcodereview.appspot.com/10896046

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155046 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mattm@chromium.org committed Sep 5, 2012
1 parent e5351cd commit 60675bc
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 8 deletions.
11 changes: 10 additions & 1 deletion net/base/server_bound_cert_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ namespace {

const int kKeySizeInBits = 1024;
const int kValidityPeriodInDays = 365;
// When we check the system time, we add this many days to the end of the check
// so the result will still hold even after chrome has been running for a
// while.
const int kSystemTimeValidityBufferInDays = 90;

bool IsSupportedCertType(uint8 type) {
switch(type) {
Expand Down Expand Up @@ -361,7 +365,12 @@ ServerBoundCertService::ServerBoundCertService(
task_runner_(task_runner),
requests_(0),
cert_store_hits_(0),
inflight_joins_(0) {}
inflight_joins_(0) {
base::Time start = base::Time::Now();
base::Time end = start + base::TimeDelta::FromDays(
kValidityPeriodInDays + kSystemTimeValidityBufferInDays);
is_system_time_valid_ = x509_util::IsSupportedValidityRange(start, end);
}

ServerBoundCertService::~ServerBoundCertService() {
STLDeleteValues(&inflight_);
Expand Down
8 changes: 8 additions & 0 deletions net/base/server_bound_cert_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ class NET_EXPORT ServerBoundCertService
// the origin otherwise.
static std::string GetDomainForHost(const std::string& host);

// Tests whether the system time is within the supported range for
// certificate generation. This value is cached when ServerBoundCertService
// is created, so if the system time is changed by a huge amount, this may no
// longer hold.
bool IsSystemTimeValid() const { return is_system_time_valid_; }

// Fetches the domain bound cert for the specified origin of the specified
// type if one exists and creates one otherwise. Returns OK if successful or
// an error code upon failure.
Expand Down Expand Up @@ -134,6 +140,8 @@ class NET_EXPORT ServerBoundCertService
uint64 cert_store_hits_;
uint64 inflight_joins_;

bool is_system_time_valid_;

DISALLOW_COPY_AND_ASSIGN(ServerBoundCertService);
};

Expand Down
8 changes: 8 additions & 0 deletions net/base/x509_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ namespace net {

namespace x509_util {

// Returns true if the times can be used to create an X.509 certificate.
// Certificates can accept dates from Jan 1st, 1 to Dec 31, 9999. A bug in NSS
// limited the range to 1950-9999
// (https://bugzilla.mozilla.org/show_bug.cgi?id=786531). This function will
// return whether it is supported by the currently used crypto library.
bool IsSupportedValidityRange(base::Time not_valid_before,
base::Time not_valid_after);

// Creates a server bound certificate containing the public key in |key|.
// Domain, serial number and validity period are given as
// parameters. The certificate is signed by the private key in |key|.
Expand Down
13 changes: 13 additions & 0 deletions net/base/x509_util_nss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,19 @@ CERTCertificate* CreateSelfSignedCert(
return cert;
}

bool IsSupportedValidityRange(base::Time not_valid_before,
base::Time not_valid_after) {
CERTValidity* validity = CERT_CreateValidity(
crypto::BaseTimeToPRTime(not_valid_before),
crypto::BaseTimeToPRTime(not_valid_after));

if (!validity)
return false;

CERT_DestroyValidity(validity);
return true;
}

bool CreateDomainBoundCertEC(
crypto::ECPrivateKey* key,
const std::string& domain,
Expand Down
8 changes: 8 additions & 0 deletions net/base/x509_util_openssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ namespace net {

namespace x509_util {

bool IsSupportedValidityRange(base::Time not_valid_before,
base::Time not_valid_after) {
// TODO(mattm): The validity field of a certificate can only encode years
// 1-9999.
NOTIMPLEMENTED();
return true;
}

bool CreateDomainBoundCertEC(
crypto::ECPrivateKey* key,
const std::string& domain,
Expand Down
24 changes: 17 additions & 7 deletions net/socket/ssl_client_socket_nss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "crypto/ec_private_key.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_nss_types.h"
Expand Down Expand Up @@ -1074,14 +1075,16 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
}

if (ssl_config_.channel_id_enabled) {
if (crypto::ECPrivateKey::IsSupported()) {
if (!crypto::ECPrivateKey::IsSupported()) {
DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
} else if (!server_bound_cert_service_->IsSystemTimeValid()) {
DVLOG(1) << "System time is weird, not enabling channel ID.";
} else {
rv = SSL_SetClientChannelIDCallback(
nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
if (rv != SECSuccess)
LogFailedNSSFunction(*weak_net_log_, "SSL_SetClientChannelIDCallback",
"");
} else {
DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
}
}

Expand Down Expand Up @@ -2513,13 +2516,20 @@ void SSLClientSocketNSS::Core::RecordChannelIDSupport() const {
DISABLED = 0,
CLIENT_ONLY = 1,
CLIENT_AND_SERVER = 2,
CLIENT_NO_ECC = 3,
CLIENT_BAD_SYSTEM_TIME = 4,
DOMAIN_BOUND_CERT_USAGE_MAX
} supported = DISABLED;
if (channel_id_xtn_negotiated_)
if (channel_id_xtn_negotiated_) {
supported = CLIENT_AND_SERVER;
else if (ssl_config_.channel_id_enabled &&
crypto::ECPrivateKey::IsSupported())
supported = CLIENT_ONLY;
} else if (ssl_config_.channel_id_enabled) {
if (!crypto::ECPrivateKey::IsSupported())
supported = CLIENT_NO_ECC;
else if (!server_bound_cert_service_->IsSystemTimeValid())
supported = CLIENT_BAD_SYSTEM_TIME;
else
supported = CLIENT_ONLY;
}
UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
DOMAIN_BOUND_CERT_USAGE_MAX);
}
Expand Down

0 comments on commit 60675bc

Please sign in to comment.