Commit 0b96d77a authored by Matt Caswell's avatar Matt Caswell
Browse files

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: default avatarRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2275)
parent 7c12c7b6
Loading
Loading
Loading
Loading
+85 −16
Original line number Diff line number Diff line
@@ -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,62 @@ 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";
        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";
    tmplen = 0;
    donelen = 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;
            donelen = 1;
        }
        if (in_len > 2) {
            if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen,
                                  in + donelen, in_len - 2))
                goto err;
            tmplen += chunklen;
            donelen += in_len - 2;
        }
        if (in_len > 1 ) {
            if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen,
                                  in + donelen, 1))
                goto err;
            tmplen += chunklen;
        }
    }
    if (cdat->aead == EVP_CIPH_CCM_MODE)
        tmpflen = 0;
    else {
@@ -1032,7 +1079,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 +1097,28 @@ 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 (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), "%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 +1127,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 +1136,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;