blob: 50af83520723a2a5c6d6806948098735b37bb7df [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
33static AvbIOResult mt_read_from_partition(AvbOps* ops,
34 const char* partition,
35 int64_t offset,
36 size_t num_bytes,
37 void* buffer,
38 size_t* out_num_read)
39{
40 bdev_t *bdev;
41 off_t part_size;
42 size_t read_bytes;
43
44 bdev = bio_open_by_label(partition) ? : bio_open(partition);
45 if (!bdev) {
46 dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
47 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
48 }
49
50 part_size = bdev->total_size;
51
52 if (offset < 0) {
53 if (-offset > part_size)
54 {
55 bio_close(bdev);
56 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
57 }
58
59 offset += part_size;
60 }
61
62 if (offset+num_bytes > (uint64_t)part_size)
63 {
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 {
98 bio_close(bdev);
99 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
100 }
101
102 offset += part_size;
103 }
104
105 if (offset+num_bytes > (uint64_t)part_size)
106 {
107 bio_close(bdev);
108 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
109 }
110
111 write_bytes = bio_write(bdev, buffer,offset, num_bytes);
112
113 if (write_bytes != num_bytes)
114 {
115 bio_close(bdev);
116 return AVB_IO_RESULT_ERROR_IO;
117 }
118
119 bio_close(bdev);
120 return AVB_IO_RESULT_OK;
121}
122
123#ifdef AVB_ENABLE_ANTIROLLBACK
124typedef struct {
125 uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
126} rollback_indexes_t;
127#define VERIDX_IN_PRMB 0
128/*antirollback index is stored in rpmb region block 1*/
129static AvbIOResult mt_read_rollback_index(AvbOps* ops,
130 size_t rollback_index_location,
131 uint64_t* out_rollback_index)
132{
133 int ret=0;
134 unsigned char blk[256] = {0};
135 ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
136 if(ret != 0 )
137 {
138 *out_rollback_index = 0;
139 return AVB_IO_RESULT_OK;
140 }
141 rollback_indexes_t* indexes = (rollback_indexes_t*)blk;
142 *out_rollback_index=indexes->rollback_indexes[rollback_index_location];
143#if 0
144 dprintf(CRITICAL, "indexes read: %08llx %08llx %08llx %08llx\n",
145 indexes->rollback_indexes[0], indexes->rollback_indexes[1],
146 indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
147#endif
148 return AVB_IO_RESULT_OK;
149}
150
151static AvbIOResult mt_write_rollback_index(AvbOps* ops,
152 size_t rollback_index_location,
153 uint64_t rollback_index)
154{
155 int ret=0;
156 unsigned char blk[256] = {0};
157 ret = mmc_rpmb_block_read(VERIDX_IN_PRMB,blk);
158 if(ret != 0 )
159 {
160 return AVB_IO_RESULT_ERROR_IO;
161 }
162 rollback_indexes_t* indexes = (rollback_indexes_t*)blk;
163 indexes->rollback_indexes[rollback_index_location] = rollback_index;
164#if 0
165 dprintf(CRITICAL, "indexes write: %08llx %08llx %08llx %08llx\n",
166 indexes->rollback_indexes[0], indexes->rollback_indexes[1],
167 indexes->rollback_indexes[2], indexes->rollback_indexes[3]);
168#endif
169 ret = mmc_rpmb_block_write(VERIDX_IN_PRMB,(unsigned char*)indexes);
170 if(ret != 0 )
171 {
172 return AVB_IO_RESULT_ERROR_IO;
173 }
174 return AVB_IO_RESULT_OK;
175}
176#else
177static AvbIOResult mt_read_rollback_index(AvbOps* ops,
178 size_t rollback_index_location,
179 uint64_t* out_rollback_index)
180{
181 *out_rollback_index = 0;
182 return AVB_IO_RESULT_OK;
183}
184
185static AvbIOResult mt_write_rollback_index(AvbOps* ops,
186 size_t rollback_index_location,
187 uint64_t rollback_index)
188{
189 return AVB_IO_RESULT_OK;
190}
191#endif
192
193#define INDEX_RPMB_UNLOCK 1
194#define AVB_DEVICE_UNLOCK 0x5a
195static AvbIOResult mt_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
196{
197 if (out_is_unlocked != NULL) {
198 *out_is_unlocked = false;
199 }
200
201#if defined(AVB_ENABLE_ANTIROLLBACK) || defined(AVB_ENABLE_DEVICE_STATE_CHANGE)
202 unsigned char blk[256]={0};
203 int ret = -1;
204
205 ret=mmc_rpmb_block_read(INDEX_RPMB_UNLOCK,&blk[0]);
206 if(ret != 0){
207 dprintf(CRITICAL, "mmc_rpmb_block_read fail %d.\n", ret);
208 return AVB_IO_RESULT_ERROR_IO;
209 }
210
211 if(blk[0] == AVB_DEVICE_UNLOCK)
212 *out_is_unlocked = true;
213#endif
214
215 dprintf(CRITICAL, "mt_read_is_device_unlocked return: %d.\n", *out_is_unlocked);
216
217 return AVB_IO_RESULT_OK;
218}
219
220static AvbIOResult mt_get_unique_guid_for_partition(AvbOps* ops,
221 const char* partition,
222 char* guid_buf,
223 size_t guid_buf_size)
224{
225 bdev_t *bdev;
226
227 bdev = bio_open_by_label(partition) ? : bio_open(partition);
228 if (!bdev) {
229 dprintf(CRITICAL, "Partition [%s] is not exist.\n", partition);
230 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
231 }
232
233 strlcpy(guid_buf, bdev->unique_uuid, guid_buf_size);
234
235 bio_close(bdev);
236 return AVB_IO_RESULT_OK;
237}
238
239#include <libfdt.h>
240#include <image.h>
241extern const unsigned char blob[];
242static const unsigned char* get_pubkey_in_blob(void)
243{
244 int sig_node;
245 int noffset;
246 const void *sig_blob=&blob[0];
247 sig_node = fdt_subnode_offset(sig_blob, 0, FDT_SIG_NODE);
248 for (noffset = fdt_first_subnode(sig_blob, sig_node);
249 noffset >= 0;
250 noffset = fdt_next_subnode(sig_blob, noffset))
251 {
252 return (const unsigned char*)fdt_getprop(sig_blob, noffset, BLOB_MOD_NODE, NULL);
253 }
254 return NULL;
255}
256
257static AvbIOResult mt_validate_vbmeta_public_key(AvbOps* ops,
258 const uint8_t* public_key_data,
259 size_t public_key_length,
260 const uint8_t* public_key_metadata,
261 size_t public_key_metadata_length,
262 bool* out_is_trusted)
263{
264 unsigned char* pubkey_in_blob;
265 unsigned char* pubkey_in_footer;
266 AvbRSAPublicKeyHeader* header;
267
268 header = (AvbRSAPublicKeyHeader*)public_key_data;
269 pubkey_in_blob = (unsigned char*)get_pubkey_in_blob();
270 pubkey_in_footer = (unsigned char*)(public_key_data+sizeof(AvbRSAPublicKeyHeader));
271 if(memcmp(pubkey_in_blob,pubkey_in_footer,avb_be32toh(header->key_num_bits)/32)==0)
272 {
273 *out_is_trusted = true;
274 }
275 else
276 {
277 *out_is_trusted = false;
278 }
279
280 return AVB_IO_RESULT_OK;
281}
282
283static AvbOps avbops;
284
285static AvbABOps avbabops = {
286 .ops = &avbops,
287
288 .read_ab_metadata = avb_ab_data_read,
289 .write_ab_metadata = avb_ab_data_write,
290};
291
292
293static AvbOps avbops = {
294 .ab_ops = &avbabops,
295
296 .read_from_partition = mt_read_from_partition,
297 .write_to_partition = mt_write_to_partition,
298 .validate_vbmeta_public_key = mt_validate_vbmeta_public_key,
299 .read_rollback_index = mt_read_rollback_index,
300 .write_rollback_index = mt_write_rollback_index,
301 .read_is_device_unlocked = mt_read_is_device_unlocked,
302 .get_unique_guid_for_partition = mt_get_unique_guid_for_partition,
303};
304
305bool is_device_unlocked(void)
306{
307 AvbIOResult io_ret;
308 bool is_device_unlocked;
309 io_ret = avbops.read_is_device_unlocked(&avbops, &is_device_unlocked);
310 if (io_ret != AVB_IO_RESULT_OK) {
311 //any error treat as locked
312 return false;
313 }
314 return is_device_unlocked;
315}
316
317void* get_partition_data(char* part_name,AvbSlotVerifyData* verifyData)
318{
319 size_t i=0;
320
321 for(;i<verifyData->num_loaded_partitions;i++)
322 {
323 if(avb_strcmp(part_name,verifyData->loaded_partitions[i].partition_name)==0)
324 {
325 return verifyData->loaded_partitions[i].data;
326 }
327 }
328 return NULL;
329}
330
331AvbSlotVerifyResult avb_update_rollback_indexes(AvbOps* ops,AvbSlotVerifyData* verifyData)
332{
333 size_t n = 0;
334 AvbIOResult io_ret;
335 AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_OK;
336 /* Update stored rollback index such that the stored rollback index
337 * is the largest value supporting all currently bootable slots. Do
338 * this for every rollback index location.
339 */
340 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
341 uint64_t rollback_index_value = 0;
342
343 rollback_index_value = verifyData->rollback_indexes[n];
344 if (rollback_index_value != 0) {
345 uint64_t current_rollback_index_value;
346 io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
347 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
348 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
349 goto out;
350 } else if (io_ret != AVB_IO_RESULT_OK) {
351 avb_error("Error getting rollback index for slot.\n");
352 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
353 goto out;
354 }
355 if (current_rollback_index_value != rollback_index_value) {
356 io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
357 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
358 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
359 goto out;
360 } else if (io_ret != AVB_IO_RESULT_OK) {
361 avb_error("Error setting stored rollback index.\n");
362 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
363 goto out;
364 }
365 }
366 }
367 }
368out:
369 return ret;
370}
371
372#ifndef AB_OTA_UPDATER
373AvbSlotVerifyResult android_verified_boot_2_0(AvbSlotVerifyData** verifyData)
374{
375 AvbSlotVerifyResult verify_result;
376 const char* requested_partitions[] = {BOOT_PART_NAME,NULL};
377 verify_result = avb_slot_verify(&avbops,requested_partitions,"",is_device_unlocked(),verifyData);
378 dprintf(CRITICAL, "avb boot verification result is %s\n",avb_slot_verify_result_to_string(verify_result));
379 if(verify_result == AVB_SLOT_VERIFY_RESULT_OK)
380 {
381 verify_result = avb_update_rollback_indexes(&avbops,*verifyData);
382 dprintf(CRITICAL, "avb boot rollback indexes result is %s\n",avb_slot_verify_result_to_string(verify_result));
383 }
384 return verify_result;
385}
386#else
387//static AvbSlotVerifyData *slot_data;
388AvbSlotVerifyResult android_verified_boot_2_0(AvbSlotVerifyData** verifyData)
389{
390 AvbABFlowResult ab_result;
391 const char* requested_partitions[] = {"bootimg", NULL};
392 /* ab flow */
393 ab_result = avb_ab_flow(&avbabops, requested_partitions, false, verifyData);
394 dprintf(CRITICAL, "ab_result: %s\n", avb_ab_flow_result_to_string(ab_result));
395
396 return ab_result;
397}
398#endif