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
68 changes: 68 additions & 0 deletions tests/api/test_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2188,6 +2188,74 @@ int test_wc_ecc_export_private_only(void)
return EXPECT_RESULT();
} /* END test_wc_ecc_export_private_only */

/*
* Testing wc_ecc_export_private_only() encodes the scalar at the fixed width
* of the curve, zero padded at the front, whatever its bit length.
*/
int test_wc_ecc_export_private_only_fixed_width(void)
{
EXPECT_DECLS;
#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \
defined(HAVE_ECC_KEY_IMPORT) && !defined(NO_ECC_SECP) && \
!defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
!defined(WOLFSSL_MICROCHIP_TA100) && \
(!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
ecc_key key;
byte one[1] = { 0x01 };
byte full[32] = {
0x80, 0x35, 0x79, 0xbd, 0x24, 0x68, 0xac, 0xe1,
0x17, 0x5b, 0x9f, 0xd3, 0x46, 0x8a, 0xce, 0xf2,
0x29, 0x6d, 0xa1, 0xe5, 0x38, 0x7c, 0xb0, 0xf4,
0x4a, 0x8e, 0xc2, 0x16, 0x5a, 0x9e, 0xd2, 0x27
};
byte expOne[32];
byte fill[40];
byte out[40];
word32 outLen;

XMEMSET(&key, 0, sizeof(ecc_key));
XMEMSET(expOne, 0, sizeof(expOne));
expOne[31] = 0x01;
XMEMSET(fill, 0xa5, sizeof(fill));

ExpectIntEQ(wc_ecc_init(&key), 0);
PRIVATE_KEY_UNLOCK();

/* A scalar of 1 is all padding but the last byte. Only the 32 bytes of
* the encoding are written into the larger buffer. */
ExpectIntEQ(wc_ecc_import_private_key_ex(one, (word32)sizeof(one), NULL,
0, &key, ECC_SECP256R1), 0);
XMEMCPY(out, fill, sizeof(out));
outLen = (word32)sizeof(out);
ExpectIntEQ(wc_ecc_export_private_only(&key, out, &outLen), 0);
ExpectIntEQ(outLen, 32);
ExpectBufEQ(out, expOne, sizeof(expOne));
ExpectBufEQ(out + 32, fill + 32, sizeof(out) - 32);

/* A buffer one byte short fails, reports the size needed and is left
* alone. */
XMEMCPY(out, fill, sizeof(out));
outLen = 31;
ExpectIntEQ(wc_ecc_export_private_only(&key, out, &outLen),
WC_NO_ERR_TRACE(BUFFER_E));
ExpectIntEQ(outLen, 32);
ExpectBufEQ(out, fill, sizeof(out));

/* A full width scalar fills every byte. */
ExpectIntEQ(wc_ecc_import_private_key_ex(full, (word32)sizeof(full), NULL,
0, &key, ECC_SECP256R1), 0);
XMEMCPY(out, fill, sizeof(out));
outLen = 32;
ExpectIntEQ(wc_ecc_export_private_only(&key, out, &outLen), 0);
ExpectIntEQ(outLen, 32);
ExpectBufEQ(out, full, sizeof(full));

PRIVATE_KEY_LOCK();
wc_ecc_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_ecc_export_private_only_fixed_width */

/*
* Testing wc_ecc_rs_to_sig()
*/
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ int test_wc_ecc_import_private_key(void);
int test_wc_ecc_make_pub_order_minus_1(void);
int test_wc_ecc_fp_cached_matches_uncached(void);
int test_wc_ecc_export_private_only(void);
int test_wc_ecc_export_private_only_fixed_width(void);
int test_wc_ecc_rs_to_sig(void);
int test_wc_ecc_import_raw(void);
int test_wc_ecc_import_privkey_range(void);
Expand Down Expand Up @@ -125,6 +126,7 @@ int test_wc_ecc_make_key_id_dev(void);
TEST_DECL_GROUP("ecc", test_wc_ecc_make_pub_order_minus_1), \
TEST_DECL_GROUP("ecc", test_wc_ecc_fp_cached_matches_uncached), \
TEST_DECL_GROUP("ecc", test_wc_ecc_export_private_only), \
TEST_DECL_GROUP("ecc", test_wc_ecc_export_private_only_fixed_width), \
TEST_DECL_GROUP("ecc", test_wc_ecc_rs_to_sig), \
TEST_DECL_GROUP("ecc", test_wc_ecc_import_raw), \
TEST_DECL_GROUP("ecc", test_wc_ecc_import_privkey_range), \
Expand Down
23 changes: 21 additions & 2 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12411,8 +12411,27 @@ static int _ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
else
#endif
{
err = wc_export_int(ecc_get_k(key), d, dLen,
dOrderSz ? ecc_order_size(key->dp) : keySz, encType);
word32 orderSz = ecc_order_size(key->dp);
word32 dSz = dOrderSz ? orderSz : keySz;
mp_int* k = ecc_get_k(key);

/* The scalar is in [1, n-1]: it is range checked on import and
* generated in range. When the output covers the order it always
* fits, so encode it in constant time. wc_export_int() sizes the
* value first, and counting its bits leaks the scalar's length. */
if ((encType == WC_TYPE_UNSIGNED_BIN) && (dSz >= orderSz)) {
if (*dLen < dSz) {
*dLen = dSz;
err = BUFFER_E;
}
else {
*dLen = dSz;
err = mp_to_unsigned_bin_len_ct(k, d, (int)dSz);
Comment thread
SparkiDev marked this conversation as resolved.
Resolved
}
}
else {
err = wc_export_int(k, d, dLen, dSz, encType);
}
ecc_put_k(key);
if (err != MP_OKAY)
return err;
Expand Down
Loading