summaryrefslogtreecommitdiffstats
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
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)
-rw-r--r--crypto/evp/e_aes.c10
-rw-r--r--crypto/evp/e_des3.c7
-rw-r--r--crypto/evp/evp_enc.c20
-rw-r--r--crypto/evp/evp_err.c3
-rw-r--r--crypto/evp/evp_locl.h2
-rw-r--r--include/openssl/evp.h3
-rw-r--r--test/evp_test.c3
7 files changed, 34 insertions, 14 deletions
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index d3be6a086a..c0b0a1ebaf 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -17,6 +17,7 @@
#include "internal/evp_int.h"
#include "modes_lcl.h"
#include <openssl/rand.h>
+#include "evp_locl.h"
typedef struct {
union {
@@ -2233,6 +2234,10 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* If not padding input must be multiple of 8 */
if (!pad && inlen & 0x7)
return -1;
+ if (is_partially_overlapping(out, in, inlen)) {
+ EVPerr(EVP_F_AES_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ return 0;
+ }
if (!out) {
if (EVP_CIPHER_CTX_encrypting(ctx)) {
/* If padding round up to multiple of 8 */
@@ -2551,6 +2556,11 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
} else {
buf = octx->data_buf;
buf_len = &(octx->data_buf_len);
+
+ if (is_partially_overlapping(out + *buf_len, in, len)) {
+ EVPerr(EVP_F_AES_OCB_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ return 0;
+ }
}
/*
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index a842913658..da77936c96 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -15,6 +15,7 @@
# include "internal/evp_int.h"
# include <openssl/des.h>
# include <openssl/rand.h>
+# include "evp_locl.h"
typedef struct {
union {
@@ -392,6 +393,12 @@ static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
*/
if (inl >= EVP_MAXCHUNK || inl % 8)
return -1;
+
+ if (is_partially_overlapping(out, in, inl)) {
+ EVPerr(EVP_F_DES_EDE3_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
+ return 0;
+ }
+
if (EVP_CIPHER_CTX_encrypting(ctx))
return des_ede3_wrap(ctx, out, in, inl);
else
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) {
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 2527df60dd..bf09052809 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -21,11 +21,14 @@
static ERR_STRING_DATA EVP_str_functs[] = {
{ERR_FUNC(EVP_F_AESNI_INIT_KEY), "aesni_init_key"},
{ERR_FUNC(EVP_F_AES_INIT_KEY), "aes_init_key"},
+ {ERR_FUNC(EVP_F_AES_OCB_CIPHER), "aes_ocb_cipher"},
{ERR_FUNC(EVP_F_AES_T4_INIT_KEY), "aes_t4_init_key"},
+ {ERR_FUNC(EVP_F_AES_WRAP_CIPHER), "aes_wrap_cipher"},
{ERR_FUNC(EVP_F_ALG_MODULE_INIT), "alg_module_init"},
{ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY), "camellia_init_key"},
{ERR_FUNC(EVP_F_CHACHA20_POLY1305_CTRL), "chacha20_poly1305_ctrl"},
{ERR_FUNC(EVP_F_CMLL_T4_INIT_KEY), "cmll_t4_init_key"},
+ {ERR_FUNC(EVP_F_DES_EDE3_WRAP_CIPHER), "des_ede3_wrap_cipher"},
{ERR_FUNC(EVP_F_DO_SIGVER_INIT), "do_sigver_init"},
{ERR_FUNC(EVP_F_EVP_CIPHERINIT_EX), "EVP_CipherInit_ex"},
{ERR_FUNC(EVP_F_EVP_CIPHER_CTX_COPY), "EVP_CIPHER_CTX_copy"},
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 7f3526f1ba..209577b7c2 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -64,3 +64,5 @@ struct evp_Encode_Ctx_st {
typedef struct evp_pbe_st EVP_PBE_CTL;
DEFINE_STACK_OF(EVP_PBE_CTL)
+
+int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index fda0713ce4..8252e25780 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1467,11 +1467,14 @@ int ERR_load_EVP_strings(void);
/* Function codes. */
# define EVP_F_AESNI_INIT_KEY 165
# define EVP_F_AES_INIT_KEY 133
+# define EVP_F_AES_OCB_CIPHER 169
# define EVP_F_AES_T4_INIT_KEY 178
+# define EVP_F_AES_WRAP_CIPHER 170
# define EVP_F_ALG_MODULE_INIT 177
# define EVP_F_CAMELLIA_INIT_KEY 159
# define EVP_F_CHACHA20_POLY1305_CTRL 182
# define EVP_F_CMLL_T4_INIT_KEY 179
+# define EVP_F_DES_EDE3_WRAP_CIPHER 171
# define EVP_F_DO_SIGVER_INIT 161
# define EVP_F_EVP_CIPHERINIT_EX 123
# define EVP_F_EVP_CIPHER_CTX_COPY 163
diff --git a/test/evp_test.c b/test/evp_test.c
index cc0a5bd420..f0e8ca35c0 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -1101,9 +1101,6 @@ static int cipher_test_run(struct evp_test *t)
static char aux_err[64];
t->aux_err = aux_err;
for (inp_misalign = (size_t)-1; inp_misalign != 2; inp_misalign++) {
- if (frag && inp_misalign == (size_t)-1)
- continue;
-
if (inp_misalign == (size_t)-1) {
/* kludge: inp_misalign == -1 means "exercise in-place" */
BIO_snprintf(aux_err, sizeof(aux_err),