blob: fbeea7250b6553b0daa19eebae6e311c7761dadd [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2019 MediaTek Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * 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 NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <lib/bio.h>
24#include <lib/dl_commands.h>
25/* VERIFIED BOOT 2 */
26#include <libavb/libavb.h>
27#include <libavb_ab/libavb_ab.h>
28
29#include <platform/mmc_rpmb.h>
30#include <sys/types.h>
31#include <string.h>
32
33#include "blxboot_ab.h"
34
35static AvbIOResult mt_read_from_partition(AvbOps *ops,
36 const char *partition,
37 int64_t offset,
38 size_t num_bytes,
39 void *buffer,
40 size_t *out_num_read)
41{
42 bdev_t *bdev;
43 off_t part_size;
44 size_t read_bytes;
45
46 bdev = bio_open_by_label(partition) ? : bio_open(partition);
47 if (!bdev) {
48 dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
49 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
50 }
51
52 part_size = bdev->total_size;
53
54 if (offset < 0) {
55 if (-offset > part_size) {
56 bio_close(bdev);
57 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
58 }
59
60 offset += part_size;
61 }
62
63 if (offset+num_bytes > (uint64_t)part_size) {
64 bio_close(bdev);
65 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
66 }
67
68 read_bytes = bio_read(bdev, buffer, offset, num_bytes);
69
70 if (out_num_read != NULL)
71 *out_num_read = read_bytes;
72
73 bio_close(bdev);
74 return AVB_IO_RESULT_OK;
75}
76
77static AvbIOResult mt_write_to_partition(AvbOps *ops,
78 const char *partition,
79 int64_t offset,
80 size_t num_bytes,
81 const void *buffer)
82{
83 bdev_t *bdev;
84 off_t part_size;
85 size_t write_bytes;
86
87 bdev = bio_open_by_label(partition) ? : bio_open(partition);
88 if (!bdev) {
89 dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
90 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
91 }
92
93 part_size = bdev->total_size;
94
95 if (offset < 0) {
96 if (-offset > part_size) {
97 bio_close(bdev);
98 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
99 }
100
101 offset += part_size;
102 }
103
104 if (offset+num_bytes > (uint64_t)part_size) {
105 bio_close(bdev);
106 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
107 }
108
109 write_bytes = bio_write(bdev, buffer,offset, num_bytes);
110
111 if (write_bytes != num_bytes) {
112 bio_close(bdev);
113 return AVB_IO_RESULT_ERROR_IO;
114 }
115
116 bio_close(bdev);
117 return AVB_IO_RESULT_OK;
118}
119
120#ifdef AVB_ENABLE_ANTIROLLBACK
121typedef struct {
122 uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
123} rollback_indexes_t;
124#define VERIDX_IN_PRMB 0
125/*antirollback index is stored in rpmb region block 1*/
126static AvbIOResult mt_read_rollback_index(AvbOps *ops,
127 size_t rollback_index_location,
128 uint64_t *out_rollback_index)
129{
130 int ret=0;
131 unsigned char blk[256] = {0};
132 ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
133 if (ret != 0 ) {
134 *out_rollback_index = 0;
135 return AVB_IO_RESULT_OK;
136 }
137 rollback_indexes_t *indexes = (rollback_indexes_t *)blk;
138 *out_rollback_index=indexes->rollback_indexes[rollback_index_location];
139#if 0
140 dprintf(CRITICAL, "indexes read: %08llx %08llx %08llx %08llx\n",
141 indexes->rollback_indexes[0], indexes->rollback_indexes[1],
142 indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
143#endif
144 return AVB_IO_RESULT_OK;
145}
146
147static AvbIOResult mt_write_rollback_index(AvbOps *ops,
148 size_t rollback_index_location,
149 uint64_t rollback_index)
150{
151 int ret=0;
152 unsigned char blk[256] = {0};
153 ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
154 if (ret != 0 ) {
155 return AVB_IO_RESULT_ERROR_IO;
156 }
157 rollback_indexes_t *indexes = (rollback_indexes_t *)blk;
158 indexes->rollback_indexes[rollback_index_location] = rollback_index;
159#if 0
160 dprintf(CRITICAL, "indexes write: %08llx %08llx %08llx %08llx\n",
161 indexes->rollback_indexes[0], indexes->rollback_indexes[1],
162 indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
163#endif
164 ret = mmc_rpmb_block_write(VERIDX_IN_PRMB,(unsigned char *)indexes);
165 if (ret != 0 ) {
166 return AVB_IO_RESULT_ERROR_IO;
167 }
168 return AVB_IO_RESULT_OK;
169}
170#else
171static AvbIOResult mt_read_rollback_index(AvbOps *ops,
172 size_t rollback_index_location,
173 uint64_t *out_rollback_index)
174{
175 *out_rollback_index = 0;
176 return AVB_IO_RESULT_OK;
177}
178
179static AvbIOResult mt_write_rollback_index(AvbOps *ops,
180 size_t rollback_index_location,
181 uint64_t rollback_index)
182{
183 return AVB_IO_RESULT_OK;
184}
185#endif
186
187#define INDEX_RPMB_UNLOCK 1
188#define AVB_DEVICE_UNLOCK 0x5a
189static AvbIOResult mt_read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
190{
191 if (out_is_unlocked != NULL) {
192 *out_is_unlocked = false;
193 }
194
195#if defined(AVB_ENABLE_ANTIROLLBACK) || defined(AVB_ENABLE_DEVICE_STATE_CHANGE)
196 unsigned char blk[256]= {0};
197 int ret = -1;
198
199 ret=mmc_rpmb_block_read(INDEX_RPMB_UNLOCK,&blk[0]);
200 if (ret != 0) {
201 dprintf(CRITICAL, "mmc_rpmb_block_read fail %d.\n", ret);
202 return AVB_IO_RESULT_ERROR_IO;
203 }
204
205 if (blk[0] == AVB_DEVICE_UNLOCK)
206 *out_is_unlocked = true;
207#endif
208
209 dprintf(CRITICAL, "mt_read_is_device_unlocked return: %d.\n", *out_is_unlocked);
210
211 return AVB_IO_RESULT_OK;
212}
213
214static AvbIOResult mt_get_unique_node_for_partition(AvbOps *ops,
215 const char *partition,
216 char *guid_buf,
217 size_t guid_buf_size)
218{
219
220 strlcpy(guid_buf, "/dev/ubiblock0_0", guid_buf_size);
221 return AVB_IO_RESULT_OK;
222
223}
224static AvbIOResult mt_get_unique_guid_for_partition(AvbOps *ops,
225 const char *partition,
226 char *guid_buf,
227 size_t guid_buf_size)
228{
229 bdev_t *bdev;
230
231 bdev = bio_open_by_label(partition) ? : bio_open(partition);
232 if (!bdev) {
233 dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
234 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
235 }
236
237 strlcpy(guid_buf, bdev->unique_uuid, guid_buf_size);
238 bio_close(bdev);
239 return AVB_IO_RESULT_OK;
240}
241
242#include <libfdt.h>
243#include <image.h>
244extern const unsigned char blob[];
245static const unsigned char *get_pubkey_in_blob(void)
246{
247 int sig_node;
248 int noffset;
249 const void *sig_blob=&blob[0];
250 sig_node = fdt_subnode_offset(sig_blob, 0, FDT_SIG_NODE);
251 for (noffset = fdt_first_subnode(sig_blob, sig_node);
252 noffset >= 0;
253 noffset = fdt_next_subnode(sig_blob, noffset)) {
254 return (const unsigned char *)fdt_getprop(sig_blob, noffset, BLOB_MOD_NODE, NULL);
255 }
256 return NULL;
257}
258
259static AvbIOResult mt_validate_vbmeta_public_key(AvbOps *ops,
260 const uint8_t *public_key_data,
261 size_t public_key_length,
262 const uint8_t *public_key_metadata,
263 size_t public_key_metadata_length,
264 bool *out_is_trusted)
265{
266 unsigned char *pubkey_in_blob;
267 unsigned char *pubkey_in_footer;
268 AvbRSAPublicKeyHeader *header;
269
270 header = (AvbRSAPublicKeyHeader *)public_key_data;
271 pubkey_in_blob = (unsigned char *)get_pubkey_in_blob();
272 if (!pubkey_in_blob) {
273 avb_error("Public key is NULL in blob\n");
274 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
275 }
276 pubkey_in_footer = (unsigned char *)(public_key_data+sizeof(AvbRSAPublicKeyHeader));
277 if (memcmp(pubkey_in_blob,pubkey_in_footer,avb_be32toh(header->key_num_bits)/32)==0) {
278 *out_is_trusted = true;
279 } else {
280 *out_is_trusted = false;
281 }
282
283 return AVB_IO_RESULT_OK;
284}
285
286static AvbOps avbops;
287
288static AvbABOps avbabops = {
289 .ops = &avbops,
290
291 .read_ab_metadata = avb_ab_data_read,
292 .write_ab_metadata = avb_ab_data_write,
293};
294
295static AvbIOResult mt_get_size_of_partition(AvbOps *ops,
296 const char *partition,
297 uint64_t *out_size_num_bytes)
298{
299 bdev_t *bdev;
300
301 bdev = bio_open_by_label(partition) ? : bio_open(partition);
302 *out_size_num_bytes = (uint64_t)bdev->total_size;
303 return AVB_IO_RESULT_OK;
304}
305
306static AvbOps avbops = {
307 .ab_ops = &avbabops,
308
309 .read_from_partition = mt_read_from_partition,
310 .write_to_partition = mt_write_to_partition,
311 .validate_vbmeta_public_key = mt_validate_vbmeta_public_key,
312 .read_rollback_index = mt_read_rollback_index,
313 .write_rollback_index = mt_write_rollback_index,
314 .read_is_device_unlocked = mt_read_is_device_unlocked,
315 .get_size_of_partition = mt_get_size_of_partition,
316#ifdef BOOT_DEV_NAND
317 .get_unique_guid_for_partition = mt_get_unique_node_for_partition,
318#else
319 .get_unique_guid_for_partition = mt_get_unique_guid_for_partition,
320#endif
321};
322
323bool is_device_unlocked(void)
324{
325 AvbIOResult io_ret;
326 bool is_device_unlocked;
327 io_ret = avbops.read_is_device_unlocked(&avbops, &is_device_unlocked);
328 if (io_ret != AVB_IO_RESULT_OK) {
329 //any error treat as locked
330 return false;
331 }
332 return is_device_unlocked;
333}
334
335void *get_partition_data(const char *part_name, AvbSlotVerifyData *verifyData)
336{
337 size_t i=0;
338
339 if ((part_name == NULL) || (verifyData == NULL))
340 return NULL;
341
342 for (; i<verifyData->num_loaded_partitions; i++) {
343 if (avb_strcmp(part_name,verifyData->loaded_partitions[i].partition_name)==0) {
344 return verifyData->loaded_partitions[i].data;
345 }
346 }
347 return NULL;
348}
349
350AvbSlotVerifyResult avb_update_rollback_indexes(AvbOps *ops,AvbSlotVerifyData *verifyData)
351{
352 size_t n = 0;
353 AvbIOResult io_ret;
354 AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_OK;
355 /* Update stored rollback index such that the stored rollback index
356 * is the largest value supporting all currently bootable slots. Do
357 * this for every rollback index location.
358 */
359 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
360 uint64_t rollback_index_value = 0;
361
362 rollback_index_value = verifyData->rollback_indexes[n];
363 if (rollback_index_value != 0) {
364 uint64_t current_rollback_index_value;
365 io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
366 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
367 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
368 goto out;
369 } else if (io_ret != AVB_IO_RESULT_OK) {
370 avb_error("Error getting rollback index for slot.\n");
371 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
372 goto out;
373 }
374 if (current_rollback_index_value != rollback_index_value) {
375 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
376 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
377 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
378 goto out;
379 } else if (io_ret != AVB_IO_RESULT_OK) {
380 avb_error("Error setting stored rollback index.\n");
381 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
382 goto out;
383 }
384 }
385 }
386 }
387out:
388 return ret;
389}
390
391AvbSlotVerifyResult android_verified_boot_2_0(const char *part_name,
392 AvbSlotVerifyData **verifyData)
393{
394 AvbSlotVerifyResult verify_result;
395 const char *requested_partitions[] = { part_name, NULL };
396 const char *ab_suffix = get_suffix() ? : "";
397
398 verify_result = avb_slot_verify(&avbops,requested_partitions,ab_suffix,is_device_unlocked(),AVB_HASHTREE_ERROR_MODE_RESTART,verifyData);
399 dprintf(CRITICAL, "avb boot verification result is %s\n",avb_slot_verify_result_to_string(verify_result));
400 if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
401 verify_result = avb_update_rollback_indexes(&avbops,*verifyData);
402 dprintf(CRITICAL, "avb boot rollback indexes result is %s\n",avb_slot_verify_result_to_string(verify_result));
403 }
404 return verify_result;
405}
406