Commit d4a0dbd9a467984d7f4a4861213298e2b95a3327

Authored by Ji Luo
Committed by faqiang.zhu
1 parent 22ab111509

[iot] Support authenticated unlock

Add fastboot commands "fastboot oem at-get-vboot-unlock-challenge"
and "fastboot oem at-unlock-vboot" to support the authenticated
unlock feature for Android Things devices. Use software random
numbers generator to generate the 16 bytes random challenge, it
should be replaced with hardware encrypted random generator when
the TEE part is ready.

Test: Generate unlock challenge by:
        ./avbtool make_atx_unlock_credential
        --output=atx_unlock_credential.bin
        --intermediate_key_certificate=atx_pik_certificate.bin
        --unlock_key_certificate=atx_puk_certificate.bin
        --challenge=my_generated_challenge.bin
        --unlock_key=testkey_atx_puk.pem
      validated the unlock credential successfully on imx7d_pico
      and AIY.

Change-Id: I4b8cee87c9e96924169479b65020a081136681f6
Signed-off-by: Ji Luo <ji.luo@nxp.com>

Showing 11 changed files with 144 additions and 10 deletions Side-by-side Diff

board/freescale/imx8mq_phanbell/imx8m_phanbell.c
... ... @@ -368,8 +368,8 @@
368 368 int board_late_init(void)
369 369 {
370 370 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
371   - setenv("board_name", "Phanbell");
372   - setenv("board_rev", "iMX8MQ");
  371 + env_set("board_name", "Phanbell");
  372 + env_set("board_rev", "iMX8MQ");
373 373 #endif
374 374  
375 375 #ifdef CONFIG_ENV_IS_IN_MMC
configs/imx8mq_phanbell_androidthings_defconfig
... ... @@ -68,4 +68,7 @@
68 68 CONFIG_USB_XHCI_DWC3=y
69 69 CONFIG_USB_DWC3=y
70 70 CONFIG_USB_DWC3_GADGET=y
  71 +CONFIG_CMD_UUID=y
  72 +CONFIG_LIB_RAND=y
  73 +CONFIG_AVB_SUPPORT=y
configs/imx8mq_phanbell_androidthings_uuu_defconfig
... ... @@ -71,4 +71,7 @@
71 71 CONFIG_USB_XHCI_DWC3=y
72 72 CONFIG_USB_DWC3=y
73 73 CONFIG_USB_DWC3_GADGET=y
  74 +CONFIG_CMD_UUID=y
  75 +CONFIG_LIB_RAND=y
  76 +CONFIG_AVB_SUPPORT=y
configs/pico-imx7d-trusty_defconfig
... ... @@ -38,4 +38,5 @@
38 38 CONFIG_AVB_SUPPORT=y
39 39 CONFIG_AVB_ATX=y
40 40 CONFIG_USE_STDINT=y
  41 +CONFIG_LIB_RAND=y
configs/pico-imx7d_defconfig
... ... @@ -36,4 +36,5 @@
36 36 CONFIG_OF_LIBFDT=y
37 37 CONFIG_AVB_SUPPORT=y
38 38 CONFIG_AVB_ATX=y
  39 +CONFIG_LIB_RAND=y
drivers/usb/gadget/f_fastboot.c
... ... @@ -1640,10 +1640,11 @@
1640 1640 .read_permanent_attributes = fsl_read_permanent_attributes,
1641 1641 .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash,
1642 1642 #ifdef CONFIG_IMX_TRUSTY_OS
1643   - .set_key_version = fsl_write_rollback_index_rpmb
  1643 + .set_key_version = fsl_write_rollback_index_rpmb,
1644 1644 #else
1645   - .set_key_version = fsl_set_key_version
  1645 + .set_key_version = fsl_set_key_version,
1646 1646 #endif
  1647 + .get_random = fsl_get_random
1647 1648 };
1648 1649 #endif
1649 1650 static AvbOps fsl_avb_ops = {
... ... @@ -3320,6 +3321,27 @@
3320 3321 strcpy(response, "FAILInternal error!");
3321 3322 else
3322 3323 strcpy(response, "OKAY");
  3324 + } else if (endswith(cmd, FASTBOOT_AT_GET_UNLOCK_CHALLENGE)) {
  3325 + if (avb_atx_get_unlock_challenge(fsl_avb_ops.atx_ops,
  3326 + interface.transfer_buffer, &download_bytes))
  3327 + strcpy(response, "FAILInternal error!");
  3328 + else
  3329 + strcpy(response, "OKAY");
  3330 + } else if (endswith(cmd, FASTBOOT_AT_UNLOCK_VBOOT)) {
  3331 +#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK
  3332 + if (avb_atx_verify_unlock_credential(fsl_avb_ops.atx_ops,
  3333 + interface.transfer_buffer))
  3334 + strcpy(response, "FAILIncorrect unlock credential!");
  3335 + else {
  3336 +#endif
  3337 + status = do_fastboot_unlock(true);
  3338 + if (status != FASTBOOT_LOCK_ERROR)
  3339 + strcpy(response, "OKAY");
  3340 + else
  3341 + strcpy(response, "FAILunlock device failed.");
  3342 +#ifdef CONFIG_AT_AUTHENTICATE_UNLOCK
  3343 + }
  3344 +#endif
3323 3345 }
3324 3346 #endif /* CONFIG_AVB_ATX */
3325 3347 #ifdef CONFIG_ANDROID_THINGS_SUPPORT
3326 3348  
... ... @@ -3366,11 +3388,18 @@
3366 3388 strcpy(response, "OKAY");
3367 3389 } else if (endswith(cmd, "unlock")) {
3368 3390 printf("flashing unlock.\n");
  3391 +#ifdef CONFIG_AVB_ATX
  3392 + /* We should do nothing here For Android Things which
  3393 + * enables the authenticated unlock feature.
  3394 + */
  3395 + strcpy(response, "OKAY");
  3396 +#else
3369 3397 status = do_fastboot_unlock(false);
3370 3398 if (status != FASTBOOT_LOCK_ERROR)
3371 3399 strcpy(response, "OKAY");
3372 3400 else
3373 3401 strcpy(response, "FAILunlock device failed.");
  3402 +#endif
3374 3403 } else if (endswith(cmd, "lock")) {
3375 3404 printf("flashing lock.\n");
3376 3405 status = do_fastboot_lock();
... ... @@ -3438,7 +3467,8 @@
3438 3467 /* initialize the response buffer */
3439 3468 fb_response_str = response;
3440 3469  
3441   -#ifdef CONFIG_FASTBOOT_LOCK
  3470 + /* Always enable image flash for Android Things. */
  3471 +#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX)
3442 3472 /* for imx8 boot from USB, lock status can be ignored for uuu.*/
3443 3473 if (!(is_imx8() || is_imx8m()) || !(is_boot_from_usb())) {
3444 3474 int status;
... ... @@ -3462,6 +3492,7 @@
3462 3492 fastboot_fail("no flash device defined");
3463 3493  
3464 3494 rx_process_flash(cmd);
  3495 +
3465 3496 #ifdef CONFIG_FASTBOOT_LOCK
3466 3497 if (strncmp(cmd, "gpt", 3) == 0) {
3467 3498 int gpt_valid = 0;
... ... @@ -3497,7 +3528,7 @@
3497 3528 /* initialize the response buffer */
3498 3529 fb_response_str = response;
3499 3530  
3500   -#ifdef CONFIG_FASTBOOT_LOCK
  3531 +#if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX)
3501 3532 FbLockState status;
3502 3533 status = fastboot_get_lock_stat();
3503 3534 if (status == FASTBOOT_LOCK) {
include/configs/imx8mq_evk_androidthings.h
... ... @@ -10,7 +10,6 @@
10 10 #define CONFIG_CMD_READ
11 11  
12 12 #define CONFIG_ANDROID_AB_SUPPORT
13   -#define CONFIG_AVB_SUPPORT
14 13 #define CONFIG_SUPPORT_EMMC_RPMB
15 14 #define CONFIG_SYSTEM_RAMDISK_SUPPORT
16 15 #define CONFIG_AVB_FUSE_BANK_SIZEW 0
... ... @@ -51,6 +50,10 @@
51 50 #define TEE_LOAD_ADDR_1G 0x7e000000
52 51 #define TEE_LOAD_ADDR_3G 0xfe000000
53 52  
  53 +
  54 +#define KEYSLOT_HWPARTITION_ID 2
  55 +#define KEYSLOT_BLKS 0x1FFF
  56 +
54 57 #ifdef CONFIG_SPL_BUILD
55 58  
56 59 #define CONFIG_SPL_SHA256
... ... @@ -64,8 +67,6 @@
64 67 #define BOOTLOADER_RBIDX_START 0x1F000
65 68 #define BOOTLOADER_RBIDX_LEN 0x08
66 69 #define BOOTLOADER_RBIDX_INITVAL 0
67   -#define KEYSLOT_HWPARTITION_ID 2
68   -#define KEYSLOT_BLKS 0x1FFF
69 70 #endif
70 71  
71 72 #else
... ... @@ -236,12 +236,27 @@
236 236 AvbSlotVerifyFlags flags,
237 237 AvbHashtreeErrorMode hashtree_error_mode,
238 238 AvbSlotVerifyData** out_data);
  239 +/* Generates |num_bytes| random bytes and stores them in |output|,
  240 + * which must point to a buffer large enough to store the bytes.
  241 + *
  242 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  243 + */
  244 +AvbIOResult fsl_get_random(AvbAtxOps* atx_ops,
  245 + size_t num_bytes,
  246 + uint8_t* output);
239 247  
240 248 /* Program ATX perm_attr into RPMB partition */
241 249 int avb_atx_fuse_perm_attr(uint8_t *staged_buffer, uint32_t size);
242 250  
243 251 /* Initialize rpmb key with the staged key */
244 252 int fastboot_set_rpmb_key(uint8_t *staged_buf, uint32_t key_size);
  253 +
  254 +/* Generate ATX unlock challenge */
  255 +int avb_atx_get_unlock_challenge(struct AvbAtxOps* atx_ops,
  256 + uint8_t *upload_buffer, uint32_t *size);
  257 +/* Verify ATX unlock credential */
  258 +int avb_atx_verify_unlock_credential(struct AvbAtxOps* atx_ops,
  259 + uint8_t *staged_buffer);
245 260  
246 261 #endif /* __FSL_AVB_H__ */
include/fsl_fastboot.h
... ... @@ -96,6 +96,8 @@
96 96 #define FASTBOOT_BOOTLOADER_VBOOT_KEY "fuse at-bootloader-vboot-key"
97 97 #ifdef CONFIG_AVB_ATX
98 98 #define FASTBOOT_AVB_AT_PERM_ATTR "fuse at-perm-attr"
  99 +#define FASTBOOT_AT_UNLOCK_VBOOT "at-unlock-vboot"
  100 +#define FASTBOOT_AT_GET_UNLOCK_CHALLENGE "at-get-vboot-unlock-challenge"
99 101 #endif /* CONFIG_AVB_ATX */
100 102 #endif /* CONFIG_ANDROID_THINGS_SUPPORT */
101 103  
... ... @@ -127,6 +127,9 @@
127 127 help
128 128 Enable A/B bootloader select in SPL.
129 129  
  130 +config AT_AUTHENTICATE_UNLOCK
  131 + bool "Enable authenticate unlock for Android Things devices"
  132 +
130 133 source lib/dhry/Kconfig
131 134  
132 135 menu "Security support"
lib/avb/fsl/fsl_avbkey.c
... ... @@ -235,6 +235,54 @@
235 235 #endif
236 236 }
237 237  
  238 +int avb_atx_get_unlock_challenge(struct AvbAtxOps* atx_ops,
  239 + uint8_t *upload_buffer, uint32_t *upload_size)
  240 +{
  241 + struct AvbAtxUnlockChallenge *buf = NULL;
  242 + int ret, size;
  243 +
  244 + size = sizeof(struct AvbAtxUnlockChallenge);
  245 + buf = (struct AvbAtxUnlockChallenge *)malloc(size);
  246 + if (buf == NULL) {
  247 + ERR("unable to alloc memory!\n");
  248 + return -1;
  249 + }
  250 +
  251 + if (avb_atx_generate_unlock_challenge(atx_ops, buf) !=
  252 + AVB_IO_RESULT_OK) {
  253 + ERR("generate unlock challenge fail!\n");
  254 + ret = -1;
  255 + goto fail;
  256 + }
  257 + /* Current avbtool only accept 16 bytes random numbers as unlock
  258 + * challenge, need to return the whole 'AvbAtxUnlockChallenge'
  259 + * when avbtool is ready.
  260 + */
  261 + memcpy(upload_buffer, buf->challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE);
  262 + *upload_size = AVB_ATX_UNLOCK_CHALLENGE_SIZE;
  263 + ret = 0;
  264 +fail:
  265 + if (buf != NULL)
  266 + free(buf);
  267 + return ret;
  268 +}
  269 +
  270 +int avb_atx_verify_unlock_credential(struct AvbAtxOps* atx_ops,
  271 + uint8_t *staged_buffer)
  272 +{
  273 + bool out_is_trusted;
  274 + AvbIOResult ret;
  275 + const AvbAtxUnlockCredential* buf = NULL;
  276 +
  277 + buf = (const AvbAtxUnlockCredential*)staged_buffer;
  278 + ret = avb_atx_validate_unlock_credential(atx_ops, buf, &out_is_trusted);
  279 + if ((ret != AVB_IO_RESULT_OK) || (out_is_trusted != true)) {
  280 + ERR("validate unlock credential fail!\n");
  281 + return -1;
  282 + } else
  283 + return 0;
  284 +}
  285 +
238 286 /* Reads permanent |attributes| data. There are no restrictions on where this
239 287 * data is stored. On success, returns AVB_IO_RESULT_OK and populates
240 288 * |attributes|.
... ... @@ -304,6 +352,33 @@
304 352 #endif /* CONFIG_ARM64 */
305 353 }
306 354  
  355 + /* Generates |num_bytes| random bytes and stores them in |output|,
  356 + * which must point to a buffer large enough to store the bytes.
  357 + *
  358 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  359 + */
  360 +AvbIOResult fsl_get_random(AvbAtxOps* atx_ops,
  361 + size_t num_bytes,
  362 + uint8_t* output)
  363 +{
  364 + uint32_t num = 0;
  365 + uint32_t i;
  366 +
  367 + if (output == NULL) {
  368 + ERR("Output buffer is NULL!\n");
  369 + return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
  370 + }
  371 +
  372 + /* set the seed as device boot time. */
  373 + srand((uint32_t)get_timer(0));
  374 + for (i = 0; i < num_bytes; i++) {
  375 + num = rand() % 256;
  376 + output[i] = (uint8_t)num;
  377 + }
  378 +
  379 + return AVB_IO_RESULT_OK;
  380 +}
  381 +
307 382 #endif /* CONFIG_AVB_ATX */
308 383 #endif /* CONFIG_SPL_BUILD */
309 384  
... ... @@ -1386,7 +1461,6 @@
1386 1461 if (plain_idx != NULL)
1387 1462 free(plain_idx);
1388 1463 }
1389   -
1390 1464 #endif /* AVB_RPMB && CONFIG_AVB_ATX */
1391 1465  
1392 1466 #if defined(CONFIG_IMX_TRUSTY_OS) && defined(CONFIG_ANDROID_AUTO_SUPPORT)