diff -ru openssl-0.9.8d-0/crypto/evp/evp.h openssl-0.9.8d/crypto/evp/evp.h
--- openssl-0.9.8d-0/crypto/evp/evp.h	2006-06-09 08:42:13.000000000 -0700
+++ openssl-0.9.8d/crypto/evp/evp.h	2007-02-07 22:12:06.125000000 -0800
@@ -347,6 +347,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 */
 
@@ -526,7 +528,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,
@@ -535,7 +540,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,
@@ -584,6 +592,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);
 
@@ -885,9 +894,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			 136
 #define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
+#define EVP_F_EVP_DECRYPTFINAL_CTS			 137
 #define EVP_F_EVP_DECRYPTFINAL_EX			 101
 #define EVP_F_EVP_DIGESTINIT_EX				 128
+#define EVP_F_EVP_ENCRYPTFINAL_CTS			 138
 #define EVP_F_EVP_ENCRYPTFINAL_EX			 127
 #define EVP_F_EVP_MD_CTX_COPY_EX			 110
 #define EVP_F_EVP_OPENINIT				 102
@@ -935,6 +947,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		 144
+#define EVP_R_EXPECTING_PREVIOUS_PLAINTEXT		 145
 #define EVP_R_INITIALIZATION_ERROR			 134
 #define EVP_R_INPUT_NOT_INITIALIZED			 111
 #define EVP_R_INVALID_KEY_LENGTH			 130
@@ -954,6 +968,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				 146
 #define EVP_R_UNSUPPORTED_PRF				 125
 #define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM		 118
 #define EVP_R_UNSUPPORTED_SALT_TYPE			 126
diff -ru openssl-0.9.8d-0/crypto/evp/evp_enc.c openssl-0.9.8d/crypto/evp/evp_enc.c
--- openssl-0.9.8d-0/crypto/evp/evp_enc.c	2005-12-02 05:47:02.000000000 -0800
+++ openssl-0.9.8d/crypto/evp/evp_enc.c	2007-02-07 22:12:06.140625000 -0800
@@ -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;
diff -ru openssl-0.9.8d-0/crypto/evp/evp_err.c openssl-0.9.8d/crypto/evp/evp_err.c
--- openssl-0.9.8d-0/crypto/evp/evp_err.c	2006-06-09 08:42:13.000000000 -0700
+++ openssl-0.9.8d/crypto/evp/evp_err.c	2007-02-07 22:12:06.140625000 -0800
@@ -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"},
@@ -132,6 +135,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_KEY_LENGTH)    ,"invalid key length"},
@@ -151,6 +156,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"},
diff -ru openssl-0.9.8d-0/crypto/evp/evp_test.c openssl-0.9.8d/crypto/evp/evp_test.c
--- openssl-0.9.8d-0/crypto/evp/evp_test.c	2006-06-09 08:42:13.000000000 -0700
+++ openssl-0.9.8d/crypto/evp/evp_test.c	2007-02-07 22:12:06.140625000 -0800
@@ -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);
diff -ru openssl-0.9.8d-0/crypto/evp/evptests.txt openssl-0.9.8d/crypto/evp/evptests.txt
--- openssl-0.9.8d-0/crypto/evp/evptests.txt	2006-06-09 08:42:13.000000000 -0700
+++ openssl-0.9.8d/crypto/evp/evptests.txt	2007-02-07 22:12:06.140625000 -0800
@@ -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::::
+
diff -ru openssl-0.9.8d-0/test/evptests.txt openssl-0.9.8d/test/evptests.txt
--- openssl-0.9.8d-0/test/evptests.txt	2006-09-28 04:51:47.000000000 -0700
+++ openssl-0.9.8d/test/evptests.txt	2007-02-07 22:12:32.640625000 -0800
@@ -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::::
+
