[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Wed Jan 25 15:09:35 UTC 2017


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 <matt at 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 <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2275)

commit ef055ec536a3c6e698dd9f45b41d57a32366b4fa
Author: Matt Caswell <matt at 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 <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2275)

commit 7141ba31969d0b378d08104a51f8f99b9187b9d5
Author: Matt Caswell <matt at 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 <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2275)

commit 0b96d77a62d8ac9a45ac1dda47560ced676b5b8d
Author: Matt Caswell <matt at 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 <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2275)

commit 7c12c7b61c5b37c9dff930ccc68421fb7de00271
Author: Matt Caswell <matt at 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 <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2275)

commit 0ba5a9eaa0a6ae7fc25ee70eefc1f4fbdaf09483
Author: Matt Caswell <matt at 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 <rsalz at 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;
 


More information about the openssl-commits mailing list