137a7bc39SJason Zhu /* 237a7bc39SJason Zhu * Copyright (C) 2017 The Android Open Source Project 337a7bc39SJason Zhu * 437a7bc39SJason Zhu * Permission is hereby granted, free of charge, to any person 537a7bc39SJason Zhu * obtaining a copy of this software and associated documentation 637a7bc39SJason Zhu * files (the "Software"), to deal in the Software without 737a7bc39SJason Zhu * restriction, including without limitation the rights to use, copy, 837a7bc39SJason Zhu * modify, merge, publish, distribute, sublicense, and/or sell copies 937a7bc39SJason Zhu * of the Software, and to permit persons to whom the Software is 1037a7bc39SJason Zhu * furnished to do so, subject to the following conditions: 1137a7bc39SJason Zhu * 1237a7bc39SJason Zhu * The above copyright notice and this permission notice shall be 1337a7bc39SJason Zhu * included in all copies or substantial portions of the Software. 1437a7bc39SJason Zhu * 1537a7bc39SJason Zhu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1637a7bc39SJason Zhu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1737a7bc39SJason Zhu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1837a7bc39SJason Zhu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1937a7bc39SJason Zhu * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2037a7bc39SJason Zhu * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2137a7bc39SJason Zhu * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2237a7bc39SJason Zhu * SOFTWARE. 2337a7bc39SJason Zhu */ 2437a7bc39SJason Zhu 2537a7bc39SJason Zhu #include <common.h> 2637a7bc39SJason Zhu #include <image.h> 2737a7bc39SJason Zhu #include <android_image.h> 2837a7bc39SJason Zhu #include <malloc.h> 2937a7bc39SJason Zhu #include <mapmem.h> 3037a7bc39SJason Zhu #include <errno.h> 3137a7bc39SJason Zhu #include <command.h> 3237a7bc39SJason Zhu #include <mmc.h> 3337a7bc39SJason Zhu #include <blk.h> 3437a7bc39SJason Zhu #include <part.h> 3516a62313SJason Zhu #include <stdio.h> 3637a7bc39SJason Zhu #include <android_avb/avb_ops_user.h> 3737a7bc39SJason Zhu #include <android_avb/libavb_ab.h> 3837a7bc39SJason Zhu #include <android_avb/avb_atx_validate.h> 3937a7bc39SJason Zhu #include <android_avb/avb_atx_types.h> 4037a7bc39SJason Zhu #include <optee_include/OpteeClientInterface.h> 4137a7bc39SJason Zhu #include <optee_include/tee_api_defines.h> 4237a7bc39SJason Zhu #include <android_avb/avb_vbmeta_image.h> 4337a7bc39SJason Zhu #include <android_avb/avb_atx_validate.h> 44459bc933SJason Zhu #include <boot_rkimg.h> 4537a7bc39SJason Zhu 4637a7bc39SJason Zhu static void byte_to_block(int64_t *offset, 4737a7bc39SJason Zhu size_t *num_bytes, 4837a7bc39SJason Zhu lbaint_t *offset_blk, 4937a7bc39SJason Zhu lbaint_t *blkcnt) 5037a7bc39SJason Zhu { 5137a7bc39SJason Zhu *offset_blk = (lbaint_t)(*offset / 512); 5237a7bc39SJason Zhu if (*num_bytes % 512 == 0) { 537c1937d6SJason Zhu if (*offset % 512 == 0) 5437a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512); 557c1937d6SJason Zhu else 5637a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 5737a7bc39SJason Zhu } else { 5837a7bc39SJason Zhu if (*offset % 512 == 0) { 5937a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 6037a7bc39SJason Zhu } else { 6137a7bc39SJason Zhu if ((*offset % 512) + (*num_bytes % 512) < 512 || 6237a7bc39SJason Zhu (*offset % 512) + (*num_bytes % 512) == 512) { 6337a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 1; 6437a7bc39SJason Zhu } else { 6537a7bc39SJason Zhu *blkcnt = (lbaint_t)(*num_bytes / 512) + 2; 6637a7bc39SJason Zhu } 6737a7bc39SJason Zhu } 6837a7bc39SJason Zhu } 6937a7bc39SJason Zhu } 7037a7bc39SJason Zhu 7116a62313SJason Zhu static AvbIOResult get_size_of_partition(AvbOps *ops, 7216a62313SJason Zhu const char *partition, 7316a62313SJason Zhu uint64_t *out_size_in_bytes) 7416a62313SJason Zhu { 7516a62313SJason Zhu struct blk_desc *dev_desc; 7616a62313SJason Zhu disk_partition_t part_info; 7716a62313SJason Zhu 7816a62313SJason Zhu dev_desc = rockchip_get_bootdev(); 7916a62313SJason Zhu if (!dev_desc) { 8016a62313SJason Zhu printf("%s: Could not find device\n", __func__); 8116a62313SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 8216a62313SJason Zhu } 8316a62313SJason Zhu 8428317110SJoseph Chen if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) 8516a62313SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 8628317110SJoseph Chen 8716a62313SJason Zhu *out_size_in_bytes = (part_info.size) * 512; 8816a62313SJason Zhu return AVB_IO_RESULT_OK; 8916a62313SJason Zhu } 9016a62313SJason Zhu 9137a7bc39SJason Zhu static AvbIOResult read_from_partition(AvbOps *ops, 9237a7bc39SJason Zhu const char *partition, 9337a7bc39SJason Zhu int64_t offset, 9437a7bc39SJason Zhu size_t num_bytes, 9537a7bc39SJason Zhu void *buffer, 9637a7bc39SJason Zhu size_t *out_num_read) 9737a7bc39SJason Zhu { 9837a7bc39SJason Zhu struct blk_desc *dev_desc; 9937a7bc39SJason Zhu lbaint_t offset_blk, blkcnt; 10037a7bc39SJason Zhu disk_partition_t part_info; 10116a62313SJason Zhu uint64_t partition_size; 10216a62313SJason Zhu 10316a62313SJason Zhu if (offset < 0) { 10416a62313SJason Zhu if (get_size_of_partition(ops, partition, &partition_size)) 10516a62313SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 10616a62313SJason Zhu 10716a62313SJason Zhu if (-offset > partition_size) 10816a62313SJason Zhu return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; 10916a62313SJason Zhu 11016a62313SJason Zhu offset = partition_size - (-offset); 11116a62313SJason Zhu } 11237a7bc39SJason Zhu 11337a7bc39SJason Zhu byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt); 114459bc933SJason Zhu dev_desc = rockchip_get_bootdev(); 11537a7bc39SJason Zhu if (!dev_desc) { 116459bc933SJason Zhu printf("%s: Could not find device\n", __func__); 11737a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 11837a7bc39SJason Zhu } 11937a7bc39SJason Zhu 12037a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 12137a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 12237a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 12337a7bc39SJason Zhu } 12437a7bc39SJason Zhu 12537a7bc39SJason Zhu if ((offset % 512 == 0) && (num_bytes % 512 == 0)) { 1267c1937d6SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, 1277c1937d6SJason Zhu blkcnt, buffer); 12837a7bc39SJason Zhu *out_num_read = blkcnt * 512; 12937a7bc39SJason Zhu } else { 13037a7bc39SJason Zhu char *buffer_temp; 1317c1937d6SJason Zhu 13237a7bc39SJason Zhu buffer_temp = malloc(512 * blkcnt); 1337c1937d6SJason Zhu if (!buffer_temp) { 13437a7bc39SJason Zhu printf("malloc error!\n"); 13537a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_OOM; 13637a7bc39SJason Zhu } 1377c1937d6SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, 1387c1937d6SJason Zhu blkcnt, buffer_temp); 13937a7bc39SJason Zhu memcpy(buffer, buffer_temp + (offset % 512), num_bytes); 14037a7bc39SJason Zhu *out_num_read = num_bytes; 14137a7bc39SJason Zhu free(buffer_temp); 14237a7bc39SJason Zhu } 14337a7bc39SJason Zhu 14437a7bc39SJason Zhu return AVB_IO_RESULT_OK; 14537a7bc39SJason Zhu } 14637a7bc39SJason Zhu 14737a7bc39SJason Zhu static AvbIOResult write_to_partition(AvbOps *ops, 14837a7bc39SJason Zhu const char *partition, 14937a7bc39SJason Zhu int64_t offset, 15037a7bc39SJason Zhu size_t num_bytes, 15137a7bc39SJason Zhu const void *buffer) 15237a7bc39SJason Zhu { 15337a7bc39SJason Zhu struct blk_desc *dev_desc; 15437a7bc39SJason Zhu char *buffer_temp; 15537a7bc39SJason Zhu disk_partition_t part_info; 15637a7bc39SJason Zhu lbaint_t offset_blk, blkcnt; 15737a7bc39SJason Zhu 15837a7bc39SJason Zhu byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt); 15937a7bc39SJason Zhu buffer_temp = malloc(512 * blkcnt); 1607c1937d6SJason Zhu if (!buffer_temp) { 16137a7bc39SJason Zhu printf("malloc error!\n"); 16237a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_OOM; 16337a7bc39SJason Zhu } 16437a7bc39SJason Zhu memset(buffer_temp, 0, 512 * blkcnt); 165459bc933SJason Zhu dev_desc = rockchip_get_bootdev(); 16637a7bc39SJason Zhu if (!dev_desc) { 167459bc933SJason Zhu printf("%s: Could not find device\n", __func__); 16837a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 16937a7bc39SJason Zhu } 17037a7bc39SJason Zhu 17137a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 17237a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 17337a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 17437a7bc39SJason Zhu } 17537a7bc39SJason Zhu 1767c1937d6SJason Zhu if ((offset % 512 != 0) && (num_bytes % 512) != 0) 1777c1937d6SJason Zhu blk_dread(dev_desc, part_info.start + offset_blk, 1787c1937d6SJason Zhu blkcnt, buffer_temp); 17937a7bc39SJason Zhu 18037a7bc39SJason Zhu memcpy(buffer_temp, buffer + (offset % 512), num_bytes); 18137a7bc39SJason Zhu blk_dwrite(dev_desc, part_info.start + offset_blk, blkcnt, buffer); 18237a7bc39SJason Zhu free(buffer_temp); 18337a7bc39SJason Zhu 18437a7bc39SJason Zhu return AVB_IO_RESULT_OK; 18537a7bc39SJason Zhu } 18637a7bc39SJason Zhu 1877c1937d6SJason Zhu static AvbIOResult 1887c1937d6SJason Zhu validate_vbmeta_public_key(AvbOps *ops, 18937a7bc39SJason Zhu const uint8_t *public_key_data, 19037a7bc39SJason Zhu size_t public_key_length, 19137a7bc39SJason Zhu const uint8_t *public_key_metadata, 19237a7bc39SJason Zhu size_t public_key_metadata_length, 19337a7bc39SJason Zhu bool *out_is_trusted) 19437a7bc39SJason Zhu { 195caed6b4fSJoseph Chen /* remain AVB_VBMETA_PUBLIC_KEY_VALIDATE to compatible legacy code */ 196caed6b4fSJoseph Chen #if defined(CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE) || \ 197caed6b4fSJoseph Chen defined(AVB_VBMETA_PUBLIC_KEY_VALIDATE) 1987c1937d6SJason Zhu if (out_is_trusted) { 19937a7bc39SJason Zhu avb_atx_validate_vbmeta_public_key(ops, 20037a7bc39SJason Zhu public_key_data, 20137a7bc39SJason Zhu public_key_length, 20237a7bc39SJason Zhu public_key_metadata, 20337a7bc39SJason Zhu public_key_metadata_length, 20437a7bc39SJason Zhu out_is_trusted); 20537a7bc39SJason Zhu } 20637a7bc39SJason Zhu #else 2077c1937d6SJason Zhu if (out_is_trusted) 20837a7bc39SJason Zhu *out_is_trusted = true; 20937a7bc39SJason Zhu #endif 21037a7bc39SJason Zhu return AVB_IO_RESULT_OK; 21137a7bc39SJason Zhu } 21237a7bc39SJason Zhu 21337a7bc39SJason Zhu static AvbIOResult read_rollback_index(AvbOps *ops, 21437a7bc39SJason Zhu size_t rollback_index_location, 21537a7bc39SJason Zhu uint64_t *out_rollback_index) 21637a7bc39SJason Zhu { 2177c1937d6SJason Zhu if (out_rollback_index) { 21837a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 21937a7bc39SJason Zhu int ret; 2207c1937d6SJason Zhu 22137a7bc39SJason Zhu ret = trusty_read_rollback_index(rollback_index_location, 22237a7bc39SJason Zhu out_rollback_index); 2237c1937d6SJason Zhu switch (ret) { 2247c1937d6SJason Zhu case TEE_SUCCESS: 2257c1937d6SJason Zhu ret = AVB_IO_RESULT_OK; 2267c1937d6SJason Zhu break; 2277c1937d6SJason Zhu case TEE_ERROR_GENERIC: 2287c1937d6SJason Zhu case TEE_ERROR_NO_DATA: 2297c1937d6SJason Zhu case TEE_ERROR_ITEM_NOT_FOUND: 23037a7bc39SJason Zhu *out_rollback_index = 0; 23137a7bc39SJason Zhu ret = trusty_write_rollback_index(rollback_index_location, 23237a7bc39SJason Zhu *out_rollback_index); 2337c1937d6SJason Zhu if (ret) { 2347c1937d6SJason Zhu printf("%s: init rollback index error\n", 2357c1937d6SJason Zhu __FILE__); 2367c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 23737a7bc39SJason Zhu } else { 2387c1937d6SJason Zhu ret = 2397c1937d6SJason Zhu trusty_read_rollback_index(rollback_index_location, 2407c1937d6SJason Zhu out_rollback_index); 2417c1937d6SJason Zhu if (ret) 2427c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 2437c1937d6SJason Zhu else 2447c1937d6SJason Zhu ret = AVB_IO_RESULT_OK; 24537a7bc39SJason Zhu } 2467c1937d6SJason Zhu break; 2477c1937d6SJason Zhu default: 2487c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 2497c1937d6SJason Zhu printf("%s: trusty_read_rollback_index failed", 2507c1937d6SJason Zhu __FILE__); 2517c1937d6SJason Zhu } 2527c1937d6SJason Zhu 2537c1937d6SJason Zhu return ret; 254ae205b95SJoseph Chen #else 255ae205b95SJoseph Chen *out_rollback_index = 0; 256ae205b95SJoseph Chen 257ae205b95SJoseph Chen return AVB_IO_RESULT_OK; 25837a7bc39SJason Zhu #endif 25937a7bc39SJason Zhu } 260ae205b95SJoseph Chen 26137a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 26237a7bc39SJason Zhu } 26337a7bc39SJason Zhu 26437a7bc39SJason Zhu static AvbIOResult write_rollback_index(AvbOps *ops, 26537a7bc39SJason Zhu size_t rollback_index_location, 26637a7bc39SJason Zhu uint64_t rollback_index) 26737a7bc39SJason Zhu { 26837a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 2697c1937d6SJason Zhu if (trusty_write_rollback_index(rollback_index_location, 2707c1937d6SJason Zhu rollback_index)) { 27137a7bc39SJason Zhu printf("%s: Fail to write rollback index\n", __FILE__); 27237a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 27337a7bc39SJason Zhu } 27437a7bc39SJason Zhu return AVB_IO_RESULT_OK; 27537a7bc39SJason Zhu #endif 27637a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 27737a7bc39SJason Zhu } 27837a7bc39SJason Zhu 27937a7bc39SJason Zhu static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 28037a7bc39SJason Zhu { 2817c1937d6SJason Zhu if (out_is_unlocked) { 28237a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 283*d9e299e0SJason Zhu uint8_t vboot_flag = 0; 28437a7bc39SJason Zhu int ret; 28537a7bc39SJason Zhu 28637a7bc39SJason Zhu ret = trusty_read_lock_state((uint8_t *)out_is_unlocked); 2877c1937d6SJason Zhu switch (ret) { 2887c1937d6SJason Zhu case TEE_SUCCESS: 2897c1937d6SJason Zhu ret = AVB_IO_RESULT_OK; 2907c1937d6SJason Zhu break; 2917c1937d6SJason Zhu case TEE_ERROR_GENERIC: 2927c1937d6SJason Zhu case TEE_ERROR_NO_DATA: 2937c1937d6SJason Zhu case TEE_ERROR_ITEM_NOT_FOUND: 294*d9e299e0SJason Zhu if (trusty_read_vbootkey_enable_flag(&vboot_flag)) { 295*d9e299e0SJason Zhu printf("Can't read vboot flag\n"); 296*d9e299e0SJason Zhu return AVB_IO_RESULT_ERROR_IO; 297*d9e299e0SJason Zhu } 298*d9e299e0SJason Zhu 299*d9e299e0SJason Zhu if (vboot_flag) 300*d9e299e0SJason Zhu *out_is_unlocked = 0; 301*d9e299e0SJason Zhu else 30237a7bc39SJason Zhu *out_is_unlocked = 1; 303*d9e299e0SJason Zhu 30437a7bc39SJason Zhu if (trusty_write_lock_state(*out_is_unlocked)) { 30537a7bc39SJason Zhu printf("%s: init lock state error\n", __FILE__); 3067c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 30737a7bc39SJason Zhu } else { 3087c1937d6SJason Zhu ret = 3097c1937d6SJason Zhu trusty_read_lock_state((uint8_t *)out_is_unlocked); 3107c1937d6SJason Zhu if (ret == 0) 3117c1937d6SJason Zhu ret = AVB_IO_RESULT_OK; 3127c1937d6SJason Zhu else 3137c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 31437a7bc39SJason Zhu } 3157c1937d6SJason Zhu break; 3167c1937d6SJason Zhu default: 3177c1937d6SJason Zhu ret = AVB_IO_RESULT_ERROR_IO; 3187c1937d6SJason Zhu printf("%s: trusty_read_lock_state failed\n", __FILE__); 3197c1937d6SJason Zhu } 3207c1937d6SJason Zhu return ret; 321ae205b95SJoseph Chen #else 322ae205b95SJoseph Chen *out_is_unlocked = 1; 323ae205b95SJoseph Chen 324ae205b95SJoseph Chen return AVB_IO_RESULT_OK; 32537a7bc39SJason Zhu #endif 32637a7bc39SJason Zhu } 32737a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 32837a7bc39SJason Zhu } 32937a7bc39SJason Zhu 33037a7bc39SJason Zhu static AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 33137a7bc39SJason Zhu { 3327c1937d6SJason Zhu if (out_is_unlocked) { 33337a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 33437a7bc39SJason Zhu if (trusty_write_lock_state(*out_is_unlocked)) { 33537a7bc39SJason Zhu printf("%s: Fail to write lock state\n", __FILE__); 33637a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 33737a7bc39SJason Zhu } 33837a7bc39SJason Zhu return AVB_IO_RESULT_OK; 33937a7bc39SJason Zhu #endif 34037a7bc39SJason Zhu } 34137a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_IO; 34237a7bc39SJason Zhu } 34337a7bc39SJason Zhu 34437a7bc39SJason Zhu static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, 34537a7bc39SJason Zhu const char *partition, 34637a7bc39SJason Zhu char *guid_buf, 34737a7bc39SJason Zhu size_t guid_buf_size) 34837a7bc39SJason Zhu { 34937a7bc39SJason Zhu struct blk_desc *dev_desc; 35037a7bc39SJason Zhu disk_partition_t part_info; 3517c1937d6SJason Zhu 352459bc933SJason Zhu dev_desc = rockchip_get_bootdev(); 35337a7bc39SJason Zhu if (!dev_desc) { 354459bc933SJason Zhu printf("%s: Could not find device\n", __func__); 35537a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 35637a7bc39SJason Zhu } 35737a7bc39SJason Zhu 35837a7bc39SJason Zhu if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 35937a7bc39SJason Zhu printf("Could not find \"%s\" partition\n", partition); 36037a7bc39SJason Zhu return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 36137a7bc39SJason Zhu } 3627c1937d6SJason Zhu if (guid_buf && guid_buf_size > 0) 36337a7bc39SJason Zhu memcpy(guid_buf, part_info.uuid, guid_buf_size); 3647c1937d6SJason Zhu 36537a7bc39SJason Zhu return AVB_IO_RESULT_OK; 36637a7bc39SJason Zhu } 36737a7bc39SJason Zhu 36837a7bc39SJason Zhu /* read permanent attributes from rpmb */ 36937a7bc39SJason Zhu AvbIOResult avb_read_perm_attr(AvbAtxOps *atx_ops, 37037a7bc39SJason Zhu AvbAtxPermanentAttributes *attributes) 37137a7bc39SJason Zhu { 3727c1937d6SJason Zhu if (attributes) { 37337a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 37437a7bc39SJason Zhu trusty_read_permanent_attributes((uint8_t *)attributes, 37537a7bc39SJason Zhu sizeof(struct AvbAtxPermanentAttributes)); 37637a7bc39SJason Zhu return AVB_IO_RESULT_OK; 37737a7bc39SJason Zhu #endif 37837a7bc39SJason Zhu } 37937a7bc39SJason Zhu 38037a7bc39SJason Zhu return -1; 38137a7bc39SJason Zhu } 38237a7bc39SJason Zhu 38337a7bc39SJason Zhu /*read permanent attributes hash from efuse */ 38437a7bc39SJason Zhu AvbIOResult avb_read_perm_attr_hash(AvbAtxOps *atx_ops, 38537a7bc39SJason Zhu uint8_t hash[AVB_SHA256_DIGEST_SIZE]) 38637a7bc39SJason Zhu { 38774b485fbSJason Zhu #ifndef CONFIG_ROCKCHIP_PRELOADER_PUB_KEY 38837a7bc39SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 3897c1937d6SJason Zhu if (trusty_read_attribute_hash((uint32_t *)hash, 3907c1937d6SJason Zhu AVB_SHA256_DIGEST_SIZE / 4)) 39137a7bc39SJason Zhu return -1; 39237a7bc39SJason Zhu #else 393647502d6SJason Zhu printf("Please open the macro!\n"); 39437a7bc39SJason Zhu return -1; 39537a7bc39SJason Zhu #endif 39665f0143bSJason Zhu #endif 39737a7bc39SJason Zhu return AVB_IO_RESULT_OK; 39837a7bc39SJason Zhu } 39937a7bc39SJason Zhu 40082e713e1SJason Zhu static void avb_set_key_version(AvbAtxOps *atx_ops, 40182e713e1SJason Zhu size_t rollback_index_location, 40282e713e1SJason Zhu uint64_t key_version) 40382e713e1SJason Zhu { 40482e713e1SJason Zhu #ifdef CONFIG_OPTEE_CLIENT 405ee9d3433SJason Zhu uint64_t key_version_temp = 0; 406ee9d3433SJason Zhu 407ee9d3433SJason Zhu if (trusty_read_rollback_index(rollback_index_location, &key_version_temp)) 408ee9d3433SJason Zhu printf("%s: Fail to read rollback index\n", __FILE__); 409ee9d3433SJason Zhu if (key_version_temp == key_version) 410ee9d3433SJason Zhu return; 4117c1937d6SJason Zhu if (trusty_write_rollback_index(rollback_index_location, key_version)) 41282e713e1SJason Zhu printf("%s: Fail to write rollback index\n", __FILE__); 41382e713e1SJason Zhu #endif 41482e713e1SJason Zhu } 41582e713e1SJason Zhu 4168d0db1d9SJason Zhu AvbIOResult rk_get_random(AvbAtxOps *atx_ops, 4178d0db1d9SJason Zhu size_t num_bytes, 4188d0db1d9SJason Zhu uint8_t *output) 4198d0db1d9SJason Zhu { 4208d0db1d9SJason Zhu int i; 4218d0db1d9SJason Zhu unsigned int seed; 4228d0db1d9SJason Zhu 4238d0db1d9SJason Zhu seed = (unsigned int)get_timer(0); 4248d0db1d9SJason Zhu for (i = 0; i < num_bytes; i++) { 4258d0db1d9SJason Zhu srand(seed); 4268d0db1d9SJason Zhu output[i] = (uint8_t)(rand()); 4278d0db1d9SJason Zhu seed = (unsigned int)(output[i]); 4288d0db1d9SJason Zhu } 4298d0db1d9SJason Zhu 4308d0db1d9SJason Zhu return 0; 4318d0db1d9SJason Zhu } 4328d0db1d9SJason Zhu 43327e62cd7SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 43427e62cd7SJoseph Chen static AvbIOResult get_preloaded_partition(AvbOps* ops, 43527e62cd7SJoseph Chen const char* partition, 43627e62cd7SJoseph Chen size_t num_bytes, 43727e62cd7SJoseph Chen uint8_t** out_pointer, 43827e62cd7SJoseph Chen size_t* out_num_bytes_preloaded, 43927e62cd7SJoseph Chen int allow_verification_error) 44027e62cd7SJoseph Chen { 44128317110SJoseph Chen struct preloaded_partition *preload_info = NULL; 44228317110SJoseph Chen struct AvbOpsData *data = ops->user_data; 44327e62cd7SJoseph Chen struct blk_desc *dev_desc; 44428317110SJoseph Chen disk_partition_t part_info; 44527e62cd7SJoseph Chen ulong load_addr; 44628317110SJoseph Chen AvbIOResult ret; 44727e62cd7SJoseph Chen 44827e62cd7SJoseph Chen dev_desc = rockchip_get_bootdev(); 44927e62cd7SJoseph Chen if (!dev_desc) 45028317110SJoseph Chen return AVB_IO_RESULT_ERROR_IO; 45127e62cd7SJoseph Chen 45228317110SJoseph Chen if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 45328317110SJoseph Chen printf("Could not find \"%s\" partition\n", partition); 45428317110SJoseph Chen return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 45528317110SJoseph Chen } 45628317110SJoseph Chen 45728317110SJoseph Chen if (!allow_verification_error) { 45828317110SJoseph Chen if (!strncmp(partition, ANDROID_PARTITION_BOOT, 4) || 45928317110SJoseph Chen !strncmp(partition, ANDROID_PARTITION_RECOVERY, 8)) 46028317110SJoseph Chen preload_info = &data->boot; 46128317110SJoseph Chen else if (!strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11)) 46228317110SJoseph Chen preload_info = &data->vendor_boot; 46328317110SJoseph Chen else if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9)) 46428317110SJoseph Chen preload_info = &data->init_boot; 46536e836f2SJoseph Chen else if (!strncmp(partition, ANDROID_PARTITION_RESOURCE, 8)) 46636e836f2SJoseph Chen preload_info = &data->resource; 46728317110SJoseph Chen 46828317110SJoseph Chen if (!preload_info) { 46928317110SJoseph Chen printf("Error: unknown full load partition '%s'\n", partition); 47028317110SJoseph Chen return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 47128317110SJoseph Chen } 47228317110SJoseph Chen 47336e836f2SJoseph Chen printf("preloaded: %sfull image from '%s' at 0x%08lx - 0x%08lx\n", 47436e836f2SJoseph Chen preload_info->size ? "pre-" : "", partition, 47536e836f2SJoseph Chen (ulong)preload_info->addr, 47628317110SJoseph Chen (ulong)preload_info->addr + num_bytes); 47728317110SJoseph Chen 47828317110SJoseph Chen /* If the partition hasn't yet been preloaded, do it now.*/ 47928317110SJoseph Chen if (preload_info->size == 0) { 48028317110SJoseph Chen ret = ops->read_from_partition(ops, partition, 48128317110SJoseph Chen 0, num_bytes, 48228317110SJoseph Chen preload_info->addr, 48328317110SJoseph Chen &preload_info->size); 48428317110SJoseph Chen if (ret != AVB_IO_RESULT_OK) 48528317110SJoseph Chen return ret; 48628317110SJoseph Chen } 48728317110SJoseph Chen *out_pointer = preload_info->addr; 48828317110SJoseph Chen *out_num_bytes_preloaded = preload_info->size; 48928317110SJoseph Chen ret = AVB_IO_RESULT_OK; 49028317110SJoseph Chen } else { 49128317110SJoseph Chen if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9) || 49228317110SJoseph Chen !strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11) || 49328317110SJoseph Chen !strncmp(partition, ANDROID_PARTITION_BOOT, 4) || 49436e836f2SJoseph Chen !strncmp(partition, ANDROID_PARTITION_RECOVERY, 8) || 49536e836f2SJoseph Chen !strncmp(partition, ANDROID_PARTITION_RESOURCE, 8)) { 49628317110SJoseph Chen printf("preloaded: distribute image from '%s'\n", partition); 49728317110SJoseph Chen } else { 49828317110SJoseph Chen printf("Error: unknown preloaded partition '%s'\n", partition); 49928317110SJoseph Chen return AVB_IO_RESULT_ERROR_OOM; 50028317110SJoseph Chen } 50128317110SJoseph Chen 50228317110SJoseph Chen /* 50328317110SJoseph Chen * Already preloaded during boot/recovery loading, 50428317110SJoseph Chen * here we just return a dummy buffer. 50528317110SJoseph Chen */ 50628317110SJoseph Chen if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9) || 50736e836f2SJoseph Chen !strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11) || 50836e836f2SJoseph Chen !strncmp(partition, ANDROID_PARTITION_RESOURCE, 8)) { 50928317110SJoseph Chen *out_pointer = (u8 *)avb_malloc(ARCH_DMA_MINALIGN); 51028317110SJoseph Chen *out_num_bytes_preloaded = num_bytes; /* return what it expects */ 51128317110SJoseph Chen return AVB_IO_RESULT_OK; 51228317110SJoseph Chen } 51328317110SJoseph Chen 51428317110SJoseph Chen /* 51528317110SJoseph Chen * only boot/recovery partition can reach here 51628317110SJoseph Chen * and init/vendor_boot are loaded at this round. 51728317110SJoseph Chen */ 51827e62cd7SJoseph Chen load_addr = env_get_ulong("kernel_addr_r", 16, 0); 51927e62cd7SJoseph Chen if (!load_addr) 5201e9494b5SJoseph Chen return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 52127e62cd7SJoseph Chen 52227e62cd7SJoseph Chen ret = android_image_load_by_partname(dev_desc, partition, &load_addr); 52327e62cd7SJoseph Chen if (!ret) { 52427e62cd7SJoseph Chen *out_pointer = (u8 *)load_addr; 52527e62cd7SJoseph Chen *out_num_bytes_preloaded = num_bytes; /* return what it expects */ 5261e9494b5SJoseph Chen ret = AVB_IO_RESULT_OK; 52727e62cd7SJoseph Chen } else { 5281e9494b5SJoseph Chen ret = AVB_IO_RESULT_ERROR_IO; 52927e62cd7SJoseph Chen } 53028317110SJoseph Chen } 53127e62cd7SJoseph Chen 53227e62cd7SJoseph Chen return ret; 53327e62cd7SJoseph Chen } 53427e62cd7SJoseph Chen #endif 53527e62cd7SJoseph Chen 53616a62313SJason Zhu AvbIOResult validate_public_key_for_partition(AvbOps *ops, 53716a62313SJason Zhu const char *partition, 53816a62313SJason Zhu const uint8_t *public_key_data, 53916a62313SJason Zhu size_t public_key_length, 54016a62313SJason Zhu const uint8_t *public_key_metadata, 54116a62313SJason Zhu size_t public_key_metadata_length, 54216a62313SJason Zhu bool *out_is_trusted, 54316a62313SJason Zhu uint32_t *out_rollback_index_location) 54416a62313SJason Zhu { 54516a62313SJason Zhu /* remain AVB_VBMETA_PUBLIC_KEY_VALIDATE to compatible legacy code */ 54616a62313SJason Zhu #if defined(CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE) || \ 54716a62313SJason Zhu defined(AVB_VBMETA_PUBLIC_KEY_VALIDATE) 54816a62313SJason Zhu if (out_is_trusted) { 54916a62313SJason Zhu avb_atx_validate_vbmeta_public_key(ops, 55016a62313SJason Zhu public_key_data, 55116a62313SJason Zhu public_key_length, 55216a62313SJason Zhu public_key_metadata, 55316a62313SJason Zhu public_key_metadata_length, 55416a62313SJason Zhu out_is_trusted); 55516a62313SJason Zhu } 55616a62313SJason Zhu #else 55716a62313SJason Zhu if (out_is_trusted) 55816a62313SJason Zhu *out_is_trusted = true; 55916a62313SJason Zhu #endif 56016a62313SJason Zhu *out_rollback_index_location = 0; 56116a62313SJason Zhu return AVB_IO_RESULT_OK; 56216a62313SJason Zhu } 56316a62313SJason Zhu 5647c1937d6SJason Zhu AvbOps *avb_ops_user_new(void) 5657c1937d6SJason Zhu { 56648cf108aSJoseph Chen AvbOps *ops = NULL; 56748cf108aSJoseph Chen struct AvbOpsData *ops_data = NULL; 56837a7bc39SJason Zhu 56937a7bc39SJason Zhu ops = calloc(1, sizeof(AvbOps)); 5707c1937d6SJason Zhu if (!ops) { 57108f7f19aSJason Zhu printf("Error allocating memory for AvbOps.\n"); 57237a7bc39SJason Zhu goto out; 57337a7bc39SJason Zhu } 57437a7bc39SJason Zhu ops->ab_ops = calloc(1, sizeof(AvbABOps)); 5757c1937d6SJason Zhu if (!ops->ab_ops) { 57608f7f19aSJason Zhu printf("Error allocating memory for AvbABOps.\n"); 57737a7bc39SJason Zhu free(ops); 57837a7bc39SJason Zhu goto out; 57937a7bc39SJason Zhu } 58037a7bc39SJason Zhu 58137a7bc39SJason Zhu ops->atx_ops = calloc(1, sizeof(AvbAtxOps)); 5827c1937d6SJason Zhu if (!ops->atx_ops) { 58308f7f19aSJason Zhu printf("Error allocating memory for AvbAtxOps.\n"); 58437a7bc39SJason Zhu free(ops->ab_ops); 58537a7bc39SJason Zhu free(ops); 58637a7bc39SJason Zhu goto out; 58737a7bc39SJason Zhu } 58848cf108aSJoseph Chen 58948cf108aSJoseph Chen ops_data = calloc(1, sizeof(struct AvbOpsData)); 59048cf108aSJoseph Chen if (!ops_data) { 59148cf108aSJoseph Chen printf("Error allocating memory for AvbOpsData.\n"); 59248cf108aSJoseph Chen free(ops->atx_ops); 59348cf108aSJoseph Chen free(ops->ab_ops); 59448cf108aSJoseph Chen free(ops); 59548cf108aSJoseph Chen goto out; 59648cf108aSJoseph Chen } 59748cf108aSJoseph Chen 59837a7bc39SJason Zhu ops->ab_ops->ops = ops; 59937a7bc39SJason Zhu ops->atx_ops->ops = ops; 60048cf108aSJoseph Chen ops_data->ops = ops; 60148cf108aSJoseph Chen ops->user_data = ops_data; 60237a7bc39SJason Zhu 60337a7bc39SJason Zhu ops->read_from_partition = read_from_partition; 60437a7bc39SJason Zhu ops->write_to_partition = write_to_partition; 60537a7bc39SJason Zhu ops->validate_vbmeta_public_key = validate_vbmeta_public_key; 60637a7bc39SJason Zhu ops->read_rollback_index = read_rollback_index; 60737a7bc39SJason Zhu ops->write_rollback_index = write_rollback_index; 60837a7bc39SJason Zhu ops->read_is_device_unlocked = read_is_device_unlocked; 60937a7bc39SJason Zhu ops->write_is_device_unlocked = write_is_device_unlocked; 61037a7bc39SJason Zhu ops->get_unique_guid_for_partition = get_unique_guid_for_partition; 61137a7bc39SJason Zhu ops->get_size_of_partition = get_size_of_partition; 61227e62cd7SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 61327e62cd7SJoseph Chen ops->get_preloaded_partition = get_preloaded_partition; 61427e62cd7SJoseph Chen #endif 61516a62313SJason Zhu ops->validate_public_key_for_partition = validate_public_key_for_partition; 61637a7bc39SJason Zhu ops->ab_ops->read_ab_metadata = avb_ab_data_read; 61737a7bc39SJason Zhu ops->ab_ops->write_ab_metadata = avb_ab_data_write; 61837a7bc39SJason Zhu ops->atx_ops->read_permanent_attributes = avb_read_perm_attr; 61937a7bc39SJason Zhu ops->atx_ops->read_permanent_attributes_hash = avb_read_perm_attr_hash; 62082e713e1SJason Zhu ops->atx_ops->set_key_version = avb_set_key_version; 6218d0db1d9SJason Zhu ops->atx_ops->get_random = rk_get_random; 62237a7bc39SJason Zhu 62337a7bc39SJason Zhu return ops; 62448cf108aSJoseph Chen out: 62548cf108aSJoseph Chen return NULL; 62637a7bc39SJason Zhu } 62737a7bc39SJason Zhu 6287c1937d6SJason Zhu void avb_ops_user_free(AvbOps *ops) 6297c1937d6SJason Zhu { 63048cf108aSJoseph Chen free(ops->user_data); 63137a7bc39SJason Zhu free(ops->ab_ops); 63237a7bc39SJason Zhu free(ops->atx_ops); 63337a7bc39SJason Zhu free(ops); 63437a7bc39SJason Zhu } 635