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