Back to index

tor  0.2.3.19-rc
Typedefs | Functions
aes.h File Reference

Headers for aes.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct aes_cnt_cipher

Functions

aes_cnt_cipher_t * aes_new_cipher (const char *key, const char *iv)
 Return a newly allocated counter-mode AES128 cipher implementation, using the 128-bit key key and the 128-bit IV iv.
void aes_cipher_free (aes_cnt_cipher_t *cipher)
 Release storage held by cipher
void aes_crypt (aes_cnt_cipher_t *cipher, const char *input, size_t len, char *output)
 Encrypt len bytes from input, storing the result in output.
void aes_crypt_inplace (aes_cnt_cipher_t *cipher, char *data, size_t len)
 Encrypt len bytes from input, storing the results in place.
int evaluate_evp_for_aes (int force_value)
 Check whether we should use the EVP interface for AES.
int evaluate_ctr_for_aes (void)
 Test the OpenSSL counter mode implementation to see whether it has the counter-mode bug from OpenSSL 1.0.0.

Detailed Description

Headers for aes.c.

Definition in file aes.h.


Typedef Documentation

typedef struct aes_cnt_cipher

Definition at line 17 of file aes.h.


Function Documentation

void aes_cipher_free ( aes_cnt_cipher_t *  cipher)

Release storage held by cipher

Definition at line 369 of file aes.c.

{
  if (!cipher)
    return;
  if (cipher->using_evp) {
    EVP_CIPHER_CTX_cleanup(&cipher->key.evp);
  }
  memset(cipher, 0, sizeof(aes_cnt_cipher_t));
  tor_free(cipher);
}

Here is the caller graph for this function:

void aes_crypt ( aes_cnt_cipher_t *  cipher,
const char *  input,
size_t  len,
char *  output 
)

Encrypt len bytes from input, storing the result in output.

Uses the key in cipher, and advances the counter by len bytes as it encrypts.

Definition at line 405 of file aes.c.

{
#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
#endif
  {
    int c = cipher->pos;
    if (PREDICT_UNLIKELY(!len)) return;

    while (1) {
      do {
        if (len-- == 0) { cipher->pos = c; return; }
        *(output++) = *(input++) ^ cipher->buf[c];
      } while (++c != 16);
      cipher->pos = c = 0;
      if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 0))) {
        if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 1))) {
          if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 2))) {
            ++COUNTER(cipher, 3);
            UPDATE_CTR_BUF(cipher, 3);
          }
          UPDATE_CTR_BUF(cipher, 2);
        }
        UPDATE_CTR_BUF(cipher, 1);
      }
      UPDATE_CTR_BUF(cipher, 0);
      _aes_fill_buf(cipher);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void aes_crypt_inplace ( aes_cnt_cipher_t *  cipher,
char *  data,
size_t  len 
)

Encrypt len bytes from input, storing the results in place.

Uses the key in cipher, and advances the counter by len bytes as it encrypts.

Definition at line 466 of file aes.c.

{
#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;

    while (1) {
      do {
        if (len-- == 0) { cipher->pos = c; return; }
        *(data++) ^= cipher->buf[c];
      } while (++c != 16);
      cipher->pos = c = 0;
      if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 0))) {
        if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 1))) {
          if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 2))) {
            ++COUNTER(cipher, 3);
            UPDATE_CTR_BUF(cipher, 3);
          }
          UPDATE_CTR_BUF(cipher, 2);
        }
        UPDATE_CTR_BUF(cipher, 1);
      }
      UPDATE_CTR_BUF(cipher, 0);
      _aes_fill_buf(cipher);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

aes_cnt_cipher_t* aes_new_cipher ( const char *  key,
const char *  iv 
)

Return a newly allocated counter-mode AES128 cipher implementation, using the 128-bit key key and the 128-bit IV iv.

Definition at line 315 of file aes.c.

{
  aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t));

  aes_set_key(result, key, 128);
  aes_set_iv(result, iv);

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int evaluate_ctr_for_aes ( void  )

Test the OpenSSL counter mode implementation to see whether it has the counter-mode bug from OpenSSL 1.0.0.

If the implementation works, then we will use it for future encryption/decryption operations.

We can't just look at the OpenSSL version, since some distributions update their OpenSSL packages without changing the version number.

Definition at line 235 of file aes.c.

{
#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;
}

Here is the caller graph for this function:

int evaluate_evp_for_aes ( int  force_val)

Check whether we should use the EVP interface for AES.

If force_val is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP if there is an engine enabled for aes-ecb.

Definition at line 201 of file aes.c.

{
  ENGINE *e;

  if (force_val >= 0) {
    should_use_EVP = force_val;
    return 0;
  }
#ifdef DISABLE_ENGINES
  should_use_EVP = 0;
#else
  e = ENGINE_get_cipher_engine(NID_aes_128_ecb);

  if (e) {
    log_notice(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.",
               ENGINE_get_name(e));
    should_use_EVP = 1;
  } else {
    log_notice(LD_CRYPTO, "No AES engine found; using AES_* functions.");
    should_use_EVP = 0;
  }
#endif

  return 0;
}

Here is the caller graph for this function: