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]