diff options
author | Andy Polyakov <appro@openssl.org> | 2016-06-20 11:11:25 +0200 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2016-06-27 10:09:07 +0200 |
commit | 5fc77684f1bfa87d0cf9f7a84de92550fa854a84 (patch) | |
tree | 79bb99c5f75bc08d5ca8961a8e1e1f868c235496 /crypto/evp | |
parent | c3a73daf0acc1272905db954b92a23146aad82f0 (diff) |
evp/evp_enc.c: refine partial buffer overlap detection.
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/evp_enc.c | 30 |
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; |