Hi.
I am implementing TLS 1.3 on NXP S32K314 Platform.
During the TLS handshake process, a SHARED SECRET is generated for hashing through HSE_GenerateDhSharedSecret() using the server's shared key and private key.
Can I extract the shared secret raw data through the created shared secret key handle?
When I export the shared secret key handle through HSE_ExportKey(), an HSE_SRV_RSP_NOT_ALLOWED error occurs. I need the shared secret key, not the key handle.
If it is not possible in HSE, please guide me on how to do this.
Below is debuggin code about this.
static psa_status_t hse_psa_raw_key_agreement(
psa_algorithm_t alg, psa_key_id_t private_key,
const uint8_t *peer_key, size_t peer_key_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
int ret = 0;
uint8_t hseEccCurveId = 0;
KeymgmtErrCodeT err;
key_import_param_t key_import_param_shared;
hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
hseKeyHandle_t peerKeyhandle = HSE_INVALID_KEY_HANDLE;
hseKeyHandle_t sharedSecretKeyHandle = HSE_INVALID_KEY_HANDLE;
psa_status_t status = PSA_SUCCESS;
hseKeyInfo_t reqKeyInfo = {0};
// Validate input parameters
if (peer_key == NULL || output == NULL || output_length == NULL)
{
return PSA_ERROR_INVALID_ARGUMENT;
}
// Only support ECDH algorithm for now
if (alg != PSA_ALG_ECDH)
{
return PSA_ERROR_NOT_SUPPORTED;
}
// Get private key attributes to determine curve
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
status = psa_get_key_attributes(private_key, &key_attributes);
if (status != PSA_SUCCESS)
{
return status;
}
// PSA Key attribute
psa_key_type_t key_type = psa_get_key_type(&key_attributes);
size_t key_bits = psa_get_key_bits(&key_attributes);
// check the algorithm
if (!PSA_ALG_IS_ECDH(alg))
{
return PSA_ERROR_NOT_SUPPORTED;
}
hseEccCurveId = HSE_EC_SEC_SECP521R1;
// Import peer Public Key
ret = hse_import_psa_public_key(peer_key, peer_key_length,
hseEccCurveId, &peerKeyhandle);
if (ret != 0)
{
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(&key_import_param_shared, 0x00, sizeof(key_import_param_t));
// Allocate the Slot for shared secret Key
key_import_param_shared.key_type = HSE_KEY_TYPE_SHARED_SECRET;
key_import_param_shared.key_catalog = HSE_KEY_CATALOG_ID_RAM;
key_import_param_shared.key_param.sym_key_param.size = 521; //key_bits;
//key_import_param_shared.key_flag = HSE_KF_USAGE_SIGN | HSE_KF_USAGE_VERIFY | HSE_KF_USAGE_EXCHANGE | HSE_KF_ACCESS_EXPORTABLE;
key_import_param_shared.key_flag = HSE_KF_USAGE_EXCHANGE | HSE_KF_ACCESS_EXPORTABLE;
/* key_import_param_shared.key_param.ecc_pubkey_param.size = key_bits / 8; */
err = KeystoreMgmt_FindAllocateSlot(&key_import_param_shared, &sharedSecretKeyHandle);
if (KEYMGMT_ERR_SUCCESS != err)
{
status = PSA_ERROR_HARDWARE_FAILURE;
goto cleanup;
}
// Create EDCH Shared secret key handle
srvResponse = HSE_GenerateDhSharedSecret(private_key, peerKeyhandle, sharedSecretKeyHandle);
/* Check the response */
switch(srvResponse)
{
case HSE_SRV_RSP_OK:
__printf("\nPrivate keyHandle 0x%02x | Peer KeyHandle : 0x%02x |"
" Shared Secret KeyHandle 0x%02x\r\n", private_key, peerKeyhandle, sharedSecretKeyHandle );
/* Copy shared secret key handle to Shared secret mpi z */
//ret = mbedtls_mpi_lset(output, (mbedtls_mpi_sint)sharedSecretKeyHandle );
/* Copy shared secret key handle to Shared secret mpi z */
srvResponse = HSE_GetKeyInfo(sharedSecretKeyHandle, &reqKeyInfo);
__printf("keyFlags : 0x%x\r\n", reqKeyInfo.keyFlags);
__printf("keyBitLen : 0x%x\r\n", reqKeyInfo.keyBitLen);
__printf("keyCounter : 0x%x\r\n", reqKeyInfo.keyCounter);
__printf("keyType : 0x%x\r\n", reqKeyInfo.keyType);
__printf("eccCurveId : 0x%x\r\n", reqKeyInfo.specific.eccCurveId);
if(reqKeyInfo.keyFlags & HSE_KF_ACCESS_EXPORTABLE)
__printf("%s: target key is exportable\r\n", __func__);
#ifdef GEN2_USING_SRAM_BUFF_FOR_HSE
{
uint8_t *output_data;
output_data = pvPortMalloc(output_size);
if (output_data)
{
ret = HSE_ExportKey(sharedSecretKeyHandle, &reqKeyInfo, output_data, output_size, NULL, 0UL, NULL, 0U);
//ret = HSE_ExportEccPubKey(sharedSecretKeyHandle, HSE_EC_SEC_SECP521R1, output_size, output_data);
if(ret == HSE_SRV_RSP_OK)
{
memcpy(output, output_data, output_size);
*output_length = output_size;
}
vPortFree(output_data);
}
else
{
ret = HSE_SRV_RSP_MEMORY_FAILURE;
}
}
#else
ret = HSE_ExportKey(sharedSecretKeyHandle, NULL, output, output_size, NULL, 0UL, NULL, 0U);
#endif
if(ret == HSE_SRV_RSP_OK)
{
__printf("%s: shared secret output (%d bytes): ", __func__, output_length);
for (size_t i = 0; i < output_length && i < 16; i++) {
__printf("%02x ", output[i]);
}
__printf("\n");
*output_length = key_bits / 8; // Set proper output length
status = PSA_SUCCESS;
}
else
{
__printf("%s: Key export failed: 0x%x\r\n", __func__, ret);
status = PSA_ERROR_INVALID_ARGUMENT;
}
break;
case HSE_SRV_RSP_INVALID_PARAM:
status = PSA_ERROR_INVALID_ARGUMENT;
break;
default:
status = PSA_ERROR_HARDWARE_FAILURE;
break;
}
cleanup:
if (peerKeyhandle != HSE_INVALID_KEY_HANDLE) {
nxp_hse_ecc_unloadkey(peerKeyhandle);
}
return status;
}