Skip to content
Closed
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 src/pk_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -4749,6 +4749,74 @@ int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
return ret;
}

/*
* Decode an octet-encoded EC public point into @key.
*
* The point conversion form of @key is set from the encoding byte so that
* re-encoding with wolfSSL_i2o_ECPublicKey() reproduces @buf. Hybrid
* encodings have no wolfSSL equivalent and leave the form unchanged.
*
* Return code compliant with OpenSSL.
*
* @param [in, out] key EC key (must already have a group set).
* @param [in] buf Octet-encoded public point.
* @param [in] len Length of @buf in bytes.
* @param [in] ctx BN context. May be NULL.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_EC_KEY_oct2key(WOLFSSL_EC_KEY *key, const unsigned char *buf,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [Medium] wolfSSL_EC_KEY_oct2key does not record the point conversion form

OpenSSL's EC_KEY_oct2key() saves the encoding form on the key (key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01)), so that a later i2o_ECPublicKey() / EC_KEY_key2buf() re-emits the same form. The wolfSSL implementation never touches key->form, so a compressed input silently round-trips back as uncompressed.

Verified empirically on this branch:

compressed enc len=33 first=0x03
oct2key(compressed)=1 conv_form after=4 (OpenSSL sets 2)

This matters for applications that hash or compare the re-encoded public key (e.g. JWK/COSE key thumbprints, TLS raw public keys), because they will get a different byte string than OpenSSL would.

Fix: Call wolfSSL_EC_KEY_set_conv_form(key, buf[0] & ~0x01) on success, and document the behaviour in the function's doxygen block.

size_t len, WOLFSSL_BN_CTX *ctx)
{
int ret = 1;
const WOLFSSL_EC_GROUP *group = NULL;
WOLFSSL_EC_POINT *point = NULL;

WOLFSSL_ENTER("wolfSSL_EC_KEY_oct2key");

if ((key == NULL) || (buf == NULL) || (len == 0)) {
WOLFSSL_MSG("wolfSSL_EC_KEY_oct2key Bad arguments");
ret = 0;
}

if (ret == 1) {
group = wolfSSL_EC_KEY_get0_group(key);
if (group == NULL) {
WOLFSSL_MSG("EC_KEY has no group set");
ret = 0;
}
}

if (ret == 1) {
point = wolfSSL_EC_POINT_new((WOLFSSL_EC_GROUP*)group);
if (point == NULL) {
WOLFSSL_MSG("wolfSSL_EC_POINT_new failed");
ret = 0;
}
}

if ((ret == 1) &&
(wolfSSL_EC_POINT_oct2point(group, point, buf, len, ctx) != 1)) {
WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point failed");
ret = 0;
}

if ((ret == 1) && (wolfSSL_EC_KEY_set_public_key(key, point) != 1)) {
WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key failed");
ret = 0;
}

if (ret == 1) {
/* SEC 1: 0x02/0x03 compressed, 0x04 uncompressed. Clearing the low
* bit turns the leading byte into the conversion form. */
wolfSSL_EC_KEY_set_conv_form(key, buf[0] & ~0x01);
}

wolfSSL_EC_POINT_free(point);

return ret;
}

#ifndef NO_WOLFSSL_STUB
/* Set the ASN.1 encoding flag against the EC key.
*
Expand Down
Loading
Loading