blob: a70631cfc2104fdb9078d477956557c6c53c1a8f [file] [log] [blame]
/**
* @file ex_hlse_config.c
* @author NXP Semiconductors
* @version 1.0
* @par License
*
* Copyright 2017 NXP
* SPDX-License-Identifier: Apache-2.0
*
* @par Description
* Example invocation of configure key specific functionality of the A71CH
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "a71ch_ex_hlse.h"
#include "a71_debug.h"
#include "sm_types.h"
#include "sm_apdu.h"
#include "ax_util.h"
#include "tst_sm_util.h"
#include "tst_a71ch_util.h"
#include "axHostCrypto.h"
#include "tstHostCrypto.h"
#include "tst_hlse_a71ch_util.h"
#include "HLSEAPI.h"
#include "HostCryptoAPI.h"
static U8 exSetConfigKey(U8 initMode);
static U8 exSstPubEnc(U8 initMode);
static U8 exSstPubEraseAfterInjectLock(void);
static U8 exSstKeyPairEnc(U8 initMode);
static U8 configKeyModuleLock[16]; //!< Configuration Key for Module, acting as transport key (index ::A71CH_CFG_KEY_IDX_MODULE_LOCK)
static U8 configKeyPrivateKey[16]; //!< Configuration Key for Private Key encryption (index ::A71CH_CFG_KEY_IDX_PRIVATE_KEYS)
static U8 configKeyPublicKey[16]; //!< Configuration Key for Public Key encryption (index ::A71CH_CFG_KEY_IDX_PUBLIC_KEYS)
#define EX_CONFIG_DEMO_LOCK_UNLOCK
#define EX_CONFIG_ALSO_USE_SCP03
/**
* Demonstrate storage and usage of config keys:
* - ::exSetConfigKey
* - ::exSstPubEnc
* - ::exSstKeyPairEnc
* - ::exSstPubEraseAfterInjectLock
*
*/
U8 exHlseConfig()
{
U8 result = 1;
int i = 0;
PRINTF( "\r\n-----------\r\nStart exConfig()\r\n------------\r\n");
DEV_ClearChannelState();
// Choose a (unique) pattern for each config key
for (i=0; i<16; i++) {
configKeyModuleLock[i] = (U8)(i ^ A71CH_CFG_KEY_IDX_MODULE_LOCK);
configKeyPrivateKey[i] = (U8)(i ^ A71CH_CFG_KEY_IDX_PRIVATE_KEYS);
configKeyPublicKey[i] = (U8)(i ^ A71CH_CFG_KEY_IDX_PUBLIC_KEYS);
}
// No channel encryption
// ---------------------
// - First set the config keys
result &= exSetConfigKey(INIT_MODE_RESET);
// - Set wrapped Public keys
result &= exSstPubEnc(INIT_MODE_NO_RESET);
// - Set wrapped key pairs (only private key is wrapped)
result &= exSstKeyPairEnc(INIT_MODE_NO_RESET);
// - Check on erasing Public keys after Module Inject Lock has been set
result &= exSstPubEraseAfterInjectLock();
#ifdef EX_CONFIG_ALSO_USE_SCP03
// Using channel encryption
// ------------------------
// - First set the config keysSym keys
result &= exSetConfigKey(INIT_MODE_RESET_DO_SCP03);
// - Set wrapped Public keys
result &= exSstPubEnc(INIT_MODE_NO_RESET);
// - Set wrapped key pairs (only private key is wrapped)
result &= exSstKeyPairEnc(INIT_MODE_NO_RESET);
// - Check on erasing Public keys after Module Inject Lock has been set
result &= exSstPubEraseAfterInjectLock();
#endif
// overall result
PRINTF( "\r\n-----------\r\nEnd exConfig(), result = %s\r\n------------\r\n", ((result == 1)? "OK": "FAILED"));
return result;
}
/**
* Demonstrate
* - setting config keys
* - use of transport key (config key at index ::A71CH_CFG_KEY_IDX_MODULE_LOCK) to lock/unlock A71CH
*
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter
*/
static U8 exSetConfigKey(U8 initMode)
{
U8 result = 1;
U16 err;
U8 uid[A71CH_MODULE_UNIQUE_ID_LEN] = {0};
U16 uidLen = sizeof(uid);
U8 challenge[A71CH_MODULE_UNLOCK_CHALLENGE_LEN] = {0};
U16 challengeLen = sizeof(challenge);
U8 unlockCode[A71CH_MODULE_UNLOCK_CHALLENGE_LEN] = {0};
S32 hcRet = 0;
U8 indexCfgKey = A71CH_CFG_KEY_IDX_MODULE_LOCK;
HLSE_OBJECT_HANDLE moduleHandle = 0;
U16 moduleHandleNum = 1;
PRINTF("\r\n-----------\r\nStart exSetConfigKey(%s)\r\n------------\r\n", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= hlse_a71chInitModule(initMode);
// Store all configure keys (value is stored in variables with module scope)
indexCfgKey = A71CH_CFG_KEY_IDX_MODULE_LOCK;
PRINTF("\r\nA71_SetConfigKey(0x%02x)\r\n", indexCfgKey);
#if 0
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyModuleLock, sizeof(configKeyModuleLock));
#else
{
HLSE_OBJECT_HANDLE handleCfgKeyModuleLock;
HLSE_OBJECT_INDEX index = indexCfgKey;
HLSE_OBJECT_TYPE objType = HLSE_CONFIG_KEY;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE;
attr[2].value = &configKeyModuleLock; // &smVal;
attr[2].valueLen = sizeof(configKeyModuleLock); //sizeof(smVal);
err = HLSE_CreateObject(attr, templateSize, &handleCfgKeyModuleLock);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyModuleLock", configKeyModuleLock, sizeof(configKeyModuleLock), AX_COLON_32);
indexCfgKey = A71CH_CFG_KEY_IDX_PRIVATE_KEYS;
PRINTF("\r\nA71_SetConfigKey(0x%02x)\r\n", indexCfgKey);
#if 0
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyPrivateKey, sizeof(configKeyPrivateKey));
#else
{
HLSE_OBJECT_HANDLE handleCfgKeyPrivateKey;
HLSE_OBJECT_INDEX index = indexCfgKey;
HLSE_OBJECT_TYPE objType = HLSE_CONFIG_KEY;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE;
attr[2].value = &configKeyPrivateKey;
attr[2].valueLen = sizeof(configKeyPrivateKey);
err = HLSE_CreateObject(attr, templateSize, &handleCfgKeyPrivateKey);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyPrivateKey", configKeyPrivateKey, sizeof(configKeyPrivateKey), AX_COLON_32);
indexCfgKey = A71CH_CFG_KEY_IDX_PUBLIC_KEYS;
PRINTF("\r\nA71_SetConfigKey(0x%02x)\r\n", indexCfgKey);
#if 0
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyPublicKey, sizeof(configKeyPublicKey));
#else
{
HLSE_OBJECT_HANDLE handleCfgKeyPublicKey;
HLSE_OBJECT_INDEX index = indexCfgKey;
HLSE_OBJECT_TYPE objType = HLSE_CONFIG_KEY;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE;
attr[2].value = &configKeyPublicKey;
attr[2].valueLen = sizeof(configKeyPublicKey);
err = HLSE_CreateObject(attr, templateSize, &handleCfgKeyPublicKey);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyPublicKey", configKeyPublicKey, sizeof(configKeyPublicKey), AX_COLON_32);
// Get the Module's handle
err = HLSE_EnumerateObjects(HLSE_MODULE, &moduleHandle, &moduleHandleNum);
result &= AX_CHECK_SW(err, HLSE_SW_OK, "err");
#ifdef EX_CONFIG_DEMO_LOCK_UNLOCK
// Lock device for transport
PRINTF("\r\nA71_LockModule()\r\n");
#if 0
err = A71_LockModule();
#else
{
HLSE_LIFE_CYCLE_STATE lifeCycleState = HLSE_MODULE_LOCKED;
HLSE_ATTRIBUTE attr;
attr.type = HLSE_ATTR_MODULE_TRANSPORT_LOCK_STATE;
attr.value = &lifeCycleState;
attr.valueLen = sizeof(lifeCycleState);
err = HLSE_SetObjectAttribute(moduleHandle, &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
PRINTF("\r\nA71_GetUniqueID().\r\n");
#if 0
err = A71_GetUniqueID(uid, &uidLen);
#else
{
HLSE_ATTRIBUTE attr;
attr.type = HLSE_ATTR_MODULE_UNIQUE_ID;
attr.value = uid;
attr.valueLen = uidLen;
err = HLSE_GetObjectAttribute(moduleHandle, &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("uid", uid, uidLen, AX_COLON_32);
PRINTF("\r\nA71_GetUnlockChallenge().\r\n");
#if 0
err = A71_GetUnlockChallenge(challenge, &challengeLen);
#else
{
HLSE_ATTRIBUTE attr;
attr.type = HLSE_ATTR_MODULE_UNLOCK_CHALLENGE;
attr.value = challenge;
attr.valueLen = challengeLen;
err = HLSE_GetObjectAttribute(moduleHandle, &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("challenge", challenge, challengeLen, AX_COLON_32);
// Decrypt challenge
hcRet = HOST_AES_ECB_DECRYPT(unlockCode, challenge, configKeyModuleLock, sizeof(configKeyModuleLock));
if (hcRet != HOST_CRYPTO_OK)
{
PRINTF("HOST_AES_ECB_DECRYPT: failed.\r\n");
result = 0;
}
PRINTF("\r\nA71_UnlockModule()\r\n");
#if 0
err = A71_UnlockModule(unlockCode, 16);
#else
{
HLSE_A71_MODULE_UNLOCK_PARAMS moduleUnlockVal;
HLSE_ATTRIBUTE attr;
moduleUnlockVal.lockMode = HLSE_MODULE_UNLOCKED;
memcpy(&moduleUnlockVal.response, unlockCode, 16);
attr.type = HLSE_ATTR_MODULE_TRANSPORT_LOCK_STATE;
attr.value = &moduleUnlockVal;
attr.valueLen = sizeof(moduleUnlockVal);
err = HLSE_SetObjectAttribute(moduleHandle, &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
#endif
PRINTF( "\r\n-----------\r\nEnd exSetConfigKey(%s), result = %s\r\n------------\r\n", getInitModeAsString(initMode), ((result == 1)? "OK": "FAILED"));
return result;
}
/**
* Demonstrate
* - setting a wrapped public key
* - demonstrate key can be used through verify operation
*
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter
*/
static U8 exSstPubEnc(U8 initMode)
{
U8 result = 1;
U16 err;
int i;
ECCCurve_t eccCurve = ECCCurve_NIST_P256;
EC_KEY *eccKeyCA[A71CH_PUBLIC_KEY_MAX] = {0};
eccKeyComponents_t eccKcCA[A71CH_PUBLIC_KEY_MAX] = {0};
U8 fetchedPubKey[65];
U16 fetchedPubKeyLen = sizeof(fetchedPubKey);
// const U16 expectedPubKeyLen = 65;
const U16 expectedPrivKeyLen = 32;
// to hold handles for created keys
HLSE_OBJECT_HANDLE handles[A71CH_PUBLIC_KEY_MAX] = {0};
PRINTF("\r\n-----------\r\nStart exSstPubEnc(%s)\r\n------------\r\n", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= hlse_a71chInitModule(initMode);
// Start by creating, inserting and checking keys
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
U8 wrappedKey[64+8];
U16 wrappedKeyLen = sizeof(wrappedKey);
eccKeyCA[i] = NULL;
err = HOSTCRYPTO_GenerateEccKey(eccCurve, &eccKeyCA[i]);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPublicKey(eccKeyCA[i], eccKcCA[i].pub, &(eccKcCA[i].pubLen), (64 << 1)+1);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPrivateKey(eccKeyCA[i], eccKcCA[i].priv, &(eccKcCA[i].privLen), 64);
result &= AX_CHECK_SW(err, SW_OK, "err");
eccKcCA[i].bits = expectedPrivKeyLen << 3;
eccKcCA[i].curve = eccCurve;
// Wrap public key (strip first character before wrapping) on host
PRINTF("\r\nHOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)\r\n", (SST_Index_t)i);
err = HOSTCRYPTO_AesWrapKeyRFC3394(configKeyPublicKey, sizeof(configKeyPublicKey),
wrappedKey, &wrappedKeyLen, &(eccKcCA[i].pub[1]), eccKcCA[i].pubLen - 1);
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("wrappedKey", wrappedKey, wrappedKeyLen, AX_COLON_32);
PRINTF( "\r\nA71_SetEccPublicKey(0x%02X)\r\n", (SST_Index_t)i);
#if 0
err = A71_SetEccPublicKey ((SST_Index_t) i, wrappedKey, wrappedKeyLen);
#else
{
HLSE_OBJECT_INDEX index = i;
HLSE_OBJECT_TYPE objType = HLSE_PUBLIC_KEY;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE;
attr[2].value = wrappedKey;
attr[2].valueLen = wrappedKeyLen;
err = HLSE_CreateObject(attr, templateSize, &handles[i]);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Read out and verify public key
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
HLSE_ATTRIBUTE attr;
PRINTF( "\r\nA71_GetEccPublicKey(0x%02X)\r\n", (SST_Index_t)i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetEccPublicKey ((SST_Index_t) i, fetchedPubKey, &fetchedPubKeyLen);
#else
attr.type = HLSE_ATTR_OBJECT_VALUE;
attr.value = fetchedPubKey;
attr.valueLen = fetchedPubKeyLen;
err = HLSE_GetObjectAttribute(handles[i], &attr);
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// Compare with reference value
result &= AX_COMPARE_BYTE_ARRAY("eccKcCA[i].pub", eccKcCA[i].pub, eccKcCA[i].pubLen,
"fetchedPubKey", fetchedPubKey, fetchedPubKeyLen, AX_COLON_32);
}
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
HOSTCRYPTO_FreeEccKey(&eccKeyCA[i]);
}
PRINTF( "\r\n-----------\r\nEnd exSstPubEnc(%s), result = %s\r\n------------\r\n", getInitModeAsString(initMode),
((result == 1)? "OK": "FAILED"));
return result;
}
/**
* Demonstrate
* - Once the module Inject Lock has been set, its only possible to erase a public key
* through a challenge response protocol
*
*/
static U8 exSstPubEraseAfterInjectLock()
{
U8 result = 1;
U16 err;
int i;
// ECCCurve_t eccCurve = ECCCurve_NIST_P256;
// EC_KEY *eccKeyCA[A71CH_PUBLIC_KEY_MAX] = {0};
// eccKeyComponents_t eccKcCA[A71CH_PUBLIC_KEY_MAX] = {0};
U8 fetchedPubKey[65];
U16 fetchedPubKeyLen = sizeof(fetchedPubKey);
// const U16 expectedPubKeyLen = 65;
// const U16 expectedPrivKeyLen = 32;
HLSE_OBJECT_HANDLE handles[A71CH_PUBLIC_KEY_MAX] = {0};
U16 handleNum = A71CH_PUBLIC_KEY_MAX;
err = HLSE_EnumerateObjects(HLSE_PUBLIC_KEY, handles, &handleNum);
result &= AX_CHECK_SW(err, HLSE_SW_OK, "err");
if ((err != HLSE_SW_OK)) {
return 0;
}
PRINTF("\r\n-----------\r\nStart exSstPubEraseAfterInjectLock()\r\n------------\r\n");
// Check whether ErasePublicKey - without challenge/response - fails
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
PRINTF( "\r\nA71_EraseEccPublicKey(0x%02X)\r\n", (SST_Index_t)i);
#if 0
err = A71_EraseEccPublicKey((SST_Index_t) i);
result &= AX_CHECK_SW(err, SW_WRONG_DATA, "err");
#else
if (i < handleNum ) {
err = HLSE_EraseObject(handles[i]);
result &= AX_CHECK_SW(err, SW_WRONG_DATA, "err");
}
#endif
}
// Confirm reading out public key is still possible
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
PRINTF("\r\nA71_GetEccPublicKey (index=0x%02X)\r\n", i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetEccPublicKey ((SST_Index_t)i, fetchedPubKey, &fetchedPubKeyLen);
result &= AX_CHECK_SW(err, SW_OK, "Failed to retrieve Public Ecc Key");
#else
if (i < handleNum) {
err = hlse_GetEccPublicKey(fetchedPubKey, &fetchedPubKeyLen, &handles[i]);
result &= AX_CHECK_SW(err, SW_OK, "Failed to retrieve Public Ecc Key");
}
#endif
}
// Do a ErasePublicKey with challenge response
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
PRINTF( "\r\nA71_EraseEccPublicKeyWithChallenge(0x%02X)\r\n", (SST_Index_t)i);
err = A71_EraseEccPublicKeyWithChallenge((SST_Index_t) i, configKeyPublicKey, sizeof(configKeyPublicKey));
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Check whether reading out (erased) public key now fails.
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
PRINTF("\r\nA71_GetEccPublicKey (index=0x%02X)\r\n", i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetEccPublicKey ((SST_Index_t)i, fetchedPubKey, &fetchedPubKeyLen);
result &= AX_CHECK_SW(err, SW_CONDITIONS_NOT_SATISFIED, "Get Public Ecc Key was supposed to fail");
#else
if (i < handleNum) {
err = hlse_GetEccPublicKey(fetchedPubKey, &fetchedPubKeyLen, &handles[i]);
result &= AX_CHECK_SW(err, SW_CONDITIONS_NOT_SATISFIED, "Get Public Ecc Key was supposed to fail");
}
#endif
}
PRINTF( "\r\n-----------\r\nEnd exSstPubEraseAfterInjectLock(), result = %s\r\n------------\r\n",
((result == 1)? "OK": "FAILED"));
return result;
}
/**
* Demonstrate
* - setting (encrypted)/getting/erasing of key pairs
* - demonstrate key can be used through sign operations
* - demonstrate a plain key pair can not be inserted once 'inject lock' has been enabled
* - demonstrate a keywrapped key pair can still be inserted
* - demonstrate generating a key pair is conditional on a correct challenge/response
*
* @param[in] initMode Visit the documentation of ::a71chInitModule for more information on this parameter
*/
static U8 exSstKeyPairEnc(U8 initMode)
{
U8 result = 1;
U16 err;
int i;
HLSE_RET_CODE retcode;
ECCCurve_t eccCurve = ECCCurve_NIST_P256;
EC_KEY *eccKeyTls[A71CH_KEY_PAIR_MAX] = { 0 };
eccKeyComponents_t eccKcTls[A71CH_KEY_PAIR_MAX] = { 0 };
EC_KEY *eccKeyAlt = NULL;
eccKeyComponents_t eccKcAlt;
U8 fetchedPubKey[65];
U16 fetchedPubKeyLen = sizeof(fetchedPubKey);
U8 hashSha256[32];
U16 hashSha256Len = sizeof(hashSha256);
U8 signature[128];
U16 signatureLen = sizeof(signature);
// const U16 expectedPubKeyLen = 65;
const U16 expectedPrivKeyLen = 32;
U8 wrappedPrivKey[32+8];
U16 wrappedPrivKeyLen = sizeof(wrappedPrivKey);
SST_Index_t kpIndex;
// to hold handles for created keys
HLSE_OBJECT_HANDLE handles[A71CH_KEY_PAIR_MAX] = {0};
HLSE_OBJECT_HANDLE moduleHandle = 0;
U16 moduleHandleNum = 1;
HLSE_MECHANISM_INFO mechInfo;
PRINTF("\r\n-----------\r\nStart exSstKeyPairEnc(%s)\r\n------------\r\n", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= hlse_a71chInitModule(initMode);
// Start by creating, inserting and checking keys
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
eccKeyTls[i] = NULL;
err = HOSTCRYPTO_GenerateEccKey(eccCurve, &eccKeyTls[i]);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPublicKey(eccKeyTls[i], eccKcTls[i].pub, &(eccKcTls[i].pubLen), (64 << 1)+1);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPrivateKey(eccKeyTls[i], eccKcTls[i].priv, &(eccKcTls[i].privLen), 64);
result &= AX_CHECK_SW(err, SW_OK, "err");
eccKcTls[i].bits = expectedPrivKeyLen << 3;
eccKcTls[i].curve = eccCurve;
// Wrap private key on host
wrappedPrivKeyLen = sizeof(wrappedPrivKey);
PRINTF("\r\nHOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)\r\n", (SST_Index_t)i);
err = HOSTCRYPTO_AesWrapKeyRFC3394(configKeyPrivateKey, sizeof(configKeyPrivateKey),
wrappedPrivKey, &wrappedPrivKeyLen, eccKcTls[i].priv, eccKcTls[i].privLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("wrappedPrivKey", wrappedPrivKey, wrappedPrivKeyLen, AX_COLON_32);
PRINTF( "\r\nA71_SetEccKeyPair(0x%02X)\r\n", (SST_Index_t)i);
#if 0
err = A71_SetEccKeyPair((SST_Index_t) i, eccKcTls[i].pub, eccKcTls[i].pubLen,
wrappedPrivKey, wrappedPrivKeyLen);
#else
{
// to hold wrapped private key + public key
U8 keyPair[40 + 65];
HLSE_OBJECT_INDEX index = i;
HLSE_OBJECT_TYPE objType = HLSE_KEY_PAIR;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
memcpy(keyPair, wrappedPrivKey, 40);
memcpy(keyPair + 40, eccKcTls[i].pub, 65);
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_WRAPPED_OBJECT_VALUE;
attr[2].value = keyPair;
attr[2].valueLen = sizeof(keyPair);
err = HLSE_CreateObject(attr, templateSize, &handles[i]);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Read out and verify public key
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
HLSE_ATTRIBUTE attr;
PRINTF( "\r\nA71_GetPublicKeyEccKeyPair (0x%02X)\r\n", (SST_Index_t)i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t) i, fetchedPubKey, &fetchedPubKeyLen);
#else
attr.type = HLSE_ATTR_OBJECT_VALUE;
attr.value = fetchedPubKey;
attr.valueLen = fetchedPubKeyLen;
err = HLSE_GetObjectAttribute(handles[i], &attr);
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// Compare with reference value
result &= AX_COMPARE_BYTE_ARRAY("eccKcTls[i].pub", eccKcTls[i].pub, eccKcTls[i].pubLen,
"fetchedPubKey", fetchedPubKey, fetchedPubKeyLen, AX_COLON_32);
}
// Create alternative key
err = HOSTCRYPTO_GenerateEccKey(eccCurve, &eccKeyAlt);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPublicKey(eccKeyAlt, eccKcAlt.pub, &(eccKcAlt.pubLen), (64 << 1)+1);
result &= AX_CHECK_SW(err, SW_OK, "err");
err = HOSTCRYPTO_GetPrivateKey(eccKeyAlt, eccKcAlt.priv, &(eccKcAlt.privLen), 64);
result &= AX_CHECK_SW(err, SW_OK, "err");
eccKcAlt.bits = expectedPrivKeyLen << 3;
eccKcAlt.curve = eccCurve;
HOSTCRYPTO_FreeEccKey(&eccKeyAlt);
// Fill up the hash with some reference data
hashSha256Len = sizeof(hashSha256);
for (i=0; i<hashSha256Len; i++) { hashSha256[i] = (U8)i; }
// Sign a hash of correct length on the A71CH and do the verification on the Host
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
signatureLen = sizeof(signature);
PRINTF("\r\nA71_EccSign(0x%02X)\r\n", (SST_Index_t)i);
#if 0
err = A71_EccSign((SST_Index_t)i, hashSha256, hashSha256Len, signature, &signatureLen);
#else
err = hlse_EccSign(handles[i], hashSha256, hashSha256Len, signature, &signatureLen);
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// Verify ... on opposite platform
PRINTF("\r\n(Host)ECDSA_verify API with eccKeyTls[i] (verify signature created on A71CH).\r\n");
memset(&mechInfo, 0, sizeof(mechInfo));
mechInfo.mechanism = HLSE_ECDSA_VERIFY;
retcode = HLCRYPT_Verify(&mechInfo,(U8 *)eccKeyTls[i],0,hashSha256,hashSha256Len,signature,signatureLen);
if (retcode == HLSE_SW_OK)
{
PRINTF("Verification OK for eccKeyTls[i].\r\n");
}
else
{
PRINTF("Return value: %d, Verification Not OK for eccKeyTls[i]. Test Failed!\r\n", retcode);
result &= 0;
break;
}
}
// Erase the keypair at index 0 & verify the value is no longer readable
// ** Erase **
kpIndex = A71CH_KEY_PAIR_0;
PRINTF("\r\nA71_EraseEccKeyPair(index=0x%02X)\r\n", kpIndex);
#if 0
err = A71_EraseEccKeyPair(kpIndex);
#else
err = HLSE_EraseObject(handles[kpIndex]);
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// ** Check whether erase was effective **
PRINTF("\r\nA71_GetPublicKeyEccKeyPair (index=0x%02X)\r\n", kpIndex);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t)kpIndex, fetchedPubKey, &fetchedPubKeyLen);
#else
{
HLSE_ATTRIBUTE attr;
attr.type = HLSE_ATTR_OBJECT_VALUE;
attr.value = fetchedPubKey;
attr.valueLen = fetchedPubKeyLen;
err = HLSE_GetObjectAttribute(handles[kpIndex], &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_CONDITIONS_NOT_SATISFIED, "Get Public Ecc Key was supposed to fail");
// Now disable the plain insertion/reading out of Symmetric keys & Keypairs
PRINTF("\r\nA71_InjectLock()\r\n");
#if 0
err = A71_InjectLock();
#else
// Get the Module's handle
err = HLSE_EnumerateObjects(HLSE_MODULE, &moduleHandle, &moduleHandleNum);
result &= AX_CHECK_SW(err, HLSE_SW_OK, "err");
{
HLSE_LIFE_CYCLE_STATE lifeCycleState = HLSE_INJECT_LOCKED;
HLSE_ATTRIBUTE attr;
attr.type = HLSE_ATTR_MODULE_INJECTION_LOCK_STATE;
attr.value = &lifeCycleState;
attr.valueLen = sizeof(lifeCycleState);
err = HLSE_SetObjectAttribute(moduleHandle, &attr);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
assert(result);
// Check whether the plain inject has been disabled (check only first key pair)
PRINTF( "\r\nA71_SetEccKeyPair(0x%02x)\r\n", kpIndex);
#if 0
err = A71_SetEccKeyPair((SST_Index_t)kpIndex, eccKcAlt.pub, eccKcAlt.pubLen, eccKcAlt.priv, eccKcAlt.privLen);
#else
{
// to hold wrapped private key + public key
U8 keyPair[40 + 65];
HLSE_OBJECT_INDEX index = kpIndex;
HLSE_OBJECT_TYPE objType = HLSE_KEY_PAIR;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
memcpy(keyPair, eccKcAlt.priv, eccKcAlt.privLen);
memcpy(keyPair + eccKcAlt.privLen, eccKcAlt.pub, 65);
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE; // plain
attr[2].value = keyPair;
attr[2].valueLen = eccKcAlt.privLen + eccKcAlt.pubLen;
err = HLSE_CreateObject(attr, templateSize, &handles[kpIndex]);
}
#endif
result &= AX_CHECK_SW(err, SW_COMMAND_NOT_ALLOWED, "Expected to fail, frozen credential cannot be overwritten");
// Put back the original (reference) value in the first slot, now first wrap private key on host
wrappedPrivKeyLen = sizeof(wrappedPrivKey);
PRINTF("\r\nHOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)\r\n", (SST_Index_t)kpIndex);
err = HOSTCRYPTO_AesWrapKeyRFC3394(configKeyPrivateKey, sizeof(configKeyPrivateKey),
wrappedPrivKey, &wrappedPrivKeyLen, eccKcTls[kpIndex].priv, eccKcTls[kpIndex].privLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("wrappedPrivKey", wrappedPrivKey, wrappedPrivKeyLen, AX_COLON_32);
PRINTF( "\r\nA71_SetEccKeyPair(0x%02X)\r\n", (SST_Index_t)kpIndex);
#if 0
err = A71_SetEccKeyPair((SST_Index_t) kpIndex, eccKcTls[kpIndex].pub, eccKcTls[kpIndex].pubLen,
wrappedPrivKey, wrappedPrivKeyLen);
#else
{
// to hold wrapped private key + public key
U8 keyPair[40 + 65];
HLSE_OBJECT_INDEX index = kpIndex;
HLSE_OBJECT_TYPE objType = HLSE_KEY_PAIR;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
memcpy(keyPair, wrappedPrivKey, 40);
memcpy(keyPair + 40, eccKcTls[kpIndex].pub, 65);
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_WRAPPED_OBJECT_VALUE;
attr[2].value = keyPair;
attr[2].valueLen = sizeof(keyPair);
err = HLSE_CreateObject(attr, templateSize, &handles[kpIndex]);
}
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// Check all keys are still fine by doing a sign/verify operation
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
signatureLen = sizeof(signature);
PRINTF("\r\nA71_EccSign(0x%02X)\r\n", (SST_Index_t)i);
#if 0
err = A71_EccSign((SST_Index_t)i, hashSha256, hashSha256Len, signature, &signatureLen);
#else
err = hlse_EccSign(handles[i], hashSha256, hashSha256Len, signature, &signatureLen);
#endif
result &= AX_CHECK_SW(err, SW_OK, "err");
// Verify ... on opposite platform
PRINTF("\r\n(Host)ECDSA_verify API with eccKeyTls[i] (verify signature created on A71CH).\r\n");
memset(&mechInfo, 0, sizeof(mechInfo));
mechInfo.mechanism = HLSE_ECDSA_VERIFY;
retcode = HLCRYPT_Verify(&mechInfo,(U8 *)eccKeyTls[i],0,hashSha256,hashSha256Len,signature,signatureLen);
if (retcode == HLSE_SW_OK)
{
PRINTF("Verification OK for eccKeyTls[i].\r\n");
}
else
{
PRINTF("Return value: %d, Verification Not OK for eccKeyTls[i]. Test Failed!\r\n", retcode);
result &= 0;
break;
}
}
// Check whether the plain inject has been disabled (for all key pair)
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF( "\r\nA71_SetEccKeyPair(0x%02X)\r\n", (SST_Index_t)kpIndex);
#if 0
err = A71_SetEccKeyPair((SST_Index_t) kpIndex, eccKcTls[kpIndex].pub, eccKcTls[kpIndex].pubLen,
eccKcTls[kpIndex].priv, eccKcTls[kpIndex].privLen);
#else
{
// to hold private key + public key
U8 keyPair[40 + 65];
HLSE_OBJECT_INDEX index = kpIndex;
HLSE_OBJECT_TYPE objType = HLSE_KEY_PAIR;
HLSE_ATTRIBUTE attr[3];
unsigned short templateSize = 3;
memcpy(keyPair, eccKcTls[kpIndex].priv, eccKcTls[kpIndex].privLen);
memcpy(keyPair + eccKcTls[kpIndex].privLen, eccKcTls[kpIndex].pub, 65);
attr[0].type = HLSE_ATTR_OBJECT_TYPE;
attr[0].value = &objType;
attr[0].valueLen = sizeof(objType);
attr[1].type = HLSE_ATTR_OBJECT_INDEX;
attr[1].value = &index;
attr[1].valueLen = sizeof(index);
attr[2].type = HLSE_ATTR_OBJECT_VALUE; // plain
attr[2].value = keyPair;
attr[2].valueLen = eccKcTls[kpIndex].privLen + eccKcTls[kpIndex].pubLen;
err = HLSE_CreateObject(attr, templateSize, &handles[kpIndex]);
}
#endif
result &= AX_CHECK_SW(err, SW_COMMAND_NOT_ALLOWED, "err");
}
// Check whether GenerateKeyPair - without challenge/response - fails
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF( "\r\nA71_GenerateEccKeyPair(0x%02X)\r\n", (SST_Index_t)kpIndex);
#if 0
err = A71_GenerateEccKeyPair((SST_Index_t) kpIndex);
#else
err = hlse_GenerateEccKeyPair(kpIndex, &handles[kpIndex]);
#endif
result &= AX_CHECK_SW(err, SW_COMMAND_NOT_ALLOWED, "err");
}
// Do a GenerateKeyPair with challenge response
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF( "\r\nA71_GenerateEccKeyPairWithChallenge(0x%02X)\r\n", (SST_Index_t)kpIndex);
err = A71_GenerateEccKeyPairWithChallenge((SST_Index_t) kpIndex, configKeyPrivateKey, sizeof(configKeyPrivateKey));
result &= AX_CHECK_SW(err, SW_OK, "err");
}
//!< \todo Extend example program to check whether there's a new keypair inside A71CH
// Check whether EraseKeyPair - without challenge/response - fails
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF( "\r\nA71_EraseEccKeyPair(0x%02X)\r\n", (SST_Index_t)kpIndex);
#if 0
err = A71_EraseEccKeyPair((SST_Index_t) kpIndex);
#else
err = HLSE_EraseObject(handles[kpIndex]);
#endif
result &= AX_CHECK_SW(err, SW_WRONG_DATA, "err");
}
// Do a EraseKeyPair with challenge response
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF( "\r\nA71_EraseEccKeyPairWithChallenge(0x%02X)\r\n", (SST_Index_t)kpIndex);
err = A71_EraseEccKeyPairWithChallenge((SST_Index_t) kpIndex, configKeyPrivateKey, sizeof(configKeyPrivateKey));
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Check whether reading out public key from erased keypairs now fails.
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
PRINTF("\r\nA71_GetPublicKeyEccKeyPair (index=0x%02X)\r\n", kpIndex);
fetchedPubKeyLen = sizeof(fetchedPubKey);
#if 0
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t)kpIndex, fetchedPubKey, &fetchedPubKeyLen);
#else
err = hlse_GetEccPublicKey(fetchedPubKey, &fetchedPubKeyLen, &handles[kpIndex]);
#endif
result &= AX_CHECK_SW(err, SW_CONDITIONS_NOT_SATISFIED, "Get Public Ecc Key was supposed to fail");
}
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
HOSTCRYPTO_FreeEccKey(&eccKeyTls[i]);
}
PRINTF( "\r\n-----------\r\nEnd exSstKeyPairEnc(%s), result = %s\r\n------------\r\n", getInitModeAsString(initMode),
((result == 1)? "OK": "FAILED"));
return result;
}