commit 5245a296c58eb8aba712e94a78d5bcaa2a2f25fb Author: Nick Mathewson nickm@torproject.org Date: Sun Aug 12 19:40:47 2018 -0400
Make some x509 functions generic; remove some fields NSS doesn't need --- src/lib/tls/x509.c | 79 +++++++++++++++++++++++++++++++++------- src/lib/tls/x509.h | 2 ++ src/lib/tls/x509_internal.h | 7 ++++ src/lib/tls/x509_nss.c | 35 +++++++++++------- src/lib/tls/x509_openssl.c | 82 +++++++++++++----------------------------- src/test/test_link_handshake.c | 8 +++-- 6 files changed, 127 insertions(+), 86 deletions(-)
diff --git a/src/lib/tls/x509.c b/src/lib/tls/x509.c index fc6139ace..d2270f910 100644 --- a/src/lib/tls/x509.c +++ b/src/lib/tls/x509.c @@ -14,6 +14,7 @@ #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 @@ -51,19 +52,6 @@ tor_tls_pick_certificate_lifetime(time_t now, *end_time_out = end_time; }
-/** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER - * representation and length, respectively. */ -void -tor_x509_cert_get_der(const tor_x509_cert_t *cert, - const uint8_t **encoded_out, size_t *size_out) -{ - tor_assert(cert); - tor_assert(encoded_out); - tor_assert(size_out); - *encoded_out = cert->encoded; - *size_out = cert->encoded_len; -} - /** Return the underlying implementation for <b>cert</b> */ const tor_x509_cert_impl_t * tor_x509_cert_get_impl(const tor_x509_cert_t *cert) @@ -90,3 +78,68 @@ 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; + if (cert->cert) + 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) { + crypto_pk_free(pk); + goto err; + } + } + cert->pkey_digests_set = 1; + crypto_pk_free(pk); + } + + return cert; + err: + /* LCOV_EXCL_START for the same reason as the exclusion above */ + tor_free(cert); + log_err(LD_CRYPTO, "Couldn't wrap encoded X509 certificate."); + tor_x509_cert_impl_free_(x509_cert); + return NULL; + /* LCOV_EXCL_STOP */ +} diff --git a/src/lib/tls/x509.h b/src/lib/tls/x509.h index ccaa92184..8316df75a 100644 --- a/src/lib/tls/x509.h +++ b/src/lib/tls/x509.h @@ -27,8 +27,10 @@ typedef struct x509_st tor_x509_cert_impl_t; /** Structure that we use for a single certificate. */ struct tor_x509_cert_t { tor_x509_cert_impl_t *cert; +#ifdef ENABLE_OPENSSL uint8_t *encoded; size_t encoded_len; +#endif unsigned pkey_digests_set : 1; common_digests_t cert_digests; common_digests_t pkey_digests; diff --git a/src/lib/tls/x509_internal.h b/src/lib/tls/x509_internal.h index 2cca393d2..86f5a0de5 100644 --- a/src/lib/tls/x509_internal.h +++ b/src/lib/tls/x509_internal.h @@ -25,4 +25,11 @@ MOCK_DECL(tor_x509_cert_t *, tor_x509_cert_new, const tor_x509_cert_impl_t *tor_x509_cert_get_impl( const tor_x509_cert_t *cert);
+void tor_x509_cert_impl_free_(tor_x509_cert_impl_t *cert); +#ifdef ENABLE_OPENSSL +int tor_x509_cert_set_cached_der_encoding(tor_x509_cert_t *cert); +#else +#define tor_x509_cert_set_cached_der_encoding(cert) (0) +#endif + #endif diff --git a/src/lib/tls/x509_nss.c b/src/lib/tls/x509_nss.c index e0087eae6..ac9e6658d 100644 --- a/src/lib/tls/x509_nss.c +++ b/src/lib/tls/x509_nss.c @@ -17,6 +17,9 @@ #include "lib/crypt_ops/crypto_util.h" #include "lib/log/util_bug.h"
+#include <pk11pub.h> +#include <cert.h> + MOCK_IMPL(tor_x509_cert_impl_t *, tor_tls_create_certificate,(crypto_pk_t *rsa, crypto_pk_t *rsa_sign, @@ -33,12 +36,27 @@ tor_tls_create_certificate,(crypto_pk_t *rsa, return NULL; }
-MOCK_IMPL(tor_x509_cert_t *, -tor_x509_cert_new,(tor_x509_cert_impl_t *x509_cert)) +/** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER + * representation and length, respectively. */ +void +tor_x509_cert_get_der(const tor_x509_cert_t *cert, + const uint8_t **encoded_out, size_t *size_out) { - tor_assert(x509_cert); - // XXXX - return NULL; + tor_assert(cert); + tor_assert(cert->cert); + tor_assert(encoded_out); + tor_assert(size_out); + + const SECItem *item = &cert->cert->derCert; + *encoded_out = item->data; + *size_out = (size_t)item->len; +} + +void +tor_x509_cert_impl_free_(tor_x509_cert_impl_t *cert) +{ + if (cert) + CERT_DestroyCertificate(cert); }
tor_x509_cert_t * @@ -49,13 +67,6 @@ tor_x509_cert_dup(const tor_x509_cert_t *cert) return NULL; }
-void -tor_x509_cert_free_(tor_x509_cert_t *cert) -{ - (void)cert; - // XXXX -} - tor_x509_cert_t * tor_x509_cert_decode(const uint8_t *certificate, size_t certificate_len) diff --git a/src/lib/tls/x509_openssl.c b/src/lib/tls/x509_openssl.c index 43d33d781..43bd6b4d4 100644 --- a/src/lib/tls/x509_openssl.c +++ b/src/lib/tls/x509_openssl.c @@ -182,75 +182,41 @@ tor_tls_create_certificate,(crypto_pk_t *rsa, #undef SERIAL_NUMBER_SIZE }
-/** Free all storage held in <b>cert</b> */ -void -tor_x509_cert_free_(tor_x509_cert_t *cert) -{ - if (! cert) - return; - if (cert->cert) - X509_free(cert->cert); - tor_free(cert->encoded); - 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,(X509 *x509_cert)) +/** Set the 'encoded' and 'encoded_len' fields of "cert" from cert->cert. */ +int +tor_x509_cert_set_cached_der_encoding(tor_x509_cert_t *cert) { - tor_x509_cert_t *cert; - EVP_PKEY *pkey; - RSA *rsa; - int length; unsigned char *buf = NULL; + int length = i2d_X509(cert->cert, &buf);
- if (!x509_cert) - return NULL; - - length = i2d_X509(x509_cert, &buf); - cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); if (length <= 0 || buf == NULL) { - goto err; + return -1; } cert->encoded_len = (size_t) length; cert->encoded = tor_malloc(length); memcpy(cert->encoded, buf, length); OPENSSL_free(buf); + return 0; +}
- cert->cert = x509_cert; - - crypto_common_digests(&cert->cert_digests, - (char*)cert->encoded, cert->encoded_len); - - if ((pkey = X509_get_pubkey(x509_cert)) && - (rsa = EVP_PKEY_get1_RSA(pkey))) { - crypto_pk_t *pk = crypto_new_pk_from_openssl_rsa_(rsa); - if (crypto_pk_get_common_digests(pk, &cert->pkey_digests) < 0) { - crypto_pk_free(pk); - EVP_PKEY_free(pkey); - goto err; - } - - cert->pkey_digests_set = 1; - crypto_pk_free(pk); - EVP_PKEY_free(pkey); - } +void +tor_x509_cert_impl_free_(tor_x509_cert_impl_t *cert) +{ + if (cert) + X509_free(cert); +}
- return cert; - err: - /* LCOV_EXCL_START for the same reason as the exclusion above */ - tor_free(cert); - log_err(LD_CRYPTO, "Couldn't wrap encoded X509 certificate."); - X509_free(x509_cert); - return NULL; - /* LCOV_EXCL_STOP */ +/** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER + * representation and length, respectively. */ +void +tor_x509_cert_get_der(const tor_x509_cert_t *cert, + const uint8_t **encoded_out, size_t *size_out) +{ + tor_assert(cert); + tor_assert(encoded_out); + tor_assert(size_out); + *encoded_out = cert->encoded; + *size_out = cert->encoded_len; }
/** Return a new copy of <b>cert</b>. */ diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index e4722b4df..677276599 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -811,9 +811,11 @@ CERTS_FAIL(expired_rsa_id, /* both */ tor_x509_cert_t *newc; time_t new_end = time(NULL) - 86400 * 10; newc = tor_x509_cert_replace_expiration(idc, new_end, d->key2); - certs_cell_cert_setlen_body(cert, newc->encoded_len); - memcpy(certs_cell_cert_getarray_body(cert), - newc->encoded, newc->encoded_len); + const uint8_t *encoded; + size_t encoded_len; + tor_x509_cert_get_der(newc, &encoded, &encoded_len); + certs_cell_cert_setlen_body(cert, encoded_len); + memcpy(certs_cell_cert_getarray_body(cert), encoded, encoded_len); REENCODE(); tor_x509_cert_free(newc); })
tor-commits@lists.torproject.org