2018-08-11 18:16:04 -04:00
|
|
|
/* Copyright (c) 2003, Roger Dingledine.
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2019-01-16 12:33:22 -05:00
|
|
|
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
2018-08-11 18:16:04 -04:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
2018-08-12 16:04:12 -04:00
|
|
|
* \file x509_openssl.c
|
2018-08-11 18:16:04 -04:00
|
|
|
* \brief Wrapper functions to present a consistent interface to
|
2018-08-12 16:04:12 -04:00
|
|
|
* X.509 functions.
|
2018-08-11 18:16:04 -04:00
|
|
|
**/
|
|
|
|
|
2018-08-11 19:38:07 -04:00
|
|
|
#define TOR_X509_PRIVATE
|
2018-08-11 18:16:04 -04:00
|
|
|
#include "lib/tls/x509.h"
|
2018-08-12 18:01:14 -04:00
|
|
|
#include "lib/tls/x509_internal.h"
|
2018-08-11 18:16:04 -04:00
|
|
|
#include "lib/log/util_bug.h"
|
2018-08-12 16:04:12 -04:00
|
|
|
#include "lib/crypt_ops/crypto_rand.h"
|
2018-08-12 19:40:47 -04:00
|
|
|
#include "lib/crypt_ops/crypto_util.h"
|
2018-08-11 18:16:04 -04:00
|
|
|
|
2018-08-11 19:54:11 -04:00
|
|
|
/** Choose the start and end times for a certificate */
|
|
|
|
void
|
|
|
|
tor_tls_pick_certificate_lifetime(time_t now,
|
|
|
|
unsigned int cert_lifetime,
|
|
|
|
time_t *start_time_out,
|
|
|
|
time_t *end_time_out)
|
|
|
|
{
|
|
|
|
time_t start_time, end_time;
|
|
|
|
/* Make sure we're part-way through the certificate lifetime, rather
|
|
|
|
* than having it start right now. Don't choose quite uniformly, since
|
|
|
|
* then we might pick a time where we're about to expire. Lastly, be
|
|
|
|
* sure to start on a day boundary. */
|
|
|
|
/* Our certificate lifetime will be cert_lifetime no matter what, but if we
|
|
|
|
* start cert_lifetime in the past, we'll have 0 real lifetime. instead we
|
|
|
|
* start up to (cert_lifetime - min_real_lifetime - start_granularity) in
|
|
|
|
* the past. */
|
|
|
|
const time_t min_real_lifetime = 24*3600;
|
|
|
|
const time_t start_granularity = 24*3600;
|
|
|
|
time_t earliest_start_time;
|
|
|
|
/* Don't actually start in the future! */
|
|
|
|
if (cert_lifetime <= min_real_lifetime + start_granularity) {
|
|
|
|
earliest_start_time = now - 1;
|
|
|
|
} else {
|
|
|
|
earliest_start_time = now + min_real_lifetime + start_granularity
|
|
|
|
- cert_lifetime;
|
|
|
|
}
|
|
|
|
start_time = crypto_rand_time_range(earliest_start_time, now);
|
|
|
|
/* Round the start time back to the start of a day. */
|
|
|
|
start_time -= start_time % start_granularity;
|
|
|
|
|
|
|
|
end_time = start_time + cert_lifetime;
|
|
|
|
|
|
|
|
*start_time_out = start_time;
|
|
|
|
*end_time_out = end_time;
|
|
|
|
}
|
|
|
|
|
2018-08-11 18:16:04 -04:00
|
|
|
/** Return a set of digests for the public key in <b>cert</b>, or NULL if this
|
|
|
|
* cert's public key is not one we know how to take the digest of. */
|
|
|
|
const common_digests_t *
|
|
|
|
tor_x509_cert_get_id_digests(const tor_x509_cert_t *cert)
|
|
|
|
{
|
|
|
|
if (cert->pkey_digests_set)
|
|
|
|
return &cert->pkey_digests;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Return a set of digests for the public key in <b>cert</b>. */
|
|
|
|
const common_digests_t *
|
|
|
|
tor_x509_cert_get_cert_digests(const tor_x509_cert_t *cert)
|
|
|
|
{
|
|
|
|
return &cert->cert_digests;
|
|
|
|
}
|
|
|
|
|
2018-08-12 19:40:47 -04:00
|
|
|
/** Free all storage held in <b>cert</b> */
|
|
|
|
void
|
|
|
|
tor_x509_cert_free_(tor_x509_cert_t *cert)
|
|
|
|
{
|
|
|
|
if (! cert)
|
|
|
|
return;
|
2018-09-04 14:37:42 -04:00
|
|
|
tor_x509_cert_impl_free(cert->cert);
|
2018-08-12 19:40:47 -04:00
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
tor_free(cert->encoded);
|
|
|
|
#endif
|
|
|
|
memwipe(cert, 0x03, sizeof(*cert));
|
|
|
|
/* LCOV_EXCL_BR_START since cert will never be NULL here */
|
|
|
|
tor_free(cert);
|
|
|
|
/* LCOV_EXCL_BR_STOP */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate a new tor_x509_cert_t to hold the certificate "x509_cert".
|
|
|
|
*
|
|
|
|
* Steals a reference to x509_cert.
|
|
|
|
*/
|
|
|
|
MOCK_IMPL(tor_x509_cert_t *,
|
|
|
|
tor_x509_cert_new,(tor_x509_cert_impl_t *x509_cert))
|
|
|
|
{
|
|
|
|
tor_x509_cert_t *cert;
|
|
|
|
|
|
|
|
if (!x509_cert)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
|
|
|
|
cert->cert = x509_cert;
|
|
|
|
|
|
|
|
if (tor_x509_cert_set_cached_der_encoding(cert) < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
{
|
|
|
|
const uint8_t *encoded=NULL;
|
|
|
|
size_t encoded_len=0;
|
|
|
|
tor_x509_cert_get_der(cert, &encoded, &encoded_len);
|
|
|
|
tor_assert(encoded);
|
|
|
|
crypto_common_digests(&cert->cert_digests, (char *)encoded, encoded_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
crypto_pk_t *pk = tor_tls_cert_get_key(cert);
|
|
|
|
if (pk) {
|
|
|
|
if (crypto_pk_get_common_digests(pk, &cert->pkey_digests) < 0) {
|
2018-08-23 14:03:00 -04:00
|
|
|
log_warn(LD_CRYPTO, "unable to compute digests of certificate key");
|
2018-08-12 19:40:47 -04:00
|
|
|
crypto_pk_free(pk);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cert->pkey_digests_set = 1;
|
|
|
|
crypto_pk_free(pk);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cert;
|
|
|
|
err:
|
|
|
|
log_err(LD_CRYPTO, "Couldn't wrap encoded X509 certificate.");
|
2018-09-04 19:41:59 -04:00
|
|
|
tor_x509_cert_free(cert);
|
2018-08-12 19:40:47 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-09-04 12:59:47 -04:00
|
|
|
|
|
|
|
/** Return a new copy of <b>cert</b>. */
|
|
|
|
tor_x509_cert_t *
|
|
|
|
tor_x509_cert_dup(const tor_x509_cert_t *cert)
|
|
|
|
{
|
|
|
|
tor_assert(cert);
|
|
|
|
tor_assert(cert->cert);
|
|
|
|
return tor_x509_cert_new(tor_x509_cert_impl_dup_(cert->cert));
|
|
|
|
}
|