blob: 79397502cd4936b282fd89ab1f30139903a16637 [file] [log] [blame]
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include "VerifiedBoot.h"
30#include "BootLinux.h"
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070031#include "KeymasterClient.h"
32#include "libavb/libavb.h"
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070033#include <Library/VerifiedBootMenu.h>
Shivaprasad Hongalf1fb0472017-05-23 20:05:16 -070034#include <Library/MenuKeysDetection.h>
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070035
36STATIC CONST CHAR8 *VerityMode = " androidboot.veritymode=";
37STATIC CONST CHAR8 *VerifiedState = " androidboot.verifiedbootstate=";
38STATIC CONST CHAR8 *KeymasterLoadState = " androidboot.keymaster=1";
39STATIC CONST CHAR8 *Space = " ";
40STATIC struct verified_boot_verity_mode VbVm[] =
41{
42 {FALSE, "logging"},
43 {TRUE, "enforcing"},
44};
45STATIC struct verified_boot_state_name VbSn[] =
46{
47 {GREEN, "green"},
48 {ORANGE, "orange"},
49 {YELLOW, "yellow"},
50 {RED, "red"},
51};
52
53struct boolean_string
54{
55 BOOLEAN value;
56 CHAR8 *name;
57};
58
59STATIC struct boolean_string BooleanString[] =
60{
61 {FALSE, "false"},
62 {TRUE, "true"}
63};
64
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070065
66typedef struct {
67 AvbOps *Ops;
68 AvbSlotVerifyData *SlotData;
69} VB2Data;
70
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070071UINT32 GetAVBVersion()
72{
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070073#if VERIFIED_BOOT_2
74 return 2;
75#elif VERIFIED_BOOT
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070076 return 1;
77#else
78 return 0;
79#endif
80}
81
82BOOLEAN VerifiedBootEnbled()
83{
84 return (GetAVBVersion() > NO_AVB);
85}
86
Shivaprasad Hongalb7c1eb42017-04-21 15:11:39 -070087STATIC CHAR8 DtboImageName[] = "dtbo";
88STATIC EFI_STATUS TempLoadDtboImage(AvbOps *Ops, VOID **DtboImage, UINTN *DtboSize)
89{
90 /* Hardcoded reading from dtbo_a partition
91 And reading 8192KB size as mentioned in partition.xml */
92 *DtboSize = 8192 * 1024;
93 *DtboImage = AllocatePool(*DtboSize);
94 Ops->read_from_partition(Ops, "dtbo_a", 0, *DtboSize, *DtboImage, DtboSize);
95 return EFI_SUCCESS;
96}
97
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070098STATIC EFI_STATUS AppendVBCmdLine(BootInfo *Info, CONST CHAR8 *Src)
99{
100 EFI_STATUS Status = EFI_SUCCESS;
101 INT32 SrcLen = AsciiStrLen(Src);
102 CHAR8 *Dst = Info->VBCmdLine + Info->VBCmdLineFilledLen;
103 INT32 DstLen = Info->VBCmdLineLen - Info->VBCmdLineFilledLen;
104
105 GUARD(AsciiStrnCatS(Dst, DstLen, Src, SrcLen));
106 Info->VBCmdLineFilledLen += SrcLen;
107
108 return EFI_SUCCESS;
109}
110
111STATIC EFI_STATUS AppendVBCommonCmdLine(BootInfo *Info)
112{
113 EFI_STATUS Status = EFI_SUCCESS;
114
Shivaprasad Hongal5dd35932017-07-06 17:41:23 -0700115 if (Info->VbIntf->Revision >= QCOM_VERIFIEDBOOT_PROTOCOL_REVISION) {
116 GUARD(AppendVBCmdLine(Info, VerifiedState));
117 GUARD(AppendVBCmdLine(Info, VbSn[Info->BootState].name));
118 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700119 GUARD(AppendVBCmdLine(Info, KeymasterLoadState));
120 GUARD(AppendVBCmdLine(Info, Space));
121 return EFI_SUCCESS;
122}
123
124STATIC EFI_STATUS VBCommonInit(BootInfo *Info)
125{
126 EFI_STATUS Status = EFI_SUCCESS;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700127
128 /* AVB 2.0 requires multi slot */
129 if (GetAVBVersion() >= AVB_2 && !Info->MultiSlotBoot) {
130 DEBUG((EFI_D_ERROR, "AVB requires multislot support!\n"));
131 return EFI_LOAD_ERROR;
132 }
133
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700134 Info->BootState = RED;
135
136 Status = gBS->LocateProtocol(&gEfiQcomVerifiedBootProtocolGuid, NULL,
137 (VOID **)&(Info->VbIntf));
138 if (Status != EFI_SUCCESS) {
139 DEBUG((EFI_D_ERROR, "Unable to locate VB protocol: %r\n", Status));
140 return Status;
141 }
Zhen Kongdb33a732017-07-10 12:23:00 -0700142
143 return Status;
144}
145
146STATIC EFI_STATUS VBAllocateCmdLine (BootInfo *Info)
147{
148 EFI_STATUS Status = EFI_SUCCESS;
149
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700150 /* allocate VB command line*/
151 Info->VBCmdLine = AllocatePool(DTB_PAD_SIZE);
152 if (Info->VBCmdLine == NULL) {
153 DEBUG((EFI_D_ERROR, "VB CmdLine allocation failed!\n"));
154 Status = EFI_OUT_OF_RESOURCES;
155 return Status;
156 }
157 Info->VBCmdLineLen = DTB_PAD_SIZE;
158 Info->VBCmdLineFilledLen = 0;
159 Info->VBCmdLine[Info->VBCmdLineFilledLen] = '\0';
160
161 return Status;
162}
163
164STATIC EFI_STATUS LoadImageNoAuth(BootInfo *Info)
165{
166 EFI_STATUS Status = EFI_SUCCESS;
167
168 if (Info->Images[0].ImageBuffer != NULL && Info->Images[0].ImageSize > 0) {
169 /* fastboot boot option image already loaded */
170 return Status;
171 }
172
173 Status = LoadImage(Info->Pname, (VOID **)&(Info->Images[0].ImageBuffer),
174 (UINT32 *)&(Info->Images[0].ImageSize));
175 if (Status != EFI_SUCCESS) {
176 DEBUG((EFI_D_ERROR,
177 "ERROR: Failed to load image from partition: %r\n", Status));
178 return EFI_LOAD_ERROR;
179 }
180 Info->NumLoadedImages = 1;
181 Info->Images[0].Name = AllocatePool(StrLen(Info->Pname) + 1);
182 UnicodeStrToAsciiStr(Info->Pname, Info->Images[0].Name);
183 return Status;
184}
185
Zhen Kongdb33a732017-07-10 12:23:00 -0700186STATIC EFI_STATUS LoadImageNoAuthWrapper (BootInfo *Info)
187{
188 EFI_STATUS Status = EFI_SUCCESS;
189 CHAR8 *SystemPath = NULL;
190 UINT32 SystemPathLen = 0;
191
192 GUARD (VBAllocateCmdLine (Info));
193 GUARD (LoadImageNoAuth (Info));
194
195 if (!IsBootDevImage ()) {
196 SystemPathLen = GetSystemPath (&SystemPath);
197 if (SystemPathLen == 0 ||
198 SystemPath == NULL) {
199 DEBUG ((EFI_D_ERROR, "GetSystemPath failed!\n"));
200 return EFI_LOAD_ERROR;
201 }
202 GUARD (AppendVBCmdLine (Info, SystemPath));
203 }
204
205 return Status;
206}
207
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700208STATIC EFI_STATUS LoadImageAndAuthVB1(BootInfo *Info)
209{
210 EFI_STATUS Status = EFI_SUCCESS;
211 CHAR8 StrPnameAscii[MAX_GPT_NAME_SIZE]; /* partition name starting with
212 / and no suffix */
213 CHAR8 PnameAscii[MAX_GPT_NAME_SIZE];
214 CHAR8 *SystemPath = NULL;
215 UINT32 SystemPathLen = 0;
216
217 GUARD(VBCommonInit(Info));
Zhen Kongdb33a732017-07-10 12:23:00 -0700218 GUARD (VBAllocateCmdLine (Info));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700219 GUARD(LoadImageNoAuth(Info));
220
221 device_info_vb_t DevInfo_vb;
222 DevInfo_vb.is_unlocked = IsUnlocked();
223 DevInfo_vb.is_unlock_critical = IsUnlockCritical();
224 Status = Info->VbIntf->VBDeviceInit(Info->VbIntf,
225 (device_info_vb_t *)&DevInfo_vb);
226 if (Status != EFI_SUCCESS) {
227 DEBUG((EFI_D_ERROR, "Error during VBDeviceInit: %r\n", Status));
228 return Status;
229 }
230
231 AsciiStrnCpyS(StrPnameAscii, ARRAY_SIZE(StrPnameAscii), "/", AsciiStrLen("/"));
232 UnicodeStrToAsciiStr(Info->Pname, PnameAscii);
233 if (Info->MultiSlotBoot) {
234 AsciiStrnCatS(StrPnameAscii, ARRAY_SIZE(StrPnameAscii), PnameAscii,
235 AsciiStrLen(PnameAscii) - (MAX_SLOT_SUFFIX_SZ - 1));
236 } else {
237 AsciiStrnCatS(StrPnameAscii, ARRAY_SIZE(StrPnameAscii),
238 PnameAscii, AsciiStrLen(PnameAscii));
239 }
240
241 Status = Info->VbIntf->VBVerifyImage(Info->VbIntf, (UINT8 *)StrPnameAscii,
242 (UINT8 *)Info->Images[0].ImageBuffer,
243 Info->Images[0].ImageSize,
244 &Info->BootState);
245 if (Status != EFI_SUCCESS || Info->BootState == BOOT_STATE_MAX) {
246 DEBUG((EFI_D_ERROR, "VBVerifyImage failed with: %r\n", Status));
247 return Status;
248 }
249
250 Status = Info->VbIntf->VBSendRot(Info->VbIntf);
251 if (Status != EFI_SUCCESS) {
252 DEBUG((EFI_D_ERROR, "Error sending Rot : %r\n", Status));
253 return Status;
254 }
255
Zhen Kongdb33a732017-07-10 12:23:00 -0700256 if (!IsBootDevImage ()) {
257 SystemPathLen = GetSystemPath (&SystemPath);
258 if (SystemPathLen == 0 ||
259 SystemPath == NULL) {
260 DEBUG ((EFI_D_ERROR, "GetSystemPath failed!\n"));
261 return EFI_LOAD_ERROR;
262 }
263 GUARD (AppendVBCmdLine (Info, SystemPath));
264 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700265 GUARD(AppendVBCommonCmdLine(Info));
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700266 GUARD(AppendVBCmdLine(Info, VerityMode));
267 GUARD(AppendVBCmdLine(Info, VbVm[IsEnforcing()].name));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700268
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700269 Info->VBData = NULL;
270 return Status;
271}
272
273STATIC BOOLEAN ResultShouldContinue(AvbSlotVerifyResult Result)
274{
275 switch (Result) {
276 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
277 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
278 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
279 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700280 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700281 return FALSE;
282
283 case AVB_SLOT_VERIFY_RESULT_OK:
284 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
285 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
286 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
287 return TRUE;
288 }
289
290 return FALSE;
291}
292
293STATIC EFI_STATUS LoadImageAndAuthVB2(BootInfo *Info)
294{
295 EFI_STATUS Status = EFI_SUCCESS;
296 AvbSlotVerifyResult Result;
297 AvbSlotVerifyData *SlotData = NULL;
298 VB2Data *VBData = NULL;
299 AvbOpsUserData *UserData = NULL;
300 AvbOps *Ops = NULL;
301 CHAR8 PnameAscii[MAX_GPT_NAME_SIZE] = {0};
302 CHAR8 *SlotSuffix = NULL;
303 BOOLEAN AllowVerificationError = IsUnlocked();
Shivaprasad Hongala0091a42017-04-27 18:31:34 -0700304 CONST CHAR8 *RequestedPartitionAll[] = {"boot", "dtbo", NULL};
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700305 CONST CHAR8 *CONST *RequestedPartition = NULL;
306 UINTN NumRequestedPartition = 0;
307 UINT32 ImageHdrSize = 0;
308 UINT32 PageSize = 0;
309 UINT32 ImageSizeActual = 0;
310 VOID *ImageBuffer = NULL;
311 UINTN ImageSize = 0;
312 KMRotAndBootState Data = {0};
313 CONST boot_img_hdr *BootImgHdr = NULL;
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700314 AvbSlotVerifyFlags VerifyFlags = AllowVerificationError ?
315 AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR :
316 AVB_SLOT_VERIFY_FLAGS_NONE;
317 AvbHashtreeErrorMode VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700318
319 Info->BootState = RED;
320 GUARD(VBCommonInit(Info));
Zhen Kongdb33a732017-07-10 12:23:00 -0700321 GUARD (VBAllocateCmdLine (Info));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700322
323 UserData = avb_calloc(sizeof(AvbOpsUserData));
324 if (UserData == NULL) {
325 DEBUG((EFI_D_ERROR,
326 "ERROR: Failed to allocate AvbOpsUserData\n"));
327 Status = EFI_OUT_OF_RESOURCES;
328 goto out;
329 }
330
331 Ops = AvbOpsNew(UserData);
332 if (Ops == NULL) {
333 DEBUG((EFI_D_ERROR, "ERROR: Failed to allocate AvbOps\n"));
334 Status = EFI_OUT_OF_RESOURCES;
335 goto out;
336 }
337
338 UnicodeStrToAsciiStr(Info->Pname, PnameAscii);
339 if ((MAX_SLOT_SUFFIX_SZ + 1) > AsciiStrLen(PnameAscii)) {
340 DEBUG((EFI_D_ERROR, "ERROR: Can not determine slot suffix\n"));
341 Status = EFI_INVALID_PARAMETER;
342 goto out;
343 }
344 SlotSuffix = &PnameAscii[AsciiStrLen(PnameAscii) - MAX_SLOT_SUFFIX_SZ + 1];
345
346 DEBUG((EFI_D_VERBOSE, "Slot: %a, allow verification error: %a\n",
347 SlotSuffix, BooleanString[AllowVerificationError].name));
348
349 RequestedPartition = RequestedPartitionAll;
350 NumRequestedPartition = ARRAY_SIZE(RequestedPartitionAll) - 1;
351 if (Info->NumLoadedImages) {
352 /* fastboot boot option, skip Index 0, as boot image already
353 * loaded */
354 RequestedPartition = &RequestedPartitionAll[1];
355 NumRequestedPartition--;
356 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700357
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700358 if(FixedPcdGetBool(AllowEio)) {
lijuang7f5a26d2017-07-27 19:41:32 +0800359 VerityFlags = IsEnforcing() ?
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700360 AVB_HASHTREE_ERROR_MODE_RESTART :
361 AVB_HASHTREE_ERROR_MODE_EIO;
362 } else {
363 VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
364 }
365
366 Result = avb_slot_verify(Ops, RequestedPartition, SlotSuffix,
367 VerifyFlags, VerityFlags,
368 &SlotData);
369
370 if (AllowVerificationError && ResultShouldContinue(Result)) {
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700371 DEBUG((EFI_D_ERROR, "State: Unlocked, AvbSlotVerify returned "
372 "%a, continue boot\n",
373 avb_slot_verify_result_to_string(Result)));
374 } else if (Result != AVB_SLOT_VERIFY_RESULT_OK) {
375 DEBUG((EFI_D_ERROR,
376 "ERROR: Device State %a, AvbSlotVerify returned %a\n",
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700377 AllowVerificationError ? "Unlocked" : "Locked",
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700378 avb_slot_verify_result_to_string(Result)));
379 Status = EFI_LOAD_ERROR;
380 Info->BootState = RED;
381 goto out;
382 }
383
384 for (UINTN ReqIndex = 0; ReqIndex < NumRequestedPartition; ReqIndex++) {
385 DEBUG((EFI_D_VERBOSE, "Requested Partition: %a\n",
386 RequestedPartition[ReqIndex]));
387 for (UINTN LoadedIndex = 0;
388 LoadedIndex < SlotData->num_loaded_partitions; LoadedIndex++) {
389 DEBUG((EFI_D_VERBOSE, "Loaded Partition: %a\n",
390 SlotData->loaded_partitions[LoadedIndex].partition_name));
391 if (!AsciiStrnCmp(
392 RequestedPartition[ReqIndex],
393 SlotData->loaded_partitions[LoadedIndex].partition_name,
394 AsciiStrLen(SlotData->loaded_partitions[LoadedIndex]
395 .partition_name))) {
396 if (Info->NumLoadedImages >= ARRAY_SIZE(Info->Images)) {
397 DEBUG((EFI_D_ERROR, "NumLoadedPartition"
398 "(%d) too large "
399 "max images(%d)\n",
400 Info->NumLoadedImages,
401 ARRAY_SIZE(Info->Images)));
402 Status = EFI_LOAD_ERROR;
403 Info->BootState = RED;
404 goto out;
405 }
406 Info->Images[Info->NumLoadedImages].Name =
407 SlotData->loaded_partitions[LoadedIndex].partition_name;
408 Info->Images[Info->NumLoadedImages].ImageBuffer =
409 SlotData->loaded_partitions[LoadedIndex].data;
410 Info->Images[Info->NumLoadedImages].ImageSize =
411 SlotData->loaded_partitions[LoadedIndex].data_size;
412 Info->NumLoadedImages++;
413 break;
414 }
415 }
416 }
417
418 if (Info->NumLoadedImages < (ARRAY_SIZE(RequestedPartitionAll) - 1)) {
Shivaprasad Hongalb7c1eb42017-04-21 15:11:39 -0700419 VOID *DtboImage = NULL;
420 UINTN DtboSize = 0;
421
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700422 DEBUG((EFI_D_ERROR,
423 "ERROR: AvbSlotVerify slot data error: num of "
424 "loaded partitions %d, requested %d\n",
425 Info->NumLoadedImages, ARRAY_SIZE(RequestedPartitionAll) - 1));
Shivaprasad Hongalb7c1eb42017-04-21 15:11:39 -0700426 /* Temporary workaround load dtbo image here, probably dtbo is not
427 included in vbmeta */
428 Status = TempLoadDtboImage(Ops, &DtboImage, &DtboSize);
429 if (Status == EFI_SUCCESS) {
430 Info->Images[Info->NumLoadedImages].Name = DtboImageName;
431 Info->Images[Info->NumLoadedImages].ImageBuffer = DtboImage;
432 Info->Images[Info->NumLoadedImages].ImageSize = DtboSize;
433 Info->NumLoadedImages++;
434 } else {
435 DEBUG((EFI_D_ERROR, "LoadDtboImage failed!"));
436 Status = EFI_LOAD_ERROR;
437 goto out;
438 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700439 }
440
441 DEBUG((EFI_D_VERBOSE, "Total loaded partition %d\n", Info->NumLoadedImages));
442
443 VBData = (VB2Data *)avb_calloc(sizeof(VB2Data));
444 if (VBData == NULL) {
445 DEBUG((EFI_D_ERROR, "ERROR: Failed to allocate VB2Data\n"));
446 Status = EFI_OUT_OF_RESOURCES;
447 goto out;
448 }
449 VBData->Ops = Ops;
450 VBData->SlotData = SlotData;
451 Info->VBData = (VOID *)VBData;
452
453 GetPageSize(&ImageHdrSize);
454 GUARD_OUT(GetImage(Info, &ImageBuffer, &ImageSize, "boot"));
455
456 Status = CheckImageHeader(ImageBuffer, ImageHdrSize, &ImageSizeActual, &PageSize);
457 if (Status != EFI_SUCCESS) {
458 DEBUG((EFI_D_ERROR, "Invalid boot image header:%r\n", Status));
Zhen Kong4c788f52017-07-19 16:51:58 -0700459 goto out;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700460 }
461
462 if (ImageSizeActual > ImageSize) {
463 Status = EFI_BUFFER_TOO_SMALL;
464 DEBUG((EFI_D_ERROR,
465 "Boot size in vbmeta less than actual boot image size "
466 "flash corresponding vbmeta.img\n"));
467 goto out;
468 }
469
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700470 if (AllowVerificationError) {
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700471 Info->BootState = ORANGE;
472 } else {
473 if (UserData->IsUserKey) {
474 Info->BootState = YELLOW;
475 } else {
476 Info->BootState = GREEN;
477 }
478 }
479
480 /* command line */
481 GUARD_OUT(AppendVBCommonCmdLine(Info));
482 GUARD_OUT(AppendVBCmdLine(Info, SlotData->cmdline));
483
484 /* Set Rot & Boot State*/
485 Data.Color = Info->BootState;
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700486 Data.IsUnlocked = AllowVerificationError;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700487 Data.PublicKeyLength = UserData->PublicKeyLen;
488 Data.PublicKey = UserData->PublicKey;
489
490 BootImgHdr = (struct boot_img_hdr *)ImageBuffer;
491 Data.SystemSecurityLevel = (BootImgHdr->os_version & 0x7FF);
Shivaprasad Hongal3df04522017-06-16 12:12:05 -0700492 Data.SystemVersion = (BootImgHdr->os_version & 0xFFFFF800) >> 11;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700493
494 GUARD_OUT(KeyMasterSetRotAndBootState(&Data));
495
496 DEBUG((EFI_D_INFO, "VB2: Authenticate complete! boot state is: %a\n",
497 VbSn[Info->BootState].name));
498
499out:
500 if (Status != EFI_SUCCESS) {
501 if (SlotData != NULL) {
502 avb_slot_verify_data_free(SlotData);
503 }
504 if (Ops != NULL) {
505 AvbOpsFree(Ops);
506 }
507 if (UserData != NULL) {
508 avb_free(UserData);
509 }
510 if (VBData != NULL) {
511 avb_free(VBData);
512 }
513 Info->BootState = RED;
Zhen Kong4c788f52017-07-19 16:51:58 -0700514 HandleActiveSlotUnbootable();
515 /* HandleActiveSlotUnbootable should have swapped slots and
516 * reboot the device. If no bootable slot found, enter fastboot */
517 DEBUG((EFI_D_WARN,
Shivaprasad Hongal38d73ea2017-05-05 18:09:47 -0700518 "No bootable slots found enter fastboot mode\n"));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700519 }
520
521 DEBUG((EFI_D_ERROR, "VB2: boot state: %a(%d)\n",
522 VbSn[Info->BootState].name, Info->BootState));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700523 return Status;
524}
525
526STATIC EFI_STATUS DisplayVerifiedBootScreen(BootInfo *Info)
527{
528 EFI_STATUS Status = EFI_SUCCESS;
529 CHAR8 FfbmStr[FFBM_MODE_BUF_SIZE] = {'\0'};
530
531 if (GetAVBVersion() < AVB_1) {
532 return EFI_SUCCESS;
533 }
534
535 if (!StrnCmp(Info->Pname, L"boot", StrLen(L"boot"))) {
536 Status = GetFfbmCommand(FfbmStr, FFBM_MODE_BUF_SIZE);
537 if (Status != EFI_SUCCESS) {
538 DEBUG((EFI_D_VERBOSE,
539 "No Ffbm cookie found, ignore: %r\n", Status));
540 FfbmStr[0] = '\0';
541 }
542 }
543
544 DEBUG((EFI_D_VERBOSE, "Boot State is : %d\n", Info->BootState));
Shivaprasad Hongalf1fb0472017-05-23 20:05:16 -0700545 switch (Info->BootState)
546 {
lijuange4b02a82017-07-21 15:53:22 +0800547 case RED:
548 Status = DisplayVerifiedBootMenu(DISPLAY_MENU_RED);
549 if (Status != EFI_SUCCESS) {
550 DEBUG((EFI_D_INFO, "Your device is corrupt. It can't be trusted and will not boot." \
551 "\nYour device will shutdown in 30s\n"));
552 }
553 MicroSecondDelay(30000000);
554 ShutdownDevice();
555 break;
556 case YELLOW:
557 Status = DisplayVerifiedBootMenu(DISPLAY_MENU_YELLOW);
558 if (Status == EFI_SUCCESS) {
559 WaitForExitKeysDetection();
560 } else {
561 DEBUG((EFI_D_INFO, "Your device has loaded a different operating system." \
562 "\nWait for 5 seconds before proceeding\n"));
Shivaprasad Hongalf1fb0472017-05-23 20:05:16 -0700563 MicroSecondDelay(5000000);
lijuange4b02a82017-07-21 15:53:22 +0800564 }
565 break;
566 case ORANGE:
567 if (FfbmStr[0] != '\0' && !TargetBuildVariantUser()) {
568 DEBUG((EFI_D_VERBOSE, "Device will boot into FFBM mode\n"));
569 } else {
570 Status = DisplayVerifiedBootMenu(DISPLAY_MENU_ORANGE);
571 if (Status == EFI_SUCCESS) {
572 WaitForExitKeysDetection();
573 } else {
574 DEBUG((EFI_D_INFO, "Device is unlocked, Skipping boot verification\n"));
575 MicroSecondDelay(5000000);
576 }
577 }
578 break;
579 default:
580 break;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700581 }
582 return EFI_SUCCESS;
583}
584
585EFI_STATUS LoadImageAndAuth(BootInfo *Info)
586{
587 EFI_STATUS Status = EFI_SUCCESS;
588 BOOLEAN MdtpActive = FALSE;
589 QCOM_MDTP_PROTOCOL *MdtpProtocol;
590 UINT32 AVBVersion = NO_AVB;
591
592 if (Info == NULL) {
593 DEBUG((EFI_D_ERROR, "Invalid parameter Info\n"));
594 return EFI_INVALID_PARAMETER;
595 }
596
597 /* Get Partition Name*/
598 if (!Info->MultiSlotBoot) {
599 if (Info->BootIntoRecovery) {
600 DEBUG((EFI_D_INFO, "Booting Into Recovery Mode\n"));
601 StrnCpyS(Info->Pname, ARRAY_SIZE(Info->Pname),
602 L"recovery", StrLen(L"recovery"));
603 } else {
604 DEBUG((EFI_D_INFO, "Booting Into Mission Mode\n"));
605 StrnCpyS(Info->Pname, ARRAY_SIZE(Info->Pname), L"boot",
606 StrLen(L"boot"));
607 }
608 } else {
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700609 Slot CurrentSlot = {{0}};
610
611 GUARD(FindBootableSlot(&CurrentSlot));
612 if (IsSuffixEmpty(&CurrentSlot)) {
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700613 DEBUG((EFI_D_ERROR, "No bootable slot\n"));
614 return EFI_LOAD_ERROR;
615 }
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700616
617 GUARD(StrnCpyS(Info->Pname, ARRAY_SIZE(Info->Pname), L"boot",
618 StrLen(L"boot")));
619 GUARD(StrnCatS(Info->Pname, ARRAY_SIZE(Info->Pname),
620 CurrentSlot.Suffix, StrLen(CurrentSlot.Suffix)));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700621 }
622
623 DEBUG((EFI_D_VERBOSE, "MultiSlot %a, partition name %s\n",
624 BooleanString[Info->MultiSlotBoot].name, Info->Pname));
625
626 if (FixedPcdGetBool(EnableMdtpSupport)) {
627 Status = IsMdtpActive(&MdtpActive);
628 if (EFI_ERROR(Status)) {
629 DEBUG((EFI_D_ERROR,
630 "Failed to get activation state for MDTP, "
631 "Status=%r."
632 " Considering MDTP as active and continuing \n",
633 Status));
634 if (Status != EFI_NOT_FOUND)
635 MdtpActive = TRUE;
636 }
637 }
638
639 AVBVersion = GetAVBVersion();
640 DEBUG((EFI_D_VERBOSE, "AVB version %d\n", AVBVersion));
641
642 /* Load and Authenticate */
643 switch (AVBVersion) {
644 case NO_AVB:
Zhen Kongdb33a732017-07-10 12:23:00 -0700645 return LoadImageNoAuthWrapper (Info);
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700646 break;
647 case AVB_1:
648 Status = LoadImageAndAuthVB1(Info);
649 break;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700650 case AVB_2:
651 Status = LoadImageAndAuthVB2(Info);
652 break;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700653 default:
654 DEBUG((EFI_D_ERROR, "Unsupported AVB version %d\n", AVBVersion));
655 Status = EFI_UNSUPPORTED;
656 }
657
658 // if MDTP is active Display Recovery UI
659 if (Status != EFI_SUCCESS && MdtpActive) {
660 Status = gBS->LocateProtocol(&gQcomMdtpProtocolGuid, NULL,
661 (VOID **)&MdtpProtocol);
662 if (EFI_ERROR(Status)) {
663 DEBUG((EFI_D_ERROR,
664 "Failed to locate MDTP protocol, Status=%r\n", Status));
665 return Status;
666 }
667 /* Perform Local Deactivation of MDTP */
668 Status = MdtpProtocol->MdtpDeactivate(MdtpProtocol, FALSE);
669 }
670
Zhen Kong4c788f52017-07-19 16:51:58 -0700671 if (IsUnlocked() && Status != EFI_SUCCESS) {
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700672 DEBUG((EFI_D_ERROR, "LoadImageAndAuth failed %r\n", Status));
673 return Status;
674 }
675
Zhen Kong4c788f52017-07-19 16:51:58 -0700676 DisplayVerifiedBootScreen(Info);
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700677 DEBUG((EFI_D_VERBOSE, "Sending Milestone Call\n"));
678 Status = Info->VbIntf->VBSendMilestone(Info->VbIntf);
679 if (Status != EFI_SUCCESS) {
680 DEBUG((EFI_D_ERROR, "Error sending milestone call to TZ\n"));
681 return Status;
682 }
683
684 return Status;
685}
686
687VOID FreeVerifiedBootResource(BootInfo *Info)
688{
689 DEBUG((EFI_D_VERBOSE, "FreeVerifiedBootResource\n"));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700690
691 if (Info == NULL) {
692 return;
693 }
694
695 VB2Data *VBData = Info->VBData;
696 if (VBData != NULL) {
697 AvbOps *Ops = VBData->Ops;
698 if (Ops != NULL) {
699 if (Ops->user_data != NULL) {
700 avb_free(Ops->user_data);
701 }
702 AvbOpsFree(Ops);
703 }
704
705 AvbSlotVerifyData *SlotData = VBData->SlotData;
706 if (SlotData != NULL) {
707 avb_slot_verify_data_free(SlotData);
708 }
709 avb_free(VBData);
710 }
711
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700712 if (Info->VBCmdLine != NULL) {
713 FreePool(Info->VBCmdLine);
714 }
715 return;
716}
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700717
718EFI_STATUS GetCertFingerPrint(UINT8 *FingerPrint, UINTN FingerPrintLen,
719 UINTN *FingerPrintLenOut)
720{
721 EFI_STATUS Status = EFI_SUCCESS;
722
723 if (FingerPrint == NULL || FingerPrintLenOut == NULL ||
724 FingerPrintLen < AVB_SHA256_DIGEST_SIZE) {
725 DEBUG((EFI_D_ERROR,
726 "GetCertFingerPrint: Invalid parameters\n"));
727 return EFI_INVALID_PARAMETER;
728 }
729
730 if (GetAVBVersion() == AVB_1) {
731 QCOM_VERIFIEDBOOT_PROTOCOL *VbIntf = NULL;
732
733 Status = gBS->LocateProtocol(&gEfiQcomVerifiedBootProtocolGuid,
734 NULL, (VOID **)&VbIntf);
735 if (Status != EFI_SUCCESS) {
736 DEBUG((EFI_D_ERROR,
737 "Unable to locate VerifiedBoot Protocol\n"));
738 return Status;
739 }
740
741 if (VbIntf->Revision < QCOM_VERIFIEDBOOT_PROTOCOL_REVISION) {
742 DEBUG((EFI_D_ERROR, "GetCertFingerPrint: VB1: not "
743 "supported for this revision\n"));
744 return EFI_UNSUPPORTED;
745 }
746
747 Status = VbIntf->VBGetCertFingerPrint(
748 VbIntf, FingerPrint, FingerPrintLen, FingerPrintLenOut);
749 if (Status != EFI_SUCCESS) {
750 DEBUG((EFI_D_ERROR,
751 "Failed Reading CERT FingerPrint\n"));
752 return Status;
753 }
754 } else if (GetAVBVersion() == AVB_2) {
755 CHAR8 *UserKeyBuffer = NULL;
756 UINT32 UserKeyLength = 0;
757 AvbSHA256Ctx UserKeyCtx = {{0}};
758 CHAR8 *UserKeyDigest = NULL;
759
760 GUARD(GetUserKey(&UserKeyBuffer, &UserKeyLength));
761
762 avb_sha256_init(&UserKeyCtx);
763 avb_sha256_update(&UserKeyCtx, (UINT8 *)UserKeyBuffer, UserKeyLength);
764 UserKeyDigest = (CHAR8 *)avb_sha256_final(&UserKeyCtx);
765
766 CopyMem(FingerPrint, UserKeyDigest, AVB_SHA256_DIGEST_SIZE);
767 *FingerPrintLenOut = AVB_SHA256_DIGEST_SIZE;
768 } else {
769 DEBUG((EFI_D_ERROR, "GetCertFingerPrint: not supported\n"));
770 return EFI_UNSUPPORTED;
771 }
772
773 return Status;
774}