From 2bdb4af50364121a5f0e47024e9f71e1a6025fcf Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 24 Oct 2018 18:36:31 +0200 Subject: [PATCH] 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: Paul Dale (Merged from https://github.com/openssl/openssl/pull/7393) --- test/evp_test.c | 192 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 172 insertions(+), 20 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 2ac69e11da..be18afb63d 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -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) { - type = EVP_PKEY_HMAC; - } else if (strcmp(alg, "CMAC") == 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 (strncmp(alg, "CMAC", sz) == 0) { #ifndef OPENSSL_NO_CMAC - type = EVP_PKEY_CMAC; + type = EVP_PKEY_CMAC; #else - t->skip = 1; - return 1; + 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; + type = EVP_PKEY_POLY1305; #else - t->skip = 1; - return 1; + 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; + type = EVP_PKEY_SIPHASH; #else - t->skip = 1; - return 1; + t->skip = 1; + return 1; #endif - } else - return 0; + } 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, -- 2.25.1