【简介】
S32K 的HSE core 被设计成芯片的安全相关的核心,相关加密算法对应的密钥管理也是在HSE中尽心管理的。我们今天看下HSE 的密钥管理都有哪些服务。HSE 的KEY 在配置前需要先进行格式化,以下代码是S32K Secure Boot 代码中对对key 进行格式的的代码。
hseSrvResponse_t HseFrm_Key_FormatCatalogs(const hseKeyGroupCfgEntry_t* pNvmCatalog, const hseKeyGroupCfgEntry_t* pRamCatalog)
{
hseSrvResponse_t hseSrvResponse = 0xFFFFFFFF;
hseSrvDescriptor_t hseSrvDesc ;
hseSrvDescriptor_t* pHseSrvDesc = &hseSrvDesc;
hseFormatKeyCatalogsSrv_t* pFormatKeyCatalogsReq = &pHseSrvDesc->hseSrv.formatKeyCatalogsReq;
MEMSET(pHseSrvDesc, 0, sizeof(hseSrvDescriptor_t));
//Use the same default catalog configurations to re-format the NVM and RAM catalogs
pHseSrvDesc->srvId = HSE_SRV_ID_FORMAT_KEY_CATALOGS;
pFormatKeyCatalogsReq->pNvmKeyCatalogCfg= (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)pNvmCatalog);
pFormatKeyCatalogsReq->pRamKeyCatalogCfg= (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)pRamCatalog);
hseSrvResponse = gHsePort_HseIf.reqApi( pHseSrvDesc , NULL );
return hseSrvResponse;
}从上述代码可知格式化处理实际上是调用的HSE 的HSE_SRV_ID_FORMAT_KEY_CATALOGS 服务来根据传入Key 的信息进行格式化。
以下是HSE 接口文档对该服务的描述。


