Skip to content

Commit 336826e

Browse files
committed
Add HMAC Generation with SE05X with Arduino
1 parent 6bddeb0 commit 336826e

File tree

6 files changed

+259
-1
lines changed

6 files changed

+259
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
SE05X HMAC
3+
4+
This sketch uses the SE05X to securely store and use an HMAC Key
5+
and calculates the HMAC-SHA512 sum of a given message
6+
7+
Circuit:
8+
- Portenta C33
9+
*/
10+
11+
#include <SE05X.h>
12+
13+
const int HMAC_KEY_ID = 667;
14+
const byte hmac_key[32] = {
15+
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
16+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
17+
};
18+
19+
20+
void print_hex(const byte in[], size_t len) {
21+
for (size_t i = 0; i < len; i++) {
22+
Serial.print(in[i] >> 4, HEX);
23+
Serial.print(in[i] & 0x0f, HEX);
24+
}
25+
Serial.println();
26+
}
27+
28+
void setup() {
29+
Serial.begin(9600);
30+
while (!Serial);
31+
32+
if (!SE05X.begin()) {
33+
Serial.println("Error with secure element");
34+
while(1);
35+
}
36+
37+
SE05X.deleteBinaryObject(HMAC_KEY_ID); //remove key if already exists
38+
39+
SE05X.writeHMACKey(HMAC_KEY_ID, hmac_key, sizeof(hmac_key));
40+
String message = "This is a test for the Arduino Portenta C33 to test HMAC with SHA512 algorithm. This are some bytes of data, which should work";
41+
42+
43+
byte buffer[64];
44+
for(int i = 0; i < 64; i++)
45+
buffer[i] = 0;
46+
47+
size_t len = 64; // 64 byte = 512 bit, length for SHA512
48+
SE05X.HMAC_Generate(HMAC_KEY_ID, kSE05x_MACAlgo_HMAC_SHA512, (const byte*)message.c_str(), message.length(), buffer, &len);
49+
print_hex(buffer,len);
50+
}
51+
52+
void loop() {
53+
54+
}

libraries/SE05X/src/SE05X.cpp

+41-1
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,46 @@ int SE05XClass::writeAESKey(int objectId, const byte data[], size_t length)
646646
return 1;
647647
}
648648

