Hello,
I've updated the ciphertext stealing code a bit, and below is a new
patch against the latest CVS HEAD. Note that I have sent another TSU
notification for this patch in case this is considered different from
the previous patch (which was against 0.9.8d).
Please let me know if you have any suggestions or discover any problems. Thanks!
An-Cheng
Index: crypto/evp/evp.h
===================================================================
RCS file: /home/pach/prog/openssl/cvs/openssl/crypto/evp/evp.h,v
retrieving revision 1.170
diff -u -r1.170 evp.h
--- crypto/evp/evp.h 8 Feb 2007 19:07:43 -0000 1.170
+++ crypto/evp/evp.h 15 Mar 2007 06:13:20 -0000
@@ -328,6 +328,8 @@
#define EVP_CIPH_NO_PADDING 0x100
/* cipher handles random key generation */
#define EVP_CIPH_RAND_KEY 0x200
+/* Use ciphertext stealing instead of padding */
+#define EVP_CIPH_CIPHERTEXT_STEALING 0x400
/* ctrl() values */
@@ -514,7 +516,10 @@
const unsigned char *key, const unsigned char *iv);
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
+int EVP_EncryptUpdate_cts(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+int EVP_EncryptFinal_cts(EVP_CIPHER_CTX *ctx, unsigned char *out, int
*outl);
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
@@ -523,7 +528,10 @@
const unsigned char *key, const unsigned char *iv);
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
+int EVP_DecryptUpdate_cts(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_DecryptFinal_cts(EVP_CIPHER_CTX *ctx, unsigned char *outm, int
*outl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int
*outl);
int EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
@@ -582,6 +590,7 @@
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
+int EVP_CIPHER_CTX_set_cts(EVP_CIPHER_CTX *c, int cts);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
@@ -1143,9 +1152,12 @@
#define EVP_F_ECKEY_PKEY2PKCS8 132
#define EVP_F_EVP_CIPHERINIT_EX 123
#define EVP_F_EVP_CIPHER_CTX_CTRL 124
+#define EVP_F_EVP_CIPHER_CTX_SET_CTS 161
#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122
+#define EVP_F_EVP_DECRYPTFINAL_CTS 162
#define EVP_F_EVP_DECRYPTFINAL_EX 101
#define EVP_F_EVP_DIGESTINIT_EX 128
+#define EVP_F_EVP_ENCRYPTFINAL_CTS 163
#define EVP_F_EVP_ENCRYPTFINAL_EX 127
#define EVP_F_EVP_MD_CTX_COPY_EX 110
#define EVP_F_EVP_OPENINIT 102
@@ -1220,6 +1232,8 @@
#define EVP_R_EXPECTING_A_DSA_KEY 129
#define EVP_R_EXPECTING_A_ECDSA_KEY 141
#define EVP_R_EXPECTING_A_EC_KEY 142
+#define EVP_R_EXPECTING_PREVIOUS_CIPHERTEXT 158
+#define EVP_R_EXPECTING_PREVIOUS_PLAINTEXT 159
#define EVP_R_INITIALIZATION_ERROR 134
#define EVP_R_INPUT_NOT_INITIALIZED 111
#define EVP_R_INVALID_DIGEST 152
@@ -1249,6 +1263,7 @@
#define EVP_R_UNSUPPORTED_KEYLENGTH 123
#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124
#define EVP_R_UNSUPPORTED_KEY_SIZE 108
+#define EVP_R_UNSUPPORTED_MODE 160
#define EVP_R_UNSUPPORTED_PRF 125
#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118
#define EVP_R_UNSUPPORTED_SALT_TYPE 126
Index: crypto/evp/evp_enc.c
===================================================================
RCS file: /home/pach/prog/openssl/cvs/openssl/crypto/evp/evp_enc.c,v
retrieving revision 1.45
diff -u -r1.45 evp_enc.c
--- crypto/evp/evp_enc.c 21 Jan 2007 13:07:09 -0000 1.45
+++ crypto/evp/evp_enc.c 15 Mar 2007 06:05:13 -0000
@@ -274,12 +274,88 @@
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
}
+int
+EVP_EncryptUpdate_cts(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+ const unsigned char *in, int inl)
+{
+ int bl = ctx->cipher->block_size;
+ int leftover = 0;
+ OPENSSL_assert(bl <= (int)sizeof(ctx->buf));
+ *outl = 0;
+
+ if ((ctx->buf_len + inl) <= bl) {
+ /* new plaintext is no more than 1 block */
+ /* copy the in data into the buffer and return */
+ memcpy(&(ctx->buf[ctx->buf_len]), in, inl);
+ ctx->buf_len += inl;
+ *outl = 0;
+ return 1;
+ }
+
+ /* more than 1 block of new plaintext available */
+ /* encrypt the previous plaintext, if any */
+ if (ctx->final_used) {
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->final, bl))) {
+ return 0;
+ }
+ out += bl;
+ *outl += bl;
+ ctx->final_used = 0;
+ }
+
+ /* we already know ctx->buf_len + inl must be > bl */
+ memcpy(&(ctx->buf[ctx->buf_len]), in, (bl - ctx->buf_len));
+ in += (bl - ctx->buf_len);
+ inl -= (bl - ctx->buf_len);
+ ctx->buf_len = bl;
+
+ if (inl <= bl) {
+ memcpy(ctx->final, ctx->buf, bl);
+ ctx->final_used = 1;
+ memcpy(ctx->buf, in, inl);
+ ctx->buf_len = inl;
+ return 1;
+ } else {
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))) {
+ return 0;
+ }
+ out += bl;
+ *outl += bl;
+ ctx->buf_len = 0;
+
+ leftover = inl & ctx->block_mask;
+ if (leftover) {
+ inl -= (bl + leftover);
+ memcpy(ctx->buf, &(in[(inl + bl)]), leftover);
+ ctx->buf_len = leftover;
+ } else {
+ inl -= (2 * bl);
+ memcpy(ctx->buf, &(in[(inl + bl)]), bl);
+ ctx->buf_len = bl;
+ }
+ memcpy(ctx->final, &(in[inl]), bl);
+ ctx->final_used = 1;
+ if (!(ctx->cipher->do_cipher(ctx, out, in, inl))) {
+ return 0;
+ }
+ out += inl;
+ *outl += inl;
+ }
+
+ return 1;
+}
+
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
int i,j,bl;
OPENSSL_assert(inl > 0);
+ if (ctx->flags & EVP_CIPH_CIPHERTEXT_STEALING)
+ {
+ return EVP_EncryptUpdate_cts(ctx, out, outl, in, inl);
+ }
+
if(ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0)
{
if(ctx->cipher->do_cipher(ctx,out,in,inl))
@@ -339,11 +415,82 @@
return ret;
}
+int
+EVP_EncryptFinal_cts(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+ unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
+ int bl = ctx->cipher->block_size;
+ int leftover = 0;
+ *outl = 0;
+
+ if (!ctx->final_used) {
+ EVPerr(EVP_F_EVP_ENCRYPTFINAL_CTS, EVP_R_EXPECTING_PREVIOUS_CIPHERTEXT);
+ return 0;
+ }
+ if (ctx->buf_len == 0) {
+ EVPerr(EVP_F_EVP_ENCRYPTFINAL_CTS, EVP_R_EXPECTING_PREVIOUS_PLAINTEXT);
+ return 0;
+ }
+
+ /* handle leftover bytes */
+ leftover = ctx->buf_len;
+
+ switch (EVP_CIPHER_CTX_mode(ctx)) {
+ case EVP_CIPH_ECB_MODE: {
+ /* encrypt => C_{n} plus C' */
+ if (!(ctx->cipher->do_cipher(ctx, tmp, ctx->final, bl))) {
+ return 0;
+ }
+
+ /* P_n plus C' */
+ memcpy(&(ctx->buf[leftover]), &(tmp[leftover]), (bl - leftover));
+ /* encrypt => C_{n-1} */
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))) {
+ return 0;
+ }
+
+ memcpy((out + bl), tmp, leftover);
+ *outl += (bl + leftover);
+ return 1;
+ }
+ case EVP_CIPH_CBC_MODE: {
+ /* encrypt => C_{n} plus C' */
+ if (!(ctx->cipher->do_cipher(ctx, tmp, ctx->final, bl))) {
+ return 0;
+ }
+
+ /* P_n plus 0s */
+ memset(&(ctx->buf[leftover]), 0, (bl - leftover));
+
+ /* note that in cbc encryption, plaintext will be xor'ed with the previous
+ * ciphertext, which is what we want.
+ */
+ /* encrypt => C_{n-1} */
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))) {
+ return 0;
+ }
+
+ memcpy((out + bl), tmp, leftover);
+ *outl += (bl + leftover);
+ return 1;
+ }
+ default:
+ EVPerr(EVP_F_EVP_ENCRYPTFINAL_CTS, EVP_R_UNSUPPORTED_MODE);
+ return 0;
+ }
+ return 0;
+}
+
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int n,ret;
unsigned int i, b, bl;
+ if (ctx->flags & EVP_CIPH_CIPHERTEXT_STEALING)
+ {
+ return EVP_EncryptFinal_cts(ctx, out, outl);
+ }
+
b=ctx->cipher->block_size;
OPENSSL_assert(b <= sizeof ctx->buf);
if (b == 1)
@@ -375,12 +522,24 @@
return ret;
}
+int
+EVP_DecryptUpdate_cts(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+ const unsigned char *in, int inl)
+{
+ return EVP_EncryptUpdate_cts(ctx, out, outl, in, inl);
+}
+
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
int fix_len;
unsigned int b;
+ if (ctx->flags & EVP_CIPH_CIPHERTEXT_STEALING)
+ {
+ return EVP_DecryptUpdate_cts(ctx, out, outl, in, inl);
+ }
+
if (inl == 0)
{
*outl=0;
@@ -430,11 +589,103 @@
return ret;
}
+int
+EVP_DecryptFinal_cts(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+ unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
+ int bl = ctx->cipher->block_size;
+ int leftover = 0;
+ *outl = 0;
+
+ if (!ctx->final_used) {
+ EVPerr(EVP_F_EVP_DECRYPTFINAL_CTS, EVP_R_EXPECTING_PREVIOUS_CIPHERTEXT);
+ return 0;
+ }
+ if (ctx->buf_len == 0) {
+ EVPerr(EVP_F_EVP_DECRYPTFINAL_CTS, EVP_R_EXPECTING_PREVIOUS_CIPHERTEXT);
+ return 0;
+ }
+
+ /* handle leftover bytes */
+ leftover = ctx->buf_len;
+
+ switch (EVP_CIPHER_CTX_mode(ctx)) {
+ case EVP_CIPH_ECB_MODE: {
+ /* decrypt => P_n plus C' */
+ if (!(ctx->cipher->do_cipher(ctx, tmp, ctx->final, bl))) {
+ return 0;
+ }
+
+ /* C_n plus C' */
+ memcpy(&(ctx->buf[leftover]), &(tmp[leftover]), (bl - leftover));
+ /* decrypt => P_{n-1} */
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))) {
+ return 0;
+ }
+
+ memcpy((out + bl), tmp, leftover);
+ *outl += (bl + leftover);
+ return 1;
+ }
+ case EVP_CIPH_CBC_MODE: {
+ int i = 0;
+ unsigned char C_n_minus_2[EVP_MAX_BLOCK_LENGTH];
+
+ memcpy(C_n_minus_2, ctx->iv, bl);
+
+ /* C_n plus 0s in ctx->buf */
+ memset(&(ctx->buf[leftover]), 0, (bl - leftover));
+
+ /* ctx->final is C_{n-1} */
+ /* decrypt => (P_n plus C')'' */
+ if (!(ctx->cipher->do_cipher(ctx, tmp, ctx->final, bl))) {
+ return 0;
+ }
+ /* XOR'ed with C_{n-2} => (P_n plus C')' */
+ for (i = 0; i < bl; i++) {
+ tmp[i] = tmp[i] ^ C_n_minus_2[i];
+ }
+ /* XOR'ed with (C_n plus 0s) => P_n plus C' */
+ for (i = 0; i < bl; i++) {
+ tmp[i] = tmp[i] ^ ctx->buf[i];
+ }
+
+ /* C_n plus C' in ctx->buf */
+ memcpy(&(ctx->buf[leftover]), &(tmp[leftover]), (bl - leftover));
+ /* decrypt => P_{n-1}'' */
+ if (!(ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))) {
+ return 0;
+ }
+ /* XOR'ed with C_{n-1} => P_{n-1}' */
+ for (i = 0; i < bl; i++) {
+ out[i] = out[i] ^ ctx->final[i];
+ }
+ /* XOR'ed with C_{n-2} => P_{n-1} */
+ for (i = 0; i < bl; i++) {
+ out[i] = out[i] ^ C_n_minus_2[i];
+ }
+
+ memcpy((out + bl), tmp, leftover);
+ *outl += (bl + leftover);
+ return 1;
+ }
+ default:
+ EVPerr(EVP_F_EVP_DECRYPTFINAL_CTS, EVP_R_UNSUPPORTED_MODE);
+ return 0;
+ }
+ return 0;
+}
+
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int i,n;
unsigned int b;
+ if (ctx->flags & EVP_CIPH_CIPHERTEXT_STEALING)
+ {
+ return EVP_DecryptFinal_cts(ctx, out, outl);
+ }
+
*outl=0;
b=ctx->cipher->block_size;
if (ctx->flags & EVP_CIPH_NO_PADDING)
@@ -531,6 +782,27 @@
return 1;
}
+int
+EVP_CIPHER_CTX_set_cts(EVP_CIPHER_CTX *ctx, int cts)
+{
+ switch (EVP_CIPHER_CTX_mode(ctx)) {
+ case EVP_CIPH_ECB_MODE:
+ case EVP_CIPH_CBC_MODE:
+ /* supported */
+ break;
+ default:
+ /* not supported */
+ EVPerr(EVP_F_EVP_CIPHER_CTX_SET_CTS, EVP_R_UNSUPPORTED_MODE);
+ return 0;
+ }
+ if (cts) {
+ ctx->flags |= EVP_CIPH_CIPHERTEXT_STEALING;
+ } else {
+ ctx->flags &= ~EVP_CIPH_CIPHERTEXT_STEALING;
+ }
+ return 1;
+}
+
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{
int ret;
Index: crypto/evp/evp_err.c
===================================================================
RCS file: /home/pach/prog/openssl/cvs/openssl/crypto/evp/evp_err.c,v
retrieving revision 1.43
diff -u -r1.43 evp_err.c
--- crypto/evp/evp_err.c 21 Nov 2006 21:29:39 -0000 1.43
+++ crypto/evp/evp_err.c 15 Mar 2007 06:13:20 -0000
@@ -1,6 +1,6 @@
/* crypto/evp/evp_err.c */
/* ====================================================================
- * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -79,9 +79,12 @@
{ERR_FUNC(EVP_F_ECKEY_PKEY2PKCS8), "ECKEY_PKEY2PKCS8"},
{ERR_FUNC(EVP_F_EVP_CIPHERINIT_EX), "EVP_CipherInit_ex"},
{ERR_FUNC(EVP_F_EVP_CIPHER_CTX_CTRL), "EVP_CIPHER_CTX_ctrl"},
+{ERR_FUNC(EVP_F_EVP_CIPHER_CTX_SET_CTS), "EVP_CIPHER_CTX_set_cts"},
{ERR_FUNC(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH),
"EVP_CIPHER_CTX_set_key_length"},
+{ERR_FUNC(EVP_F_EVP_DECRYPTFINAL_CTS), "EVP_DecryptFinal_cts"},
{ERR_FUNC(EVP_F_EVP_DECRYPTFINAL_EX), "EVP_DecryptFinal_ex"},
{ERR_FUNC(EVP_F_EVP_DIGESTINIT_EX), "EVP_DigestInit_ex"},
+{ERR_FUNC(EVP_F_EVP_ENCRYPTFINAL_CTS), "EVP_EncryptFinal_cts"},
{ERR_FUNC(EVP_F_EVP_ENCRYPTFINAL_EX), "EVP_EncryptFinal_ex"},
{ERR_FUNC(EVP_F_EVP_MD_CTX_COPY_EX), "EVP_MD_CTX_copy_ex"},
{ERR_FUNC(EVP_F_EVP_OPENINIT), "EVP_OpenInit"},
@@ -159,6 +162,8 @@
{ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY) ,"expecting a dsa key"},
{ERR_REASON(EVP_R_EXPECTING_A_ECDSA_KEY) ,"expecting a ecdsa key"},
{ERR_REASON(EVP_R_EXPECTING_A_EC_KEY) ,"expecting a ec key"},
+{ERR_REASON(EVP_R_EXPECTING_PREVIOUS_CIPHERTEXT),"expecting previous
ciphertext"},
+{ERR_REASON(EVP_R_EXPECTING_PREVIOUS_PLAINTEXT),"expecting previous
plaintext"},
{ERR_REASON(EVP_R_INITIALIZATION_ERROR) ,"initialization error"},
{ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) ,"input not initialized"},
{ERR_REASON(EVP_R_INVALID_DIGEST) ,"invalid digest"},
@@ -188,6 +193,7 @@
{ERR_REASON(EVP_R_UNSUPPORTED_KEYLENGTH) ,"unsupported keylength"},
{ERR_REASON(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION),"unsupported
key derivation function"},
{ERR_REASON(EVP_R_UNSUPPORTED_KEY_SIZE) ,"unsupported key size"},
+{ERR_REASON(EVP_R_UNSUPPORTED_MODE) ,"unsupported mode"},
{ERR_REASON(EVP_R_UNSUPPORTED_PRF) ,"unsupported prf"},
{ERR_REASON(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM),"unsupported
private key algorithm"},
{ERR_REASON(EVP_R_UNSUPPORTED_SALT_TYPE) ,"unsupported salt type"},
Index: crypto/evp/evp_test.c
===================================================================
RCS file: /home/pach/prog/openssl/cvs/openssl/crypto/evp/evp_test.c,v
retrieving revision 1.26
diff -u -r1.26 evp_test.c
--- crypto/evp/evp_test.c 9 Jun 2006 15:44:41 -0000 1.26
+++ crypto/evp/evp_test.c 15 Mar 2007 06:05:13 -0000
@@ -317,6 +317,217 @@
return 1;
}
+static int
+test_cts(const char *cipher)
+{
+ const EVP_CIPHER *c;
+ static char key[EVP_MAX_BLOCK_LENGTH];
+ static char iv[EVP_MAX_BLOCK_LENGTH];
+ static char ptext[EVP_MAX_BLOCK_LENGTH * 4];
+ static char ctext[EVP_MAX_BLOCK_LENGTH * 4];
+ static char dptext[EVP_MAX_BLOCK_LENGTH * 4];
+ static int initialized = 0;
+ int i, testlen, blocksize, off;
+
+ c = EVP_get_cipherbyname(cipher);
+ if (!c) {
+ return 0;
+ }
+
+ if (!initialized) {
+ for (i = 0; i < EVP_MAX_BLOCK_LENGTH; i++) {
+ key[i] = i;
+ iv[i] = i + 1;
+ }
+ for (i = 0; i < (EVP_MAX_BLOCK_LENGTH * 4); i++) {
+ ptext[i] = i + 2;
+ }
+
+ initialized = 1;
+ }
+
+ blocksize = c->block_size;
+ for (testlen = (blocksize + 1); testlen < (EVP_MAX_BLOCK_LENGTH * 4);
+ testlen++) {
+ int clen, clen2, dplen, dplen2;
+ EVP_CIPHER_CTX ectx;
+ EVP_CIPHER_CTX dctx;
+
+ EVP_CIPHER_CTX_init(&ectx);
+ if (!EVP_EncryptInit_ex(&ectx, c, NULL, key, iv)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ EXIT(201);
+ }
+ if (!EVP_CIPHER_CTX_set_cts(&ectx, 1)) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ EVP_CIPHER_CTX_init(&dctx);
+ if (!EVP_DecryptInit_ex(&dctx, c, NULL, key, iv)) {
+ fprintf(stderr, "DecryptInit failed\n");
+ EXIT(203);
+ }
+ if (!EVP_CIPHER_CTX_set_cts(&dctx, 1)) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ if ((!(ectx.flags & EVP_CIPH_CIPHERTEXT_STEALING))
+ || (!(dctx.flags & EVP_CIPH_CIPHERTEXT_STEALING))) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ if (!EVP_EncryptUpdate(&ectx, ctext, &clen, ptext, testlen)) {
+ fprintf(stderr, "EncryptUpdate failed\n");
+ EXIT(204);
+ }
+ if(!EVP_EncryptFinal_ex(&ectx, (ctext + clen), &clen2)) {
+ fprintf(stderr, "EncryptFinal failed\n");
+ EXIT(205);
+ }
+ if ((clen + clen2) != testlen) {
+ fprintf(stderr, "Plaintext len=%d, ciphertext len=%d\n", testlen,
+ (clen + clen2));
+ EXIT(206);
+ }
+ if (!EVP_DecryptUpdate(&dctx, dptext, &dplen, ctext, (clen + clen2))) {
+ fprintf(stderr, "DecryptUpdate failed\n");
+ EXIT(207);
+ }
+ if(!EVP_DecryptFinal_ex(&dctx, (dptext + dplen), &dplen2)) {
+ fprintf(stderr, "DecryptFinal failed\n");
+ EXIT(208);
+ }
+ if ((dplen + dplen2) != testlen) {
+ fprintf(stderr, "Plaintext len=%d, decrypted len=%d\n", testlen,
+ (dplen + dplen2));
+ EXIT(207);
+ }
+
+ if (memcmp(ptext, dptext, testlen)) {
+ fprintf(stderr, "Plaintext != decrypted\n");
+ EXIT(208);
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ectx);
+ EVP_CIPHER_CTX_cleanup(&dctx);
+ }
+
+ /* test update/final with small data segments */
+ {
+ int clen, clen2, dplen, dplen2, tlen;
+ EVP_CIPHER_CTX ectx;
+ EVP_CIPHER_CTX dctx;
+
+ EVP_CIPHER_CTX_init(&ectx);
+ if (!EVP_EncryptInit_ex(&ectx, c, NULL, key, iv)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ EXIT(201);
+ }
+ if (!EVP_CIPHER_CTX_set_cts(&ectx, 1)) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ EVP_CIPHER_CTX_init(&dctx);
+ if (!EVP_DecryptInit_ex(&dctx, c, NULL, key, iv)) {
+ fprintf(stderr, "DecryptInit failed\n");
+ EXIT(203);
+ }
+ if (!EVP_CIPHER_CTX_set_cts(&dctx, 1)) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ if ((!(ectx.flags & EVP_CIPH_CIPHERTEXT_STEALING))
+ || (!(dctx.flags & EVP_CIPH_CIPHERTEXT_STEALING))) {
+ fprintf(stderr, "Setting CTS failed\n");
+ EXIT(202);
+ }
+
+ testlen = EVP_MAX_BLOCK_LENGTH * 2 + 1;
+
+ /* encrypt in chunks of 1,2,2,2,... bytes */
+ if (!EVP_EncryptUpdate(&ectx, ctext, &clen, ptext, 1)) {
+ fprintf(stderr, "EncryptUpdate failed\n");
+ EXIT(204);
+ }
+ off = 1;
+ while ((off + 2) <= (testlen - 1)) {
+ if (!EVP_EncryptUpdate(&ectx, (ctext + clen), &tlen,
+ (ptext + off), 2)) {
+ fprintf(stderr, "EncryptUpdate failed\n");
+ EXIT(204);
+ }
+ off += 2;
+ clen += tlen;
+ }
+ if (!EVP_EncryptUpdate(&ectx, (ctext + clen), &tlen, (ptext + off),
+ (testlen - off))) {
+ fprintf(stderr, "EncryptUpdate failed\n");
+ EXIT(204);
+ }
+ clen += tlen;
+
+ if(!EVP_EncryptFinal_ex(&ectx, (ctext + clen), &clen2)) {
+ fprintf(stderr, "EncryptFinal failed\n");
+ EXIT(205);
+ }
+
+ if ((clen + clen2) != testlen) {
+ fprintf(stderr, "Plaintext len=%d, ciphertext len=%d\n", testlen,
+ (clen + clen2));
+ EXIT(206);
+ }
+
+ /* decrypt in chunks of 3,2,2,2,... bytes */
+ if (!EVP_DecryptUpdate(&dctx, dptext, &dplen, ctext, 3)) {
+ fprintf(stderr, "DecryptUpdate failed\n");
+ EXIT(207);
+ }
+
+ off = 3;
+ testlen = clen + clen2;
+ while ((off + 2) <= (testlen - 1)) {
+ if (!EVP_DecryptUpdate(&dctx, (dptext + dplen), &tlen,
+ (ctext + off), 2)) {
+ fprintf(stderr, "DecryptUpdate failed\n");
+ EXIT(207);
+ }
+ off += 2;
+ dplen += tlen;
+ }
+ if (!EVP_DecryptUpdate(&dctx, (dptext + dplen), &tlen, (ctext + off),
+ (testlen - off))) {
+ fprintf(stderr, "DecryptUpdate failed\n");
+ EXIT(207);
+ }
+ dplen += tlen;
+
+ if(!EVP_DecryptFinal_ex(&dctx, (dptext + dplen), &dplen2)) {
+ fprintf(stderr, "DecryptFinal failed\n");
+ EXIT(208);
+ }
+
+ if ((dplen + dplen2) != testlen) {
+ fprintf(stderr, "Plaintext len=%d, decrypted len=%d\n", testlen,
+ (dplen + dplen2));
+ EXIT(207);
+ }
+
+ if (memcmp(ptext, dptext, testlen)) {
+ fprintf(stderr, "Plaintext != decrypted\n");
+ EXIT(208);
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ectx);
+ EVP_CIPHER_CTX_cleanup(&dctx);
+ }
+ return 1;
+}
+
int main(int argc,char **argv)
{
const char *szTestFile;
@@ -386,7 +597,16 @@
} else {
encdec = atoi(sstrsep(&p,"\n"));
}
-
+
+ if (memcmp(key, "TEST_CTS", 8) == 0) {
+ printf("Testing CTS with %s ... ", cipher);
+ if (test_cts(cipher)) {
+ printf("OK\n");
+ } else {
+ printf("failed\n");
+ }
+ continue;
+ }
kn=convert(key);
in=convert(iv);
Index: crypto/evp/evptests.txt
===================================================================
RCS file: /home/pach/prog/openssl/cvs/openssl/crypto/evp/evptests.txt,v
retrieving revision 1.11
diff -u -r1.11 evptests.txt
--- crypto/evp/evptests.txt 9 Jun 2006 15:44:42 -0000 1.11
+++ crypto/evp/evptests.txt 15 Mar 2007 06:05:13 -0000
@@ -310,3 +310,14 @@
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:0
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:0
+#cipher:TEST_CTS::::
+AES-128-ECB:TEST_CTS::::
+AES-192-ECB:TEST_CTS::::
+AES-256-ECB:TEST_CTS::::
+AES-128-CBC:TEST_CTS::::
+AES-192-CBC:TEST_CTS::::
+AES-256-CBC:TEST_CTS::::
+DES-ECB:TEST_CTS::::
+DESX-CBC:TEST_CTS::::
+DES-EDE3-CBC:TEST_CTS::::
+
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [EMAIL PROTECTED]