| /* |
| * Copyright 2018-2020 NXP |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <fsl_sss_sscp.h> |
| |
| #if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM |
| |
| #include <HLSEAPI.h> |
| #include <a71ch_api.h> |
| #include <fsl_sscp.h> |
| #include <fsl_sscp_a71ch.h> |
| #include <fsl_sscp_commands.h> |
| #include <fsl_sss_keyid_map.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "ax_sss_scp.h" |
| #include "sm_apdu.h" |
| #include "stdlib.h" |
| //#define NX_LOG_ENABLE_SSCP_DEBUG 1 |
| #include <fsl_sss_util_asn1_der.h> |
| #include <nxLog_sscp.h> |
| #include <nxScp03_Types.h> |
| |
| /* ************************************************************************** */ |
| /* Includes */ |
| /* ************************************************************************** */ |
| |
| /* ************************************************************************** */ |
| /* Local Defines */ |
| /* ************************************************************************** */ |
| #define DER_ECC_NISTP256_HEADER 26 |
| #define ADD_DER_ECC_NISTP256_HEADER(x) (x) + DER_ECC_NISTP256_HEADER |
| #define REMOVE_DER_ECC_NISTP256_HEADER(x) (x) - DER_ECC_NISTP256_HEADER |
| #define CONVERT_BYTE(x) (x) / 8 |
| #define CONVERT_BIT(x) (x) * 8 |
| |
| /* ************************************************************************** */ |
| /* Structures and Typedefs */ |
| /* ************************************************************************** */ |
| |
| /* ************************************************************************** */ |
| /* Global Variables */ |
| /* ************************************************************************** */ |
| |
| keyStoreTable_t gkeystore_shadow_ch; |
| keyIdAndTypeIndexLookup_t gLookupEntires_ch[KS_N_ENTIRES]; |
| |
| typedef struct |
| { |
| /** Fixed - Unique 32bit magic number. |
| * |
| * In case some one over-writes we can know. */ |
| uint32_t magic; |
| /** Fixed - constant based on version number */ |
| uint16_t version; |
| |
| uint16_t maxEntries; |
| /** Dynamic entries */ |
| keyIdAndTypeIndexLookup_t entries[KS_N_ENTIRES]; |
| } keyStoreTableEEPROM_t; |
| /* ************************************************************************** */ |
| /* Static function declarations */ |
| /* ************************************************************************** */ |
| |
| static HLSE_RET_CODE a71ch_GenerateKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID); |
| static HLSE_RET_CODE a71ch_EraseKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID); |
| static HLSE_RET_CODE a71ch_FreezeKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID); |
| |
| static sss_status_t swToSSSResult(uint16_t checkSW); |
| |
| static HLSE_RET_CODE a71ch_AllocateKeyStore(sss_a71ch_key_store_t *keyStore, uint32_t keyStoreID); |
| |
| static HLSE_RET_CODE a71ch_loadKeyStore(sss_a71ch_key_store_t *keyStore); |
| static HLSE_RET_CODE a71ch_saveKeyStore(sss_a71ch_key_store_t *keyStore); |
| |
| static HLSE_RET_CODE a71ch_AllocateKeyObject(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| sss_key_part_t keyPart, |
| sss_cipher_type_t cipherType, |
| size_t keyByteLenMax, |
| uint32_t options, |
| uint8_t *a71ch_slotid); |
| |
| static HLSE_RET_CODE a71ch_KeyObjectGetHandle( |
| sss_a71ch_key_store_t *keyStore, uint32_t extKeyID, uint32_t *keyType, uint32_t *cipherType); |
| |
| static HLSE_RET_CODE a71ch_getKey(keyStoreTable_t *keystore_shadow, |
| sss_key_part_t key_part, |
| sss_cipher_type_t cipher_type, |
| uint32_t extId, |
| uint8_t *key, |
| uint32_t *keyByteLen, |
| uint32_t *keyBitLen); |
| |
| static HLSE_RET_CODE a71ch_setKey(keyStoreTable_t *keystore_shadow, |
| sss_key_part_t key_part, |
| sss_cipher_type_t cipher_type, |
| uint32_t extId, |
| uint8_t *key, |
| size_t keyLen, |
| size_t keyBitLen); |
| |
| static HLSE_RET_CODE a71ch_DhDeriveKey(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| uint8_t *pubKeyBuf, |
| size_t pubKeyBufBitLen, |
| uint8_t *pDerivekey, |
| size_t *pDerivekeykeyBitlen); |
| |
| static HLSE_RET_CODE a71ch_SymDeriveKey(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| const uint8_t *saltData, |
| size_t saltLen, |
| const uint8_t *info, |
| size_t infoLen, |
| uint8_t *pDerivekey, |
| size_t derivekeykeylen); |
| |
| static HLSE_RET_CODE a71ch_CalHmacSha256(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| const uint8_t *info, |
| size_t infoLen, |
| uint8_t *hmac, |
| size_t hmaclen); |
| |
| static HLSE_RET_CODE a71ch_eccSign(keyStoreTable_t *keystore_shadow, |
| uint32_t extKeyID, |
| uint8_t *pHash, |
| uint16_t hashLen, |
| uint8_t *pSignature, |
| uint16_t *pSignatureLen); |
| |
| static HLSE_RET_CODE a71ch_eccVerify(keyStoreTable_t *keystore_shadow, |
| uint32_t extKeyID, |
| uint8_t *pHash, |
| uint16_t hashLen, |
| uint8_t *pSignature, |
| uint16_t SignatureLen); |
| |
| /* ************************************************************************** */ |
| /* Public Functions */ |
| /* ************************************************************************** */ |
| |
| sss_status_t sscp_a71ch_openSession(void *connectionData, sss_sscp_session_t *openSession) |
| |
| { |
| uint32_t retval = kStatus_SSS_Fail; |
| if (connectionData == NULL) { |
| return kStatus_SSS_InvalidArgument; |
| } |
| SE_Connect_Ctx_t *pA71Auth = (SE_Connect_Ctx_t *)connectionData; |
| memset(openSession, 0, sizeof(*openSession)); |
| SmCommState_t CommState = {0}; |
| CommState.connType = pA71Auth->connType; |
| uint8_t atr[100]; |
| uint16_t atrLen = ARRAY_SIZE(atr); |
| U16 lReturn; |
| |
| #if defined(SMCOM_JRCP_V1) || defined(SMCOM_JRCP_V2) || defined(RJCT_VCOM) || defined(SMCOM_PCSC) |
| lReturn = SM_RjctConnect(NULL, pA71Auth->portName, &CommState, atr, &atrLen); |
| { |
| if (lReturn == SW_OK) { |
| openSession->fp_closeConnection = &sscp_a71ch_closeConnect; |
| retval = kStatus_SSS_Success; |
| } |
| else if (lReturn == ERR_COM_ALREADY_OPEN) |
| retval = kStatus_SSS_Success; |
| else if (lReturn == ERR_API_ERROR) |
| retval = kStatus_SSS_InvalidArgument; |
| } |
| #else |
| /* AX_EMBEDDED Or Native */ |
| lReturn = SM_Connect(NULL, &CommState, atr, &atrLen); |
| if (lReturn != SW_OK) { |
| LOG_E("SM_Connect Failed. Status %04X", lReturn); |
| return retval; |
| } |
| else { |
| retval = kStatus_SSS_Success; |
| } |
| #endif |
| if (retval == kStatus_SSS_Success) { |
| #if SSS_HAVE_SCP_SCP03_SSS |
| if ((retval == kStatus_SSS_Success) && (pA71Auth->auth.authType == kSSS_AuthType_SCP03)) { |
| retval = kStatus_SSS_Fail; |
| |
| LOG_I("Invoking SM_ChannelAuthenticate()"); |
| lReturn = SM_ChannelAuthenticate(&pA71Auth->auth.ctx.a71chAuthKeys, NULL); |
| if (lReturn == SW_OK) { |
| retval = kStatus_SSS_Success; |
| } |
| else { |
| LOG_E("SM_ChannelAuthenticate() failed."); |
| } |
| } |
| #endif |
| } |
| |
| return (sss_status_t)retval; |
| } |
| |
| void sscp_a71chkey_store_context_free(sss_a71ch_key_store_t *context) |
| { |
| memset(&gLookupEntires_ch, 0, sizeof(gLookupEntires_ch)); |
| memset(&gkeystore_shadow_ch, 0, sizeof(gkeystore_shadow_ch)); |
| } |
| void sscp_a71ch_closeSession(sss_sscp_session_t *closeSession) |
| { |
| if (closeSession->sessionId != 0) { |
| } |
| if (closeSession->fp_closeConnection != NULL) { |
| closeSession->fp_closeConnection(); |
| closeSession->fp_closeConnection = NULL; |
| } |
| } |
| void sscp_a71ch_closeConnect(void) |
| { |
| HLSE_CloseConnection(HLSE_CLOSE_CONNECTION_NO_RESET); |
| } |
| |
| sss_status_t sscp_a71ch_init(sscp_a71ch_context_t *context, sss_a71ch_key_store_t *keyStore) |
| { |
| /* assign A71ch implementation of ::sscp_invoke_command() */ |
| context->keyStore = keyStore; |
| context->invoke = &sscp_a71ch_invoke_command; |
| keyStore->session->sscp_context = (sscp_context_t *)context; |
| return kStatus_SSS_Success; |
| } |
| |
| void sscp_a71ch_free(sscp_a71ch_context_t *context) |
| { |
| if (context != NULL) { |
| memset(context, 0, sizeof(*context)); |
| } |
| } |
| |
| void getA7CHKeyStore(sss_a71ch_key_store_t **ks, sscp_context_reference_t *ref) |
| { |
| switch (ref->type) { |
| case kSSCP_ParamContextType_SSS_Symmetric: { |
| sss_sscp_symmetric_t *ctx = (sss_sscp_symmetric_t *)ref->ptr; |
| *ks = (sss_a71ch_key_store_t *)ctx->keyObject->keyStore; |
| } break; |
| case kSSCP_ParamContextType_SSS_Aead: |
| break; |
| case kSSCP_ParamContextType_SSS_Digest: |
| break; |
| case kSSCP_ParamContextType_SSS_Mac: { |
| sss_mac_t *ctx = (sss_mac_t *)ref->ptr; |
| *ks = (sss_a71ch_key_store_t *)ctx->keyObject->keyStore; |
| break; |
| } |
| case kSSCP_ParamContextType_SSS_Tunnel: |
| break; |
| case kSSCP_ParamContextType_SSS_DeriveKey: { |
| sss_derive_key_t *ctx = (sss_derive_key_t *)ref->ptr; |
| *ks = (sss_a71ch_key_store_t *)ctx->keyObject->keyStore; |
| break; |
| } |
| case kSSCP_ParamContextType_SSS_Asymmetric: { |
| sss_asymmetric_t *ctx = (sss_asymmetric_t *)ref->ptr; |
| *ks = (sss_a71ch_key_store_t *)ctx->keyObject->keyStore; |
| break; |
| } |
| case kSSCP_ParamContextType_SSS_Object: { |
| sss_object_t *pobj = (sss_object_t *)ref->ptr; |
| *ks = (sss_a71ch_key_store_t *)pobj->keyStore; |
| break; |
| } |
| case kSSCP_ParamContextType_SSS_KeyStore: { |
| *ks = (sss_a71ch_key_store_t *)ref->ptr; |
| break; |
| } |
| case kSSCP_ParamContextType_SSS_RandomGen: |
| *ks = (sss_a71ch_key_store_t *)ref->ptr; |
| break; |
| } |
| } |
| |
| sscp_status_t sscp_a71ch_invoke_command( |
| sscp_context_t *a71chContext, uint32_t commandID, sscp_operation_t *op, uint32_t *returnOrigin) |
| { |
| uint16_t resSW = SMCOM_SND_FAILED; |
| sscp_status_t retSSCP = kStatus_SSCP_Success; |
| uint32_t keyId; |
| sss_a71ch_key_store_t *a71ch_keystore = NULL; |
| sss_derive_key_t *derctx; |
| sscp_a71ch_context_t *context = (sscp_a71ch_context_t *)a71chContext; |
| if (kSSCP_ParamType_ContextReference == SSCP_OP_GET_PARAM(0, op->paramTypes)) { |
| getA7CHKeyStore(&a71ch_keystore, &op->params[0].context); |
| } |
| |
| #if SSS_HAVE_A71CH_SIM |
| if (a71ch_keystore != NULL) { |
| if (a71ch_keystore->session->sessionId != 0) { |
| set_SessionId_Tlv(a71ch_keystore->session->sessionId); |
| } |
| } |
| #endif |
| |
| switch (commandID) { |
| case kSSCP_CMD_GENERATE_KEY: |
| resSW = a71ch_GenerateKey( |
| a71ch_keystore->keystore_shadow, op->params[1].value.a, op->params[2].value.b, op->params[1].value.b); |
| break; |
| |
| case kSSCP_CMD_ERASE_KEY: |
| resSW = a71ch_EraseKey( |
| a71ch_keystore->keystore_shadow, op->params[1].value.a, op->params[2].value.a, op->params[1].value.b); |
| if (resSW == SMCOM_OK) { |
| resSW = a71ch_saveKeyStore(a71ch_keystore); |
| } |
| break; |
| |
| case kSSCP_CMD_GET_KEY: |
| resSW = a71ch_getKey(a71ch_keystore->keystore_shadow, |
| op->params[1].value.a, |
| op->params[3].value.b, |
| op->params[1].value.b, |
| op->params[2].memref.buffer, |
| &op->params[3].value.a, |
| &op->params[3].value.b); |
| break; |
| |
| case kSSCP_CMD_FREEZE_KEY: |
| resSW = a71ch_FreezeKey( |
| a71ch_keystore->keystore_shadow, op->params[1].value.a, op->params[2].value.a, op->params[1].value.b); |
| break; |
| |
| case kSSCP_CMD_ALLOCATE_KEYSTORE: |
| resSW = a71ch_AllocateKeyStore(a71ch_keystore, op->params[1].value.a); |
| break; |
| |
| case kSSCP_CMD_LOAD_KEYSTORE: |
| if (a71ch_keystore->shadow_handle == 0) { |
| /* It's OK. Allocate + Load here. */ |
| resSW = a71ch_AllocateKeyStore(a71ch_keystore, __LINE__); |
| } |
| else { |
| resSW = a71ch_loadKeyStore(a71ch_keystore); |
| } |
| break; |
| |
| case kSSCP_CMD_SAVE_KEYSTORE: |
| resSW = a71ch_saveKeyStore(a71ch_keystore); |
| break; |
| case kSSCP_CMD_SET_KEY: { |
| resSW = a71ch_setKey(a71ch_keystore->keystore_shadow, |
| op->params[1].value.a, |
| op->params[3].value.b, |
| op->params[1].value.b, |
| op->params[2].memref.buffer, |
| op->params[2].memref.size, |
| op->params[3].value.a); |
| } break; |
| case kSSCP_KEYOBJ_CMD_ALLOCATE_HANDLE: { |
| uint8_t a71ch_slotid = 0; |
| resSW = a71ch_AllocateKeyObject(a71ch_keystore, |
| op->params[1].value.a, |
| op->params[1].value.b, |
| op->params[3].value.a, |
| op->params[2].value.a, |
| op->params[2].value.b, |
| &a71ch_slotid); |
| op->params[4].value.a = a71ch_slotid; |
| } break; |
| case kSSCP_KEYOBJ_CMD_GET_HANDLE: |
| resSW = a71ch_KeyObjectGetHandle( |
| a71ch_keystore, op->params[1].value.a, &(op->params[2].value.a), &(op->params[2].value.b)); |
| break; |
| |
| case kSSCP_ASYMMETRIC_CTX_INIT: |
| op->params[3].value.a = (0xFFFFFFFFu ^ op->params[2].value.a); |
| resSW = SMCOM_OK; |
| break; |
| case kSSCP_ASYMMETRIC_CMD_ENCRYPT: |
| break; |
| case kSSCP_ASYMMETRIC_CMD_DECRYPT: |
| break; |
| case kSSCP_ASYMMETRIC_CMD_SIGN_DIGEST: |
| keyId = (0xFFFFFFFFu ^ op->params[1].value.a); |
| resSW = a71ch_eccSign(a71ch_keystore->keystore_shadow, |
| keyId, |
| op->params[2].memref.buffer, |
| (uint16_t)op->params[2].memref.size, |
| op->params[3].memref.buffer, |
| (uint16_t *)&op->params[3].memref.size); |
| break; |
| case kSSCP_ASYMMETRIC_CMD_VERIFY_DIGEST: |
| keyId = (0xFFFFFFFFu ^ op->params[1].value.a); |
| resSW = a71ch_eccVerify(context->keyStore->keystore_shadow, |
| keyId, |
| op->params[2].memref.buffer, |
| (uint16_t)op->params[2].memref.size, |
| op->params[3].memref.buffer, |
| (uint16_t)op->params[3].memref.size); |
| break; |
| |
| case kSSCP_SYMM_CIPHER_CTX_INIT: |
| op->params[2].value.a = (0xFFFFFFFFu ^ op->params[1].value.a); |
| resSW = SMCOM_OK; |
| break; |
| |
| case kSSCP_DERIVE_CTX_INIT: |
| op->params[3].value.a = (0xFFFFFFFFu ^ op->params[2].value.a); |
| resSW = SMCOM_OK; |
| break; |
| |
| case kSSCP_ASYMM_DH_DERIVE_KEY: { |
| resSW = a71ch_DhDeriveKey(a71ch_keystore, |
| (0xFFFFFFFFu ^ (op->params[1].value.a)), /* = context->sessionId*/ |
| op->params[2].memref.buffer, /* key*/ |
| op->params[2].memref.size, /*keylen*/ |
| op->params[3].memref.buffer, /* derivekey*/ |
| &(op->params[4].memref.size)); /* derivekeykeylen;*/ |
| } break; |
| |
| case kSSCP_DERIVE_KEY: |
| derctx = (sss_derive_key_t *)op->params[0].context.ptr; |
| if (derctx != NULL) { |
| if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && (derctx->mode == kMode_SSS_Mac)) { |
| resSW = a71ch_CalHmacSha256(a71ch_keystore, |
| (0xFFFFFFFFu ^ (op->params[1].value.a)), /* extKeyID = ~context->sessionId*/ |
| op->params[3].memref.buffer, /* info */ |
| op->params[3].memref.size, /* infoLen */ |
| op->params[4].memref.buffer, /* hmac*/ |
| op->params[4].memref.size); /* hmaclen;*/ |
| } |
| else if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && |
| (derctx->mode == kMode_SSS_ComputeSharedSecret)) { |
| resSW = a71ch_SymDeriveKey(a71ch_keystore, |
| (0xFFFFFFFFu ^ (op->params[1].value.a)), /* extKeyID = ~context->sessionId*/ |
| op->params[2].memref.buffer, /* (void *)saltData*/ |
| op->params[2].memref.size, /* saltLen */ |
| op->params[3].memref.buffer, /* info */ |
| op->params[3].memref.size, /* infoLen */ |
| op->params[4].memref.buffer, /* derivekey*/ |
| op->params[4].memref.size); /* derivekeykeylen;*/ |
| } |
| } |
| break; |
| case kSSCP_CMD_SSS_MacOneGo: |
| derctx = (sss_derive_key_t *)op->params[0].context.ptr; |
| if (derctx != NULL) { |
| if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && (derctx->mode == kMode_SSS_Mac)) { |
| resSW = a71ch_CalHmacSha256(a71ch_keystore, |
| op->params[3].value.a, |
| op->params[1].memref.buffer, /* info */ |
| op->params[1].memref.size, /* infoLen */ |
| op->params[2].memref.buffer, /* hmac*/ |
| op->params[2].memref.size); /* hmaclen;*/ |
| |
| if (HLSE_SW_OK == resSW) { |
| op->params[2].memref.size = 32; //Only HMAC SHA256 is supported |
| } |
| } |
| } |
| break; |
| case kSSCP_CMD_SSS_MacInit: { |
| derctx = (sss_derive_key_t *)op->params[0].context.ptr; |
| if (derctx != NULL) { |
| if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && (derctx->mode == kMode_SSS_Mac)) { |
| uint16_t intId = 0; |
| uint8_t nBlock = 1; |
| sss_status_t status = |
| ks_common_extId_to_int_index(a71ch_keystore->keystore_shadow, op->params[1].value.a, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keystore_shadow", op->params[1].value.a); |
| resSW = HLSE_ERR_API_ERROR; |
| } |
| else { |
| nBlock = (intId & 0xF0) >> 4; |
| resSW = A71_HmacSha256Init((intId & 0x0F), nBlock); |
| } |
| } |
| } |
| } break; |
| case kSSCP_CMD_SSS_MacUpdate: { |
| derctx = (sss_derive_key_t *)op->params[0].context.ptr; |
| if (derctx != NULL) { |
| if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && (derctx->mode == kMode_SSS_Mac)) { |
| uint16_t intId = 0; |
| uint8_t nBlock = 1; |
| sss_status_t status = |
| ks_common_extId_to_int_index(a71ch_keystore->keystore_shadow, op->params[1].value.a, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keystore_shadow", op->params[1].value.a); |
| resSW = HLSE_ERR_API_ERROR; |
| } |
| else { |
| nBlock = (intId & 0xF0) >> 4; |
| resSW = A71_HmacSha256Update( |
| (intId & 0x0F), nBlock, op->params[2].memref.buffer, (U16)op->params[2].memref.size); |
| } |
| } |
| } |
| } break; |
| case kSSCP_CMD_SSS_MacFinish: { |
| derctx = (sss_derive_key_t *)op->params[0].context.ptr; |
| if (derctx != NULL) { |
| if ((derctx->algorithm == kAlgorithm_SSS_HMAC_SHA256) && (derctx->mode == kMode_SSS_Mac)) { |
| uint16_t intId = 0; |
| uint8_t nBlock = 1; |
| U16 dataLen = (U16)op->params[2].memref.size; |
| sss_status_t status = |
| ks_common_extId_to_int_index(a71ch_keystore->keystore_shadow, op->params[1].value.a, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keystore_shadow", op->params[1].value.a); |
| resSW = HLSE_ERR_API_ERROR; |
| } |
| else { |
| nBlock = (intId & 0xF0) >> 4; |
| resSW = A71_HmacSha256Final((intId & 0x0F), nBlock, op->params[2].memref.buffer, &dataLen); |
| if (HLSE_SW_OK == resSW) { |
| op->params[2].memref.size = 32; //Only HMAC SHA256 is supported |
| } |
| } |
| } |
| } |
| } break; |
| case kSSCP_GEN_RANDOM_NUM: { |
| resSW = A71_GetRandom(op->params[2].memref.buffer, (uint8_t)op->params[2].memref.size); |
| } break; |
| case kSSCP_CMD_SSS_DigestOneGo: { |
| U16 shaLen = (U16)op->params[2].memref.size; |
| resSW = A71_GetSha256( |
| op->params[1].memref.buffer, (U16)op->params[1].memref.size, op->params[2].memref.buffer, &shaLen); |
| op->params[2].memref.size = shaLen; |
| } break; |
| case kSSCP_CMD_SSS_DigestInit: { |
| resSW = A71_Sha256Init(); |
| } break; |
| case kSSCP_CMD_SSS_DigestUpdate: { |
| resSW = A71_Sha256Update(op->params[1].memref.buffer, (U16)op->params[1].memref.size); |
| } break; |
| case kSSCP_CMD_SSS_DigestFinish: { |
| U16 shaLen = (U16)op->params[1].memref.size; |
| resSW = A71_Sha256Final(op->params[1].memref.buffer, &shaLen); |
| op->params[1].memref.size = shaLen; |
| } break; |
| case kSSCP_GET_UID: { |
| U16 bufSize = (U16)op->params[1].memref.size; |
| resSW = A71_GetUniqueID(op->params[1].memref.buffer, &bufSize); |
| op->params[1].memref.size = bufSize; |
| } break; |
| case kSSCP_GET_CERT_UID: { |
| U16 bufSize = (U16)op->params[1].memref.size; |
| resSW = A71_GetCertUid(op->params[1].memref.buffer, &bufSize); |
| op->params[1].memref.size = bufSize; |
| } break; |
| default: |
| retSSCP = kStatus_SSCP_Fail; |
| LOG_E("Not a SSCP command"); |
| } |
| *returnOrigin = (uint32_t)swToSSSResult(resSW); |
| return (retSSCP); |
| } |
| |
| /* ************************************************************************** */ |
| /* Private Functions */ |
| /* ************************************************************************** */ |
| static HLSE_RET_CODE a71ch_CalHmacSha256(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| const uint8_t *info, |
| size_t infoLen, |
| uint8_t *pDerivekey, |
| size_t derivekeykeylen) |
| { |
| HLSE_RET_CODE hlseret; |
| uint16_t intId = 0; |
| uint8_t nBlock = 1; |
| U16 Hmaclen = 64; |
| |
| sss_status_t status = ks_common_extId_to_int_index(keyStore->keystore_shadow, extKeyID, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| nBlock = (intId & 0xF0) >> 4; |
| hlseret = A71_GetHmacSha256((U8)(intId & 0x0F), nBlock, info, (U16)infoLen, pDerivekey, &Hmaclen); |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_SymDeriveKey(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| const uint8_t *saltData, |
| size_t saltLen, |
| const uint8_t *info, |
| size_t infoLen, |
| uint8_t *pDerivekey, |
| size_t derivekeykeylen) |
| { |
| HLSE_RET_CODE hlseret; |
| uint16_t intId = 0; |
| uint8_t nBlock = 1; |
| |
| sss_status_t status = ks_common_extId_to_int_index(keyStore->keystore_shadow, extKeyID, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| nBlock = (intId & 0xF0) >> 4; |
| hlseret = A71_HkdfSymKey((U8)(intId & 0x0F), |
| nBlock, |
| saltData, |
| (uint16_t)saltLen, |
| info, |
| (uint16_t)infoLen, |
| pDerivekey, |
| (uint16_t)derivekeykeylen); |
| } |
| |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_DhDeriveKey(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| uint8_t *pubKeyBuf, |
| size_t pubKeyBufBitLen, |
| uint8_t *pDerivekey, |
| size_t *pDerivekeykeyBitlen) |
| { |
| HLSE_RET_CODE hlseret; |
| sss_status_t asn_retval = kStatus_SSS_Fail; |
| uint16_t intId = 0; |
| uint16_t derivekeyBytelen; |
| uint16_t pubKeyBufByteLen; |
| size_t publicKeyLen = 0; |
| uint16_t publicKeyIndex = 0; |
| |
| sss_status_t status = ks_common_extId_to_int_index(keyStore->keystore_shadow, extKeyID, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| pubKeyBufByteLen = (uint16_t)CONVERT_BYTE(pubKeyBufBitLen); |
| derivekeyBytelen = (uint16_t)CONVERT_BYTE(*pDerivekeykeyBitlen); |
| |
| asn_retval = |
| sss_util_pkcs8_asn1_get_ec_public_key_index(pubKeyBuf, pubKeyBufByteLen, &publicKeyIndex, &publicKeyLen); |
| if (asn_retval != kStatus_SSS_Success) { |
| LOG_W("error in sss_util_pkcs8_asn1_get_ec_public_key_index"); |
| return HLSE_ERR_API_ERROR; |
| } |
| |
| hlseret = A71_EcdhGetSharedSecret( |
| (U8)intId, &pubKeyBuf[publicKeyIndex], (U16)publicKeyLen, pDerivekey, &derivekeyBytelen); |
| *pDerivekeykeyBitlen = CONVERT_BIT(derivekeyBytelen); |
| } |
| |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_GenerateKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID) |
| { |
| HLSE_RET_CODE hlseret = HLSE_ERR_API_ERROR; |
| if (keyType == kSSS_KeyPart_Pair && cipherType == kSSS_CipherType_EC_NIST_P) { |
| uint16_t intId = 0; |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extKeyID, &intId); |
| if (status == kStatus_SSS_Success) { |
| hlseret = A71_GenerateEccKeyPair((U8)intId); |
| } |
| else { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_EraseKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID) |
| { |
| HLSE_RET_CODE hlseret = HLSE_ERR_API_ERROR; |
| uint16_t intId = 0; |
| |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extKeyID, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| if (keyType == kSSS_KeyPart_Pair && cipherType == kSSS_CipherType_EC_NIST_P) { |
| hlseret = A71_EraseEccKeyPair((U8)intId); |
| } |
| else if (keyType == kSSS_KeyPart_Public && cipherType == kSSS_CipherType_EC_NIST_P) { |
| hlseret = A71_EraseEccPublicKey((U8)intId); |
| } |
| else if (keyType == kSSS_KeyPart_Default && |
| (cipherType == kSSS_CipherType_AES || cipherType == kSSS_CipherType_HMAC)) { |
| hlseret = A71_EraseSymKey((U8)(intId & 0x0F)); |
| } |
| else if (keyType == kSSS_KeyPart_Default && cipherType == kSSS_CipherType_Binary) { |
| HLSE_OBJECT_HANDLE Handles[5]; |
| U16 HandlesNum = sizeof(Handles) / sizeof(HLSE_OBJECT_HANDLE); |
| U16 HandlesNum_copy; |
| U8 i = 0; |
| |
| hlseret = HLSE_EnumerateObjects(HLSE_CERTIFICATE, Handles, &HandlesNum); |
| |
| if (hlseret == HLSE_SW_OK) { |
| HandlesNum_copy = HandlesNum; |
| while (HandlesNum_copy) { |
| if (HLSE_GET_OBJECT_INDEX(Handles[i]) == intId) { |
| break; |
| } |
| i++; |
| HandlesNum_copy--; |
| } |
| hlseret = HLSE_EraseObject(Handles[i]); |
| } |
| } |
| } |
| if (hlseret == HLSE_SW_OK) { |
| status = ks_common_remove_fat(keystore_shadow, extKeyID); |
| if (status != kStatus_SSS_Success) { |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_FreezeKey( |
| keyStoreTable_t *keystore_shadow, uint8_t keyType, uint8_t cipherType, uint32_t extKeyID) |
| { |
| HLSE_RET_CODE hlseret = HLSE_ERR_API_ERROR; |
| uint16_t intId = 0; |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extKeyID, &intId); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("Could not find Ext ID 0x%X in keytore_shadow", extKeyID); |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| if (keyType == kSSS_KeyPart_Pair && cipherType == kSSS_CipherType_EC_NIST_P) { |
| hlseret = A71_FreezeEccKeyPair((U8)intId); |
| } |
| if (keyType == kSSS_KeyPart_Public && cipherType == kSSS_CipherType_EC_NIST_P) { |
| hlseret = A71_FreezeEccPublicKey((U8)intId); |
| } |
| if (keyType == kSSS_KeyPart_Default && |
| (cipherType == kSSS_CipherType_AES || cipherType == kSSS_CipherType_HMAC)) { |
| hlseret = A71_FreezeSymKey((U8)intId); |
| } |
| } |
| |
| return hlseret; |
| } |
| |
| static sss_status_t swToSSSResult(uint16_t checkSW) |
| { |
| switch (checkSW) { |
| case SMCOM_OK: |
| return kStatus_SSS_Success; |
| default: |
| return kStatus_SSS_Fail; |
| } |
| } |
| |
| static HLSE_RET_CODE a71ch_AllocateKeyStore(sss_a71ch_key_store_t *keyStore, uint32_t keyStoreID) |
| { |
| HLSE_RET_CODE hlseret = HLSE_ERR_API_ERROR; |
| HLSE_OBJECT_HANDLE Handles[5]; |
| U16 HandlesNum = sizeof(Handles) / sizeof(HLSE_OBJECT_HANDLE); |
| U16 HandlesNum_copy; |
| U8 i = 0; |
| HLSE_OBJECT_INDEX index = 0; |
| |
| /* Search for our data table @ index */ |
| if (keyStore->shadow_handle == 0) { |
| hlseret = HLSE_EnumerateObjects(HLSE_DATA, Handles, &HandlesNum); |
| if (hlseret == HLSE_SW_OK) { |
| HandlesNum_copy = HandlesNum; |
| while (HandlesNum_copy) { |
| if (HLSE_GET_OBJECT_INDEX(Handles[i]) == index) { |
| keyStore->shadow_handle = Handles[i]; |
| ks_common_init_fat(&gkeystore_shadow_ch, gLookupEntires_ch, ARRAY_SIZE(gLookupEntires_ch)); |
| break; |
| } |
| i++; |
| HandlesNum_copy--; |
| } |
| } |
| } |
| |
| if (gkeystore_shadow_ch.magic == 0) { |
| ks_common_init_fat(&gkeystore_shadow_ch, gLookupEntires_ch, ARRAY_SIZE(gLookupEntires_ch)); |
| } |
| keyStore->keystore_shadow = &gkeystore_shadow_ch; |
| |
| /* If it was never there, create it @ index */ |
| if (keyStore->shadow_handle == 0) { |
| /* Could not find it yet*/ |
| HLSE_OBJECT_TYPE objType = HLSE_DATA; |
| U16 templateSize = 3; |
| HLSE_ATTRIBUTE attr[3]; |
| keyStoreTableEEPROM_t eeKeyStore; |
| |
| eeKeyStore.magic = gkeystore_shadow_ch.magic; |
| eeKeyStore.version = gkeystore_shadow_ch.version; |
| eeKeyStore.maxEntries = gkeystore_shadow_ch.maxEntries; |
| memcpy(eeKeyStore.entries, gkeystore_shadow_ch.entries, sizeof(eeKeyStore.entries)); |
| |
| 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 = &eeKeyStore; |
| attr[2].valueLen = sizeof(eeKeyStore); |
| |
| hlseret = HLSE_CreateObject(attr, templateSize, &keyStore->shadow_handle); |
| } |
| |
| /* Either we created it. Or it was already existing, read it. */ |
| if (keyStore->shadow_handle != 0) { |
| hlseret = a71ch_loadKeyStore(keyStore); |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_loadKeyStore(sss_a71ch_key_store_t *keyStore) |
| { |
| HLSE_RET_CODE hlseret; |
| HLSE_ATTRIBUTE attr; |
| keyStoreTableEEPROM_t eeKeyStore = {0}; |
| |
| if (keyStore->shadow_handle == 0) { |
| /* With shadow handle == 0, no point of reading. */ |
| hlseret = HLSE_ERR_MEMORY; |
| goto cleanup; |
| } |
| |
| attr.type = HLSE_ATTR_OBJECT_VALUE; |
| attr.value = &eeKeyStore; |
| attr.valueLen = sizeof(eeKeyStore); |
| /* Read from Key Store and load it here in gkeystore_shadow_ch */ |
| hlseret = HLSE_GetObjectAttribute(keyStore->shadow_handle, &attr); |
| |
| if (hlseret != HLSE_SW_OK) |
| goto cleanup; |
| if (eeKeyStore.magic == gkeystore_shadow_ch.magic && eeKeyStore.maxEntries == gkeystore_shadow_ch.maxEntries) { |
| keyStore->keystore_shadow = &gkeystore_shadow_ch; |
| if (eeKeyStore.version > gkeystore_shadow_ch.version) { |
| LOG_E("Keystore version mismatch"); |
| hlseret = HLSE_ERR_NOT_SUPPORTED; |
| goto cleanup; |
| } |
| memcpy(gkeystore_shadow_ch.entries, eeKeyStore.entries, sizeof(eeKeyStore.entries)); |
| keyStore->keystore_shadow->version = eeKeyStore.version; |
| } |
| else { |
| LOG_E(" Mismatch in eeKeyStore == gkeystore_shadow_ch"); |
| /* This is the case when there is mismatch between KeyStore and Middleware */ |
| hlseret = HLSE_ERR_MEMORY; |
| } |
| |
| cleanup: |
| return hlseret; |
| } |
| static HLSE_RET_CODE a71ch_saveKeyStore(sss_a71ch_key_store_t *keyStore) |
| { |
| HLSE_RET_CODE hlseret; |
| if (keyStore->shadow_handle == 0) { |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| else { |
| keyStoreTableEEPROM_t eeKeyStore; |
| if (KEYSTORE_VERSION > gkeystore_shadow_ch.version) { |
| gkeystore_shadow_ch.version = KEYSTORE_VERSION; |
| } |
| |
| eeKeyStore.magic = gkeystore_shadow_ch.magic; |
| eeKeyStore.version = gkeystore_shadow_ch.version; |
| eeKeyStore.maxEntries = gkeystore_shadow_ch.maxEntries; |
| memcpy(eeKeyStore.entries, gkeystore_shadow_ch.entries, sizeof(eeKeyStore.entries)); |
| |
| HLSE_ATTRIBUTE attr; |
| attr.type = HLSE_ATTR_OBJECT_VALUE; |
| attr.value = &eeKeyStore; |
| attr.valueLen = sizeof(eeKeyStore); |
| /* write gkeystore_shadow_ch */ |
| hlseret = HLSE_SetObjectAttribute(keyStore->shadow_handle, &attr); |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_KeyObjectGetHandle( |
| sss_a71ch_key_store_t *keyStore, uint32_t extKeyID, uint32_t *keyType, uint32_t *cipherType) |
| { |
| HLSE_RET_CODE hlseret = HLSE_ERR_GENERAL_ERROR; |
| sss_status_t ks_status = kStatus_SSS_Success; |
| *keyType = kSSS_KeyPart_NONE; |
| ks_status = ks_common_get_keyType_from_keyid(keyStore->keystore_shadow, extKeyID, keyType, cipherType); |
| if (ks_status == kStatus_SSS_Success) |
| hlseret = HLSE_SW_OK; |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_AllocateKeyObject(sss_a71ch_key_store_t *keyStore, |
| uint32_t extKeyID, |
| sss_key_part_t key_part, |
| sss_cipher_type_t cipherType, |
| size_t keyByteLenMax, |
| uint32_t options, |
| uint8_t *a71ch_slotid) |
| { |
| HLSE_RET_CODE hlseret = HLSE_SW_OK; |
| uint16_t intIndex = 0; |
| sss_status_t ks_status; |
| |
| ks_status = ks_common_check_available_int_index( |
| keyStore->keystore_shadow, (uint8_t)key_part, cipherType, &intIndex, (uint16_t)keyByteLenMax); |
| |
| if (ks_status != kStatus_SSS_Success) { |
| hlseret = HLSE_ERR_MEMORY; |
| } |
| *a71ch_slotid = (uint8_t)intIndex; |
| |
| if (hlseret == HLSE_SW_OK) { |
| ks_status = ks_common_update_fat(keyStore->keystore_shadow, |
| extKeyID, |
| (uint8_t)key_part, |
| (uint8_t)cipherType, |
| (uint8_t)intIndex, |
| 0, |
| (uint16_t)keyByteLenMax); |
| } |
| if (ks_status != kStatus_SSS_Success) { |
| hlseret = HLSE_ERR_MEMORY; |
| } |
| if (hlseret == HLSE_SW_OK) { |
| switch (cipherType) { |
| case kSSS_CipherType_Binary: { |
| HLSE_OBJECT_INDEX index = intIndex; |
| HLSE_OBJECT_TYPE objType = HLSE_CERTIFICATE; |
| U16 templateSize = 3; |
| HLSE_ATTRIBUTE attr[3]; |
| HLSE_OBJECT_HANDLE handle = 0; |
| void *pMem; |
| pMem = SSS_MALLOC(keyByteLenMax); |
| if (NULL != pMem) { |
| 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; |
| /* This is dummy value we write... Actually this source code */ |
| attr[2].value = pMem; |
| attr[2].valueLen = (U16)keyByteLenMax; |
| |
| memset(pMem, 0, keyByteLenMax); |
| hlseret = HLSE_CreateObject(attr, templateSize, &handle); |
| /* TODO: if object is already present and all attributes are same then mark it as success*/ |
| if (hlseret == HLSE_OBJ_ALREADY_EXISTS) |
| hlseret = HLSE_SW_OK; |
| } |
| if (NULL != pMem) { |
| SSS_FREE(pMem); |
| } |
| break; |
| } |
| case kSSS_CipherType_EC_NIST_P: |
| case kSSS_CipherType_AES: |
| case kSSS_CipherType_HMAC: |
| case kSSS_CipherType_UserID: |
| break; |
| default: |
| hlseret = HLSE_ERR_API_ERROR; |
| } |
| } |
| if (hlseret == HLSE_SW_OK) { |
| /* Persist to EEPROM */ |
| hlseret = a71ch_saveKeyStore(keyStore); |
| } |
| else { |
| /* Reset the structure based on EEPROM */ |
| a71ch_loadKeyStore(keyStore); |
| } |
| return hlseret; |
| } |
| |
| static HLSE_RET_CODE a71ch_getKey(keyStoreTable_t *keystore_shadow, |
| sss_key_part_t key_part, |
| sss_cipher_type_t cipher_type, |
| uint32_t extId, |
| uint8_t *key, |
| uint32_t *keyByteLen, |
| uint32_t *keyBitLen) |
| { |
| HLSE_RET_CODE resSW = HLSE_ERR_API_ERROR; |
| uint16_t intId = 0; |
| U8 i = 0; |
| HLSE_OBJECT_HANDLE Handles[5]; |
| HLSE_OBJECT_HANDLE GetHandle = 0; |
| U16 HandlesNum = sizeof(Handles) / sizeof(HLSE_OBJECT_HANDLE); |
| U16 HandlesNum_copy; |
| HLSE_ATTRIBUTE attr; |
| U16 keyLen = *keyByteLen; |
| /* clang-format off */ |
| const uint8_t der_header[DER_ECC_NISTP256_HEADER] = { 0x30, 0x59, 0x30, 0x13,0x06, 0x07, 0x2A, 0x86, |
| 0x48, 0xCE, 0x3D, 0x02,0x01, 0x06, 0x08, 0x2A, |
| 0x86, 0x48, 0xCE, 0x3D,0x03, 0x01, 0x07, 0x03, |
| 0x42, 0x00 |
| }; |
| /* clang-format on */ |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extId, &intId); |
| if (status == kStatus_SSS_Success) { |
| if (key_part == kSSS_KeyPart_Pair && cipher_type == kSSS_CipherType_EC_NIST_P) { |
| if (keyLen < DER_ECC_NISTP256_HEADER + 65 /* NIST256 public key len */) { |
| LOG_E("Buffer size insufficient "); |
| return resSW; |
| } |
| memcpy(key, der_header, DER_ECC_NISTP256_HEADER); |
| resSW = A71_GetPublicKeyEccKeyPair((U8)intId, ADD_DER_ECC_NISTP256_HEADER(key), &keyLen); |
| /* Return the Key length including the ECC DER Header */ |
| keyLen = ADD_DER_ECC_NISTP256_HEADER(keyLen); |
| /* Return the Key length in bits */ |
| *keyByteLen = keyLen; |
| *keyBitLen = 256; |
| } |
| else if (key_part == kSSS_KeyPart_Public && cipher_type == kSSS_CipherType_EC_NIST_P) { |
| if (keyLen < DER_ECC_NISTP256_HEADER + 32 /* NIST256 public key len */) { |
| LOG_E("Buffer size insufficient "); |
| return resSW; |
| } |
| memcpy(key, der_header, DER_ECC_NISTP256_HEADER); |
| resSW = A71_GetEccPublicKey((U8)intId, ADD_DER_ECC_NISTP256_HEADER(key), &keyLen); |
| /* Return the Key length including the ECC DER Header */ |
| keyLen = ADD_DER_ECC_NISTP256_HEADER(keyLen); |
| /* Return the Key length in bits */ |
| *keyByteLen = keyLen; |
| *keyBitLen = 256; |
| } |
| else if (key_part == kSSS_KeyPart_Default && cipher_type == kSSS_CipherType_Binary) { |
| resSW = HLSE_EnumerateObjects(HLSE_CERTIFICATE, Handles, &HandlesNum); |
| if (resSW == HLSE_SW_OK) { |
| HandlesNum_copy = HandlesNum; |
| while (HandlesNum_copy) { |
| if (HLSE_GET_OBJECT_INDEX(Handles[i]) == intId) { |
| GetHandle = Handles[i]; |
| break; |
| } |
| i++; |
| HandlesNum_copy--; |
| } |
| } |
| if (GetHandle != 0) { |
| attr.type = HLSE_ATTR_OBJECT_VALUE; |
| attr.value = key; |
| attr.valueLen = keyLen; |
| resSW = HLSE_GetObjectAttribute(GetHandle, &attr); |
| *keyByteLen = attr.valueLen; |
| *keyBitLen = (attr.valueLen * 8); |
| } |
| } |
| } |
| else { |
| LOG_E("Could not find Ext ID 0x%X in keystore_shadow", extId); |
| } |
| return resSW; |
| } |
| |
| static HLSE_RET_CODE a71ch_setKey(keyStoreTable_t *keystore_shadow, |
| sss_key_part_t key_part, |
| sss_cipher_type_t cipher_type, |
| uint32_t extId, |
| uint8_t *key, |
| size_t keyLen, |
| size_t keyBitLen) |
| { |
| HLSE_RET_CODE resSW = HLSE_ERR_API_ERROR; |
| sss_status_t asn_retval = kStatus_SSS_Fail; |
| uint16_t intId = 0; |
| U8 i = 0; |
| HLSE_OBJECT_HANDLE Handles[5]; |
| HLSE_OBJECT_HANDLE GetHandle = 0; |
| U16 HandlesNum = sizeof(Handles) / sizeof(HLSE_OBJECT_HANDLE); |
| U16 HandlesNum_copy; |
| HLSE_ATTRIBUTE attr; |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extId, &intId); |
| |
| if (status == kStatus_SSS_Success) { |
| if (key_part == kSSS_KeyPart_Public && cipher_type == kSSS_CipherType_EC_NIST_P) { |
| size_t publicKeyLen = 0; |
| uint16_t publicKeyIndex = 0; |
| const uint8_t *pPublicKey = NULL; |
| if (keyBitLen != 256) { |
| LOG_E("Invalid bit length. Only NIST256 is supported in A71CH"); |
| return resSW; |
| } |
| asn_retval = sss_util_pkcs8_asn1_get_ec_public_key_index(key, keyLen, &publicKeyIndex, &publicKeyLen); |
| if (asn_retval != kStatus_SSS_Success) { |
| LOG_E("error in sss_util_pkcs8_asn1_get_ec_public_key_index"); |
| return resSW; |
| } |
| |
| if (publicKeyLen == 0) { |
| LOG_E("Public key len is 0"); |
| return resSW; |
| } |
| |
| pPublicKey = &key[publicKeyIndex]; |
| resSW = A71_SetEccPublicKey((U8)intId, pPublicKey, (U16)publicKeyLen); |
| } |
| else if (key_part == kSSS_KeyPart_Default && |
| (cipher_type == kSSS_CipherType_AES || cipher_type == kSSS_CipherType_HMAC)) { |
| uint8_t slot_id = intId & 0x0F; |
| uint8_t slot_length = (intId & 0xF0) >> 4; |
| uint8_t j = 0; |
| U16 maxKeyLen = 16; |
| size_t keyLenRem = keyLen; |
| size_t KeyLenToWrite = 0; |
| size_t keyLen_roundoff = ((keyLen / 16) * 16) + ((keyLen % 16) == 0 ? 0 : 16); |
| size_t slots_req = (keyLen_roundoff / 16); |
| |
| if (slot_length != slots_req) { |
| return resSW; |
| } |
| |
| while (j < slot_length) { |
| KeyLenToWrite = (keyLenRem < maxKeyLen) ? keyLenRem : maxKeyLen; |
| if (KeyLenToWrite < maxKeyLen) { |
| uint8_t temp_key[16] = { |
| 0, |
| }; |
| memcpy(temp_key, (key + (j * maxKeyLen)), KeyLenToWrite); |
| resSW = A71_SetSymKey((U8)slot_id, temp_key, (U16)maxKeyLen); |
| } |
| else { |
| resSW = A71_SetSymKey((U8)slot_id, (key + (j * maxKeyLen)), (U16)maxKeyLen); |
| } |
| if (HLSE_SW_OK != resSW) { |
| break; |
| } |
| j++; |
| slot_id++; |
| keyLenRem = keyLenRem - KeyLenToWrite; |
| } |
| } |
| else if (key_part == kSSS_KeyPart_Pair && cipher_type == kSSS_CipherType_EC_NIST_P) { |
| uint8_t *pPrivateKey = NULL; |
| size_t privateKeyLen = 0; |
| uint8_t *pPublicKey = NULL; |
| size_t publicKeyLen = 0; |
| uint16_t privateKeyIndex = 0; |
| uint16_t publicKeyIndex = 0; |
| |
| if (keyBitLen != 256) { |
| LOG_E("Invalid bit length. Only NIST256 is supported in A71CH"); |
| return resSW; |
| } |
| |
| asn_retval = sss_util_pkcs8_asn1_get_ec_pair_key_index( |
| key, keyLen, &publicKeyIndex, &publicKeyLen, &privateKeyIndex, &privateKeyLen); |
| if (asn_retval != kStatus_SSS_Success) { |
| LOG_W("error in sss_util_pkcs8_asn1_get_ec_pair_key_index"); |
| return resSW; |
| } |
| |
| if (privateKeyLen == 0) { |
| LOG_E("private key len is 0"); |
| return resSW; |
| } |
| if (publicKeyLen == 0) { |
| LOG_E("Public key len is 0"); |
| return resSW; |
| } |
| |
| pPrivateKey = &key[privateKeyIndex]; |
| pPublicKey = &key[publicKeyIndex]; |
| |
| resSW = A71_SetEccKeyPair((U8)intId, pPublicKey, (U16)publicKeyLen, pPrivateKey, (U16)privateKeyLen); |
| } |
| else if (key_part == kSSS_KeyPart_Default && cipher_type == kSSS_CipherType_Binary) { |
| resSW = HLSE_EnumerateObjects(HLSE_CERTIFICATE, Handles, &HandlesNum); |
| if (resSW == HLSE_SW_OK) { |
| HandlesNum_copy = HandlesNum; |
| while (HandlesNum_copy) { |
| if (HLSE_GET_OBJECT_INDEX(Handles[i]) == intId) { |
| GetHandle = Handles[i]; |
| break; |
| } |
| i++; |
| HandlesNum_copy--; |
| } |
| } |
| if (GetHandle != 0) { |
| attr.type = HLSE_ATTR_OBJECT_VALUE; |
| attr.value = key; |
| attr.valueLen = (U16)keyLen; |
| resSW = HLSE_SetObjectAttribute(GetHandle, &attr); |
| } |
| } |
| } |
| else { |
| LOG_E("Could not find Ext ID 0x%X in keystore_shadow", extId); |
| } |
| return resSW; |
| } |
| |
| static HLSE_RET_CODE a71ch_eccSign(keyStoreTable_t *keystore_shadow, |
| uint32_t extKeyID, |
| uint8_t *pHash, |
| uint16_t hashLen, |
| uint8_t *pSignature, |
| uint16_t *pSignatureLen) |
| { |
| uint16_t intId = 0; |
| HLSE_RET_CODE resSW = HLSE_ERR_API_ERROR; |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extKeyID, &intId); |
| /* A71CH Max hashlen is AX_SHA256_LEN*/ |
| if (hashLen != AX_SHA256_LEN) { |
| LOG_E("Only SHA256(input) is supported "); |
| return resSW; |
| } |
| if (status == kStatus_SSS_Success) { |
| resSW = A71_EccSign((SST_Index_t)intId, pHash, hashLen, pSignature, pSignatureLen); |
| } |
| return resSW; |
| } |
| |
| static HLSE_RET_CODE a71ch_eccVerify(keyStoreTable_t *keystore_shadow, |
| uint32_t extKeyID, |
| uint8_t *pHash, |
| uint16_t hashLen, |
| uint8_t *pSignature, |
| uint16_t SignatureLen) |
| { |
| uint16_t intId = 0; |
| uint8_t result = 0; |
| HLSE_RET_CODE resSW = HLSE_ERR_API_ERROR; |
| sss_status_t status = ks_common_extId_to_int_index(keystore_shadow, extKeyID, &intId); |
| if (status == kStatus_SSS_Success) { |
| resSW = A71_EccVerify((SST_Index_t)intId, pHash, hashLen, pSignature, SignatureLen, &result); |
| } |
| if (resSW == SW_OK) |
| if (result == 0) |
| resSW = ERR_GENERAL_ERROR; |
| |
| return resSW; |
| } |
| |
| #endif /* SSS_HAVE_A71CH */ |