]> Git Repo - J-u-boot.git/blame - common/avb_verify.c
avb: move SPDX license identifiers to the first line
[J-u-boot.git] / common / avb_verify.c
CommitLineData
a14aa59e 1// SPDX-License-Identifier: GPL-2.0+
3af30e44
IO
2/*
3 * (C) Copyright 2018, Linaro Limited
3af30e44
IO
4 */
5
6#include <avb_verify.h>
e9ee7398 7#include <blk.h>
1eb69ae4 8#include <cpu_func.h>
3af30e44
IO
9#include <image.h>
10#include <malloc.h>
11#include <part.h>
6663e074
JW
12#include <tee.h>
13#include <tee/optee_ta_avb.h>
3af30e44 14
55d56d23 15static const unsigned char avb_root_pub[1032] = {
3af30e44
IO
16 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
17 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
18 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
19 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
20 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
21 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
22 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
23 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
24 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
25 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
26 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
27 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
28 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
29 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
30 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
31 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
32 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
33 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
34 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
35 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
36 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
37 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
38 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
39 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
40 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
41 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
42 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
43 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
44 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
45 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
46 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
47 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
48 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
49 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
50 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
51 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
52 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
53 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
54 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
55 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
56 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
57 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
58 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
59 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
60 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
61 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
62 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
63 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
64 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
65 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
66 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
67 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
68 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
69 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
70 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
71 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
72 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
73 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
74 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
75 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
76 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
77 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
78 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
79 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
80 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
81 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
82 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
83 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
84 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
85 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
86 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
87 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
88 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
89 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
90 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
91 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
92 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
93 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
94 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
95 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
96 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
97 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
98 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
99 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
100 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
101 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
102 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
103 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
104 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
105 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
106 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
107 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
108 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
109 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
110 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
111 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
112 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
113 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
114 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
115 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
116 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
117 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
118 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
119 0xd8, 0x7e,
120};
121
5d4fd877
IO
122/**
123 * ============================================================================
124 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
125 * ============================================================================
126 */
127char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
128{
129 struct AvbOpsData *data;
130 char *cmdline = NULL;
131
132 if (!ops)
133 return NULL;
134
135 data = (struct AvbOpsData *)ops->user_data;
136 if (!data)
137 return NULL;
138
139 data->boot_state = boot_state;
140 switch (boot_state) {
141 case AVB_GREEN:
142 cmdline = "androidboot.verifiedbootstate=green";
143 break;
144 case AVB_YELLOW:
145 cmdline = "androidboot.verifiedbootstate=yellow";
146 break;
147 case AVB_ORANGE:
148 cmdline = "androidboot.verifiedbootstate=orange";
149 case AVB_RED:
150 break;
151 }
152
153 return cmdline;
154}
155
156char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
157{
158 char *cmd_line;
159
160 if (!cmdline_new)
161 return cmdline_orig;
162
163 if (cmdline_orig)
164 cmd_line = cmdline_orig;
165 else
166 cmd_line = " ";
167
168 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
169
170 return cmd_line;
171}
172
173static int avb_find_dm_args(char **args, char *str)
174{
175 int i;
176
177 if (!str)
178 return -1;
179
2e2067b8 180 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
5d4fd877
IO
181 if (strstr(args[i], str))
182 return i;
183 }
184
185 return -1;
186}
187
188static char *avb_set_enforce_option(const char *cmdline, const char *option)
189{
190 char *cmdarg[AVB_MAX_ARGS];
191 char *newargs = NULL;
192 int i = 0;
193 int total_args;
194
195 memset(cmdarg, 0, sizeof(cmdarg));
196 cmdarg[i++] = strtok((char *)cmdline, " ");
197
198 do {
199 cmdarg[i] = strtok(NULL, " ");
200 if (!cmdarg[i])
201 break;
202
203 if (++i >= AVB_MAX_ARGS) {
204 printf("%s: Can't handle more then %d args\n",
205 __func__, i);
206 return NULL;
207 }
208 } while (true);
209
210 total_args = i;
211 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
212 if (i >= 0) {
213 cmdarg[i] = (char *)option;
214 } else {
215 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
216 if (i < 0) {
217 printf("%s: No verity options found\n", __func__);
218 return NULL;
219 }
220
221 cmdarg[i] = (char *)option;
222 }
223
224 for (i = 0; i <= total_args; i++)
225 newargs = append_cmd_line(newargs, cmdarg[i]);
226
227 return newargs;
228}
229
230char *avb_set_ignore_corruption(const char *cmdline)
231{
232 char *newargs = NULL;
233
234 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
235 if (newargs)
236 newargs = append_cmd_line(newargs,
237 "androidboot.veritymode=eio");
238
239 return newargs;
240}
241
242char *avb_set_enforce_verity(const char *cmdline)
243{
244 char *newargs;
245
246 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
247 if (newargs)
248 newargs = append_cmd_line(newargs,
249 "androidboot.veritymode=enforcing");
250 return newargs;
251}
252
3af30e44
IO
253/**
254 * ============================================================================
255 * IO(mmc) auxiliary functions
256 * ============================================================================
257 */
258static unsigned long mmc_read_and_flush(struct mmc_part *part,
259 lbaint_t start,
260 lbaint_t sectors,
261 void *buffer)
262{
263 unsigned long blks;
264 void *tmp_buf;
265 size_t buf_size;
266 bool unaligned = is_buf_unaligned(buffer);
267
268 if (start < part->info.start) {
269 printf("%s: partition start out of bounds\n", __func__);
270 return 0;
271 }
272 if ((start + sectors) > (part->info.start + part->info.size)) {
273 sectors = part->info.start + part->info.size - start;
274 printf("%s: read sector aligned to partition bounds (%ld)\n",
275 __func__, sectors);
276 }
277
278 /*
279 * Reading fails on unaligned buffers, so we have to
280 * use aligned temporary buffer and then copy to destination
281 */
282
283 if (unaligned) {
284 printf("Handling unaligned read buffer..\n");
285 tmp_buf = get_sector_buf();
286 buf_size = get_sector_buf_size();
287 if (sectors > buf_size / part->info.blksz)
288 sectors = buf_size / part->info.blksz;
289 } else {
290 tmp_buf = buffer;
291 }
292
e9ee7398
IO
293 blks = blk_dread(part->mmc_blk,
294 start, sectors, tmp_buf);
3af30e44
IO
295 /* flush cache after read */
296 flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
297
298 if (unaligned)
299 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
300
301 return blks;
302}
303
304static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
305 lbaint_t sectors, void *buffer)
306{
307 void *tmp_buf;
308 size_t buf_size;
309 bool unaligned = is_buf_unaligned(buffer);
310
311 if (start < part->info.start) {
312 printf("%s: partition start out of bounds\n", __func__);
313 return 0;
314 }
315 if ((start + sectors) > (part->info.start + part->info.size)) {
316 sectors = part->info.start + part->info.size - start;
317 printf("%s: sector aligned to partition bounds (%ld)\n",
318 __func__, sectors);
319 }
320 if (unaligned) {
321 tmp_buf = get_sector_buf();
322 buf_size = get_sector_buf_size();
323 printf("Handling unaligned wrire buffer..\n");
324 if (sectors > buf_size / part->info.blksz)
325 sectors = buf_size / part->info.blksz;
326
327 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
328 } else {
329 tmp_buf = buffer;
330 }
331
e9ee7398
IO
332 return blk_dwrite(part->mmc_blk,
333 start, sectors, tmp_buf);
3af30e44
IO
334}
335
336static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
337{
338 int ret;
339 u8 dev_num;
340 int part_num = 0;
341 struct mmc_part *part;
342 struct blk_desc *mmc_blk;
343
344 part = malloc(sizeof(struct mmc_part));
345 if (!part)
346 return NULL;
347
348 dev_num = get_boot_device(ops);
349 part->mmc = find_mmc_device(dev_num);
350 if (!part->mmc) {
351 printf("No MMC device at slot %x\n", dev_num);
047bc5c7 352 goto err;
3af30e44
IO
353 }
354
355 if (mmc_init(part->mmc)) {
356 printf("MMC initialization failed\n");
047bc5c7 357 goto err;
3af30e44
IO
358 }
359
c2f72d00
IO
360 if (IS_MMC(part->mmc)) {
361 ret = mmc_switch_part(part->mmc, part_num);
362 if (ret)
363 goto err;
364 }
3af30e44
IO
365
366 mmc_blk = mmc_get_blk_desc(part->mmc);
367 if (!mmc_blk) {
368 printf("Error - failed to obtain block descriptor\n");
047bc5c7 369 goto err;
3af30e44
IO
370 }
371
372 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
04534119 373 if (ret < 0) {
3af30e44 374 printf("Can't find partition '%s'\n", partition);
047bc5c7 375 goto err;
3af30e44
IO
376 }
377
378 part->dev_num = dev_num;
379 part->mmc_blk = mmc_blk;
380
381 return part;
047bc5c7
ER
382err:
383 free(part);
384 return NULL;
3af30e44
IO
385}
386
387static AvbIOResult mmc_byte_io(AvbOps *ops,
388 const char *partition,
389 s64 offset,
390 size_t num_bytes,
391 void *buffer,
392 size_t *out_num_read,
393 enum mmc_io_type io_type)
394{
395 ulong ret;
396 struct mmc_part *part;
397 u64 start_offset, start_sector, sectors, residue;
398 u8 *tmp_buf;
399 size_t io_cnt = 0;
400
401 if (!partition || !buffer || io_type > IO_WRITE)
402 return AVB_IO_RESULT_ERROR_IO;
403
404 part = get_partition(ops, partition);
405 if (!part)
406 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
407
e1904f45
ER
408 if (!part->info.blksz)
409 return AVB_IO_RESULT_ERROR_IO;
410
3af30e44
IO
411 start_offset = calc_offset(part, offset);
412 while (num_bytes) {
413 start_sector = start_offset / part->info.blksz;
414 sectors = num_bytes / part->info.blksz;
415 /* handle non block-aligned reads */
416 if (start_offset % part->info.blksz ||
417 num_bytes < part->info.blksz) {
418 tmp_buf = get_sector_buf();
419 if (start_offset % part->info.blksz) {
420 residue = part->info.blksz -
421 (start_offset % part->info.blksz);
422 if (residue > num_bytes)
423 residue = num_bytes;
424 } else {
425 residue = num_bytes;
426 }
427
428 if (io_type == IO_READ) {
429 ret = mmc_read_and_flush(part,
430 part->info.start +
431 start_sector,
432 1, tmp_buf);
433
434 if (ret != 1) {
435 printf("%s: read error (%ld, %lld)\n",
436 __func__, ret, start_sector);
437 return AVB_IO_RESULT_ERROR_IO;
438 }
439 /*
440 * if this is not aligned at sector start,
441 * we have to adjust the tmp buffer
442 */
443 tmp_buf += (start_offset % part->info.blksz);
444 memcpy(buffer, (void *)tmp_buf, residue);
445 } else {
446 ret = mmc_read_and_flush(part,
447 part->info.start +
448 start_sector,
449 1, tmp_buf);
450
451 if (ret != 1) {
452 printf("%s: read error (%ld, %lld)\n",
453 __func__, ret, start_sector);
454 return AVB_IO_RESULT_ERROR_IO;
455 }
456 memcpy((void *)tmp_buf +
457 start_offset % part->info.blksz,
458 buffer, residue);
459
460 ret = mmc_write(part, part->info.start +
461 start_sector, 1, tmp_buf);
462 if (ret != 1) {
463 printf("%s: write error (%ld, %lld)\n",
464 __func__, ret, start_sector);
465 return AVB_IO_RESULT_ERROR_IO;
466 }
467 }
468
469 io_cnt += residue;
470 buffer += residue;
471 start_offset += residue;
472 num_bytes -= residue;
473 continue;
474 }
475
476 if (sectors) {
477 if (io_type == IO_READ) {
478 ret = mmc_read_and_flush(part,
479 part->info.start +
480 start_sector,
481 sectors, buffer);
482 } else {
483 ret = mmc_write(part,
484 part->info.start +
485 start_sector,
486 sectors, buffer);
487 }
488
489 if (!ret) {
490 printf("%s: sector read error\n", __func__);
491 return AVB_IO_RESULT_ERROR_IO;
492 }
493
494 io_cnt += ret * part->info.blksz;
495 buffer += ret * part->info.blksz;
496 start_offset += ret * part->info.blksz;
497 num_bytes -= ret * part->info.blksz;
498 }
499 }
500
501 /* Set counter for read operation */
502 if (io_type == IO_READ && out_num_read)
503 *out_num_read = io_cnt;
504
505 return AVB_IO_RESULT_OK;
506}
507
508/**
509 * ============================================================================
510 * AVB 2.0 operations
511 * ============================================================================
512 */
513
514/**
515 * read_from_partition() - reads @num_bytes from @offset from partition
516 * identified by a string name
517 *
518 * @ops: contains AVB ops handlers
519 * @partition_name: partition name, NUL-terminated UTF-8 string
520 * @offset: offset from the beginning of partition
521 * @num_bytes: amount of bytes to read
522 * @buffer: destination buffer to store data
523 * @out_num_read:
524 *
525 * @return:
526 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
527 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
528 * subsystem
529 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
530 * the given name
531 */
532static AvbIOResult read_from_partition(AvbOps *ops,
533 const char *partition_name,
534 s64 offset_from_partition,
535 size_t num_bytes,
536 void *buffer,
537 size_t *out_num_read)
538{
539 return mmc_byte_io(ops, partition_name, offset_from_partition,
540 num_bytes, buffer, out_num_read, IO_READ);
541}
542
543/**
544 * write_to_partition() - writes N bytes to a partition identified by a string
545 * name
546 *
547 * @ops: AvbOps, contains AVB ops handlers
548 * @partition_name: partition name
549 * @offset_from_partition: offset from the beginning of partition
550 * @num_bytes: amount of bytes to write
551 * @buf: data to write
552 * @out_num_read:
553 *
554 * @return:
555 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
556 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
557 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
558 * @partition_name was not found
559 */
560static AvbIOResult write_to_partition(AvbOps *ops,
561 const char *partition_name,
562 s64 offset_from_partition,
563 size_t num_bytes,
564 const void *buffer)
565{
566 return mmc_byte_io(ops, partition_name, offset_from_partition,
567 num_bytes, (void *)buffer, NULL, IO_WRITE);
568}
569
570/**
571 * validate_vmbeta_public_key() - checks if the given public key used to sign
572 * the vbmeta partition is trusted
573 *
574 * @ops: AvbOps, contains AVB ops handlers
575 * @public_key_data: public key for verifying vbmeta partition signature
576 * @public_key_length: length of public key
577 * @public_key_metadata:
578 * @public_key_metadata_length:
579 * @out_key_is_trusted:
580 *
581 * @return:
582 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
583 */
584static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
585 const u8 *public_key_data,
586 size_t public_key_length,
587 const u8
588 *public_key_metadata,
589 size_t
590 public_key_metadata_length,
591 bool *out_key_is_trusted)
592{
593 if (!public_key_length || !public_key_data || !out_key_is_trusted)
594 return AVB_IO_RESULT_ERROR_IO;
595
596 *out_key_is_trusted = false;
597 if (public_key_length != sizeof(avb_root_pub))
598 return AVB_IO_RESULT_ERROR_IO;
599
600 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
601 *out_key_is_trusted = true;
602
603 return AVB_IO_RESULT_OK;
604}
605
6663e074
JW
606#ifdef CONFIG_OPTEE_TA_AVB
607static int get_open_session(struct AvbOpsData *ops_data)
608{
609 struct udevice *tee = NULL;
610
611 while (!ops_data->tee) {
612 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
613 struct tee_open_session_arg arg;
614 int rc;
615
616 tee = tee_find_device(tee, NULL, NULL, NULL);
617 if (!tee)
618 return -ENODEV;
619
620 memset(&arg, 0, sizeof(arg));
621 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
622 rc = tee_open_session(tee, &arg, 0, NULL);
3106e475
IK
623 if (rc || arg.ret)
624 continue;
625
626 ops_data->tee = tee;
627 ops_data->session = arg.session;
6663e074
JW
628 }
629
630 return 0;
631}
632
633static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
634 ulong num_param, struct tee_param *param)
635{
636 struct tee_invoke_arg arg;
637
638 if (get_open_session(ops_data))
639 return AVB_IO_RESULT_ERROR_IO;
640
641 memset(&arg, 0, sizeof(arg));
642 arg.func = func;
643 arg.session = ops_data->session;
644
645 if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
646 return AVB_IO_RESULT_ERROR_IO;
647 switch (arg.ret) {
648 case TEE_SUCCESS:
649 return AVB_IO_RESULT_OK;
650 case TEE_ERROR_OUT_OF_MEMORY:
651 return AVB_IO_RESULT_ERROR_OOM;
fc1fe01b
IO
652 case TEE_ERROR_STORAGE_NO_SPACE:
653 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
654 case TEE_ERROR_ITEM_NOT_FOUND:
655 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
6663e074
JW
656 case TEE_ERROR_TARGET_DEAD:
657 /*
658 * The TA has paniced, close the session to reload the TA
659 * for the next request.
660 */
661 tee_close_session(ops_data->tee, ops_data->session);
662 ops_data->tee = NULL;
663 return AVB_IO_RESULT_ERROR_IO;
664 default:
665 return AVB_IO_RESULT_ERROR_IO;
666 }
667}
668#endif
669
3af30e44
IO
670/**
671 * read_rollback_index() - gets the rollback index corresponding to the
672 * location of given by @out_rollback_index.
673 *
674 * @ops: contains AvbOps handlers
675 * @rollback_index_slot:
676 * @out_rollback_index: used to write a retrieved rollback index.
677 *
678 * @return
679 * AVB_IO_RESULT_OK, if the roolback index was retrieved
680 */
681static AvbIOResult read_rollback_index(AvbOps *ops,
682 size_t rollback_index_slot,
683 u64 *out_rollback_index)
684{
6663e074 685#ifndef CONFIG_OPTEE_TA_AVB
3af30e44 686 /* For now we always return 0 as the stored rollback index. */
5d4fd877 687 printf("%s not supported yet\n", __func__);
3af30e44
IO
688
689 if (out_rollback_index)
690 *out_rollback_index = 0;
691
692 return AVB_IO_RESULT_OK;
6663e074
JW
693#else
694 AvbIOResult rc;
695 struct tee_param param[2];
696
697 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
698 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
699
700 memset(param, 0, sizeof(param));
701 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
702 param[0].u.value.a = rollback_index_slot;
703 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
704
705 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
706 ARRAY_SIZE(param), param);
707 if (rc)
708 return rc;
709
710 *out_rollback_index = (u64)param[1].u.value.a << 32 |
711 (u32)param[1].u.value.b;
712 return AVB_IO_RESULT_OK;
713#endif
3af30e44
IO
714}
715
716/**
717 * write_rollback_index() - sets the rollback index corresponding to the
718 * location of given by @out_rollback_index.
719 *
720 * @ops: contains AvbOps handlers
721 * @rollback_index_slot:
722 * @rollback_index: rollback index to write.
723 *
724 * @return
725 * AVB_IO_RESULT_OK, if the roolback index was retrieved
726 */
727static AvbIOResult write_rollback_index(AvbOps *ops,
728 size_t rollback_index_slot,
729 u64 rollback_index)
730{
6663e074 731#ifndef CONFIG_OPTEE_TA_AVB
3af30e44 732 /* For now this is a no-op. */
5d4fd877 733 printf("%s not supported yet\n", __func__);
3af30e44
IO
734
735 return AVB_IO_RESULT_OK;
6663e074
JW
736#else
737 struct tee_param param[2];
738
739 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
740 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
741
742 memset(param, 0, sizeof(param));
743 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
744 param[0].u.value.a = rollback_index_slot;
745 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
746 param[1].u.value.a = (u32)(rollback_index >> 32);
747 param[1].u.value.b = (u32)rollback_index;
748
749 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
750 ARRAY_SIZE(param), param);
751#endif
3af30e44
IO
752}
753
754/**
755 * read_is_device_unlocked() - gets whether the device is unlocked
756 *
757 * @ops: contains AVB ops handlers
758 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
759 * false otherwise
760 *
761 * @return:
762 * AVB_IO_RESULT_OK: state is retrieved successfully
763 * AVB_IO_RESULT_ERROR_IO: an error occurred
764 */
765static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
766{
6663e074 767#ifndef CONFIG_OPTEE_TA_AVB
3af30e44
IO
768 /* For now we always return that the device is unlocked. */
769
5d4fd877 770 printf("%s not supported yet\n", __func__);
3af30e44
IO
771
772 *out_is_unlocked = true;
773
774 return AVB_IO_RESULT_OK;
6663e074
JW
775#else
776 AvbIOResult rc;
777 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
778
779 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
780 if (rc)
781 return rc;
782 *out_is_unlocked = !param.u.value.a;
783 return AVB_IO_RESULT_OK;
784#endif
3af30e44
IO
785}
786
787/**
788 * get_unique_guid_for_partition() - gets the GUID for a partition identified
789 * by a string name
790 *
791 * @ops: contains AVB ops handlers
792 * @partition: partition name (NUL-terminated UTF-8 string)
793 * @guid_buf: buf, used to copy in GUID string. Example of value:
794 * 527c1c6d-6361-4593-8842-3c78fcd39219
795 * @guid_buf_size: @guid_buf buffer size
796 *
797 * @return:
798 * AVB_IO_RESULT_OK, on success (GUID found)
799 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
800 * provided
801 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
802 */
803static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
804 const char *partition,
805 char *guid_buf,
806 size_t guid_buf_size)
807{
808 struct mmc_part *part;
809 size_t uuid_size;
810
811 part = get_partition(ops, partition);
812 if (!part)
813 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
814
815 uuid_size = sizeof(part->info.uuid);
816 if (uuid_size > guid_buf_size)
817 return AVB_IO_RESULT_ERROR_IO;
818
819 memcpy(guid_buf, part->info.uuid, uuid_size);
820 guid_buf[uuid_size - 1] = 0;
821
822 return AVB_IO_RESULT_OK;
823}
824
7a5fbfe6
IO
825/**
826 * get_size_of_partition() - gets the size of a partition identified
827 * by a string name
828 *
829 * @ops: contains AVB ops handlers
830 * @partition: partition name (NUL-terminated UTF-8 string)
831 * @out_size_num_bytes: returns the value of a partition size
832 *
833 * @return:
834 * AVB_IO_RESULT_OK, on success (GUID found)
835 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
836 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
837 */
838static AvbIOResult get_size_of_partition(AvbOps *ops,
839 const char *partition,
840 u64 *out_size_num_bytes)
841{
842 struct mmc_part *part;
843
844 if (!out_size_num_bytes)
845 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
846
847 part = get_partition(ops, partition);
848 if (!part)
849 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
850
851 *out_size_num_bytes = part->info.blksz * part->info.size;
852
853 return AVB_IO_RESULT_OK;
854}
855
f254bd02 856#ifdef CONFIG_OPTEE_TA_AVB
fc1fe01b
IO
857static AvbIOResult read_persistent_value(AvbOps *ops,
858 const char *name,
859 size_t buffer_size,
860 u8 *out_buffer,
861 size_t *out_num_bytes_read)
862{
863 AvbIOResult rc;
864 struct tee_shm *shm_name;
865 struct tee_shm *shm_buf;
866 struct tee_param param[2];
867 struct udevice *tee;
868 size_t name_size = strlen(name) + 1;
869
870 if (get_open_session(ops->user_data))
871 return AVB_IO_RESULT_ERROR_IO;
872
873 tee = ((struct AvbOpsData *)ops->user_data)->tee;
874
875 rc = tee_shm_alloc(tee, name_size,
876 TEE_SHM_ALLOC, &shm_name);
877 if (rc)
878 return AVB_IO_RESULT_ERROR_OOM;
879
880 rc = tee_shm_alloc(tee, buffer_size,
881 TEE_SHM_ALLOC, &shm_buf);
882 if (rc) {
883 rc = AVB_IO_RESULT_ERROR_OOM;
884 goto free_name;
885 }
886
887 memcpy(shm_name->addr, name, name_size);
888
889 memset(param, 0, sizeof(param));
890 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
891 param[0].u.memref.shm = shm_name;
892 param[0].u.memref.size = name_size;
893 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
894 param[1].u.memref.shm = shm_buf;
895 param[1].u.memref.size = buffer_size;
896
897 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
898 2, param);
899 if (rc)
900 goto out;
901
902 if (param[1].u.memref.size > buffer_size) {
903 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
904 goto out;
905 }
906
907 *out_num_bytes_read = param[1].u.memref.size;
908
909 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
910
911out:
912 tee_shm_free(shm_buf);
913free_name:
914 tee_shm_free(shm_name);
915
916 return rc;
917}
918
919static AvbIOResult write_persistent_value(AvbOps *ops,
920 const char *name,
921 size_t value_size,
922 const u8 *value)
923{
924 AvbIOResult rc;
925 struct tee_shm *shm_name;
926 struct tee_shm *shm_buf;
927 struct tee_param param[2];
928 struct udevice *tee;
929 size_t name_size = strlen(name) + 1;
930
931 if (get_open_session(ops->user_data))
932 return AVB_IO_RESULT_ERROR_IO;
933
934 tee = ((struct AvbOpsData *)ops->user_data)->tee;
935
936 if (!value_size)
937 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
938
939 rc = tee_shm_alloc(tee, name_size,
940 TEE_SHM_ALLOC, &shm_name);
941 if (rc)
942 return AVB_IO_RESULT_ERROR_OOM;
943
944 rc = tee_shm_alloc(tee, value_size,
945 TEE_SHM_ALLOC, &shm_buf);
946 if (rc) {
947 rc = AVB_IO_RESULT_ERROR_OOM;
948 goto free_name;
949 }
950
951 memcpy(shm_name->addr, name, name_size);
952 memcpy(shm_buf->addr, value, value_size);
953
954 memset(param, 0, sizeof(param));
955 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
956 param[0].u.memref.shm = shm_name;
957 param[0].u.memref.size = name_size;
958 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
959 param[1].u.memref.shm = shm_buf;
960 param[1].u.memref.size = value_size;
961
962 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
963 2, param);
964 if (rc)
965 goto out;
966
967out:
968 tee_shm_free(shm_buf);
969free_name:
970 tee_shm_free(shm_name);
971
972 return rc;
973}
f254bd02
SP
974#endif
975
3af30e44
IO
976/**
977 * ============================================================================
978 * AVB2.0 AvbOps alloc/initialisation/free
979 * ============================================================================
980 */
981AvbOps *avb_ops_alloc(int boot_device)
982{
983 struct AvbOpsData *ops_data;
984
985 ops_data = avb_calloc(sizeof(struct AvbOpsData));
986 if (!ops_data)
987 return NULL;
988
989 ops_data->ops.user_data = ops_data;
990
991 ops_data->ops.read_from_partition = read_from_partition;
992 ops_data->ops.write_to_partition = write_to_partition;
993 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
994 ops_data->ops.read_rollback_index = read_rollback_index;
995 ops_data->ops.write_rollback_index = write_rollback_index;
996 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
997 ops_data->ops.get_unique_guid_for_partition =
998 get_unique_guid_for_partition;
fc1fe01b
IO
999#ifdef CONFIG_OPTEE_TA_AVB
1000 ops_data->ops.write_persistent_value = write_persistent_value;
1001 ops_data->ops.read_persistent_value = read_persistent_value;
1002#endif
7a5fbfe6 1003 ops_data->ops.get_size_of_partition = get_size_of_partition;
3af30e44
IO
1004 ops_data->mmc_dev = boot_device;
1005
1006 return &ops_data->ops;
1007}
1008
1009void avb_ops_free(AvbOps *ops)
1010{
1011 struct AvbOpsData *ops_data;
1012
47e41631 1013 if (!ops)
3af30e44
IO
1014 return;
1015
1016 ops_data = ops->user_data;
1017
6663e074
JW
1018 if (ops_data) {
1019#ifdef CONFIG_OPTEE_TA_AVB
1020 if (ops_data->tee)
1021 tee_close_session(ops_data->tee, ops_data->session);
1022#endif
3af30e44 1023 avb_free(ops_data);
6663e074 1024 }
3af30e44 1025}
This page took 0.27936 seconds and 4 git commands to generate.