Commit 063d358ab4bbfea998e0c975f31724757243545a

Authored by Ji Luo
Committed by Ye Li
1 parent b92588e129

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)
... ... @@ -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.
... ... @@ -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, &reg);
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 {