The branch master has been updated via b153f0921bea38127de0b9440b0487db3004330d (commit) via ef055ec536a3c6e698dd9f45b41d57a32366b4fa (commit) via 7141ba31969d0b378d08104a51f8f99b9187b9d5 (commit) via 0b96d77a62d8ac9a45ac1dda47560ced676b5b8d (commit) via 7c12c7b61c5b37c9dff930ccc68421fb7de00271 (commit) via 0ba5a9eaa0a6ae7fc25ee70eefc1f4fbdaf09483 (commit) from 5ee289eaf6fa747e6b63b989c7a79ff1c9c95db3 (commit)
- Log ----------------------------------------------------------------- commit b153f0921bea38127de0b9440b0487db3004330d Author: Matt Caswell <m...@openssl.org> Date: Wed Jan 25 15:01:43 2017 +0000 Remove assert from is_partially_overlapping() This function is used to validate application supplied parameters. An assert should be used to check for an error that is internal to OpenSSL. Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) commit ef055ec536a3c6e698dd9f45b41d57a32366b4fa Author: Matt Caswell <m...@openssl.org> Date: Wed Jan 25 09:26:35 2017 +0000 Adjust in and in_len instead of donelen Don't use the temp variable donelen in the non-aad fragmented code path. Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) commit 7141ba31969d0b378d08104a51f8f99b9187b9d5 Author: Matt Caswell <m...@openssl.org> Date: Tue Jan 24 12:57:34 2017 +0000 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 <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) commit 0b96d77a62d8ac9a45ac1dda47560ced676b5b8d Author: Matt Caswell <m...@openssl.org> Date: Mon Jan 23 12:45:33 2017 +0000 Update evp_test to make sure passing partial block to "Update" is ok The previous commit fixed a bug where a partial block had been passed to an "Update" function and it wasn't properly handled. We should catch this type of error in evp_test. Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) commit 7c12c7b61c5b37c9dff930ccc68421fb7de00271 Author: Matt Caswell <m...@openssl.org> Date: Mon Jan 23 12:44:48 2017 +0000 Properly handle a partial block in OCB mode If we have previously been passed a partial block in an "Update" call then make sure we properly increment the output buffer when we use it. Fixes #2273 Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) commit 0ba5a9eaa0a6ae7fc25ee70eefc1f4fbdaf09483 Author: Matt Caswell <m...@openssl.org> Date: Mon Jan 23 12:43:59 2017 +0000 Don't use magic numbers in aes_ocb_cipher() Lots of references to 16 replaced by AES_BLOCK_SIZE. Also a few other style tweaks in that function Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2275) ----------------------------------------------------------------------- Summary of changes: crypto/evp/e_aes.c | 36 +++++++++++++------ crypto/evp/e_des3.c | 7 ++++ crypto/evp/evp_enc.c | 22 ++++++------ crypto/evp/evp_err.c | 3 ++ crypto/evp/evp_locl.h | 2 ++ include/openssl/evp.h | 3 ++ test/evp_test.c | 99 ++++++++++++++++++++++++++++++++++++++++++--------- 7 files changed, 133 insertions(+), 39 deletions(-) diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 5810798..c0b0a1e 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 */ @@ -2536,7 +2541,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (!octx->key_set) return -1; - if (in) { + if (in != NULL) { /* * Need to ensure we are only passing full blocks to low level OCB * routines. We do it here rather than in EVP_EncryptUpdate/ @@ -2551,16 +2556,21 @@ 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; + } } /* * If we've got a partially filled buffer from a previous call then * use that data first */ - if (*buf_len) { + if (*buf_len > 0) { unsigned int remaining; - remaining = 16 - (*buf_len); + remaining = AES_BLOCK_SIZE - (*buf_len); if (remaining > len) { memcpy(buf + (*buf_len), in, len); *(buf_len) += len; @@ -2574,21 +2584,25 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, len -= remaining; in += remaining; if (out == NULL) { - if (!CRYPTO_ocb128_aad(&octx->ocb, buf, 16)) + if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE)) return -1; } else if (EVP_CIPHER_CTX_encrypting(ctx)) { - if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, 16)) + if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, + AES_BLOCK_SIZE)) return -1; } else { - if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, 16)) + if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, + AES_BLOCK_SIZE)) return -1; } - written_len = 16; + written_len = AES_BLOCK_SIZE; *buf_len = 0; + if (out != NULL) + out += AES_BLOCK_SIZE; } /* Do we have a partial block to handle at the end? */ - trailing_len = len % 16; + trailing_len = len % AES_BLOCK_SIZE; /* * If we've got some full blocks to handle, then process these first @@ -2611,7 +2625,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, } /* Handle any trailing partial block */ - if (trailing_len) { + if (trailing_len > 0) { memcpy(buf, in, trailing_len); *buf_len = trailing_len; } @@ -2622,7 +2636,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, * First of all empty the buffer of any partial block that we might * have been provided - both for data and AAD */ - if (octx->data_buf_len) { + if (octx->data_buf_len > 0) { if (EVP_CIPHER_CTX_encrypting(ctx)) { if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out, octx->data_buf_len)) @@ -2635,7 +2649,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, written_len = octx->data_buf_len; octx->data_buf_len = 0; } - if (octx->aad_buf_len) { + if (octx->aad_buf_len > 0) { if (!CRYPTO_ocb128_aad (&octx->ocb, octx->aad_buf, octx->aad_buf_len)) return -1; diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c index a842913..da77936 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 bedc964..bb6dd67 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; /* @@ -287,7 +286,7 @@ static int is_partially_overlapping(const void *ptr1, const void *ptr2, */ int overlapped = (len > 0) & (diff != 0) & ((diff < (PTRDIFF_T)len) | (diff > (0 - (PTRDIFF_T)len))); - assert(!overlapped); + return overlapped; } @@ -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 2527df6..bf09052 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 7f3526f..209577b 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 fda0713..8252e25 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 a4c3146..e1a5f14 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -880,12 +880,12 @@ static int cipher_test_parse(struct evp_test *t, const char *keyword, } static int cipher_test_enc(struct evp_test *t, int enc, - size_t out_misalign, size_t inp_misalign) + size_t out_misalign, size_t inp_misalign, int frag) { struct cipher_data *cdat = t->data; unsigned char *in, *out, *tmp = NULL; - size_t in_len, out_len; - int tmplen, tmpflen; + size_t in_len, out_len, donelen = 0; + int tmplen, chunklen, tmpflen; EVP_CIPHER_CTX *ctx = NULL; const char *err; err = "INTERNAL_ERROR"; @@ -983,15 +983,63 @@ static int cipher_test_enc(struct evp_test *t, int enc, } } if (cdat->aad) { - if (!EVP_CipherUpdate(ctx, NULL, &tmplen, cdat->aad, cdat->aad_len)) { - err = "AAD_SET_ERROR"; - goto err; + err = "AAD_SET_ERROR"; + if (!frag) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, cdat->aad, + cdat->aad_len)) + goto err; + } else { + /* + * Supply the AAD in chunks less than the block size where possible + */ + if (cdat->aad_len > 0) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, cdat->aad, 1)) + goto err; + donelen++; + } + if (cdat->aad_len > 2) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, cdat->aad + donelen, + cdat->aad_len - 2)) + goto err; + donelen += cdat->aad_len - 2; + } + if (cdat->aad_len > 1 + && !EVP_CipherUpdate(ctx, NULL, &chunklen, + cdat->aad + donelen, 1)) + goto err; } } EVP_CIPHER_CTX_set_padding(ctx, 0); err = "CIPHERUPDATE_ERROR"; - if (!EVP_CipherUpdate(ctx, tmp + out_misalign, &tmplen, in, in_len)) - goto err; + tmplen = 0; + if (!frag) { + /* We supply the data all in one go */ + if (!EVP_CipherUpdate(ctx, tmp + out_misalign, &tmplen, in, in_len)) + goto err; + } else { + /* Supply the data in chunks less than the block size where possible */ + if (in_len > 0) { + if (!EVP_CipherUpdate(ctx, tmp + out_misalign, &chunklen, in, 1)) + goto err; + tmplen += chunklen; + in++; + in_len--; + } + if (in_len > 1) { + if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen, + in, in_len - 1)) + goto err; + tmplen += chunklen; + in += in_len - 1; + in_len = 1; + } + if (in_len > 0 ) { + if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen, + in, 1)) + goto err; + tmplen += chunklen; + } + } if (cdat->aead == EVP_CIPH_CCM_MODE) tmpflen = 0; else { @@ -1032,7 +1080,7 @@ static int cipher_test_enc(struct evp_test *t, int enc, static int cipher_test_run(struct evp_test *t) { struct cipher_data *cdat = t->data; - int rv; + int rv, frag = 0; size_t out_misalign, inp_misalign; if (!cdat->key) { @@ -1050,21 +1098,25 @@ static int cipher_test_run(struct evp_test *t) t->err = "NO_TAG"; return 0; } - for (out_misalign = 0; out_misalign <= 1; out_misalign++) { + for (out_misalign = 0; out_misalign <= 1;) { static char aux_err[64]; t->aux_err = aux_err; for (inp_misalign = (size_t)-1; inp_misalign != 2; inp_misalign++) { if (inp_misalign == (size_t)-1) { /* kludge: inp_misalign == -1 means "exercise in-place" */ - BIO_snprintf(aux_err, sizeof(aux_err), "%s in-place", - out_misalign ? "misaligned" : "aligned"); + BIO_snprintf(aux_err, sizeof(aux_err), + "%s in-place, %sfragmented", + out_misalign ? "misaligned" : "aligned", + frag ? "" : "not "); } else { - BIO_snprintf(aux_err, sizeof(aux_err), "%s output and %s input", + BIO_snprintf(aux_err, sizeof(aux_err), + "%s output and %s input, %sfragmented", out_misalign ? "misaligned" : "aligned", - inp_misalign ? "misaligned" : "aligned"); + inp_misalign ? "misaligned" : "aligned", + frag ? "" : "not "); } if (cdat->enc) { - rv = cipher_test_enc(t, 1, out_misalign, inp_misalign); + rv = cipher_test_enc(t, 1, out_misalign, inp_misalign, frag); /* Not fatal errors: return */ if (rv != 1) { if (rv < 0) @@ -1073,7 +1125,7 @@ static int cipher_test_run(struct evp_test *t) } } if (cdat->enc != 1) { - rv = cipher_test_enc(t, 0, out_misalign, inp_misalign); + rv = cipher_test_enc(t, 0, out_misalign, inp_misalign, frag); /* Not fatal errors: return */ if (rv != 1) { if (rv < 0) @@ -1082,6 +1134,21 @@ static int cipher_test_run(struct evp_test *t) } } } + + if (out_misalign == 1 && frag == 0) { + /* + * XTS, CCM and Wrap modes have special requirements about input + * lengths so we don't fragment for those + */ + if (cdat->aead == EVP_CIPH_CCM_MODE + || EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_XTS_MODE + || EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) + break; + out_misalign = 0; + frag++; + } else { + out_misalign++; + } } t->aux_err = NULL; _____ openssl-commits mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-commits