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
53 changes: 51 additions & 2 deletions doc/dox_comments/header_files/cryptocb.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,9 @@ int wc_CryptoCb_Ed25519MakePub(ed25519_key* key, byte* pubKey,
public key crosses the callback boundary as its compressed wire bytes in
wc_CryptoInfo.pk.ed25519checkkey (\c pubKey / \c pubKeySz), so a device
handler only deals with byte arrays. The dispatch only runs when a public
key is present; \c checkPriv is 1 when a private key is also set and the
device should additionally validate priv/pub consistency.
key is present; \c checkPriv is 1 when a private key is also set or
referenced by id or label, and the device should additionally validate
priv/pub consistency.

\param key Ed25519 key to validate

Expand All @@ -410,3 +411,51 @@ int wc_CryptoCb_Ed25519MakePub(ed25519_key* key, byte* pubKey,
\sa wc_ed25519_check_key
*/
int wc_CryptoCb_Ed25519CheckKey(ed25519_key* key);

/*!
\ingroup CryptoCb

\brief Offload deriving an Ed448 public key from its private key to a
CryptoCB device.

Used by wc_ed448_make_public (and so by key generation and private-key
import). The device writes the compressed public key into
wc_CryptoInfo.pk.ed448makepub (\c pubOut / \c pubOutSz, always
ED448_PUB_KEY_SIZE).

\param key Ed448 key providing the device id, heap hint and the
private key
\param pubKey [out] resulting compressed public key
\param pubKeySz size of pubKey buffer, must be ED448_PUB_KEY_SIZE

\return 0 on success
\return CRYPTOCB_UNAVAILABLE if no device handles the operation, or key or
pubKey is NULL or pubKeySz is wrong (wolfCrypt falls back to
software, which reports the argument error)

\sa wc_CryptoCb_RegisterDevice
\sa wc_ed448_make_public
*/
int wc_CryptoCb_Ed448MakePub(ed448_key* key, byte* pubKey, word32 pubKeySz);

/*!
\ingroup CryptoCb

\brief Offload validating an Ed448 key to a CryptoCB device.

Used by wc_ed448_check_key and when checking a device private key against
a certificate. The compressed public key is passed in
wc_CryptoInfo.pk.ed448checkkey (\c pubKey / \c pubKeySz). \c checkPriv is
1 when a private key is set or referenced by id or label, and the device
should also check that it matches the public key.

\param key Ed448 key to validate

\return 0 if the key is valid
\return CRYPTOCB_UNAVAILABLE if no device handles the operation (wolfCrypt
falls back to software)

\sa wc_CryptoCb_RegisterDevice
\sa wc_ed448_check_key
*/
int wc_CryptoCb_Ed448CheckKey(ed448_key* key);
59 changes: 59 additions & 0 deletions doc/dox_comments/header_files/ed25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,65 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen,
*/
int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId);

/*!
\ingroup ED25519

\brief Initializes an ed25519_key object that references a private key held
by a crypto callback device, identified by id. Only available when built
with WOLF_PRIVATE_KEY_ID.

\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or id is NULL and len is greater
than 0.
\return BUFFER_E if len is negative or greater than ED25519_MAX_ID_LEN.

\param [in,out] key Pointer to the ed25519_key to initialize.
\param [in] id Key identifier bytes.
\param [in] len Length of id in bytes.
\param [in] heap Heap hint. May be NULL.
\param [in] devId Device identifier for the crypto callback.

_Example_
\code
ed25519_key key;
unsigned char id[] = { 0x01, 0x02, 0x03, 0x04 };
int ret = wc_ed25519_init_id(&key, id, sizeof(id), NULL, devId);
\endcode

\sa wc_ed25519_init_ex
\sa wc_ed25519_init_label
*/
int wc_ed25519_init_id(ed25519_key* key, const unsigned char* id, int len,
void* heap, int devId);

/*!
\ingroup ED25519

\brief Initializes an ed25519_key object that references a private key held
by a crypto callback device, identified by label. Only available when
built with WOLF_PRIVATE_KEY_ID.

\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL.
\return BUFFER_E if label is empty or longer than ED25519_MAX_LABEL_LEN.

\param [in,out] key Pointer to the ed25519_key to initialize.
\param [in] label NUL-terminated label string.
\param [in] heap Heap hint. May be NULL.
\param [in] devId Device identifier for the crypto callback.

_Example_
\code
ed25519_key key;
int ret = wc_ed25519_init_label(&key, "my-key", NULL, devId);
\endcode

\sa wc_ed25519_init_ex
\sa wc_ed25519_init_id
*/
int wc_ed25519_init_label(ed25519_key* key, const char* label, void* heap,
int devId);

/*!
\ingroup ED25519
\brief Allocates and initializes new Ed25519 key. These New/Delete
Expand Down
59 changes: 59 additions & 0 deletions doc/dox_comments/header_files/ed448.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,65 @@ int wc_ed448ph_verify_msg(const byte* sig, word32 siglen, const byte* msg,

int wc_ed448_init(ed448_key* key);

/*!
\ingroup ED448

\brief Initializes an ed448_key object that references a private key held
by a crypto callback device, identified by id. Only available when built
with WOLF_PRIVATE_KEY_ID.

\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or id is NULL and len is greater
than 0.
\return BUFFER_E if len is negative or greater than ED448_MAX_ID_LEN.

\param [in,out] key Pointer to the ed448_key to initialize.
\param [in] id Key identifier bytes.
\param [in] len Length of id in bytes.
\param [in] heap Heap hint. May be NULL.
\param [in] devId Device identifier for the crypto callback.

_Example_
\code
ed448_key key;
unsigned char id[] = { 0x01, 0x02, 0x03, 0x04 };
int ret = wc_ed448_init_id(&key, id, sizeof(id), NULL, devId);
\endcode

\sa wc_ed448_init_ex
\sa wc_ed448_init_label
*/
int wc_ed448_init_id(ed448_key* key, const unsigned char* id, int len,
void* heap, int devId);

/*!
\ingroup ED448

\brief Initializes an ed448_key object that references a private key held
by a crypto callback device, identified by label. Only available when
built with WOLF_PRIVATE_KEY_ID.

\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL.
\return BUFFER_E if label is empty or longer than ED448_MAX_LABEL_LEN.

\param [in,out] key Pointer to the ed448_key to initialize.
\param [in] label NUL-terminated label string.
\param [in] heap Heap hint. May be NULL.
\param [in] devId Device identifier for the crypto callback.

_Example_
\code
ed448_key key;
int ret = wc_ed448_init_label(&key, "my-key", NULL, devId);
\endcode

\sa wc_ed448_init_ex
\sa wc_ed448_init_id
*/
int wc_ed448_init_label(ed448_key* key, const char* label, void* heap,
int devId);

/*!
\ingroup ED448

Expand Down
92 changes: 90 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6880,16 +6880,21 @@ int Ed25519CheckPubKey(WOLFSSL* ssl)
#else /* HAVE_ED25519_KEY_IMPORT */
ed25519_key* key = (ed25519_key*)ssl->hsKey;
int ret = 0;
int trusted = 0;

/* Public key required for signing. */
if (key != NULL && !key->pubKeySet) {
const unsigned char* pubKey;
word32 pubKeySz;

#ifdef ED25519_MAX_ID_LEN
/* A device key pair is checked by wolfSSL_CTX_check_private_key. */
trusted = (key->idLen > 0) || (key->labelLen > 0);
#endif
ret = wc_CertGetPubKey(ssl->buffers.certificate->buffer,
ssl->buffers.certificate->length, &pubKey, &pubKeySz);
if (ret == 0) {
ret = wc_ed25519_import_public(pubKey, pubKeySz, key);
ret = wc_ed25519_import_public_ex(pubKey, pubKeySz, key, trusted);
}
}

Expand Down Expand Up @@ -7210,16 +7215,21 @@ int Ed448CheckPubKey(WOLFSSL* ssl)
#else /* HAVE_ED448_KEY_IMPORT */
ed448_key* key = (ed448_key*)ssl->hsKey;
int ret = 0;
int trusted = 0;

/* Public key required for signing. */
if (key != NULL && !key->pubKeySet) {
const unsigned char* pubKey;
word32 pubKeySz;

#ifdef ED448_MAX_ID_LEN
/* A device key pair is checked by wolfSSL_CTX_check_private_key. */
trusted = (key->idLen > 0) || (key->labelLen > 0);
#endif
ret = wc_CertGetPubKey(ssl->buffers.certificate->buffer,
ssl->buffers.certificate->length, &pubKey, &pubKeySz);
if (ret == 0) {
ret = wc_ed448_import_public(pubKey, pubKeySz, key);
ret = wc_ed448_import_public_ex(pubKey, pubKeySz, key, trusted);
}
}

Expand Down Expand Up @@ -34165,6 +34175,54 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
else {
XFREE(ecKey, heap, DYNAMIC_TYPE_ECC);
}
#endif
}
else if (hsType == DYNAMIC_TYPE_ED25519) {
#if defined(HAVE_ED25519) && defined(ED25519_MAX_ID_LEN)
ed25519_key* edKey;

edKey = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
DYNAMIC_TYPE_ED25519);
if (edKey == NULL) {
return MEMORY_E;
}

