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]