Improvements to code for ECDHE and peer review fixes.
This commit is contained in:
@@ -276,12 +276,11 @@ int stsafe_interface_init(void)
|
||||
* \details Uses dedicated key slot (slot 1) for persistent keys.
|
||||
* For ephemeral ECDHE keys, use stsafe_create_ecdhe_key() instead.
|
||||
*/
|
||||
static int stsafe_create_key(stsafe_slot_t* pSlot, stsafe_curve_id_t curve_id,
|
||||
static int stsafe_create_key(stsafe_slot_t slot, stsafe_curve_id_t curve_id,
|
||||
uint8_t* pPubKeyRaw)
|
||||
{
|
||||
int rc = STSAFE_A_OK;
|
||||
stse_ReturnCode_t ret;
|
||||
stsafe_slot_t slot = STSAFE_KEY_SLOT_1; /* Use dedicated key slot for persistent keys */
|
||||
|
||||
if (pPubKeyRaw == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -299,10 +298,6 @@ static int stsafe_create_key(stsafe_slot_t* pSlot, stsafe_curve_id_t curve_id,
|
||||
rc = (int)ret;
|
||||
}
|
||||
|
||||
if (rc == STSAFE_A_OK && pSlot != NULL) {
|
||||
*pSlot = slot;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -460,64 +455,6 @@ static int stsafe_shared_secret(stsafe_slot_t slot, stsafe_curve_id_t curve_id,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief ECDHE shared secret using STSAFE-A120
|
||||
* \details Computes shared secret using the ephemeral ECDHE private key
|
||||
* that was generated by stsafe_create_ecdhe_key(). The ephemeral
|
||||
* private key is stored internally in the STSE device.
|
||||
*/
|
||||
static int stsafe_shared_secret_ecdhe(stsafe_curve_id_t curve_id,
|
||||
uint8_t* pPubKeyX, uint8_t* pPubKeyY,
|
||||
uint8_t* pSharedSecret,
|
||||
int32_t* pSharedSecretLen)
|
||||
{
|
||||
int rc = STSAFE_A_OK;
|
||||
stse_ReturnCode_t ret;
|
||||
int key_sz = stsafe_get_key_size(curve_id);
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
uint8_t* peerPubKey = NULL;
|
||||
#else
|
||||
uint8_t peerPubKey[STSAFE_MAX_PUBKEY_RAW_LEN];
|
||||
#endif
|
||||
|
||||
if (pPubKeyX == NULL || pPubKeyY == NULL || pSharedSecret == NULL ||
|
||||
pSharedSecretLen == NULL || key_sz == 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
peerPubKey = (uint8_t*)XMALLOC(STSAFE_MAX_PUBKEY_RAW_LEN, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (peerPubKey == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Combine peer X and Y (X||Y format) */
|
||||
XMEMCPY(peerPubKey, pPubKeyX, key_sz);
|
||||
XMEMCPY(peerPubKey + key_sz, pPubKeyY, key_sz);
|
||||
|
||||
/* Compute shared secret using ephemeral slot (0xFF)
|
||||
* The ephemeral private key was generated by stse_generate_ECDHE_key_pair() */
|
||||
ret = stse_ecc_establish_shared_secret(&g_stse_handler,
|
||||
STSAFE_KEY_SLOT_EPHEMERAL, (stse_ecc_key_type_t)curve_id, peerPubKey, pSharedSecret);
|
||||
if (ret != STSE_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stse_ecc_establish_shared_secret (ECDHE) error: %d\n",
|
||||
ret);
|
||||
rc = (int)ret;
|
||||
}
|
||||
|
||||
if (rc == STSAFE_A_OK) {
|
||||
*pSharedSecretLen = (int32_t)key_sz;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
XFREE(peerPubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read device certificate from STSAFE-A120
|
||||
*/
|
||||
@@ -536,11 +473,16 @@ static int stsafe_read_certificate(uint8_t** ppCert, uint32_t* pCertLen)
|
||||
|
||||
/* First, get certificate size */
|
||||
ret = stse_get_device_certificate_size(&g_stse_handler, certZone, &certLen);
|
||||
if (ret != STSE_OK || certLen == 0) {
|
||||
if (ret != STSE_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stse_get_device_certificate_size error: %d\n",
|
||||
ret);
|
||||
rc = (int)ret;
|
||||
}
|
||||
else if (certLen == 0) {
|
||||
/* Certificate size is 0 - invalid certificate data */
|
||||
STSAFE_INTERFACE_PRINTF("stse_get_device_certificate_size returned zero length\n");
|
||||
rc = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
if (rc == STSAFE_A_OK) {
|
||||
@@ -988,6 +930,14 @@ static int stsafe_read_certificate(uint8_t** ppCert, uint32_t* pCertLen)
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Check if length parsing succeeded */
|
||||
if (*pCertLen == 0) {
|
||||
rc = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Invalid ASN.1 header - expected SEQUENCE tag */
|
||||
rc = ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1469,23 +1419,12 @@ int SSL_STSAFE_SharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey,
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
#ifdef WOLFSSL_STSAFEA120
|
||||
/* Use ECDHE shared secret computation for A120 */
|
||||
err = stsafe_shared_secret_ecdhe(curve_id, otherKeyX, otherKeyY,
|
||||
out, (int32_t*)outlen);
|
||||
if (err != STSAFE_A_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stsafe_shared_secret_ecdhe error: %d\n", err);
|
||||
err = WC_HW_E;
|
||||
}
|
||||
#else
|
||||
/* Legacy A100/A110 uses slot-based shared secret */
|
||||
err = stsafe_shared_secret(slot, curve_id, otherKeyX, otherKeyY,
|
||||
out, (int32_t*)outlen);
|
||||
if (err != STSAFE_A_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stsafe_shared_secret error: %d\n", err);
|
||||
err = WC_HW_E;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (tmpKeyInit) {
|
||||
@@ -1597,17 +1536,25 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
key_sz = stsafe_get_key_size(curve_id);
|
||||
|
||||
/* For A120, generate keys in slot 1 (persistent slot) by default for ECDSA signing.
|
||||
* For ECDH operations, ephemeral keys will be generated on-demand in the ECDH callback
|
||||
* if needed (see WC_PK_TYPE_ECDH handling below). */
|
||||
* For ECDH operations, the key slot from devCtx will be used directly.
|
||||
* If ECDH is required, keys should be generated in the ephemeral slot from the start. */
|
||||
#ifdef WOLFSSL_STSAFEA120
|
||||
stse_ReturnCode_t ret;
|
||||
slot = STSAFE_KEY_SLOT_1; /* Use persistent slot for ECDSA signing */
|
||||
ret = stse_generate_ecc_key_pair(&g_stse_handler, slot,
|
||||
(stse_ecc_key_type_t)curve_id,
|
||||
STSAFE_PERSISTENT_KEY_USAGE_LIMIT,
|
||||
pubKeyRaw);
|
||||
if (ret != STSE_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stse_generate_ecc_key_pair (slot 1) error: %d\n", ret);
|
||||
/* Retrieve slot from devCtx if available, otherwise use default */
|
||||
slot = STSAFE_KEY_SLOT_1; /* Default fallback */
|
||||
if (info->pk.eckg.key != NULL && info->pk.eckg.key->devCtx != NULL) {
|
||||
slot = STSAFE_DEVCXT_TO_SLOT(info->pk.eckg.key->devCtx);
|
||||
}
|
||||
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: KeyGen slot %d, curve_id %d\n",
|
||||
slot, curve_id);
|
||||
|
||||
if (slot == STSAFE_KEY_SLOT_EPHEMERAL) {
|
||||
rc = stsafe_create_ecdhe_key(curve_id, pubKeyRaw);
|
||||
} else {
|
||||
rc = stsafe_create_key(slot, curve_id, pubKeyRaw);
|
||||
}
|
||||
if (rc != STSE_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: KeyGen (slot %d) error: %d\n", slot, rc);
|
||||
rc = WC_HW_E;
|
||||
} else {
|
||||
rc = STSAFE_A_OK;
|
||||
@@ -1624,21 +1571,17 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
/* Store slot number directly in devCtx (no dynamic allocation) */
|
||||
info->pk.eckg.key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot);
|
||||
/* Import public key */
|
||||
rc = wc_ecc_import_unsigned(info->pk.eckg.key, pubKeyRaw,
|
||||
&pubKeyRaw[key_sz], NULL, ecc_curve);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
/* Import public key - preserve devCtx */
|
||||
void* saved_devCtx = info->pk.eckg.key->devCtx;
|
||||
rc = wc_ecc_import_unsigned(info->pk.eckg.key, pubKeyRaw,
|
||||
&pubKeyRaw[key_sz], NULL, ecc_curve);
|
||||
/* Restore devCtx in case import cleared it */
|
||||
if (saved_devCtx != NULL && info->pk.eckg.key->devCtx != saved_devCtx) {
|
||||
info->pk.eckg.key->devCtx = saved_devCtx;
|
||||
}
|
||||
/* Store slot number directly in devCtx */
|
||||
info->pk.eckg.key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
XFREE(pubKeyRaw, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
@@ -1653,6 +1596,7 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
#endif
|
||||
byte* r;
|
||||
byte* s;
|
||||
stsafe_slot_t slot;
|
||||
stsafe_curve_id_t curve_id;
|
||||
int ecc_curve;
|
||||
word32 inSz = info->pk.eccsign.inlen;
|
||||
@@ -1690,12 +1634,12 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
|
||||
XMEMSET(sigRS, 0, STSAFE_MAX_SIG_LEN);
|
||||
/* Retrieve slot from devCtx if available, otherwise use default */
|
||||
stsafe_slot_t slot = STSAFE_KEY_SLOT_1; /* Default fallback */
|
||||
slot = STSAFE_KEY_SLOT_1; /* Default fallback */
|
||||
if (info->pk.eccsign.key != NULL && info->pk.eccsign.key->devCtx != NULL) {
|
||||
slot = STSAFE_DEVCXT_TO_SLOT(info->pk.eccsign.key->devCtx);
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: Using slot %d from devCtx for signing\n", slot);
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: Sign using slot %d\n", slot);
|
||||
} else {
|
||||
WOLFSSL_MSG("STSAFE: Warning: devCtx not found, using default slot 1");
|
||||
WOLFSSL_MSG("STSAFE: Sign using default slot 1");
|
||||
}
|
||||
rc = stsafe_sign(slot, curve_id, digest, sigRS);
|
||||
if (rc != STSAFE_A_OK) {
|
||||
@@ -1815,6 +1759,7 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
word32 otherKeyX_len = STSAFE_MAX_KEY_LEN;
|
||||
word32 otherKeyY_len = STSAFE_MAX_KEY_LEN;
|
||||
stsafe_curve_id_t curve_id;
|
||||
stsafe_slot_t slot;
|
||||
int ecc_curve;
|
||||
|
||||
WOLFSSL_MSG("STSAFE: ECDH");
|
||||
@@ -1872,116 +1817,26 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
if (rc == 0) {
|
||||
*info->pk.ecdh.outlen = 0;
|
||||
|
||||
/* Check if private key is software but public key is hardware.
|
||||
* In this case, we can't use hardware for computation since the
|
||||
* private key is not in a slot. Return CRYPTOCB_UNAVAILABLE to
|
||||
* let software handle it (but software path may also fail if
|
||||
* public key export fails). */
|
||||
if (info->pk.ecdh.private_key == NULL ||
|
||||
info->pk.ecdh.private_key->devId == INVALID_DEVID) {
|
||||
if (info->pk.ecdh.public_key != NULL &&
|
||||
info->pk.ecdh.public_key->devId != INVALID_DEVID) {
|
||||
WOLFSSL_MSG("STSAFE: Private key is software, public key is hardware - cannot use hardware");
|
||||
rc = CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
/* For ECDH operations, use ephemeral slot (0xFF).
|
||||
* Keys are generated in slot 1 by default (for ECDSA signing).
|
||||
* If the key is in slot 1, generate a new ephemeral key for ECDH.
|
||||
* If the key is already in the ephemeral slot, use it directly. */
|
||||
stsafe_slot_t slot;
|
||||
stsafe_slot_t original_slot = STSAFE_KEY_SLOT_1;
|
||||
int need_ephemeral_key = 0;
|
||||
|
||||
/* For ECDH operations, use the slot from devCtx. */
|
||||
slot = STSAFE_KEY_SLOT_EPHEMERAL;
|
||||
if (info->pk.ecdh.private_key != NULL &&
|
||||
info->pk.ecdh.private_key->devCtx != NULL) {
|
||||
original_slot = STSAFE_DEVCXT_TO_SLOT(info->pk.ecdh.private_key->devCtx);
|
||||
|
||||
/* If key is in slot 1 (for ECDSA), we need to generate ephemeral key for ECDH */
|
||||
if (original_slot == STSAFE_KEY_SLOT_1) {
|
||||
need_ephemeral_key = 1;
|
||||
}
|
||||
slot = STSAFE_DEVCXT_TO_SLOT(info->pk.ecdh.private_key->devCtx);
|
||||
}
|
||||
|
||||
if (need_ephemeral_key) {
|
||||
#ifdef WOLFSSL_STSAFEA120
|
||||
/* Key is in slot 1 (for ECDSA), but ECDH requires ephemeral slot.
|
||||
* Generate ephemeral key pair for ECDH. Note: This will overwrite any
|
||||
* existing key in ephemeral slot, so for bidirectional ECDH, both keys
|
||||
* should be generated in ephemeral slot from the start. */
|
||||
stse_ReturnCode_t ret;
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
byte* ephemeralPubKey = NULL;
|
||||
#else
|
||||
byte ephemeralPubKey[STSAFE_MAX_PUBKEY_RAW_LEN];
|
||||
#endif
|
||||
int key_sz = stsafe_get_key_size(curve_id);
|
||||
slot = STSAFE_KEY_SLOT_EPHEMERAL;
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: ECDH with slot %d, curve_id %d\n",
|
||||
slot, curve_id);
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
ephemeralPubKey = (byte*)XMALLOC(STSAFE_MAX_PUBKEY_RAW_LEN, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ephemeralPubKey == NULL) {
|
||||
rc = MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rc == 0) {
|
||||
ret = stse_generate_ecc_key_pair(&g_stse_handler, slot,
|
||||
(stse_ecc_key_type_t)curve_id,
|
||||
STSAFE_EPHEMERAL_KEY_USAGE_LIMIT,
|
||||
ephemeralPubKey);
|
||||
if (ret != STSE_OK) {
|
||||
STSAFE_INTERFACE_PRINTF("stse_generate_ecc_key_pair (ephemeral for ECDH) error: %d\n", ret);
|
||||
rc = (int)ret;
|
||||
} else {
|
||||
WOLFSSL_MSG("STSAFE: Generated ephemeral key for ECDH");
|
||||
/* Update devCtx to reflect ephemeral slot for this key */
|
||||
if (info->pk.ecdh.private_key != NULL) {
|
||||
info->pk.ecdh.private_key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot);
|
||||
}
|
||||
/* Update the public key in the key structure to match the new ephemeral key */
|
||||
if (info->pk.ecdh.private_key != NULL && rc == 0) {
|
||||
void* saved_devCtx = info->pk.ecdh.private_key->devCtx;
|
||||
rc = wc_ecc_import_unsigned(info->pk.ecdh.private_key,
|
||||
ephemeralPubKey, &ephemeralPubKey[key_sz],
|
||||
NULL, ecc_curve);
|
||||
/* Restore devCtx in case import cleared it */
|
||||
if (saved_devCtx != NULL && info->pk.ecdh.private_key->devCtx != saved_devCtx) {
|
||||
info->pk.ecdh.private_key->devCtx = saved_devCtx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
XFREE(ephemeralPubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
#else /* WOLFSSL_STSAFEA100 */
|
||||
/* For A100/A110, ephemeral key generation in ECDH callback
|
||||
* is not supported. Keys must be generated in ephemeral slot
|
||||
* from the start for ECDH operations. */
|
||||
WOLFSSL_MSG("STSAFE: ECDH requires ephemeral slot - key must be generated in ephemeral slot");
|
||||
rc = stsafe_shared_secret(slot, curve_id,
|
||||
otherKeyX, otherKeyY,
|
||||
info->pk.ecdh.out, (int32_t*)info->pk.ecdh.outlen);
|
||||
if (rc != STSAFE_A_OK) {
|
||||
WOLFSSL_MSG("STSAFE: stsafe_shared_secret failed");
|
||||
STSAFE_INTERFACE_PRINTF("stsafe_shared_secret "
|
||||
"error: %d (slot: %d, curve_id: %d)\n",
|
||||
rc, slot, curve_id);
|
||||
rc = WC_HW_E;
|
||||
#endif
|
||||
} else {
|
||||
/* Key is already in ephemeral slot, use it */
|
||||
slot = STSAFE_KEY_SLOT_EPHEMERAL;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
STSAFE_INTERFACE_PRINTF("STSAFE: Computing shared secret with ephemeral slot %d, curve_id %d\n",
|
||||
slot, curve_id);
|
||||
rc = stsafe_shared_secret(slot, curve_id,
|
||||
otherKeyX, otherKeyY,
|
||||
info->pk.ecdh.out, (int32_t*)info->pk.ecdh.outlen);
|
||||
if (rc != STSAFE_A_OK) {
|
||||
WOLFSSL_MSG("STSAFE: stsafe_shared_secret failed");
|
||||
STSAFE_INTERFACE_PRINTF("stsafe_shared_secret error: %d (slot: %d, curve_id: %d)\n",
|
||||
rc, slot, curve_id);
|
||||
rc = WC_HW_E;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user