From b565a17d9fc69711813a19723a3f656ae5cd2fc9 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 1 Oct 2020 15:34:24 +0100 Subject: Add a test for encoding and decoding of parameters files Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/13050) --- test/endecode_test.c | 199 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 167 insertions(+), 32 deletions(-) (limited to 'test/endecode_test.c') diff --git a/test/endecode_test.c b/test/endecode_test.c index 70258afcc0..b882ff85b1 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -93,18 +93,21 @@ typedef int (encoder)(void **encoded, long *encoded_len, void *object, const char *output_type, int selection, const char *pass, const char *pcipher); typedef int (decoder)(void **object, void *encoded, long encoded_len, - const char *pass); + const char *keytype, const char *input_type, + int selection, const char *pass); typedef int (tester)(const void *data1, size_t data1_len, const void *data2, size_t data2_len); typedef int (checker)(const char *type, const void *data, size_t data_len); typedef void (dumper)(const char *label, const void *data, size_t data_len); +#define FLAG_DECODE_WITH_TYPE 0x0001 + static int test_encode_decode(const char *type, EVP_PKEY *pkey, const char *output_type, int selection, const char *pass, const char *pcipher, encoder *encode_cb, decoder *decode_cb, tester *test_cb, checker *check_cb, - dumper *dump_cb) + dumper *dump_cb, int flags) { void *encoded = NULL; long encoded_len = 0; @@ -118,16 +121,23 @@ static int test_encode_decode(const char *type, EVP_PKEY *pkey, * encoding |pkey2| as well. That last encoding is for checking and * dumping purposes. */ - if (!encode_cb(&encoded, &encoded_len, pkey, output_type, selection, - pass, pcipher) - || !check_cb(type, encoded, encoded_len) - || !decode_cb((void **)&pkey2, encoded, encoded_len, pass) - || !encode_cb(&encoded2, &encoded2_len, pkey2, output_type, selection, - pass, pcipher)) + if (!TEST_true(encode_cb(&encoded, &encoded_len, pkey, output_type, + selection, pass, pcipher)) + || !TEST_true(check_cb(type, encoded, encoded_len)) + || !TEST_true(decode_cb((void **)&pkey2, encoded, encoded_len, + (flags & FLAG_DECODE_WITH_TYPE ? type : NULL), + output_type, selection, pass)) + || !TEST_true(encode_cb(&encoded2, &encoded2_len, pkey2, output_type, + selection, pass, pcipher))) goto end; - if (!TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1)) - goto end; + if (selection == OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) { + if (!TEST_int_eq(EVP_PKEY_parameters_eq(pkey, pkey2), 1)) + goto end; + } else { + if (!TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1)) + goto end; + } /* * Double check the encoding, but only for unprotected keys, @@ -193,25 +203,71 @@ static int encode_EVP_PKEY_prov(void **encoded, long *encoded_len, } static int decode_EVP_PKEY_prov(void **object, void *encoded, long encoded_len, - const char *pass) + const char *keytype, const char *input_type, + int selection, const char *pass) { - EVP_PKEY *pkey = NULL; + EVP_PKEY *pkey = NULL, *testpkey = NULL; OSSL_DECODER_CTX *dctx = NULL; - BIO *mem_deser = NULL; + BIO *encoded_bio = NULL; const unsigned char *upass = (const unsigned char *)pass; int ok = 0; + int i; + const char *badtype; - if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&pkey, NULL, NULL, - NULL, NULL)) - || (pass != NULL - && !OSSL_DECODER_CTX_set_passphrase(dctx, upass, strlen(pass))) - || !TEST_ptr(mem_deser = BIO_new_mem_buf(encoded, encoded_len)) - || !TEST_true(OSSL_DECODER_from_bio(dctx, mem_deser))) + if (strcmp(input_type, "DER") == 0) + badtype = "PEM"; + else + badtype = "DER"; + + if (!TEST_ptr(encoded_bio = BIO_new_mem_buf(encoded, encoded_len))) goto end; + + /* + * We attempt the decode 3 times. The first time we provide the expected + * starting input type. The second time we provide NULL for the starting + * type. The third time we provide a bad starting input type. + * The bad starting input type should fail. The other two should succeed + * and produce the same result. + */ + for (i = 0; i < 3; i++) { + const char *testtype = (i == 0) ? input_type + : ((i == 1) ? NULL : badtype); + + if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&testpkey, + testtype, + keytype, + NULL, NULL)) + || (pass != NULL + && !OSSL_DECODER_CTX_set_passphrase(dctx, upass, strlen(pass))) + || !TEST_int_gt(BIO_reset(encoded_bio), 0) + /* We expect to fail when using a bad input type */ + || !TEST_int_eq(OSSL_DECODER_from_bio(dctx, encoded_bio), + (i == 2) ? 0 : 1)) + goto end; + OSSL_DECODER_CTX_free(dctx); + dctx = NULL; + + if (i == 0) { + pkey = testpkey; + testpkey = NULL; + } else if (i == 1) { + if (selection == OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) { + if (!TEST_int_eq(EVP_PKEY_parameters_eq(pkey, testpkey), 1)) + goto end; + } else { + if (!TEST_int_eq(EVP_PKEY_eq(pkey, testpkey), 1)) + goto end; + } + } + } ok = 1; *object = pkey; + pkey = NULL; + end: - BIO_free(mem_deser); + EVP_PKEY_free(pkey); + EVP_PKEY_free(testpkey); + BIO_free(encoded_bio); OSSL_DECODER_CTX_free(dctx); return ok; } @@ -433,7 +489,7 @@ static int test_unprotected_via_DER(const char *type, EVP_PKEY *key) NULL, NULL, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, test_mem, check_unprotected_PKCS8_DER, - dump_der); + dump_der, 0); } static int check_unprotected_PKCS8_PEM(const char *type, @@ -454,7 +510,64 @@ static int test_unprotected_via_PEM(const char *type, EVP_PKEY *key) NULL, NULL, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, test_text, check_unprotected_PKCS8_PEM, - dump_pem); + dump_pem, 0); +} + +static int check_params_DER(const char *type, const void *data, size_t data_len) +{ + const unsigned char *datap = data; + int ok = 0; + int itype = NID_undef; + EVP_PKEY *pkey = NULL; + + if (strcmp(type, "DH") == 0) + itype = EVP_PKEY_DH; + else if (strcmp(type, "X9.42 DH") == 0) + itype = EVP_PKEY_DHX; + else if (strcmp(type, "DSA") == 0) + itype = EVP_PKEY_DSA; + else if (strcmp(type, "EC") == 0) + itype = EVP_PKEY_EC; + + if (itype != NID_undef) { + pkey = d2i_KeyParams(itype, NULL, &datap, data_len); + ok = (pkey != NULL); + EVP_PKEY_free(pkey); + } + + return ok; +} + +static int check_params_PEM(const char *type, + const void *data, size_t data_len) +{ + static char expected_pem_header[80]; + + return + TEST_int_gt(BIO_snprintf(expected_pem_header, + sizeof(expected_pem_header), + "-----BEGIN %s PARAMETERS-----", type), 0) + && TEST_strn_eq(data, expected_pem_header, strlen(expected_pem_header)); +} + +static int test_params_via_DER(const char *type, EVP_PKEY *key) +{ + return test_encode_decode(type, key, + "DER", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + NULL, NULL, + encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, + test_mem, check_params_DER, + dump_der, FLAG_DECODE_WITH_TYPE); +} + +static int test_params_via_PEM(const char *type, EVP_PKEY *key) +{ + return test_encode_decode(type, key, + "PEM", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + NULL, NULL, + encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, + test_text, check_params_PEM, + dump_pem, 0); } static int check_unprotected_legacy_PEM(const char *type, @@ -477,7 +590,7 @@ static int test_unprotected_via_legacy_PEM(const char *type, EVP_PKEY *key) NULL, NULL, encode_EVP_PKEY_legacy_PEM, decode_EVP_PKEY_prov, test_text, check_unprotected_legacy_PEM, - dump_pem); + dump_pem, 0); } #ifndef OPENSSL_NO_DSA @@ -499,7 +612,7 @@ static int test_unprotected_via_MSBLOB(const char *type, EVP_PKEY *key) NULL, NULL, encode_EVP_PKEY_MSBLOB, decode_EVP_PKEY_prov, test_mem, check_MSBLOB, - dump_der); + dump_der, 0); } # ifndef OPENSSL_NO_RC4 @@ -520,7 +633,7 @@ static int test_unprotected_via_PVK(const char *type, EVP_PKEY *key) NULL, NULL, encode_EVP_PKEY_PVK, decode_EVP_PKEY_prov, test_mem, check_PVK, - dump_der); + dump_der, 0); } # endif #endif @@ -547,7 +660,7 @@ static int test_protected_via_DER(const char *type, EVP_PKEY *key) pass, pass_cipher, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, test_mem, check_protected_PKCS8_DER, - dump_der); + dump_der, 0); } static int check_protected_PKCS8_PEM(const char *type, @@ -568,7 +681,7 @@ static int test_protected_via_PEM(const char *type, EVP_PKEY *key) pass, pass_cipher, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, test_text, check_protected_PKCS8_PEM, - dump_pem); + dump_pem, 0); } static int check_protected_legacy_PEM(const char *type, @@ -592,7 +705,7 @@ static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key) pass, pass_cipher, encode_EVP_PKEY_legacy_PEM, decode_EVP_PKEY_prov, test_text, check_protected_legacy_PEM, - dump_pem); + dump_pem, 0); } #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) @@ -603,7 +716,7 @@ static int test_protected_via_PVK(const char *type, EVP_PKEY *key) | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, pass, NULL, encode_EVP_PKEY_PVK, decode_EVP_PKEY_prov, - test_mem, check_PVK, dump_der); + test_mem, check_PVK, dump_der, 0); } #endif @@ -624,7 +737,7 @@ static int test_public_via_DER(const char *type, EVP_PKEY *key) | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, NULL, NULL, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, - test_mem, check_public_DER, dump_der); + test_mem, check_public_DER, dump_der, 0); } static int check_public_PEM(const char *type, const void *data, size_t data_len) @@ -644,7 +757,7 @@ static int test_public_via_PEM(const char *type, EVP_PKEY *key) | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, NULL, NULL, encode_EVP_PKEY_prov, decode_EVP_PKEY_prov, - test_text, check_public_PEM, dump_pem); + test_text, check_public_PEM, dump_pem, 0); } #ifndef OPENSSL_NO_DSA @@ -667,7 +780,7 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) NULL, NULL, encode_public_EVP_PKEY_MSBLOB, decode_EVP_PKEY_prov, - test_mem, check_public_MSBLOB, dump_der); + test_mem, check_public_MSBLOB, dump_der, 0); } #endif @@ -726,6 +839,20 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) ADD_TEST(test_public_##KEYTYPE##_via_DER); \ ADD_TEST(test_public_##KEYTYPE##_via_PEM) +#define IMPLEMENT_TEST_SUITE_PARAMS(KEYTYPE, KEYTYPEstr) \ + static int test_params_##KEYTYPE##_via_DER(void) \ + { \ + return test_params_via_DER(KEYTYPEstr, key_##KEYTYPE); \ + } \ + static int test_params_##KEYTYPE##_via_PEM(void) \ + { \ + return test_params_via_PEM(KEYTYPEstr, key_##KEYTYPE); \ + } + +#define ADD_TEST_SUITE_PARAMS(KEYTYPE) \ + ADD_TEST(test_params_##KEYTYPE##_via_DER); \ + ADD_TEST(test_params_##KEYTYPE##_via_PEM) + #define IMPLEMENT_TEST_SUITE_LEGACY(KEYTYPE, KEYTYPEstr) \ static int test_unprotected_##KEYTYPE##_via_legacy_PEM(void) \ { \ @@ -777,8 +904,10 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) #ifndef OPENSSL_NO_DH DOMAIN_KEYS(DH); IMPLEMENT_TEST_SUITE(DH, "DH") +IMPLEMENT_TEST_SUITE_PARAMS(DH, "DH") DOMAIN_KEYS(DHX); IMPLEMENT_TEST_SUITE(DHX, "X9.42 DH") +IMPLEMENT_TEST_SUITE_PARAMS(DHX, "X9.42 DH") /* * DH has no support for PEM_write_bio_PrivateKey_traditional(), * so no legacy tests. @@ -787,6 +916,7 @@ IMPLEMENT_TEST_SUITE(DHX, "X9.42 DH") #ifndef OPENSSL_NO_DSA DOMAIN_KEYS(DSA); IMPLEMENT_TEST_SUITE(DSA, "DSA") +IMPLEMENT_TEST_SUITE_PARAMS(DSA, "DSA") IMPLEMENT_TEST_SUITE_LEGACY(DSA, "DSA") IMPLEMENT_TEST_SUITE_MSBLOB(DSA, "DSA") # ifndef OPENSSL_NO_RC4 @@ -796,6 +926,7 @@ IMPLEMENT_TEST_SUITE_PVK(DSA, "DSA") #ifndef OPENSSL_NO_EC DOMAIN_KEYS(EC); IMPLEMENT_TEST_SUITE(EC, "EC") +IMPLEMENT_TEST_SUITE_PARAMS(EC, "EC") IMPLEMENT_TEST_SUITE_LEGACY(EC, "EC") DOMAIN_KEYS(ECExplicitPrimeNamedCurve); IMPLEMENT_TEST_SUITE(ECExplicitPrimeNamedCurve, "EC") @@ -1101,7 +1232,9 @@ int setup_tests(void) if (ok) { #ifndef OPENSSL_NO_DH ADD_TEST_SUITE(DH); + ADD_TEST_SUITE_PARAMS(DH); ADD_TEST_SUITE(DHX); + ADD_TEST_SUITE_PARAMS(DHX); /* * DH has no support for PEM_write_bio_PrivateKey_traditional(), * so no legacy tests. @@ -1109,6 +1242,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_DSA ADD_TEST_SUITE(DSA); + ADD_TEST_SUITE_PARAMS(DSA); ADD_TEST_SUITE_LEGACY(DSA); ADD_TEST_SUITE_MSBLOB(DSA); # ifndef OPENSSL_NO_RC4 @@ -1117,6 +1251,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_EC ADD_TEST_SUITE(EC); + ADD_TEST_SUITE_PARAMS(EC); ADD_TEST_SUITE_LEGACY(EC); ADD_TEST_SUITE(ECExplicitPrimeNamedCurve); ADD_TEST_SUITE_LEGACY(ECExplicitPrimeNamedCurve); -- cgit v1.2.3