根据上述的描述,格式化key 服务需要用户构造NVM/RAM key 的格式化结构,将该结构传递给HSE来进行格式化,对应的成员结构如下:
/** @brief The entry of the Key Catalog Configuration
* @details The size of a key slot is computed internally based on keytype and maxKeyBitLen.
* @note A key group (catalog entry) contains keys that have the same key type and the keybitLen <= maxKeyBitLen.
* */
typedef struct
{
hseMuMask_t muMask; /**< @brief Specifies the MU Instance(s) for the key group. A key group can belong to one ore more MUs. */
hseKeyGroupOwner_t groupOwner; /**< @brief Specifies the key group owner. */
hseKeyType_t keyType; /**< @brief The key type (see #hseKeyType_t). */
uint8_t numOfKeySlots; /**< @brief The number of key slots. */
uint16_t maxKeyBitLen; /**< @brief The maximum length of the key (in bits). All stored keys have keyBitLen <= maxKeyBitLen. */
uint8_t hseReserved[2]; /**< @brief HSE reserved */
} hseKeyGroupCfgEntry_t; 
格式化key 完成后就可以使用HSE的服务来往slot中导入key了,以下代码是导入key对应的代码。
/*
NVM keys:
In empty slots, an encrypted key can be imported only authenticated, and a plain key
can be imported with/without authentication (public keys must be imported in plain).
In non-empty slots, NVM keys can be imported(overwritten) in plain/encrypted,
but must authenticated
*/
hseSrvResponse_t HseMid_KeyMgmt_ImportKey(
hseKeyHandle_t keyHandle,
hseKeyInfo_t* pKeyElemInfo,
hseMid_ImportKeyVal_t* pKeyVal,
hseKeyFormat_t* pKeyFormat,
hseFrm_KeyCipher_t* pCipher, hseFrm_KeyAuth_t* pAuth,
boolean needErase, boolean keepCounter
)
{
hseSrvResponse_t hseSrvResponse = 0xFFFFFFFF;
hseKeyInfo_t* pKeyInfo = &gsImportKeyInfo;
_TRY_START;
/* keyInfo copy to non-cacheable */
MEMCPY( pKeyInfo , pKeyElemInfo, sizeof(hseKeyInfo_t) );
hseSrvResponse = HseMid_KeyMgmt_EraseOrKeepKeyCounter(keyHandle, needErase,keepCounter, &(pKeyInfo->keyCounter), 1 );
_THROW_DIFF( HSE_SRV_RSP_OK , hseSrvResponse );
hseSrvResponse = HseFrm_Key_Import(keyHandle, pKeyInfo, (hseFrm_Key_t*)pKeyVal, NULL, pKeyFormat, pCipher, pAuth);
_THROW_DIFF( HSE_SRV_RSP_OK , hseSrvResponse );
_TRY_END;
return hseSrvResponse ;
}
hseSrvResponse_t HseFrm_Key_Import
(
hseKeyHandle_t targetKeyHandle,
hseKeyInfo_t* pKeyInfo,
hseFrm_Key_t* pKey,
hseFrm_KeyLen_t* pKeyLen,
hseKeyFormat_t* pKeyFormat,
hseFrm_KeyCipher_t *pCipher,
hseFrm_KeyAuth_t *pAuth
)
{
hseSrvResponse_t hseSrvResponse = 0xFFFFFFFF;
hseSrvDescriptor_t hseSrvDesc ;
hseSrvDescriptor_t* pHseSrvDesc = &hseSrvDesc;
hseImportKeySrv_t* pImportKeyReq = &pHseSrvDesc->hseSrv.importKeyReq;
MEMSET(pHseSrvDesc, 0, sizeof(hseSrvDescriptor_t));
pHseSrvDesc->srvId = HSE_SRV_ID_IMPORT_KEY;
pImportKeyReq->targetKeyHandle = targetKeyHandle;
pImportKeyReq->pKeyInfo = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKeyInfo));
pImportKeyReq->pKey[0] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKey->pKey[0]));
pImportKeyReq->pKey[1] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKey->pKey[1]));
pImportKeyReq->pKey[2] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKey->pKey[2]));
if( NULL != pKeyFormat )
{
MEMCPY( &(pImportKeyReq->keyFormat), pKeyFormat, sizeof(hseKeyFormat_t) );
}
if( NULL != pKeyLen )
{
pImportKeyReq->keyLen[0] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKeyLen->keyLen[0]));
pImportKeyReq->keyLen[1] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKeyLen->keyLen[1]));
pImportKeyReq->keyLen[2] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)(pKeyLen->keyLen[2]));
}
else
{
HseFrm_Key_SetKeyLen( (hseKeyInfo_t*)pKeyInfo, (uint16_t*)( &(pImportKeyReq->keyLen[0]) ), &(pImportKeyReq->keyFormat) );
}
/* plain */
pImportKeyReq->cipher.cipherKeyHandle = HSE_INVALID_KEY_HANDLE;
pImportKeyReq->keyContainer.authKeyHandle = HSE_INVALID_KEY_HANDLE;
/* key import with/without encrypted/authenticated */
/* encrypted/authenticated */
if( NULL != pCipher)
{
/* encrypted */
pImportKeyReq->cipher.cipherKeyHandle = pCipher->keyHandle;
pImportKeyReq->cipher.cipherScheme = pCipher->cipherScheme;
}
if( NULL != pAuth)
{
/* authenticated */
pImportKeyReq->keyContainer.pKeyContainer = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)pAuth->pKeyContainer);
pImportKeyReq->keyContainer.keyContainerLen = pAuth->keyContainerLen;
pImportKeyReq->keyContainer.authKeyHandle = pAuth->authKeyHandle;
pImportKeyReq->keyContainer.authScheme = pAuth->authScheme;
pImportKeyReq->keyContainer.authLen[0] = (uint16_t) *(pAuth->pAuthLen[0]);
pImportKeyReq->keyContainer.authLen[1] = (uint16_t) *(pAuth->pAuthLen[1]);
pImportKeyReq->keyContainer.pAuth[0] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)pAuth->pAuth[0]);
pImportKeyReq->keyContainer.pAuth[1] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)pAuth->pAuth[1]);
/* When a key container is defined by the host, it must be ensured that the key values pointed by pKey[] are
within the key container, that means (for i between 0 and 2) addresses pKey[i] and (pKey[i] + *pKeyLen[i])
must be between keyContainer.pKeyContainer and (keyContainer.pKeyContainer +
keyContainer.keyContainerLen - 1) */
/* key import with auth, pKeyInfo and pKey point to pKeyContainer */
pImportKeyReq->pKeyInfo = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)( pAuth->pKeyContainer + 0 )) ;
pImportKeyReq->pKey[0] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)( pAuth->pKeyContainer + sizeof(hseKeyInfo_t) )) ;
pImportKeyReq->pKey[1] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)( pAuth->pKeyContainer + sizeof(hseKeyInfo_t) + pImportKeyReq->keyLen[0] )) ;
pImportKeyReq->pKey[2] = (HOST_ADDR)hsePort_Mem_AddrHandler((HOST_ADDR)( pAuth->pKeyContainer + sizeof(hseKeyInfo_t) + pImportKeyReq->keyLen[0] + pImportKeyReq->keyLen[1] )) ;
}
/* encrypted and authenticated */
hseSrvResponse = gHsePort_HseIf.reqApi( pHseSrvDesc , NULL );
return hseSrvResponse;
}对应的 HSE_SRV_ID_IMPORT_KEY 服务可以导入key.


通过上述服务就可以通知HSE core 来格式化处理KEY数据。
我要赚赏金
