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
2 changes: 1 addition & 1 deletion src/wp_ecc_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ static int wp_ecc_get_params_enc_pub_key(wp_Ecc* ecc, OSSL_PARAM params[],
p = OSSL_PARAM_locate(params, key);
if (p != NULL) {
int rc;
word32 outLen = (word32)p->return_size;
word32 outLen = (word32)p->data_size;
Comment thread
yosuke-wolfssl marked this conversation as resolved.

if (ecc->hasPub == 0) {
ok = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/wp_ecx_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ static int wp_ecx_get_params_enc_pub_key(wp_Ecx* ecx, OSSL_PARAM params[],

p = OSSL_PARAM_locate(params, key);
if (p != NULL) {
word32 outLen = (word32)p->return_size;
word32 outLen = (word32)p->data_size;

if (p->data == NULL) {
outLen = ecx->data->len;
Expand Down Expand Up @@ -584,7 +584,7 @@ static int wp_ecx_get_params_priv_key(wp_Ecx* ecx, OSSL_PARAM params[])

p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
if (p != NULL) {
word32 outLen = (word32)p->return_size;
word32 outLen = (word32)p->data_size;

if (p->data == NULL) {
outLen = ecx->data->len;
Expand Down
77 changes: 77 additions & 0 deletions test/test_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,83 @@ int test_eckeygen_p256(void *data)

return err;
}

/* get_params for the ECC encoded public key must size the export buffer from
* data_size, not a stale/zero return_size. Compare a stale-return_size export
* against a known-good fresh export of the same key. */
int test_ecc_p256_get_params_stale_ret(void *data)
{
int err = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *key = NULL;
unsigned char ref[128];
unsigned char readback[128];
size_t refLen = 0;
OSSL_PARAM params[2];

(void)data;

PRINT_MSG("P-256 encoded pub key get_params with stale return_size");

err = (ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "EC", NULL)) == NULL;
if (err == 0) {
err = EVP_PKEY_keygen_init(ctx) != 1;
}
if (err == 0) {
err = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx,
NID_X9_62_prime256v1) != 1;
}
if (err == 0) {
err = EVP_PKEY_keygen(ctx, &key) != 1;
}

/* Reference export via a fresh param. Its return_size defaults to
* OSSL_PARAM_UNMODIFIED, so this block succeeds even with the bug; the
* stale-return_size query below is the actual regression check. */
if (err == 0) {
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, ref, sizeof(ref));
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_get_params(key, params) != 1) {
PRINT_ERR_MSG("reference encoded pub key get_params failed");
err = 1;
}
else {
refLen = params[0].return_size;
}
}
if (err == 0 && (refLen == 0 || refLen > sizeof(ref))) {
PRINT_ERR_MSG("unexpected encoded pub key length: %zu", refLen);
err = 1;
}

/* Same query with return_size forced to 0 to mimic a reused param. */
if (err == 0) {
memset(readback, 0, sizeof(readback));
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, readback, sizeof(readback));
params[0].return_size = 0;
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_get_params(key, params) != 1) {
PRINT_ERR_MSG("encoded pub key get_params failed with stale "
"return_size");
err = 1;
}
}
if (err == 0 && params[0].return_size != refLen) {
PRINT_ERR_MSG("encoded pub key return_size wrong: %zu vs %zu",
params[0].return_size, refLen);
err = 1;
}
if (err == 0 && memcmp(readback, ref, refLen) != 0) {
PRINT_ERR_MSG("encoded pub key bytes not returned correctly");
err = 1;
}

EVP_PKEY_free(key);
EVP_PKEY_CTX_free(ctx);
return err;
}
#endif /* WP_HAVE_EC_P256 */

#ifdef WP_HAVE_EC_P384
Expand Down
103 changes: 103 additions & 0 deletions test/test_ecx.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,109 @@ int test_ecx_x25519_raw_priv_roundtrip(void *data)
return err;
}