if (label) {
ret = wc_ed25519_init_label(edKey, (char*)data, heap, devId);
}
else if (id) {
ret = wc_ed25519_init_id(edKey, data, (int)length, heap, devId);
}
if (ret == 0) {
*pkey = (void*)edKey;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI says this results in the device being asked to check the keypair on every TLS handshake because Ed25519CheckPubKey calls wc_ed25519_import_public which imports the key as untrusted. Possibly not what we want.

This is a rather indirect code path, so I'm not totally sure. Can you check?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, you are right! I fixed that now: for id/label keys the cert public key is now imported as trusted, so the pair is only checked by wolfSSL_CTX_check_private_key, same as RSA/ECC device keys already. This also lets WOLF_CRYPTO_CB_ONLY_ED25519/ED448 builds perform a handshake with a device that doesn't implement CHECK_KEY.

}
else {
XFREE(edKey, heap, DYNAMIC_TYPE_ED25519);
}
#endif
}
else if (hsType == DYNAMIC_TYPE_ED448) {
#if defined(HAVE_ED448) && defined(ED448_MAX_ID_LEN)
ed448_key* edKey;

edKey = (ed448_key*)XMALLOC(sizeof(ed448_key), heap,
DYNAMIC_TYPE_ED448);
if (edKey == NULL) {
return MEMORY_E;
}

if (label) {
ret = wc_ed448_init_label(edKey, (char*)data, heap, devId);
}
else if (id) {
ret = wc_ed448_init_id(edKey, data, (int)length, heap, devId);
}
if (ret == 0) {
*pkey = (void*)edKey;
}
else {
XFREE(edKey, heap, DYNAMIC_TYPE_ED448);
}
#endif
}
else if (hsType == DYNAMIC_TYPE_MLDSA) {
Expand Down Expand Up @@ -34311,6 +34369,10 @@ static int DecodePrivateKey_ex(WOLFSSL *ssl, byte keyType, const DerBuffer* key,
*hsType = DYNAMIC_TYPE_RSA;
else if (keyType == ecc_dsa_sa_algo)
*hsType = DYNAMIC_TYPE_ECC;
else if (keyType == ed25519_sa_algo)
*hsType = DYNAMIC_TYPE_ED25519;
else if (keyType == ed448_sa_algo)
*hsType = DYNAMIC_TYPE_ED448;
else if ((keyType == falcon_level1_sa_algo) ||
(keyType == falcon_level5_sa_algo))
*hsType = DYNAMIC_TYPE_FALCON;
Expand Down Expand Up @@ -34365,6 +34427,32 @@ static int DecodePrivateKey_ex(WOLFSSL *ssl, byte keyType, const DerBuffer* key,
*sigLen = (word32)wc_ecc_sig_size_calc(keySz);
#else
ret = NOT_COMPILED_IN;
#endif
}
else if (*hsType == DYNAMIC_TYPE_ED25519) {
#ifdef HAVE_ED25519
if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
WOLFSSL_MSG("ED25519 key size too small");
ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
}

/* Return the maximum signature length. */
*sigLen = ED25519_SIG_SIZE;
#else
ret = NOT_COMPILED_IN;
#endif
}
else if (*hsType == DYNAMIC_TYPE_ED448) {
#ifdef HAVE_ED448
if (ED448_KEY_SIZE < ssl->options.minEccKeySz) {
WOLFSSL_MSG("ED448 key size too small");
ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
}

/* Return the maximum signature length. */
*sigLen = ED448_SIG_SIZE;
#else
ret = NOT_COMPILED_IN;
#endif
}
else if (*hsType == DYNAMIC_TYPE_FALCON) {
Expand Down
Loading
Loading