blob: e02b9933899a5ac28a3ed8f4ed8a24e04c14b63d [file] [log] [blame]
/*
*
* Copyright 2018-2020 NXP
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#if defined(SSS_USE_FTR_FILE)
#include "fsl_sss_ftr.h"
#else
#include "fsl_sss_ftr_default.h"
#endif
#if SSS_HAVE_SSCP
#include <fsl_sscp.h>
#include <fsl_sscp_commands.h>
#include <fsl_sss_sscp.h>
#include <nxEnsure.h>
#include <stdlib.h>
#include <string.h>
#include "nxLog_sscp.h"
#if SSS_HAVE_A71CH_SIM || SSS_HAVE_A71CH
#include "a71ch_api.h"
#include "fsl_sscp_a71ch.h"
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
#include "a71cl_api.h"
#include "fsl_sscp_a71cl.h"
#endif
/* Shorthand for SSCP_OP_SET_PARAM */
#define SSCP_PARAMS(p1, p2, p3, p4, p5, p6) \
SSCP_OP_SET_PARAM(/* First param always ContextReference */ \
kSSCP_ParamType_ContextReference, \
kSSCP_ParamType_##p1, \
kSSCP_ParamType_##p2, \
kSSCP_ParamType_##p3, \
kSSCP_ParamType_##p4, \
kSSCP_ParamType_##p5, \
kSSCP_ParamType_##p6)
#define SET_OP_0_KeyObject() \
op.params[0].context.ptr = keyObject; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Object;
#define SET_OP_0_KeyStore() \
op.params[0].context.ptr = keyStore; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_KeyStore;
#define SET_OP_0_DeriveKey() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_DeriveKey;
#define SET_OP_0_Asymm() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Asymmetric;
#define SET_OP_0_Symm() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Symmetric;
#define SET_OP_0_Tunnel() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Tunnel;
#define SET_OP_0_Mac() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Mac;
#define SET_OP_0_Digest() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_Digest;
#define SET_OP_0_RandGen() \
op.params[0].context.ptr = context; \
op.params[0].context.type = kSSCP_ParamContextType_SSS_RandomGen;
/* ************************************************************************** */
/* Functions : sss_sscp_session */
/* ************************************************************************** */
sss_status_t sss_sscp_session_create(sss_sscp_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;
}
sss_status_t sss_sscp_session_open(sss_sscp_session_t *session,
sss_type_t subsystem,
uint32_t application_id,
sss_connection_type_t connection_type,
void *connectionData)
{
uint32_t ret = kStatus_SSS_InvalidArgument;
session->sessionId = 0;
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
if (kType_SSS_SE_A71CH == subsystem) {
ret = sscp_a71ch_openSession(connectionData, session);
}
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
if (kType_SSS_SE_A71CL == subsystem) {
ret = sscp_a71cl_openSession(connectionData);
}
#endif
if (ret == kStatus_SSS_Success) {
session->subsystem = subsystem;
session->sscp_context = NULL;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_session_prop_get_u32(sss_sscp_session_t *session, uint32_t property, uint32_t *pValue)
{
sss_status_t retval = kStatus_SSS_Success;
sss_session_prop_u32_t prop = property;
sss_sscp_sesion_prop_u32_t sscpprop = 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 (sscpprop) {
case kSSS_SSCP_SessionProp_CertUIDLen: {
*pValue = 10;
retval = kStatus_SSS_Success;
} break;
default: {
*pValue = 0;
retval = kStatus_SSS_Fail;
}
}
cleanup:
return retval;
}
sss_status_t sss_sscp_session_prop_get_au8(
sss_sscp_session_t *session, uint32_t property, uint8_t *pValue, size_t *pValueLen)
{
sss_status_t retval = kStatus_SSS_Fail;
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sss_session_prop_au8_t prop = property;
sss_sscp_sesion_prop_au8_t sscpprop = property;
sscp_context_t *sscpCtx = NULL;
sscp_operation_t op = {0};
if (pValue == NULL || pValueLen == NULL) {
goto cleanup;
}
sscpCtx = session->sscp_context;
switch (prop) {
case kSSS_SessionProp_UID: {
if (*pValueLen >= 18) {
op.params[1].memref.buffer = pValue;
op.params[1].memref.size = *pValueLen;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_GET_UID, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
goto cleanup;
}
*pValueLen = op.params[1].memref.size;
retval = kStatus_SSS_Success;
}
else {
LOG_D("Buffer too short");
}
} break;
default:;
}
switch (sscpprop) {
case kSSS_SSCP_SessionProp_CertUID: {
op.params[1].memref.buffer = pValue;
op.params[1].memref.size = *pValueLen;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_GET_CERT_UID, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
goto cleanup;
}
*pValueLen = op.params[1].memref.size;
retval = kStatus_SSS_Success;
} break;
default:;
}
cleanup:
return (retval);
}
void sss_sscp_session_close(sss_sscp_session_t *session)
{
session->subsystem = kType_SSS_SubSystem_NONE;
if (session->sscp_context != NULL) {
session->sscp_context->invoke = NULL;
}
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
sscp_a71ch_closeSession(session);
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
sscp_a71cl_closeSession();
#endif
memset(session, 0, sizeof(*session));
}
void sss_sscp_session_delete(sss_sscp_session_t *session)
{
;
}
/* End: sscp_session */
/* ************************************************************************** */
/* Functions : sss_sscp_keyobj */
/* ************************************************************************** */
sss_status_t sss_sscp_key_object_init(sss_sscp_object_t *keyObject, sss_sscp_key_store_t *keyStore)
{
uint32_t ret = kStatus_SSS_Fail;
ENSURE_OR_GO_CLEANUP(keyStore);
ENSURE_OR_GO_CLEANUP(keyObject);
ENSURE_OR_GO_CLEANUP(keyStore->session);
memset(keyObject, 0, sizeof(*keyObject));
keyObject->keyStore = keyStore;
ret = kStatus_SSS_Success;
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_allocate_handle(sss_sscp_object_t *keyObject,
uint32_t keyId,
sss_key_part_t keyPart,
sss_cipher_type_t cipherType,
size_t keyByteLenMax,
uint32_t options)
{
SSCP_BUILD_ASSURE(sizeof(sss_object_t) >= sizeof(sss_sscp_object_t), _sss_sscp_object_size);
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
if (options == kKeyObject_Mode_Persistent) {
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, None, None, None, None);
SET_OP_0_KeyObject();
op.params[1].value.a = keyId;
op.params[1].value.b = keyPart;
op.params[2].value.a = (uint32_t)keyByteLenMax;
op.params[2].value.b = options;
op.params[3].value.a = cipherType;
sscp_context_t *sscpCtx = keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_KEYOBJ_CMD_ALLOCATE_HANDLE, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
keyObject->keyId = keyId;
keyObject->objectType = keyPart;
keyObject->cipherType = cipherType;
keyObject->slotId = op.params[4].value.a;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
}
else if (options == kKeyObject_Mode_Transient) {
ret = kStatus_SSS_Fail;
keyObject->transientObject = SSS_MALLOC(keyByteLenMax);
ENSURE_OR_GO_CLEANUP(keyObject->transientObject);
keyObject->transientObjectLen = (uint32_t)keyByteLenMax;
memset(keyObject->transientObject, 0, keyByteLenMax);
ret = kStatus_SSS_Success;
}
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_get_handle(sss_sscp_object_t *keyObject, uint32_t keyId)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSS_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, ValueOutput, None, None, None, None);
SET_OP_0_KeyObject();
op.params[1].value.a = keyId;
sscp_context_t *sscpCtx = keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_KEYOBJ_CMD_GET_HANDLE, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
keyObject->objectType = op.params[2].value.a;
keyObject->cipherType = op.params[2].value.b;
keyObject->keyId = keyId;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_set_user(sss_sscp_object_t *keyObject, uint32_t user, uint32_t options)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, None, None, None, None);
SET_OP_0_KeyObject();
op.params[1].value.a = keyObject->keyId;
op.params[2].value.a = user;
op.params[2].value.b = options;
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_SET_USER, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_set_purpose(sss_sscp_object_t *keyObject, sss_mode_t purpose, uint32_t options)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyObject();
op.params[1].value.a = purpose;
op.params[1].value.b = options;
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_SET_PURPOSE, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_set_access(sss_sscp_object_t *keyObject, uint32_t access, uint32_t options)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyObject();
op.params[1].value.a = access;
op.params[1].value.b = options;
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_SET_ACCESS, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_set_eccgfp_group(sss_sscp_object_t *keyObject, sss_eccgfp_group_t *group)
{
uint32_t ret = kStatus_SSS_Fail;
/* TBU */
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_get_user(sss_sscp_object_t *keyObject, uint32_t *user)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueOutput, None, None, None, None, None);
SET_OP_0_KeyObject();
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_GET_USER, &op, &ret);
if (resSSCP == kStatus_SSCP_Success) {
*user = op.params[0].value.a;
}
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_get_purpose(sss_sscp_object_t *keyObject, sss_mode_t *purpose)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueOutput, None, None, None, None, None);
SET_OP_0_KeyObject();
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_GET_PURPOSE, &op, &ret);
if (resSSCP == kStatus_SSCP_Success) {
*purpose = op.params[0].value.a;
}
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_object_get_access(sss_sscp_object_t *keyObject, uint32_t *access)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueOutput, None, None, None, None, None);
SET_OP_0_KeyObject();
sscp_context_t *ctx = keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_KEYOBJ_CMD_GET_ACCESS, &op, &ret);
if (resSSCP == kStatus_SSCP_Success) {
*access = op.params[0].value.a;
}
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
void sss_sscp_key_object_free(sss_sscp_object_t *keyObject)
{
if (keyObject->transientObject != NULL)
SSS_FREE(keyObject->transientObject);
memset(keyObject, 0, sizeof(*keyObject));
}
/* End: sscp_keyobj */
/* ************************************************************************** */
/* Functions : sss_sscp_keyderive */
/* ************************************************************************** */
sss_status_t sss_sscp_derive_key_context_init(sss_sscp_derive_key_t *context,
sss_sscp_session_t *session,
sss_sscp_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSS_Fail;
sscp_operation_t op = {0};
ENSURE_OR_GO_CLEANUP(context);
ENSURE_OR_GO_CLEANUP(keyObject);
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CH);
memset(context, 0, sizeof(*context));
context->algorithm = algorithm;
context->mode = mode;
context->session = session;
context->keyObject = keyObject;
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, ValueOutput, None, None, None);
SET_OP_0_DeriveKey();
op.params[1].value.a = context->algorithm;
op.params[1].value.b = context->mode;
op.params[2].value.a = context->keyObject->keyId;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_DERIVE_CTX_INIT, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
context->sessionId = op.params[3].value.a;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_derive_key_one_go(sss_sscp_derive_key_t *context,
const uint8_t *saltData,
size_t saltLen,
const uint8_t *info,
size_t infoLen,
sss_sscp_object_t *derivedKeyObject,
uint16_t deriveDataLen)
{
return sss_sscp_derive_key_go(
context, saltData, saltLen, info, infoLen, derivedKeyObject, deriveDataLen, NULL, NULL);
}
sss_status_t sss_sscp_derive_key_sobj_one_go(sss_sscp_derive_key_t *context,
sss_sscp_object_t *saltKeyObject,
const uint8_t *info,
size_t infoLen,
sss_sscp_object_t *derivedKeyObject,
uint16_t deriveDataLen)
{
// Not implemented
return kStatus_SSS_Fail;
#if 0
// Retrieve salt value from salt object
uint8_t saltData[256];
size_t saltLen;
return sss_sscp_derive_key_go(context,
saltData,
saltLen,
info,
infoLen,
derivedKeyObject,
deriveDataLen,
NULL,
NULL);
#endif
}
sss_status_t sss_sscp_derive_key_go(sss_sscp_derive_key_t *context,
const uint8_t *saltData,
size_t saltLen,
const uint8_t *info,
size_t infoLen,
sss_sscp_object_t *derivedKeyObject,
uint16_t deriveDataLen,
uint8_t *hkdfOutput,
size_t *hkdfOutputLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sss_status_t retval = kStatus_SSS_Fail;
sscp_operation_t op = {0};
uint8_t derivedkey[256] = {0};
size_t derivedkeyBitlen = deriveDataLen * 8;
sss_object_t *sss_derived_keyObject = (sss_object_t *)derivedKeyObject;
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefInput, MemrefOutput, None, None);
SET_OP_0_DeriveKey();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)saltData;
op.params[2].memref.size = saltLen;
op.params[3].memref.buffer = (void *)info;
op.params[3].memref.size = infoLen;
op.params[4].memref.buffer = derivedkey;
op.params[4].memref.size = deriveDataLen;
op.params[5].value.a = (uint32_t)derivedkeyBitlen;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_DERIVE_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
retval = sss_key_store_set_key(sss_derived_keyObject->keyStore,
sss_derived_keyObject,
derivedkey,
deriveDataLen,
(deriveDataLen * 8),
NULL,
0);
}
return retval;
}
sss_status_t sss_sscp_derive_key_dh(
sss_sscp_derive_key_t *context, sss_sscp_object_t *otherPartyKeyObject, sss_sscp_object_t *derivedKeyObject)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sss_status_t retval;
sscp_operation_t op = {0};
uint8_t pubkey[128] = {0};
size_t pubKeyByteLen = sizeof(pubkey);
size_t keyBitlen = sizeof(pubkey) * 8;
uint8_t derivedkey[32] = {0};
size_t derivedkeyBitlen = sizeof(derivedkey) * 8;
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_other_keyObject->keyStore, sss_other_keyObject, pubkey, &pubKeyByteLen, &keyBitlen);
if (retval == kStatus_SSS_Success) {
retval = kStatus_SSS_Fail;
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, MemrefInput, MemrefOutput, MemrefOutput, None);
SET_OP_0_DeriveKey();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (pubkey);
op.params[2].memref.size = (pubKeyByteLen * 8);
op.params[3].memref.buffer = derivedkey;
op.params[3].memref.size = sizeof(derivedkey);
op.params[4].memref.size = derivedkeyBitlen;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_ASYMM_DH_DERIVE_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
derivedkeyBitlen = op.params[4].memref.size;
retval = sss_key_store_set_key(sss_derived_keyObject->keyStore,
sss_derived_keyObject,
derivedkey,
sizeof(derivedkey),
derivedkeyBitlen,
NULL,
0);
}
}
return (retval);
}
void sss_sscp_derive_key_context_free(sss_sscp_derive_key_t *context)
{
memset(context, 0, sizeof(*context));
}
/* End: sscp_keyderive */
/* ************************************************************************** */
/* Functions : sss_sscp_keystore */
/* ************************************************************************** */
sss_status_t sss_sscp_key_store_context_init(sss_sscp_key_store_t *keyStore, sss_sscp_session_t *session)
{
uint32_t ret = kStatus_SSS_Fail;
ENSURE_OR_GO_CLEANUP(keyStore);
ENSURE_OR_GO_CLEANUP(session);
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
if (session->subsystem == kType_SSS_SE_A71CH) {
sss_a71ch_key_store_t *a71ch_keyStore = (sss_a71ch_key_store_t *)keyStore;
memset(a71ch_keyStore, 0, sizeof(*a71ch_keyStore));
keyStore->session = session;
ret = sscp_a71ch_init((sscp_a71ch_context_t *)&session->mem_sscp_ctx, a71ch_keyStore);
if (ret == kStatus_SSS_Success) {
session->sscp_context = &session->mem_sscp_ctx;
}
}
#endif
#if SSS_HAVE_A71CL || SSS_HAVE_SE050_L
if (session->subsystem == kType_SSS_SE_A71CL) {
sss_a71cl_key_store_t *a71cl_keyStore = (sss_a71cl_key_store_t *)keyStore;
memset(a71cl_keyStore, 0, sizeof(*a71cl_keyStore));
keyStore->session = session;
ret = sscp_a71cl_init((sscp_a71cl_context_t *)&session->mem_sscp_ctx, a71cl_keyStore);
if (ret == kStatus_SSS_Success) {
session->sscp_context = &session->mem_sscp_ctx;
}
}
#endif
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_allocate(sss_sscp_key_store_t *keyStore, uint32_t keyStoreId)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyStoreId;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_ALLOCATE_KEYSTORE, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_save(sss_sscp_key_store_t *keyStore)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(None, None, None, None, None, None);
SET_OP_0_KeyStore();
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SAVE_KEYSTORE, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_load(sss_sscp_key_store_t *keyStore)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyStore();
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_LOAD_KEYSTORE, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_set_key(sss_sscp_key_store_t *keyStore,
sss_sscp_object_t *keyObject,
const uint8_t *data,
size_t dataLen,
size_t keyBitLen,
void *options,
size_t optionsLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
if (keyObject->transientObject == NULL) {
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, None, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyObject->objectType;
op.params[1].value.b = keyObject->keyId;
op.params[2].memref.buffer = (void *)data;
op.params[2].memref.size = dataLen;
op.params[3].value.a = (uint32_t)keyBitLen;
op.params[3].value.b = keyObject->cipherType;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SET_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
}
else {
memcpy(keyObject->transientObject, data, dataLen);
keyObject->transientObjectLen = dataLen;
keyObject->transientObjectBitLen = dataLen * 8;
ret = kStatus_SSS_Success;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_generate_key(
sss_sscp_key_store_t *keyStore, sss_sscp_object_t *keyObject, size_t keyBitLen, void *options)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, None, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyObject->objectType;
op.params[1].value.b = keyObject->keyId;
op.params[2].value.a = (uint32_t)(keyBitLen / 8);
op.params[2].value.b = keyObject->cipherType;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_GENERATE_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_get_key(
sss_sscp_key_store_t *keyStore, sss_sscp_object_t *keyObject, uint8_t *data, size_t *dataLen, size_t *pKeyBitLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
if (keyObject->transientObject == NULL) {
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefOutput, ValueOutput, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyObject->objectType;
op.params[1].value.b = keyObject->keyId;
op.params[2].memref.buffer = data;
op.params[2].memref.size = *dataLen;
op.params[3].value.a = (uint32_t)(*dataLen);
op.params[3].value.b = keyObject->cipherType;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_GET_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
*dataLen = op.params[3].value.a;
*pKeyBitLen = op.params[3].value.b;
ret = kStatus_SSS_Success;
}
else {
*pKeyBitLen = 0;
ret = kStatus_SSS_Fail;
}
}
else {
if (*dataLen >= keyObject->transientObjectLen) {
memcpy(data, keyObject->transientObject, keyObject->transientObjectLen);
*pKeyBitLen = keyObject->transientObjectLen * 8;
*dataLen = keyObject->transientObjectLen;
ret = kStatus_SSS_Success;
}
else {
LOG_E("Error: dataLen > keyObject->transientObjectLen");
ret = kStatus_SSS_Fail;
}
}
return (sss_status_t)ret;
}
#if 0
/* To be reviewed: Purnank */
sss_status_t sss_sscp_key_store_get_key_fromoffset(sss_sscp_key_store_t *keyStore,
sss_sscp_object_t *keyObject,
uint8_t *data,
size_t *dataLen,
size_t *pKeyBitLen,
uint16_t offset)
{
sscp_status_t resSSCP = kStatus_SSCP_Success;
return (sss_status_t)ret;
}
#endif
sss_status_t sss_sscp_key_store_open_key(sss_sscp_key_store_t *keyStore, sss_sscp_object_t *keyObject)
{
uint32_t ret = kStatus_SSS_Fail;
/* TBU */
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_freeze_key(sss_sscp_key_store_t *keyStore, sss_sscp_object_t *keyObject)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyObject->objectType;
op.params[1].value.b = keyObject->keyId;
op.params[2].value.a = keyObject->cipherType;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_FREEZE_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_key_store_erase_key(sss_sscp_key_store_t *keyStore, sss_sscp_object_t *keyObject)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, None, None, None, None, None);
SET_OP_0_KeyStore();
op.params[1].value.a = keyObject->objectType;
op.params[1].value.b = keyObject->keyId;
op.params[2].value.a = keyObject->cipherType;
sscp_context_t *sscpCtx = keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_CMD_ERASE_KEY, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
void sss_sscp_key_store_context_free(sss_sscp_key_store_t *keyStore)
{
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
sss_a71ch_key_store_t *a71xx_keyStore = (sss_a71ch_key_store_t *)keyStore;
sscp_a71chkey_store_context_free(a71xx_keyStore);
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
sss_a71cl_key_store_t *a71xx_keyStore = (sss_a71cl_key_store_t *)keyStore;
#else
#error "No Security Subsystem Defined"
#endif
memset(a71xx_keyStore, 0, sizeof(*a71xx_keyStore));
}
/* End: sscp_keystore */
/* ************************************************************************** */
/* Functions : sss_sscp_asym */
/* ************************************************************************** */
sss_status_t sss_sscp_asymmetric_context_init(sss_sscp_asymmetric_t *context,
sss_sscp_session_t *session,
sss_sscp_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSS_Fail;
sscp_operation_t op = {0};
ENSURE_OR_GO_CLEANUP(context);
ENSURE_OR_GO_CLEANUP(keyObject);
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CH);
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CL);
#endif
memset(context, 0, sizeof(*context));
context->algorithm = algorithm;
context->mode = mode;
context->session = session;
context->keyObject = keyObject;
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, ValueInput, None, None, None);
SET_OP_0_Asymm();
op.params[1].value.a = context->algorithm;
op.params[1].value.b = context->mode;
op.params[2].value.a = context->keyObject->keyId;
op.params[3].value.a = context->sessionId;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_ASYMMETRIC_CTX_INIT, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
context->sessionId = op.params[3].value.a;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_asymmetric_encrypt(
sss_sscp_asymmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_Asymm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)srcData;
op.params[2].memref.size = srcLen;
op.params[3].memref.buffer = destData;
op.params[3].memref.size = *destLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_ASYMMETRIC_CMD_ENCRYPT, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
*destLen = op.params[3].memref.size;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_asymmetric_decrypt(
sss_sscp_asymmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_Asymm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)srcData;
op.params[2].memref.size = srcLen;
op.params[3].memref.buffer = destData;
op.params[3].memref.size = *destLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_ASYMMETRIC_CMD_DECRYPT, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
*destLen = op.params[2].memref.size;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_asymmetric_sign_digest(
sss_sscp_asymmetric_t *context, uint8_t *digest, size_t digestLen, uint8_t *signature, size_t *signatureLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_Asymm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = digest;
op.params[2].memref.size = digestLen;
op.params[3].memref.buffer = signature;
op.params[3].memref.size = *signatureLen;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_ASYMMETRIC_CMD_SIGN_DIGEST, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
*signatureLen = op.params[3].memref.size;
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_asymmetric_verify_digest(
sss_sscp_asymmetric_t *context, uint8_t *digest, size_t digestLen, uint8_t *signature, size_t signatureLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefInput, ValueOutput, None, None);
SET_OP_0_Asymm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = digest;
op.params[2].memref.size = digestLen;
op.params[3].memref.buffer = signature;
op.params[3].memref.size = signatureLen;
sscp_context_t *sscpCtx = context->keyObject->keyStore->session->sscp_context;
resSSCP = sscpCtx->invoke(sscpCtx, kSSCP_ASYMMETRIC_CMD_VERIFY_DIGEST, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
void sss_sscp_asymmetric_context_free(sss_sscp_asymmetric_t *context)
{
memset(context, 0, sizeof(*context));
}
/* End: sscp_asym */
/* ************************************************************************** */
/* Functions : sss_sscp_symm */
/* ************************************************************************** */
sss_status_t sss_sscp_symmetric_context_init(sss_sscp_symmetric_t *context,
sss_sscp_session_t *session,
sss_sscp_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSS_Fail;
sscp_operation_t op = {0};
ENSURE_OR_GO_CLEANUP(context);
ENSURE_OR_GO_CLEANUP(keyObject);
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CH);
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CL);
#elif
#error "No Security Subsystem Defined"
#endif
memset(context, 0, sizeof(*context));
context->algorithm = algorithm;
context->mode = mode;
context->session = session;
context->keyObject = keyObject;
op.paramTypes = SSCP_PARAMS(ValueInput, ValueInput, ValueOutput, None, None, None);
SET_OP_0_Symm();
op.params[1].value.a = context->algorithm;
op.params[1].value.b = context->mode;
op.params[2].value.a = context->keyObject->keyId;
op.params[3].value.a = context->sessionId;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_CTX_INIT, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
context->sessionId = op.params[3].value.a;
}
cleanup:
return (sss_status_t)ret;
}
sss_status_t sss_sscp_cipher_one_go(
sss_sscp_symmetric_t *context, uint8_t *iv, size_t ivLen, const uint8_t *srcData, uint8_t *destData, size_t dataLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefInput, MemrefOutput, None, None);
SET_OP_0_Symm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = iv;
op.params[2].memref.size = ivLen;
op.params[3].memref.buffer = (void *)srcData;
op.params[3].memref.size = dataLen;
op.params[4].memref.buffer = destData;
op.params[4].memref.size = dataLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_ONE_GO, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return ret;
}
sss_status_t sss_sscp_cipher_init(sss_sscp_symmetric_t *context, uint8_t *iv, size_t ivLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, None, None, None, None);
SET_OP_0_Symm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = iv;
op.params[2].memref.size = ivLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_INIT, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_cipher_update(
sss_sscp_symmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_Symm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)srcData;
op.params[2].memref.size = srcLen;
op.params[3].memref.buffer = destData;
op.params[3].memref.size = *destLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_UPDATE, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_cipher_finish(
sss_sscp_symmetric_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_Symm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)srcData;
op.params[2].memref.size = srcLen;
op.params[3].memref.buffer = destData;
op.params[3].memref.size = *destLen;
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_FINISH, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_cipher_crypt_ctr(sss_sscp_symmetric_t *context,
const uint8_t *srcData,
uint8_t *destData,
size_t size,
uint8_t *initialCounter,
uint8_t *lastEncryptedCounter,
size_t *szLeft)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, MemrefInOut, MemrefInOut, MemrefInOut);
SET_OP_0_Symm();
op.params[1].value.a = context->sessionId;
op.params[2].memref.buffer = (void *)(uintptr_t)srcData;
op.params[2].memref.size = size;
op.params[3].memref.buffer = destData;
op.params[3].memref.size = size;
op.params[4].memref.buffer = initialCounter;
op.params[4].memref.size = SSS_AES_BLOCK_SIZE;
op.params[5].memref.buffer = lastEncryptedCounter;
op.params[5].memref.size = SSS_AES_BLOCK_SIZE;
op.params[6].memref.buffer = szLeft;
op.params[6].memref.size = sizeof(*szLeft);
sscp_context_t *ctx = context->keyObject->keyStore->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_SYMM_CIPHER_CRYPT_CTR, &op, &ret);
if (resSSCP != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return kStatus_SSS_Success;
}
void sss_sscp_symmetric_context_free(sss_sscp_symmetric_t *context)
{
memset(context, 0, sizeof(*context));
}
/* End: sscp_symm */
/* ************************************************************************** */
/* Functions : sss_sscp_mac */
/* ************************************************************************** */
/* ************************************************************************** */
/* Functions : sss_sscp_aead */
/* ************************************************************************** */
sss_status_t sss_sscp_aead_context_init(sss_sscp_aead_t *context,
sss_sscp_session_t *session,
sss_sscp_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Fail;
/* TBU */
return retval;
}
sss_status_t sss_sscp_aead_one_go(sss_sscp_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)
{
SSCP_BUILD_ASSURE(sizeof(sss_aead_t) >= sizeof(sss_sscp_aead_t), _sss_sscp_aead_size);
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
/* set paramTypes for the tag[] buffer according to mode
* for encrypt (and authenticate) mode, the tag[] is output, written by invoked function,
* for decrypt (and verify) mode, the tag[] is input, to be verified by invoked function
*/
if (context->mode == kMode_SSS_Encrypt) {
op.paramTypes = SSCP_PARAMS(MemrefInput, MemrefOutput, MemrefInput, MemrefInput, MemrefOutput, None);
}
else {
op.paramTypes = SSCP_PARAMS(MemrefInput, MemrefOutput, MemrefInput, MemrefInput, MemrefInput, None);
}
op.params[0].context.ptr = context;
op.params[0].context.type = kSSCP_ParamContextType_SSS_Aead;
op.params[1].memref.buffer = (void *)(uintptr_t)srcData;
op.params[1].memref.size = size;
op.params[2].memref.buffer = destData;
op.params[2].memref.size = size;
op.params[3].memref.buffer = nonce;
op.params[3].memref.size = nonceLen;
op.params[4].memref.buffer = (void *)(uintptr_t)aad;
op.params[4].memref.size = aadLen;
op.params[5].memref.buffer = tag;
op.params[5].memref.size = *tagLen;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_AeadOneGo, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
if (context->mode == kMode_SSS_Encrypt) {
/* tagLen returns number of bytes written to tag */
*tagLen = op.params[5].memref.size;
}
return (sss_status_t)ret;
}
/* End: sscp_aead */
sss_status_t sss_sscp_aead_init(
sss_sscp_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;
/* TBU */
return retval;
}
sss_status_t sss_sscp_aead_update_aad(sss_sscp_aead_t *context, const uint8_t *aadData, size_t aadDataLen)
{
sss_status_t retval = kStatus_SSS_Fail;
/* TBU */
return retval;
}
sss_status_t sss_sscp_aead_update(
sss_sscp_aead_t *context, const uint8_t *srcData, size_t srcLen, uint8_t *destData, size_t *destLen)
{
sss_status_t retval = kStatus_SSS_Fail;
/* TBU */
return retval;
}
sss_status_t sss_sscp_aead_finish(sss_sscp_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;
/* TBU */
return retval;
}
void sss_sscp_aead_context_free(sss_sscp_aead_t *context)
{
;
}
/* End: sscp_aead */
sss_status_t sss_sscp_mac_context_init(sss_sscp_mac_t *context,
sss_sscp_session_t *session,
sss_sscp_object_t *keyObject,
sss_algorithm_t algorithm,
sss_mode_t mode)
{
uint32_t ret = kStatus_SSS_Fail;
ENSURE_OR_GO_CLEANUP(context);
ENSURE_OR_GO_CLEANUP(keyObject);
#if SSS_HAVE_A71CH || SSS_HAVE_A71CH_SIM
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CH);
#elif SSS_HAVE_A71CL || SSS_HAVE_SE050_L
ENSURE_OR_GO_CLEANUP(keyObject->keyStore->session->subsystem == kType_SSS_SE_A71CL);
#elif
#error "No Security Subsystem Defined"
#endif
memset(context, 0, sizeof(*context));
context->algorithm = algorithm;
context->mode = mode;
context->session = session;
context->keyObject = keyObject;
ret = kStatus_SSS_Success;
cleanup:
return (sss_status_t)ret;
}
void sss_sscp_mac_context_free(sss_sscp_mac_t *context)
{
;
}
/* End: sscp_mac */
/* ************************************************************************** */
/* Functions : sss_sscp_tunnel */
/* ************************************************************************** */
sss_status_t sss_sscp_tunnel(sss_sscp_tunnel_t *context,
uint8_t *data,
size_t dataLen,
sss_sscp_object_t *keyObjects,
uint32_t keyObjectCount,
uint32_t tunnelType)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
op.paramTypes = SSCP_PARAMS(MemrefInput, ContextReference, ValueInput, None, None, None);
SET_OP_0_Tunnel();
op.params[1].memref.buffer = data;
op.params[1].memref.size = dataLen;
op.params[2].context.ptr = keyObjects;
op.params[2].context.type = kSSCP_ParamContextType_SSS_Object;
op.params[3].value.a = keyObjectCount;
op.params[3].value.b = tunnelType;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_Tunnel, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
/* End: sscp_tunnel */
/* ************************************************************************** */
/* Functions : sss_sscp_mac */
/* ************************************************************************** */
sss_status_t sss_sscp_mac_one_go(
sss_sscp_mac_t *context, const uint8_t *message, size_t messageLen, uint8_t *mac, size_t *macLen)
{
SSCP_BUILD_ASSURE(sizeof(sss_mac_t) >= sizeof(sss_sscp_mac_t), _sss_sscp_mac_size);
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
/* if the caller gives NULL pointer to macLen, it is assumed that mac[] buffer is big enough to hold full
* mac */
size_t len = (macLen != NULL) ? *macLen : context->macFullLen;
/* if the *macLen cannot hold full mac (per algorithm spec) return error */
if (len < context->macFullLen) {
return kStatus_SSS_Fail;
}
op.paramTypes = SSCP_PARAMS(MemrefInput, MemrefOutput, None, None, None, None);
SET_OP_0_Mac();
op.params[1].memref.buffer = (void *)(uintptr_t)message;
op.params[1].memref.size = messageLen;
op.params[2].memref.buffer = mac;
op.params[2].memref.size = len;
op.params[3].value.a = context->keyObject->keyId;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_MacOneGo, &op, &ret);
if (status != kStatus_SSCP_Success) {
if (macLen) {
*macLen = 0;
}
return kStatus_SSS_Fail;
}
/* update the size member of kSSCP_ParamType_MemrefOutput param with the actual byte length written to output buffer
*/
if (macLen) {
*macLen = op.params[2].memref.size;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_mac_init(sss_sscp_mac_t *context)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
op.paramTypes = SSCP_PARAMS(None, None, None, None, None, None);
SET_OP_0_Mac();
op.params[1].value.a = context->keyObject->keyId;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_MacInit, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_mac_update(sss_sscp_mac_t *context, const uint8_t *message, size_t messageLen)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
op.paramTypes = SSCP_PARAMS(MemrefInput, None, None, None, None, None);
SET_OP_0_Mac();
op.params[1].value.a = context->keyObject->keyId;
op.params[2].memref.buffer = (void *)(uintptr_t)message;
op.params[2].memref.size = messageLen;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_MacUpdate, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_mac_finish(sss_sscp_mac_t *context, uint8_t *mac, size_t *macLen)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
/* if the caller gives NULL pointer to macLen, it is assumed that mac[] buffer is big enough to hold full
* mac */
size_t len = (macLen != NULL) ? *macLen : context->macFullLen;
/* if the *macLen cannot hold full mac (per algorithm spec) return error */
if (len < context->macFullLen) {
return kStatus_SSS_Fail;
}
op.paramTypes = SSCP_PARAMS(MemrefOutput, None, None, None, None, None);
SET_OP_0_Mac();
op.params[1].value.a = context->keyObject->keyId;
op.params[2].memref.buffer = mac;
op.params[2].memref.size = len;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_MacFinish, &op, &ret);
if (status != kStatus_SSCP_Success) {
if (macLen) {
*macLen = 0;
}
return kStatus_SSS_Fail;
}
/* the size member of kSSCP_ParamType_MemrefOutput param is updated with the actual byte length written to output
* buffer
*/
if (macLen) {
*macLen = op.params[2].memref.size;
}
return (sss_status_t)ret;
}
/* End: sscp_mac */
/* ************************************************************************** */
/* Functions : sss_sscp_digest */
/* ************************************************************************** */
sss_status_t sss_sscp_digest_context_init(
sss_sscp_digest_t *context, sss_sscp_session_t *session, sss_algorithm_t algorithm, sss_mode_t mode)
{
sss_status_t retval = kStatus_SSS_Fail;
ENSURE_OR_GO_CLEANUP(context);
context->session = session;
context->algorithm = algorithm;
context->mode = mode;
retval = kStatus_SSS_Success;
cleanup:
return retval;
}
sss_status_t sss_sscp_digest_one_go(
sss_sscp_digest_t *context, const uint8_t *message, size_t messageLen, uint8_t *digest, size_t *digestLen)
{
SSCP_BUILD_ASSURE(sizeof(sss_digest_t) >= sizeof(sss_sscp_digest_t), _sss_sscp_digest_size);
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
/* if the caller gives NULL pointer to digestLen, it is assumed that digest[] buffer is big enough to hold full
* digest */
size_t len = (digestLen != NULL) ? *digestLen : context->digestFullLen;
/* if the *digestLen cannot hold full digest (per algorithm spec) return error */
if (len < context->digestFullLen) {
return kStatus_SSS_Fail;
}
op.paramTypes = SSCP_PARAMS(MemrefInput, MemrefOutput, None, None, None, None);
SET_OP_0_Digest();
op.params[1].memref.buffer = (void *)(uintptr_t)message;
op.params[1].memref.size = messageLen;
op.params[2].memref.buffer = digest;
op.params[2].memref.size = len;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_DigestOneGo, &op, &ret);
if (status != kStatus_SSCP_Success) {
if (digestLen) {
*digestLen = 0;
}
return kStatus_SSS_Fail;
}
/* update the size member of kSSCP_ParamType_MemrefOutput param with the actual byte length written to output buffer
*/
if (digestLen) {
*digestLen = op.params[2].memref.size;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_digest_init(sss_sscp_digest_t *context)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
op.paramTypes = SSCP_PARAMS(None, None, None, None, None, None);
SET_OP_0_Digest();
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_DigestInit, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_digest_update(sss_sscp_digest_t *context, const uint8_t *message, size_t messageLen)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
op.paramTypes = SSCP_PARAMS(MemrefInput, None, None, None, None, None);
SET_OP_0_Digest();
op.params[1].memref.buffer = (void *)(uintptr_t)message;
op.params[1].memref.size = messageLen;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_DigestUpdate, &op, &ret);
if (status != kStatus_SSCP_Success) {
return kStatus_SSS_Fail;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_digest_finish(sss_sscp_digest_t *context, uint8_t *digest, size_t *digestLen)
{
sscp_operation_t op = {0};
sscp_status_t status = kStatus_SSCP_Fail;
uint32_t ret = 0;
/* if the caller gives NULL pointer to digestLen, it is assumed that digest[] buffer is big enough to hold full
* digest */
size_t len = (digestLen != NULL) ? *digestLen : context->digestFullLen;
/* if the *digestLen cannot hold full digest (per algorithm spec) return error */
if (len < context->digestFullLen) {
return kStatus_SSS_Fail;
}
op.paramTypes = SSCP_PARAMS(MemrefOutput, None, None, None, None, None);
SET_OP_0_Digest();
op.params[1].memref.buffer = digest;
op.params[1].memref.size = len;
sscp_context_t *sscpCtx = context->session->sscp_context;
status = sscpCtx->invoke(sscpCtx, kSSCP_CMD_SSS_DigestFinish, &op, &ret);
if (status != kStatus_SSCP_Success) {
if (digestLen) {
*digestLen = 0;
}
return kStatus_SSS_Fail;
}
/* the size member of kSSCP_ParamType_MemrefOutput param is updated with the actual byte length written to output
* buffer
*/
if (digestLen) {
*digestLen = op.params[1].memref.size;
}
return (sss_status_t)ret;
}
void sss_sscp_digest_context_free(sss_sscp_digest_t *context)
{
memset(context, 0, sizeof(*context));
}
/* End: sscp_digest */
/* ************************************************************************** */
/* Functions : sss_sscp_rng */
/* ************************************************************************** */
sss_status_t sss_sscp_rng_context_init(sss_sscp_rng_context_t *context, sss_sscp_session_t *session)
{
sss_status_t retval = kStatus_SSS_Fail;
ENSURE_OR_GO_CLEANUP(context);
context->session = session;
retval = kStatus_SSS_Success;
cleanup:
return retval;
}
sss_status_t sss_sscp_rng_get_random(sss_sscp_rng_context_t *context, uint8_t *random_data, size_t dataLen)
{
sscp_status_t resSSCP = kStatus_SSCP_Fail;
uint32_t ret = kStatus_SSCP_Fail;
size_t chunk = 0;
size_t offset = 0;
sscp_operation_t op = {0};
op.paramTypes = SSCP_PARAMS(ValueInput, MemrefInput, MemrefOutput, None, None, None);
SET_OP_0_RandGen();
while (dataLen > 0) {
if (dataLen > 128) {
chunk = 128;
}
else {
chunk = dataLen;
}
op.params[1].value.a = context->session->sessionId;
op.params[2].memref.buffer = (void *)(random_data + offset);
op.params[2].memref.size = chunk;
sscp_context_t *ctx = context->session->sscp_context;
resSSCP = ctx->invoke(ctx, kSSCP_GEN_RANDOM_NUM, &op, &ret);
if ((resSSCP == kStatus_SSCP_Success) && (ret == kStatus_SSS_Success)) {
ret = kStatus_SSS_Success;
}
else {
ret = kStatus_SSS_Fail;
break;
}
offset += chunk;
dataLen -= chunk;
}
return (sss_status_t)ret;
}
sss_status_t sss_sscp_rng_context_free(sss_sscp_rng_context_t *context)
{
sss_status_t retval = kStatus_SSS_Success;
memset(context, 0, sizeof(*context));
return retval;
}
/* End: sscp_rng */
#endif /* SSS_HAVE_SSCP */