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