X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=test%2Fevp_test.c;h=cad580e10cdb7ff59741595e863e613ee5b3539a;hp=3e237b014bb71b16ec277b4c5851c875ff4e2dd2;hb=0109e030db9207a47e195b4c3a3b13e9017f0ed2;hpb=f929439f61e7e4cf40e06de56880758b5344f198 diff --git a/test/evp_test.c b/test/evp_test.c index 3e237b014b..cad580e10c 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1,7 +1,7 @@ /* - * Copyright 2015-2017 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; @@ -74,6 +75,27 @@ static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst); static int parse_bin(const char *value, unsigned char **buf, size_t *buflen); +/* + * Compare two memory regions for equality, returning zero if they differ. + * However, if there is expected to be an error and the actual error + * matches then the memory is expected to be different so handle this + * case without producing unnecessary test framework output. + */ +static int memory_err_compare(EVP_TEST *t, const char *err, + const void *expected, size_t expected_len, + const void *got, size_t got_len) +{ + int r; + + if (t->expected_err != NULL && strcmp(t->expected_err, err) == 0) + r = !TEST_mem_ne(expected, expected_len, got, got_len); + else + r = TEST_mem_eq(expected, expected_len, got, got_len); + if (!r) + t->err = err; + return r; +} + /* * Structure used to hold a list of blocks of memory to test * calls to "update" like functions. @@ -397,10 +419,11 @@ static int digest_test_run(EVP_TEST *t) t->err = "DIGEST_LENGTH_MISMATCH"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "DIGEST_MISMATCH"; + if (!memory_err_compare(t, "DIGEST_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: @@ -435,9 +458,9 @@ typedef struct cipher_data_st { size_t plaintext_len; unsigned char *ciphertext; size_t ciphertext_len; - /* GCM, CCM 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; @@ -462,8 +485,9 @@ 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 = EVP_CIPHER_mode(cipher); + cdat->aead = m; else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) cdat->aead = -1; else @@ -475,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); } @@ -489,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); @@ -499,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); } @@ -523,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"; @@ -625,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); @@ -688,11 +724,9 @@ static int cipher_test_enc(EVP_TEST *t, int enc, t->err = "CIPHERFINAL_ERROR"; goto err; } - if (!TEST_mem_eq(expected_out, out_len, - tmp + out_misalign, tmplen + tmpflen)) { - t->err = "VALUE_MISMATCH"; + if (!memory_err_compare(t, "VALUE_MISMATCH", expected_out, out_len, + tmp + out_misalign, tmplen + tmpflen)) goto err; - } if (enc && expected->aead) { unsigned char rtag[16]; @@ -705,11 +739,10 @@ static int cipher_test_enc(EVP_TEST *t, int enc, t->err = "TAG_RETRIEVE_ERROR"; goto err; } - if (!TEST_mem_eq(expected->tag, expected->tag_len, - rtag, expected->tag_len)) { - t->err = "TAG_VALUE_MISMATCH"; + if (!memory_err_compare(t, "TAG_VALUE_MISMATCH", + expected->tag, expected->tag_len, + rtag, expected->tag_len)) goto err; - } } t->err = NULL; ok = 1; @@ -779,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; @@ -811,64 +845,112 @@ 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 */ 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; 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 (sz >= sizeof(epilogue) + && 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; } +/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */ +static void openssl_free(char *m) +{ + OPENSSL_free(m); +} + static void mac_test_cleanup(EVP_TEST *t) { MAC_DATA *mdat = t->data; + 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); } @@ -880,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) @@ -890,10 +978,35 @@ static int mac_test_parse(EVP_TEST *t, return parse_bin(value, &mdata->input, &mdata->input_len); if (strcmp(keyword, "Output") == 0) return parse_bin(value, &mdata->output, &mdata->output_len); + if (strcmp(keyword, "Ctrl") == 0) + return sk_OPENSSL_STRING_push(mdata->controls, + OPENSSL_strdup(value)) != 0; return 0; } -static int mac_test_run(EVP_TEST *t) +static int mac_test_ctrl_pkey(EVP_TEST *t, EVP_PKEY_CTX *pctx, + 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_PKEY_CTX_ctrl_str(pctx, tmpval, p); + if (rv == -2) + t->err = "PKEY_CTRL_INVALID"; + else if (rv <= 0) + t->err = "PKEY_CTRL_ERROR"; + else + rv = 1; + OPENSSL_free(tmpval); + return rv > 0; +} + +static int mac_test_run_pkey(EVP_TEST *t) { MAC_DATA *expected = t->data; EVP_MD_CTX *mctx = NULL; @@ -902,6 +1015,13 @@ static int mac_test_run(EVP_TEST *t) const EVP_MD *md = NULL; unsigned char *got = NULL; 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) { @@ -936,7 +1056,13 @@ static int mac_test_run(EVP_TEST *t) t->err = "DIGESTSIGNINIT_ERROR"; goto err; } - + for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) + if (!mac_test_ctrl_pkey(t, pctx, + sk_OPENSSL_STRING_value(expected->controls, + i))) { + t->err = "EVPPKEYCTXCTRL_ERROR"; + goto err; + } if (!EVP_DigestSignUpdate(mctx, expected->input, expected->input_len)) { t->err = "DIGESTSIGNUPDATE_ERROR"; goto err; @@ -950,8 +1076,9 @@ static int mac_test_run(EVP_TEST *t) goto err; } if (!EVP_DigestSignFinal(mctx, got, &got_len) - || !TEST_mem_eq(expected->output, expected->output_len, - 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; } @@ -964,6 +1091,161 @@ 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 (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 (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); + + 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_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; + } + 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, @@ -1108,10 +1390,11 @@ static int pkey_test_run(EVP_TEST *t) t->err = "KEYOP_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "KEYOP_MISMATCH"; + if (!memory_err_compare(t, "KEYOP_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); @@ -1226,10 +1509,10 @@ static int pderive_test_run(EVP_TEST *t) t->err = "DERIVE_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SHARED_SECRET_MISMATCH"; + if (!memory_err_compare(t, "SHARED_SECRET_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } t->err = NULL; err: @@ -1444,11 +1727,10 @@ static int pbe_test_run(EVP_TEST *t) goto err; } } - if (!TEST_mem_eq(expected->key, expected->key_len, - key, expected->key_len)) { - t->err = "KEY_MISMATCH"; + if (!memory_err_compare(t, "KEY_MISMATCH", expected->key, expected->key_len, + key, expected->key_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(key); @@ -1497,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) @@ -1534,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"; @@ -1542,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 = @@ -1550,20 +1834,19 @@ 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 (!TEST_mem_eq(expected->output, expected->output_len, - encode_out, output_len)) { - t->err = "BAD_ENCODING"; + if (!memory_err_compare(t, "BAD_ENCODING", + expected->output, expected->output_len, + encode_out, output_len)) goto err; - } } if (!TEST_ptr(decode_out = @@ -1585,8 +1868,9 @@ static int encode_test_run(EVP_TEST *t) output_len += chunk_len; if (expected->encoding != BASE64_INVALID_ENCODING - && !TEST_mem_eq(expected->input, expected->input_len, - decode_out, output_len)) { + && !memory_err_compare(t, "BAD_DECODING", + expected->input, expected->input_len, + decode_out, output_len)) { t->err = "BAD_DECODING"; goto err; } @@ -1596,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; } @@ -1607,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; @@ -1640,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; } @@ -1658,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, @@ -1669,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; } @@ -1683,14 +1999,15 @@ 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; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "KDF_MISMATCH"; + if (!memory_err_compare(t, "KDF_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: @@ -1707,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 **/ @@ -2079,11 +2496,12 @@ static int digestsign_test_run(EVP_TEST *t) t->err = "DIGESTSIGNFINAL_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SIGNATURE_MISMATCH"; + if (!memory_err_compare(t, "SIGNATURE_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); return 1; @@ -2156,11 +2574,12 @@ static int oneshot_digestsign_test_run(EVP_TEST *t) t->err = "DIGESTSIGN_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SIGNATURE_MISMATCH"; + if (!memory_err_compare(t, "SIGNATURE_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); return 1; @@ -2209,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, @@ -2378,7 +2798,7 @@ static void free_key_list(KEY_LIST *lst) /* * Is the key type an unsupported algorithm? */ -static int key_unsupported() +static int key_unsupported(void) { long err = ERR_peek_error(); @@ -2439,6 +2859,7 @@ top: if (strcmp(pp->key, "PrivateKey") == 0) { pkey = PEM_read_bio_PrivateKey(t->s.key, NULL, 0, NULL); if (pkey == NULL && !key_unsupported()) { + EVP_PKEY_free(pkey); TEST_info("Can't read private key %s", pp->value); TEST_openssl_errors(); return 0; @@ -2447,6 +2868,7 @@ top: } else if (strcmp(pp->key, "PublicKey") == 0) { pkey = PEM_read_bio_PUBKEY(t->s.key, NULL, 0, NULL); if (pkey == NULL && !key_unsupported()) { + EVP_PKEY_free(pkey); TEST_info("Can't read public key %s", pp->value); TEST_openssl_errors(); return 0; @@ -2489,7 +2911,7 @@ top: pkey = EVP_PKEY_new_raw_private_key(nid, NULL, keybin, keylen); else pkey = EVP_PKEY_new_raw_public_key(nid, NULL, keybin, keylen); - if (pkey == NULL) { + if (pkey == NULL && !key_unsupported()) { TEST_info("Can't read %s data", pp->key); OPENSSL_free(keybin); TEST_openssl_errors(); @@ -2507,6 +2929,17 @@ top: if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key)))) return 0; key->name = take_value(pp); + + /* Hack to detect SM2 keys */ + if(pkey != NULL && strstr(key->name, "SM2") != NULL) { +#ifdef OPENSSL_NO_SM2 + EVP_PKEY_free(pkey); + pkey = NULL; +#else + EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); +#endif + } + key->key = pkey; key->next = *klist; *klist = key; @@ -2557,8 +2990,8 @@ top: return 0; } if (rv < 0) { - TEST_info("Line %d: error processing keyword %s\n", - t->s.curr, pp->key); + TEST_info("Line %d: error processing keyword %s = %s\n", + t->s.curr, pp->key, pp->value); return 0; } } @@ -2600,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;