ソースを参照

Merge branch 'openssl_compat'

Nick Mathewson 8 年 前
コミット
a5f7a8b047

+ 4 - 0
changes/bug17921_bug17984

@@ -0,0 +1,4 @@
+  o Minor features (compilation):
+    - Tor builds successfully with the unreleased OpenSSL 1.1 alpha
+      releases, and with the latest LibreSSL. Closes tickets 17921 and
+      17984.

+ 15 - 16
src/common/aes.c

@@ -81,47 +81,46 @@
 
 #ifdef USE_EVP_AES_CTR
 
-struct aes_cnt_cipher {
-  EVP_CIPHER_CTX evp;
-};
+/* We don't actually define the struct here. */
 
 aes_cnt_cipher_t *
 aes_new_cipher(const char *key, const char *iv)
 {
-  aes_cnt_cipher_t *cipher;
-  cipher = tor_malloc_zero(sizeof(aes_cnt_cipher_t));
-  EVP_EncryptInit(&cipher->evp, EVP_aes_128_ctr(),
+  EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
+  EVP_EncryptInit(cipher, EVP_aes_128_ctr(),
                   (const unsigned char*)key, (const unsigned char *)iv);
-  return cipher;
+  return (aes_cnt_cipher_t *) cipher;
 }
 void
-aes_cipher_free(aes_cnt_cipher_t *cipher)
+aes_cipher_free(aes_cnt_cipher_t *cipher_)
 {
-  if (!cipher)
+  if (!cipher_)
     return;
-  EVP_CIPHER_CTX_cleanup(&cipher->evp);
-  memwipe(cipher, 0, sizeof(aes_cnt_cipher_t));
-  tor_free(cipher);
+  EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
+  EVP_CIPHER_CTX_cleanup(cipher);
+  EVP_CIPHER_CTX_free(cipher);
 }
 void
-aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
+aes_crypt(aes_cnt_cipher_t *cipher_, const char *input, size_t len,
           char *output)
 {
   int outl;
+  EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
 
   tor_assert(len < INT_MAX);
 
-  EVP_EncryptUpdate(&cipher->evp, (unsigned char*)output,
+  EVP_EncryptUpdate(cipher, (unsigned char*)output,
                     &outl, (const unsigned char *)input, (int)len);
 }
 void
-aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
+aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len)
 {
   int outl;
+  EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
 
   tor_assert(len < INT_MAX);
 
-  EVP_EncryptUpdate(&cipher->evp, (unsigned char*)data,
+  EVP_EncryptUpdate(cipher, (unsigned char*)data,
                     &outl, (unsigned char*)data, (int)len);
 }
 int

+ 0 - 1
src/common/aes.h

@@ -13,7 +13,6 @@
  * \brief Headers for aes.c
  */
 
-struct aes_cnt_cipher;
 typedef struct aes_cnt_cipher aes_cnt_cipher_t;
 
 aes_cnt_cipher_t* aes_new_cipher(const char *key, const char *iv);

+ 2 - 0
src/common/compat_openssl.h

@@ -35,9 +35,11 @@
   (((st) == SSL3_ST_SW_SRVR_HELLO_A) ||    \
    ((st) == SSL3_ST_SW_SRVR_HELLO_B))
 #define OSSL_HANDSHAKE_STATE int
+#define CONST_IF_OPENSSL_1_1_API
 #else
 #define STATE_IS_SW_SERVER_HELLO(st) \
   ((st) == TLS_ST_SW_SRVR_HELLO)
+#define CONST_IF_OPENSSL_1_1_API const
 #endif
 
 #endif

+ 4 - 0
src/common/crypto.c

@@ -373,8 +373,12 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
          used by Tor and the set of algorithms available in the engine */
       log_engine("RSA", ENGINE_get_default_RSA());
       log_engine("DH", ENGINE_get_default_DH());
+#ifdef OPENSSL_1_1_API
+      log_engine("EC", ENGINE_get_default_EC());
+#else
       log_engine("ECDH", ENGINE_get_default_ECDH());
       log_engine("ECDSA", ENGINE_get_default_ECDSA());
+#endif
       log_engine("RAND", ENGINE_get_default_RAND());
       log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
       log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));

+ 12 - 6
src/common/tortls.c

@@ -911,7 +911,7 @@ tor_tls_cert_is_valid(int severity,
   } else if (cert_key) {
     int min_bits = 1024;
 #ifdef EVP_PKEY_EC
-    if (EVP_PKEY_type(cert_key->type) == EVP_PKEY_EC)
+    if (EVP_PKEY_base_id(cert_key) == EVP_PKEY_EC)
       min_bits = 128;
 #endif
     if (EVP_PKEY_bits(cert_key) >= min_bits)
@@ -1338,7 +1338,7 @@ find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher)
     return c != NULL;
   }
 # endif
