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 <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7393)
This commit is contained in:
Richard Levitte 2018-10-24 18:36:31 +02:00
parent 5e55159b3a
commit 2bdb4af503

View File

@ -832,8 +832,9 @@ static const EVP_TEST_METHOD cipher_test_method = {
**/ **/
typedef struct mac_data_st { typedef struct mac_data_st {
/* MAC type */ /* MAC type in one form or another */
int type; const EVP_MAC *mac; /* for mac_test_run_mac */
int type; /* for mac_test_run_pkey */
/* Algorithm string for this MAC */ /* Algorithm string for this MAC */
char *alg; char *alg;
/* MAC key */ /* MAC key */
@ -851,37 +852,62 @@ typedef struct mac_data_st {
static int mac_test_init(EVP_TEST *t, const char *alg) 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; MAC_DATA *mdat;
if (strcmp(alg, "HMAC") == 0) { if ((mac = EVP_get_macbyname(alg)) == NULL) {
type = EVP_PKEY_HMAC; /*
} else if (strcmp(alg, "CMAC") == 0) { * 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 #ifndef OPENSSL_NO_CMAC
type = EVP_PKEY_CMAC; type = EVP_PKEY_CMAC;
#else #else
t->skip = 1; t->skip = 1;
return 1; return 1;
#endif #endif
} else if (strcmp(alg, "Poly1305") == 0) { } else if (strncmp(alg, "Poly1305", sz) == 0) {
#ifndef OPENSSL_NO_POLY1305 #ifndef OPENSSL_NO_POLY1305
type = EVP_PKEY_POLY1305; type = EVP_PKEY_POLY1305;
#else #else
t->skip = 1; t->skip = 1;
return 1; return 1;
#endif #endif
} else if (strcmp(alg, "SipHash") == 0) { } else if (strncmp(alg, "SipHash", sz) == 0) {
#ifndef OPENSSL_NO_SIPHASH #ifndef OPENSSL_NO_SIPHASH
type = EVP_PKEY_SIPHASH; type = EVP_PKEY_SIPHASH;
#else #else
t->skip = 1; t->skip = 1;
return 1; return 1;
#endif #endif
} else } else {
return 0; /*
* 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 = OPENSSL_zalloc(sizeof(*mdat));
mdat->type = type; mdat->type = type;
mdat->mac = mac;
mdat->controls = sk_OPENSSL_STRING_new_null(); mdat->controls = sk_OPENSSL_STRING_new_null();
t->data = mdat; t->data = mdat;
return 1; return 1;
@ -927,7 +953,7 @@ static int mac_test_parse(EVP_TEST *t,
return 0; return 0;
} }
static int mac_test_run(EVP_TEST *t) static int mac_test_run_pkey(EVP_TEST *t)
{ {
MAC_DATA *expected = t->data; MAC_DATA *expected = t->data;
EVP_MD_CTX *mctx = NULL; EVP_MD_CTX *mctx = NULL;
@ -938,6 +964,12 @@ static int mac_test_run(EVP_TEST *t)
size_t got_len; size_t got_len;
int i; 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 #ifdef OPENSSL_NO_DES
if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) { if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
/* Skip DES */ /* Skip DES */
@ -1005,6 +1037,126 @@ static int mac_test_run(EVP_TEST *t)
return 1; 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 = { static const EVP_TEST_METHOD mac_test_method = {
"MAC", "MAC",
mac_test_init, mac_test_init,