1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include "libavb_aftl/avb_aftl_verify.h"
26
27 #include <libavb/avb_cmdline.h>
28 #include <libavb/avb_slot_verify.h>
29 #include <libavb/avb_util.h>
30
31 #include "libavb_aftl/avb_aftl_types.h"
32 #include "libavb_aftl/avb_aftl_util.h"
33 #include "libavb_aftl/avb_aftl_validate.h"
34
35 /* Read the vbmeta partition, after the AvbVBMetaImageHeader structure, to find
36 * the AftlImage.
37 */
avb_aftl_find_aftl_image(AvbOps * ops,const char * part_name,size_t vbmeta_size,uint8_t * out_image_buf,size_t * out_image_size)38 static AftlSlotVerifyResult avb_aftl_find_aftl_image(AvbOps* ops,
39 const char* part_name,
40 size_t vbmeta_size,
41 uint8_t* out_image_buf,
42 size_t* out_image_size) {
43 AvbIOResult io_ret;
44
45 avb_assert(vbmeta_size <= AVB_AFTL_MAX_AFTL_IMAGE_SIZE);
46 io_ret = ops->read_from_partition(ops,
47 part_name,
48 vbmeta_size /* offset */,
49 AVB_AFTL_MAX_AFTL_IMAGE_SIZE - vbmeta_size,
50 out_image_buf,
51 out_image_size);
52 switch (io_ret) {
53 case AVB_IO_RESULT_OK:
54 break;
55 case AVB_IO_RESULT_ERROR_OOM:
56 return AFTL_SLOT_VERIFY_RESULT_ERROR_OOM;
57 case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
58 case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
59 return AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND;
60 default:
61 avb_errorv(
62 part_name, ": Error loading AftlImage from partition.\n", NULL);
63 return AFTL_SLOT_VERIFY_RESULT_ERROR_IO;
64 }
65
66 if (*out_image_size < 4 || (out_image_buf[0] != 'A') ||
67 (out_image_buf[1] != 'F') || (out_image_buf[2] != 'T') ||
68 (out_image_buf[3] != 'L')) {
69 avb_errorv(part_name, ": Unexpected AftlImage magic.\n", NULL);
70 return AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND;
71 }
72
73 return AFTL_SLOT_VERIFY_RESULT_OK;
74 }
75
76 /* Performs the three validation steps for an AFTL image:
77 1. Ensure the vbmeta image hash matches that in the image.
78 2. Ensure the root hash of the Merkle tree matches that in the image.
79 3. Verify the signature using the transparency log public key.
80 */
avb_aftl_verify_image(uint8_t * cur_vbmeta_data,size_t cur_vbmeta_size,uint8_t * aftl_blob,size_t aftl_size,uint8_t * key_bytes,size_t key_num_bytes)81 static AftlSlotVerifyResult avb_aftl_verify_image(uint8_t* cur_vbmeta_data,
82 size_t cur_vbmeta_size,
83 uint8_t* aftl_blob,
84 size_t aftl_size,
85 uint8_t* key_bytes,
86 size_t key_num_bytes) {
87 size_t i;
88 AftlImage* image;
89 AftlSlotVerifyResult result = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
90
91 /* Attempt to parse the AftlImage pointed to by aftl_blob. */
92 image = parse_aftl_image(aftl_blob, aftl_size);
93 if (!image) {
94 return AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_IMAGE;
95 }
96
97 /* Now that a valid AftlImage has been parsed, attempt to verify
98 the inclusion proof(s) in three steps. */
99 for (i = 0; i < image->header.icp_count; i++) {
100 /* 1. Ensure that the vbmeta hash stored in the AftlIcpEntry matches
101 the one that represents the partition. */
102 if (!avb_aftl_verify_vbmeta_hash(
103 cur_vbmeta_data, cur_vbmeta_size, image->entries[i])) {
104 avb_error("AFTL vbmeta hash verification failed.\n");
105 result = AFTL_SLOT_VERIFY_RESULT_ERROR_VBMETA_HASH_MISMATCH;
106 break;
107 }
108 /* 2. Ensure that the root hash of the Merkle tree representing
109 the transparency log entry matches the one stored in the
110 AftlIcpEntry. */
111 if (!avb_aftl_verify_icp_root_hash(image->entries[i])) {
112 avb_error("AFTL root hash verification failed.\n");
113 result = AFTL_SLOT_VERIFY_RESULT_ERROR_TREE_HASH_MISMATCH;
114 break;
115 }
116 /* 3. Verify the signature using the transparency log public
117 key stored on device. */
118 if (!avb_aftl_verify_entry_signature(
119 key_bytes, key_num_bytes, image->entries[i])) {
120 avb_error("AFTL signature verification failed on entry.\n");
121 result = AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_PROOF_SIGNATURE;
122 break;
123 }
124 result = AFTL_SLOT_VERIFY_RESULT_OK;
125 }
126 free_aftl_image(image);
127 return result;
128 }
129
aftl_slot_verify(AvbOps * ops,AvbSlotVerifyData * slot_verify_data,uint8_t * key_bytes,size_t key_size)130 AftlSlotVerifyResult aftl_slot_verify(AvbOps* ops,
131 AvbSlotVerifyData* slot_verify_data,
132 uint8_t* key_bytes,
133 size_t key_size) {
134 size_t i;
135 size_t aftl_image_size;
136 size_t vbmeta_size;
137 uint8_t* current_aftl_blob;
138 char part_name[AVB_PART_NAME_MAX_SIZE];
139 char* pname;
140 AftlSlotVerifyResult ret = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
141
142 avb_assert(slot_verify_data != NULL);
143 avb_assert(key_bytes != NULL);
144 avb_assert(key_size == AVB_AFTL_PUB_KEY_SIZE);
145 if (slot_verify_data->vbmeta_images == NULL) {
146 return AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
147 }
148
149 current_aftl_blob = avb_malloc(AVB_AFTL_MAX_AFTL_IMAGE_SIZE);
150 if (current_aftl_blob == NULL) {
151 return AFTL_SLOT_VERIFY_RESULT_ERROR_OOM;
152 }
153
154 /* Walk through each vbmeta blob in the AvbSlotVerifyData struct. */
155 for (i = 0; i < slot_verify_data->num_vbmeta_images; i++) {
156 /* Rebuild partition name, appending the suffix */
157 pname = slot_verify_data->vbmeta_images[i].partition_name;
158 if (!avb_str_concat(part_name,
159 sizeof part_name,
160 (const char*)pname,
161 avb_strlen(pname),
162 slot_verify_data->ab_suffix,
163 avb_strlen(slot_verify_data->ab_suffix))) {
164 avb_error("Partition name and suffix does not fit.\n");
165 ret = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
166 break;
167 }
168
169 /* Use the partition info to find the AftlImage */
170 vbmeta_size = slot_verify_data->vbmeta_images[i].vbmeta_size;
171 ret = avb_aftl_find_aftl_image(
172 ops, part_name, vbmeta_size, current_aftl_blob, &aftl_image_size);
173 if (ret != AFTL_SLOT_VERIFY_RESULT_OK) {
174 avb_errorv(part_name, ": Unable to find the AftlImage.\n", NULL);
175 break;
176 }
177
178 /* Validate the AFTL image in the vbmeta image. */
179 ret = avb_aftl_verify_image(slot_verify_data->vbmeta_images[i].vbmeta_data,
180 vbmeta_size,
181 current_aftl_blob,
182 aftl_image_size,
183 key_bytes,
184 key_size);
185 if (ret != AVB_SLOT_VERIFY_RESULT_OK) break;
186 }
187
188 avb_free(current_aftl_blob);
189 return ret;
190 }
191