The following program succeeds on 0.9.6 but
fails on 0.9.7.  It tests the feature of
calling EVP_CipherInit once to build
a key schedule, then cycling through
calls to EVP_CipherInit, EVP_CipherUpdate,
and EVP_CipherFinal to encrypt/decrypt
multiple messages with the same key.

Is this a bug or a design change to
the EVP layer?

The ability to
recycle an EVP_CIPHER_CTX is important
to avoid having to reconstruct a key
schedule for every message, when
the key stays the same and only
the IV changes.

Is there a better way to do this that
works on both 0.9.6 and 0.9.7?

Thanks,
James Yonan

/*
 * This program tests EVP_CIPHER_CTX reuse where
 * EVP_CipherInit is called on a ctx that has
 * had EVP_CipherFinal called on it at least
 * once.
 */

#include <stdio.h>
#include <openssl/evp.h>

#define ASSERT(x) \
  do { \
    const int stat = (x); \
    if (!stat) { \
      printf("ERROR: '%s' returned %d\n", #x, stat); \
      exit (1); \
    } \
  } while (0)

/* print hex string */
static void
print_hex (unsigned const char *data, int len)
{
  int i;
  for (i = 0; i < len; ++i)
    printf("%02x", (int)data[i]);
}

/* encrypt from plaintext -> ciphertext */
static int
cipher_test (unsigned char *dest, int *dest_len,
             unsigned char *src,
             int src_len, const EVP_CIPHER *cipher,
             unsigned char *key, int key_len,
             int enc)
{
  EVP_CIPHER_CTX ctx;
  unsigned char iv[EVP_MAX_IV_LENGTH];
  int i, outlen;

  /* init cipher */
  EVP_CIPHER_CTX_init (&ctx);

  /* init key schedule */
  ASSERT (EVP_CipherInit (&ctx, cipher, NULL, NULL, enc));
  ASSERT (EVP_CIPHER_CTX_set_key_length (&ctx, key_len));
  ASSERT (EVP_CipherInit (&ctx, NULL, key, NULL, enc));

  /*
   * Encrypt/decrypt two messages using same key schedule.
   * 0.9.6 does fine here, 0.9.7 fails on 2nd pass
   * at EVP_CipherInit.
   */
  for (i = 1; i <= 2; ++i)
    {
      printf ("Loop i=%d\n", i);
      memset (iv, 0, sizeof (iv));
      ASSERT (EVP_CipherInit (&ctx, NULL, NULL, iv, enc));
      *dest_len = 0;
      ASSERT (EVP_CipherUpdate (&ctx, dest, &outlen,
                                src, src_len));
      *dest_len += outlen;
      ASSERT (EVP_CipherFinal (&ctx, dest + outlen, &outlen));
      *dest_len += outlen;
    }

  /* show result */
  printf ("%s\n From: ", (enc ? "ENCRYPT" : "DECRYPT"));
  print_hex (src, src_len);
  printf ("\n   To: ");
  print_hex (dest, *dest_len);
  printf("\n Residual IV: ");

  /* Is the right way to get the residual IV? */
  print_hex (ctx.iv, EVP_CIPHER_CTX_iv_length (&ctx));

  printf("\n");

  /* cleanup */
  EVP_CIPHER_CTX_cleanup (&ctx);
}

/* which cipher to use */
#define CIPHER  EVP_idea_cbc()

int main(int argc, char* argv[])
{
  static unsigned char key[] = {
    0x2a, 0x18, 0x7b, 0xf3, 0x64, 0x1e, 0xb4, 0xcb,
    0x07, 0xed, 0x2d, 0x0a, 0x98, 0x1f, 0xc7, 0x48
  };

  static unsigned char source[] = "Hello World!";

  unsigned char plaintext[1024];
  int plaintext_len = 0;

  unsigned char ciphertext[1024];
  int ciphertext_len = 0;

  cipher_test (ciphertext, &ciphertext_len, source,
               sizeof(source), CIPHER, key, sizeof (key), 1);

  cipher_test (plaintext, &plaintext_len, ciphertext,
               ciphertext_len, CIPHER, key, sizeof (key), 0);

  if (!strcmp (source, plaintext))
    printf("TEST SUCCEEDED\n");
  else
    printf("TEST FAILED\n");
}


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to