/** * @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 #include #include #include #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