• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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