blob: 03e0fc99eee2338490ad1976e78fcf291cc749cd [file] [log] [blame]
/*
*
* Copyright 2018-2020 NXP
* SPDX-License-Identifier: Apache-2.0
*/
/** @file */
#ifdef __cplusplus
extern "C" {
#endif
#include <fsl_sss_se05x_apis.h>
#include <nxLog_sss.h>
#if SSS_HAVE_APPLET_SE05X_IOT
#include <fsl_sss_policy.h>
#include <fsl_sss_se05x_policy.h>
#include <fsl_sss_se05x_scp03.h>
#include <fsl_sss_util_asn1_der.h>
#include <fsl_sss_util_rsa_sign_utils.h>
#include <se05x_const.h>
#include <se05x_ecc_curves.h>
#include <sm_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nxEnsure.h"
#include "nxScp03_Apis.h"
#include "se05x_APDU.h"
#include "se05x_tlv.h"
#include "smCom.h"
#if (__GNUC__ && !AX_EMBEDDED)
#define LOCK_TXN(lock) \
LOG_D("Trying to Acquire Lock thread: %ld", pthread_self()); \
pthread_mutex_lock(&lock); \
LOG_D("LOCK Acquired by thread: %ld", pthread_self());
#define UNLOCK_TXN(lock) \
LOG_D("Trying to Released Lock by thread: %ld", pthread_self()); \
pthread_mutex_unlock(&lock); \
LOG_D("LOCK Released by thread: %ld", pthread_self());
#elif AX_EMBEDDED && USE_RTOS
#define LOCK_TXN(lock) \
LOG_D("Trying to Acquire Lock"); \
if (xSemaphoreTake(lock, portMAX_DELAY) == pdTRUE) { \
LOG_D("LOCK Acquired"); } \
else { \
LOG_D("LOCK Acquisition failed"); }
#define UNLOCK_TXN(lock) \
LOG_D("Trying to Released Lock"); \
if (xSemaphoreGive(lock) == pdTRUE) { \
LOG_D("LOCK Released");} \
else { \
LOG_D("LOCK Releasing failed"); }
#endif
#if (__GNUC__ && !AX_EMBEDDED) || (AX_EMBEDDED && USE_RTOS)
#define USE_LOCK 1
#else
#define USE_LOCK 0
#endif
static SE05x_ECSignatureAlgo_t se05x_get_ec_sign_hash_mode(sss_algorithm_t algorithm);
/* Used during testing as well */
void get_ecc_raw_data(uint8_t *key, uint8_t **key_buf, size_t *key_buflen, uint32_t curve_id);
#if SSSFTR_SE05X_AuthSession
static smStatus_t se05x_CreateVerifyUserIDSession(
pSe05xSession_t se05xSession, const uint32_t auth_id, SE05x_AuthCtx_ID_t *pin, pSe05xPolicy_t policy);
#endif
#if SSS_HAVE_SCP_SCP03_SSS
#if SSSFTR_SE05X_AuthECKey
static smStatus_t se05x_CreateECKeySession(
pSe05xSession_t se05xSession, const uint32_t auth_id, SE05x_AuthCtx_ECKey_t *pFScpCtx);
#endif
#if SSSFTR_SE05X_AuthSession
static smStatus_t se05x_CreateVerifyAESKeySession(
pSe05xSession_t se05xSession, const uint32_t auth_id, NXSCP03_AuthCtx_t *pAppletSCPCtx);
#endif
#endif
static smStatus_t sss_se05x_channel_txnRaw(void *conn_ctx,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle);
#if 0
static SE05x_RSASignatureAlgo_t se05x_get_rsa_sign_mode(
sss_algorithm_t algorithm);
#endif
#if SSSFTR_SE05X_RSA
static SE05x_RSAEncryptionAlgo_t se05x_get_rsa_encrypt_mode(sss_algorithm_t algorithm);
static SE05x_RSASignatureAlgo_t se05x_get_rsa_sign_hash_mode(sss_algorithm_t algorithm);
#endif
static SE05x_CipherMode_t se05x_get_cipher_mode(sss_algorithm_t algorithm);
static SE05x_MACAlgo_t se05x_get_mac_algo(sss_algorithm_t algorithm);
#if SSSFTR_SE05X_KEY_SET || SSSFTR_SE05X_KEY_GET
static uint8_t CheckIfKeyIdExists(uint32_t keyId, pSe05xSession_t session_ctx);
#endif
static smStatus_t sss_se05x_channel_txn(void *conn_ctx,
struct _sss_se05x_tunnel_context *pChannelCtx,
SE_AuthType_t currAuth,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle);
static smStatus_t sss_se05x_TXn(struct Se05xSession *pSession,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle);
#if SSSFTR_SE05X_AuthECKey || SSSFTR_SE05X_AuthSession
static sss_status_t sss_session_auth_open(sss_se05x_session_t *session,
sss_type_t subsystem,
uint32_t auth_id,
sss_connection_type_t connection_type,
void *connectionData);
#endif
#if SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_rsa_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len);
#endif
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
static sss_status_t se05x_check_input_len(size_t inLen, sss_algorithm_t algorithm);
#endif
#if SSS_HAVE_SE05X_VER_GTE_06_00
static sss_status_t sss_se05x_aead_CCMfinish(sss_se05x_aead_t *context,
const uint8_t *srcData,
size_t srcLen,
uint8_t *destData,
size_t *destLen,
uint8_t *tag,
size_t *tagLen);
#endif
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_ec_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_ECCurve_t curveID,
const uint8_t *privKey,
size_t privKeyLen,
const uint8_t *pubKey,
size_t pubKeyLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
SE05x_Result_t obj_exists);
#if SSS_HAVE_SE05X_VER_GTE_06_00
typedef smStatus_t (*fp_Ec_KeyWrite_t)(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_ECCurve_t curveID,
const uint8_t *privKey,
size_t privKeyLen,
const uint8_t *pubKey,
size_t pubKeyLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
uint32_t version);
#endif //SSS_HAVE_SE05X_VER_GTE_06_00
#endif //SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_symm_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_KeyID_t kekID,
const uint8_t *keyValue,
size_t keyValueLen,
const SE05x_INS_t ins_type,
const SE05x_SymmKeyType_t type,
SE05x_Result_t obj_exists);
#if SSS_HAVE_SE05X_VER_GTE_06_00
typedef smStatus_t (*fp_Symm_KeyWrite_t)(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_KeyID_t kekID,
const uint8_t *keyValue,
size_t keyValueLen,
const SE05x_INS_t ins_type,
const SE05x_SymmKeyType_t type,
uint32_t version);
#endif //SSS_HAVE_SE05X_VER_GTE_06_00
#endif //SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_RSA_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
uint32_t objectID,
uint16_t size,
const uint8_t *p,
size_t pLen,
const uint8_t *q,
size_t qLen,
const uint8_t *dp,
size_t dpLen,
const uint8_t *dq,
size_t dqLen,
const uint8_t *qInv,
size_t qInvLen,
const uint8_t *pubExp,
size_t pubExpLen,
const uint8_t *priv,
size_t privLen,
const uint8_t *pubMod,
size_t pubModLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
const SE05x_RSAKeyFormat_t rsa_format,
SE05x_Result_t obj_exists);
#if SSS_HAVE_SE05X_VER_GTE_06_00
typedef smStatus_t (*fp_RSA_KeyWrite_t)(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
uint32_t objectID,
uint16_t size,
const uint8_t *p,
size_t pLen,
const uint8_t *q,
size_t qLen,
const uint8_t *dp,
size_t dpLen,
const uint8_t *dq,
size_t dqLen,
const uint8_t *qInv,
size_t qInvLen,
const uint8_t *pubExp,
size_t pubExpLen,
const uint8_t *priv,
size_t privLen,
const uint8_t *pubMod,
size_t pubModLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
const SE05x_RSAKeyFormat_t rsa_format,
uint32_t version);
#endif //SSS_HAVE_SE05X_VER_GTE_06_00
#endif //SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
/* ************************************************************************** */
/* Defines */
/* ************************************************************************** */
/* ************************************************************************** */
/* Functions : sss_se05x_session */
/* ************************************************************************** */
sss_status_t sss_se05x_session_create(sss_se05x_session_t *session,
sss_type_t subsystem,
uint32_t application_id,
sss_connection_type_t connection_type,
void *connectionData)
{
sss_status_t retval = kStatus_SSS_Success;
/* Nothing special to be handled */
return retval;
}
#define HEX_EXPECTED_APPLET_VERSION \
(0 | (APPLET_SE050_VER_MAJOR) << (8 * 3) | (APPLET_SE050_VER_MINOR) << (8 * 2) | (APPLET_SE050_VER_DEV) << (8 * 1))
#if defined(APPLET_SE050_VER_DEV_PATCH1)
#define HEX_EXPECTED_APPLET_VERSION_PATCH1 \
(0 | (APPLET_SE050_VER_MAJOR) << (8 * 3) | (APPLET_SE050_VER_MINOR) << (8 * 2) | \
(APPLET_SE050_VER_DEV_PATCH1) << (8 * 1))
#endif
sss_status_t sss_se05x_session_open(sss_se05x_session_t *session,
sss_type_t subsystem,
uint32_t application_id,
sss_connection_type_t connection_type,
void *connectionData)
{
sss_status_t retval = kStatus_SSS_InvalidArgument;
SE05x_Connect_Ctx_t *pAuthCtx = NULL;
SmCommState_t CommState = {0};
smStatus_t status = SM_NOT_OK;
U16 lReturn;
pSe05xSession_t se05xSession;
ENSURE_OR_GO_EXIT(session);
se05xSession = &session->s_ctx;
memset(session, 0, sizeof(*session));
ENSURE_OR_GO_EXIT(connectionData);
pAuthCtx = (SE05x_Connect_Ctx_t *)connectionData;
if (pAuthCtx->connType != kType_SE_Conn_Type_Channel) {
uint8_t atr[100];
uint16_t atrLen = ARRAY_SIZE(atr);
CommState.connType = pAuthCtx->connType;
if (1 == pAuthCtx->skip_select_applet) {
if (pAuthCtx->auth.authType == kSSS_AuthType_None) {
CommState.select = SELECT_NONE;
}
else if (pAuthCtx->auth.authType == kSSS_AuthType_SCP03) {
CommState.select = SELECT_SSD;
}
}
#if defined(SMCOM_JRCP_V1) || defined(SMCOM_JRCP_V2) || defined(RJCT_VCOM) || defined(SMCOM_PCSC) || \
defined(SMCOM_RC663_VCOM)
lReturn = SM_RjctConnect(&(se05xSession->conn_ctx), pAuthCtx->portName, &CommState, atr, &atrLen);
if (lReturn != SW_OK) {
LOG_E("SM_RjctConnect Failed. Status %04X", lReturn);
goto exit;
}
if (atrLen != 0) {
LOG_AU8_I(atr, atrLen);
}
#else
/* AX_EMBEDDED Or Native */
lReturn = SM_I2CConnect(&(se05xSession->conn_ctx), &CommState, atr, &atrLen, pAuthCtx->portName);
if (lReturn != SW_OK) {
LOG_E("SM_Connect Failed. Status %04X", lReturn);
retval = kStatus_SSS_Fail;
return retval;
}
if (atrLen != 0) {
LOG_AU8_I(atr, atrLen);
}
#endif
if (1 == pAuthCtx->skip_select_applet) {
status = lReturn;
/* Not selecting the applet, so we don't know whether it's old or new */
}
else {
if (HEX_EXPECTED_APPLET_VERSION == (0xFFFFFF00 & CommState.appletVersion)) {
/* Fine */
}
#if defined(HEX_EXPECTED_APPLET_VERSION_PATCH1)
else if (HEX_EXPECTED_APPLET_VERSION_PATCH1 == (0xFFFFFF00 & CommState.appletVersion)) {
/* Fine */
}
#endif
else if ((0xFFFFFF00 & CommState.appletVersion) < HEX_EXPECTED_APPLET_VERSION) {
LOG_E("Mismatch Applet version.");
LOG_E("Compiled for 0x%X. Got older 0x%X",
(HEX_EXPECTED_APPLET_VERSION) >> 8,
(CommState.appletVersion) >> 8);
LOG_E("Aborting!!!");
SM_Close(se05xSession->conn_ctx, 0);
return kStatus_SSS_Fail;
}
else {
LOG_I("Newer version of Applet Found");
LOG_I("Compiled for 0x%X. Got newer 0x%X",
(HEX_EXPECTED_APPLET_VERSION) >> 8,
(CommState.appletVersion) >> 8);
}
}
}
if (pAuthCtx->auth.authType == kSSS_AuthType_ECKey) {
if (CommState.appletVersion == 0) {
/*Get Applet version from previously opened session*/
uint8_t appletVersion[32] = {0};
uint8_t versionIterator = 0;
size_t appletVersionLen = sizeof(appletVersion);
sss_se05x_session_t *se05x_session = (sss_se05x_session_t *)pAuthCtx->tunnelCtx->session;
status = Se05x_API_GetVersion(&se05x_session->s_ctx, appletVersion, &appletVersionLen);
if (status != SM_OK) {
LOG_E("Unable to retrive applet version");
retval = kStatus_SSS_Fail;
goto exit;
}
for (versionIterator = 0; versionIterator < 3; versionIterator++) {
CommState.appletVersion = CommState.appletVersion << 8 | appletVersion[versionIterator];
}
CommState.appletVersion = CommState.appletVersion << 8;
}
if (CommState.appletVersion >= 0x03050000) {
pAuthCtx->auth.ctx.eckey.pDyn_ctx->authType = kSSS_AuthType_INT_ECKey_Counter;
}
else {
pAuthCtx->auth.ctx.eckey.pDyn_ctx->authType = kSSS_AuthType_ECKey;
}
}
se05xSession->fp_TXn = &sss_se05x_TXn;
se05xSession->fp_RawTXn = &sss_se05x_channel_txn;
/* Auth type is None */
if (1 == pAuthCtx->skip_select_applet) {
/* Not selecting the applet */
}
else {
if ((pAuthCtx->auth.authType == kSSS_AuthType_None) && (connection_type == kSSS_ConnectionType_Plain)) {
LOG_W("Communication channel is Plain.");
LOG_W("!!!Not recommended for production use.!!!");
se05xSession->fp_Transform = &se05x_Transform;
se05xSession->fp_DeCrypt = &se05x_DeCrypt;
se05xSession->authType = kSSS_AuthType_None;
status = SM_OK;
}
}
#if SSS_HAVE_SCP_SCP03_SSS
/* Auth type is Platform SCP03 */
if ((pAuthCtx->auth.authType == kSSS_AuthType_SCP03) && (connection_type == kSSS_ConnectionType_Encrypted)) {
se05xSession->fp_Transform = &se05x_Transform;
se05xSession->fp_DeCrypt = &se05x_DeCrypt;
retval = nxScp03_AuthenticateChannel(se05xSession, &pAuthCtx->auth.ctx.scp03);
if (retval == kStatus_SSS_Success) {
/* There is a differnet behaviour of Platform SCP between SE050 and future applet.
* Here we switch make it clear. */
if (CommState.appletVersion >= 0x04030000) {
pAuthCtx->auth.ctx.scp03.pDyn_ctx->authType = (uint8_t)kSSS_AuthType_AESKey;
}
else {
pAuthCtx->auth.ctx.scp03.pDyn_ctx->authType = (uint8_t)kSSS_AuthType_SCP03;
}
/*Auth type to Platform SCP03 again as channel authentication will modify it
to auth type None*/
se05xSession->authType = kSSS_AuthType_SCP03;
se05xSession->pdynScp03Ctx = pAuthCtx->auth.ctx.scp03.pDyn_ctx;
status = SM_OK;
se05xSession->fp_Transform = &se05x_Transform_scp;
}
else {
LOG_E("Could not set SCP03 Secure Channel");
}
}
#else
if (pAuthCtx->auth.authType != kSSS_AuthType_None && pAuthCtx->auth.authType != kSSS_AuthType_ID) {
LOG_E(
"Set the SCP to SCP03_SSS in the build configuration and "
"recompile.!");
}
#endif
#if SSSFTR_SE05X_AuthECKey || SSSFTR_SE05X_AuthSession
if (pAuthCtx->connType == kType_SE_Conn_Type_Channel) {
se05xSession->pChannelCtx = (struct _sss_se05x_tunnel_context *)pAuthCtx->tunnelCtx;
}
if ((application_id != 0) &&
((connection_type == kSSS_ConnectionType_Password) || (connection_type == kSSS_ConnectionType_Encrypted))) {
retval = sss_session_auth_open(session, subsystem, application_id, connection_type, connectionData);
if (retval == kStatus_SSS_Success) {
status = SM_OK;
}
else {
SM_Close(se05xSession->conn_ctx, 0);
status = SM_NOT_OK;
}
}
#endif
if (status == SM_OK) {
session->subsystem = subsystem;
retval = kStatus_SSS_Success;
}
else {
memset(session, 0x00, sizeof(*session));
retval = kStatus_SSS_Fail;
}
exit:
return retval;
}
#if SSSFTR_SE05X_AuthECKey || SSSFTR_SE05X_AuthSession
static sss_status_t sss_session_auth_open(sss_se05x_session_t *session,
sss_type_t subsystem,
uint32_t auth_id,
sss_connection_type_t connect_type,
void *connectionData)
{
sss_status_t retval = kStatus_SSS_Fail;
void *conn_ctx = session->s_ctx.conn_ctx;
memset(session, 0, sizeof(*session));
SE05x_Connect_Ctx_t *pAuthCtx;
smStatus_t status = SM_NOT_OK;
#if SSSFTR_SE05X_AuthSession
Se05xPolicy_t se05x_policy;
uint8_t *ppolicySet;
uint8_t session_policies_buff[MAX_POLICY_BUFFER_SIZE];
size_t valid_policy_buff_len = 0;
#endif
retval = kStatus_SSS_Fail;
pSe05xSession_t se05xSession = &session->s_ctx;
/* Restore connection context */
se05xSession->conn_ctx = conn_ctx;
ENSURE_OR_GO_EXIT(connectionData != NULL);
pAuthCtx = (SE05x_Connect_Ctx_t *)connectionData;
if ((pAuthCtx->auth.authType == kSSS_AuthType_ID) && (connect_type != kSSS_ConnectionType_Password)) {
LOG_D("ERROR: Need both AUTHType=ID and ConnType=Password");
goto exit;
}
if (((pAuthCtx->auth.authType == kSSS_AuthType_AESKey) || (pAuthCtx->auth.authType == kSSS_AuthType_ECKey)) &&
(connect_type != kSSS_ConnectionType_Encrypted)) {
LOG_D("ERROR: Need both AUTHType={AESKey||ECKey} and ConnType=Encrypted");
goto exit;
}
se05xSession->fp_TXn = &sss_se05x_TXn;
se05xSession->fp_RawTXn = &sss_se05x_channel_txn;
if (pAuthCtx->connType == kType_SE_Conn_Type_Channel) {
se05xSession->pChannelCtx = (struct _sss_se05x_tunnel_context *)pAuthCtx->tunnelCtx;
}
#if SSSFTR_SE05X_AuthSession
/*Session Policy check*/
if (pAuthCtx->session_policy) {
if (kStatus_SSS_Success != sss_se05x_create_session_policy_buffer(
pAuthCtx->session_policy, &session_policies_buff[0], &valid_policy_buff_len)) {
goto exit;
}
ppolicySet = session_policies_buff;
}
else {
ppolicySet = NULL;
}
se05x_policy.value = (uint8_t *)ppolicySet;
se05x_policy.value_len = valid_policy_buff_len;
#endif
/* Auth type is Platform UserID */
if (pAuthCtx->auth.authType == kSSS_AuthType_ID)
#if SSSFTR_SE05X_AuthSession
{
LOG_W("Communication channel is with UserID (But Plain).");
LOG_W("!!!Not recommended for production use.!!!");
se05xSession->fp_Transform = &se05x_Transform;
se05xSession->fp_DeCrypt = &se05x_DeCrypt;
status = se05x_CreateVerifyUserIDSession(se05xSession, auth_id, &pAuthCtx->auth.ctx.idobj, &se05x_policy);
if (status != SM_OK) {
se05xSession->hasSession = 1;
se05xSession->authType = kSSS_AuthType_ID;
}
}
#else
LOG_W("User Id Support compiled out");
status = SM_NOT_OK;
#endif
#if SSS_HAVE_SCP_SCP03_SSS
/* Auth type is ECKey */
if ((pAuthCtx->auth.authType == kSSS_AuthType_ECKey) && (auth_id != 0)) {
#if SSSFTR_SE05X_AuthECKey
se05xSession->fp_Transform = &se05x_Transform;
se05xSession->fp_DeCrypt = &se05x_DeCrypt;
status = se05x_CreateECKeySession(se05xSession, auth_id, &pAuthCtx->auth.ctx.eckey);
if (status == SM_OK) {
se05xSession->fp_Transform = &se05x_Transform_scp;
if (se05x_policy.value_len > 0) {
status = Se05x_API_ExchangeSessionData(se05xSession, &se05x_policy);
}
}
#else
LOG_W("ECKey Support compiled out");
status = SM_NOT_OK;
#endif
}
/* Auth type is Applet SCP03 */
if ((pAuthCtx->auth.authType == kSSS_AuthType_AESKey) && (auth_id != 0)) {
#if SSSFTR_SE05X_AuthSession
se05xSession->fp_Transform = &se05x_Transform;
se05xSession->fp_DeCrypt = &se05x_DeCrypt;
status = se05x_CreateVerifyAESKeySession(se05xSession, auth_id, &pAuthCtx->auth.ctx.scp03);
if (status == SM_OK) {
se05xSession->fp_Transform = &se05x_Transform_scp;
if (se05x_policy.value_len > 0) {
status = SM_NOT_OK;
status = Se05x_API_ExchangeSessionData(se05xSession, &se05x_policy);
}
}
#else
LOG_W("AppletSCP Support compiled out");
status = SM_NOT_OK;
#endif
}
#endif
if (status == SM_OK) {
session->subsystem = subsystem;
retval = kStatus_SSS_Success;
}
else {
memset(session, 0x00, sizeof(*session));
retval = kStatus_SSS_Fail;
}
/* Restore connection context */
session->s_ctx.conn_ctx = conn_ctx;
exit:
return retval;
}
#endif
sss_status_t sss_se05x_refresh_session(sss_se05x_session_t *session, void *connectionData)
{
sss_status_t retval = kStatus_SSS_Fail;
pSe05xSession_t se05xSession = &session->s_ctx;
sss_policy_session_u *session_policy = (sss_policy_session_u *)connectionData;
smStatus_t status = SM_NOT_OK;
size_t valid_policy_buff_len = 0;
Se05xPolicy_t se05x_policy = {0};
uint8_t *ppolicySet;
uint8_t session_policies_buff[MAX_POLICY_BUFFER_SIZE];
if (session_policy) {
if (kStatus_SSS_Success !=
sss_se05x_create_session_policy_buffer(session_policy, &session_policies_buff[0], &valid_policy_buff_len)) {
goto exit;
}
ppolicySet = session_policies_buff;
se05x_policy.value = (uint8_t *)ppolicySet;
se05x_policy.value_len = valid_policy_buff_len;
}
else {
ppolicySet = NULL;
se05x_policy.value = NULL;
se05x_policy.value_len = 0;
}
status = Se05x_API_RefreshSession(se05xSession, &se05x_policy);
if (status == SM_OK) {
retval = kStatus_SSS_Success;
}
exit:
return retval;
}
sss_status_t sss_se05x_session_prop_get_u32(sss_se05x_session_t *session, uint32_t property, uint32_t *pValue)
{
sss_status_t retval = kStatus_SSS_Success;
sss_session_prop_u32_t prop = property;
sss_s05x_sesion_prop_u32_t se050xprop = property;
if (pValue == NULL) {
retval = kStatus_SSS_Fail;
goto cleanup;
}
switch (prop) {
case kSSS_SessionProp_VerMaj:
*pValue = PLUGANDTRUST_HOSTLIB_VER_MAJOR;
break;
case kSSS_SessionProp_VerMin:
*pValue = PLUGANDTRUST_HOSTLIB_VER_MINOR;
break;
case kSSS_SessionProp_VerDev:
*pValue = PLUGANDTRUST_HOSTLIB_VER_DEV;
break;
case kSSS_SessionProp_UIDLen:
*pValue = 18;
break;
default:
*pValue = 0;
retval = kStatus_SSS_Fail;
}
if (retval == kStatus_SSS_Success)
goto cleanup;
switch (se050xprop) {
case kSSS_SE05x_SessionProp_CertUIDLen: {
*pValue = 10;
retval = kStatus_SSS_Success;
} break;
default: {
*pValue = 0;
retval = kStatus_SSS_Fail;
}
}
cleanup:
return retval;
}
sss_status_t sss_se05x_session_prop_get_au8(
sss_se05x_session_t *session, uint32_t property, uint8_t *pValue, size_t *pValueLen)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_session_prop_au8_t prop = property;
sss_s05x_sesion_prop_au8_t se050xprop = property;
smStatus_t sm_status = SM_NOT_OK;
if (pValue == NULL || pValueLen == NULL) {
goto cleanup;
}
switch (prop) {
case kSSS_SessionProp_UID:
if (*pValueLen >= 18) {
sm_status = Se05x_API_ReadObject(&session->s_ctx, kSE05x_AppletResID_UNIQUE_ID, 0, 18, pValue, pValueLen);
}
else {
LOG_D("Buffer too short");
}
break;
default:;
}
if (sm_status == SM_OK)
goto cleanup;
switch (se050xprop) {
case kSSS_SE05x_SessionProp_CertUID:
if (*pValueLen >= 10) {
uint8_t uid18[SE050_MODULE_UNIQUE_ID_LEN];
size_t uid18Len = sizeof(uid18);
sm_status = Se05x_API_ReadObject(
&session->s_ctx, kSE05x_AppletResID_UNIQUE_ID, 0, (uint16_t)uid18Len, uid18, &uid18Len);
if (sm_status == SM_OK) {
int idx = 0;
#define A71CH_UID_IC_TYPE_OFFSET 2
#define A71CH_UID_IC_FABRICATION_DATA_OFFSET 8
#define A71CH_UID_IC_SERIAL_NR_OFFSET 10
#define A71CH_UID_IC_BATCH_ID_OFFSET 13
pValue[idx++] = uid18[A71CH_UID_IC_TYPE_OFFSET];
pValue[idx++] = uid18[A71CH_UID_IC_TYPE_OFFSET + 1];
pValue[idx++] = uid18[A71CH_UID_IC_FABRICATION_DATA_OFFSET];
pValue[idx++] = uid18[A71CH_UID_IC_FABRICATION_DATA_OFFSET + 1];
pValue[idx++] = uid18[A71CH_UID_IC_SERIAL_NR_OFFSET];
pValue[idx++] = uid18[A71CH_UID_IC_SERIAL_NR_OFFSET + 1];
pValue[idx++] = uid18[A71CH_UID_IC_SERIAL_NR_OFFSET + 2];
pValue[idx++] = uid18[A71CH_UID_IC_BATCH_ID_OFFSET];
pValue[idx++] = uid18[A71CH_UID_IC_BATCH_ID_OFFSET + 1];
pValue[idx++] = uid18[A71CH_UID_IC_BATCH_ID_OFFSET + 2];
*pValueLen = 10;
}
}
break;
}
cleanup:
if (sm_status == SM_OK)
retval = kStatus_SSS_Success;
return retval;
}
void sss_se05x_session_close(sss_se05x_session_t *session)
{
Se05x_API_CloseSession(&session->s_ctx);
if (session->s_ctx.pChannelCtx == NULL) {
SM_Close(session->s_ctx.conn_ctx, 0);
}
memset(session, 0, sizeof(*session));
}
void sss_se05x_session_delete(sss_se05x_session_t *session)
{
;
}
/* End: se05x_session */
/* ************************************************************************** */
/* Functions : sss_se05x_keyobj */
/* ************************************************************************** */
sss_status_t sss_se05x_key_object_init(sss_se05x_object_t *keyObject, sss_se05x_key_store_t *keyStore)
{
sss_status_t retval = kStatus_SSS_Success;
memset(keyObject, 0, sizeof(*keyObject));
keyObject->keyStore = keyStore;
return retval;
}
sss_status_t sss_se05x_key_object_allocate_handle(sss_se05x_object_t *keyObject,
uint32_t keyId,
sss_key_part_t keyPart,
sss_cipher_type_t cipherType,
size_t keyByteLenMax,
uint32_t options)
{
sss_status_t retval = kStatus_SSS_Success;
smStatus_t status;
SE05x_Result_t exists = kSE05x_Result_NA;
keyObject->objectType = keyPart;
keyObject->cipherType = cipherType;
keyObject->keyId = keyId;
if (options == kKeyObject_Mode_Persistent)
keyObject->isPersistant = 1;
status = Se05x_API_CheckObjectExists(&keyObject->keyStore->session->s_ctx, keyId, &exists);
if (status == SM_OK) {
if (exists == kSE05x_Result_SUCCESS) {
LOG_W("Object id 0x%X exists", keyId);
}
}
else {
LOG_E("Couldn't check if object id 0x%X exists", keyId);
return kStatus_SSS_Fail;
}
return retval;
}
//static sss_status_t sss_se05x_key_object_get_handle_binary(
// sss_se05x_object_t *keyObject) {
// sss_status_t retval = kStatus_SSS_Success;
// keyObject->objectType = kSSS_KeyPart_Default;
// keyObject->cipherType = kSSS_CipherType_Binary;
// return retval;
//}
sss_status_t sss_se05x_key_object_get_handle(sss_se05x_object_t *keyObject, uint32_t keyId)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_KEY_GET
SE05x_SecObjTyp_t retObjectType;
uint8_t retTransientType;
SE05x_ECCurve_t retCurveId;
const SE05x_AttestationType_t attestationType = kSE05x_AttestationType_None;
smStatus_t apiRetval;
if (0 == CheckIfKeyIdExists(keyId, &keyObject->keyStore->session->s_ctx)) {
/* Object does not exist */
LOG_D("keyId does not exist");
LOG_U32_D(keyId);
return retval;
}
apiRetval = Se05x_API_ReadType(
&keyObject->keyStore->session->s_ctx, keyId, &retObjectType, &retTransientType, attestationType);
if (apiRetval == SM_OK) {
keyObject->isPersistant = retTransientType;
if (retObjectType >= kSE05x_SecObjTyp_EC_KEY_PAIR && retObjectType <= kSE05x_SecObjTyp_EC_PUB_KEY) {
apiRetval = Se05x_API_EC_CurveGetId(&keyObject->keyStore->session->s_ctx, keyId, &retCurveId);
if (apiRetval == SM_OK) {
keyObject->curve_id = retCurveId;
if ((retCurveId >= kSE05x_ECCurve_NIST_P192) && (retCurveId <= kSE05x_ECCurve_NIST_P521)) {
keyObject->cipherType = kSSS_CipherType_EC_NIST_P;
}
else if ((retCurveId >= kSE05x_ECCurve_Brainpool160) && (retCurveId <= kSE05x_ECCurve_Brainpool512)) {
keyObject->cipherType = kSSS_CipherType_EC_BRAINPOOL;
}
else if ((retCurveId >= kSE05x_ECCurve_Secp160k1) && (retCurveId <= kSE05x_ECCurve_Secp256k1)) {
keyObject->cipherType = kSSS_CipherType_EC_NIST_K;
}
else if (retCurveId == kSE05x_ECCurve_RESERVED_ID_ECC_ED_25519) {
keyObject->cipherType = kSSS_CipherType_EC_TWISTED_ED;
}
else if (retCurveId == kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_25519) {
keyObject->cipherType = kSSS_CipherType_EC_MONTGOMERY;
}
else if (retCurveId == kSE05x_ECCurve_TPM_ECC_BN_P256) {
keyObject->cipherType = kSSS_CipherType_EC_BARRETO_NAEHRIG;
}
#if SSS_HAVE_SE05X_VER_GTE_06_00
else if (retCurveId == kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_448) {
keyObject->cipherType = kSSS_CipherType_EC_MONTGOMERY;
}
#endif
else {
return retval;
}
}
else {
LOG_E("error in Se05x_API_GetECCurveId");
return retval;
}
}
#if SSSFTR_RSA
else if (retObjectType == kSE05x_SecObjTyp_RSA_KEY_PAIR_CRT) {
keyObject->cipherType = kSSS_CipherType_RSA_CRT;
}
else if (retObjectType == kSE05x_SecObjTyp_RSA_PRIV_KEY_CRT) {
keyObject->cipherType = kSSS_CipherType_RSA_CRT;
}
else if (retObjectType >= kSE05x_SecObjTyp_RSA_KEY_PAIR && retObjectType <= kSE05x_SecObjTyp_RSA_PUB_KEY) {
keyObject->cipherType = kSSS_CipherType_RSA;
}
#endif
else if (retObjectType == kSE05x_SecObjTyp_AES_KEY) {
keyObject->cipherType = kSSS_CipherType_AES;
}
else if (retObjectType == kSE05x_SecObjTyp_DES_KEY) {
keyObject->cipherType = kSSS_CipherType_DES;
}
else if (retObjectType == kSE05x_SecObjTyp_BINARY_FILE) {
keyObject->cipherType = kSSS_CipherType_Binary;
}
else if (retObjectType == kSE05x_SecObjTyp_UserID) {
keyObject->cipherType = kSSS_CipherType_UserID;
}
else if (retObjectType == kSE05x_SecObjTyp_COUNTER) {
keyObject->cipherType = kSSS_CipherType_Count;
}
else if (retObjectType == kSE05x_SecObjTyp_PCR) {
keyObject->cipherType = kSSS_CipherType_PCR;
}
else if (retObjectType == kSE05x_SecObjTyp_HMAC_KEY) {
keyObject->cipherType = kSSS_CipherType_HMAC;
}
switch (retObjectType) {
case kSE05x_SecObjTyp_EC_KEY_PAIR:
case kSE05x_SecObjTyp_RSA_KEY_PAIR:
case kSE05x_SecObjTyp_RSA_KEY_PAIR_CRT:
keyObject->objectType = kSSS_KeyPart_Pair;
break;
case kSE05x_SecObjTyp_EC_PUB_KEY:
case kSE05x_SecObjTyp_RSA_PUB_KEY:
keyObject->objectType = kSSS_KeyPart_Public;
break;
case kSE05x_SecObjTyp_BINARY_FILE:
case kSE05x_SecObjTyp_PCR:
case kSE05x_SecObjTyp_AES_KEY:
case kSE05x_SecObjTyp_DES_KEY:
case kSE05x_SecObjTyp_HMAC_KEY:
keyObject->objectType = kSSS_KeyPart_Default;
break;
default:
keyObject->objectType = kSSS_KeyPart_NONE;
break;
}
}
else {
LOG_E("error in Se05x_API_ReadType");
return retval;
}
keyObject->keyId = keyId;
retval = kStatus_SSS_Success;
#endif // SSSFTR_SE05X_KEY_GET
return retval;
}
sss_status_t sss_se05x_key_object_set_user(sss_se05x_object_t *keyObject, uint32_t user, uint32_t options)
{
sss_status_t retval = kStatus_SSS_Fail;
/* Purpose / Policy is set during creation time and hence can not
* enforced in SE050 later on */
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_set_purpose(sss_se05x_object_t *keyObject, sss_mode_t purpose, uint32_t options)
{
sss_status_t retval = kStatus_SSS_Fail;
/* Purpose / Policy is set during creation time and hence can not
* enforced in SE050 later on */
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_set_access(sss_se05x_object_t *keyObject, uint32_t access, uint32_t options)
{
sss_status_t retval = kStatus_SSS_Fail;
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_set_eccgfp_group(sss_se05x_object_t *keyObject, sss_eccgfp_group_t *group)
{
sss_status_t retval = kStatus_SSS_Fail;
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_get_user(sss_se05x_object_t *keyObject, uint32_t *user)
{
sss_status_t retval = kStatus_SSS_Fail;
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_get_purpose(sss_se05x_object_t *keyObject, sss_mode_t *purpose)
{
sss_status_t retval = kStatus_SSS_Fail;
LOG_W("Not supported in SE05X");
return retval;
}
sss_status_t sss_se05x_key_object_get_access(sss_se05x_object_t *keyObject, uint32_t *access)
{
sss_status_t retval = kStatus_SSS_Fail;
LOG_W("Not supported in SE05X");
return retval;
}
void sss_se05x_key_object_free(sss_se05x_object_t *keyObject)
{
memset(keyObject, 0, sizeof(*keyObject));
}
/* End: se05x_keyobj */
/* ************************************************************************** */
/* Functions : sss_se05x_keyderive */
/* ************************************************************************** */
sss_status_t sss_se05x_derive_key_context_init(sss_se05x_derive_key_t *context,
sss_se05x_session_t *session,
sss_se05x_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
context->keyObject = keyObject;
context->algorithm = algorithm;
context->mode = mode;
return retval;
}
sss_status_t sss_se05x_derive_key_go(sss_se05x_derive_key_t *context,
const uint8_t *saltData,
size_t saltLen,
const uint8_t *info,
size_t infoLen,
sss_se05x_object_t *derivedKeyObject,
uint16_t deriveDataLen,
uint8_t *hkdfOutput,
size_t *hkdfOutputLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t hkdfKey[SE05X_MAX_BUF_SIZE_CMD] = {
0,
};
size_t hkdfKeyLen = sizeof(hkdfKey);
sss_object_t *sss_derived_keyObject = (sss_object_t *)derivedKeyObject;
SE05x_DigestMode_t digestMode;
digestMode = se05x_get_sha_algo(context->algorithm);
status = Se05x_API_HKDF(&context->session->s_ctx,
context->keyObject->keyId,
digestMode,
saltData,
saltLen,
info,
infoLen,
deriveDataLen,
hkdfKey,
&hkdfKeyLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = sss_key_store_set_key((sss_key_store_t *)derivedKeyObject->keyStore,
sss_derived_keyObject,
hkdfKey,
hkdfKeyLen,
hkdfKeyLen * 8,
NULL,
0);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_derive_key_one_go(sss_se05x_derive_key_t *context,
const uint8_t *saltData,
size_t saltLen,
const uint8_t *info,
size_t infoLen,
sss_se05x_object_t *derivedKeyObject,
uint16_t deriveDataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t hkdfKey[1024] = {
0,
};
size_t hkdfKeyLen = sizeof(hkdfKey);
sss_object_t *sss_derived_keyObject = (sss_object_t *)derivedKeyObject;
SE05x_DigestMode_t digestMode;
digestMode = se05x_get_sha_algo(context->algorithm);
uint32_t derivedKeyID = (derivedKeyObject == NULL ? 0 : derivedKeyObject->keyId);
uint8_t *pHkdfKey = hkdfKey;
SE05x_HkdfMode_t hkdfMode =
(context->mode == kMode_SSS_HKDF_ExpandOnly ? kSE05x_HkdfMode_ExpandOnly : kSE05x_HkdfMode_ExtractExpand);
#if SSS_HAVE_SE05X_VER_GTE_06_00
if (context->keyObject->keyStore == derivedKeyObject->keyStore) {
pHkdfKey = NULL;
}
#endif
status = Se05x_API_HKDF_Extended(&context->session->s_ctx,
context->keyObject->keyId,
digestMode,
hkdfMode,
saltData,
saltLen,
0,
info,
infoLen,
derivedKeyID,
deriveDataLen,
pHkdfKey,
&hkdfKeyLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (pHkdfKey != NULL) {
retval = sss_key_store_set_key((sss_key_store_t *)derivedKeyObject->keyStore,
sss_derived_keyObject,
hkdfKey,
hkdfKeyLen,
hkdfKeyLen * 8,
NULL,
0);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_derive_key_sobj_one_go(sss_se05x_derive_key_t *context,
sss_se05x_object_t *saltKeyObject,
const uint8_t *info,
size_t infoLen,
sss_se05x_object_t *derivedKeyObject,
uint16_t deriveDataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t hkdfKey[1024] = {
0,
};
size_t hkdfKeyLen = sizeof(hkdfKey);
sss_object_t *sss_derived_keyObject = (sss_object_t *)derivedKeyObject;
SE05x_DigestMode_t digestMode;
digestMode = se05x_get_sha_algo(context->algorithm);
uint32_t saltID = (saltKeyObject == NULL ? 0 : saltKeyObject->keyId);
uint32_t derivedKeyID = (derivedKeyObject == NULL ? 0 : derivedKeyObject->keyId);
uint8_t *pHkdfKey = hkdfKey;
SE05x_HkdfMode_t hkdfMode =
(context->mode == kMode_SSS_HKDF_ExpandOnly ? kSE05x_HkdfMode_ExpandOnly : kSE05x_HkdfMode_ExtractExpand);
if (saltKeyObject != NULL) {
// Enforce that Salt is stored (securely) in the same keystore as the HMAC key.
if (context->keyObject->keyStore != saltKeyObject->keyStore) {
retval = kStatus_SSS_InvalidArgument;
goto exit;
}
}
#if SSS_HAVE_SE05X_VER_GTE_06_00
if (context->keyObject->keyStore == derivedKeyObject->keyStore) {
pHkdfKey = NULL;
}
#endif
status = Se05x_API_HKDF_Extended(&context->session->s_ctx,
context->keyObject->keyId,
digestMode,
hkdfMode,
NULL,
0,
saltID,
info,
infoLen,
derivedKeyID,
deriveDataLen,
pHkdfKey,
&hkdfKeyLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (pHkdfKey != NULL) {
retval = sss_key_store_set_key((sss_key_store_t *)derivedKeyObject->keyStore,
sss_derived_keyObject,
hkdfKey,
hkdfKeyLen,
hkdfKeyLen * 8,
NULL,
0);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_derive_key_dh(
sss_se05x_derive_key_t *context, sss_se05x_object_t *otherPartyKeyObject, sss_se05x_object_t *derivedKeyObject)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t pubkey[256] = {0};
size_t pubkeylen = sizeof(pubkey);
uint8_t sharedsecret[256];
size_t sharedsecretLen = sizeof(sharedsecret);
size_t pbKeyBitLen = 0;
uint8_t *pPublicKey = NULL;
size_t publicKeyLen = 0;
uint16_t publicKeyIndex = 0;
sss_object_t *sss_other_keyObject = (sss_object_t *)otherPartyKeyObject;
sss_object_t *sss_derived_keyObject = (sss_object_t *)derivedKeyObject;
retval = sss_key_store_get_key(
(sss_key_store_t *)sss_other_keyObject->keyStore, sss_other_keyObject, pubkey, &pubkeylen, &pbKeyBitLen);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
switch (otherPartyKeyObject->cipherType) {
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
/* TODO: Implement asn parser */
publicKeyLen = pubkeylen;
publicKeyIndex = 0;
break;
default: {
retval = sss_util_pkcs8_asn1_get_ec_public_key_index(
(const uint8_t *)pubkey, pubkeylen, &publicKeyIndex, &publicKeyLen);
if (retval != kStatus_SSS_Success) {
LOG_W("error in sss_util_pkcs8_asn1_get_ec_public_key_index");
goto exit;
}
}
}
// Change Endianness Public Key in case of Montgomery Curve
{
if (otherPartyKeyObject->cipherType == kSSS_CipherType_EC_MONTGOMERY) {
for (size_t keyValueIdx = 0; keyValueIdx < (publicKeyLen >> 1); keyValueIdx++) {
uint8_t swapByte = pubkey[publicKeyIndex + keyValueIdx];
pubkey[publicKeyIndex + keyValueIdx] = pubkey[publicKeyIndex + publicKeyLen - 1 - keyValueIdx];
pubkey[publicKeyIndex + publicKeyLen - 1 - keyValueIdx] = swapByte;
}
}
}
pPublicKey = &pubkey[publicKeyIndex];
#if SSS_HAVE_SE05X_VER_GTE_06_00
uint8_t invertEndiannes = 0x00;
if (otherPartyKeyObject->cipherType == kSSS_CipherType_EC_MONTGOMERY) {
// In case of Montgomery curves we want to store the
// shared secret using Little Endian Convention
invertEndiannes = 0x01;
}
if (context->keyObject->keyStore == derivedKeyObject->keyStore) {
status = Se05x_API_ECDHGenerateSharedSecret_InObject(&context->session->s_ctx,
context->keyObject->keyId,
pPublicKey,
publicKeyLen,
derivedKeyObject->keyId,
invertEndiannes);
if (status != SM_OK) {
LOG_W("error in Se05x_API_ECDHGenerateSharedSecret_InObject");
retval = kStatus_SSS_Fail;
goto exit;
}
}
else {
#endif
status = Se05x_API_ECGenSharedSecret(&context->session->s_ctx,
context->keyObject->keyId,
pPublicKey,
publicKeyLen,
sharedsecret,
&sharedsecretLen);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Change Endianness Shared Secret in case of Montgomery Curve
{
if (otherPartyKeyObject->cipherType == kSSS_CipherType_EC_MONTGOMERY) {
for (size_t keyValueIdx = 0; keyValueIdx < (publicKeyLen >> 1); keyValueIdx++) {
uint8_t swapByte = sharedsecret[keyValueIdx];
sharedsecret[keyValueIdx] = sharedsecret[publicKeyLen - 1 - keyValueIdx];
sharedsecret[publicKeyLen - 1 - keyValueIdx] = swapByte;
}
}
}
retval = sss_key_store_set_key((sss_key_store_t *)derivedKeyObject->keyStore,
sss_derived_keyObject,
sharedsecret,
sharedsecretLen,
sharedsecretLen * 8,
NULL,
0);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
#if SSS_HAVE_SE05X_VER_GTE_06_00
}
#endif
retval = kStatus_SSS_Success;
exit:
return retval;
}
void sss_se05x_derive_key_context_free(sss_se05x_derive_key_t *context)
{
;
}
/* End: se05x_keyderive */
/* ************************************************************************** */
/* Functions : sss_se05x_keystore */
/* ************************************************************************** */
sss_status_t sss_se05x_key_store_context_init(sss_se05x_key_store_t *keyStore, sss_se05x_session_t *session)
{
sss_status_t retval = kStatus_SSS_Success;
memset(keyStore, 0, sizeof(*keyStore));
keyStore->session = session;
return retval;
}
sss_status_t sss_se05x_key_store_allocate(sss_se05x_key_store_t *keyStore, uint32_t keyStoreId)
{
return kStatus_SSS_Success;
}
sss_status_t sss_se05x_key_store_save(sss_se05x_key_store_t *keyStore)
{
return kStatus_SSS_Success;
}
sss_status_t sss_se05x_key_store_load(sss_se05x_key_store_t *keyStore)
{
return kStatus_SSS_Success;
}
#if SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_rsa_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
//int ret;
uint32_t key_type = keyObject->objectType;
Se05xPolicy_t se05x_policy;
//SE05x_KeyPart_t key_part;
uint8_t *rsaN = NULL, *rsaE = NULL, *rsaD = NULL;
uint8_t *rsaP = NULL, *rsaQ = NULL, *rsaDP = NULL, *rsaDQ = NULL, *rsaQINV = NULL;
size_t rsaNlen, rsaElen, rsaDlen;
size_t rsaPlen, rsaQlen, rsaDPlen, rsaDQlen, rsaQINVlen;
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
SE05x_INS_t transient_type;
SE05x_RSAKeyFormat_t rsa_format;
uint8_t IdExists = 0;
size_t keyBitLength = 0;
SE05x_Result_t obj_exists = kSE05x_Result_NA;
/* Assign proper instruction type based on keyObject->isPersistant */
(keyObject->isPersistant) ? (transient_type = kSE05x_INS_NA) : (transient_type = kSE05x_INS_TRANSIENT);
if (keyObject->cipherType == kSSS_CipherType_RSA)
rsa_format = kSE05x_RSAKeyFormat_RAW;
else if (keyObject->cipherType == kSSS_CipherType_RSA_CRT)
rsa_format = kSE05x_RSAKeyFormat_CRT;
else {
retval = kStatus_SSS_Fail;
goto exit;
}
#if 0
if (key_type == kSSS_KeyPart_Public)
key_part = SE05x_KeyPart_Public;
else if (key_type == kSSS_KeyPart_Private)
key_part = kSE05x_KeyPart_Private;
else if (key_type == kSSS_KeyPart_Pair)
key_part = kSE05x_KeyPart_Pair;
else {
retval = kStatus_SSS_Fail;
goto exit;
}
/* Set the kye parameters */
status = Se05x_API_WriteRSAKey(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLen,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
key_part,
rsa_format);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
#endif
if (key_type == kSSS_KeyPart_Public) {
retval = sss_util_asn1_rsa_parse_public(key, keyLen, &rsaN, &rsaNlen, &rsaE, &rsaElen);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
/* Set the Public Exponent */
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLength,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
rsaE,
rsaElen,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_Public,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
/* Set the Modulus */
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
rsaN,
rsaNlen,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
}
else if (key_type == kSSS_KeyPart_Private) {
if (keyObject->cipherType == kSSS_CipherType_RSA) {
retval = sss_util_asn1_rsa_parse_private(key,
keyLen,
keyObject->cipherType,
&rsaN,
&rsaNlen,
NULL,
NULL,
&rsaD,
&rsaDlen,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (retval != kStatus_SSS_Success) {
retval = kStatus_SSS_Fail;
goto exit;
}
if ((rsaN == NULL) || (rsaD == NULL)) {
retval = kStatus_SSS_Fail;
goto exit;
}
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
// Set D(Private exponent) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLength,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
rsaD,
rsaDlen,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_Private,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set N(Modulus) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
rsaN,
rsaNlen,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
}
else if (keyObject->cipherType == kSSS_CipherType_RSA_CRT) {
retval = sss_util_asn1_rsa_parse_private(key,
keyLen,
keyObject->cipherType,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&rsaP,
&rsaPlen,
&rsaQ,
&rsaQlen,
&rsaDP,
&rsaDPlen,
&rsaDQ,
&rsaDQlen,
&rsaQINV,
&rsaQINVlen);
if (retval != kStatus_SSS_Success) {
retval = kStatus_SSS_Fail;
goto exit;
}
if ((rsaP == NULL) || (rsaQ == NULL) || (rsaDP == NULL) || (rsaDQ == NULL) || (rsaQINV == NULL)) {
retval = kStatus_SSS_Fail;
goto exit;
}
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
// Set P component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLength,
rsaP,
rsaPlen,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_Private,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set Q component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
rsaQ,
rsaQlen,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set DP component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
rsaDP,
rsaDPlen,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set DQ component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
rsaDQ,
rsaDQlen,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set INV_Q component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
rsaQINV,
rsaQINVlen,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
}
}
else if (key_type == kSSS_KeyPart_Pair) {
if (keyObject->cipherType == kSSS_CipherType_RSA) {
retval = sss_util_asn1_rsa_parse_private(key,
keyLen,
keyObject->cipherType,
&rsaN,
&rsaNlen,
&rsaE,
&rsaElen,
&rsaD,
&rsaDlen,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
ENSURE_OR_EXIT_WITH_STATUS_ON_ERROR(
!((rsaD == NULL) || (rsaE == NULL) || (rsaN == NULL)), retval, kStatus_SSS_Fail);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
// Set E(Public exponent) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLength,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
rsaE,
rsaElen,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_Pair,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set D(Private exponent) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
rsaD,
rsaDlen,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set N(Modulus) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
rsaN,
rsaNlen,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
}
else if (keyObject->cipherType == kSSS_CipherType_RSA_CRT) {
retval = sss_util_asn1_rsa_parse_private(key,
keyLen,
keyObject->cipherType,
&rsaN,
&rsaNlen,
&rsaE,
&rsaElen,
NULL,
NULL,
&rsaP,
&rsaPlen,
&rsaQ,
&rsaQlen,
&rsaDP,
&rsaDPlen,
&rsaDQ,
&rsaDQlen,
&rsaQINV,
&rsaQINVlen);
ENSURE_OR_GO_EXIT(retval == kStatus_SSS_Success);
if ((rsaP == NULL) || (rsaQ == NULL) || (rsaDP == NULL) || (rsaDQ == NULL) || (rsaQINV == NULL) ||
(rsaE == NULL) || (rsaN == NULL)) {
retval = kStatus_SSS_Fail;
goto exit;
}
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
// Set P component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(U16)keyBitLength,
rsaP,
rsaPlen,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_Pair,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set Q component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
rsaQ,
rsaQlen,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set DP component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
rsaDP,
rsaDPlen,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set DQ component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
rsaDQ,
rsaDQlen,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set INV_Q component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
rsaQINV,
rsaQINVlen,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set E (Public exponent) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
rsaE,
rsaElen,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
// Set N (Modulus) component
status = sss_se05x_LL_set_RSA_key(&keyStore->session->s_ctx,
NULL,
keyObject->keyId,
0,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
rsaN,
rsaNlen,
transient_type,
kSE05x_KeyPart_NA,
rsa_format,
obj_exists);
if (status != SM_OK) {
retval = kStatus_SSS_Fail;
goto exit;
}
}
}
exit:
if (rsaN != NULL)
SSS_FREE(rsaN);
if (rsaE != NULL)
SSS_FREE(rsaE);
if (rsaD != NULL)
SSS_FREE(rsaD);
if (rsaP != NULL)
SSS_FREE(rsaP);
if (rsaQ != NULL)
SSS_FREE(rsaQ);
if (rsaDP != NULL)
SSS_FREE(rsaDP);
if (rsaDQ != NULL)
SSS_FREE(rsaDQ);
if (rsaQINV != NULL)
SSS_FREE(rsaQINV);
return retval;
}
#endif // SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
static size_t getEccPrivPubKeyLen(uint32_t curve_id, size_t *pubKeyLen, size_t *privKeyLen)
{
sss_status_t retval = kStatus_SSS_Success;
if (privKeyLen == NULL || pubKeyLen == NULL) {
return kStatus_SSS_Fail;
}
switch (curve_id) {
case kSE05x_ECCurve_Secp160k1:
case kSE05x_ECCurve_Brainpool160: {
*privKeyLen = 20;
*pubKeyLen = 41;
} break;
case kSE05x_ECCurve_NIST_P192:
case kSE05x_ECCurve_Brainpool192:
case kSE05x_ECCurve_Secp192k1: {
*privKeyLen = 24;
*pubKeyLen = 49;
} break;
case kSE05x_ECCurve_NIST_P224:
case kSE05x_ECCurve_Brainpool224:
case kSE05x_ECCurve_Secp224k1: {
*privKeyLen = 28;
*pubKeyLen = 57;
} break;
case kSE05x_ECCurve_NIST_P256:
case kSE05x_ECCurve_Brainpool256:
case kSE05x_ECCurve_Secp256k1: {
*privKeyLen = 32;
*pubKeyLen = 65;
} break;
case kSE05x_ECCurve_Brainpool320: {
*privKeyLen = 40;
*pubKeyLen = 81;
} break;
case kSE05x_ECCurve_NIST_P384:
case kSE05x_ECCurve_Brainpool384: {
*privKeyLen = 48;
*pubKeyLen = 97;
} break;
case kSE05x_ECCurve_NIST_P521: {
*privKeyLen = 66;
*pubKeyLen = 133;
} break;
case kSE05x_ECCurve_Brainpool512: {
*privKeyLen = 64;
*pubKeyLen = 129;
} break;
case kSE05x_ECCurve_ECC_MONT_DH_25519:
case kSE05x_ECCurve_ECC_ED_25519: {
*privKeyLen = 32;
*pubKeyLen = 32;
} break;
#if SSS_HAVE_SE05X_VER_GTE_06_00
case kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_448: {
*privKeyLen = 56;
*pubKeyLen = 56;
} break;
#endif
default: {
*privKeyLen = 0;
*pubKeyLen = 0;
retval = kStatus_SSS_Fail;
} break;
}
return retval;
}
#endif //SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
/* sss_se05x_create_curve_if_needed for internal to this file and for tests */
smStatus_t sss_se05x_create_curve_if_needed(Se05xSession_t *pSession, uint32_t curve_id)
{
smStatus_t status = SM_NOT_OK;
//uint32_t existing_curve_id = 0;
uint8_t curveList[kSE05x_ECCurve_Total_Weierstrass_Curves] = {
0,
};
size_t curveListLen = sizeof(curveList);
//int i = 0;
if (curve_id == kSE05x_ECCurve_RESERVED_ID_ECC_ED_25519) {
/* ECC_ED_25519 is always preset */
return SM_OK;
}
if (curve_id == kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_25519
#if SSS_HAVE_SE05X_VER_GTE_06_00
|| curve_id == kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_448
#endif
) {
#if SSS_HAVE_SE05X_VER_GTE_06_00
status = Se05x_API_CreateECCurve(pSession, curve_id);
/* If curve is already created, Se05x_API_CreateECCurve fails. Ignore this error */
return SM_OK;
#else
return SM_OK;
/* ECC_MONT_DH_25519 and ECC_MONT_DH_448 are always present */
#endif
}
status = Se05x_API_ReadECCurveList(pSession, curveList, &curveListLen);
if (status == SM_OK) {
if (curveList[curve_id - 1] == kSE05x_SetIndicator_SET) {
return SM_OK;
}
}
else {
return SM_NOT_OK;
}
switch (curve_id) {
case kSE05x_ECCurve_NIST_P192:
status = Se05x_API_CreateCurve_prime192v1(pSession, curve_id);
break;
case kSE05x_ECCurve_NIST_P224:
status = Se05x_API_CreateCurve_secp224r1(pSession, curve_id);
break;
case kSE05x_ECCurve_NIST_P256:
status = Se05x_API_CreateCurve_prime256v1(pSession, curve_id);
break;
case kSE05x_ECCurve_NIST_P384:
status = Se05x_API_CreateCurve_secp384r1(pSession, curve_id);
break;
case kSE05x_ECCurve_NIST_P521:
status = Se05x_API_CreateCurve_secp521r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool160:
status = Se05x_API_CreateCurve_brainpoolP160r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool192:
status = Se05x_API_CreateCurve_brainpoolP192r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool224:
status = Se05x_API_CreateCurve_brainpoolP224r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool256:
status = Se05x_API_CreateCurve_brainpoolP256r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool320:
status = Se05x_API_CreateCurve_brainpoolP320r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool384:
status = Se05x_API_CreateCurve_brainpoolP384r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Brainpool512:
status = Se05x_API_CreateCurve_brainpoolP512r1(pSession, curve_id);
break;
case kSE05x_ECCurve_Secp160k1:
status = Se05x_API_CreateCurve_secp160k1(pSession, curve_id);
break;
case kSE05x_ECCurve_Secp192k1:
status = Se05x_API_CreateCurve_secp192k1(pSession, curve_id);
break;
case kSE05x_ECCurve_Secp224k1:
status = Se05x_API_CreateCurve_secp224k1(pSession, curve_id);
break;
case kSE05x_ECCurve_Secp256k1:
status = Se05x_API_CreateCurve_secp256k1(pSession, curve_id);
break;
case kSE05x_ECCurve_TPM_ECC_BN_P256:
status = Se05x_API_CreateCurve_tpm_bm_p256(pSession, curve_id);
break;
default:
break;
}
ENSURE_OR_GO_EXIT(status != SM_NOT_OK);
if (status == SM_ERR_CONDITIONS_OF_USE_NOT_SATISFIED) {
LOG_W("Allowing SM_ERR_CONDITIONS_OF_USE_NOT_SATISFIED for CreateCurve");
}
exit:
return status;
}
#endif // SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_KEY_SET || SSSFTR_SE05X_KEY_GET
static uint8_t CheckIfKeyIdExists(uint32_t keyId, pSe05xSession_t session_ctx)
{
smStatus_t retStatus = SM_NOT_OK;
SE05x_Result_t IdExists = 0;
retStatus = Se05x_API_CheckObjectExists(session_ctx, keyId, &IdExists);
if (retStatus == SM_OK) {
if (IdExists == kSE05x_Result_SUCCESS) {
LOG_D("Key Id 0x%X exists", keyId);
return 1;
}
else {
return 0;
}
}
else {
LOG_E("Error in Se05x_API_CheckObjectExists");
return 0;
}
}
#endif
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_ecc_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_status_t asn_retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
SE05x_INS_t transient_type;
SE05x_ECCurve_t curveId = keyObject->curve_id;
SE05x_KeyPart_t key_part = kSE05x_KeyPart_NA;
SE05x_Result_t exists = kSE05x_Result_NA;
SE05x_ECCurve_t retCurveId = keyObject->curve_id;
size_t std_pubKey_len = 0;
size_t std_privKey_len = 0;
uint8_t privKeyReversed[64] = {
0,
};
uint8_t pubKeyReversed[64] = {
0,
};
/* Assign proper instruction type based on keyObject->isPersistant */
(keyObject->isPersistant) ? (transient_type = kSE05x_INS_NA) : (transient_type = kSE05x_INS_TRANSIENT);
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
if (keyObject->curve_id == 0) {
keyObject->curve_id = se05x_sssKeyTypeLenToCurveId(keyObject->cipherType, keyBitLen);
}
if (keyObject->curve_id == 0) {
goto exit;
}
status = sss_se05x_create_curve_if_needed(&keyObject->keyStore->session->s_ctx, keyObject->curve_id);
if (status == SM_NOT_OK) {
goto exit;
}
else if (status == SM_ERR_CONDITIONS_OF_USE_NOT_SATISFIED) {
LOG_W("Allowing SM_ERR_CONDITIONS_OF_USE_NOT_SATISFIED for CreateCurve");
}
status = Se05x_API_CheckObjectExists(&keyStore->session->s_ctx, keyObject->keyId, &exists);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (exists == kSE05x_Result_SUCCESS) {
/* Check if object is of same curve id */
status = Se05x_API_EC_CurveGetId(&keyObject->keyStore->session->s_ctx, keyObject->keyId, &retCurveId);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (retCurveId == keyObject->curve_id) {
curveId = kSE05x_ECCurve_NA;
}
else {
LOG_W("Cannot overwrite object with different curve id");
goto exit;
}
//if (se05x_policy.value_len != 0) {
// LOG_W("Policy + Existing Key is not a valid combination");
//}
}
else {
curveId = keyObject->curve_id;
}
if (keyObject->objectType == kSSS_KeyPart_Pair) {
const uint8_t *pPrivateKey = NULL;
const uint8_t *pPublicKey = NULL;
size_t privateKeyLen = 0;
size_t publicKeyLen = 0;
uint16_t privateKeyIndex = 0;
uint16_t publicKeyIndex = 0;
if (exists == kSE05x_Result_FAILURE)
key_part = kSE05x_KeyPart_Pair;
switch (keyObject->curve_id) {
case kSE05x_ECCurve_TPM_ECC_BN_P256: {
LOG_I("Key pair should be paased without header");
/* No header included in ED and BN curve keys */
privateKeyIndex = 0;
publicKeyIndex = 32;
privateKeyLen = 32;
publicKeyLen = 32;
} break;
default: {
if ((keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_ED_25519)) {
asn_retval = sss_util_rfc8410_asn1_get_ec_pair_key_index(
key, keyLen, &publicKeyIndex, &publicKeyLen, &privateKeyIndex, &privateKeyLen);
if (asn_retval != kStatus_SSS_Success) {
LOG_W("error in sss_util_rfc8410_asn1_get_ec_pair_key_index");
goto exit;
}
}
else {
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");
goto exit;
}
}
asn_retval = getEccPrivPubKeyLen(keyObject->curve_id, &std_pubKey_len, &std_privKey_len);
if (asn_retval != kStatus_SSS_Success) {
LOG_W("error in getEccPrivPubKeyLen");
goto exit;
}
if (privateKeyLen != std_privKey_len) {
if (key[privateKeyIndex] == 0) {
privateKeyIndex++;
privateKeyLen--;
}
}
if (privateKeyLen != std_privKey_len) {
LOG_W("error in private key length");
goto exit;
}
if (publicKeyLen != std_pubKey_len) {
if (key[publicKeyIndex] == 0) {
publicKeyIndex++;
publicKeyLen--;
}
}
if (publicKeyLen != std_pubKey_len) {
LOG_W("error in public key length");
goto exit;
}
}
}
// Conditionally Reverse Endianness
if ((keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_ED_25519)) {
size_t i = 0;
size_t nByteKey = 32; // Corresponds to kSE05x_ECCurve_ECC_MONT_DH_25519
if (keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) {
nByteKey = 56;
}
if (keyObject->curve_id != kSE05x_ECCurve_ECC_ED_25519) {
while (i < nByteKey) {
privKeyReversed[i] = key[privateKeyIndex + privateKeyLen - i - 1];
i++;
}
pPrivateKey = &privKeyReversed[0];
}
else {
// SE05x expects private key to be in litte endian format
pPrivateKey = &key[privateKeyIndex];
}
i = 0;
while (i < nByteKey) {
pubKeyReversed[i] = key[publicKeyIndex + publicKeyLen - i - 1];
i++;
}
pPublicKey = &pubKeyReversed[0];
}
else {
pPrivateKey = &key[privateKeyIndex];
pPublicKey = &key[publicKeyIndex];
}
#ifdef TMP_ENDIAN_VERBOSE
{
printf("Private Key After Reverse:\n");
for (size_t z = 0; z < privateKeyLen; z++) {
printf("%02X.", pPrivateKey[z]);
}
printf("\n");
}
#endif
status = sss_se05x_LL_set_ec_key(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_UNLIMITED,
keyObject->keyId,
curveId,
pPrivateKey,
privateKeyLen,
pPublicKey,
publicKeyLen,
transient_type,
key_part,
exists);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
else if (keyObject->objectType == kSSS_KeyPart_Public) {
const uint8_t *pPublicKey = NULL;
size_t publicKeyLen = 0;
uint16_t publicKeyIndex = 0;
if (exists == kSE05x_Result_FAILURE)
key_part = kSE05x_KeyPart_Public;
switch (keyObject->curve_id) {
case kSE05x_ECCurve_TPM_ECC_BN_P256: {
LOG_I("Public key should be paased without header");
publicKeyLen = keyLen;
} break;
default: {
asn_retval = sss_util_pkcs8_asn1_get_ec_public_key_index(key, keyLen, &publicKeyIndex, &publicKeyLen);
if (asn_retval != kStatus_SSS_Success) {
LOG_W("error in sss_util_pkcs8_asn1_get_ec_public_key_index");
goto exit;
}
asn_retval = getEccPrivPubKeyLen(keyObject->curve_id, &std_pubKey_len, &std_privKey_len);
if (asn_retval != kStatus_SSS_Success) {
LOG_W("error in getEccPrivPubKeyLen");
goto exit;
}
if (publicKeyLen != std_pubKey_len) {
if (key[publicKeyIndex] == 0) {
publicKeyIndex++;
publicKeyLen--;
}
}
if (publicKeyLen != std_pubKey_len) {
LOG_W("error in public key length");
goto exit;
}
}
}
#ifdef TMP_ENDIAN_VERBOSE
{
printf("Pub Key Before Reverse:\n");
for (size_t z = 0; z < publicKeyLen; z++) {
printf("%02X.", key[publicKeyIndex + z]);
}
printf("\n");
}
#endif
// Conditionally Reverse Endianness
if ((keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_ED_25519)) {
size_t i = 0;
size_t nByteKey = 32; // Corresponds to kSE05x_ECCurve_ECC_MONT_DH_25519
if (keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) {
nByteKey = 56;
}
while (i < nByteKey) {
pubKeyReversed[i] = key[publicKeyIndex + publicKeyLen - i - 1];
i++;
}
pPublicKey = &pubKeyReversed[0];
}
else {
pPublicKey = &key[publicKeyIndex];
}
#ifdef TMP_ENDIAN_VERBOSE
{
printf("Pub Key After Reverse:\n");
for (size_t z = 0; z < publicKeyLen; z++) {
printf("%02X.", pPublicKey[z]);
}
printf("\n");
}
#endif
status = sss_se05x_LL_set_ec_key(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_NA,
keyObject->keyId,
curveId,
NULL,
0,
pPublicKey,
publicKeyLen,
transient_type,
key_part,
exists);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
else if (keyObject->objectType == kSSS_KeyPart_Private) {
const uint8_t *pPrivKey = NULL;
size_t privKeyLen = (uint16_t)keyLen;
uint16_t privateKeyIndex = 0;
if (exists == kSE05x_Result_FAILURE)
key_part = kSE05x_KeyPart_Private;
LOG_I("Private key should be passed without header");
switch (keyObject->curve_id) {
case kSE05x_ECCurve_TPM_ECC_BN_P256: {
privateKeyIndex = 0;
} break;
#if SSS_HAVE_SE05X_VER_GTE_06_00
case kSE05x_ECCurve_RESERVED_ID_ECC_MONT_DH_448: {
LOG_W(
"Private Key injection is not supported for "
"ECC_MONT_DH_448 curve");
goto exit;
}
#endif
default: {
asn_retval = getEccPrivPubKeyLen(keyObject->curve_id, &std_pubKey_len, &std_privKey_len);
if (asn_retval != kStatus_SSS_Success) {
LOG_W("error in getEccPrivPubKeyLen");
goto exit;
}
if (keyLen != std_privKey_len) {
if (key[0] == 0) {
privKeyLen = keyLen - 1;
privateKeyIndex = 1;
}
}
if (privKeyLen != std_privKey_len) {
LOG_W("error in private key length");
goto exit;
}
} break;
}
pPrivKey = &key[privateKeyIndex];
status = sss_se05x_LL_set_ec_key(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_NA,
keyObject->keyId,
curveId,
pPrivKey,
privKeyLen,
NULL,
0,
transient_type,
key_part,
exists);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
else {
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif // SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_aes_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
SE05x_INS_t transient_type;
SE05x_SymmKeyType_t type = 0;
SE05x_KeyID_t kekID = SE05x_KeyID_KEK_NONE;
uint8_t IdExists = 0;
SE05x_Result_t objExists = kSE05x_Result_NA;
/* Assign proper instruction type based on keyObject->isPersistant */
(keyObject->isPersistant) ? (transient_type = kSE05x_INS_NA) : (transient_type = kSE05x_INS_TRANSIENT);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
objExists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
if (keyBitLen % 8 == 0) {
if (keyObject->cipherType == kSSS_CipherType_AES) {
type = kSE05x_SymmKeyType_AES;
}
else if (keyObject->cipherType == kSSS_CipherType_CMAC) {
type = kSE05x_SymmKeyType_CMAC;
}
else if (keyObject->cipherType == kSSS_CipherType_HMAC) {
type = kSE05x_SymmKeyType_HMAC;
}
if (keyStore->kekKey != NULL) {
kekID = keyStore->kekKey->keyId;
}
status = sss_se05x_LL_set_symm_key(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_NA,
keyObject->keyId,
kekID,
key,
keyLen,
transient_type,
type,
objExists);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
else {
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif // SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_des_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
SE05x_INS_t transient_type;
SE05x_KeyID_t kekID = SE05x_KeyID_KEK_NONE;
uint8_t IdExists = 0;
SE05x_Result_t objExists = kSE05x_Result_NA;
/* Assign proper instruction type based on keyObject->isPersistant */
(keyObject->isPersistant) ? (transient_type = kSE05x_INS_NA) : (transient_type = kSE05x_INS_TRANSIENT);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
objExists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
if (keyStore->kekKey != NULL) {
kekID = keyStore->kekKey->keyId;
}
status = sss_se05x_LL_set_symm_key(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_NA,
keyObject->keyId,
kekID,
key,
keyLen,
transient_type,
kSE05x_SymmKeyType_DES,
objExists);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif // SSSFTR_SE05X_KEY_SET
#if 0
static sss_status_t sss_se05x_key_store_set_deswrapped_key(
sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
if (keyObject->isPersistant) {
status = Se05x_API_DES_SetNewWrapped_P(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
keyObject->kekId,
(U16)keyBitLen,
key,
keyLen);
}
else {
status = Se05x_API_DES_SetNewWrapped_T(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
keyObject->kekId,
(U16)keyBitLen,
key,
keyLen);
}
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif
#if SSSFTR_SE05X_KEY_SET
static sss_status_t sss_se05x_key_store_set_cert(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
uint16_t data_rem;
uint16_t offset = 0;
uint16_t fileSize = 0;
uint8_t IdExists = 0;
#if SSS_HAVE_SE05X_VER_GTE_06_00
SE05x_Result_t obj_exists = kSE05x_Result_NA;
#endif
ENSURE_OR_GO_EXIT(keyLen < 0xFFFFu);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
fileSize = (IdExists == 1) ? 0 : (uint16_t)keyLen;
data_rem = (uint16_t)keyLen;
#if SSS_HAVE_SE05X_VER_GTE_06_00
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
#endif
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
while (data_rem > 0) {
uint16_t chunk = (data_rem > BINARY_WRITE_MAX_LEN) ? BINARY_WRITE_MAX_LEN : data_rem;
data_rem = data_rem - chunk;
#if SSS_HAVE_SE05X_VER_GTE_06_00
/* Call APIs For SE051 */
obj_exists = (IdExists == 1) ? kSE05x_Result_SUCCESS : kSE05x_Result_FAILURE;
if (obj_exists == kSE05x_Result_FAILURE) {
status = Se05x_API_WriteBinary_Ver(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
offset,
(uint16_t)fileSize,
(key + offset),
chunk,
0);
}
else if (obj_exists == kSE05x_Result_SUCCESS) {
status = Se05x_API_UpdateBinary_Ver(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
offset,
(uint16_t)fileSize,
(key + offset),
chunk,
0);
}
else {
LOG_E("Invalid Object exist status!!!");
}
#else
/* Call APIs For SE050 */
status = Se05x_API_WriteBinary(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
offset,
(uint16_t)fileSize,
(key + offset),
chunk);
#endif
ENSURE_OR_GO_EXIT(status == SM_OK);
fileSize = 0;
offset = offset + chunk;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif // SSSFTR_SE05X_KEY_SET
#if 0
static sss_status_t sss_se05x_key_store_set_pcr(
sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
void *policy_buff,
size_t policy_buff_len)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05xPolicy_t se05x_policy;
se05x_policy.value = (uint8_t *)policy_buff;
se05x_policy.value_len = policy_buff_len;
if (keyObject->cipherType == kSSS_CipherType_PCR) {
status = Se05x_API_WritePCR(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
key,
keyLen,
NULL,
0);
}
else if (keyObject->cipherType == kSSS_CipherType_Update_PCR) {
status = Se05x_API_WritePCR(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
NULL,
0,
key,
keyLen
);
}
else if (keyObject->cipherType == kSSS_CipherType_Reset_PCR) {
status = Se05x_API_WritePCR(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
NULL,
0,
NULL,
0);
}
else
{
goto exit;
}
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif
sss_status_t sss_se05x_key_store_set_key(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
const uint8_t *key,
size_t keyLen,
size_t keyBitLen,
void *options,
size_t optionsLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_KEY_SET
sss_cipher_type_t cipher_type = (sss_cipher_type_t)keyObject->cipherType;
sss_policy_t *policies = (sss_policy_t *)options;
uint8_t *ppolicySet;
size_t valid_policy_buff_len = 0;
uint8_t policies_buff[MAX_POLICY_BUFFER_SIZE];
if (policies) {
if (kStatus_SSS_Success !=
sss_se05x_create_object_policy_buffer(policies, &policies_buff[0], &valid_policy_buff_len)) {
goto exit;
}
ppolicySet = policies_buff;
}
else {
ppolicySet = NULL;
}
switch (cipher_type) {
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT:
if (kStatus_SSS_Success !=
sss_se05x_key_store_set_rsa_key(
keyStore, keyObject, key, keyLen, keyBitLen, ppolicySet, valid_policy_buff_len)) {
goto exit;
}
break;
#endif
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_TWISTED_ED:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
if (kStatus_SSS_Success !=
sss_se05x_key_store_set_ecc_key(
keyStore, keyObject, key, keyLen, keyBitLen, ppolicySet, valid_policy_buff_len)) {
goto exit;
}
break;
#endif // SSSFTR_SE05X_ECC
case kSSS_CipherType_AES:
if ((keyLen != 16 && keyLen != 24 && keyLen != 32 && keyLen != 40)) {
goto exit;
}
/* fall through */
case kSSS_CipherType_CMAC:
case kSSS_CipherType_HMAC:
#if SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
if (kStatus_SSS_Success !=
sss_se05x_key_store_set_aes_key(
keyStore, keyObject, key, keyLen, keyBitLen, ppolicySet, valid_policy_buff_len)) {
goto exit;
}
#else
goto exit;
#endif
break;
case kSSS_CipherType_DES:
if (kStatus_SSS_Success !=
sss_se05x_key_store_set_des_key(
keyStore, keyObject, key, keyLen, keyBitLen, ppolicySet, valid_policy_buff_len)) {
goto exit;
}
break;
case kSSS_CipherType_Binary:
if (kStatus_SSS_Success !=
sss_se05x_key_store_set_cert(
keyStore, keyObject, key, keyLen, keyBitLen, ppolicySet, valid_policy_buff_len)) {
goto exit;
}
break;
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
#endif /* SSSFTR_SE05X_KEY_SET */
return retval;
}
sss_status_t sss_se05x_key_store_generate_key(
sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject, size_t keyBitLen, void *options)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_KEY_SET
smStatus_t status = SM_NOT_OK;
sss_policy_t *policies = (sss_policy_t *)options;
uint8_t *ppolicySet;
size_t valid_policy_buff_len = 0;
Se05xPolicy_t se05x_policy;
SE05x_INS_t transient_type;
uint8_t IdExists = 0;
uint8_t policies_buff[MAX_POLICY_BUFFER_SIZE];
if (policies) {
if (kStatus_SSS_Success !=
sss_se05x_create_object_policy_buffer(policies, &policies_buff[0], &valid_policy_buff_len)) {
goto exit;
}
ppolicySet = policies_buff;
}
else {
ppolicySet = NULL;
}
se05x_policy.value = (uint8_t *)ppolicySet;
se05x_policy.value_len = valid_policy_buff_len;
/* Assign proper instruction type based on keyObject->isPersistant */
(keyObject->isPersistant) ? (transient_type = kSE05x_INS_NA) : (transient_type = kSE05x_INS_TRANSIENT);
ENSURE_OR_GO_EXIT(keyObject->objectType == kSSS_KeyPart_Pair);
switch (keyObject->cipherType) {
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
case kSSS_CipherType_EC_TWISTED_ED: {
SE05x_ECCurve_t curve_id;
if (keyObject->curve_id == 0) {
keyObject->curve_id = se05x_sssKeyTypeLenToCurveId(keyObject->cipherType, keyBitLen);
}
if (keyObject->curve_id == 0) {
goto exit;
}
status = sss_se05x_create_curve_if_needed(&keyObject->keyStore->session->s_ctx, keyObject->curve_id);
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
curve_id = (IdExists == 1) ? 0 : keyObject->curve_id;
status = Se05x_API_WriteECKey(&keyStore->session->s_ctx,
&se05x_policy,
SE05x_MaxAttemps_NA,
keyObject->keyId,
curve_id,
NULL,
0,
NULL,
0,
transient_type,
kSE05x_KeyPart_Pair);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
}
#endif // < SSSFTR_SE05X_ECC
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
/* Hard Coded Public exponent to be 65537 */
//uint8_t pubexp[] = {0x01, 0x00, 0x01};
SE05x_KeyPart_t key_part = kSE05x_KeyPart_Pair;
SE05x_RSAKeyFormat_t rsa_format;
size_t keyBitLength = 0;
if (keyObject->cipherType == kSSS_CipherType_RSA)
rsa_format = kSE05x_RSAKeyFormat_RAW;
else if (keyObject->cipherType == kSSS_CipherType_RSA_CRT)
rsa_format = kSE05x_RSAKeyFormat_CRT;
else {
retval = kStatus_SSS_Fail;
goto exit;
}
IdExists = CheckIfKeyIdExists(keyObject->keyId, &keyStore->session->s_ctx);
keyBitLength = (IdExists == 1) ? 0 : keyBitLen;
status = Se05x_API_WriteRSAKey(&keyStore->session->s_ctx,
&se05x_policy,
keyObject->keyId,
(uint16_t)keyBitLength,
SE05X_RSA_NO_p,
SE05X_RSA_NO_q,
SE05X_RSA_NO_dp,
SE05X_RSA_NO_dq,
SE05X_RSA_NO_qInv,
SE05X_RSA_NO_pubExp,
SE05X_RSA_NO_priv,
SE05X_RSA_NO_pubMod,
transient_type,
key_part,
rsa_format);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
}
#endif // SSSFTR_SE05X_RSA
default: {
goto exit;
}
}
retval = kStatus_SSS_Success;
exit:
#endif // SSSFTR_SE05X_KEY_SET
return retval;
}
#define ADD_DER_ECC_NISTP192_HEADER(x) ((x) + der_ecc_nistp192_header_len)
#define REMOVE_DER_ECC_NISTP192_HEADER(x) ((x)-der_ecc_nistp192_header_len)
#define ADD_DER_ECC_NISTP224_HEADER(x) ((x) + der_ecc_nistp224_header_len)
#define REMOVE_DER_ECC_NISTP224_HEADER(x) ((x)-der_ecc_nistp224_header_len)
#define ADD_DER_ECC_NISTP256_HEADER(x) ((x) + der_ecc_nistp256_header_len)
#define REMOVE_DER_ECC_NISTP256_HEADER(x) ((x)-der_ecc_nistp256_header_len)
#define ADD_DER_ECC_NISTP384_HEADER(x) ((x) + der_ecc_nistp384_header_len)
#define REMOVE_DER_ECC_NISTP384_HEADER(x) ((x)-der_ecc_nistp384_header_len)
#define ADD_DER_ECC_NISTP521_HEADER(x) ((x) + der_ecc_nistp521_header_len)
#define REMOVE_DER_ECC_NISTP521_HEADER(x) ((x)-der_ecc_nistp521_header_len)
#define ADD_DER_ECC_160K_HEADER(x) ((x) + der_ecc_160k_header_len)
#define REMOVE_DER_ECC_160K_HEADER(x) ((x)-der_ecc_160k_header_len)
#define ADD_DER_ECC_192K_HEADER(x) ((x) + der_ecc_192k_header_len)
#define REMOVE_DER_ECC_192K_HEADER(x) ((x)-der_ecc_192k_header_len)
#define ADD_DER_ECC_224K_HEADER(x) ((x) + der_ecc_224k_header_len)
#define REMOVE_DER_ECC_224K_HEADER(x) ((x)-der_ecc_224k_header_len)
#define ADD_DER_ECC_256K_HEADER(x) ((x) + der_ecc_256k_header_len)
#define REMOVE_DER_ECC_256K_HEADER(x) ((x)-der_ecc_256k_header_len)
#define ADD_DER_ECC_BP160_HEADER(x) ((x) + der_ecc_bp160_header_len)
#define REMOVE_DER_ECC_BP160_HEADER(x) ((x)-der_ecc_bp160_header_len)
#define ADD_DER_ECC_BP192_HEADER(x) ((x) + der_ecc_bp192_header_len)
#define REMOVE_DER_ECC_BP192_HEADER(x) ((x)-der_ecc_bp192_header_len)
#define ADD_DER_ECC_BP224_HEADER(x) ((x) + der_ecc_bp224_header_len)
#define REMOVE_DER_ECC_BP224_HEADER(x) ((x)-der_ecc_bp224_header_len)
#define ADD_DER_ECC_BP320_HEADER(x) ((x) + der_ecc_bp320_header_len)
#define REMOVE_DER_ECC_BP320_HEADER(x) ((x)-der_ecc_bp320_header_len)
#define ADD_DER_ECC_BP384_HEADER(x) ((x) + der_ecc_bp384_header_len)
#define REMOVE_DER_ECC_BP384_HEADER(x) ((x)-der_ecc_bp384_header_len)
#define ADD_DER_ECC_BP256_HEADER(x) ((x) + der_ecc_bp256_header_len)
#define REMOVE_DER_ECC_BP256_HEADER(x) ((x)-der_ecc_bp256_header_len)
#define ADD_DER_ECC_BP512_HEADER(x) ((x) + der_ecc_bp512_header_len)
#define REMOVE_DER_ECC_BP512_HEADER(x) ((x)-der_ecc_bp512_header_len)
#define ADD_DER_ECC_MONT_DH_448_HEADER(x) ((x) + der_ecc_mont_dh_448_header_len)
#define REMOVE_DER_ECC_MONT_DH_448_HEADER(x) ((x)-der_ecc_mont_dh_448_header_len)
#define ADD_DER_ECC_MONT_DH_25519_HEADER(x) ((x) + der_ecc_mont_dh_25519_header_len)
#define REMOVE_DER_ECC_MONT_DH_25519_HEADER(x) ((x)-der_ecc_mont_dh_25519_header_len)
#define ADD_DER_ECC_TWISTED_ED_25519_HEADER(x) ((x) + der_ecc_twisted_ed_25519_header_len)
#define REMOVE_DER_ECC_TWISTED_ED_25519_HEADER(x) ((x)-der_ecc_twisted_ed_25519_header_len)
#define CONVERT_BYTE(x) ((x) / 8)
#define CONVERT_BIT(x) ((x)*8)
void add_ecc_header(uint8_t *key, uint8_t **key_buf, size_t *key_buflen, uint32_t curve_id)
{
#if SSSFTR_SE05X_KEY_SET
if (curve_id == kSE05x_ECCurve_NIST_P192) {
memcpy(key, gecc_der_header_nist192, der_ecc_nistp192_header_len);
*key_buf = ADD_DER_ECC_NISTP192_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_NISTP192_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P224) {
memcpy(key, gecc_der_header_nist224, der_ecc_nistp224_header_len);
*key_buf = ADD_DER_ECC_NISTP224_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_NISTP224_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P256) {
memcpy(key, gecc_der_header_nist256, der_ecc_nistp256_header_len);
*key_buf = ADD_DER_ECC_NISTP256_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_NISTP256_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P384) {
memcpy(key, gecc_der_header_nist384, der_ecc_nistp384_header_len);
*key_buf = ADD_DER_ECC_NISTP384_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_NISTP384_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P521) {
memcpy(key, gecc_der_header_nist521, der_ecc_nistp521_header_len);
*key_buf = ADD_DER_ECC_NISTP521_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_NISTP521_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool160) {
memcpy(key, gecc_der_header_bp160, der_ecc_bp160_header_len);
*key_buf = ADD_DER_ECC_BP160_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP160_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool192) {
memcpy(key, gecc_der_header_bp192, der_ecc_bp192_header_len);
*key_buf = ADD_DER_ECC_BP192_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP192_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool224) {
memcpy(key, gecc_der_header_bp224, der_ecc_bp224_header_len);
*key_buf = ADD_DER_ECC_BP224_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP224_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool320) {
memcpy(key, gecc_der_header_bp320, der_ecc_bp320_header_len);
*key_buf = ADD_DER_ECC_BP320_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP320_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool384) {
memcpy(key, gecc_der_header_bp384, der_ecc_bp384_header_len);
*key_buf = ADD_DER_ECC_BP384_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP384_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool256) {
memcpy(key, gecc_der_header_bp256, der_ecc_bp256_header_len);
*key_buf = ADD_DER_ECC_BP256_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP256_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool512) {
memcpy(key, gecc_der_header_bp512, der_ecc_bp512_header_len);
*key_buf = ADD_DER_ECC_BP512_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_BP512_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp256k1) {
memcpy(key, gecc_der_header_256k, der_ecc_256k_header_len);
*key_buf = ADD_DER_ECC_256K_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_256K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp160k1) {
memcpy(key, gecc_der_header_160k, der_ecc_160k_header_len);
*key_buf = ADD_DER_ECC_160K_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_160K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp192k1) {
memcpy(key, gecc_der_header_192k, der_ecc_192k_header_len);
*key_buf = ADD_DER_ECC_192K_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_192K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp224k1) {
memcpy(key, gecc_der_header_224k, der_ecc_224k_header_len);
*key_buf = ADD_DER_ECC_224K_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_224K_HEADER(*key_buflen);
}
#if SSS_HAVE_SE05X_VER_GTE_06_00
else if (curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) {
memcpy(key, gecc_der_header_mont_dh_448, der_ecc_mont_dh_448_header_len);
*key_buf = ADD_DER_ECC_MONT_DH_448_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_MONT_DH_448_HEADER(*key_buflen);
}
#endif
else if (curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) {
memcpy(key, gecc_der_header_mont_dh_25519, der_ecc_mont_dh_25519_header_len);
*key_buf = ADD_DER_ECC_MONT_DH_25519_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_MONT_DH_25519_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_ECC_ED_25519) {
memcpy(key, gecc_der_header_twisted_ed_25519, der_ecc_twisted_ed_25519_header_len);
*key_buf = ADD_DER_ECC_TWISTED_ED_25519_HEADER(key);
*key_buflen = (uint16_t)ADD_DER_ECC_TWISTED_ED_25519_HEADER(*key_buflen);
}
else {
LOG_W("Returned is not in DER Format");
*key_buf = key;
*key_buflen = 0;
}
#endif
}
void get_ecc_raw_data(uint8_t *key, uint8_t **key_buf, size_t *key_buflen, uint32_t curve_id)
{
if (curve_id == kSE05x_ECCurve_NIST_P192) {
*key_buf = ADD_DER_ECC_NISTP192_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_NISTP192_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P224) {
*key_buf = ADD_DER_ECC_NISTP224_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_NISTP224_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P256) {
*key_buf = ADD_DER_ECC_NISTP256_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_NISTP256_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P384) {
*key_buf = ADD_DER_ECC_NISTP384_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_NISTP384_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_NIST_P521) {
*key_buf = ADD_DER_ECC_NISTP521_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_NISTP521_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool160) {
*key_buf = ADD_DER_ECC_BP160_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP160_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool192) {
*key_buf = ADD_DER_ECC_BP192_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP192_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool224) {
*key_buf = REMOVE_DER_ECC_BP224_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP224_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool320) {
*key_buf = ADD_DER_ECC_BP320_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP320_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool384) {
*key_buf = ADD_DER_ECC_BP384_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP384_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool256) {
*key_buf = ADD_DER_ECC_BP256_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP256_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Brainpool512) {
*key_buf = ADD_DER_ECC_BP512_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_BP512_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp256k1) {
*key_buf = ADD_DER_ECC_256K_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_256K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp160k1) {
*key_buf = ADD_DER_ECC_160K_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_160K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp192k1) {
*key_buf = ADD_DER_ECC_192K_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_192K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_Secp224k1) {
*key_buf = ADD_DER_ECC_224K_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_224K_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_ECC_ED_25519) {
*key_buf = ADD_DER_ECC_TWISTED_ED_25519_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_TWISTED_ED_25519_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) {
*key_buf = ADD_DER_ECC_MONT_DH_25519_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_MONT_DH_25519_HEADER(*key_buflen);
}
else if (curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) {
*key_buf = ADD_DER_ECC_MONT_DH_448_HEADER(key);
*key_buflen = (uint16_t)REMOVE_DER_ECC_MONT_DH_448_HEADER(*key_buflen);
}
else {
LOG_W("Returned is not in DER Format");
*key_buf = key;
*key_buflen = 0;
}
}
sss_status_t sss_se05x_key_store_get_key(
sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject, uint8_t *key, size_t *keylen, size_t *pKeyBitLen)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_cipher_type_t cipher_type = keyObject->cipherType;
smStatus_t status = SM_NOT_OK;
uint16_t size;
switch (cipher_type) {
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_TWISTED_ED: {
uint8_t *key_buf = NULL;
size_t key_buflen = 0;
/* Return the Key length including the ECC DER Header */
add_ecc_header(key, &key_buf, &key_buflen, keyObject->curve_id);
status = Se05x_API_ReadObject(&keyStore->session->s_ctx, keyObject->keyId, 0, 0, key_buf, keylen);
ENSURE_OR_GO_EXIT(status == SM_OK);
/* Change Endiannes. */
if ((keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_ED_25519)) {
for (size_t keyValueIdx = 0; keyValueIdx < (*keylen >> 1); keyValueIdx++) {
uint8_t swapByte = key_buf[keyValueIdx];
key_buf[keyValueIdx] = key_buf[*keylen - 1 - keyValueIdx];
key_buf[*keylen - 1 - keyValueIdx] = swapByte;
}
}
/* Return the Key length with header length */
*keylen += key_buflen;
break;
}
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
uint8_t modulus[1024];
uint8_t exponent[4];
size_t modLen = sizeof(modulus);
size_t expLen = sizeof(exponent);
status = Se05x_API_ReadRSA(
&keyStore->session->s_ctx, keyObject->keyId, 0, 0, kSE05x_RSAPubKeyComp_MOD, modulus, &modLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
status = Se05x_API_ReadRSA(
&keyStore->session->s_ctx, keyObject->keyId, 0, 0, kSE05x_RSAPubKeyComp_PUB_EXP, exponent, &expLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (sss_util_asn1_rsa_get_public(key, keylen, modulus, modLen, exponent, expLen) != kStatus_SSS_Success) {
goto exit;
}
} break;
#endif // SSSFTR_SE05X_RSA
case kSSS_CipherType_AES:
status = Se05x_API_ReadObject(&keyStore->session->s_ctx, keyObject->keyId, 0, 0, key, keylen);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_Binary: {
uint16_t rem_data = 0;
uint16_t offset = 0;
size_t max_buffer = 0;
status = Se05x_API_ReadSize(&keyStore->session->s_ctx, keyObject->keyId, &size);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (*keylen < size) {
LOG_E("Insufficient buffer ");
goto exit;
}
rem_data = size;
*keylen = size;
while (rem_data > 0) {
uint16_t chunk = (rem_data > BINARY_WRITE_MAX_LEN) ? BINARY_WRITE_MAX_LEN : rem_data;
rem_data = rem_data - chunk;
max_buffer = chunk;
status = Se05x_API_ReadObject(
&keyStore->session->s_ctx, keyObject->keyId, offset, chunk, (key + offset), &max_buffer);
ENSURE_OR_GO_EXIT(status == SM_OK);
offset = offset + chunk;
}
} break;
case kSSS_CipherType_DES:
status = Se05x_API_ReadObject(&keyStore->session->s_ctx, keyObject->keyId, 0, 0, key, keylen);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_PCR:
status = Se05x_API_ReadObject(&keyStore->session->s_ctx, keyObject->keyId, 0, 0, key, keylen);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_Count:
status = Se05x_API_ReadObject(&keyStore->session->s_ctx, keyObject->keyId, 0, 0, key, keylen);
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_key_store_get_key_attst(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
uint8_t *key,
size_t *keylen,
size_t *pKeyBitLen,
sss_se05x_object_t *keyObject_attst,
sss_algorithm_t algorithm_attst,
uint8_t *random_attst,
size_t randomLen_attst,
sss_se05x_attst_data_t *attst_data)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_cipher_type_t cipher_type = keyObject->cipherType;
smStatus_t status = SM_NOT_OK;
uint16_t size;
uint32_t attestID;
SE05x_AttestationAlgo_t attestAlgo;
attestID = keyObject_attst->keyId;
switch (keyObject_attst->cipherType) {
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL: {
SE05x_ECSignatureAlgo_t ecSignAlgo = se05x_get_ec_sign_hash_mode(algorithm_attst);
attestAlgo = (SE05x_AttestationAlgo_t)ecSignAlgo;
} break;
case kSSS_CipherType_EC_TWISTED_ED:
case kSSS_CipherType_EC_BARRETO_NAEHRIG: {
LOG_E("Attestation not supported");
return retval;
} break;
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
SE05x_RSASignatureAlgo_t rsaSigningAlgo = se05x_get_rsa_sign_hash_mode(algorithm_attst);
attestAlgo = (SE05x_AttestationAlgo_t)rsaSigningAlgo;
} break;
#endif
default:
goto exit;
}
switch (cipher_type) {
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_TWISTED_ED: {
uint8_t *key_buf = NULL;
size_t key_buflen = 0;
/* Return the Key length including the ECC DER Header */
add_ecc_header(key, &key_buf, &key_buflen, keyObject->curve_id);
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key_buf,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
ENSURE_OR_GO_EXIT(status == SM_OK);
/* Change Endiannes. */
if ((keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_25519) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_MONT_DH_448) ||
(keyObject->curve_id == kSE05x_ECCurve_ECC_ED_25519)) {
for (size_t keyValueIdx = 0; keyValueIdx < (*keylen >> 1); keyValueIdx++) {
uint8_t swapByte = key_buf[keyValueIdx];
key_buf[keyValueIdx] = key_buf[*keylen - 1 - keyValueIdx];
key_buf[*keylen - 1 - keyValueIdx] = swapByte;
}
}
attst_data->valid_number = 1;
/* Return the Key length with header length */
*keylen += key_buflen;
break;
}
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
uint8_t modulus[1024];
uint8_t exponent[4];
size_t modLen = sizeof(modulus);
size_t expLen = sizeof(exponent);
uint16_t key_size_bytes = 0;
if (attestAlgo == (SE05x_AttestationAlgo_t)kSE05x_RSASignatureAlgo_SHA_512_PKCS1 ||
attestAlgo == (SE05x_AttestationAlgo_t)kSE05x_RSASignatureAlgo_SHA512_PKCS1_PSS)
{
status = Se05x_API_ReadSize(&keyStore->session->s_ctx, keyObject_attst->keyId, &key_size_bytes);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
if ((key_size_bytes * 8) == 512) {
return kStatus_SSS_Fail;
}
}
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadRSA_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
kSE05x_RSAPubKeyComp_MOD,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
modulus,
&modLen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
ENSURE_OR_GO_EXIT(status == SM_OK);
attst_data->data[1].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadRSA_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
kSE05x_RSAPubKeyComp_PUB_EXP,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
exponent,
&expLen,
attst_data->data[1].attribute,
&(attst_data->data[1].attributeLen),
&(attst_data->data[1].timeStamp),
attst_data->data[1].outrandom,
&(attst_data->data[1].outrandomLen),
attst_data->data[1].chipId,
&(attst_data->data[1].chipIdLen),
attst_data->data[1].signature,
&(attst_data->data[1].signatureLen));
attst_data->valid_number = 2;
ENSURE_OR_GO_EXIT(status == SM_OK);
if (sss_util_asn1_rsa_get_public(key, keylen, modulus, modLen, exponent, expLen) != kStatus_SSS_Success) {
goto exit;
}
} break;
#endif // SSSFTR_SE05X_RSA
case kSSS_CipherType_AES:
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_Binary: {
uint16_t rem_data = 0;
uint16_t offset = 0;
size_t dataLen = 0;
// size_t signatureLen = 0;
status = Se05x_API_ReadSize(&keyStore->session->s_ctx, keyObject->keyId, &size);
ENSURE_OR_GO_EXIT(status == SM_OK);
if (*keylen < size) {
LOG_E("Insufficient buffer ");
goto exit;
}
rem_data = size;
*keylen = size;
if (size > BINARY_WRITE_MAX_LEN) {
LOG_E("Cannot read large binary data with attestation");
goto exit;
}
// while (rem_data > 0) {
// uint16_t chunk = (rem_data > BINARY_WRITE_MAX_LEN) ?
// BINARY_WRITE_MAX_LEN :
// rem_data;
// rem_data = rem_data - chunk;
dataLen = rem_data;
// signatureLen = attst_data->data[0].signatureLen;
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
offset,
rem_data,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
(key + 0),
&dataLen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&attst_data->data[0].signatureLen);
// attst_data->data[0].signatureLen -= signatureLen;
// attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
// offset = offset + chunk;
// }
} break;
case kSSS_CipherType_DES:
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_PCR:
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_Count:
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
case kSSS_CipherType_HMAC:
case kSSS_CipherType_CMAC:
case kSSS_CipherType_UserID: {
attst_data->data[0].timeStampLen = sizeof(SE05x_TimeStamp_t);
status = Se05x_API_ReadObject_W_Attst(&keyStore->session->s_ctx,
keyObject->keyId,
0,
0,
attestID,
attestAlgo,
random_attst,
randomLen_attst,
key,
keylen,
attst_data->data[0].attribute,
&(attst_data->data[0].attributeLen),
&(attst_data->data[0].timeStamp),
attst_data->data[0].outrandom,
&(attst_data->data[0].outrandomLen),
attst_data->data[0].chipId,
&(attst_data->data[0].chipIdLen),
attst_data->data[0].signature,
&(attst_data->data[0].signatureLen));
attst_data->valid_number = 1;
ENSURE_OR_GO_EXIT(status == SM_OK);
break;
}
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
#if 0
/* To be reviewed: Purnank */
sss_status_t sss_se05x_key_store_get_key_fromoffset(sss_se05x_key_store_t *keyStore,
sss_se05x_object_t *keyObject,
uint8_t *key,
size_t *keylen,
size_t *pKeyBitLen,
uint16_t offset)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_key_type_t key_type = keyObject->objectType;
smStatus_t status = SM_NOT_OK;
switch (key_type) {
case kSSS_KeyType_Certificate:
status =
Se05x_API_FIL_BinaryReadFromOffset(&keyStore->session->s_ctx,
keyObject->keyId,
(uint16_t)*keylen,
offset,
key,
keylen);
if (status != SM_OK)
goto exit;
break;
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
#endif
sss_status_t sss_se05x_key_store_open_key(sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject)
{
sss_status_t retval = kStatus_SSS_Fail;
if (NULL == keyObject) {
keyStore->kekKey = NULL;
retval = kStatus_SSS_Success;
}
else if (keyObject->keyStore == keyStore) {
keyStore->kekKey = keyObject;
retval = kStatus_SSS_Success;
}
else {
LOG_W("KeyObject must be of same KeyStore.");
}
return retval;
}
sss_status_t sss_se05x_key_store_freeze_key(sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject)
{
sss_status_t retval = kStatus_SSS_Fail;
/* Purpose / Policy is set during creation time and hence can not
* enforced in SE050 later on */
return retval;
}
sss_status_t sss_se05x_key_store_erase_key(sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status;
status = Se05x_API_DeleteSecureObject(&keyStore->session->s_ctx, keyObject->keyId);
if (SM_OK == status) {
LOG_D("Erased Key id %X", keyObject->keyId);
retval = kStatus_SSS_Success;
}
else {
LOG_W("Could not delete Key id %X", keyObject->keyId);
}
return retval;
}
void sss_se05x_key_store_context_free(sss_se05x_key_store_t *keyStore)
{
memset(keyStore, 0, sizeof(*keyStore));
}
sss_status_t sss_se05x_key_store_export_key(
sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject, uint8_t *key, size_t *keylen)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_cipher_type_t cipher_type = keyObject->cipherType;
smStatus_t status = SM_NOT_OK;
switch (cipher_type) {
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_TWISTED_ED:
case kSSS_CipherType_AES:
case kSSS_CipherType_DES: {
status =
Se05x_API_ExportObject(&keyStore->session->s_ctx, keyObject->keyId, kSE05x_RSAKeyComponent_NA, key, keylen);
if (status != SM_OK) {
goto exit;
}
break;
}
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_key_store_import_key(
sss_se05x_key_store_t *keyStore, sss_se05x_object_t *keyObject, uint8_t *key, size_t keylen)
{
sss_status_t retval = kStatus_SSS_Fail;
sss_cipher_type_t cipher_type = keyObject->cipherType;
smStatus_t status = SM_NOT_OK;
switch (cipher_type) {
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL:
case kSSS_CipherType_EC_BARRETO_NAEHRIG:
case kSSS_CipherType_EC_MONTGOMERY:
case kSSS_CipherType_EC_TWISTED_ED:
case kSSS_CipherType_AES:
case kSSS_CipherType_DES: {
status =
Se05x_API_ImportObject(&keyStore->session->s_ctx, keyObject->keyId, kSE05x_RSAKeyComponent_NA, key, keylen);
if (status != SM_OK) {
goto exit;
}
break;
}
default:
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
/* End: se05x_keystore */
/* ************************************************************************** */
/* Functions : sss_se05x_asym */
/* ************************************************************************** */
sss_status_t sss_se05x_asymmetric_context_init(sss_se05x_asymmetric_t *context,
sss_se05x_session_t *session,
sss_se05x_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
context->keyObject = keyObject;
context->algorithm = algorithm;
context->mode = mode;
return retval;
}
sss_status_t sss_se05x_asymmetric_encrypt(
sss_se05x_asymmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_RSA
smStatus_t status = SM_NOT_OK;
SE05x_RSAEncryptionAlgo_t rsaEncryptionAlgo = se05x_get_rsa_encrypt_mode(context->algorithm);
status = Se05x_API_RSAEncrypt(
&context->session->s_ctx, context->keyObject->keyId, rsaEncryptionAlgo, srcData, srcLen, destData, destLen);
if (status == SM_OK)
retval = kStatus_SSS_Success;
#endif
return retval;
}
sss_status_t sss_se05x_asymmetric_decrypt(
sss_se05x_asymmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_RSA
smStatus_t status = SM_NOT_OK;
SE05x_RSAEncryptionAlgo_t rsaEncryptionAlgo = se05x_get_rsa_encrypt_mode(context->algorithm);
status = Se05x_API_RSADecrypt(
&context->session->s_ctx, context->keyObject->keyId, rsaEncryptionAlgo, srcData, srcLen, destData, destLen);
if (status == SM_OK)
retval = kStatus_SSS_Success;
#endif
return retval;
}
sss_status_t sss_se05x_asymmetric_sign_digest(
sss_se05x_asymmetric_t *context, uint8_t *digest, size_t digestLen, uint8_t *signature, size_t *signatureLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
if (kStatus_SSS_Success != se05x_check_input_len(digestLen, context->algorithm)) {
LOG_E("Algorithm and digest length do not match");
return kStatus_SSS_Fail;
}
#endif
switch (context->keyObject->cipherType) {
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL: {
SE05x_ECSignatureAlgo_t ecSignAlgo = se05x_get_ec_sign_hash_mode(context->algorithm);
status = Se05x_API_ECDSASign(&context->session->s_ctx,
context->keyObject->keyId,
ecSignAlgo,
digest,
digestLen,
signature,
signatureLen);
} break;
case kSSS_CipherType_EC_BARRETO_NAEHRIG: {
if (context->algorithm != kAlgorithm_SSS_ECDAA) {
return kStatus_SSS_Fail;
}
/* clang-format off */
uint8_t random[32] = {
0x7A, 0xCB, 0x93, 0x3D, 0xBE, 0x70, 0x39, 0x9B, 0xF6,
0xC9, 0x2D, 0xA3, 0x3A, 0xF0, 0x1D, 0x4F, 0xB7, 0x70,
0xE9, 0x8C, 0x03, 0x25, 0xF4, 0x1D, 0x3E, 0xBA, 0xF8,
0x98, 0x6D, 0xA7, 0x12, 0xCA
};
/* clang-format on */
uint8_t raw_signature[64];
size_t raw_signatureLen = sizeof(raw_signature);
SE05x_ECDAASignatureAlgo_t ecSignAlgo = kSE05x_ECDAASignatureAlgo_ECDAA;
sss_status_t asn_retval = kStatus_SSS_Fail;
status = Se05x_API_ECDAASign(&context->session->s_ctx,
context->keyObject->keyId,
ecSignAlgo,
digest,
digestLen,
random,
sizeof(random),
raw_signature,
&raw_signatureLen);
if (status != SM_OK) {
LOG_E("SE050 ECDAA Sign failed");
return kStatus_SSS_Fail;
}
asn_retval = sss_util_asn1_ecdaa_get_signature(signature, signatureLen, raw_signature, raw_signatureLen);
if (asn_retval != kStatus_SSS_Success) {
LOG_E("SE050 ECDAA Sign failed");
return kStatus_SSS_Fail;
}
} break;
#if SSS_HAVE_SE05X_VER_GTE_06_00
case kSSS_CipherType_EC_MONTGOMERY: {
LOG_W(
"Sign operation is not supported for "
"kSSS_CipherType_EC_MONTGOMERY curve");
return kStatus_SSS_Fail;
} break;
#endif
#endif //SSSFTR_SE05X_ECC
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
if ((context->algorithm <= kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512) &&
(context->algorithm >= kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1)) {
/* Perform EMSA encoding on input data and and RSA decrypt on emsa data --> RSA sign without hash */
/* clang-format off */
uint8_t emsa_data[512] = {0,}; /* MAX - SHA512*/
size_t emsa_len = sizeof(emsa_data);
/* clang-format on */
if (0 != emsa_encode(context, digest, digestLen, emsa_data, &emsa_len)) {
return kStatus_SSS_Fail;
}
status = Se05x_API_RSADecrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
emsa_data,
emsa_len,
signature,
signatureLen);
}
else if ((context->algorithm <= kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512) &&
(context->algorithm >= kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1)) {
/* Perform PKCS1-v15 encoding on input data and and RSA decrypt on PKCS1-v15 data --> RSA sign without hash */
/* clang-format off */
uint8_t pkcs1v15_encode_data[512] = {0,}; /* MAX - SHA512*/
size_t encode_data_len = sizeof(pkcs1v15_encode_data);
/* clang-format on */
if (0 != pkcs1_v15_encode(context, digest, digestLen, pkcs1v15_encode_data, &encode_data_len)) {
return kStatus_SSS_Fail;
}
status = Se05x_API_RSADecrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
pkcs1v15_encode_data,
encode_data_len,
signature,
signatureLen);
}
else if (context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH) {
/* Perform PKCS1-v15 encoding on input data and and RSA decrypt on PKCS1-v15 data --> RSA sign without hash */
/* clang-format off */
uint8_t pkcs1v15_encode_data[512] = {0,}; /* MAX - SHA512*/
size_t encode_data_len = sizeof(pkcs1v15_encode_data);
/* clang-format on */
if (0 != pkcs1_v15_encode_no_hash(context, digest, digestLen, pkcs1v15_encode_data, &encode_data_len)) {
return kStatus_SSS_Fail;
}
status = Se05x_API_RSADecrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
pkcs1v15_encode_data,
encode_data_len,
signature,
signatureLen);
}
else if (context->algorithm == kAlgorithm_SSS_RSASSA_NO_PADDING) {
uint8_t padded_data[512] = {0};
size_t padded_len = sizeof(padded_data);
size_t parsedKeyByteLen = 0;
uint16_t u16parsedKeyByteLen = 0;
status = Se05x_API_ReadSize(&context->session->s_ctx, context->keyObject->keyId, &u16parsedKeyByteLen);
parsedKeyByteLen = u16parsedKeyByteLen;
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
if (digestLen <= parsedKeyByteLen && digestLen > 0) {
memset(padded_data, 0x00, padded_len);
memcpy(&padded_data[parsedKeyByteLen - digestLen], &digest[0], digestLen);
padded_len = parsedKeyByteLen;
}
else {
return kStatus_SSS_Fail;
}
status = Se05x_API_RSADecrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
padded_data,
padded_len,
signature,
signatureLen);
}
else {
LOG_E("Selected padding is not supported for RSA Sign in SE050");
return kStatus_SSS_Fail;
}
} break;
#endif // SSSFTR_SE05X_RSA
default:
break;
}
if (status == SM_OK) {
retval = kStatus_SSS_Success;
#if 0 // SSS_HAVE_MBEDTLS && SSSFTR_SE05X_ECC
if (context->keyObject->cipherType >= kSSS_CipherType_EC_NIST_P &&
context->keyObject->cipherType <
kSSS_CipherType_EC_BARRETO_NAEHRIG) {
int ret;
/* Workaround for ECDSA signiture to omit prefix zeros if asn1
signiutre tag (integer) length in R and S component is 20 */
size_t length = 0, bufIndex = 0;
ret = asn_1_parse_tlv(signature, &length, &bufIndex);
if (ret != 0) {
retval = kStatus_SSS_Fail;
return retval;
}
if (signature[bufIndex] == 0x02) /* Check for tag interger */
{
LOG_AU8_D(signature, *signatureLen);
int count = 0;
uint16_t i = 0;
/* For R and S component */
for (i = 0; i < 2; i++) {
count = 0;
ret = asn_1_parse_tlv(signature, &length, &bufIndex);
if (ret != 0) {
retval = kStatus_SSS_Fail;
return retval;
}
if (length == 0x20) {
size_t j = bufIndex;
for (;; j++) {
if (signature[j] == 0 && signature[j + 1] > 0x7F) {
count++;
}
else {
break;
}
}
}
if (count) {
uint16_t k = 0;
signature[bufIndex - 1] -=
count; /* Update the tag length */
signature[1] -=
count; /* Update the Sequence tag length */
for (k = 0; k < (*signatureLen - bufIndex - count);
k++) {
signature[bufIndex + k] =
signature[bufIndex + count + k];
}
*signatureLen -= count;
}
bufIndex += length - count;
}
}
}
#endif // SSS_HAVE_MBEDTLS && SSSFTR_SE05X_ECC
}
return retval;
}
sss_status_t sss_se05x_asymmetric_sign(
sss_se05x_asymmetric_t *context, uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
switch (context->keyObject->cipherType) {
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
SE05x_RSASignatureAlgo_t rsaSigningAlgo = se05x_get_rsa_sign_hash_mode(context->algorithm);
uint16_t key_size_bytes = 0;
if (context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512 ||
context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512)
{
status = Se05x_API_ReadSize(&context->session->s_ctx, context->keyObject->keyId, &key_size_bytes);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
if ((key_size_bytes * 8) == 512) {
return kStatus_SSS_Fail;
}
}
status = Se05x_API_RSASign(
&context->session->s_ctx, context->keyObject->keyId, rsaSigningAlgo, srcData, srcLen, destData, destLen);
} break;
#endif // SSSFTR_SE05X_RSA
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_TWISTED_ED: {
if (context->algorithm == kAlgorithm_SSS_SHA512) {
SE05x_EDSignatureAlgo_t ecSignAlgo = kSE05x_EDSignatureAlgo_ED25519PURE_SHA_512;
status = Se05x_API_EdDSASign(
&context->session->s_ctx, context->keyObject->keyId, ecSignAlgo, srcData, srcLen, destData, destLen);
}
#ifdef TMP_ENDIAN_VERBOSE_SIGN
{
printf("Signature before Reverse:\n");
for (size_t z = 0; z < *destLen; z++) {
printf("%02X.", destData[z]);
}
printf("\n");
}
#endif
// Revert Endianness
size_t offset = 0;
for (size_t keyValueIdx = 0; keyValueIdx < (*destLen >> 2); keyValueIdx++) {
uint8_t swapByte = destData[keyValueIdx];
destData[offset + keyValueIdx] = destData[offset + (*destLen >> 1) - 1 - keyValueIdx];
destData[offset + (*destLen >> 1) - 1 - keyValueIdx] = swapByte;
}
offset = *destLen >> 1;
for (size_t keyValueIdx = 0; keyValueIdx < (*destLen >> 2); keyValueIdx++) {
uint8_t swapByte = destData[offset + keyValueIdx];
destData[offset + keyValueIdx] = destData[offset + (*destLen >> 1) - 1 - keyValueIdx];
destData[offset + (*destLen >> 1) - 1 - keyValueIdx] = swapByte;
}
#ifdef TMP_ENDIAN_VERBOSE_SIGN
{
printf("Signature after Reverse:\n");
for (size_t z = 0; z < *destLen; z++) {
printf("%02X.", destData[z]);
}
printf("\n");
}
#endif
} break;
#endif // SSSFTR_SE05X_ECC
default:
break;
}
if (status == SM_OK) {
retval = kStatus_SSS_Success;
}
return retval;
}
sss_status_t sss_se05x_asymmetric_verify_digest(
sss_se05x_asymmetric_t *context, uint8_t *digest, size_t digestLen, uint8_t *signature, size_t signatureLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
smStatus_t status = SM_NOT_OK;
SE05x_Result_t result = kSE05x_Result_FAILURE;
#endif // SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
if (kStatus_SSS_Success != se05x_check_input_len(digestLen, context->algorithm)) {
LOG_E("Algorithm and digest length do not match");
return kStatus_SSS_Fail;
}
switch (context->keyObject->cipherType) {
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_NIST_P:
case kSSS_CipherType_EC_NIST_K:
case kSSS_CipherType_EC_BRAINPOOL: {
SE05x_ECSignatureAlgo_t ecSignAlgo = se05x_get_ec_sign_hash_mode(context->algorithm);
status = Se05x_API_ECDSAVerify(&context->session->s_ctx,
context->keyObject->keyId,
ecSignAlgo,
digest,
digestLen,
signature,
signatureLen,
&result);
} break;
case kSSS_CipherType_EC_BARRETO_NAEHRIG: {
retval = kStatus_SSS_Fail;
LOG_W("Verify not supported for BN Curve");
} break;
#if SSS_HAVE_SE05X_VER_GTE_06_00
case kSSS_CipherType_EC_MONTGOMERY: {
LOG_W(
"Verify operation is not supported for "
"kSSS_CipherType_EC_MONTGOMERY curve");
return kStatus_SSS_Fail;
} break;
#endif
#endif // SSSFTR_SE05X_ECC
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
if ((context->algorithm <= kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512) &&
(context->algorithm >= kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1)) {
/* clang-format off */
uint8_t dec_data[512] = { 0, }; /* MAX - SHA512*/
size_t dec_len = sizeof(dec_data);
/* clang-format on */
status = Se05x_API_RSAEncrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
signature,
signatureLen,
dec_data,
&dec_len);
if (0 == emsa_decode_and_compare(context, dec_data, dec_len, digest, digestLen)) {
result = kSE05x_Result_SUCCESS;
}
}
else if ((context->algorithm <= kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512) &&
(context->algorithm >= kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1)) {
/* clang-format off */
uint8_t dec_data[512] = { 0, }; /* MAX - SHA512*/
size_t dec_len = sizeof(dec_data);
uint8_t pkcs1v15_encode_data[512] = { 0, }; /* MAX - SHA512*/
size_t encode_data_len = sizeof(pkcs1v15_encode_data);
/* clang-format on */
status = Se05x_API_RSAEncrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
signature,
signatureLen,
dec_data,
&dec_len);
if (0 != pkcs1_v15_encode(context, digest, digestLen, pkcs1v15_encode_data, &encode_data_len)) {
return kStatus_SSS_Fail;
}
if (memcmp(dec_data, pkcs1v15_encode_data, encode_data_len) == 0) {
result = kSE05x_Result_SUCCESS;
}
}
else if (context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH) {
/* clang-format off */
uint8_t dec_data[512] = { 0, }; /* MAX - SHA512*/
size_t dec_len = sizeof(dec_data);
uint8_t pkcs1v15_encode_data[512] = { 0, }; /* MAX - SHA512*/
size_t encode_data_len = sizeof(pkcs1v15_encode_data);
/* clang-format on */
status = Se05x_API_RSAEncrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
signature,
signatureLen,
dec_data,
&dec_len);
if (0 != pkcs1_v15_encode_no_hash(context, digest, digestLen, pkcs1v15_encode_data, &encode_data_len)) {
return kStatus_SSS_Fail;
}
if (memcmp(dec_data, pkcs1v15_encode_data, encode_data_len) == 0) {
result = kSE05x_Result_SUCCESS;
}
}
else if (context->algorithm == kAlgorithm_SSS_RSASSA_NO_PADDING) {
uint8_t dec_data[512] = {
0,
}; /*MAX - RSA4096*/
size_t dec_len = sizeof(dec_data);
status = Se05x_API_RSAEncrypt(&context->session->s_ctx,
context->keyObject->keyId,
kSE05x_RSAEncryptionAlgo_NO_PAD,
signature,
signatureLen,
dec_data,
&dec_len);
uint8_t padded_data[512] = {0};
size_t padded_len = sizeof(padded_data);
size_t parsedKeyByteLen = 0;
uint16_t u16parsedKeyByteLen = 0;
status = Se05x_API_ReadSize(&context->session->s_ctx, context->keyObject->keyId, &u16parsedKeyByteLen);
parsedKeyByteLen = u16parsedKeyByteLen;
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
if (digestLen <= parsedKeyByteLen && digestLen > 0) {
memset(padded_data, 0x00, padded_len);
memcpy(&padded_data[parsedKeyByteLen - digestLen], &digest[0], digestLen);
padded_len = parsedKeyByteLen;
}
else {
return kStatus_SSS_Fail;
}
if (memcmp(&dec_data[0], &padded_data[0], padded_len) == 0) {
result = kSE05x_Result_SUCCESS;
}
}
else {
LOG_E("Selected padding is not supported for RSA Sign in SE050");
return kStatus_SSS_Fail;
}
} break;
#endif // SSSFTR_SE05X_RSA
default:
break;
}
#endif // SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
if (status == SM_OK) {
if (result == kSE05x_Result_SUCCESS) {
retval = kStatus_SSS_Success;
}
}
#endif // SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
return retval;
}
sss_status_t sss_se05x_asymmetric_verify(
sss_se05x_asymmetric_t *context, uint8_t *srcData, size_t srcLen, uint8_t *signature, size_t signatureLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
SE05x_Result_t result = kSE05x_Result_FAILURE;
switch (context->keyObject->cipherType) {
#if SSSFTR_SE05X_RSA
case kSSS_CipherType_RSA:
case kSSS_CipherType_RSA_CRT: {
SE05x_RSASignatureAlgo_t rsaSigningAlgo = se05x_get_rsa_sign_hash_mode(context->algorithm);
uint16_t key_size_bytes = 0;
if (context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512 ||
context->algorithm == kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512)
{
status = Se05x_API_ReadSize(&context->session->s_ctx, context->keyObject->keyId, &key_size_bytes);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
if ((key_size_bytes * 8) == 512) {
return kStatus_SSS_Fail;
}
}
status = Se05x_API_RSAVerify(&context->session->s_ctx,
context->keyObject->keyId,
rsaSigningAlgo,
srcData,
srcLen,
signature,
signatureLen,
&result);
} break;
#endif // SSSFTR_SE05X_RSA
#if SSSFTR_SE05X_ECC
case kSSS_CipherType_EC_TWISTED_ED: {
#ifdef TMP_ENDIAN_VERBOSE
{
printf("Signatire before Reverse:\n");
for (size_t z = 0; z < signatureLen; z++) {
printf("%02X.", signature[z]);
}
printf("\n");
}
#endif
// Revert Endianness
size_t offset = 0;
for (size_t keyValueIdx = 0; keyValueIdx < (signatureLen >> 2); keyValueIdx++) {
uint8_t swapByte = signature[keyValueIdx];
signature[offset + keyValueIdx] = signature[offset + (signatureLen >> 1) - 1 - keyValueIdx];
signature[offset + (signatureLen >> 1) - 1 - keyValueIdx] = swapByte;
}
offset = signatureLen >> 1;
for (size_t keyValueIdx = 0; keyValueIdx < (signatureLen >> 2); keyValueIdx++) {
uint8_t swapByte = signature[offset + keyValueIdx];
signature[offset + keyValueIdx] = signature[offset + (signatureLen >> 1) - 1 - keyValueIdx];
signature[offset + (signatureLen >> 1) - 1 - keyValueIdx] = swapByte;
}
#ifdef TMP_ENDIAN_VERBOSE
{
printf("Signatire after Reverse:\n");
for (size_t z = 0; z < signatureLen; z++) {
printf("%02X.", signature[z]);
}
printf("\n");
}
#endif
if (context->algorithm == kAlgorithm_SSS_SHA512) {
SE05x_EDSignatureAlgo_t ecSignAlgo = kSE05x_EDSignatureAlgo_ED25519PURE_SHA_512;
status = Se05x_API_EdDSAVerify(&context->session->s_ctx,
context->keyObject->keyId,
ecSignAlgo,
srcData,
srcLen,
signature,
signatureLen,
&result);
}
} break;
#endif // SSSFTR_SE05X_ECC
default:
break;
}
if (status == SM_OK) {
if (result == kSE05x_Result_SUCCESS) {
retval = kStatus_SSS_Success;
}
}
return retval;
}
void sss_se05x_asymmetric_context_free(sss_se05x_asymmetric_t *context)
{
memset(context, 0, sizeof(*context));
}
/* End: se05x_asym */
/* ************************************************************************** */
/* Functions : sss_se05x_symm */
/* ************************************************************************** */
sss_status_t sss_se05x_symmetric_context_init(sss_se05x_symmetric_t *context,
sss_se05x_session_t *session,
sss_se05x_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
context->keyObject = keyObject;
context->algorithm = algorithm;
context->mode = mode;
context->cache_data_len = 0;
return retval;
}
sss_status_t sss_se05x_cipher_one_go(sss_se05x_symmetric_t *context,
uint8_t *iv,
size_t ivLen,
const uint8_t *srcData,
uint8_t *destData,
size_t dataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
SE05x_CipherMode_t cipherMode = se05x_get_cipher_mode(context->algorithm);
SE05x_Cipher_Oper_OneShot_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_OneShot_Encrypt : kSE05x_Cipher_Oper_OneShot_Decrypt;
status = Se05x_API_CipherOneShot(&context->session->s_ctx,
context->keyObject->keyId,
cipherMode,
srcData,
dataLen,
iv,
ivLen,
destData,
&dataLen,
OperType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_cipher_init(sss_se05x_symmetric_t *context, uint8_t *iv, size_t ivLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
//size_t retdataLen = 0;
SE05x_Cipher_Oper_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_Encrypt : kSE05x_Cipher_Oper_Decrypt;
SE05x_CipherMode_t cipherMode = se05x_get_cipher_mode(context->algorithm);
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
SE05x_CryptoModeSubType_t subtype = {0};
uint8_t list[1024] = {
0,
};
switch (context->algorithm) {
case kAlgorithm_SSS_AES_ECB:
subtype.cipher = kSE05x_CipherMode_AES_ECB_NOPAD;
context->cryptoObjectId = kSE05x_CryptoObject_AES_ECB_NOPAD;
break;
case kAlgorithm_SSS_AES_CBC:
subtype.cipher = kSE05x_CipherMode_AES_CBC_NOPAD;
context->cryptoObjectId = kSE05x_CryptoObject_AES_CBC_NOPAD;
break;
case kAlgorithm_SSS_AES_CTR:
subtype.cipher = kSE05x_CipherMode_AES_CTR;
context->cryptoObjectId = kSE05x_CryptoObject_AES_CTR;
break;
case kAlgorithm_SSS_DES_ECB:
subtype.cipher = kSE05x_CipherMode_DES_ECB_NOPAD;
context->cryptoObjectId = kSE05x_CryptoObject_DES_ECB_NOPAD;
break;
case kAlgorithm_SSS_DES_CBC:
subtype.cipher = kSE05x_CipherMode_DES_ECB_NOPAD;
context->cryptoObjectId = kSE05x_CryptoObject_DES_CBC_NOPAD;
break;
default:
return kStatus_SSS_Fail;
}
size_t listlen = sizeof(list);
size_t i;
uint8_t create_crypto_obj = 1;
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
create_crypto_obj = 0;
}
}
if (create_crypto_obj) {
status = Se05x_API_CreateCryptoObject(
&context->session->s_ctx, context->cryptoObjectId, kSE05x_CryptoContext_CIPHER, subtype);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
}
#endif
if (cipherMode == kSE05x_CipherMode_AES_ECB_NOPAD) {
ivLen = 0;
}
status = Se05x_API_CipherInit(
&context->session->s_ctx, context->keyObject->keyId, context->cryptoObjectId, iv, ivLen, OperType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_cipher_update(
sss_se05x_symmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t inputData[CIPHER_BLOCK_SIZE] = {
0,
};
size_t inputData_len = 0;
size_t src_offset = 0;
size_t output_offset = 0;
size_t outBuffSize = *destLen;
size_t blockoutLen = 0;
if ((context->cache_data_len + srcLen) < CIPHER_BLOCK_SIZE) {
/* Insufficinet data to process . Cache the data */
memcpy((context->cache_data + context->cache_data_len), srcData, srcLen);
context->cache_data_len = context->cache_data_len + srcLen;
*destLen = 0;
return kStatus_SSS_Success;
}
else {
/* Concatenate the unprocessed and current input data*/
memcpy(inputData, context->cache_data, context->cache_data_len);
inputData_len = context->cache_data_len;
memcpy((inputData + inputData_len), srcData, (CIPHER_BLOCK_SIZE - context->cache_data_len));
inputData_len += (CIPHER_BLOCK_SIZE - context->cache_data_len);
src_offset += (CIPHER_BLOCK_SIZE - context->cache_data_len);
context->cache_data_len = 0;
blockoutLen = outBuffSize;
ENSURE_OR_GO_EXIT(blockoutLen >= inputData_len);
status = Se05x_API_CipherUpdate(&context->session->s_ctx,
context->cryptoObjectId,
inputData,
inputData_len,
(destData + output_offset),
&blockoutLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
outBuffSize -= blockoutLen;
output_offset += blockoutLen;
while (srcLen - src_offset >= CIPHER_BLOCK_SIZE) {
memcpy(inputData, (srcData + src_offset), 16);
src_offset += CIPHER_BLOCK_SIZE;
blockoutLen = outBuffSize;
inputData_len = CIPHER_BLOCK_SIZE;
ENSURE_OR_GO_EXIT(blockoutLen >= inputData_len);
status = Se05x_API_CipherUpdate(&context->session->s_ctx,
context->cryptoObjectId,
inputData,
inputData_len,
(destData + output_offset),
&blockoutLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
outBuffSize -= blockoutLen;
output_offset += blockoutLen;
}
*destLen = output_offset;
/* Copy unprocessed data to cache */
if ((srcLen - src_offset) > 0) {
memcpy(context->cache_data, (srcData + src_offset), (srcLen - src_offset));
context->cache_data_len = (srcLen - src_offset);
}
}
retval = kStatus_SSS_Success;
exit:
if (retval == kStatus_SSS_Fail) {
*destLen = 0;
}
return retval;
}
sss_status_t sss_se05x_cipher_finish(
sss_se05x_symmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t srcdata_updated[2 * CIPHER_BLOCK_SIZE] = {
0,
};
size_t srcdata_updated_len = 0;
if (srcLen > CIPHER_BLOCK_SIZE) {
LOG_E("srcLen cannot be grater than 16 bytes. Call update function ");
*destLen = 0;
goto exit;
}
if (context->cache_data_len != 0) {
memcpy(srcdata_updated, context->cache_data, context->cache_data_len);
srcdata_updated_len = context->cache_data_len;
context->cache_data_len = 0;
}
if (srcLen != 0) {
memcpy((srcdata_updated + srcdata_updated_len), srcData, srcLen);
srcdata_updated_len += srcLen;
}
if (context->algorithm == kAlgorithm_SSS_AES_ECB || context->algorithm == kAlgorithm_SSS_AES_CBC) {
if (srcdata_updated_len % CIPHER_BLOCK_SIZE != 0) {
srcdata_updated_len = srcdata_updated_len + (CIPHER_BLOCK_SIZE - (srcdata_updated_len % 16));
}
}
if (*destLen < srcdata_updated_len) {
LOG_E("Output buffer not sufficient");
goto exit;
}
status = Se05x_API_CipherFinal(
&context->session->s_ctx, context->cryptoObjectId, srcdata_updated, srcdata_updated_len, destData, destLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_cipher_crypt_ctr(sss_se05x_symmetric_t *context,
const uint8_t *srcData,
uint8_t *destData,
size_t size,
uint8_t *initialCounter,
uint8_t *lastEncryptedCounter,
size_t *szLeft)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
size_t outputDataLen = 128;
SE05x_CipherMode_t cipherMode = se05x_get_cipher_mode(context->algorithm);
SE05x_Cipher_Oper_OneShot_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_OneShot_Encrypt : kSE05x_Cipher_Oper_OneShot_Decrypt;
status = Se05x_API_CipherOneShot(&context->session->s_ctx,
context->keyObject->keyId,
cipherMode,
srcData,
size,
initialCounter,
16,
destData,
&outputDataLen,
OperType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
void sss_se05x_symmetric_context_free(sss_se05x_symmetric_t *context)
{
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
smStatus_t status;
uint8_t list[1024] = {
0,
};
uint8_t object_exists = 0;
size_t listlen = sizeof(list);
if (context->cryptoObjectId != 0) {
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (size_t i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
object_exists = 1;
}
}
if (object_exists) {
status = Se05x_API_DeleteCryptoObject(&context->session->s_ctx, context->cryptoObjectId);
if (status != SM_OK) {
LOG_D("Could not delete crypto object 0x04X", context->cryptoObjectId);
return;
}
}
}
#endif
memset(context, 0, sizeof(*context));
}
/* End: se05x_symm */
/* ************************************************************************** */
/* Functions : sss_se05x_aead */
/* ************************************************************************** */
sss_status_t sss_se05x_aead_context_init(sss_se05x_aead_t *context,
sss_se05x_session_t *session,
sss_se05x_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Fail;
context->session = session;
context->keyObject = keyObject;
if ((algorithm == kAlgorithm_SSS_AES_CCM) || (algorithm == kAlgorithm_SSS_AES_GCM) ||
(algorithm == kAlgorithm_SSS_AES_GCM_INT_IV)) {
context->algorithm = algorithm;
}
else {
LOG_E("Improper Algorithm provided!!!");
goto exit;
}
context->mode = mode;
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_aead_one_go(sss_se05x_aead_t *context,
const uint8_t *srcData,
uint8_t *destData,
size_t size,
uint8_t *nonce,
size_t nonceLen,
const uint8_t *aad,
size_t aadLen,
uint8_t *tag,
size_t *tagLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSS_HAVE_SE05X_VER_GTE_06_00
smStatus_t status = SM_NOT_OK;
size_t destDataLen = size;
SE05x_CipherMode_t cipherMode =
(context->algorithm == kAlgorithm_SSS_AES_GCM) ? kSE05x_CipherMode_AES_GCM : kSE05x_CipherMode_AES_GCM_INT_IV;
SE05x_Cipher_Oper_OneShot_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_OneShot_Encrypt : kSE05x_Cipher_Oper_OneShot_Decrypt;
status = Se05x_API_AeadOneShot(&context->session->s_ctx,
context->keyObject->keyId,
cipherMode,
srcData,
size,
aad,
aadLen,
nonce,
nonceLen,
tag,
tagLen,
destData,
&destDataLen,
OperType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
return retval;
}
sss_status_t sss_se05x_aead_init(
sss_se05x_aead_t *context, uint8_t *nonce, size_t nonceLen, size_t tagLen, size_t aadLen, size_t payloadLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSS_HAVE_SE05X_VER_GTE_06_00
smStatus_t status = SM_NOT_OK;
context->cache_data_len = 0;
SE05x_CipherMode_t cipherMode = kSE05x_CipherMode_NA;
SE05x_Cipher_Oper_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_Encrypt : kSE05x_Cipher_Oper_Decrypt;
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
SE05x_CryptoModeSubType_t subtype = {0};
uint8_t list[1024] = {
0,
};
size_t listlen = sizeof(list);
size_t i;
uint8_t create_crypto_obj = 1;
if (context->algorithm == kAlgorithm_SSS_AES_GCM) {
context->cryptoObjectId = kSE05x_CryptoObject_AES_GCM;
subtype.aead = kSE05x_AeadGCMAlgo;
}
else if (context->algorithm == kAlgorithm_SSS_AES_GCM_INT_IV) {
context->cryptoObjectId = kSE05x_CryptoObject_AES_GCM_INT_IV;
subtype.aead = kSE05x_AeadGCM_IVAlgo;
}
else if (context->algorithm == kAlgorithm_SSS_AES_CCM) {
context->cryptoObjectId = kSE05x_CryptoObject_AES_CCM;
subtype.aead = kSE05x_AeadCCMAlgo;
}
else {
goto exit;
}
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
create_crypto_obj = 0;
}
}
if (create_crypto_obj) {
status = Se05x_API_CreateCryptoObject(
&context->session->s_ctx, context->cryptoObjectId, kSE05x_CryptoContext_AEAD, subtype);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
}
if (status != SM_OK) {
LOG_W("CreateCryptoObject Failed");
return kStatus_SSS_Fail;
}
#endif
memset(context->cache_data, 0x00, sizeof(context->cache_data));
if ((context->algorithm == (kAlgorithm_SSS_AES_GCM)) || (context->algorithm == (kAlgorithm_SSS_AES_GCM_INT_IV))) {
cipherMode = (context->algorithm == kAlgorithm_SSS_AES_GCM) ? kSE05x_CipherMode_AES_GCM :
kSE05x_CipherMode_AES_GCM_INT_IV;
status = Se05x_API_AeadInit(&context->session->s_ctx,
context->keyObject->keyId,
cipherMode,
context->cryptoObjectId,
nonce,
nonceLen,
OperType);
}
else {
status = Se05x_API_AeadCCMInit(&context->session->s_ctx,
context->keyObject->keyId,
context->cryptoObjectId,
nonce,
nonceLen,
aadLen,
payloadLen,
tagLen,
OperType);
}
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
return retval;
}
sss_status_t sss_se05x_aead_update_aad(sss_se05x_aead_t *context, const uint8_t *aadData, size_t aadDataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSS_HAVE_SE05X_VER_GTE_06_00
smStatus_t status = SM_NOT_OK;
size_t src_offset = 0;
if (aadDataLen > AEAD_BLOCK_SIZE) {
while ((aadDataLen - src_offset) >= AEAD_BLOCK_SIZE) {
/*For the subsequent blocks which are of block size 16*/
status = Se05x_API_AeadUpdate_aad(
&context->session->s_ctx, context->cryptoObjectId, (aadData + src_offset), AEAD_BLOCK_SIZE);
ENSURE_OR_GO_EXIT(status == SM_OK);
src_offset += AEAD_BLOCK_SIZE;
}
if ((aadDataLen - src_offset) > 0) {
/*For the subsequent blocks which are yet to process*/
status = Se05x_API_AeadUpdate_aad(
&context->session->s_ctx, context->cryptoObjectId, (aadData + src_offset), (aadDataLen - src_offset));
ENSURE_OR_GO_EXIT(status == SM_OK);
}
}
else {
status = Se05x_API_AeadUpdate_aad(&context->session->s_ctx, context->cryptoObjectId, aadData, aadDataLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
retval = kStatus_SSS_Success;
exit:
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
return retval;
}
sss_status_t sss_se05x_aead_update(
sss_se05x_aead_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSS_HAVE_SE05X_VER_GTE_06_00
smStatus_t status = SM_NOT_OK;
uint8_t inputData[AEAD_BLOCK_SIZE] = {
0,
};
size_t inputData_len = 0;
size_t src_offset = 0;
size_t output_offset = 0;
size_t outBuffSize = *destLen;
size_t blockoutLen = 0;
if ((context->cache_data_len + srcLen) < AEAD_BLOCK_SIZE) {
/* Insufficinet data to process . Cache the data */
memcpy((context->cache_data + context->cache_data_len), srcData, srcLen);
context->cache_data_len = context->cache_data_len + srcLen;
*destLen = 0;
return kStatus_SSS_Success;
}
else {
/* Concatenate the unprocessed and current input data*/
memcpy(inputData, context->cache_data, context->cache_data_len);
inputData_len = context->cache_data_len;
memcpy((inputData + inputData_len), srcData, (AEAD_BLOCK_SIZE - context->cache_data_len));
inputData_len += (AEAD_BLOCK_SIZE - context->cache_data_len);
src_offset += (AEAD_BLOCK_SIZE - context->cache_data_len);
blockoutLen = outBuffSize;
status = Se05x_API_AeadUpdate(&context->session->s_ctx,
context->cryptoObjectId,
inputData,
inputData_len,
(destData + output_offset),
&blockoutLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
outBuffSize -= blockoutLen;
output_offset += blockoutLen;
while ((srcLen - src_offset) >= AEAD_BLOCK_SIZE) {
/*For the subsequent blocks which are of block size 16*/
memcpy(inputData, (srcData + src_offset), AEAD_BLOCK_SIZE);
src_offset += AEAD_BLOCK_SIZE;
blockoutLen = outBuffSize;
status = Se05x_API_AeadUpdate(&context->session->s_ctx,
context->cryptoObjectId,
inputData,
inputData_len,
(destData + output_offset),
&blockoutLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
outBuffSize -= blockoutLen;
output_offset += blockoutLen;
}
*destLen = output_offset;
/* Copy unprocessed data to cache */
memcpy(context->cache_data, (srcData + src_offset), (srcLen - src_offset));
context->cache_data_len = (srcLen - src_offset);
}
retval = kStatus_SSS_Success;
exit:
if (retval == kStatus_SSS_Fail) {
*destLen = 0;
}
#endif /*SSS_HAVE_SE05X_VER_GTE_06_00*/
return retval;
}
sss_status_t sss_se05x_aead_finish(sss_se05x_aead_t *context,
const uint8_t *srcData,
size_t srcLen,
uint8_t *destData,
size_t *destLen,
uint8_t *tag,
size_t *tagLen)
{
sss_status_t retval = kStatus_SSS_Fail;
#if SSS_HAVE_SE05X_VER_GTE_06_00
smStatus_t status = SM_NOT_OK;
SE05x_Cipher_Oper_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_Encrypt : kSE05x_Cipher_Oper_Decrypt;
uint8_t srcdata_updated[2 * CIPHER_BLOCK_SIZE] = {
0,
};
size_t srcdata_updated_len = 0;
if (srcLen > CIPHER_BLOCK_SIZE) {
LOG_E("srcLen cannot be grater than 16 bytes. Call update function ");
*destLen = 0;
goto exit;
}
if (context->algorithm == kAlgorithm_SSS_AES_CCM) {
retval = sss_se05x_aead_CCMfinish(context, srcData, srcLen, destData, destLen, tag, tagLen);
}
else {
if (context->cache_data_len != 0) {
memcpy(srcdata_updated, context->cache_data, context->cache_data_len);
srcdata_updated_len = context->cache_data_len;
}
if (srcLen != 0) {
memcpy((srcdata_updated + srcdata_updated_len), srcData, srcLen);
srcdata_updated_len += srcLen;
}
if (srcdata_updated_len > 0) {
if (context->algorithm == kAlgorithm_SSS_AES_GCM) {
/*Input length if less than CIPHER_BLOCK_SIZE, give lenght as CIPHER_BLOCK_SIZE*/
if (srcdata_updated_len > CIPHER_BLOCK_SIZE) {
srcdata_updated_len = 2 * CIPHER_BLOCK_SIZE;
}
else {
srcdata_updated_len = CIPHER_BLOCK_SIZE;
}
}
status = Se05x_API_AeadUpdate(&context->session->s_ctx,
context->cryptoObjectId,
srcdata_updated,
srcdata_updated_len,
destData,
destLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
}
else {
/* This condition will occur if all data including cache is alread processed */
LOG_D("No Data in cache, All data are already processed");
*destLen = 0;
}
status = Se05x_API_AeadFinal(&context->session->s_ctx, context->cryptoObjectId, tag, tagLen, OperType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
}
exit:
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
return retval;
}
#if SSS_HAVE_SE05X_VER_GTE_06_00
static sss_status_t sss_se05x_aead_CCMfinish(sss_se05x_aead_t *context,
const uint8_t *srcData,
size_t srcLen,
uint8_t *destData,
size_t *destLen,
uint8_t *tag,
size_t *tagLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t dataprocessed = 1;
SE05x_Cipher_Oper_t OperType =
(context->mode == kMode_SSS_Encrypt) ? kSE05x_Cipher_Oper_Encrypt : kSE05x_Cipher_Oper_Decrypt;
uint8_t srcdata_updated[2 * CIPHER_BLOCK_SIZE] = {
0,
};
size_t srcdata_updated_len = 0;
size_t outLen = 0;
size_t tempoutLen = 0;
size_t destBufLen = *destLen;
if (context->cache_data_len != 0) {
memcpy(srcdata_updated, context->cache_data, context->cache_data_len);
srcdata_updated_len = context->cache_data_len;
}
if (srcLen != 0) {
memcpy((srcdata_updated + srcdata_updated_len), srcData, srcLen);
srcdata_updated_len += srcLen;
}
if (srcdata_updated_len > 0) {
if (srcdata_updated_len < CIPHER_BLOCK_SIZE) {
status = Se05x_API_AeadCCMLastUpdate(
&context->session->s_ctx, context->cryptoObjectId, srcdata_updated, srcdata_updated_len);
ENSURE_OR_GO_EXIT(status == SM_OK);
dataprocessed = 0;
}
else if (srcdata_updated_len >= CIPHER_BLOCK_SIZE) {
tempoutLen = destBufLen - outLen;
status = Se05x_API_AeadUpdate(&context->session->s_ctx,
context->cryptoObjectId,
srcdata_updated,
CIPHER_BLOCK_SIZE,
destData,
&tempoutLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
srcdata_updated_len = srcdata_updated_len - CIPHER_BLOCK_SIZE;
outLen = outLen + tempoutLen;
/* Put the remaining data in CCMLastUpdate if present (will always be less than CIPHER_BLOCK_SIZE) */
if (srcdata_updated_len) {
status = Se05x_API_AeadCCMLastUpdate(&context->session->s_ctx,
context->cryptoObjectId,
srcdata_updated + CIPHER_BLOCK_SIZE,
srcdata_updated_len);
ENSURE_OR_GO_EXIT(status == SM_OK);
dataprocessed = 0;
}
}
}
else {
/* This condition will occur if all data including
cache is already processed just send final*/
dataprocessed = 1;
}
if (dataprocessed == 0) {
/*All data is updated, lastupdate datalen < 16 o/p
is expected here */
tempoutLen = destBufLen - outLen;
status = Se05x_API_AeadCCMFinal(
&context->session->s_ctx, context->cryptoObjectId, (destData + outLen), &tempoutLen, tag, tagLen, OperType);
outLen = outLen + tempoutLen;
}
else {
/*All data is processed no destination data*/
status = Se05x_API_AeadFinal(&context->session->s_ctx, context->cryptoObjectId, tag, tagLen, OperType);
}
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
*destLen = outLen;
exit:
return retval;
}
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
void sss_se05x_aead_context_free(sss_se05x_aead_t *context)
{
#if SSS_HAVE_SE05X_VER_GTE_06_00
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
smStatus_t status;
uint8_t list[1024] = {
0,
};
uint8_t object_exists = 0;
size_t listlen = sizeof(list);
if (context->cryptoObjectId != 0) {
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (size_t i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
object_exists = 1;
}
}
if (object_exists) {
status = Se05x_API_DeleteCryptoObject(&context->session->s_ctx, context->cryptoObjectId);
if (status != SM_OK) {
LOG_D("Could not delete crypto object 0x04X", context->cryptoObjectId);
return;
}
}
}
#endif /* SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ */
memset(context, 0, sizeof(*context));
#endif /* SSS_HAVE_SE05X_VER_GTE_06_00 */
}
/* End: se05x_aead */
/* ************************************************************************** */
/* Functions : sss_se05x_mac */
/* ************************************************************************** */
sss_status_t sss_se05x_mac_context_init(sss_se05x_mac_t *context,
sss_se05x_session_t *session,
sss_se05x_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
context->keyObject = keyObject;
context->algorithm = algorithm;
context->mode = mode;
return retval;
}
sss_status_t sss_se05x_mac_one_go(
sss_se05x_mac_t *context, const uint8_t *message, size_t messageLen, uint8_t *mac, size_t *macLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
SE05x_MACAlgo_t macOperation = se05x_get_mac_algo(context->algorithm);
status = Se05x_API_MACOneShot_G(
&context->session->s_ctx, context->keyObject->keyId, macOperation, message, messageLen, mac, macLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_mac_validate_one_go(
sss_se05x_mac_t *context, const uint8_t *message, size_t messageLen, uint8_t *mac, size_t macLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
SE05x_MACAlgo_t macOperation;
SE05x_Result_t result = kSE05x_Result_FAILURE;
size_t result_size = sizeof(result);
if (context == NULL) {
goto exit;
}
macOperation = se05x_get_mac_algo(context->algorithm);
status = Se05x_API_MACOneShot_V(&context->session->s_ctx,
context->keyObject->keyId,
macOperation,
message,
messageLen,
mac,
macLen,
(uint8_t *)&result,
&result_size);
if (status == SM_OK) {
if (result == kSE05x_Result_SUCCESS) {
retval = kStatus_SSS_Success;
}
}
exit:
return retval;
}
sss_status_t sss_se05x_mac_init(sss_se05x_mac_t *context)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
SE05x_CryptoModeSubType_t subtype = {0};
uint8_t list[1024] = {
0,
};
size_t listlen = sizeof(list);
size_t i;
uint8_t create_crypto_obj = 1;
SE05x_CryptoContext_t cryptoContext;
switch (context->algorithm) {
case kAlgorithm_SSS_CMAC_AES:
subtype.mac = kSE05x_MACAlgo_CMAC_128;
cryptoContext = kSE05x_CryptoContext_SIGNATURE;
context->cryptoObjectId = kSE05x_CryptoObject_CMAC_128;
break;
case kAlgorithm_SSS_HMAC_SHA1:
subtype.mac = kSE05x_MACAlgo_HMAC_SHA1;
cryptoContext = kSE05x_CryptoContext_SIGNATURE;
context->cryptoObjectId = kSE05x_CryptoObject_HMAC_SHA1;
break;
case kAlgorithm_SSS_HMAC_SHA256:
subtype.mac = kSE05x_MACAlgo_HMAC_SHA256;
cryptoContext = kSE05x_CryptoContext_SIGNATURE;
context->cryptoObjectId = kSE05x_CryptoObject_HMAC_SHA256;
break;
case kAlgorithm_SSS_HMAC_SHA384:
subtype.mac = kSE05x_MACAlgo_HMAC_SHA384;
cryptoContext = kSE05x_CryptoContext_SIGNATURE;
context->cryptoObjectId = kSE05x_CryptoObject_HMAC_SHA384;
break;
case kAlgorithm_SSS_HMAC_SHA512:
subtype.mac = kSE05x_MACAlgo_HMAC_SHA512;
cryptoContext = kSE05x_CryptoContext_SIGNATURE;
context->cryptoObjectId = kSE05x_CryptoObject_HMAC_SHA512;
break;
default:
return kStatus_SSS_Fail;
}
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
create_crypto_obj = 0;
}
}
if (create_crypto_obj) {
status =
Se05x_API_CreateCryptoObject(&context->session->s_ctx, context->cryptoObjectId, cryptoContext, subtype);
if (status != SM_OK) {
LOG_W("CreateCryptoObject Failed");
return kStatus_SSS_Fail;
}
}
#endif
SE05x_Mac_Oper_t operType = kSE05x_Mac_Oper_Generate;
status = Se05x_API_MACInit(&context->session->s_ctx, context->keyObject->keyId, context->cryptoObjectId, operType);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_mac_update(sss_se05x_mac_t *context, const uint8_t *message, size_t messageLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
//SE05x_MACAlgo_t macOperation = se05x_get_mac_algo(context->algorithm);
status = Se05x_API_MACUpdate(&context->session->s_ctx, message, messageLen, context->cryptoObjectId);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_mac_finish(sss_se05x_mac_t *context, uint8_t *mac, size_t *macLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
//SE05x_MACAlgo_t macOperation = se05x_get_mac_algo(context->algorithm);
status = Se05x_API_MACFinal(&context->session->s_ctx, NULL, 0, context->cryptoObjectId, NULL, 0, mac, macLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
void sss_se05x_mac_context_free(sss_se05x_mac_t *context)
{
if (context->cryptoObjectId != 0) {
smStatus_t status = Se05x_API_DeleteCryptoObject(&context->session->s_ctx, context->cryptoObjectId);
if (status != SM_OK) {
LOG_D("Could not delete crypto object 0x04X", context->cryptoObjectId);
return;
}
}
memset(context, 0, sizeof(*context));
}
/* End: se05x_mac */
/* ************************************************************************** */
/* Functions : sss_se05x_md */
/* ************************************************************************** */
sss_status_t sss_se05x_digest_context_init(
sss_se05x_digest_t *context, sss_se05x_session_t *session, sss_algorithm_t algorithm, sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
context->algorithm = algorithm;
context->mode = mode;
return retval;
}
sss_status_t sss_se05x_digest_one_go(
sss_se05x_digest_t *context, const uint8_t *message, size_t messageLen, uint8_t *digest, size_t *digestLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
uint8_t sha_type = se05x_get_sha_algo(context->algorithm);
status = Se05x_API_SHAOneShot(&context->session->s_ctx, sha_type, message, messageLen, digest, digestLen);
if (status != SM_OK) {
*digestLen = 0;
goto exit;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_digest_init(sss_se05x_digest_t *context)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
#if SSSFTR_SE05X_CREATE_DELETE_CRYPTOOBJ
SE05x_CryptoModeSubType_t subtype = {0};
uint8_t list[1024] = {
0,
};
size_t listlen = sizeof(list);
size_t i;
uint8_t create_crypto_obj = 1;
switch (context->algorithm) {
case kAlgorithm_SSS_SHA1:
subtype.digest = kSE05x_DigestMode_SHA;
context->cryptoObjectId = kSE05x_CryptoObject_DIGEST_SHA;
break;
case kAlgorithm_SSS_SHA224:
subtype.digest = kSE05x_DigestMode_SHA224;
context->cryptoObjectId = kSE05x_CryptoObject_DIGEST_SHA224;
break;
case kAlgorithm_SSS_SHA256:
subtype.digest = kSE05x_DigestMode_SHA256;
context->cryptoObjectId = kSE05x_CryptoObject_DIGEST_SHA256;
break;
case kAlgorithm_SSS_SHA384:
subtype.digest = kSE05x_DigestMode_SHA384;
context->cryptoObjectId = kSE05x_CryptoObject_DIGEST_SHA384;
break;
case kAlgorithm_SSS_SHA512:
subtype.digest = kSE05x_DigestMode_SHA512;
context->cryptoObjectId = kSE05x_CryptoObject_DIGEST_SHA512;
break;
default:
return kStatus_SSS_Fail;
}
status = Se05x_API_ReadCryptoObjectList(&context->session->s_ctx, list, &listlen);
for (i = 0; i < listlen; i += 4) {
uint16_t cryptoObjectId = list[i + 1] | (list[i + 0] << 8);
if (cryptoObjectId == context->cryptoObjectId) {
create_crypto_obj = 0;
}
}
if (create_crypto_obj) {
status = Se05x_API_CreateCryptoObject(
&context->session->s_ctx, context->cryptoObjectId, kSE05x_CryptoContext_DIGEST, subtype);
if (status != SM_OK) {
return kStatus_SSS_Fail;
}
}
#endif
status = Se05x_API_DigestInit(&context->session->s_ctx, context->cryptoObjectId);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_digest_update(sss_se05x_digest_t *context, const uint8_t *message, size_t messageLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
status = Se05x_API_DigestUpdate(&context->session->s_ctx, context->cryptoObjectId, message, messageLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_digest_finish(sss_se05x_digest_t *context, uint8_t *digest, size_t *digestLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
status = Se05x_API_DigestFinal(&context->session->s_ctx, context->cryptoObjectId, NULL, 0, digest, digestLen);
ENSURE_OR_GO_EXIT(status == SM_OK);
retval = kStatus_SSS_Success;
exit:
return retval;
}
void sss_se05x_digest_context_free(sss_se05x_digest_t *context)
{
if (context->cryptoObjectId != 0) {
smStatus_t status = Se05x_API_DeleteCryptoObject(&context->session->s_ctx, context->cryptoObjectId);
if (status != SM_OK) {
LOG_D("Could not delete crypto object 0x04X", context->cryptoObjectId);
return;
}
}
memset(context, 0, sizeof(*context));
}
/* End: se05x_md */
/* ************************************************************************** */
/* Functions : sss_se05x_rng */
/* ************************************************************************** */
sss_status_t sss_se05x_rng_context_init(sss_se05x_rng_context_t *context, sss_se05x_session_t *session)
{
sss_status_t retval = kStatus_SSS_Success;
context->session = session;
return retval;
}
sss_status_t sss_se05x_rng_get_random(sss_se05x_rng_context_t *context, uint8_t *random_data, size_t dataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
size_t chunk = 0;
size_t offset = 0;
while (dataLen > 0) {
/* TODO - Replace 512 with max rsp buffer size based on with/without SCP */
if (dataLen > 512) {
chunk = 512;
}
else {
chunk = dataLen;
}
status = Se05x_API_GetRandom(&context->session->s_ctx, (uint16_t)chunk, (random_data + offset), &chunk);
ENSURE_OR_GO_EXIT(status == SM_OK);
offset += chunk;
dataLen -= chunk;
}
retval = kStatus_SSS_Success;
exit:
return retval;
}
sss_status_t sss_se05x_rng_context_free(sss_se05x_rng_context_t *context)
{
sss_status_t retval = kStatus_SSS_Success;
memset(context, 0, sizeof(*context));
return retval;
}
/* End: se05x_rng */
sss_status_t sss_se05x_tunnel_context_init(sss_se05x_tunnel_context_t *context, sss_se05x_session_t *session)
{
context->se05x_session = session;
sss_status_t retval = kStatus_SSS_Success;
#if (__GNUC__ && !AX_EMBEDDED)
if (pthread_mutex_init(&context->channelLock, NULL) != 0) {
LOG_E("\n mutex init has failed");
return kStatus_SSS_Fail;
}
else {
LOG_D("Mutex Init successfull");
}
#elif AX_EMBEDDED && USE_RTOS
context->channelLock = xSemaphoreCreateMutex();
if (context->channelLock == NULL) {
LOG_E("xSemaphoreCreateMutex failed");
return kStatus_SSS_Fail;
}
#endif
return retval;
}
sss_status_t sss_se05x_tunnel(sss_se05x_tunnel_context_t *context,
uint8_t *data,
size_t dataLen,
sss_se05x_object_t *keyObjects,
uint32_t keyObjectCount,
uint32_t tunnelType)
{
sss_status_t retval = kStatus_SSS_Fail;
return retval;
}
void sss_se05x_tunnel_context_free(sss_se05x_tunnel_context_t *context)
{
#if (__GNUC__ && !AX_EMBEDDED)
pthread_mutex_destroy(&context->channelLock);
#elif AX_EMBEDDED && USE_RTOS
vSemaphoreDelete(context->channelLock);
#endif
memset(context, 0, sizeof(*context));
}
static smStatus_t sss_se05x_TXn(struct Se05xSession *pSession,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle)
{
smStatus_t ret = SM_NOT_OK;
tlvHeader_t outHdr = {
0,
};
uint8_t txBuf[SE05X_MAX_BUF_SIZE_CMD] = {
0,
};
size_t txBufLen = sizeof(txBuf);
ret = pSession->fp_Transform(pSession, hdr, cmdBuf, cmdBufLen, &outHdr, txBuf, &txBufLen, hasle);
ENSURE_OR_GO_EXIT(ret == SM_OK);
ret = pSession->fp_RawTXn(
pSession->conn_ctx, pSession->pChannelCtx, pSession->authType, &outHdr, txBuf, txBufLen, rsp, rspLen, hasle);
ret = pSession->fp_DeCrypt(pSession, cmdBufLen, rsp, rspLen, hasle);
ENSURE_OR_GO_EXIT(ret == SM_OK);
exit:
return ret;
}
static smStatus_t sss_se05x_channel_txnRaw(void *conn_ctx,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle)
{
uint8_t txBuf[SE05X_MAX_BUF_SIZE_CMD] = {0};
size_t i = 0;
memcpy(&txBuf[i], hdr, sizeof(*hdr));
smStatus_t ret = SM_NOT_OK;
i += sizeof(*hdr);
if (cmdBufLen > 0) {
// The Lc field must be extended in case the length does not fit
// into a single byte (Note, while the standard would allow to
// encode 0x100 as 0x00 in the Lc field, nobody who is sane in his mind
// would actually do that).
if ((cmdBufLen < 0xFF) && !hasle) {
txBuf[i++] = (uint8_t)cmdBufLen;
}
else {
txBuf[i++] = 0x00;
txBuf[i++] = 0xFFu & (cmdBufLen >> 8);
txBuf[i++] = 0xFFu & (cmdBufLen);
}
memcpy(&txBuf[i], cmdBuf, cmdBufLen);
i += cmdBufLen;
}
else {
if (cmdBufLen == 0) {
txBuf[i++] = 0x00;
}
}
if (hasle) {
txBuf[i++] = 0x00;
txBuf[i++] = 0x00;
}
uint32_t U32rspLen = (uint32_t)*rspLen;
ret = (smStatus_t)smCom_TransceiveRaw(conn_ctx, txBuf, (U16)i, rsp, &U32rspLen);
*rspLen = U32rspLen;
return ret;
}
static smStatus_t sss_se05x_channel_txn(void *conn_ctx,
struct _sss_se05x_tunnel_context *pChannelCtx,
SE_AuthType_t currAuth,
const tlvHeader_t *hdr,
uint8_t *cmdBuf,
size_t cmdBufLen,
uint8_t *rsp,
size_t *rspLen,
uint8_t hasle)
{
smStatus_t retStatus = SM_NOT_OK;
if ((pChannelCtx != NULL)) {
#if SSSFTR_SE05X_AuthECKey || SSSFTR_SE05X_AuthSession
struct Se05xSession *se05xCtx = (struct Se05xSession *)&pChannelCtx->se05x_session->s_ctx;
if (se05xCtx->authType == kSSS_AuthType_SCP03) {
#if USE_LOCK
LOCK_TXN(pChannelCtx->channelLock);
#endif
retStatus = se05xCtx->fp_TXn(se05xCtx, hdr, cmdBuf, cmdBufLen, rsp, rspLen, hasle);
#if USE_LOCK
UNLOCK_TXN(pChannelCtx->channelLock);
#endif
ENSURE_OR_GO_EXIT(retStatus == SM_OK);
}
else if (se05xCtx->authType == kSSS_AuthType_None) {
#if USE_LOCK
LOCK_TXN(pChannelCtx->channelLock);
#endif
retStatus = se05xCtx->fp_TXn(se05xCtx, hdr, cmdBuf, cmdBufLen, rsp, rspLen, hasle);
#if USE_LOCK
UNLOCK_TXN(pChannelCtx->channelLock);
#endif
ENSURE_OR_GO_EXIT(retStatus == SM_OK);
}
else {
LOG_E("Invalid auth type");
goto exit;
}
#endif
}
else {
if (currAuth == kSSS_AuthType_SCP03) {
uint32_t u32rspLen = (uint32_t)*rspLen;
retStatus = (smStatus_t)smCom_TransceiveRaw(conn_ctx, cmdBuf, (uint16_t)cmdBufLen, rsp, &u32rspLen);
ENSURE_OR_GO_EXIT(retStatus == SM_OK);
*rspLen = u32rspLen;
}
else {
retStatus = sss_se05x_channel_txnRaw(conn_ctx, hdr, cmdBuf, cmdBufLen, rsp, rspLen, hasle);
ENSURE_OR_GO_EXIT(retStatus == SM_OK);
}
}
exit:
return retStatus;
}
/* End: se05x_tunnel */
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
sss_status_t sss_se05x_key_store_create_curve(Se05xSession_t *pSession, uint32_t curve_id)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
status = sss_se05x_create_curve_if_needed(pSession, curve_id);
if (SM_OK == status)
retval = kStatus_SSS_Success;
return retval;
}
#endif
sss_status_t sss_se05x_set_feature(
sss_se05x_session_t *session, SE05x_Applet_Feature_t feature, SE05x_Applet_Feature_Disable_t disable_features)
{
sss_status_t retval = kStatus_SSS_Fail;
smStatus_t status = SM_NOT_OK;
Se05x_AppletFeatures_t applet_features = {0};
applet_features.extended_features = NULL;
if (session == NULL)
goto exit;
#if SSS_HAVE_SE05X_VER_GTE_06_00
SE05x_ExtendedFeatures_t extended = {0};
/** Disable feature ECDH B2b8 */
if (disable_features.EXTCFG_FORBID_ECDH == 1)
extended.features[1] |= 0x80; // 8th bit
/** Disable feature ECDAA B2b7 */
if (disable_features.EXTCFG_FORBID_ECDAA == 1)
extended.features[1] |= 0x40; // 7th bit
/** Disable feature RSA_LT_2K B6b8 */
if (disable_features.EXTCFG_FORBID_RSA_LT_2K == 1)
extended.features[5] |= 0x80; // 8th bit
/** Disable feature RSA_SHA1 B6b7 */
if (disable_features.EXTCFG_FORBID_RSA_SHA1 == 1)
extended.features[5] |= 0x40; // 7th bit
/** Disable feature AES_GCM B8b8 */
if (disable_features.EXTCFG_FORBID_AES_GCM == 1)
extended.features[7] |= 0x80; // 8th bit
/** Disable feature AES_GCM_EXT_IV B8b7 */
if (disable_features.EXTCFG_FORBID_AES_GCM_EXT_IV == 1)
extended.features[7] |= 0x40; // 7th bit
/** Disable feature HKDF_EXTRACT B10b7 */
if (disable_features.EXTCFG_FORBID_HKDF_EXTRACT == 1)
extended.features[9] |= 0x40; // 7th bit
applet_features.extended_features = &extended;
#endif
if (feature.AppletConfig_ECDAA == 1)
applet_features.variant |= kSE05x_AppletConfig_ECDAA;
else if (feature.AppletConfig_ECDSA_ECDH_ECDHE == 1)
applet_features.variant |= kSE05x_AppletConfig_ECDSA_ECDH_ECDHE;
else if (feature.AppletConfig_EDDSA == 1)
applet_features.variant |= kSE05x_AppletConfig_EDDSA;
else if (feature.AppletConfig_DH_MONT == 1)
applet_features.variant |= kSE05x_AppletConfig_DH_MONT;
else if (feature.AppletConfig_HMAC == 1)
applet_features.variant |= kSE05x_AppletConfig_HMAC;
else if (feature.AppletConfig_RSA_PLAIN == 1)
applet_features.variant |= kSE05x_AppletConfig_RSA_PLAIN;
else if (feature.AppletConfig_RSA_CRT == 1)
applet_features.variant |= kSE05x_AppletConfig_RSA_CRT;
else if (feature.AppletConfig_AES == 1)
applet_features.variant |= kSE05x_AppletConfig_AES;
else if (feature.AppletConfig_DES == 1)
applet_features.variant |= kSE05x_AppletConfig_DES;
else if (feature.AppletConfig_PBKDF == 1)
applet_features.variant |= kSE05x_AppletConfig_PBKDF;
else if (feature.AppletConfig_TLS == 1)
applet_features.variant |= kSE05x_AppletConfig_TLS;
else if (feature.AppletConfig_MIFARE == 1)
applet_features.variant |= kSE05x_AppletConfig_MIFARE;
else if (feature.AppletConfig_I2CM == 1)
applet_features.variant |= kSE05x_AppletConfig_I2CM;
else
goto exit;
status = Se05x_API_SetAppletFeatures(&session->s_ctx, &applet_features);
if (status == SM_OK) {
retval = kStatus_SSS_Success;
}
exit:
return retval;
}
#if SSSFTR_SE05X_AuthSession
static smStatus_t se05x_CreateVerifyUserIDSession(
pSe05xSession_t se05xSession, const uint32_t auth_id, SE05x_AuthCtx_ID_t *userId, pSe05xPolicy_t policy)
{
sss_status_t retval = kStatus_SSS_Fail;
SE05x_Result_t exists = kSE05x_Result_FAILURE;
smStatus_t status = SM_NOT_OK;
size_t sessionIdLen = 8;
uint8_t keyVal[60];
size_t keyValLen = sizeof(keyVal);
size_t keyBitLen = sizeof(keyVal) * 8;
/* Check if Object exists only if auth_id is non kSE05x_AppletResID_TRANSPORT */
/* CheckObjectExists returns 6985 SE05x if transport is Locked */
if (auth_id == kSE05x_AppletResID_TRANSPORT) {
status = SM_OK;
LOG_D("Create Session with kSE05x_AppletResID_TRANSPORT");
}
else {
status = Se05x_API_CheckObjectExists(se05xSession, auth_id, &exists);
if (status == SM_OK && exists == kSE05x_Result_FAILURE) {
status = SM_NOT_OK;
LOG_E("UserID is not Provisioned!!!");
}
}
if (status == SM_OK) {
status = Se05x_API_CreateSession(se05xSession, auth_id, se05xSession->value, &sessionIdLen);
}
if (status == SM_OK) {
status = SM_NOT_OK;
retval = sss_host_key_store_get_key(userId->pObj->keyStore, userId->pObj, keyVal, &keyValLen, &keyBitLen);
if (keyValLen < 4) {
LOG_W("User ID cannot be less than 4 bytes");
return SM_NOT_OK;
}
if (retval == kStatus_SSS_Success) {
se05xSession->hasSession = 1;
status = Se05x_API_VerifySessionUserID(se05xSession, keyVal, keyValLen);
if (status == SM_OK) {
if (policy->value > 0) {
status = SM_NOT_OK;
status = Se05x_API_ExchangeSessionData(se05xSession, policy);
}
}
}
}
return status;
}
#endif
#if SSS_HAVE_SCP_SCP03_SSS
#if SSSFTR_SE05X_AuthSession
static smStatus_t se05x_CreateVerifyAESKeySession(
pSe05xSession_t se05xSession, const uint32_t auth_id, NXSCP03_AuthCtx_t *pAppletSCPCtx)
{
SE05x_Result_t exists = kSE05x_Result_FAILURE;
smStatus_t status = SM_NOT_OK;
size_t sessionIdLen = 8;
sss_status_t retval = kStatus_SSS_Fail;
if (auth_id == kSE05x_AppletResID_TRANSPORT) {
/* SKIP */
/* If there's a transport lock, Se05x_API_CheckObjectExists would fail. */
status = SM_OK;
}
else {
status = Se05x_API_CheckObjectExists(se05xSession, auth_id, &exists);
if (status == SM_OK && exists == kSE05x_Result_FAILURE) {
status = SM_NOT_OK;
LOG_E("Applet key is not Provisioned!!!");
}
}
if (status == SM_OK) {
status = Se05x_API_CreateSession(se05xSession, auth_id, se05xSession->value, &sessionIdLen);
if (status != SM_OK) {
se05xSession->hasSession = 0;
}
else {
se05xSession->hasSession = 1;
se05xSession->authType = kSSS_AuthType_AESKey;
retval = nxScp03_AuthenticateChannel(se05xSession, pAppletSCPCtx);
if (retval == kStatus_SSS_Success) {
pAppletSCPCtx->pDyn_ctx->authType = kSSS_AuthType_AESKey;
se05xSession->pdynScp03Ctx = pAppletSCPCtx->pDyn_ctx;
status = SM_OK;
}
else {
status = SM_NOT_OK;
}
}
}
return status;
}
#endif
#if SSSFTR_SE05X_AuthECKey
static smStatus_t se05x_CreateECKeySession(
pSe05xSession_t se05xSession, const uint32_t auth_id, SE05x_AuthCtx_ECKey_t *pFScpCtx)
{
sss_status_t retval = kStatus_SSS_Fail;
SE05x_Result_t exists = kSE05x_Result_FAILURE;
smStatus_t status = SM_NOT_OK;
size_t sessionIdLen = 8;
status = Se05x_API_CheckObjectExists(se05xSession, auth_id, &exists);
if (status == SM_OK && exists == kSE05x_Result_FAILURE) {
status = SM_NOT_OK;
LOG_E("SE ECDSA Public Key is not Provisioned!!!");
}
if (status == SM_OK) {
status = Se05x_API_CreateSession(se05xSession, auth_id, se05xSession->value, &sessionIdLen);
if (status != SM_OK) {
se05xSession->hasSession = 0;
}
else {
status = SM_NOT_OK;
se05xSession->hasSession = 1;
retval = nxECKey_AuthenticateChannel(se05xSession, pFScpCtx);
if (retval == kStatus_SSS_Success) {
NXSCP03_DynCtx_t *pDyn_ctx = pFScpCtx->pDyn_ctx;
pDyn_ctx->authType = se05xSession->authType = kSSS_AuthType_ECKey;
se05xSession->pdynScp03Ctx = pFScpCtx->pDyn_ctx;
status = SM_OK;
}
}
}
return status;
}
#endif /* SSSFTR_SE05X_AuthECKey */
#endif
#if SSSFTR_SE05X_ECC || SSSFTR_SE05X_RSA
static sss_status_t se05x_check_input_len(size_t inLen, sss_algorithm_t algorithm)
{
sss_status_t retval = kStatus_SSS_Fail;
switch (algorithm) {
case kAlgorithm_SSS_SHA1:
case kAlgorithm_SSS_ECDSA_SHA1:
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1:
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1:
retval = (inLen == 20) ? kStatus_SSS_Success : kStatus_SSS_Fail;
break;
case kAlgorithm_SSS_SHA224:
case kAlgorithm_SSS_ECDSA_SHA224:
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA224:
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA224:
retval = (inLen == 28) ? kStatus_SSS_Success : kStatus_SSS_Fail;
break;
case kAlgorithm_SSS_SHA256:
case kAlgorithm_SSS_ECDAA:
case kAlgorithm_SSS_ECDSA_SHA256:
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA256:
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA256:
retval = (inLen == 32) ? kStatus_SSS_Success : kStatus_SSS_Fail;
break;
case kAlgorithm_SSS_SHA384:
case kAlgorithm_SSS_ECDSA_SHA384:
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA384:
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA384:
retval = (inLen == 48) ? kStatus_SSS_Success : kStatus_SSS_Fail;
break;
case kAlgorithm_SSS_SHA512:
case kAlgorithm_SSS_ECDSA_SHA512:
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512:
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512:
retval = (inLen == 64) ? kStatus_SSS_Success : kStatus_SSS_Fail;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH:
case kAlgorithm_SSS_RSASSA_NO_PADDING:
retval = kStatus_SSS_Success;
break;
default:
LOG_E("Unkown algorithm");
retval = kStatus_SSS_Fail;
}
return retval;
}
#endif
static SE05x_ECSignatureAlgo_t se05x_get_ec_sign_hash_mode(sss_algorithm_t algorithm)
{
uint8_t mode;
switch (algorithm) {
case kAlgorithm_SSS_SHA1:
case kAlgorithm_SSS_ECDSA_SHA1:
mode = kSE05x_ECSignatureAlgo_SHA;
break;
case kAlgorithm_SSS_SHA224:
case kAlgorithm_SSS_ECDSA_SHA224:
mode = kSE05x_ECSignatureAlgo_SHA_224;
break;
case kAlgorithm_SSS_SHA256:
case kAlgorithm_SSS_ECDSA_SHA256:
mode = kSE05x_ECSignatureAlgo_SHA_256;
break;
case kAlgorithm_SSS_SHA384:
case kAlgorithm_SSS_ECDSA_SHA384:
mode = kSE05x_ECSignatureAlgo_SHA_384;
break;
case kAlgorithm_SSS_SHA512:
case kAlgorithm_SSS_ECDSA_SHA512:
mode = kSE05x_ECSignatureAlgo_SHA_512;
break;
default:
mode = kSE05x_ECSignatureAlgo_PLAIN;
break;
}
return mode;
}
#if SSSFTR_SE05X_RSA
static SE05x_RSAEncryptionAlgo_t se05x_get_rsa_encrypt_mode(sss_algorithm_t algorithm)
{
SE05x_RSAEncryptionAlgo_t mode;
switch (algorithm) {
case kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA1:
mode = kSE05x_RSAEncryptionAlgo_PKCS1_OAEP;
break;
case kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA224:
case kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256:
case kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA384:
case kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA512:
mode = kSE05x_RSAEncryptionAlgo_NA;
break;
case kAlgorithm_SSS_RSAES_PKCS1_V1_5:
mode = kSE05x_RSAEncryptionAlgo_PKCS1;
break;
default:
mode = kSE05x_RSAEncryptionAlgo_NO_PAD;
break;
}
return mode;
}
static SE05x_RSASignatureAlgo_t se05x_get_rsa_sign_hash_mode(sss_algorithm_t algorithm)
{
SE05x_RSASignatureAlgo_t mode;
switch (algorithm) {
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1:
mode = kSE05x_RSASignatureAlgo_SHA1_PKCS1;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA224:
mode = kSE05x_RSASignatureAlgo_SHA_224_PKCS1;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA256:
mode = kSE05x_RSASignatureAlgo_SHA_256_PKCS1;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA384:
mode = kSE05x_RSASignatureAlgo_SHA_384_PKCS1;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512:
mode = kSE05x_RSASignatureAlgo_SHA_512_PKCS1;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1:
mode = kSE05x_RSASignatureAlgo_SHA1_PKCS1_PSS;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA224:
mode = kSE05x_RSASignatureAlgo_SHA224_PKCS1_PSS;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA256:
mode = kSE05x_RSASignatureAlgo_SHA256_PKCS1_PSS;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA384:
mode = kSE05x_RSASignatureAlgo_SHA384_PKCS1_PSS;
break;
case kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512:
mode = kSE05x_RSASignatureAlgo_SHA512_PKCS1_PSS;
break;
default:
mode = kSE05x_RSASignatureAlgo_NA;
}
return mode;
}
#endif // SSSFTR_SE05X_RSA
static SE05x_CipherMode_t se05x_get_cipher_mode(sss_algorithm_t algorithm)
{
SE05x_CipherMode_t mode;
switch (algorithm) {
case kAlgorithm_SSS_AES_ECB:
mode = kSE05x_CipherMode_AES_ECB_NOPAD;
break;
case kAlgorithm_SSS_DES_ECB:
mode = kSE05x_CipherMode_DES_ECB_NOPAD;
break;
case kAlgorithm_SSS_AES_CBC:
mode = kSE05x_CipherMode_AES_CBC_NOPAD;
break;
case kAlgorithm_SSS_DES_CBC:
mode = kSE05x_CipherMode_DES_CBC_NOPAD;
break;
case kAlgorithm_SSS_AES_CTR:
mode = kSE05x_CipherMode_AES_CTR;
break;
default:
mode = 0;
}
return mode;
}
SE05x_MACAlgo_t se05x_get_mac_algo(sss_algorithm_t algorithm)
{
SE05x_MACAlgo_t mode;
switch (algorithm) {
case kAlgorithm_SSS_CMAC_AES:
mode = kSE05x_MACAlgo_CMAC_128;
break;
case kAlgorithm_SSS_HMAC_SHA1:
mode = kSE05x_MACAlgo_HMAC_SHA1;
break;
case kAlgorithm_SSS_HMAC_SHA256:
mode = kSE05x_MACAlgo_HMAC_SHA256;
break;
case kAlgorithm_SSS_HMAC_SHA384:
mode = kSE05x_MACAlgo_HMAC_SHA384;
break;
case kAlgorithm_SSS_HMAC_SHA512:
mode = kSE05x_MACAlgo_HMAC_SHA512;
break;
default:
mode = 0;
}
return mode;
}
SE05x_DigestMode_t se05x_get_sha_algo(sss_algorithm_t algorithm)
{
SE05x_DigestMode_t sha_type;
switch (algorithm) {
case kAlgorithm_SSS_SHA1:
case kAlgorithm_SSS_HMAC_SHA1:
sha_type = kSE05x_DigestMode_SHA;
break;
case kAlgorithm_SSS_SHA224:
sha_type = kSE05x_DigestMode_SHA224;
break;
case kAlgorithm_SSS_SHA256:
case kAlgorithm_SSS_HMAC_SHA256:
sha_type = kSE05x_DigestMode_SHA256;
break;
case kAlgorithm_SSS_SHA384:
case kAlgorithm_SSS_HMAC_SHA384:
sha_type = kSE05x_DigestMode_SHA384;
break;
case kAlgorithm_SSS_SHA512:
case kAlgorithm_SSS_HMAC_SHA512:
sha_type = kSE05x_DigestMode_SHA512;
break;
default:
sha_type = 0x00;
}
return sha_type;
}
////////////////////////////////////////////////////////////////////////
#if SSSFTR_SE05X_ECC && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_ec_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_ECCurve_t curveID,
const uint8_t *privKey,
size_t privKeyLen,
const uint8_t *pubKey,
size_t pubKeyLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
SE05x_Result_t obj_exists)
{
smStatus_t status = SM_NOT_OK;
#if SSS_HAVE_SE05X_VER_GTE_06_00
fp_Ec_KeyWrite_t fpEcKey_Ver = NULL;
/* Call APIs For SE051 */
if (obj_exists == kSE05x_Result_FAILURE) {
fpEcKey_Ver = &Se05x_API_WriteECKey_Ver;
}
else if (obj_exists == kSE05x_Result_SUCCESS) {
fpEcKey_Ver = &Se05x_API_UpdateECKey_Ver;
}
if (fpEcKey_Ver != NULL) {
status = fpEcKey_Ver(session_ctx,
policy,
maxAttempt,
objectID,
curveID,
privKey,
privKeyLen,
pubKey,
pubKeyLen,
ins_type,
key_part,
0);
}
else {
LOG_E("Invalid Object exist status!!!");
}
#else
/* Call APIs For SE050 */
status = Se05x_API_WriteECKey(
session_ctx, policy, maxAttempt, objectID, curveID, privKey, privKeyLen, pubKey, pubKeyLen, ins_type, key_part);
#endif
return status;
}
#endif //SSSFTR_SE05X_ECC
#if SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_symm_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
SE05x_MaxAttemps_t maxAttempt,
uint32_t objectID,
SE05x_KeyID_t kekID,
const uint8_t *keyValue,
size_t keyValueLen,
const SE05x_INS_t ins_type,
const SE05x_SymmKeyType_t type,
SE05x_Result_t obj_exists)
{
smStatus_t status = SM_NOT_OK;
#if SSS_HAVE_SE05X_VER_GTE_06_00
fp_Symm_KeyWrite_t fpSymmKey_Ver = NULL;
/* Call APIs For SE051 */
if (obj_exists == kSE05x_Result_FAILURE) {
fpSymmKey_Ver = &Se05x_API_WriteSymmKey_Ver;
}
else if (obj_exists == kSE05x_Result_SUCCESS) {
fpSymmKey_Ver = &Se05x_API_UpdateSymmKey_Ver;
}
if (fpSymmKey_Ver != NULL) {
status = (*fpSymmKey_Ver)(
session_ctx, policy, maxAttempt, objectID, kekID, keyValue, keyValueLen, ins_type, type, 0);
}
else {
LOG_E("Invalid Object exist status!!!");
}
#else
/* Call APIs For SE050 */
status =
Se05x_API_WriteSymmKey(session_ctx, policy, maxAttempt, objectID, kekID, keyValue, keyValueLen, ins_type, type);
#endif
return status;
}
#endif //SSSFTR_SE05X_AES && SSSFTR_SE05X_KEY_SET
#if SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
static smStatus_t sss_se05x_LL_set_RSA_key(pSe05xSession_t session_ctx,
pSe05xPolicy_t policy,
uint32_t objectID,
uint16_t size,
const uint8_t *p,
size_t pLen,
const uint8_t *q,
size_t qLen,
const uint8_t *dp,
size_t dpLen,
const uint8_t *dq,
size_t dqLen,
const uint8_t *qInv,
size_t qInvLen,
const uint8_t *pubExp,
size_t pubExpLen,
const uint8_t *priv,
size_t privLen,
const uint8_t *pubMod,
size_t pubModLen,
const SE05x_INS_t ins_type,
const SE05x_KeyPart_t key_part,
const SE05x_RSAKeyFormat_t rsa_format,
SE05x_Result_t obj_exists)
{
smStatus_t status = SM_NOT_OK;
#if SSS_HAVE_SE05X_VER_GTE_06_00
fp_RSA_KeyWrite_t fpRSAKey_Ver = NULL;
/* Call APIs For SE051 */
if (obj_exists == kSE05x_Result_FAILURE) {
fpRSAKey_Ver = &Se05x_API_WriteRSAKey_Ver;
}
else if (obj_exists == kSE05x_Result_SUCCESS) {
fpRSAKey_Ver = &Se05x_API_UpdateRSAKey_Ver;
}
if (fpRSAKey_Ver != NULL) {
status = (*fpRSAKey_Ver)(session_ctx,
policy,
objectID,
size,
p,
pLen,
q,
qLen,
dp,
dpLen,
dq,
dqLen,
qInv,
qInvLen,
pubExp,
pubExpLen,
priv,
privLen,
pubMod,
pubModLen,
ins_type,
key_part,
rsa_format,
0);
}
else {
LOG_E("Invalid Object exist status!!!");
}
#else
/* Call APIs For SE050 */
status = Se05x_API_WriteRSAKey(session_ctx,
policy,
objectID,
size,
p,
pLen,
q,
qLen,
dp,
dpLen,
dq,
dqLen,
qInv,
qInvLen,
pubExp,
pubExpLen,
priv,
privLen,
pubMod,
pubModLen,
ins_type,
key_part,
rsa_format);
#endif
return status;
}
#endif //SSSFTR_SE05X_RSA && SSSFTR_SE05X_KEY_SET
#ifdef __cplusplus
}
#endif
#endif /* SSS_HAVE_APPLET_SE05X_IOT */