summaryrefslogtreecommitdiffstats
path: root/crypto/evp/evp_enc.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-01-24 12:57:34 +0000
committerMatt Caswell <matt@openssl.org>2017-01-25 15:02:44 +0000
commit7141ba31969d0b378d08104a51f8f99b9187b9d5 (patch)
tree58735ecf1d4e9b266e2b928f13d018d2118f05c3 /crypto/evp/evp_enc.c
parent0b96d77a62d8ac9a45ac1dda47560ced676b5b8d (diff)
Fix the overlapping check for fragmented "Update" operations
When doing in place encryption the overlapping buffer check can fail incorrectly where we have done a partial block "Update" operation. This fixes things to take account of any pending partial blocks. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275)
Diffstat (limited to 'crypto/evp/evp_enc.c')
-rw-r--r--crypto/evp/evp_enc.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index bedc964361..ef66cb1de5 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -276,8 +276,7 @@ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
# define PTRDIFF_T size_t
#endif
-static int is_partially_overlapping(const void *ptr1, const void *ptr2,
- int len)
+int is_partially_overlapping(const void *ptr1, const void *ptr2, int len)
{
PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2;
/*
@@ -296,8 +295,11 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
{
int i, j, bl;
+ bl = ctx->cipher->block_size;
+
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
- if (is_partially_overlapping(out, in, inl)) {
+ /* If block size > 1 then the cipher will have to do this check */
+ if (bl == 1 && is_partially_overlapping(out, in, inl)) {
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -314,7 +316,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
*outl = 0;
return inl == 0;
}
- if (is_partially_overlapping(out, in, inl)) {
+ if (is_partially_overlapping(out + ctx->buf_len, in, inl)) {
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -329,7 +331,6 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
}
}
i = ctx->buf_len;
- bl = ctx->cipher->block_size;
OPENSSL_assert(bl <= (int)sizeof(ctx->buf));
if (i != 0) {
if (bl - i > inl) {
@@ -342,10 +343,6 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
memcpy(&(ctx->buf[i]), in, j);
inl -= j;
in += j;
- if (is_partially_overlapping(out, in, bl)) {
- EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
- return 0;
- }
if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))
return 0;
out += bl;
@@ -422,8 +419,10 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
int fix_len;
unsigned int b;
+ b = ctx->cipher->block_size;
+
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
- if (is_partially_overlapping(out, in, inl)) {
+ if (b == 1 && is_partially_overlapping(out, in, inl)) {
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
@@ -445,7 +444,6 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
if (ctx->flags & EVP_CIPH_NO_PADDING)
return EVP_EncryptUpdate(ctx, out, outl, in, inl);
- b = ctx->cipher->block_size;
OPENSSL_assert(b <= sizeof ctx->final);
if (ctx->final_used) {