summaryrefslogtreecommitdiffstats
path: root/crypto/evp/evp_enc.c
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2016-06-20 11:11:25 +0200
committerAndy Polyakov <appro@openssl.org>2016-06-27 10:09:07 +0200
commit5fc77684f1bfa87d0cf9f7a84de92550fa854a84 (patch)
tree79bb99c5f75bc08d5ca8961a8e1e1f868c235496 /crypto/evp/evp_enc.c
parentc3a73daf0acc1272905db954b92a23146aad82f0 (diff)
evp/evp_enc.c: refine partial buffer overlap detection.
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'crypto/evp/evp_enc.c')
-rw-r--r--crypto/evp/evp_enc.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 92319e5ab7..e43a5d2eea 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -265,7 +265,11 @@ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE==64
/*
* Then we have VMS that distinguishes itself by adhering to
- * sizeof(size_t)==4 even in 64-bit builds...
+ * sizeof(size_t)==4 even in 64-bit builds, which means that
+ * difference between two pointers might be truncated to 32 bits.
+ * In the context one can even wonder how comparison for
+ * equality is implemented. To be on the safe side we adhere to
+ * PTRDIFF_T even for comparison for equality.
*/
# define PTRDIFF_T uint64_t
#else
@@ -292,10 +296,10 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
{
int i, j, bl;
- if (is_partially_overlapping(out, in, inl))
- return 0;
-
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ if (is_partially_overlapping(out, in, inl))
+ return 0;
+
i = ctx->cipher->do_cipher(ctx, out, in, inl);
if (i < 0)
return 0;
@@ -308,6 +312,8 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
*outl = 0;
return inl == 0;
}
+ if (is_partially_overlapping(out, in, inl))
+ return 0;
if (ctx->buf_len == 0 && (inl & (ctx->block_mask)) == 0) {
if (ctx->cipher->do_cipher(ctx, out, in, inl)) {
@@ -330,10 +336,12 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
} else {
j = bl - i;
memcpy(&(ctx->buf[i]), in, j);
- if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))
- return 0;
inl -= j;
in += j;
+ if (is_partially_overlapping(out, in, bl))
+ return 0;
+ if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))
+ return 0;
out += bl;
*outl = bl;
}
@@ -408,10 +416,10 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
int fix_len;
unsigned int b;
- if (is_partially_overlapping(out, in, inl))
- return 0;
-
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ if (is_partially_overlapping(out, in, inl))
+ return 0;
+
fix_len = ctx->cipher->do_cipher(ctx, out, in, inl);
if (fix_len < 0) {
*outl = 0;
@@ -433,6 +441,10 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
OPENSSL_assert(b <= sizeof ctx->final);
if (ctx->final_used) {
+ /* see comment about PTRDIFF_T comparison above */
+ if (((PTRDIFF_T)out == (PTRDIFF_T)in)
+ || is_partially_overlapping(out, in, b))
+ return 0;
memcpy(out, ctx->final, b);
out += b;
fix_len = 1;