MA-15321-3 Support secure unlock feature
authorJi Luo <ji.luo@nxp.com>
Thu, 15 Aug 2019 12:53:53 +0000 (20:53 +0800)
committerJi Luo <ji.luo@nxp.com>
Tue, 20 Aug 2019 02:11:13 +0000 (10:11 +0800)
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>
drivers/fastboot/fb_fsl/fb_fsl_command.c
include/fsl_avb.h
include/interface/keymaster/keymaster.h
include/trusty/keymaster.h
include/trusty/keymaster_serializable.h
lib/Kconfig
lib/avb/fsl/fsl_avbkey.c
lib/trusty/ql-tipc/keymaster.c
lib/trusty/ql-tipc/keymaster_serializable.c

index 7b033ba..c5b1e44 100755 (executable)
@@ -362,6 +362,21 @@ static FbLockState do_fastboot_unlock(bool force)
        if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) {
                printf("It is able to unlock device. %d\n",fastboot_lock_enable());
 
+#if defined(CONFIG_SECURE_UNLOCK) && defined(CONFIG_IMX_TRUSTY_OS)
+               if ((fastboot_bytes_received == 0) || !hab_is_enabled()) {
+                       printf("No unlock credential found or hab is not closed!\n");
+                       return FASTBOOT_LOCK_ERROR;
+               } else {
+                       char *serial = get_serial();
+                       status = trusty_verify_secure_unlock(fastboot_buf_addr,
+                                                               fastboot_bytes_received,
+                                                               serial, 16);
+                       if (status < 0) {
+                               printf("verify secure unlock credential fail due Trusty return %d\n", status);
+                               return FASTBOOT_LOCK_ERROR;
+                       }
+               }
+#endif
                wipe_all_userdata();
                status = fastboot_set_lock_stat(FASTBOOT_UNLOCK);
                if (status < 0)
index abc751e..8939670 100644 (file)
@@ -275,6 +275,9 @@ int avb_set_public_key(uint8_t *staged_buffer, uint32_t size);
 /* Get manufacture protection  public key */
 int fastboot_get_mppubk(uint8_t *staged_buffer, uint32_t *size);
 
+/* Check if hab is closed. */
+bool hab_is_enabled(void);
+
 /* Return if device is in spl recovery mode. */
 bool is_spl_recovery(void);
 
index 1b1fc63..c98442d 100644 (file)
@@ -65,7 +65,8 @@ enum keymaster_command {
     KM_SET_PRODUCT_ID                  = (0x9000 << KEYMASTER_REQ_SHIFT),
     KM_SET_ATTESTATION_KEY_ENC         = (0xa000 << KEYMASTER_REQ_SHIFT),
     KM_APPEND_ATTESTATION_CERT_CHAIN_ENC = (0xb000 << KEYMASTER_REQ_SHIFT),
-    KM_GET_MPPUBK                      = (0xc000 << KEYMASTER_REQ_SHIFT)
+    KM_GET_MPPUBK                      = (0xc000 << KEYMASTER_REQ_SHIFT),
+    KM_VERIFY_SECURE_UNLOCK            = (0xd000 << KEYMASTER_REQ_SHIFT)
 };
 
 typedef enum {
@@ -223,6 +224,20 @@ struct km_get_mppubk_resp {
     uint8_t data[64];
 } TRUSTY_ATTR_PACKED;
 
+/**
+ * km_secure_unlock_data - represents the secure unlock data
+ *
+ * @serial_size: size of |serial_data|
+ * @serial_data: serial_data (serial number)
+ * @credential_size: size of |credential_data|
+ * @credential_data: credential data
+ */
+struct km_secure_unlock_data {
+    uint32_t serial_size;
+    const uint8_t *serial_data;
+    uint32_t credential_size;
+    const uint8_t *credential_data;
+} TRUSTY_ATTR_PACKED;
 /**
  * km_set_ca_response_begin_req - starts the process to set the ATAP CA Response
  *
index 6c8d2e9..3776dbc 100644 (file)
@@ -135,4 +135,16 @@ int trusty_set_product_id(const uint8_t *product_id, uint32_t size);
  */
 int trusty_get_mppubk(uint8_t *mppubk, uint32_t* size);
 
+/* trusty_verify_secure_unlock is called to the verify the secure unlock
+ * credential.
+ *
+ * @unlock_credential: Poniter to the unlock credential.
+ * @credential_size: credential size.
+ * @serial: serial number to verify.
+ * @serial_size: serial number size.
+ */
+int trusty_verify_secure_unlock(uint8_t *unlock_credential,
+                                uint32_t credential_size,
+                                uint8_t *serial, uint32_t serial_size);
+
 #endif /* TRUSTY_KEYMASTER_H_ */
index 196e606..a8295df 100644 (file)
@@ -67,6 +67,14 @@ int km_boot_params_serialize(const struct km_boot_params *params, uint8_t **out,
 int km_attestation_data_serialize(const struct km_attestation_data *data,
                                   uint8_t **out, uint32_t *out_size);
 
+/**
+ * Serializes a km_secure_unlock_data structure. On success, allocates |*out_size|
+ * bytes to |*out| and writes the serialized |data| to |*out|. Caller takes
+ * ownership of |*out|. Returns one of trusty_err.
+ */
+int km_secure_unlock_data_serialize(const struct km_secure_unlock_data *data,
+                                  uint8_t **out, uint32_t *out_size);
+
 /**
  * Serializes a km_raw_buffer structure. On success, allocates |*out_size|
  * bytes to |*out| and writes the serialized |data| to |*out|. Caller takes
index fde5207..7bf4f6e 100644 (file)
@@ -246,6 +246,8 @@ config DUAL_BOOTLOADER
 config AT_AUTHENTICATE_UNLOCK
        bool "Enable authenticate unlock for Android Things devices"
 
+config SECURE_UNLOCK
+       bool "Enable secure unlock for Android devices, it can only be enabled on HAB closed board"
 endmenu
 
 menu "Hashing Support"
index b971530..2ba373e 100644 (file)
@@ -1148,6 +1148,18 @@ extern struct imx_sec_config_fuse_t const imx_sec_config_fuse;
 /* Check hab status, this is basically copied from imx_hab_is_enabled() */
 bool hab_is_enabled(void)
 {
+#ifdef CONFIG_ARCH_IMX8
+       sc_err_t err;
+       uint16_t lc;
+
+       err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
+       if (err != SC_ERR_NONE) {
+               printf("Error in get lifecycle\n");
+               return false;
+       }
+
+       if (lc != 0x80)
+#else
        struct imx_sec_config_fuse_t *fuse =
                (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
        uint32_t reg;
@@ -1155,11 +1167,15 @@ bool hab_is_enabled(void)
 
        ret = fuse_read(fuse->bank, fuse->word, &reg);
        if (ret) {
-               puts("\nSecure boot fuse read error\n");
-               return ret;
+               puts("\nSecure boot fuse read error!\n");
+               return false;
        }
 
-       return (reg & HAB_ENABLED_BIT) == HAB_ENABLED_BIT;
+       if (!((reg & HAB_ENABLED_BIT) == HAB_ENABLED_BIT))
+#endif
+               return false;
+       else
+               return true;
 }
 
 int do_rpmb_key_set(uint8_t *key, uint32_t key_size)
@@ -1297,23 +1313,11 @@ int avb_set_public_key(uint8_t *staged_buffer, uint32_t size) {
 
 int fastboot_get_mppubk(uint8_t *staged_buffer, uint32_t *size) {
 
-#ifdef CONFIG_ARCH_IMX8
-       sc_err_t err;
-       uint16_t lc;
-
-       err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
-       if (err != SC_ERR_NONE) {
-               printf("Error in get lifecycle\n");
-               return -1;
-       }
-
-       if (lc != 0x80) {
-#else
        if (!hab_is_enabled()) {
-#endif
                ERR("Error. This command can only be used when hab is closed!!\n");
                return -1;
        }
+
        if ((staged_buffer == NULL) || (size == NULL)) {
                ERR("Error. Get null staged_buffer!\n");
                return -1;
index 01828e0..2104204 100644 (file)
@@ -523,3 +523,34 @@ int trusty_get_mppubk(uint8_t *mppubk, uint32_t *size)
     memcpy(mppubk, resp.data, resp.data_size);
     return TRUSTY_ERR_NONE;
 }
+
+int trusty_verify_secure_unlock(uint8_t *unlock_credential,
+                                uint32_t credential_size,
+                                uint8_t *serial, uint32_t serial_size)
+{
+    int rc = TRUSTY_ERR_GENERIC;
+    uint8_t *req = NULL;
+    uint32_t req_size = 0;
+
+    struct km_secure_unlock_data secure_unlock_data = {
+        .serial_size = serial_size,
+        .serial_data = serial,
+        .credential_size = credential_size,
+        .credential_data = unlock_credential,
+    };
+
+    rc = km_secure_unlock_data_serialize(&secure_unlock_data,
+                                             &req, &req_size);
+
+    if (rc < 0) {
+        trusty_error("failed (%d) to serialize request\n", rc);
+        goto end;
+    }
+    rc = km_do_tipc(KM_VERIFY_SECURE_UNLOCK, req, req_size, NULL, NULL);
+
+end:
+    if (req) {
+        trusty_free(req);
+    }
+    return rc;
+}
index 65bcca0..6d9297d 100644 (file)
@@ -97,6 +97,27 @@ int km_attestation_data_serialize(const struct km_attestation_data *data,
     return TRUSTY_ERR_NONE;
 }
 
+int km_secure_unlock_data_serialize(const struct km_secure_unlock_data *data,
+                                 uint8_t** out, uint32_t *out_size)
+{
+    uint8_t *tmp;
+
+    if (!out || !data || !out_size) {
+        return TRUSTY_ERR_INVALID_ARGS;
+    }
+    *out_size = (sizeof(data->serial_size) + sizeof(data->credential_size) +
+                 data->serial_size + data->credential_size);
+    *out = trusty_calloc(*out_size, 1);
+    if (!*out) {
+        return TRUSTY_ERR_NO_MEMORY;
+    }
+
+    tmp = append_sized_buf_to_buf(*out, data->serial_data, data->serial_size);
+    tmp = append_sized_buf_to_buf(tmp, data->credential_data, data->credential_size);
+
+    return TRUSTY_ERR_NONE;
+}
+
 int km_raw_buffer_serialize(const struct km_raw_buffer *buf, uint8_t** out,
                             uint32_t *out_size)
 {