/** * @file configCmdScp.c * @author NXP Semiconductors * @version 1.0 * @par License * * Copyright 2017 NXP * SPDX-License-Identifier: Apache-2.0 * * @par Description * Command handling for 'scp'. Includes optional console handling */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <assert.h> // project specific include files #include "sm_types.h" #include "sm_apdu.h" #include "tst_sm_util.h" #include "tst_a71ch_util.h" #include "probeAxUtil.h" #include "configCmd.h" #include "configCli.h" #include "configState.h" #include "a71_debug.h" #include "ax_util.h" #include "axHostCrypto.h" #include "tstHostCrypto.h" #define FLOW_VERBOSE_PROBE_A70 #ifdef FLOW_VERBOSE_PROBE_A70 #define FPRINTF(...) printf (__VA_ARGS__) #else #define FPRINTF(...) #endif // #define DBG_PROBE_A70 #ifdef DBG_PROBE_A70 #define DBGPRINTF(...) printf (__VA_ARGS__) #else #define DBGPRINTF(...) #endif #if 0 /** * A hook for the command line handler to invoke A71 commands */ int a7xConfigCmdSetEcc(a71_SecureStorageClass_t ssc, U8 index, eccKeyComponents_t *eccKc, U16 *sw) { int error = AX_CLI_EXEC_FAILED; *sw = a7xCmdSetEcc(ssc, index, eccKc); if (*sw == SW_OK) { error = AX_CLI_EXEC_OK; } return error; } /** * API wrapper for set ecc (keypair/pub) command. Can be called from GUI. */ U16 a7xCmdSetEcc(a71_SecureStorageClass_t ssc, U8 index, eccKeyComponents_t *eccKc) { U16 sw; switch (ssc) { case A71_SSC_KEY_PAIR: sw = A71_SetEccKeyPair(index, eccKc->pub, eccKc->pubLen, eccKc->priv, eccKc->privLen); break; case A71_SSC_PUBLIC_KEY: sw = A71_SetEccPublicKey(index, eccKc->pub, eccKc->pubLen); break; default: sw = A7X_CONFIG_STATUS_API_ERROR; break; } return sw; } #endif /** * Clear the SCP03 state on the Host. As a result subsequent APDU commands will be * sent in the clear. */ int a7xConfigCmdScpClearHost() { DEV_ClearChannelState(); return a7xConfigSetHostScp03State(AX_SCP03_CHANNEL_OFF); } /** * A hook for the command line handler to invoke A71 commands */ int a7xConfigCmdScpFromKeyfile(ax_ScpCmdClass_t cmdClass, U8 keyVersion, char *szFilename, U16 *sw) { U8 scp03Enc[AES_KEY_LEN_nBYTE]; U8 scp03Mac[AES_KEY_LEN_nBYTE]; U8 scp03Dek[AES_KEY_LEN_nBYTE]; U8 *currentKeyDek = NULL; U8 sCounter[3]; U16 sCounterLen = sizeof(sCounter); int error = AX_CLI_EXEC_FAILED; error = a7xConfigGetScpKeysFromKeyfile(scp03Enc, scp03Mac, scp03Dek, szFilename); if (error == AX_CLI_EXEC_OK) { error = AX_CLI_EXEC_FAILED; switch (cmdClass) { case AX_SCP_CMD_AUTH: *sw = SCP_Authenticate(scp03Enc, scp03Mac, scp03Dek, SCP_KEY_SIZE, sCounter, &sCounterLen); if (*sw == SW_OK) { a7xConfigSetHostScp03State(AX_SCP03_CHANNEL_ON); error = AX_CLI_EXEC_OK; } break; case AX_SCP_CMD_PUT: *sw = SCP_GP_PutKeys(keyVersion, scp03Enc, scp03Mac, scp03Dek, currentKeyDek, SCP_KEY_SIZE); if (*sw == SW_OK) { error = AX_CLI_EXEC_OK; } break; default: error = AX_CLI_API_ERROR; break; } } return error; } /** * Get scp keys from keyfile. Can be called from GUI. */ int a7xConfigGetScpKeysFromKeyfile(U8 *enc, U8 *mac, U8 *dek, char *szKeyFile) { int nRet = AX_CLI_EXEC_FAILED; U8 hexArray[AES_KEY_LEN_nBYTE]; char szLine[AX_LINE_MAX]; char keyToken[128]; unsigned int idx; FILE *fHandle = NULL; int fEnc = 0; int fMac = 0; int fDek = 0; // Open the file fHandle = fopen(szKeyFile, "r"); if (fHandle == NULL) { printf("Failed to open file %s for reading", szKeyFile); return AX_CLI_FILE_OPEN_FAILED; } while (fgets(szLine, AX_LINE_MAX, fHandle) != NULL) { DBGPRINTF("%s\n", szLine); // Filter out lines STARTING with the comment '#' sign for (idx=0; idx<strlen(szLine); idx++) { if (!isspace(szLine[idx])) { break; } } if (szLine[idx] == '#') { continue; } // Remove all contents from the command line starting with '#' for (idx=0; idx<strlen(szLine); idx++) { if (szLine[idx] == '#') { szLine[idx] = '\0'; break; } } nRet = axCliGetKeyFixedLenHexValueFromLine(keyToken, sizeof(keyToken), hexArray, sizeof(hexArray), szLine); if (nRet != AX_CLI_EXEC_OK) { break; } if (!strcmp(keyToken, "ENC")) { if (fEnc == 0) { memcpy(enc, hexArray, sizeof(hexArray)); fEnc = 1; } else { // Duplicate key value nRet = AX_CLI_FILE_FORMAT_ERROR; break; } } else if (!strcmp(keyToken, "MAC")) { if (fMac == 0) { memcpy(mac, hexArray, sizeof(hexArray)); fMac = 1; } else { // Duplicate key value nRet = AX_CLI_FILE_FORMAT_ERROR; break; } } else if (!strcmp(keyToken, "DEK")) { if (fDek == 0) { memcpy(dek, hexArray, sizeof(hexArray)); fDek = 1; } else { // Duplicate key value nRet = AX_CLI_FILE_FORMAT_ERROR; break; } } else { printf("Unknown key name: %s\n", keyToken); nRet = AX_CLI_FILE_FORMAT_ERROR; break; } } fclose(fHandle); // Ensure we have a value for all keys if ( (nRet != AX_CLI_EXEC_OK) || (fEnc != 1) || (fMac != 1) || (fDek !=1 ) ) { nRet = AX_CLI_FILE_FORMAT_ERROR; } return nRet; }