1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "avb_utils.h" 18 19 #include <android-base/strings.h> 20 #include <libavb/libavb.h> 21 22 #include "fec_private.h" 23 24 int parse_vbmeta_from_footer(fec_handle *f, std::vector<uint8_t> *vbmeta) { 25 if (f->size <= AVB_FOOTER_SIZE) { 26 debug("file size not large enough to be avb images:" PRIu64, f->size); 27 return -1; 28 } 29 30 AvbFooter footer_read; 31 if (!raw_pread(f->fd, &footer_read, AVB_FOOTER_SIZE, 32 f->size - AVB_FOOTER_SIZE)) { 33 error("failed to read footer: %s", strerror(errno)); 34 return -1; 35 } 36 37 AvbFooter footer; 38 if (!avb_footer_validate_and_byteswap(&footer_read, &footer)) { 39 debug("invalid avb footer"); 40 return -1; 41 } 42 uint64_t vbmeta_offset = footer.vbmeta_offset; 43 uint64_t vbmeta_size = footer.vbmeta_size; 44 check(vbmeta_offset <= f->size - sizeof(footer) - vbmeta_size); 45 46 std::vector<uint8_t> vbmeta_data(vbmeta_size, 0); 47 // TODO(xunchang) handle the sparse image with libsparse. 48 if (!raw_pread(f->fd, vbmeta_data.data(), vbmeta_data.size(), 49 vbmeta_offset)) { 50 error("failed to read avb vbmeta: %s", strerror(errno)); 51 return -1; 52 } 53 54 if (auto status = avb_vbmeta_image_verify( 55 vbmeta_data.data(), vbmeta_data.size(), nullptr, nullptr); 56 status != AVB_VBMETA_VERIFY_RESULT_OK && 57 status != AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED) { 58 error("failed to verify avb vbmeta, status: %d", status); 59 return -1; 60 } 61 *vbmeta = std::move(vbmeta_data); 62 return 0; 63 } 64 65 int parse_avb_image(fec_handle *f, const std::vector<uint8_t> &vbmeta) { 66 // TODO(xunchang) check if avb verification or hashtree is disabled. 67 68 // Look for the hashtree descriptor, we expect exactly one descriptor in 69 // vbmeta. 70 // TODO(xunchang) handle the image with AvbHashDescriptor. 71 auto parse_descriptor = [](const AvbDescriptor *descriptor, 72 void *user_data) { 73 if (descriptor && 74 avb_be64toh(descriptor->tag) == AVB_DESCRIPTOR_TAG_HASHTREE) { 75 auto desp = static_cast<const AvbDescriptor **>(user_data); 76 *desp = descriptor; 77 return false; 78 } 79 return true; 80 }; 81 82 const AvbHashtreeDescriptor *hashtree_descriptor_ptr = nullptr; 83 avb_descriptor_foreach(vbmeta.data(), vbmeta.size(), parse_descriptor, 84 &hashtree_descriptor_ptr); 85 if (!hashtree_descriptor_ptr) { 86 error("failed to find avb hashtree descriptor"); 87 return -1; 88 } 89 90 AvbHashtreeDescriptor hashtree_descriptor; 91 if (!avb_hashtree_descriptor_validate_and_byteswap(hashtree_descriptor_ptr, 92 &hashtree_descriptor)) { 93 error("failed to verify avb hashtree descriptor"); 94 return -1; 95 } 96 97 // The partition name, salt, root append right after the hashtree 98 // descriptor. 99 auto read_ptr = reinterpret_cast<const uint8_t *>(hashtree_descriptor_ptr); 100 // Calculate the offset with respect to the vbmeta; and check both the 101 // salt & root are within the range. 102 uint32_t salt_offset = 103 sizeof(AvbHashtreeDescriptor) + hashtree_descriptor.partition_name_len; 104 uint32_t root_offset = salt_offset + hashtree_descriptor.salt_len; 105 check(hashtree_descriptor.salt_len < vbmeta.size()); 106 check(salt_offset < vbmeta.size() - hashtree_descriptor.salt_len); 107 check(hashtree_descriptor.root_digest_len < vbmeta.size()); 108 check(root_offset < vbmeta.size() - hashtree_descriptor.root_digest_len); 109 std::vector<uint8_t> salt( 110 read_ptr + salt_offset, 111 read_ptr + salt_offset + hashtree_descriptor.salt_len); 112 std::vector<uint8_t> root_hash( 113 read_ptr + root_offset, 114 read_ptr + root_offset + hashtree_descriptor.root_digest_len); 115 116 // Expect the AVB image has the format: 117 // 1. hashtree 118 // 2. ecc data 119 // 3. vbmeta 120 // 4. avb footer 121 check(hashtree_descriptor.fec_offset == 122 hashtree_descriptor.tree_offset + hashtree_descriptor.tree_size); 123 check(hashtree_descriptor.fec_offset <= 124 f->size - hashtree_descriptor.fec_size); 125 126 f->data_size = hashtree_descriptor.fec_offset; 127 128 f->ecc.blocks = fec_div_round_up(f->data_size, FEC_BLOCKSIZE); 129 f->ecc.rounds = fec_div_round_up(f->ecc.blocks, f->ecc.rsn); 130 f->ecc.size = hashtree_descriptor.fec_size; 131 f->ecc.start = hashtree_descriptor.fec_offset; 132 // TODO(xunchang) verify the integrity of the ecc data. 133 f->ecc.valid = true; 134 135 std::string hash_algorithm = 136 reinterpret_cast<char *>(hashtree_descriptor.hash_algorithm); 137 int nid = -1; 138 if (android::base::EqualsIgnoreCase(hash_algorithm, "sha1")) { 139 nid = NID_sha1; 140 } else if (android::base::EqualsIgnoreCase(hash_algorithm, "sha256")) { 141 nid = NID_sha256; 142 } else { 143 error("unsupported hash algorithm %s", hash_algorithm.c_str()); 144 } 145 146 hashtree_info hashtree; 147 hashtree.initialize(hashtree_descriptor.tree_offset, 148 hashtree_descriptor.tree_offset / FEC_BLOCKSIZE, salt, 149 nid); 150 if (hashtree.verify_tree(f, root_hash.data()) != 0) { 151 error("failed to verify hashtree"); 152 return -1; 153 } 154 155 // We have validate the hashtree, 156 f->data_size = hashtree.hash_start; 157 f->avb = { 158 .valid = true, 159 .vbmeta = vbmeta, 160 .hashtree = std::move(hashtree), 161 }; 162 163 return 0; 164 } 165