-# if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
+# ifndef OPENSSL_1_1_API
   if (m && m->get_cipher && m->num_ciphers) {
     /* It would seem that some of the "let's-clean-up-openssl" forks have
      * removed the get_cipher_by_char function.  Okay, so now you get a
@@ -1414,7 +1414,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl,
   /* Now we need to see if there are any ciphers whose presence means we're
    * dealing with an updated Tor. */
   for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
-    SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
+    const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
     const char *ciphername = SSL_CIPHER_get_name(cipher);
     if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) &&
         strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) &&
@@ -1431,7 +1431,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl,
   {
     const uint16_t *v2_cipher = v2_cipher_list;
     for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
-      SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
+      const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
       uint16_t id = SSL_CIPHER_get_id(cipher) & 0xffff;
       if (id == 0x00ff) /* extended renegotiation indicator. */
         continue;
@@ -1453,7 +1453,7 @@ tor_tls_classify_client_ciphers(const SSL *ssl,
     smartlist_t *elts = smartlist_new();
     char *s;
     for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) {
-      SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
+      const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i);
       const char *ciphername = SSL_CIPHER_get_name(cipher);
       smartlist_add(elts, (char*)ciphername);
     }
@@ -1562,7 +1562,8 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
 STATIC int
 tor_tls_session_secret_cb(SSL *ssl, void *secret, int *secret_len,
                           STACK_OF(SSL_CIPHER) *peer_ciphers,
-                          SSL_CIPHER **cipher, void *arg)
+                          CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
+                          void *arg)
 {
   (void) secret;
   (void) secret_len;
@@ -1733,8 +1734,13 @@ tor_tls_block_renegotiation(tor_tls_t *tls)
 void
 tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
 {
+#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && \
+  SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION != 0
   long options = SSL_get_options(tls->ssl);
   tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+#else
+  (void) tls;
+#endif
 }
 
 /** Return whether this tls initiated the connect (client) or

+ 4 - 3
src/common/tortls.h

@@ -143,9 +143,10 @@ STATIC size_t SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out,
 STATIC void tor_tls_debug_state_callback(const SSL *ssl, int type, int val);
 STATIC void tor_tls_server_info_callback(const SSL *ssl, int type, int val);
 STATIC int tor_tls_session_secret_cb(SSL *ssl, void *secret,
-                                     int *secret_len,
-                                     STACK_OF(SSL_CIPHER) *peer_ciphers,
-                                     SSL_CIPHER **cipher, void *arg);
+                            int *secret_len,
+                            STACK_OF(SSL_CIPHER) *peer_ciphers,
+                            CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher,
+                            void *arg);
 STATIC int find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m,
                              uint16_t cipher);
 MOCK_DECL(STATIC X509*, tor_tls_create_certificate,(crypto_pk_t *rsa,

+ 16 - 4
src/test/test_crypto.c

@@ -147,8 +147,14 @@ test_crypto_rng_engine(void *arg)
 
   /* We should correct the method if it's a dummy. */
   RAND_set_rand_method(&dummy_method);
+#ifdef LIBRESSL_VERSION_NUMBER
+  /* On libressl, you can't override the RNG. */
+  tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
+  tt_int_op(0, ==, crypto_force_rand_ssleay());
+#else
   tt_assert(RAND_get_rand_method() == &dummy_method);
   tt_int_op(1, ==, crypto_force_rand_ssleay());
+#endif
   tt_assert(RAND_get_rand_method() == RAND_OpenSSL());
 
   /* Make sure we aren't calling dummy_method */
@@ -1108,6 +1114,11 @@ test_crypto_digests(void *arg)
   crypto_pk_free(k);
 }
 
+#ifndef OPENSSL_1_1_API
+#define EVP_ENCODE_CTX_new() tor_malloc_zero(sizeof(EVP_ENCODE_CTX))
+#define EVP_ENCODE_CTX_free(ctx) tor_free(ctx)
+#endif
+
 /** Encode src into dest with OpenSSL's EVP Encode interface, returning the
  * length of the encoded data in bytes.
  */
@@ -1115,12 +1126,13 @@ static int
 base64_encode_evp(char *dest, char *src, size_t srclen)
 {
   const unsigned char *s = (unsigned char*)src;
-  EVP_ENCODE_CTX ctx;
+  EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
   int len, ret;
 
-  EVP_EncodeInit(&ctx);
-  EVP_EncodeUpdate(&ctx, (unsigned char *)dest, &len, s, (int)srclen);
-  EVP_EncodeFinal(&ctx, (unsigned char *)(dest + len), &ret);
+  EVP_EncodeInit(ctx);
+  EVP_EncodeUpdate(ctx, (unsigned char *)dest, &len, s, (int)srclen);
+  EVP_EncodeFinal(ctx, (unsigned char *)(dest + len), &ret);
+  EVP_ENCODE_CTX_free(ctx);
   return ret+ len;
 }
 

+ 23 - 10
src/test/test_tortls.c

