|  | @@ -18,10 +18,10 @@
 | 
	
		
			
				|  |  |  #include <openssl/evp.h>
 | 
	
		
			
				|  |  |  #include <openssl/engine.h>
 | 
	
		
			
				|  |  |  #include "crypto.h"
 | 
	
		
			
				|  |  | -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V(1,0,0,'a')
 | 
	
		
			
				|  |  | +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)
 | 
	
		
			
				|  |  |  /* See comments about which counter mode implementation to use below. */
 | 
	
		
			
				|  |  |  #include <openssl/modes.h>
 | 
	
		
			
				|  |  | -#define USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +#define CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  #include "compat.h"
 | 
	
		
			
				|  |  |  #include "aes.h"
 | 
	
	
		
			
				|  | @@ -62,7 +62,7 @@ struct aes_cnt_cipher {
 | 
	
		
			
				|  |  |      AES_KEY aes;
 | 
	
		
			
				|  |  |    } key;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#if !defined(WORDS_BIGENDIAN) && !defined(USE_OPENSSL_CTR)
 | 
	
		
			
				|  |  | +#if !defined(WORDS_BIGENDIAN)
 | 
	
		
			
				|  |  |  #define USING_COUNTER_VARS
 | 
	
		
			
				|  |  |    /** These four values, together, implement a 128-bit counter, with
 | 
	
		
			
				|  |  |     * counter0 as the low-order word and counter3 as the high-order word. */
 | 
	
	
		
			
				|  | @@ -84,11 +84,7 @@ struct aes_cnt_cipher {
 | 
	
		
			
				|  |  |    /** The encrypted value of ctr_buf. */
 | 
	
		
			
				|  |  |    uint8_t buf[16];
 | 
	
		
			
				|  |  |    /** Our current stream position within buf. */
 | 
	
		
			
				|  |  | -#ifdef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  |    unsigned int pos;
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -  uint8_t pos;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /** True iff we're using the evp implementation of this cipher. */
 | 
	
		
			
				|  |  |    uint8_t using_evp;
 | 
	
	
		
			
				|  | @@ -98,6 +94,11 @@ struct aes_cnt_cipher {
 | 
	
		
			
				|  |  |   * we're testing it or because we have hardware acceleration configured */
 | 
	
		
			
				|  |  |  static int should_use_EVP = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +/**DOCDOC*/
 | 
	
		
			
				|  |  | +static int should_use_openssl_CTR = 0;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** Check whether we should use the EVP interface for AES. If <b>force_val</b>
 | 
	
		
			
				|  |  |   * is nonnegative, we use use EVP iff it is true.  Otherwise, we use EVP
 | 
	
		
			
				|  |  |   * if there is an engine enabled for aes-ecb. */
 | 
	
	
		
			
				|  | @@ -128,7 +129,50 @@ evaluate_evp_for_aes(int force_val)
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifndef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +/**DOCDOC*/
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +evaluate_ctr_for_aes(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +  /* Result of encrypting an all-zero block with an all-zero 128-bit AES key.
 | 
	
		
			
				|  |  | +   * This should be the same as encrypting an all-zero block with an all-zero
 | 
	
		
			
				|  |  | +   * 128-bit AES key in counter mode, starting at position 0 of the stream.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  static const unsigned char encrypt_zero[] =
 | 
	
		
			
				|  |  | +    "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e";
 | 
	
		
			
				|  |  | +  unsigned char zero[16];
 | 
	
		
			
				|  |  | +  unsigned char output[16];
 | 
	
		
			
				|  |  | +  unsigned char ivec[16];
 | 
	
		
			
				|  |  | +  unsigned char ivec_tmp[16];
 | 
	
		
			
				|  |  | +  unsigned int pos, i;
 | 
	
		
			
				|  |  | +  AES_KEY key;
 | 
	
		
			
				|  |  | +  memset(zero, 0, sizeof(zero));
 | 
	
		
			
				|  |  | +  memset(ivec, 0, sizeof(ivec));
 | 
	
		
			
				|  |  | +  AES_set_encrypt_key(zero, 128, &key);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  pos = 0;
 | 
	
		
			
				|  |  | +  /* Encrypting a block one byte at a time should make the error manifest
 | 
	
		
			
				|  |  | +   * itself for known bogus openssl versions. */
 | 
	
		
			
				|  |  | +  for (i=0; i<16; ++i)
 | 
	
		
			
				|  |  | +    AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (memcmp(output, encrypt_zero, 16)) {
 | 
	
		
			
				|  |  | +    /* Counter mode is buggy */
 | 
	
		
			
				|  |  | +    log_notice(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; "
 | 
	
		
			
				|  |  | +               "not using it.");
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    /* Counter mode is okay */
 | 
	
		
			
				|  |  | +    log_notice(LD_CRYPTO, "This OpenSSL has a good implementation of counter "
 | 
	
		
			
				|  |  | +               "mode; using it.");
 | 
	
		
			
				|  |  | +    should_use_openssl_CTR = 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +  log_notice(LD_CRYPTO, "This version of OpenSSL has a slow implementation of "
 | 
	
		
			
				|  |  | +             "counter mode; not using it.");
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if !defined(USING_COUNTER_VARS)
 | 
	
		
			
				|  |  |  #define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)])
 | 
	
		
			
				|  |  |  #else
 | 
	
	
		
			
				|  | @@ -157,7 +201,6 @@ _aes_fill_buf(aes_cnt_cipher_t *cipher)
 | 
	
		
			
				|  |  |      AES_encrypt(cipher->ctr_buf.buf, cipher->buf, &cipher->key.aes);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Return a newly allocated counter-mode AES128 cipher implementation.
 | 
	
	
		
			
				|  | @@ -203,11 +246,12 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    cipher->pos = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifdef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | -  memset(cipher->buf, 0, sizeof(cipher->buf));
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -  _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +  if (should_use_openssl_CTR)
 | 
	
		
			
				|  |  | +    memset(cipher->buf, 0, sizeof(cipher->buf));
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | +    _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Release storage held by <b>cipher</b>
 | 
	
	
		
			
				|  | @@ -232,7 +276,7 @@ aes_free_cipher(aes_cnt_cipher_t *cipher)
 | 
	
		
			
				|  |  |  #define UPDATE_CTR_BUF(c, n)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifdef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  |  /* Helper function to use EVP with openssl's counter-mode wrapper. */
 | 
	
		
			
				|  |  |  static void evp_block128_fn(const uint8_t in[16],
 | 
	
		
			
				|  |  |                              uint8_t out[16],
 | 
	
	
		
			
				|  | @@ -252,29 +296,34 @@ void
 | 
	
		
			
				|  |  |  aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
 | 
	
		
			
				|  |  |            char *output)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -#ifdef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | -  if (cipher->using_evp) {
 | 
	
		
			
				|  |  | -    /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h.  If
 | 
	
		
			
				|  |  | -     * it weren't disabled, it might be better just to use that.
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | -    CRYPTO_ctr128_encrypt((const unsigned char *)input,
 | 
	
		
			
				|  |  | -                          (unsigned char *)output,
 | 
	
		
			
				|  |  | -                          len,
 | 
	
		
			
				|  |  | -                          &cipher->key.evp,
 | 
	
		
			
				|  |  | -                          cipher->ctr_buf.buf,
 | 
	
		
			
				|  |  | -                          cipher->buf,
 | 
	
		
			
				|  |  | -                          &cipher->pos,
 | 
	
		
			
				|  |  | -                          evp_block128_fn);
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    AES_ctr128_encrypt((const unsigned char *)input,
 | 
	
		
			
				|  |  | -                       (unsigned char *)output,
 | 
	
		
			
				|  |  | -                       len,
 | 
	
		
			
				|  |  | -                       &cipher->key.aes,
 | 
	
		
			
				|  |  | -                       cipher->ctr_buf.buf,
 | 
	
		
			
				|  |  | -                       cipher->buf,
 | 
	
		
			
				|  |  | -                       &cipher->pos);
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +  if (should_use_openssl_CTR) {
 | 
	
		
			
				|  |  | +    if (cipher->using_evp) {
 | 
	
		
			
				|  |  | +      /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h.  If
 | 
	
		
			
				|  |  | +       * it weren't disabled, it might be better just to use that.
 | 
	
		
			
				|  |  | +       */
 | 
	
		
			
				|  |  | +      CRYPTO_ctr128_encrypt((const unsigned char *)input,
 | 
	
		
			
				|  |  | +                            (unsigned char *)output,
 | 
	
		
			
				|  |  | +                            len,
 | 
	
		
			
				|  |  | +                            &cipher->key.evp,
 | 
	
		
			
				|  |  | +                            cipher->ctr_buf.buf,
 | 
	
		
			
				|  |  | +                            cipher->buf,
 | 
	
		
			
				|  |  | +                            &cipher->pos,
 | 
	
		
			
				|  |  | +                            evp_block128_fn);
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      AES_ctr128_encrypt((const unsigned char *)input,
 | 
	
		
			
				|  |  | +                         (unsigned char *)output,
 | 
	
		
			
				|  |  | +                         len,
 | 
	
		
			
				|  |  | +                         &cipher->key.aes,
 | 
	
		
			
				|  |  | +                         cipher->ctr_buf.buf,
 | 
	
		
			
				|  |  | +                         cipher->buf,
 | 
	
		
			
				|  |  | +                         &cipher->pos);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  |    int c = cipher->pos;
 | 
	
		
			
				|  |  |    if (PREDICT_UNLIKELY(!len)) return;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -297,7 +346,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
 | 
	
		
			
				|  |  |      UPDATE_CTR_BUF(cipher, 0);
 | 
	
		
			
				|  |  |      _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place.
 | 
	
	
		
			
				|  | @@ -307,9 +356,14 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  |  aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -#ifdef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | -  aes_crypt(cipher, data, len, data);
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +  if (should_use_openssl_CTR) {
 | 
	
		
			
				|  |  | +    aes_crypt(cipher, data, len, data);
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  |    int c = cipher->pos;
 | 
	
		
			
				|  |  |    if (PREDICT_UNLIKELY(!len)) return;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -332,7 +386,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
 | 
	
		
			
				|  |  |      UPDATE_CTR_BUF(cipher, 0);
 | 
	
		
			
				|  |  |      _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
 | 
	
	
		
			
				|  | @@ -349,8 +403,9 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv)
 | 
	
		
			
				|  |  |    cipher->pos = 0;
 | 
	
		
			
				|  |  |    memcpy(cipher->ctr_buf.buf, iv, 16);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifndef USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | -  _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  | +#ifdef CAN_USE_OPENSSL_CTR
 | 
	
		
			
				|  |  | +  if (!should_use_openssl_CTR)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | +    _aes_fill_buf(cipher);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |