blob: 3f65436e471c6e10b65acdb1c6340c3dcdcc731f [file] [log] [blame]
/**
* @file ex_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.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 "HostCryptoAPI.h"
#include "nxLog_hostLib.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 exConfig()
{
U8 result = 1;
int i = 0;
LOG_I( "-----------Start exConfig()------------");
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
LOG_I( "-----------End exConfig(), result = %s------------", ((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;
LOG_I("-----------Start exSetConfigKey(%s)------------", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= a71chInitModule(initMode);
// Store all configure keys (value is stored in variables with module scope)
indexCfgKey = A71CH_CFG_KEY_IDX_MODULE_LOCK;
LOG_I("A71_SetConfigKey(0x%02x)", indexCfgKey);
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyModuleLock, sizeof(configKeyModuleLock));
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyModuleLock", configKeyModuleLock, sizeof(configKeyModuleLock), AX_COLON_32);
indexCfgKey = A71CH_CFG_KEY_IDX_PRIVATE_KEYS;
LOG_I("A71_SetConfigKey(0x%02x)", indexCfgKey);
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyPrivateKey, sizeof(configKeyPrivateKey));
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyPrivateKey", configKeyPrivateKey, sizeof(configKeyPrivateKey), AX_COLON_32);
indexCfgKey = A71CH_CFG_KEY_IDX_PUBLIC_KEYS;
LOG_I("A71_SetConfigKey(0x%02x)", indexCfgKey);
err = A71_SetConfigKey((SST_Index_t)indexCfgKey, configKeyPublicKey, sizeof(configKeyPublicKey));
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("configKeyPublicKey", configKeyPublicKey, sizeof(configKeyPublicKey), AX_COLON_32);
#ifdef EX_CONFIG_DEMO_LOCK_UNLOCK
// Lock device for transport
LOG_I("A71_LockModule()");
err = A71_LockModule();
result &= AX_CHECK_SW(err, SW_OK, "err");
LOG_I("A71_GetUniqueID().");
err = A71_GetUniqueID(uid, &uidLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
axPrintByteArray("uid", uid, uidLen, AX_COLON_32);
LOG_I("A71_GetUnlockChallenge().");
err = A71_GetUnlockChallenge(challenge, &challengeLen);
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)
{
LOG_E("HOST_AES_ECB_DECRYPT: failed.");
result = 0;
}
LOG_I("A71_UnlockModule()");
err = A71_UnlockModule(unlockCode, 16);
result &= AX_CHECK_SW(err, SW_OK, "err");
#endif
LOG_I( "-----------End exSetConfigKey(%s), result = %s------------", 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;
LOG_I("-----------Start exSstPubEnc(%s)------------", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= 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
LOG_I("HOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)", (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);
LOG_I( "A71_SetEccPublicKey(0x%02X)", (SST_Index_t)i);
err = A71_SetEccPublicKey ((SST_Index_t) i, wrappedKey, wrappedKeyLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Read out and verify public key
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
LOG_I( "A71_GetEccPublicKey(0x%02X)", (SST_Index_t)i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
err = A71_GetEccPublicKey ((SST_Index_t) i, fetchedPubKey, &fetchedPubKeyLen);
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]);
}
LOG_I( "-----------End exSstPubEnc(%s), result = %s------------", 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;
LOG_I("-----------Start exSstPubEraseAfterInjectLock()------------");
// Check whether ErasePublicKey - without challenge/response - fails
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
LOG_I( "A71_EraseEccPublicKey(0x%02X)", (SST_Index_t)i);
err = A71_EraseEccPublicKey((SST_Index_t) i);
result &= AX_CHECK_SW(err, SW_WRONG_DATA, "err");
}
// Confirm reading out public key is still possible
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
LOG_I("A71_GetEccPublicKey (index=0x%02X)", i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
err = A71_GetEccPublicKey ((SST_Index_t)i, fetchedPubKey, &fetchedPubKeyLen);
result &= AX_CHECK_SW(err, SW_OK, "Failed to retrieve Public Ecc Key");
}
// Do a ErasePublicKey with challenge response
for (i=0; i<A71CH_PUBLIC_KEY_MAX; i++)
{
LOG_I( "A71_EraseEccPublicKeyWithChallenge(0x%02X)", (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++)
{
LOG_I("A71_GetEccPublicKey (index=0x%02X)", i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
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");
}
LOG_I( "-----------End exSstPubEraseAfterInjectLock(), result = %s------------",
((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
* @param[in] appletVersion See #SmCommState_t::appletVersion
*/
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);
HLSE_MECHANISM_INFO mechInfo;
// const U16 expectedPubKeyLen = 65;
const U16 expectedPrivKeyLen = 32;
U8 wrappedPrivKey[32+8];
U16 wrappedPrivKeyLen = sizeof(wrappedPrivKey);
SST_Index_t kpIndex;
LOG_I("-----------Start exSstKeyPairEnc(%s)------------", getInitModeAsString(initMode));
// Initialize the A71CH (Debug mode restrictions may apply)
result &= 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);
LOG_I("HOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)", (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);
LOG_I( "A71_SetEccKeyPair(0x%02X)", (SST_Index_t)i);
err = A71_SetEccKeyPair((SST_Index_t) i, eccKcTls[i].pub, eccKcTls[i].pubLen,
wrappedPrivKey, wrappedPrivKeyLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
}
// Read out and verify public key
for (i=0; i<A71CH_KEY_PAIR_MAX; i++)
{
LOG_I( "A71_GetPublicKeyEccKeyPair (0x%02X)", (SST_Index_t)i);
fetchedPubKeyLen = sizeof(fetchedPubKey);
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t) i, fetchedPubKey, &fetchedPubKeyLen);
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);
LOG_I("A71_EccSign(0x%02X)", (SST_Index_t)i);
err = A71_EccSign((SST_Index_t)i, hashSha256, hashSha256Len, signature, &signatureLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
// Verify ... on opposite platform
LOG_I("(Host)ECDSA_verify API with eccKeyTls[i] (verify signature created on A71CH).");
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)
{
LOG_I("Verification OK for eccKeyTls[i].");
}
else
{
LOG_E("Return value: %d, Verification Not OK for eccKeyTls[i]. Test Failed!", retcode);
result &= 0;
break;
}
}
// Erase the keypair at index 0 & verify the value is no longer readable
// ** Erase **
kpIndex = A71CH_KEY_PAIR_0;
LOG_I("A71_EraseEccKeyPair(index=0x%02X)", kpIndex);
err = A71_EraseEccKeyPair(kpIndex);
result &= AX_CHECK_SW(err, SW_OK, "err");
// ** Check whether erase was effective **
LOG_I("A71_GetPublicKeyEccKeyPair (index=0x%02X)", kpIndex);
fetchedPubKeyLen = sizeof(fetchedPubKey);
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t)kpIndex, fetchedPubKey, &fetchedPubKeyLen);
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
LOG_I("A71_InjectLock()");
err = A71_InjectLock();
result &= AX_CHECK_SW(err, SW_OK, "err");
assert(result);
// Check whether the plain inject has been disabled (check only first key pair)
LOG_I( "A71_SetEccKeyPair(0x%02x)", kpIndex);
err = A71_SetEccKeyPair((SST_Index_t)kpIndex, eccKcAlt.pub, eccKcAlt.pubLen, eccKcAlt.priv, eccKcAlt.privLen);
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);
LOG_I("HOSTCRYPTO_AesWrapKeyRFC3394(0x%02X)", (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);
LOG_I( "A71_SetEccKeyPair(0x%02X)", (SST_Index_t)kpIndex);
err = A71_SetEccKeyPair((SST_Index_t) kpIndex, eccKcTls[kpIndex].pub, eccKcTls[kpIndex].pubLen,
wrappedPrivKey, wrappedPrivKeyLen);
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);
LOG_I("A71_EccSign(0x%02X)", (SST_Index_t)i);
err = A71_EccSign((SST_Index_t)i, hashSha256, hashSha256Len, signature, &signatureLen);
result &= AX_CHECK_SW(err, SW_OK, "err");
// Verify ... on opposite platform
LOG_I("(Host)ECDSA_verify API with eccKeyTls[i] (verify signature created on A71CH).");
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)
{
LOG_I("Verification OK for eccKeyTls[i].");
}
else
{
LOG_E("Return value: %d, Verification Not OK for eccKeyTls[i]. Test Failed!", 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++)
{
LOG_I( "A71_SetEccKeyPair(0x%02X)", (SST_Index_t)kpIndex);
err = A71_SetEccKeyPair((SST_Index_t) kpIndex, eccKcTls[kpIndex].pub, eccKcTls[kpIndex].pubLen,
eccKcTls[kpIndex].priv, eccKcTls[kpIndex].privLen);
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++)
{
LOG_I( "A71_GenerateEccKeyPair(0x%02X)", (SST_Index_t)kpIndex);
err = A71_GenerateEccKeyPair((SST_Index_t) kpIndex);
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++)
{
LOG_I( "A71_GenerateEccKeyPairWithChallenge(0x%02X)", (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++)
{
LOG_I( "A71_EraseEccKeyPair(0x%02X)", (SST_Index_t)kpIndex);
err = A71_EraseEccKeyPair((SST_Index_t) kpIndex);
result &= AX_CHECK_SW(err, SW_WRONG_DATA, "err");
}
// Do a EraseKeyPair with challenge response
for (kpIndex=0; kpIndex<A71CH_KEY_PAIR_MAX; kpIndex++)
{
LOG_I( "A71_EraseEccKeyPairWithChallenge(0x%02X)", (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++)
{
LOG_I("A71_GetPublicKeyEccKeyPair (index=0x%02X)", kpIndex);
fetchedPubKeyLen = sizeof(fetchedPubKey);
err = A71_GetPublicKeyEccKeyPair ((SST_Index_t)kpIndex, fetchedPubKey, &fetchedPubKeyLen);
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]);
}
LOG_I( "-----------End exSstKeyPairEnc(%s), result = %s------------", getInitModeAsString(initMode),
((result == 1)? "OK": "FAILED"));
return result;
}