diff options
Diffstat (limited to 'src/lib/tls/x509.c')
-rw-r--r-- | src/lib/tls/x509.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/lib/tls/x509.c b/src/lib/tls/x509.c new file mode 100644 index 0000000000..67a8b49b9d --- /dev/null +++ b/src/lib/tls/x509.c @@ -0,0 +1,143 @@ +/* Copyright (c) 2003, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file x509_openssl.c + * \brief Wrapper functions to present a consistent interface to + * X.509 functions. + **/ + +#define TOR_X509_PRIVATE +#include "lib/tls/x509.h" +#include "lib/tls/x509_internal.h" +#include "lib/log/util_bug.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/crypt_ops/crypto_util.h" + +/** 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; +} + +/** 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; +} + +/** Free all storage held in <b>cert</b> */ +void +tor_x509_cert_free_(tor_x509_cert_t *cert) +{ + if (! cert) + return; + tor_x509_cert_impl_free(cert->cert); +#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) { + log_warn(LD_CRYPTO, "unable to compute digests of certificate key"); + 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."); + tor_x509_cert_free(cert); + return NULL; +} + +/** 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)); +} |