| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| |
| #include <common.h> |
| #include <malloc.h> |
| #include <image.h> |
| #include <u-boot/sha256.h> |
| #include <amlogic/aml_efuse.h> |
| #include <amlogic/image_check.h> |
| #include <amlogic/aml_crypto.h> |
| |
| extern struct scs_krnl_key_t __scs_krnl_devkey; |
| extern struct scs_krnl_key_t __scs_ext_krnl_devkey; |
| |
| static int is_boot_image(unsigned long img_addr) |
| { |
| if ((android_image_check_header((boot_img_hdr_t *)img_addr) == 0) || |
| (vendor_boot_image_check_header((vendor_boot_img_hdr_t *)img_addr) == 0)) |
| return 1; |
| |
| return 0; |
| } |
| |
| int android_image_check_offset(void) |
| { |
| return BOOT_IMG_V3_HDR_SIZE + sizeof(struct aml_boot_header_t); |
| } |
| |
| /** kernel/misc image verify [and decrypt]. |
| * Returns 0 on success |
| */ |
| int secure_image_check(u8 *data, u32 size, unsigned long option) |
| { |
| struct aml_boot_header_t hdr; |
| int ret = AML_SECURE_BOOT_ERR_NONE; |
| u8 *img = NULL; |
| u8 buf[SHA256_DIGEST_SIZE]; |
| int secure_boot_enabled = IS_FEAT_BOOT_VERIFY(); |
| int encryption_enabled = IS_FEAT_BOOT_ENCRYPT(); |
| int isbootimage = is_boot_image((unsigned long)data); |
| const u64 magic = 0x38a41024204c4d40; |
| struct rsa_public_key key; |
| u32 workbuf[4 * MAX_RSANUMWORDS]; |
| struct scs_krnl_key_t *scs_key; |
| |
| if (!secure_boot_enabled) |
| goto exit; |
| |
| if (option == IMAGE_CHECK_EXT) |
| scs_key = &__scs_ext_krnl_devkey; |
| else |
| scs_key = &__scs_krnl_devkey; |
| |
| if (memcmp(&scs_key->cmn_hdr.magic_u64, &magic, sizeof(magic))) { |
| ret = AML_SECURE_BOOT_ERR_KEY; |
| goto exit; |
| } |
| |
| img = data + sizeof(struct aml_boot_header_t); |
| |
| if (isbootimage) { |
| memcpy((void *)&hdr, (void *)(data + BOOT_IMG_V3_HDR_SIZE), |
| sizeof(struct aml_boot_header_t)); |
| if (hdr.magic == AML_BOOT_IMAGE_MAGIC) { |
| img += BOOT_IMG_V3_HDR_SIZE; |
| } else { |
| isbootimage = 0; |
| memcpy((void *)&hdr, (void *)data, sizeof(struct aml_boot_header_t)); |
| } |
| } else { |
| memcpy((void *)&hdr, (void *)data, sizeof(struct aml_boot_header_t)); |
| } |
| |
| if (hdr.magic != AML_BOOT_IMAGE_MAGIC) { |
| ret = AML_SECURE_BOOT_ERR_INVALID; |
| goto exit; |
| } |
| |
| /* check img payload is in mem region checked size */ |
| if (size < hdr.img_size + sizeof(struct aml_boot_header_t)) { |
| ret = AML_SECURE_BOOT_ERR_SIZE; |
| goto exit; |
| } |
| |
| if (hdr.version != AML_BOOT_IMAGE_VERSION) { |
| ret = AML_SECURE_BOOT_ERR_VERSION; |
| goto exit; |
| } |
| |
| key.len = scs_key->pubrsa_key.nword32; |
| memcpy(key.n, scs_key->pubrsa_key.n, key.len * sizeof(u32)); |
| memcpy(key.rr, scs_key->pubrsa_key.rr, key.len * sizeof(u32)); |
| key.e = scs_key->pubrsa_key.e; |
| key.n0inv = *(u32 *)scs_key->pubrsa_key.ninv128; |
| |
| sha256_csum_wd((u8 *)&hdr, sizeof(struct aml_boot_header_t) - 512, buf, 0); |
| ret = image_rsa_verify(&key, hdr.rsa_sig, buf, workbuf); |
| |
| if (ret != 1) { |
| ret = AML_SECURE_BOOT_ERR_HEADER_SIG; |
| goto exit; |
| } else { |
| if (encryption_enabled) { |
| flush_dcache_range((unsigned long)img, (unsigned long)img + hdr.img_size); |
| aes256cbc_iv0_dec_keytbl(img, img, hdr.img_size, |
| SBOOT_BL2_ENCRYPT_KEYSLOT); |
| } |
| |
| sha256_csum_wd(img, hdr.img_size, buf, 0); |
| |
| if (memcmp(hdr.img_hash, buf, 32)) |
| ret = AML_SECURE_BOOT_ERR_IMG_HASH; |
| else |
| ret = AML_SECURE_BOOT_ERR_NONE; |
| } |
| |
| exit: |
| |
| memset(buf, 0, sizeof(buf)); |
| memset(&hdr, 0, sizeof(hdr)); |
| |
| return ret; |
| } |