649+
int SE05XClass::writeHMACKey(int objectId, const byte data[], size_t length)
650+
{
651+
smStatus_t status;
652+
SE05x_Result_t result;
653+
uint8_t exists = 0;
654+
uint16_t offset = 0;
655+
uint16_t size;
656+
657+
status = Se05x_API_CheckObjectExists(&_se05x_session, objectId, &result);
658+
if (status != SM_OK) {
659+
SMLOG_E("Error in Se05x_API_CheckObjectExists \n");
660+
return 0;
661+
}
662+
663+
if (result == kSE05x_Result_SUCCESS) {
664+
SMLOG_E("Object exists \n");
665+
exists = 1;
666+
}
667+
668+
status = Se05x_API_WriteSymmKey(&_se05x_session, NULL, 0, objectId, SE05x_KeyID_KEK_NONE, data, length, kSE05x_INS_NA, kSE05x_SymmKeyType_HMAC);
669+
670+
if (status != SM_OK) {
671+
SMLOG_E("Error in Se05x_API_WriteSymmKey \n");
672+
return 0;
673+
}
674+
return 1;
675+
}
676+
677+
int SE05XClass::HMAC_Generate(int objectId, uint8_t mac_operation, const byte data[], size_t data_length, byte output[], size_t *output_len)
678+
{
679+
smStatus_t status;
680+
status = Se05x_API_MACOneShot_G(&_se05x_session, objectId, mac_operation, data, data_length, output, output_len);
681+
682+
if (status != SM_OK) {
683+
SMLOG_E("Error in Se05x_API_CipherOneShot \n");
684+
return status;
685+
}
686+
return 1;
687+
}
688+
649689
int SE05XClass::writeBinaryObject(int objectId, const byte data[], size_t length)
650690
{
651691
smStatus_t status;
@@ -719,7 +759,7 @@ int SE05XClass::deleteBinaryObject(int objectId)
719759

720760
status = Se05x_API_DeleteSecureObject(&_se05x_session, objectId);
721761
if (status != SM_OK) {
722-
SMLOG_E("Error in Se05x_API_CheckObjectExists \n");
762+
SMLOG_E("Error in Se05x_API_DeleteSecureObject \n");
723763
return 0;
724764
}
725765

libraries/SE05X/src/SE05X.h

+28
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,34 @@ class SE05XClass
234234
*/
235235
int writeAESKey(int ObjectId, const byte data[], size_t length);
236236

237+
/** writeHMACKey
238+
*
239+
* Writes symmetric key into SE050 object.
240+
*
241+
* @param[in] ObjectId SE050 object ID for the hmac key
242+
* @param[in] data Input data buffer
243+
* @param[in] length Input data buffer size
244+
*
245+
* @return 0 on Failure 1 on Success
246+
*/
247+
int writeHMACKey(int ObjectId, const byte data[], size_t length);
248+
249+
/** HMAC_Generate
250+
*
251+
* Computes the HMAC digest with SE050 chip
252+
*
253+
* @param[in] objectId SE050 object ID for the hmac key
254+
* @param[in] mac_operation Type of Hash function for HMAC
255+
* @param[in] data Input data buffer
256+
* @param[in] length Input data buffer size
257+
* @param[out] output Output data buffer
258+
* @param[out] output_length Output data buffer size (should be 32 bytes for SHA256)
259+
*
260+
* @return 0 on Failure 1 on Success
261+
*/
262+
int HMAC_Generate(int objectId, uint8_t mac_operation, const byte data[], size_t data_length, byte output[], size_t *output_len);
263+
264+
237265
/** writeBinaryObject
238266
*
239267
* Writes binary data into SE050 object.

libraries/SE05X/src/lib/apdu/se05x_APDU_apis.h

+78
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,84 @@ smStatus_t Se05x_API_DigestOneShot(pSe05xSession_t session_ctx,
11041104
uint8_t *hashValue,
11051105
size_t *phashValueLen);
11061106

1107+
1108+
/** Se05x_API_MACOneShot_G
1109+
*
1110+
* Generate. See @ref Se05x_API_MACOneShot_V for Verfiication.
1111+
*
1112+
* Performs a MAC operation in one shot (without keeping state).
1113+
*
1114+
* The 4-byte identifier of the key must refer to an AESKey, DESKey or HMACKey.
1115+
*
1116+
* # Command to Applet
1117+
*
1118+
* @rst
1119+
* +---------+------------------------+---------------------------------------------+
1120+
* | Field | Value | Description |
1121+
* +=========+========================+=============================================+
1122+
* | CLA | 0x80 | |
1123+
* +---------+------------------------+---------------------------------------------+
1124+
* | INS | INS_CRYPTO | :cpp:type:`SE05x_INS_t` |
1125+
* +---------+------------------------+---------------------------------------------+
1126+
* | P1 | P1_MAC | See :cpp:type:`SE05x_P1_t` |
1127+
* +---------+------------------------+---------------------------------------------+
1128+
* | P2 | P2_GENERATE_ONESHOT or | See :cpp:type:`SE05x_P2_t` |
1129+
* | | P2_VALIDATE_ONESHOT | |
1130+
* +---------+------------------------+---------------------------------------------+
1131+
* | Lc | #(Payload) | |
1132+
* +---------+------------------------+---------------------------------------------+
1133+
* | Payload | TLV[TAG_1] | 4-byte identifier of the key object. |
1134+
* +---------+------------------------+---------------------------------------------+
1135+
* | | TLV[TAG_2] | 1-byte :cpp:type:`MACAlgoRef` |
1136+
* +---------+------------------------+---------------------------------------------+
1137+
* | | TLV[TAG_3] | Byte array containing data to be taken as |
1138+
* | | | input to MAC. |
1139+
* +---------+------------------------+---------------------------------------------+
1140+
* | | TLV[TAG_5] | MAC to verify (when P2=P2_VALIDATE_ONESHOT) |
1141+
* +---------+------------------------+---------------------------------------------+
1142+
* | Le | 0x00 | Expecting MAC or Result. |
1143+
* +---------+------------------------+---------------------------------------------+
1144+
* @endrst
1145+
*
1146+
* # R-APDU Body
1147+
*
1148+
* @rst
1149+
* +------------+---------------------------------------+
1150+
* | Value | Description |
1151+
* +============+=======================================+
1152+
* | TLV[TAG_1] | MAC value (P2=P2_GENERATE_ONESHOT) or |
1153+
* | | :cpp:type:`SE05x_Result_t` (when |
1154+
* | | p2=P2_VALIDATE_ONESHOT). |
1155+
* +------------+---------------------------------------+
1156+
* @endrst
1157+
*
1158+
* # R-APDU Trailer
1159+
*
1160+
* @rst
1161+
* +-------------+--------------------------------------+
1162+
* | SW | Description |
1163+
* +=============+======================================+
1164+
* | SW_NO_ERROR | The command is handled successfully. |
1165+
* +-------------+--------------------------------------+
1166+
* @endrst
1167+
*
1168+
* @param[in] session_ctx Session Context [0:kSE05x_pSession]
1169+
* @param[in] objectID objectID [1:kSE05x_TAG_1]
1170+
* @param[in] macOperation macOperation [2:kSE05x_TAG_2]
1171+
* @param[in] inputData inputData [3:kSE05x_TAG_3]
1172+
* @param[in] inputDataLen Length of inputData
1173+
* @param[out] macValue [0:kSE05x_TAG_1]
1174+
* @param[in,out] pmacValueLen Length for macValue
1175+
*/
1176+
smStatus_t Se05x_API_MACOneShot_G(pSe05xSession_t session_ctx,
1177+
uint32_t objectID,
1178+
uint8_t macOperation,
1179+
const uint8_t *inputData,
1180+
size_t inputDataLen,
1181+
uint8_t *macValue,
1182+
size_t *pmacValueLen);
1183+
1184+
11071185
/** Se05x_API_CreateCryptoObject
11081186
*
11091187
* Creates a Crypto Object on the SE05X . Once the Crypto Object is created, it

libraries/SE05X/src/lib/apdu/se05x_APDU_impl.c

+56
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,62 @@ smStatus_t Se05x_API_DigestOneShot(pSe05xSession_t session_ctx,
854854
return retStatus;
855855
}
856856

857+
858+
smStatus_t Se05x_API_MACOneShot_G(pSe05xSession_t session_ctx,
859+
uint32_t objectID,
860+
uint8_t macOperation,
861+
const uint8_t *inputData,
862+
size_t inputDataLen,
863+
uint8_t *macValue,
864+
size_t *pmacValueLen)
865+
{
866+
smStatus_t retStatus = SM_NOT_OK;
867+
tlvHeader_t hdr = {{kSE05x_CLA, kSE05x_INS_CRYPTO, kSE05x_P1_MAC, kSE05x_P2_GENERATE_ONESHOT}};
868+
size_t cmdbufLen = 0;
869+
uint8_t *pCmdbuf = NULL;
870+
int tlvRet = 0;
871+
uint8_t *pRspbuf = NULL;
872+
size_t rspbufLen = 0;
873+
874+
ENSURE_OR_GO_CLEANUP(session_ctx != NULL);
875+
876+
SMLOG_D("APDU - Se05x_API_MACOneShot_G [] \n");
877+
878+
pCmdbuf = &session_ctx->apdu_buffer[0];
879+
pRspbuf = &session_ctx->apdu_buffer[0];
880+
rspbufLen = sizeof(session_ctx->apdu_buffer);
881+
882+
tlvRet = TLVSET_U32("objectID", &pCmdbuf, &cmdbufLen, kSE05x_TAG_1, objectID);
883+
if (0 != tlvRet) {
884+
goto cleanup;
885+
}
886+
tlvRet = TLVSET_U8("macOperation", &pCmdbuf, &cmdbufLen, kSE05x_TAG_2, macOperation);
887+
if (0 != tlvRet) {
888+
goto cleanup;
889+
}
890+
tlvRet = TLVSET_u8bufOptional("inputData", &pCmdbuf, &cmdbufLen, kSE05x_TAG_3, inputData, inputDataLen);
891+
if (0 != tlvRet) {
892+
goto cleanup;
893+
}
894+
retStatus = DoAPDUTxRx(session_ctx, &hdr, session_ctx->apdu_buffer, cmdbufLen, pRspbuf, &rspbufLen, 0);
895+
896+
if (retStatus == SM_OK) {
897+
retStatus = SM_NOT_OK;
898+
size_t rspIndex = 0;
899+
tlvRet = tlvGet_u8buf(pRspbuf, &rspIndex, rspbufLen, kSE05x_TAG_1, macValue, pmacValueLen);
900+
if (0 != tlvRet) {
901+
goto cleanup;
902+
}
903+
if ((rspIndex + 2) == rspbufLen) {
904+
retStatus = (smStatus_t)((pRspbuf[rspIndex] << 8) | (pRspbuf[rspIndex + 1]));
905+
}
906+
}
907+
908+
cleanup:
909+
return retStatus;
910+
}
911+
912+
857913
smStatus_t Se05x_API_CreateCryptoObject(pSe05xSession_t session_ctx,
858914
SE05x_CryptoObjectID_t cryptoObjectID,
859915
SE05x_CryptoContext_t cryptoContext,

libraries/SE05X/src/lib/apdu/se05x_types.h

+2
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ typedef enum
198198
kSE05x_P2_DH = 0x0F,
199199
kSE05x_P2_ENCRYPT_ONESHOT = 0x37,
200200
kSE05x_P2_DECRYPT_ONESHOT = 0x38,
201+
kSE05x_P2_GENERATE_ONESHOT = 0x45,
202+
kSE05x_P2_VALIDATE_ONESHOT = 0x46,
201203
kSE05x_P2_RANDOM = 0x49,
202204
kSE05x_P2_SCP = 0x52,
203205
} SE05x_P2_t;

0 commit comments

Comments
 (0)