void se_test(void)
{
sss_status_t st = ex_sss_entry(PCONTEXT);
if (st != kStatus_SSS_Success) {
ESP_LOGE("SE-GCM", "ex_sss_entry failed (0x%X)", st);
return;
}
log_se_applet_version(&PCONTEXT->session);
se_delete_object(PCONTEXT, USER_TEMPLATE_AES_KEY_ID);
se_list_ids(PCONTEXT, kSE05x_SecObjTyp_AES_KEY);
vTaskDelay(pdMS_TO_TICKS(500));
sss_status_t status = kStatus_SSS_Success;
sss_algorithm_t algorithm;
sss_mode_t mode;
/* clang-format off */
uint8_t srcData[16] = { 0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x31 }; /*HELLOHELLOHELLO1*/
uint8_t keystring[16] = { 0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x48 ,0x45 ,0x4c ,0x4c ,0x4f ,0x31 }; /*HELLOHELLOHELLO1*/
uint8_t destData[16] = {0,};
size_t destDataLen = sizeof(destData);
uint8_t iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x15, 0x71, 0x99, 0x32, 0xd3, 0x56, 0x90};
size_t ivlen = sizeof(iv);
uint32_t keyId = USER_TEMPLATE_AES_KEY_ID;
sss_key_part_t keyPart;
sss_cipher_type_t cipherType;
size_t keyByteLenMax = 16;
sss_object_t key = { 0 };
sss_aead_t ctx_aead_encrypt = { 0 };
size_t TAG_SIZE = 16;
uint8_t tag[TAG_SIZE];
uint8_t *aad =(uint8_t*)"Extra authentication data";
size_t aadSize = strlen((char*)aad);
// === 1) Symmetric Key Policy: GCM 허용 + 외부 IV 금지 ===
static const sss_policy_sym_key_u gcm_symm = {
.can_Sign = 0,
.can_Verify = 0,
.can_Encrypt = 1, // GCM Encrypt 허용
.can_Decrypt = 1, // GCM Decrypt 허용
.can_Import_Export = 0, // 필요 시 1
.forbid_Derived_Output = 0,
.can_TLS_KDF = 0,
.allow_kdf_ext_rnd = 0,
.can_TLS_PMS_KD = 0,
.can_HKDF = 0,
.can_PBKDF = 0,
.can_Wrap = 0,
.can_Desfire_Auth = 0,
.can_Desfire_Dump = 0,
.can_Desfire_KD = 0,
.forbid_external_iv = 1, // ★ AN13904: 외부 IV 금지
.can_usage_hmac_pepper = 0,
.can_KA = 0,
.can_KD = 0,
.can_Write = 0, // (공통 정책에서 R/W/Delete 처리)
.can_Gen = 0,
};
// === 2) Common Policy: Read/Write/Delete 허용 + Secure Messaging 강제 ===
static const sss_policy_common_u common = {
.forbid_All = 0,
.can_Read = 1, // 읽기 허용
.can_Write = 1, // 쓰기 허용
.can_Delete = 1, // 삭제 허용
.req_Sm = 1, // ★ SCP03 등 보호채널(암호/무결성) 강제
.req_pcr_val = 0,
};
// === 3) Policy Wrapper ===
static const sss_policy_u pol_sym = {
.type = KPolicy_Sym_Key,
.auth_obj_id = 0,
.policy.symmkey = gcm_symm,
};
static const sss_policy_u pol_common = {
.type = KPolicy_Common,
.auth_obj_id = 0,
.policy.common = common,
};
// === 4) Policy Array (두 정책 동시 적용) ===
static const sss_policy_t key_policy = {
.policies = { &pol_sym, &pol_common },
.nPolicies = 2,
};
algorithm = kAlgorithm_SSS_AES_GCM;
keyPart = kSSS_KeyPart_Default;
cipherType = kSSS_CipherType_AES;
mode = kMode_SSS_Encrypt;
/* doc:start ex_sss_symmetric-allocate-key */
/* Pre-requisite for encryption Part*/
ENSURE_OR_GO_CLEANUP(kType_SSS_SE_SE05x == ((PCONTEXT)->session).subsystem);
status = sss_key_object_init(&key, &(PCONTEXT)->ks);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_object_allocate_handle(&key, keyId, keyPart, cipherType, keyByteLenMax, kKeyObject_Mode_Persistent);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
// status = sss_key_store_set_key(&(PCONTEXT)->ks, &key, keystring, sizeof(keystring), sizeof(keystring) * 8, NULL, 0);
status = sss_key_store_set_key(&(PCONTEXT)->ks, &key, keystring, sizeof(keystring), sizeof(keystring) * 8, &key_policy, sizeof(key_policy));
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
/* doc:end ex_sss_symmetric-allocate-key */
se_list_ids(PCONTEXT, kSE05x_SecObjTyp_AES_KEY);
se_dump_free_memory(PCONTEXT);
/* doc:start ex_sss_aead-encrypt */
status = sss_aead_context_init(&ctx_aead_encrypt, &(PCONTEXT)->session, &key, algorithm, mode);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_I("Do Encryption");
LOG_MAU8_I("iv", iv, ivlen);
LOG_MAU8_I("srcData", srcData, sizeof(srcData));
/*Do Encryption*/
status = sss_aead_one_go(&ctx_aead_encrypt,srcData,destData, destDataLen, iv, ivlen, aad, aadSize, tag, &TAG_SIZE);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
/* doc:end ex_sss_aead-encrypt */
LOG_MAU8_I("encrypted data", destData, destDataLen);
LOG_I("Encryption successful !!!");
cleanup:
ex_sss_close((PCONTEXT));
}
static sss_status_t select_applet(ex_sss_boot_ctx_t *pCtx)
{
sss_session_t *pSession = &pCtx->session;
pCtx->se05x_open_ctx.skip_select_applet = 0;
pCtx->se05x_open_ctx.connType = kType_SE_Conn_Type_T1oI2C;
sss_status_t status = sss_session_open(pSession, kType_SSS_SE_SE05x, 0, kSSS_ConnectionType_Encrypted, &pCtx->se05x_open_ctx);
if (status == kStatus_SSS_Success) {
LOG_I("Applet selection successful!");
}
else {
LOG_E("Applet selection failed!");
}
status = sss_key_store_context_init(&pCtx->ks, pSession);
if (kStatus_SSS_Success != status) { LOG_E("SE keystore init fail (0x%X)", status);}
status = sss_key_store_allocate(&pCtx->ks, 1U);
if (kStatus_SSS_Success != status) { LOG_E("SE keystore alloc fail (0x%X)", status);}
return status;
}
static sss_status_t test_random(ex_sss_boot_ctx_t *pCtx)
{
sss_rng_context_t rng;
uint8_t rndData[256] = {0};
sss_status_t status = sss_rng_context_init(&rng, &pCtx->session);
ENSURE_OR_GO_CLEANUP(kStatus_SSS_Success == status);
status = sss_rng_get_random(&rng, rndData, 32);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_rng_context_free(&rng);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
cleanup:
return status;
}
sss_status_t s_alloc_Scp03key_Host(sss_object_t *keyObject, sss_key_store_t *pKs, uint32_t keyId)
{
sss_status_t status = kStatus_SSS_Fail;
status = sss_key_object_init(keyObject, pKs);
if (status != kStatus_SSS_Success) {
return status;
}
status = sss_key_object_allocate_handle(keyObject,
keyId,
kSSS_KeyPart_Default,
kSSS_CipherType_AES,
SCP03_MAX_AUTH_KEY_SIZE,
kKeyObject_Mode_Transient);
return status;
}
sss_status_t s_platform_prepare_host(sss_session_t *pHostSession,
sss_key_store_t *pHostKs,
SE_Connect_Ctx_t *se05x_open_ctx,
uint8_t *ENC_KEY,
uint8_t *MAC_KEY,
uint8_t *DEK_KEY,
size_t key_length)
{
sss_status_t status = kStatus_SSS_Fail;
NXSCP03_StaticCtx_t *pStatic_ctx = se05x_open_ctx->auth.ctx.scp03.pStatic_ctx;
NXSCP03_DynCtx_t *pDyn_ctx = se05x_open_ctx->auth.ctx.scp03.pDyn_ctx;
pStatic_ctx->keyVerNo = PF_KEY_VERSION_NO;
/* Init Allocate ENC Static Key */
status = s_alloc_Scp03key_Host(&pStatic_ctx->Enc, pHostKs, __LINE__);
if (status != kStatus_SSS_Success) {
return status;
}
/* Set ENC Static Key */
status = sss_key_store_set_key(pHostKs, &pStatic_ctx->Enc, ENC_KEY, key_length, key_length * 8, NULL, 0);
if (status != kStatus_SSS_Success) {
return status;
}
/* Init Allocate MAC Static Key */
status = s_alloc_Scp03key_Host(&pStatic_ctx->Mac, pHostKs, __LINE__);
if (status != kStatus_SSS_Success) {
return status;
}
/* Set MAC Static Key */
status = sss_key_store_set_key(pHostKs, &pStatic_ctx->Mac, MAC_KEY, key_length, key_length * 8, NULL, 0);
if (status != kStatus_SSS_Success) {
return status;
}
/* Init Allocate DEK Static Key */
status = s_alloc_Scp03key_Host(&pStatic_ctx->Dek, pHostKs, __LINE__);
if (status != kStatus_SSS_Success) {
return status;
}
/* Set DEK Static Key */
status = sss_key_store_set_key(pHostKs, &pStatic_ctx->Dek, DEK_KEY, key_length, key_length * 8, NULL, 0);
if (status != kStatus_SSS_Success) {
return status;
}
/* Init Allocate ENC Session Key */
status = s_alloc_Scp03key_Host(&pDyn_ctx->Enc, pHostKs, __LINE__);
if (status != kStatus_SSS_Success) {
return status;
}
/* Init Allocate MAC Session Key */
status = s_alloc_Scp03key_Host(&pDyn_ctx->Mac, pHostKs, __LINE__);
if (status != kStatus_SSS_Success) {
return status;
}
/* Init Allocate DEK Session Key */
status = s_alloc_Scp03key_Host(&pDyn_ctx->Rmac, pHostKs, __LINE__);
return status;
}
sss_status_t ex_sss_entry(ex_sss_boot_ctx_t *pCtx)
{
/** Prepare Host for SCP03 connection, KCs will be set in ex_sss_entry **/
SE05x_Connect_Ctx_t *pConnectCtx = &pCtx->se05x_open_ctx;
// Hardcode the connection to T1oI2C
pConnectCtx->connType = kType_SE_Conn_Type_T1oI2C;
// Auth type is Platform SCP03
pConnectCtx->auth.authType = kSSS_AuthType_SCP03;
pConnectCtx->auth.ctx.scp03.pStatic_ctx = &pCtx->ex_se05x_auth.scp03.ex_static;
pConnectCtx->auth.ctx.scp03.pDyn_ctx = &pCtx->ex_se05x_auth.scp03.ex_dyn;
pConnectCtx->auth.ctx.scp03.pStatic_ctx->key_len = AUTH_KEY_SIZE;
sss_status_t status = sss_host_session_open(&pCtx->host_session, kType_SSS_mbedTLS, 0, kSSS_ConnectionType_Plain, NULL);
if (kStatus_SSS_Success != status) {
LOG_E("Failed to open Host Session");
goto cleanup;
}
status = sss_host_key_store_context_init(&pCtx->host_ks, &pCtx->host_session);
if (kStatus_SSS_Success != status) {
LOG_E("Host: sss_key_store_context_init failed");
goto cleanup;
}
status = sss_host_key_store_allocate(&pCtx->host_ks, __LINE__);
if (kStatus_SSS_Success != status) {
LOG_E("Host: sss_key_store_allocate failed");
goto cleanup;
}
status = s_platform_prepare_host(&pCtx->host_session,
&pCtx->host_ks,
&pCtx->se05x_open_ctx,
SCP03_KEY_ENC,
SCP03_KEY_MAC,
SCP03_KEY_DEK,
AUTH_KEY_SIZE);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
/* Open the SCP03 session with the applet selected */
status = select_applet(pCtx);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
/* Test RNG */
// status = test_random(pCtx);
// ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
// LOG_I("Random test was successful from secure application");
cleanup:
return status;
}