Commit 063d358ab4bbfea998e0c975f31724757243545a
Committed by
Ye Li
1 parent
b92588e129
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
MA-15321-3 Support secure unlock feature
Decrypt and verify the secure credential in keymaster TA, unlock operation can only be allowed after secure credential verify pass. Since the mppubk can only be generated on hab closed imx8q, so secure unlock feature can only supported when hab is closed. Test: secure unlock credential verify on hab closed imx8mm_evk. Change-Id: I1ab5e24df28d1e75ff853de3adf29f34da1d0a71 Signed-off-by: Ji Luo <ji.luo@nxp.com> (cherry picked from commit 631149fc0fc8ce035311949db643c2708e41435a)
Showing 9 changed files with 128 additions and 17 deletions Side-by-side Diff
drivers/fastboot/fb_fsl/fb_fsl_command.c
... | ... | @@ -362,6 +362,21 @@ |
362 | 362 | if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) { |
363 | 363 | printf("It is able to unlock device. %d\n",fastboot_lock_enable()); |
364 | 364 | |
365 | +#if defined(CONFIG_SECURE_UNLOCK) && defined(CONFIG_IMX_TRUSTY_OS) | |
366 | + if ((fastboot_bytes_received == 0) || !hab_is_enabled()) { | |
367 | + printf("No unlock credential found or hab is not closed!\n"); | |
368 | + return FASTBOOT_LOCK_ERROR; | |
369 | + } else { | |
370 | + char *serial = get_serial(); | |
371 | + status = trusty_verify_secure_unlock(fastboot_buf_addr, | |
372 | + fastboot_bytes_received, | |
373 | + serial, 16); | |
374 | + if (status < 0) { | |
375 | + printf("verify secure unlock credential fail due Trusty return %d\n", status); | |
376 | + return FASTBOOT_LOCK_ERROR; | |
377 | + } | |
378 | + } | |
379 | +#endif | |
365 | 380 | wipe_all_userdata(); |
366 | 381 | status = fastboot_set_lock_stat(FASTBOOT_UNLOCK); |
367 | 382 | if (status < 0) |
include/fsl_avb.h
... | ... | @@ -275,6 +275,9 @@ |
275 | 275 | /* Get manufacture protection public key */ |
276 | 276 | int fastboot_get_mppubk(uint8_t *staged_buffer, uint32_t *size); |
277 | 277 | |
278 | +/* Check if hab is closed. */ | |
279 | +bool hab_is_enabled(void); | |
280 | + | |
278 | 281 | /* Return if device is in spl recovery mode. */ |
279 | 282 | bool is_spl_recovery(void); |
280 | 283 |
include/interface/keymaster/keymaster.h
... | ... | @@ -65,7 +65,8 @@ |
65 | 65 | KM_SET_PRODUCT_ID = (0x9000 << KEYMASTER_REQ_SHIFT), |
66 | 66 | KM_SET_ATTESTATION_KEY_ENC = (0xa000 << KEYMASTER_REQ_SHIFT), |
67 | 67 | KM_APPEND_ATTESTATION_CERT_CHAIN_ENC = (0xb000 << KEYMASTER_REQ_SHIFT), |
68 | - KM_GET_MPPUBK = (0xc000 << KEYMASTER_REQ_SHIFT) | |
68 | + KM_GET_MPPUBK = (0xc000 << KEYMASTER_REQ_SHIFT), | |
69 | + KM_VERIFY_SECURE_UNLOCK = (0xd000 << KEYMASTER_REQ_SHIFT) | |
69 | 70 | }; |
70 | 71 | |
71 | 72 | typedef enum { |
... | ... | @@ -223,6 +224,20 @@ |
223 | 224 | uint8_t data[64]; |
224 | 225 | } TRUSTY_ATTR_PACKED; |
225 | 226 | |
227 | +/** | |
228 | + * km_secure_unlock_data - represents the secure unlock data | |
229 | + * | |
230 | + * @serial_size: size of |serial_data| | |
231 | + * @serial_data: serial_data (serial number) | |
232 | + * @credential_size: size of |credential_data| | |
233 | + * @credential_data: credential data | |
234 | + */ | |
235 | +struct km_secure_unlock_data { | |
236 | + uint32_t serial_size; | |
237 | + const uint8_t *serial_data; | |
238 | + uint32_t credential_size; | |
239 | + const uint8_t *credential_data; | |
240 | +} TRUSTY_ATTR_PACKED; | |
226 | 241 | /** |
227 | 242 | * km_set_ca_response_begin_req - starts the process to set the ATAP CA Response |
228 | 243 | * |
include/trusty/keymaster.h
... | ... | @@ -135,5 +135,17 @@ |
135 | 135 | */ |
136 | 136 | int trusty_get_mppubk(uint8_t *mppubk, uint32_t* size); |
137 | 137 | |
138 | +/* trusty_verify_secure_unlock is called to the verify the secure unlock | |
139 | + * credential. | |
140 | + * | |
141 | + * @unlock_credential: Poniter to the unlock credential. | |
142 | + * @credential_size: credential size. | |
143 | + * @serial: serial number to verify. | |
144 | + * @serial_size: serial number size. | |
145 | + */ | |
146 | +int trusty_verify_secure_unlock(uint8_t *unlock_credential, | |
147 | + uint32_t credential_size, | |
148 | + uint8_t *serial, uint32_t serial_size); | |
149 | + | |
138 | 150 | #endif /* TRUSTY_KEYMASTER_H_ */ |
include/trusty/keymaster_serializable.h
... | ... | @@ -68,6 +68,14 @@ |
68 | 68 | uint8_t **out, uint32_t *out_size); |
69 | 69 | |
70 | 70 | /** |
71 | + * Serializes a km_secure_unlock_data structure. On success, allocates |*out_size| | |
72 | + * bytes to |*out| and writes the serialized |data| to |*out|. Caller takes | |
73 | + * ownership of |*out|. Returns one of trusty_err. | |
74 | + */ | |
75 | +int km_secure_unlock_data_serialize(const struct km_secure_unlock_data *data, | |
76 | + uint8_t **out, uint32_t *out_size); | |
77 | + | |
78 | +/** | |
71 | 79 | * Serializes a km_raw_buffer structure. On success, allocates |*out_size| |
72 | 80 | * bytes to |*out| and writes the serialized |data| to |*out|. Caller takes |
73 | 81 | * ownership of |*out|. Returns one of trusty_err. |
lib/Kconfig
... | ... | @@ -344,6 +344,8 @@ |
344 | 344 | config AT_AUTHENTICATE_UNLOCK |
345 | 345 | bool "Enable authenticate unlock for Android Things devices" |
346 | 346 | |
347 | +config SECURE_UNLOCK | |
348 | + bool "Enable secure unlock for Android devices, it can only be enabled on HAB closed board" | |
347 | 349 | endmenu |
348 | 350 | |
349 | 351 | menu "Hashing Support" |
lib/avb/fsl/fsl_avbkey.c
... | ... | @@ -1148,6 +1148,18 @@ |
1148 | 1148 | /* Check hab status, this is basically copied from imx_hab_is_enabled() */ |
1149 | 1149 | bool hab_is_enabled(void) |
1150 | 1150 | { |
1151 | +#ifdef CONFIG_ARCH_IMX8 | |
1152 | + sc_err_t err; | |
1153 | + uint16_t lc; | |
1154 | + | |
1155 | + err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL); | |
1156 | + if (err != SC_ERR_NONE) { | |
1157 | + printf("Error in get lifecycle\n"); | |
1158 | + return false; | |
1159 | + } | |
1160 | + | |
1161 | + if (lc != 0x80) | |
1162 | +#else | |
1151 | 1163 | struct imx_sec_config_fuse_t *fuse = |
1152 | 1164 | (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; |
1153 | 1165 | uint32_t reg; |
1154 | 1166 | |
... | ... | @@ -1155,11 +1167,15 @@ |
1155 | 1167 | |
1156 | 1168 | ret = fuse_read(fuse->bank, fuse->word, ®); |
1157 | 1169 | if (ret) { |
1158 | - puts("\nSecure boot fuse read error\n"); | |
1159 | - return ret; | |
1170 | + puts("\nSecure boot fuse read error!\n"); | |
1171 | + return false; | |
1160 | 1172 | } |
1161 | 1173 | |
1162 | - return (reg & HAB_ENABLED_BIT) == HAB_ENABLED_BIT; | |
1174 | + if (!((reg & HAB_ENABLED_BIT) == HAB_ENABLED_BIT)) | |
1175 | +#endif | |
1176 | + return false; | |
1177 | + else | |
1178 | + return true; | |
1163 | 1179 | } |
1164 | 1180 | |
1165 | 1181 | int do_rpmb_key_set(uint8_t *key, uint32_t key_size) |
1166 | 1182 | |
1167 | 1183 | |
... | ... | @@ -1297,23 +1313,11 @@ |
1297 | 1313 | |
1298 | 1314 | int fastboot_get_mppubk(uint8_t *staged_buffer, uint32_t *size) { |
1299 | 1315 | |
1300 | -#ifdef CONFIG_ARCH_IMX8 | |
1301 | - sc_err_t err; | |
1302 | - uint16_t lc; | |
1303 | - | |
1304 | - err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL); | |
1305 | - if (err != SC_ERR_NONE) { | |
1306 | - printf("Error in get lifecycle\n"); | |
1307 | - return -1; | |
1308 | - } | |
1309 | - | |
1310 | - if (lc != 0x80) { | |
1311 | -#else | |
1312 | 1316 | if (!hab_is_enabled()) { |
1313 | -#endif | |
1314 | 1317 | ERR("Error. This command can only be used when hab is closed!!\n"); |
1315 | 1318 | return -1; |
1316 | 1319 | } |
1320 | + | |
1317 | 1321 | if ((staged_buffer == NULL) || (size == NULL)) { |
1318 | 1322 | ERR("Error. Get null staged_buffer!\n"); |
1319 | 1323 | return -1; |
lib/trusty/ql-tipc/keymaster.c
... | ... | @@ -523,4 +523,35 @@ |
523 | 523 | memcpy(mppubk, resp.data, resp.data_size); |
524 | 524 | return TRUSTY_ERR_NONE; |
525 | 525 | } |
526 | + | |
527 | +int trusty_verify_secure_unlock(uint8_t *unlock_credential, | |
528 | + uint32_t credential_size, | |
529 | + uint8_t *serial, uint32_t serial_size) | |
530 | +{ | |
531 | + int rc = TRUSTY_ERR_GENERIC; | |
532 | + uint8_t *req = NULL; | |
533 | + uint32_t req_size = 0; | |
534 | + | |
535 | + struct km_secure_unlock_data secure_unlock_data = { | |
536 | + .serial_size = serial_size, | |
537 | + .serial_data = serial, | |
538 | + .credential_size = credential_size, | |
539 | + .credential_data = unlock_credential, | |
540 | + }; | |
541 | + | |
542 | + rc = km_secure_unlock_data_serialize(&secure_unlock_data, | |
543 | + &req, &req_size); | |
544 | + | |
545 | + if (rc < 0) { | |
546 | + trusty_error("failed (%d) to serialize request\n", rc); | |
547 | + goto end; | |
548 | + } | |
549 | + rc = km_do_tipc(KM_VERIFY_SECURE_UNLOCK, req, req_size, NULL, NULL); | |
550 | + | |
551 | +end: | |
552 | + if (req) { | |
553 | + trusty_free(req); | |
554 | + } | |
555 | + return rc; | |
556 | +} |
lib/trusty/ql-tipc/keymaster_serializable.c
... | ... | @@ -97,6 +97,27 @@ |
97 | 97 | return TRUSTY_ERR_NONE; |
98 | 98 | } |
99 | 99 | |
100 | +int km_secure_unlock_data_serialize(const struct km_secure_unlock_data *data, | |
101 | + uint8_t** out, uint32_t *out_size) | |
102 | +{ | |
103 | + uint8_t *tmp; | |
104 | + | |
105 | + if (!out || !data || !out_size) { | |
106 | + return TRUSTY_ERR_INVALID_ARGS; | |
107 | + } | |
108 | + *out_size = (sizeof(data->serial_size) + sizeof(data->credential_size) + | |
109 | + data->serial_size + data->credential_size); | |
110 | + *out = trusty_calloc(*out_size, 1); | |
111 | + if (!*out) { | |
112 | + return TRUSTY_ERR_NO_MEMORY; | |
113 | + } | |
114 | + | |
115 | + tmp = append_sized_buf_to_buf(*out, data->serial_data, data->serial_size); | |
116 | + tmp = append_sized_buf_to_buf(tmp, data->credential_data, data->credential_size); | |
117 | + | |
118 | + return TRUSTY_ERR_NONE; | |
119 | +} | |
120 | + | |
100 | 121 | int km_raw_buffer_serialize(const struct km_raw_buffer *buf, uint8_t** out, |
101 | 122 | uint32_t *out_size) |
102 | 123 | { |
-
mentioned in commit 0c13c0