X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=test%2Fevp_test.c;h=cad580e10cdb7ff59741595e863e613ee5b3539a;hp=311814b1bd6d22b03cde022abd88ad403df93789;hb=0109e030db9207a47e195b4c3a3b13e9017f0ed2;hpb=ce5d64c79c4d809ece8fe28a5b62915467a1c0e1 diff --git a/test/evp_test.c b/test/evp_test.c index 311814b1bd..cad580e10c 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1,7 +1,7 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -21,6 +21,7 @@ #include "testutil.h" #include "evp_test.h" +#define AAD_NUM 4 typedef struct evp_test_method_st EVP_TEST_METHOD; @@ -457,9 +458,9 @@ typedef struct cipher_data_st { size_t plaintext_len; unsigned char *ciphertext; size_t ciphertext_len; - /* GCM, CCM and OCB only */ - unsigned char *aad; - size_t aad_len; + /* GCM, CCM, OCB and SIV only */ + unsigned char *aad[AAD_NUM]; + size_t aad_len[AAD_NUM]; unsigned char *tag; size_t tag_len; } CIPHER_DATA; @@ -484,6 +485,7 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) m = EVP_CIPHER_mode(cipher); if (m == EVP_CIPH_GCM_MODE || m == EVP_CIPH_OCB_MODE + || m == EVP_CIPH_SIV_MODE || m == EVP_CIPH_CCM_MODE) cdat->aead = m; else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) @@ -497,13 +499,15 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) static void cipher_test_cleanup(EVP_TEST *t) { + int i; CIPHER_DATA *cdat = t->data; OPENSSL_free(cdat->key); OPENSSL_free(cdat->iv); OPENSSL_free(cdat->ciphertext); OPENSSL_free(cdat->plaintext); - OPENSSL_free(cdat->aad); + for (i = 0; i < AAD_NUM; i++) + OPENSSL_free(cdat->aad[i]); OPENSSL_free(cdat->tag); } @@ -511,6 +515,7 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword, const char *value) { CIPHER_DATA *cdat = t->data; + int i; if (strcmp(keyword, "Key") == 0) return parse_bin(value, &cdat->key, &cdat->key_len); @@ -521,8 +526,13 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword, if (strcmp(keyword, "Ciphertext") == 0) return parse_bin(value, &cdat->ciphertext, &cdat->ciphertext_len); if (cdat->aead) { - if (strcmp(keyword, "AAD") == 0) - return parse_bin(value, &cdat->aad, &cdat->aad_len); + if (strcmp(keyword, "AAD") == 0) { + for (i = 0; i < AAD_NUM; i++) { + if (cdat->aad[i] == NULL) + return parse_bin(value, &cdat->aad[i], &cdat->aad_len[i]); + } + return 0; + } if (strcmp(keyword, "Tag") == 0) return parse_bin(value, &cdat->tag, &cdat->tag_len); } @@ -545,7 +555,7 @@ static int cipher_test_enc(EVP_TEST *t, int enc, CIPHER_DATA *expected = t->data; unsigned char *in, *expected_out, *tmp = NULL; size_t in_len, out_len, donelen = 0; - int ok = 0, tmplen, chunklen, tmpflen; + int ok = 0, tmplen, chunklen, tmpflen, i; EVP_CIPHER_CTX *ctx = NULL; t->err = "TEST_FAILURE"; @@ -647,32 +657,36 @@ static int cipher_test_enc(EVP_TEST *t, int enc, goto err; } } - if (expected->aad) { + if (expected->aad[0] != NULL) { t->err = "AAD_SET_ERROR"; if (!frag) { - if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad, - expected->aad_len)) - goto err; + for (i = 0; expected->aad[i] != NULL; i++) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], + expected->aad_len[i])) + goto err; + } } else { /* * Supply the AAD in chunks less than the block size where possible */ - if (expected->aad_len > 0) { - if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad, 1)) - goto err; - donelen++; - } - if (expected->aad_len > 2) { - if (!EVP_CipherUpdate(ctx, NULL, &chunklen, - expected->aad + donelen, - expected->aad_len - 2)) + for (i = 0; expected->aad[i] != NULL; i++) { + if (expected->aad_len[i] > 0) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], 1)) + goto err; + donelen++; + } + if (expected->aad_len[i] > 2) { + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, + expected->aad[i] + donelen, + expected->aad_len[i] - 2)) + goto err; + donelen += expected->aad_len[i] - 2; + } + if (expected->aad_len[i] > 1 + && !EVP_CipherUpdate(ctx, NULL, &chunklen, + expected->aad[i] + donelen, 1)) goto err; - donelen += expected->aad_len - 2; } - if (expected->aad_len > 1 - && !EVP_CipherUpdate(ctx, NULL, &chunklen, - expected->aad + donelen, 1)) - goto err; } } EVP_CIPHER_CTX_set_padding(ctx, 0); @@ -798,10 +812,11 @@ static int cipher_test_run(EVP_TEST *t) if (out_misalign == 1 && frag == 0) { /* - * XTS, CCM and Wrap modes have special requirements about input + * XTS, SIV, 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_SIV_MODE || EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_XTS_MODE || EVP_CIPHER_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) break; @@ -838,12 +853,20 @@ typedef struct mac_data_st { /* MAC key */ unsigned char *key; size_t key_len; + /* MAC IV (GMAC) */ + unsigned char *iv; + size_t iv_len; /* Input to MAC */ unsigned char *input; size_t input_len; /* Expected output */ unsigned char *output; size_t output_len; + unsigned char *custom; + size_t custom_len; + /* MAC salt (blake2) */ + unsigned char *salt; + size_t salt_len; /* Collection of controls */ STACK_OF(OPENSSL_STRING) *controls; } MAC_DATA; @@ -863,7 +886,8 @@ static int mac_test_init(EVP_TEST *t, const char *alg) size_t sz = strlen(alg); static const char epilogue[] = " by EVP_PKEY"; - if (strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0) + if (sz >= sizeof(epilogue) + && strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0) sz -= sizeof(epilogue) - 1; if (strncmp(alg, "HMAC", sz) == 0) { @@ -924,6 +948,9 @@ static void mac_test_cleanup(EVP_TEST *t) sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free); OPENSSL_free(mdat->alg); OPENSSL_free(mdat->key); + OPENSSL_free(mdat->iv); + OPENSSL_free(mdat->custom); + OPENSSL_free(mdat->salt); OPENSSL_free(mdat->input); OPENSSL_free(mdat->output); } @@ -935,6 +962,12 @@ static int mac_test_parse(EVP_TEST *t, if (strcmp(keyword, "Key") == 0) return parse_bin(value, &mdata->key, &mdata->key_len); + if (strcmp(keyword, "IV") == 0) + return parse_bin(value, &mdata->iv, &mdata->iv_len); + if (strcmp(keyword, "Custom") == 0) + return parse_bin(value, &mdata->custom, &mdata->custom_len); + if (strcmp(keyword, "Salt") == 0) + return parse_bin(value, &mdata->salt, &mdata->salt_len); if (strcmp(keyword, "Algorithm") == 0) { mdata->alg = OPENSSL_strdup(value); if (!mdata->alg) @@ -1117,11 +1150,42 @@ static int mac_test_run_mac(EVP_TEST *t) t->err = "MAC_CTRL_ERROR"; goto err; } + if (expected->custom != NULL) { + rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, + expected->custom, expected->custom_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; + if (expected->salt != NULL) { + rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SALT, + expected->salt, expected->salt_len); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } } + + if (expected->iv != NULL) { + rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_IV, + expected->iv, expected->iv_len); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_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); @@ -1143,6 +1207,10 @@ static int mac_test_run_mac(EVP_TEST *t) goto err; } } + if (!EVP_MAC_init(ctx)) { + t->err = "MAC_INIT_ERROR"; + goto err; + } if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) { t->err = "MAC_UPDATE_ERROR"; goto err; @@ -1711,15 +1779,18 @@ static int encode_test_init(EVP_TEST *t, const char *encoding) } else if (strcmp(encoding, "invalid") == 0) { edata->encoding = BASE64_INVALID_ENCODING; if (!TEST_ptr(t->expected_err = OPENSSL_strdup("DECODE_ERROR"))) - return 0; + goto err; } else { TEST_error("Bad encoding: %s." " Should be one of {canonical, valid, invalid}", encoding); - return 0; + goto err; } t->data = edata; return 1; +err: + OPENSSL_free(edata); + return 0; } static void encode_test_cleanup(EVP_TEST *t) @@ -1748,7 +1819,7 @@ static int encode_test_run(EVP_TEST *t) ENCODE_DATA *expected = t->data; unsigned char *encode_out = NULL, *decode_out = NULL; int output_len, chunk_len; - EVP_ENCODE_CTX *decode_ctx; + EVP_ENCODE_CTX *decode_ctx = NULL, *encode_ctx = NULL; if (!TEST_ptr(decode_ctx = EVP_ENCODE_CTX_new())) { t->err = "INTERNAL_ERROR"; @@ -1756,7 +1827,6 @@ static int encode_test_run(EVP_TEST *t) } if (expected->encoding == BASE64_CANONICAL_ENCODING) { - EVP_ENCODE_CTX *encode_ctx; if (!TEST_ptr(encode_ctx = EVP_ENCODE_CTX_new()) || !TEST_ptr(encode_out = @@ -1764,15 +1834,15 @@ static int encode_test_run(EVP_TEST *t) goto err; EVP_EncodeInit(encode_ctx); - EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, - expected->input, expected->input_len); + if (!TEST_true(EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, + expected->input, expected->input_len))) + goto err; + output_len = chunk_len; EVP_EncodeFinal(encode_ctx, encode_out + chunk_len, &chunk_len); output_len += chunk_len; - EVP_ENCODE_CTX_free(encode_ctx); - if (!memory_err_compare(t, "BAD_ENCODING", expected->output, expected->output_len, encode_out, output_len)) @@ -1810,6 +1880,7 @@ static int encode_test_run(EVP_TEST *t) OPENSSL_free(encode_out); OPENSSL_free(decode_out); EVP_ENCODE_CTX_free(decode_ctx); + EVP_ENCODE_CTX_free(encode_ctx); return 1; } @@ -1821,13 +1892,14 @@ static const EVP_TEST_METHOD encode_test_method = { encode_test_run, }; + /** *** KDF TESTS **/ typedef struct kdf_data_st { /* Context for this operation */ - EVP_PKEY_CTX *ctx; + EVP_KDF_CTX *ctx; /* Expected output */ unsigned char *output; size_t output_len; @@ -1854,16 +1926,11 @@ static int kdf_test_init(EVP_TEST *t, const char *name) if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))) return 0; - kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL); + kdata->ctx = EVP_KDF_CTX_new_id(kdf_nid); if (kdata->ctx == NULL) { OPENSSL_free(kdata); return 0; } - if (EVP_PKEY_derive_init(kdata->ctx) <= 0) { - EVP_PKEY_CTX_free(kdata->ctx); - OPENSSL_free(kdata); - return 0; - } t->data = kdata; return 1; } @@ -1872,7 +1939,42 @@ static void kdf_test_cleanup(EVP_TEST *t) { KDF_DATA *kdata = t->data; OPENSSL_free(kdata->output); - EVP_PKEY_CTX_free(kdata->ctx); + EVP_KDF_CTX_free(kdata->ctx); +} + +static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx, + const char *value) +{ + int rv; + char *p, *tmpval; + + if (!TEST_ptr(tmpval = OPENSSL_strdup(value))) + return 0; + p = strchr(tmpval, ':'); + if (p != NULL) + *p++ = '\0'; + rv = EVP_KDF_ctrl_str(kctx, tmpval, p); + if (rv == -2) { + t->err = "KDF_CTRL_INVALID"; + rv = 1; + } else if (p != NULL && rv <= 0) { + /* If p has an OID and lookup fails assume disabled algorithm */ + int nid = OBJ_sn2nid(p); + + if (nid == NID_undef) + nid = OBJ_ln2nid(p); + if (nid != NID_undef + && EVP_get_digestbynid(nid) == NULL + && EVP_get_cipherbynid(nid) == NULL) { + t->skip = 1; + rv = 1; + } else { + t->err = "KDF_CTRL_ERROR"; + rv = 1; + } + } + OPENSSL_free(tmpval); + return rv > 0; } static int kdf_test_parse(EVP_TEST *t, @@ -1883,7 +1985,7 @@ static int kdf_test_parse(EVP_TEST *t, if (strcmp(keyword, "Output") == 0) return parse_bin(value, &kdata->output, &kdata->output_len); if (strncmp(keyword, "Ctrl", 4) == 0) - return pkey_test_ctrl(t, kdata->ctx, value); + return kdf_test_ctrl(t, kdata->ctx, value); return 0; } @@ -1897,7 +1999,7 @@ static int kdf_test_run(EVP_TEST *t) t->err = "INTERNAL_ERROR"; goto err; } - if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) { + if (EVP_KDF_derive(expected->ctx, got, got_len) <= 0) { t->err = "KDF_DERIVE_ERROR"; goto err; } @@ -1922,6 +2024,106 @@ static const EVP_TEST_METHOD kdf_test_method = { }; +/** +*** PKEY KDF TESTS +**/ + +typedef struct pkey_kdf_data_st { + /* Context for this operation */ + EVP_PKEY_CTX *ctx; + /* Expected output */ + unsigned char *output; + size_t output_len; +} PKEY_KDF_DATA; + +/* + * Perform public key operation setup: lookup key, allocated ctx and call + * the appropriate initialisation function + */ +static int pkey_kdf_test_init(EVP_TEST *t, const char *name) +{ + PKEY_KDF_DATA *kdata; + int kdf_nid = OBJ_sn2nid(name); + +#ifdef OPENSSL_NO_SCRYPT + if (strcmp(name, "scrypt") == 0) { + t->skip = 1; + return 1; + } +#endif + + if (kdf_nid == NID_undef) + kdf_nid = OBJ_ln2nid(name); + + if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))) + return 0; + kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL); + if (kdata->ctx == NULL) { + OPENSSL_free(kdata); + return 0; + } + if (EVP_PKEY_derive_init(kdata->ctx) <= 0) { + EVP_PKEY_CTX_free(kdata->ctx); + OPENSSL_free(kdata); + return 0; + } + t->data = kdata; + return 1; +} + +static void pkey_kdf_test_cleanup(EVP_TEST *t) +{ + PKEY_KDF_DATA *kdata = t->data; + OPENSSL_free(kdata->output); + EVP_PKEY_CTX_free(kdata->ctx); +} + +static int pkey_kdf_test_parse(EVP_TEST *t, + const char *keyword, const char *value) +{ + PKEY_KDF_DATA *kdata = t->data; + + if (strcmp(keyword, "Output") == 0) + return parse_bin(value, &kdata->output, &kdata->output_len); + if (strncmp(keyword, "Ctrl", 4) == 0) + return pkey_test_ctrl(t, kdata->ctx, value); + return 0; +} + +static int pkey_kdf_test_run(EVP_TEST *t) +{ + PKEY_KDF_DATA *expected = t->data; + unsigned char *got = NULL; + size_t got_len = expected->output_len; + + if (!TEST_ptr(got = OPENSSL_malloc(got_len))) { + t->err = "INTERNAL_ERROR"; + goto err; + } + if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) { + t->err = "KDF_DERIVE_ERROR"; + goto err; + } + if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { + t->err = "KDF_MISMATCH"; + goto err; + } + t->err = NULL; + + err: + OPENSSL_free(got); + return 1; +} + +static const EVP_TEST_METHOD pkey_kdf_test_method = { + "PKEYKDF", + pkey_kdf_test_init, + pkey_kdf_test_cleanup, + pkey_kdf_test_parse, + pkey_kdf_test_run +}; + + /** *** KEYPAIR TESTS **/ @@ -2426,6 +2628,7 @@ static const EVP_TEST_METHOD *evp_test_list[] = { &digestverify_test_method, &encode_test_method, &kdf_test_method, + &pkey_kdf_test_method, &keypair_test_method, &keygen_test_method, &mac_test_method, @@ -2830,14 +3033,14 @@ static int run_file_tests(int i) return c == 0; } +OPT_TEST_DECLARE_USAGE("file...\n") + int setup_tests(void) { size_t n = test_get_argument_count(); - if (n == 0) { - TEST_error("Usage: %s file...", test_get_program_name()); + if (n == 0) return 0; - } ADD_ALL_TESTS(run_file_tests, n); return 1;