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)
This commit is contained in:
parent
0b96d77a62
commit
7141ba3196
7 changed files with 34 additions and 14 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue