1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved
4 * Author: Jorge Ramirez <jorge@foundries.io>
5 */
6
7 #include <fsl_sss_se05x_apis.h>
8 #include <global_platf.h>
9 #include <se050.h>
10 #include <se05x_const.h>
11 #include <se05x_tlv.h>
12 #include <smCom.h>
13 #include <string.h>
14 #include <util.h>
15
16 /* Force the output until the P&T stack fixes its verbosity */
17 #define LOG_MAU8_I(msg, buf, len) nLog_au8("Info", 0xff, msg, buf, len)
18 #define LOG_I(format, ...) nLog("Info", 0xff, format, ##__VA_ARGS__)
19 #define LOG_E(format, ...) nLog("Info", NX_LEVEL_ERROR, format, ##__VA_ARGS__)
20 #define LOG_MAU8_E(msg, buf, len) \
21 nLog_au8("Info", NX_LEVEL_ERROR, msg, buf, len)
22
jcop4_get_id(void * ctx,bool display)23 static sss_status_t jcop4_get_id(void *ctx, bool display)
24 {
25 char jcop_platform_id[17] = { 0 };
26 smStatus_t ret = SM_OK;
27 unsigned char cmd[] = {
28 0x80, /* CLA '80' / '00' GlobalPlatform / ISO / IEC */
29 0xCA, /* INS 'CA' GET DATA(IDENTIFY) */
30 0x00, /* P1 '00' High order tag value */
31 0xFE, /* P2 'FE' Low order tag value - proprietary data */
32 0x02, /* Lc '02' Length of data field */
33 0xDF,
34 0x28, /* Data 'DF28' Card identification data */
35 0x00 /* Le '00' Length of response data */
36 };
37 struct msg_rsp {
38 uint8_t vTag_value_proprietary_data;
39 uint8_t vLength_of_following_data;
40 uint8_t vTag_card_identification_data[0x02];
41 uint8_t vLength_of_card_identification_data;
42 uint8_t vTag_configuration_ID;
43 uint8_t vLength_configuration_ID;
44 uint8_t vConfiguration_ID[0x0C];
45 uint8_t vTag_patch_ID;
46 uint8_t vLength_patch_ID;
47 uint8_t vPatch_ID[0x08];
48 uint8_t vTag_platform_build_ID1;
49 uint8_t vLength_platform_build_ID;
50 uint8_t vPlatform_build_ID[0x18];
51 uint8_t vTag_FIPS_mode;
52 uint8_t vLength_FIPS_mode;
53 uint8_t vFIPS_mode;
54 uint8_t vTag_pre_perso_state;
55 uint8_t vLength_pre_perso_state;
56 uint8_t vBit_mask_of_pre_perso_state;
57 uint8_t vTag_ROM_ID;
58 uint8_t vLength_ROM_ID;
59 uint8_t vROM_ID[0x08];
60 uint8_t vStatus_Word_SW_[0x02];
61 } rsp = { 0 };
62 uint8_t *p = (uint8_t *)&rsp;
63 uint32_t len = sizeof(struct msg_rsp);
64 uint16_t dummy = sizeof(struct msg_rsp);
65
66 ret = GP_Select(ctx, p, 0, p, &dummy);
67 if (ret != SM_OK) {
68 LOG_E("Could not select ISD.");
69 return kStatus_SSS_Fail;
70 }
71
72 ret = smCom_TransceiveRaw(ctx, cmd, sizeof(cmd), p, &len);
73 if (ret != SM_OK || len != sizeof(rsp)) {
74 LOG_MAU8_E("Error reading JCOP ID", p, sizeof(rsp));
75 return kStatus_SSS_Fail;
76 }
77
78 memcpy(se050_ctx.se_info.oefid, &rsp.vConfiguration_ID[2], 2);
79 if (!display)
80 return kStatus_SSS_Success;
81
82 LOG_I("SE050 JCOP4 Information:");
83 LOG_I("%s = 0x%02X", "Tag value - proprietary data 0xFE",
84 rsp.vTag_value_proprietary_data);
85 LOG_I("%s = 0x%02X", "Length of following data 0x45",
86 rsp.vLength_of_following_data);
87 LOG_MAU8_I("Tag card identification data",
88 rsp.vTag_card_identification_data,
89 sizeof(rsp.vTag_card_identification_data));
90 LOG_I("%s = 0x%02X", "Length of card identification data",
91 rsp.vLength_of_card_identification_data);
92 LOG_I("%s = 0x%02X", "Tag configuration ID (Must be 0x01)",
93 rsp.vTag_configuration_ID);
94 LOG_I("%s = 0x%02X", "Length configuration ID 0x0C",
95 rsp.vLength_configuration_ID);
96 LOG_MAU8_I("Configuration ID",
97 rsp.vConfiguration_ID, sizeof(rsp.vConfiguration_ID));
98 LOG_MAU8_I("OEF ID", &rsp.vConfiguration_ID[2], 2);
99 LOG_I("%s = 0x%02X", "Tag patch ID (Must be 0x02)", rsp.vTag_patch_ID);
100 LOG_I("%s = 0x%02X", "Length patch ID 0x08", rsp.vLength_patch_ID);
101 LOG_MAU8_I("Patch ID", rsp.vPatch_ID, sizeof(rsp.vPatch_ID));
102 LOG_I("%s = 0x%02X", "Tag platform build ID1 (Must be 0x03)",
103 rsp.vTag_platform_build_ID1);
104 LOG_I("%s = 0x%02X", "Length platform build ID 0x18",
105 rsp.vLength_platform_build_ID);
106 LOG_MAU8_I("Platform build ID",
107 rsp.vPlatform_build_ID, sizeof(rsp.vPlatform_build_ID));
108 memcpy(jcop_platform_id, rsp.vPlatform_build_ID, 16);
109
110 LOG_I("%s = %s", "JCOP Platform ID", jcop_platform_id);
111 LOG_I("%s = 0x%02X", "Tag FIPS mode (Must be 0x05)",
112 rsp.vTag_FIPS_mode);
113 LOG_I("%s = 0x%02X", "Length FIPS mode 0x01", rsp.vLength_FIPS_mode);
114 LOG_I("%s = 0x%02X", "FIPS mode var", rsp.vFIPS_mode);
115 LOG_I("%s = 0x%02X", "Tag pre-perso state (Must be 0x07)",
116 rsp.vTag_pre_perso_state);
117 LOG_I("%s = 0x%02X", "Length pre-perso state 0x01",
118 rsp.vLength_pre_perso_state);
119 LOG_I("%s = 0x%02X", "Bit mask of pre-perso state var",
120 rsp.vBit_mask_of_pre_perso_state);
121
122 LOG_I("%s = 0x%02X", "Tag ROM ID (Must be 0x08)", rsp.vTag_ROM_ID);
123 LOG_I("%s = 0x%02X", "Length ROM ID 0x08", rsp.vLength_ROM_ID);
124 LOG_MAU8_I("ROM ID", rsp.vROM_ID, sizeof(rsp.vROM_ID));
125 LOG_MAU8_I("Status Word (SW)", rsp.vStatus_Word_SW_,
126 sizeof(rsp.vStatus_Word_SW_));
127
128 return kStatus_SSS_Success;
129 }
130
131 #define ITEM(__x) { \
132 .name = #__x, \
133 .val = (kSE05x_AppletConfig_##__x), \
134 }
135
show_config(uint16_t cfg)136 static void show_config(uint16_t cfg)
137 {
138 struct items {
139 uint16_t val;
140 const char *name;
141 } features[] = {
142 ITEM(ECDAA), ITEM(ECDSA_ECDH_ECDHE), ITEM(EDDSA), ITEM(DH_MONT),
143 ITEM(HMAC), ITEM(RSA_PLAIN), ITEM(RSA_CRT), ITEM(AES),
144 ITEM(DES), ITEM(PBKDF), ITEM(TLS), ITEM(MIFARE), ITEM(I2CM),
145 };
146 size_t i = 0;
147
148 for (i = 0; i < ARRAY_SIZE(features); i++) {
149 LOG_I("\t%s%s", cfg & features[i].val ? "with\t" : "without\t",
150 features[i].name);
151 }
152 }
153
applet_get_id(sss_se05x_session_t * session,bool display)154 static sss_status_t applet_get_id(sss_se05x_session_t *session, bool display)
155 {
156 SE05x_Result_t result = kSE05x_Result_NA;
157 smStatus_t ret = SM_OK;
158 uint8_t uid[SE050_MODULE_UNIQUE_ID_LEN] = { 0 };
159 size_t uidLen = sizeof(uid);
160 uint8_t applet_version[7] = { 0 };
161 size_t applet_versionLen = sizeof(applet_version);
162
163 ret = Se05x_API_CheckObjectExists(&session->s_ctx,
164 kSE05x_AppletResID_UNIQUE_ID,
165 &result);
166 if (ret != SM_OK)
167 return kStatus_SSS_Fail;
168
169 ret = Se05x_API_ReadObject(&session->s_ctx,
170 kSE05x_AppletResID_UNIQUE_ID, 0,
171 (uint16_t)uidLen, uid, &uidLen);
172 if (ret != SM_OK)
173 return kStatus_SSS_Fail;
174
175 /*
176 * VersionInfo is a 7 - byte value consisting of:
177 * - 1 - byte Major applet version
178 * - 1 - byte Minor applet version
179 * - 1 - byte patch applet version
180 * - 2 - byte AppletConfig, indicating the supported applet features
181 * - 2-byte Secure Box version: major version (MSB) concatenated with
182 * minor version (LSB).
183 */
184 ret = Se05x_API_GetVersion(&session->s_ctx, applet_version,
185 &applet_versionLen);
186 if (ret != SM_OK) {
187 LOG_E("Failed Se05x_API_GetVersion");
188 return kStatus_SSS_Fail;
189 }
190
191 memcpy(se050_ctx.se_info.applet, applet_version, 3);
192 if (!display)
193 return kStatus_SSS_Success;
194
195 LOG_MAU8_I("Applet ID", uid, uidLen);
196
197 LOG_I("Applet Major = %d", applet_version[0]);
198 LOG_I("Applet Minor = %d", applet_version[1]);
199 LOG_I("Applet patch = %d", applet_version[2]);
200 LOG_I("AppletConfig = %02X%02X", applet_version[3], applet_version[4]);
201 show_config(applet_version[3] << 8 | applet_version[4]);
202 LOG_I("Internal = %02X%02X", applet_version[5], applet_version[6]);
203
204 return kStatus_SSS_Success;
205 }
206
se050_get_se_info(sss_se05x_session_t * session,bool display)207 sss_status_t se050_get_se_info(sss_se05x_session_t *session, bool display)
208 {
209 sss_status_t ret = kStatus_SSS_Fail;
210 __maybe_unused uint32_t oefid = 0;
211
212 if (session) {
213 ret = applet_get_id(session, display);
214 if (ret != kStatus_SSS_Success) {
215 EMSG("Can't retrieve Applet information");
216 return ret;
217 }
218
219 ret = jcop4_get_id(session->s_ctx.conn_ctx, display);
220 if (ret != kStatus_SSS_Success) {
221 EMSG("Can't retrieve JCOP information");
222 return ret;
223 }
224
225 #ifdef CFG_CORE_SE05X_OEFID
226 /* validate the requested OEFID against the runtime detected */
227 oefid = SHIFT_U32(se050_ctx.se_info.oefid[0], 8) |
228 SHIFT_U32(se050_ctx.se_info.oefid[1], 0);
229
230 if (oefid != CFG_CORE_SE05X_OEFID) {
231 EMSG("OEFID configuration error, 0x%x != 0x%"PRIx32,
232 CFG_CORE_SE05X_OEFID, oefid);
233 return kStatus_SSS_Fail;
234 }
235 #endif
236 return kStatus_SSS_Success;
237 }
238
239 return kStatus_SSS_Fail;
240 }
241