Commit 2bdb4af5 authored by Richard Levitte's avatar Richard Levitte
Browse files

Adapt test/evp_test.c to deal with available EVP_MACs



If a MAC isn't available as an EVP_MAC, the MAC test falls back to the
corresponding EVP_PKEY method.

Reviewed-by: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7393)
parent 5e55159b
Loading
Loading
Loading
Loading
+172 −20
Original line number Diff line number Diff line
@@ -832,8 +832,9 @@ static const EVP_TEST_METHOD cipher_test_method = {
**/

typedef struct mac_data_st {
    /* MAC type */
    int type;
    /* MAC type in one form or another */
    const EVP_MAC *mac;          /* for mac_test_run_mac */
    int type;                    /* for mac_test_run_pkey */
    /* Algorithm string for this MAC */
    char *alg;
    /* MAC key */
@@ -851,37 +852,62 @@ typedef struct mac_data_st {

static int mac_test_init(EVP_TEST *t, const char *alg)
{
    int type;
    const EVP_MAC *mac = NULL;
    int type = NID_undef;
    MAC_DATA *mdat;

    if (strcmp(alg, "HMAC") == 0) {
    if ((mac = EVP_get_macbyname(alg)) == NULL) {
        /*
         * Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods
         * For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running
         * the EVP_PKEY method.
         */
        size_t sz = strlen(alg);
        static const char epilogue[] = " by EVP_PKEY";

        if (strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
            sz -= sizeof(epilogue) - 1;

        if (strncmp(alg, "HMAC", sz) == 0) {
            type = EVP_PKEY_HMAC;
    } else if (strcmp(alg, "CMAC") == 0) {
        } else if (strncmp(alg, "CMAC", sz) == 0) {
#ifndef OPENSSL_NO_CMAC
            type = EVP_PKEY_CMAC;
#else
            t->skip = 1;
            return 1;
#endif
    } else if (strcmp(alg, "Poly1305") == 0) {
        } else if (strncmp(alg, "Poly1305", sz) == 0) {
#ifndef OPENSSL_NO_POLY1305
            type = EVP_PKEY_POLY1305;
#else
            t->skip = 1;
            return 1;
#endif
    } else if (strcmp(alg, "SipHash") == 0) {
        } else if (strncmp(alg, "SipHash", sz) == 0) {
#ifndef OPENSSL_NO_SIPHASH
            type = EVP_PKEY_SIPHASH;
#else
            t->skip = 1;
            return 1;
#endif
    } else
        } else {
            /*
             * Not a known EVP_PKEY method either.  If it's a known OID, then
             * assume it's been disabled.
             */
            if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) {
                t->skip = 1;
                return 1;
            }

            return 0;
        }
    }

    mdat = OPENSSL_zalloc(sizeof(*mdat));
    mdat->type = type;
    mdat->mac = mac;
    mdat->controls = sk_OPENSSL_STRING_new_null();
    t->data = mdat;
    return 1;
@@ -927,7 +953,7 @@ static int mac_test_parse(EVP_TEST *t,
    return 0;
}

static int mac_test_run(EVP_TEST *t)
static int mac_test_run_pkey(EVP_TEST *t)
{
    MAC_DATA *expected = t->data;
    EVP_MD_CTX *mctx = NULL;
@@ -938,6 +964,12 @@ static int mac_test_run(EVP_TEST *t)
    size_t got_len;
    int i;

    if (expected->alg == NULL)
        TEST_info("Trying the EVP_PKEY %s test", OBJ_nid2sn(expected->type));
    else
        TEST_info("Trying the EVP_PKEY %s test with %s",
                  OBJ_nid2sn(expected->type), expected->alg);

#ifdef OPENSSL_NO_DES
    if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
        /* Skip DES */
@@ -1005,6 +1037,126 @@ static int mac_test_run(EVP_TEST *t)
    return 1;
}

static int mac_test_run_mac(EVP_TEST *t)
{
    MAC_DATA *expected = t->data;
    EVP_MAC_CTX *ctx = NULL;
    const void *algo = NULL;
    int algo_ctrl = 0;
    unsigned char *got = NULL;
    size_t got_len;
    int rv, i;

    if (expected->alg == NULL)
        TEST_info("Trying the EVP_MAC %s test", EVP_MAC_name(expected->mac));
    else
        TEST_info("Trying the EVP_MAC %s test with %s",
                  EVP_MAC_name(expected->mac), expected->alg);

#ifdef OPENSSL_NO_DES
    if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
        /* Skip DES */
        t->err = NULL;
        goto err;
    }
#endif

    if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) {
        t->err = "MAC_CREATE_ERROR";
        goto err;
    }

    if (expected->alg != NULL
        && ((algo_ctrl = EVP_MAC_CTRL_SET_CIPHER,
             algo = EVP_get_cipherbyname(expected->alg)) == NULL
            && (algo_ctrl = EVP_MAC_CTRL_SET_MD,
                algo = EVP_get_digestbyname(expected->alg)) == NULL)) {
        t->err = "MAC_BAD_ALGORITHM";
        goto err;
    }


    if (algo_ctrl != 0) {
        rv = EVP_MAC_ctrl(ctx, algo_ctrl, algo);
        if (rv == -2) {
            t->err = "MAC_CTRL_INVALID";
            goto err;
        } else if (rv <= 0) {
            t->err = "MAC_CTRL_ERROR";
            goto err;
        }
    }

    rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY,
                      expected->key, expected->key_len);
    if (rv == -2) {
        t->err = "MAC_CTRL_INVALID";
        goto err;
    } else if (rv <= 0) {
        t->err = "MAC_CTRL_ERROR";
        goto err;
    }

    if (!EVP_MAC_init(ctx)) {
        t->err = "MAC_INIT_ERROR";
        goto err;
    }
    for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) {
        char *p, *tmpval;
        char *value = sk_OPENSSL_STRING_value(expected->controls, i);

        if (!TEST_ptr(tmpval = OPENSSL_strdup(value))) {
            t->err = "MAC_CTRL_ERROR";
            goto err;
        }
        p = strchr(tmpval, ':');
        if (p != NULL)
            *p++ = '\0';
        rv = EVP_MAC_ctrl_str(ctx, tmpval, p);
        OPENSSL_free(tmpval);
        if (rv == -2) {
            t->err = "MAC_CTRL_INVALID";
            goto err;
        } else if (rv <= 0) {
            t->err = "MAC_CTRL_ERROR";
            goto err;
        }
    }
    if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) {
        t->err = "MAC_UPDATE_ERROR";
        goto err;
    }
    if (!EVP_MAC_final(ctx, NULL, &got_len)) {
        t->err = "MAC_FINAL_LENGTH_ERROR";
        goto err;
    }
    if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
        t->err = "TEST_FAILURE";
        goto err;
    }
    if (!EVP_MAC_final(ctx, got, &got_len)
        || !memory_err_compare(t, "TEST_MAC_ERR",
                               expected->output, expected->output_len,
                               got, got_len)) {
        t->err = "TEST_MAC_ERR";
        goto err;
    }
    t->err = NULL;
 err:
    EVP_MAC_CTX_free(ctx);
    OPENSSL_free(got);
    return 1;
}

static int mac_test_run(EVP_TEST *t)
{
    MAC_DATA *expected = t->data;

    if (expected->mac != NULL)
        return mac_test_run_mac(t);
    return mac_test_run_pkey(t);
}

static const EVP_TEST_METHOD mac_test_method = {
    "MAC",
    mac_test_init,