/* get_params must size the export buffer from the caller's data_size, not
* return_size. A reused param can carry a stale/zero return_size from a prior
* size query; using it would truncate or fail the export. */
int test_ecx_x25519_get_params_stale_ret(void *data)
Comment thread
yosuke-wolfssl marked this conversation as resolved.
{
int err = 0;
EVP_PKEY *pkey = NULL;
static const unsigned char privKey[] = {
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d,
0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a
};
/* RFC 7748 Section 6.1 Alice public key, derived from privKey above. */
static const unsigned char pubKey[] = {
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 readback[32];
OSSL_PARAM params[2];

(void)data;

PRINT_MSG("X25519 get_params with stale (zero) return_size");

pkey = EVP_PKEY_new_raw_private_key_ex(wpLibCtx, "X25519", NULL,
privKey, sizeof(privKey));
if (pkey == NULL) {
PRINT_ERR_MSG("Failed to import X25519 private key");
err = 1;
}

/* Private key: full 32-byte buffer but return_size forced to 0. */
if (err == 0) {
memset(readback, 0, sizeof(readback));
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_PRIV_KEY, readback, sizeof(readback));
params[0].return_size = 0;
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_get_params(pkey, params) != 1) {
PRINT_ERR_MSG("priv key get_params failed with stale return_size");
err = 1;
}
}
if (err == 0 && params[0].return_size != sizeof(privKey)) {
PRINT_ERR_MSG("priv key return_size wrong: %zu", params[0].return_size);
err = 1;
}
if (err == 0 && memcmp(readback, privKey, sizeof(privKey)) != 0) {
PRINT_ERR_MSG("priv key bytes not returned correctly");
err = 1;
}

/* Public key: same stale-return_size condition on the export path. */
if (err == 0) {
memset(readback, 0, sizeof(readback));
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_PUB_KEY, readback, sizeof(readback));
params[0].return_size = 0;
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_get_params(pkey, params) != 1) {
PRINT_ERR_MSG("pub key get_params failed with stale return_size");
err = 1;
}
}
if (err == 0 && params[0].return_size != sizeof(pubKey)) {
PRINT_ERR_MSG("pub key return_size wrong: %zu", params[0].return_size);
err = 1;
}
if (err == 0 && memcmp(readback, pubKey, sizeof(pubKey)) != 0) {
PRINT_ERR_MSG("pub key bytes not returned correctly");
err = 1;
}

/* Encoded public key: same helper, exercised via its own key string. */
if (err == 0) {
memset(readback, 0, sizeof(readback));
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, readback, sizeof(readback));
params[0].return_size = 0;
params[1] = OSSL_PARAM_construct_end();
if (EVP_PKEY_get_params(pkey, params) != 1) {
PRINT_ERR_MSG("enc pub key get_params failed with stale "
"return_size");
err = 1;
}
}
if (err == 0 && params[0].return_size != sizeof(pubKey)) {
PRINT_ERR_MSG("enc pub key return_size wrong: %zu",
params[0].return_size);
err = 1;
}
if (err == 0 && memcmp(readback, pubKey, sizeof(pubKey)) != 0) {
PRINT_ERR_MSG("enc pub key bytes not returned correctly");
err = 1;
}

EVP_PKEY_free(pkey);
return err;
}

/* A zero-length private key octet string must be rejected without an
* out-of-bounds read (privData[len-1] with len==0). */
int test_ecx_import_zero_priv(void *data)
Expand Down
2 changes: 2 additions & 0 deletions test/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ TEST_CASE test_case[] = {
#ifdef WP_HAVE_EC_P256
#ifdef WP_HAVE_ECKEYGEN
TEST_DECL(test_eckeygen_p256, NULL),
TEST_DECL(test_ecc_p256_get_params_stale_ret, NULL),
#endif
#ifdef WP_HAVE_ECDH
#ifdef WP_HAVE_ECKEYGEN
Expand Down Expand Up @@ -515,6 +516,7 @@ TEST_CASE test_case[] = {
TEST_DECL(test_ecx_null_init, NULL),
#ifdef WP_HAVE_X25519
TEST_DECL(test_ecx_x25519_raw_priv_roundtrip, NULL),
TEST_DECL(test_ecx_x25519_get_params_stale_ret, NULL),
TEST_DECL(test_ecx_import_zero_priv, NULL),
#endif
TEST_DECL(test_ecx_dup, NULL),
Expand Down
2 changes: 2 additions & 0 deletions test/unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ int test_eckeygen_p224(void *data);

#ifdef WP_HAVE_EC_P256
int test_eckeygen_p256(void *data);
int test_ecc_p256_get_params_stale_ret(void *data);
#endif /* WP_HAVE_EC_P256 */

#ifdef WP_HAVE_EC_P384
Expand Down Expand Up @@ -522,6 +523,7 @@ int test_ecx_misc(void *data);
int test_ecx_null_init(void *data);
#ifdef WP_HAVE_X25519
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);
#endif /* WP_HAVE_X25519 */
int test_ecx_dup(void *data);
Expand Down
Loading