10.1. A71CH and SSS API¶
10.1.1. Introduction¶
The Plug&Trust Middleware provides support for the A71CH secure element through the SSS API. The full scope of the A71CH legacy API or the HLSE API is not covered by the SSS API. For use cases where this applies it’s possible to use both SSS and A71CH API’s (Mixing SSS API and A71CH API).
The A71CH support as included in the Plug&Trust Middleware, is derived from the
A71CH Host Software package
as available on www.nxp.com/a71ch.
The hostlib
directory contains refactored code that was previously published on www.nxp.com/a71ch.
This Plug&Trust Middleware provides the following additional functionality related to the A71CH:
Compatibility with OpenSSL 1.1
Support for the SSS API
Cloud demos using SSS API
OpenSSL Engine using SSS API
The following - as previously contained in the A71CH Host Software package
-
is no longer supported:
Cloud demos using A71CH API (replaced by SSS API based cloud demos)
The SW build system is based upon cmake.
10.1.2. A71CH API to SSS API mapping¶
The following table provides an overview of the A71CH API’s that can be replaced by SSS API’s. As the usage of the SSS API is conceptually different from the A71CH API, there is no one-to-one replacement of API calls. Please consult SSS APIs for an introduction on using the SSS API and the applicable examples in Section 5.2.1 SSS API Examples.
The SSS Session concept - as applicable to A71CH - is restricted to establishing a connection between Host and Secure Element. Establishing an SCP03 session is orthogonal to the Session concept.
SSS specific policies are not applicable to A71CH.
|
|
|
a71ch_crypto_derive |
||
A71_HkdfExpandSymKey |
YES |
sss_derive_key_* |
A71_HkdfSymKey |
YES |
sss_derive_key_* |
A71_PskDeriveMasterSecret |
NO |
|
A71_EcdhPskDeriveMasterSecret |
NO |
|
A71_GetHmacSha256 |
YES |
sss_mac_* |
A71_HmacSha256Init |
YES |
sss_mac_* |
A71_HmacSha256Update |
YES |
sss_mac_* |
A71_HmacSha256Final |
YES |
sss_mac_* |
a71ch_crypto_ecc |
||
A71_GenerateEccKeyPair |
YES |
sss_key_store_generate_key |
A71_GenerateEccKeyPairWithChallenge |
NO |
|
A71_GenerateEccKeyPairWithCode |
NO |
|
A71_EccSign |
YES |
sss_asymmetric_sign_digest |
A71_EccNormalizedAsnSign |
NO |
|
A71_EccRestrictedSign |
NO |
|
A71_EccVerify |
YES |
sss_asymmetric_verify_digest |
A71_EcdhGetSharedSecret |
YES |
sss_derive_key_* |
a71ch_module |
||
A71_GetCredentialInfo |
NO |
|
A71_GetModuleInfo |
NO |
|
A71_GetUniqueID |
YES |
sss_session_prop_get_au8 |
A71_GetCertUid |
YES |
sss_session_prop_get_au9 |
A71_GetUnlockChallenge |
NO |
|
A71_GetKeyPairChallenge |
NO |
|
A71_GetPublicKeyChallenge |
NO |
|
A71_GetRandom |
YES |
sss_rng_get_random |
A71_CreateClientHelloRandom |
NO |
|
A71_GetRestrictedKeyPairInfo |
NO |
|
A71_GetSha256 |
YES |
sss_digest_one_go |
A71_Sha256Init/Update/Final |
YES |
sss_digest_* |
A71_InjectLock |
NO |
|
A71_LockModule |
NO |
|
A71_UnlockModule |
NO |
|
A71_SetTlsLabel |
NO |
|
A71_EccVerifyWithKey |
NO |
|
a71ch_sst |
||
A71_Erase_*_WithChallenge |
NO |
|
A71_Erase_*_WithCode |
NO |
|
A71_EraseEccKeyPair |
YES |
sss_key_store_erase_key |
A71_EraseEccPublicKey |
YES |
sss_key_store_erase_key |
A71_EraseSymKey |
NO |
|
A71_Freeze_*_WithChallenge |
NO |
|
A71_Freeze_*_WithCode |
NO |
|
A71_FreezeEccKeyPair |
YES |
sss_key_store_freeze_key |
A71_FreezeEccPublicKey |
YES |
sss_key_store_freeze_key |
A71_FreezeGpData |
NO |
|
A71_FreezeSymKey |
NO |
|
A71_GetCounter |
NO |
|
A71_GetEccKeyPairUsage |
NO |
|
A71_GetEccPublicKey |
YES |
sss_key_store_get_key |
A71_GetGpData |
NO |
|
A71_GetPublicKeyEccKeyPair |
YES |
sss_key_store_get_key |
A71_IncrementCounter |
NO |
|
A71_SetConfigKey |
NO |
|
A71_SetCounter |
NO |
|
A71_SetEccKeyPair |
YES |
sss_key_store_set_key |
A71_SetEccPublicKey |
YES |
sss_key_store_set_key |
A71_SetGpData |
NO |
|
A71_SetGpDataWithLockCheck |
NO |
|
A71_SetRfc3394WrappedAesKey |
NO |
|
A71_SetRfc3394WrappedConfigKey |
NO |
|
A71_SetSymKey |
YES |
sss_key_store_set_key |
HLSE |
||
HLSE_GetObjectAttribute |
||
HLSE_SetObjectAttribute |
||
HLSE_EraseObject |
||
HLSE_CreateObject |
10.1.3. Mixing SSS API and A71CH API¶
The Plug&Trust Middleware contains two examples illustrating how to use both the SSS API and the A71CH API from the same application.
10.1.3.1. ECC Example¶
The example uses the SSS API to sign and verify the digest. The example is available at .../simw-top/demos/a71ch/ex_a71ch_sss_ecc.c
.
status = sss_asymmetric_context_init(&ctx_asymm, &pCtx->session, &keyPair, kAlgorithm_SSS_SHA256, kMode_SSS_Sign);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
signatureLen = sizeof(signature);
/* Do Signing */
LOG_I("Do Signing");
LOG_MAU8_I("digest", digest, digestLen);
status = sss_asymmetric_sign_digest(&ctx_asymm, digest, digestLen, signature, &signatureLen);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_MAU8_I("signature", signature, signatureLen);
LOG_I("Signing Successful !!!");
sss_asymmetric_context_free(&ctx_asymm);
Next the example uses an A71CH API (A71_GetPublicKeyEccKeyPair) to retrieve the public key from the A71CH. The A71CH specific key index is retrieved from the SSS object matching the key pair.
/* Access the A71CH with the (legacy) Host API */
SST_Index_t keyIdx = (((sss_sscp_object_t *)&keyPair)->slotId) & 0x0F;
U8 pubEccKeyScratch[128];
U16 pubEccKeyScratchLen = 0;
LOG_I("A71_GetPublicKeyEccKeyPair(0x%02x)", keyIdx);
pubEccKeyScratchLen = sizeof(pubEccKeyScratch);
sw = A71_GetPublicKeyEccKeyPair(keyIdx, pubEccKeyScratch, &pubEccKeyScratchLen);
status = ((sw == SW_OK) ? kStatus_SSS_Success : kStatus_SSS_Fail);
10.1.3.2. AES key wrapping Example¶
The example uses the SSS API to set the AES key and the A71CH API to set the same AES key which is wrapped.
Further to verify if the wrapped key is injected properly, a hkdf key is derived using both AES keys.
The example is available at .../simw-top/demos/a71ch/ex_a71ch_sss_aes_wrap_key
.
Injecting wrapped AES key starts with setting AES key which is used as KEK,
status = sss_key_object_init(&aesObj1, &pCtx->ks);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_object_allocate_handle(&aesObj1,
MAKE_TEST_ID(__LINE__),
kSSS_KeyPart_Default,
kSSS_CipherType_AES,
sizeof(aesKey),
kKeyObject_Mode_Persistent);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_store_set_key(&pCtx->ks, &aesObj1, aesKey, sizeof(aesKey), sizeof(aesKey) * 8, NULL, 0);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
Now inject the wrapped AES key using the A71CH API - A71_SetRfc3394WrappedAesKey. Wrapped key length should be 24 bytes. Large keys can be set by calling the A71_SetRfc3394WrappedAesKey API multiple times and by incrementing the key index every time.
keyIdx = (((sss_sscp_object_t *)&aesObj1)->slotId) & 0x0F;
/* Set wrapped aes key - aesKey1 */
sw = A71_SetRfc3394WrappedAesKey(keyIdx, wapped_AesKey1_0, sizeof(wapped_AesKey1_0));
status = ((sw == SW_OK) ? kStatus_SSS_Success : kStatus_SSS_Fail);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
sw = A71_SetRfc3394WrappedAesKey(keyIdx + 1, wapped_AesKey1_1, sizeof(wapped_AesKey1_1));
status = ((sw == SW_OK) ? kStatus_SSS_Success : kStatus_SSS_Fail);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
Now verify if wrapped key injected is set correctly.
/* 1 - Calculate HKDF key with wrapped AES key injected - aesKey1 */
status = calculate_hkdf_key(pCtx, aesObj1, MAKE_TEST_ID(__LINE__), HkdfKey1, &HkdfKey1Len);
/* 2 - Inject aesKey1 AES key and calculate HKDF key */
status = sss_key_object_init(&aesObj2, &pCtx->ks);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_object_allocate_handle(&aesObj2,
MAKE_TEST_ID(__LINE__),
kSSS_KeyPart_Default,
kSSS_CipherType_AES,
sizeof(aesKey1),
kKeyObject_Mode_Persistent);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_store_set_key(&pCtx->ks, &aesObj2, aesKey1, sizeof(aesKey1), sizeof(aesKey1) * 8, NULL, 0);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = calculate_hkdf_key(pCtx, aesObj2, MAKE_TEST_ID(__LINE__), HkdfKey2, &HkdfKey2Len);
/* 3 - compare both hkdf keys generated */
if (0 != memcmp(HkdfKey1, HkdfKey2, HkdfKey1Len)) {
status = kStatus_SSS_Fail;
}
10.1.4. SSS Object Identifier to A71CH Internal storage mapping¶
The SSS API uses a 32 bit unsigned value as key (object) identifier. The A71CH GP Storage contains the mapping between these key identifiers and A71CH internal storage as a dedicated data object of 160 byte.
The resulting A71CH KeyStore can contain upto:
4 ECC Key Pairs
3 ECC Public Keys
8 Symmetric Keys
4 Certificates
Any additional data object storage is only available through HLSE API calls (A71CH Legacy HLSE (Generic) API).