diff --git a/src/wp_dh_kmgmt.c b/src/wp_dh_kmgmt.c index 442f1c40..a714f1b7 100644 --- a/src/wp_dh_kmgmt.c +++ b/src/wp_dh_kmgmt.c @@ -1498,6 +1498,11 @@ static int wp_dh_export(wp_Dh *dh, int selection, OSSL_CALLBACK *paramCb, if (ok && (dh == NULL)) { ok = 0; } + /* Nothing to export when the key has no domain parameters. */ + if (ok && ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) && + (!wp_dh_has(dh, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS))) { + ok = 0; + } if (ok) { XMEMSET(params, 0, sizeof(params)); @@ -1506,9 +1511,12 @@ static int wp_dh_export(wp_Dh *dh, int selection, OSSL_CALLBACK *paramCb, sz += wp_dh_export_group_alloc_size(dh); } - data = OPENSSL_secure_malloc(sz); - if (data == NULL) { - ok = 0; + /* Named group parameters need no buffer - zero size is valid. */ + if (sz > 0) { + data = OPENSSL_secure_malloc(sz); + if (data == NULL) { + ok = 0; + } } } if (ok && ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)) { diff --git a/test/test_dh.c b/test/test_dh.c index da5baf82..6098aef6 100644 --- a/test/test_dh.c +++ b/test/test_dh.c @@ -1735,4 +1735,67 @@ int test_dh_pgen_min_bits(void *data) return err; } +/* + * A parameter-only named-group key needs no data buffer: its group is exported + * as a string. Export must succeed rather than fail on a zero-size allocation. + */ +int test_dh_export_named_group_params(void *data) +{ + int err = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + OSSL_PARAM *exported = NULL; + const OSSL_PARAM *p = NULL; + const char *name = NULL; + OSSL_PARAM params[2]; + + (void)data; + + PRINT_MSG("Testing export of parameter-only named group DH key"); + + ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "DH", NULL); + if (ctx == NULL) { + err = 1; + } + if (err == 0) { + err = EVP_PKEY_fromdata_init(ctx) != 1; + } + if (err == 0) { + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + (char *)"ffdhe2048", 0); + params[1] = OSSL_PARAM_construct_end(); + err = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, + params) != 1; + if (err != 0) { + PRINT_ERR_MSG("DH group import failed for valid group name"); + } + } + if (err == 0) { + err = EVP_PKEY_todata(pkey, EVP_PKEY_KEY_PARAMETERS, &exported) != 1; + if (err != 0) { + PRINT_ERR_MSG("Export of parameter-only named group key failed"); + } + } + if (err == 0) { + p = OSSL_PARAM_locate(exported, OSSL_PKEY_PARAM_GROUP_NAME); + if (p == NULL) { + PRINT_ERR_MSG("Exported parameters carry no group name"); + err = 1; + } + } + if (err == 0 && OSSL_PARAM_get_utf8_string_ptr(p, &name) != 1) { + PRINT_ERR_MSG("Exported group name is not a readable string"); + err = 1; + } + if (err == 0 && strcmp(name, "ffdhe2048") != 0) { + PRINT_ERR_MSG("Exported group name does not match the imported group"); + err = 1; + } + + OSSL_PARAM_free(exported); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + return err; +} + #endif /* WP_HAVE_DH */ diff --git a/test/unit.c b/test/unit.c index 87152438..7dda75ef 100644 --- a/test/unit.c +++ b/test/unit.c @@ -343,6 +343,7 @@ TEST_CASE test_case[] = { TEST_DECL(test_dh_param_check_explicit, NULL), TEST_DECL(test_dh_import_group_no_nul, NULL), TEST_DECL(test_dh_pgen_min_bits, NULL), + TEST_DECL(test_dh_export_named_group_params, NULL), #ifndef WOLFPROV_QUICKTEST TEST_DECL(test_dh_get_params, NULL), #endif diff --git a/test/unit.h b/test/unit.h index a023ee21..4cc09cdf 100644 --- a/test/unit.h +++ b/test/unit.h @@ -384,6 +384,7 @@ int test_dh_fromdata_oversize(void *data); int test_dh_param_check_explicit(void *data); int test_dh_import_group_no_nul(void *data); int test_dh_pgen_min_bits(void *data); +int test_dh_export_named_group_params(void *data); #endif /* WP_HAVE_DH */ #ifdef WP_HAVE_ECC