@@ -1347,11 +1347,10 @@ test_tortls_get_buffer_sizes(void *ignored)
   tls->ssl->s3->wbuf.offset = 0;
   tls->ssl->s3->wbuf.left = 43;
 
+  ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b);
 #if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
-  ret = tor_tls_get_buffer_sizes(NULL, NULL, NULL, NULL, NULL);
   tt_int_op(ret, OP_EQ, -1);
 #else
-  ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b);
   tt_int_op(ret, OP_EQ, 0);
   tt_int_op(rbuf_c, OP_EQ, 0);
   tt_int_op(wbuf_c, OP_EQ, 0);
@@ -1601,12 +1600,19 @@ test_tortls_block_renegotiation(void *ignored)
   tls = tor_malloc_zero(sizeof(tor_tls_t));
   tls->ssl = tor_malloc_zero(sizeof(SSL));
   tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE));
-  tls->ssl->s3->flags = 0x0010;
+#ifndef SUPPORT_UNSAFE_RENEGOTIATION_FLAG
+#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0
+#endif
 
-  tor_tls_block_renegotiation(tls);
+  tls->ssl->s3->flags = SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
 
-  tt_assert(!(SSL_get_options(tls->ssl) & 0x0010));
+  tor_tls_block_renegotiation(tls);
 
+#ifndef OPENSSL_1_1_API
+  tt_assert(!(tls->ssl->s3->flags &
+              SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+#endif
+  
  done:
   tor_free(tls->ssl->s3);
   tor_free(tls->ssl);
@@ -1623,7 +1629,9 @@ test_tortls_unblock_renegotiation(void *ignored)
   tls->ssl = tor_malloc_zero(sizeof(SSL));
   tor_tls_unblock_renegotiation(tls);
 
-  tt_assert(SSL_get_options(tls->ssl) & 0x00040000L);
+  tt_uint_op(SSL_get_options(tls->ssl) &
+             SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, OP_EQ,
+             SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
 
  done:
   tor_free(tls->ssl);
@@ -1907,6 +1915,7 @@ fixed_ssl_shutdown(SSL *s)
   return fixed_ssl_shutdown_result;
 }
 
+#ifndef LIBRESSL_VERSION_NUMBER
 static int fixed_ssl_state_to_set;
 static tor_tls_t *fixed_tls;
 
@@ -1924,6 +1933,7 @@ setting_version_and_state_ssl_shutdown(SSL *s)
   s->version = SSL2_VERSION;
   return fixed_ssl_shutdown_result;
 }
+#endif
 
 static int
 dummy_handshake_func(SSL *s)
@@ -1957,6 +1967,7 @@ test_tortls_shutdown(void *ignored)
   ret = tor_tls_shutdown(tls);
   tt_int_op(ret, OP_EQ, -9);
 
+#ifndef LIBRESSL_VERSION_NUMBER
   tls->ssl->handshake_func = dummy_handshake_func;
 
   fixed_ssl_read_result_index = 0;
@@ -2018,6 +2029,7 @@ test_tortls_shutdown(void *ignored)
   method->ssl_shutdown = setting_version_and_state_ssl_shutdown;
   ret = tor_tls_shutdown(tls);
   tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+#endif
 
  done:
   teardown_capture_of_logs(previous_log);
@@ -2080,6 +2092,7 @@ test_tortls_read(void *ignored)
   ret = tor_tls_read(tls, buf, 10);
   tt_int_op(negotiated_callback_called, OP_EQ, 1);
 
+#ifndef LIBRESSL_VERSION_NUMBER
   fixed_ssl_read_result_index = 0;
   fixed_ssl_read_result[0] = 0;
   tls->ssl->version = SSL2_VERSION;
@@ -2087,7 +2100,7 @@ test_tortls_read(void *ignored)
   ret = tor_tls_read(tls, buf, 10);
   tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE);
   tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED);
-
+#endif
   // TODO: fill up
 
  done:
@@ -2594,14 +2607,14 @@ test_tortls_create_certificate(void *ignored)
   tt_assert(!ret);
 
   fixed_crypto_pk_get_evp_pkey_result_index = 0;
-  fixed_crypto_pk_get_evp_pkey_result[0] = tor_malloc_zero(sizeof(EVP_PKEY));
+  fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new();
   fixed_crypto_pk_get_evp_pkey_result[1] = NULL;
   ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
   tt_assert(!ret);
 
   fixed_crypto_pk_get_evp_pkey_result_index = 0;
-  fixed_crypto_pk_get_evp_pkey_result[0] = tor_malloc_zero(sizeof(EVP_PKEY));
-  fixed_crypto_pk_get_evp_pkey_result[1] = tor_malloc_zero(sizeof(EVP_PKEY));
+  fixed_crypto_pk_get_evp_pkey_result[0] = EVP_PKEY_new();
+  fixed_crypto_pk_get_evp_pkey_result[1] = EVP_PKEY_new();
   ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
   tt_assert(!ret);