Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/wp_ecx_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,8 @@ static int wp_ecx_import(wp_Ecx* ecx, int selection, const OSSL_PARAM params[])
}
}
}
if (ok && ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)) {
/* Any keypair bit (OpenSSL hybrid KEMs import pub with DOMAIN|PRIVATE). */
if (ok && ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)) {
if (!wp_params_get_octet_string_ptr(params, OSSL_PKEY_PARAM_PUB_KEY,
&pubData, &len)) {
ok = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/wp_mlkem_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ static int wp_mlkem_import(wp_MlKem* mlkem, int selection,
}
}
}
if (ok && ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)) {
/* Any keypair bit (OpenSSL hybrid KEMs import pub with DOMAIN|PRIVATE). */
if (ok && ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)) {
if (!wp_params_get_octet_string_ptr(params, OSSL_PKEY_PARAM_PUB_KEY,
&pubData, &pubLen)) {
ok = 0;
Expand Down
47 changes: 47 additions & 0 deletions test/test_ecx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,53 @@ int test_ecx_import_short_pub(void *data)
OPENSSL_free(buf);
return err;
}

/* OpenSSL's hybrid KEM keymgmt imports X25519 public keys with
* DOMAIN_PARAMETERS|PRIVATE_KEY selection. */
int test_ecx_import_pub_with_priv_selection(void *data)
{
int err = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
static const unsigned char pubKey[32] = {
0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54,
0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a,
0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4,
0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a
};
unsigned char out[sizeof(pubKey)];
size_t outLen = sizeof(out);
OSSL_PARAM params[2];

(void)data;
PRINT_MSG("X25519 public import with private-key selection");

ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "X25519", NULL);
err = (ctx == NULL) || (EVP_PKEY_fromdata_init(ctx) != 1);
if (err == 0) {
params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
(void*)pubKey, sizeof(pubKey));
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_fromdata(ctx, &pkey,
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS |
OSSL_KEYMGMT_SELECT_PRIVATE_KEY, params) != 1) {
PRINT_ERR_MSG("X25519 public import failed");
err = 1;
}
}
if (err == 0) {
if (EVP_PKEY_get_raw_public_key(pkey, out, &outLen) != 1 ||
outLen != sizeof(pubKey) ||
memcmp(out, pubKey, sizeof(pubKey)) != 0) {
PRINT_ERR_MSG("X25519 imported public key mismatch");
err = 1;
}
}

EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return err;
}
#endif /* WP_HAVE_X25519 */

int test_ecx_dup(void *data)
Expand Down
27 changes: 26 additions & 1 deletion test/test_mlkem.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,20 +166,25 @@ int test_mlkem_keygen(void* data)
* import into a fresh EVP_PKEY via EVP_PKEY_fromdata, re-export, and verify
* the bytes match exactly. Proves the OSSL_PARAM marshaling for raw keys is
* lossless in both directions.
* Also import the public key with private-key selection.
*/
int test_mlkem_import_export_roundtrip(void* data)
{
int err = 0;
size_t i;
EVP_PKEY* k1 = NULL;
EVP_PKEY* k2 = NULL;
EVP_PKEY* k3 = NULL;
EVP_PKEY_CTX* ctx = NULL;
OSSL_PARAM* params = NULL;
OSSL_PARAM pubParams[2];
unsigned char* pub1 = NULL;
unsigned char* pub2 = NULL;
unsigned char* pub3 = NULL;
unsigned char* priv1 = NULL;
unsigned char* priv2 = NULL;
size_t pub1Len = 0, pub2Len = 0, priv1Len = 0, priv2Len = 0;
size_t pub1Len = 0, pub2Len = 0, pub3Len = 0;
size_t priv1Len = 0, priv2Len = 0;

(void)data;

Expand Down Expand Up @@ -249,15 +254,35 @@ int test_mlkem_import_export_roundtrip(void* data)
(memcmp(priv1, priv2, priv1Len) != 0);
if (err) PRINT_ERR_MSG("Private key roundtrip mismatch");
}
if (err == 0) {
pubParams[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_PUB_KEY, pub1, pub1Len);
pubParams[1] = OSSL_PARAM_construct_end();
err = EVP_PKEY_fromdata_init(ctx) != 1 ||
EVP_PKEY_fromdata(ctx, &k3,
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS |
OSSL_KEYMGMT_SELECT_PRIVATE_KEY, pubParams) != 1;
if (err) PRINT_ERR_MSG("Public key import failed");
}
if (err == 0) {
err = mlkem_get_pub(k3, &pub3, &pub3Len);
}
if (err == 0) {
err = (pub1Len != pub3Len) ||
(memcmp(pub1, pub3, pub1Len) != 0);
if (err) PRINT_ERR_MSG("Imported public key mismatch");
}

OPENSSL_free(pub1); pub1 = NULL;
OPENSSL_free(pub2); pub2 = NULL;
OPENSSL_free(pub3); pub3 = NULL;
OPENSSL_clear_free(priv1, priv1Len); priv1 = NULL; priv1Len = 0;
OPENSSL_clear_free(priv2, priv2Len); priv2 = NULL; priv2Len = 0;
OSSL_PARAM_free(params); params = NULL;
EVP_PKEY_CTX_free(ctx); ctx = NULL;
EVP_PKEY_free(k1); k1 = NULL;
EVP_PKEY_free(k2); k2 = NULL;
EVP_PKEY_free(k3); k3 = NULL;
}
return err;
}
Expand Down
1 change: 1 addition & 0 deletions test/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ TEST_CASE test_case[] = {
TEST_DECL(test_ecx_x25519_get_params_stale_ret, NULL),
TEST_DECL(test_ecx_import_zero_priv, NULL),
TEST_DECL(test_ecx_import_short_pub, NULL),
TEST_DECL(test_ecx_import_pub_with_priv_selection, NULL),
#endif
TEST_DECL(test_ecx_dup, NULL),
TEST_DECL(test_ecx_shared_key_first_use, NULL),
Expand Down
1 change: 1 addition & 0 deletions test/unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ int test_ecx_x25519_raw_priv_roundtrip(void *data);
int test_ecx_x25519_get_params_stale_ret(void *data);
int test_ecx_import_zero_priv(void *data);
int test_ecx_import_short_pub(void *data);
int test_ecx_import_pub_with_priv_selection(void *data);
#endif /* WP_HAVE_X25519 */
int test_ecx_dup(void *data);
int test_ecx_shared_key_first_use(void *data);
Expand Down
Loading