blob: 7c224b16c1181fdd04da4737a6463e0890a06980 [file] [log] [blame]
/**
* @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;
}