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
parse_vbmeta_from_footer(fec_handle * f,std::vector<uint8_t> * vbmeta)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
parse_avb_image(fec_handle * f,const std::vector<uint8_t> & vbmeta)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