[tor-commits] [tor/master] Make some x509 functions generic; remove some fields NSS doesn't need

nickm at torproject.org nickm at torproject.org
Wed Sep 5 00:47:14 UTC 2018


commit 5245a296c58eb8aba712e94a78d5bcaa2a2f25fb
Author: Nick Mathewson <nickm at 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);
   })





More information about the tor-commits mailing list