blob: d60601f9123f96c05a0d298b24166eba0060a655 [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 Hongalf1fb0472017-05-23 20:05:16 -070033#include <Library/MenuKeysDetection.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070034#include <Library/VerifiedBootMenu.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 = " ";
Jeevan Shriram17f173d2017-10-24 22:11:07 -070040
41STATIC struct verified_boot_verity_mode VbVm[] = {
42 {FALSE, "logging"},
43 {TRUE, "enforcing"},
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070044};
45
Jeevan Shriram17f173d2017-10-24 22:11:07 -070046STATIC struct verified_boot_state_name VbSn[] = {
47 {GREEN, "green"},
48 {ORANGE, "orange"},
49 {YELLOW, "yellow"},
50 {RED, "red"},
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070051};
52
Jeevan Shriram17f173d2017-10-24 22:11:07 -070053struct boolean_string {
54 BOOLEAN value;
55 CHAR8 *name;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070056};
57
Jeevan Shriram17f173d2017-10-24 22:11:07 -070058STATIC struct boolean_string BooleanString[] = {
59 {FALSE, "false"},
60 {TRUE, "true"}
61};
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070062
63typedef struct {
Jeevan Shriram17f173d2017-10-24 22:11:07 -070064 AvbOps *Ops;
65 AvbSlotVerifyData *SlotData;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070066} VB2Data;
67
Jeevan Shriram17f173d2017-10-24 22:11:07 -070068UINT32
69GetAVBVersion ()
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070070{
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070071#if VERIFIED_BOOT_2
Jeevan Shriram17f173d2017-10-24 22:11:07 -070072 return 2;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -070073#elif VERIFIED_BOOT
Jeevan Shriram17f173d2017-10-24 22:11:07 -070074 return 1;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070075#else
Jeevan Shriram17f173d2017-10-24 22:11:07 -070076 return 0;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070077#endif
78}
79
Jeevan Shriram17f173d2017-10-24 22:11:07 -070080BOOLEAN
81VerifiedBootEnbled ()
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070082{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070083 return (GetAVBVersion () > NO_AVB);
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070084}
85
Jeevan Shriram17f173d2017-10-24 22:11:07 -070086STATIC EFI_STATUS
87AppendVBCmdLine (BootInfo *Info, CONST CHAR8 *Src)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070088{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070089 EFI_STATUS Status = EFI_SUCCESS;
90 INT32 SrcLen = AsciiStrLen (Src);
91 CHAR8 *Dst = Info->VBCmdLine + Info->VBCmdLineFilledLen;
92 INT32 DstLen = Info->VBCmdLineLen - Info->VBCmdLineFilledLen;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070093
Jeevan Shriram17f173d2017-10-24 22:11:07 -070094 GUARD (AsciiStrnCatS (Dst, DstLen, Src, SrcLen));
95 Info->VBCmdLineFilledLen += SrcLen;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070096
Jeevan Shriram17f173d2017-10-24 22:11:07 -070097 return EFI_SUCCESS;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -070098}
99
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700100STATIC EFI_STATUS
101AppendVBCommonCmdLine (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700102{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700103 EFI_STATUS Status = EFI_SUCCESS;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700104
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700105 if (Info->VbIntf->Revision >= QCOM_VERIFIEDBOOT_PROTOCOL_REVISION) {
106 GUARD (AppendVBCmdLine (Info, VerifiedState));
107 GUARD (AppendVBCmdLine (Info, VbSn[Info->BootState].name));
108 }
109 GUARD (AppendVBCmdLine (Info, KeymasterLoadState));
110 GUARD (AppendVBCmdLine (Info, Space));
111 return EFI_SUCCESS;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700112}
113
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700114STATIC EFI_STATUS
115VBCommonInit (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700116{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700117 EFI_STATUS Status = EFI_SUCCESS;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700118
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700119 /* AVB 2.0 requires multi slot */
120 if (GetAVBVersion () >= AVB_2 && !Info->MultiSlotBoot) {
121 DEBUG ((EFI_D_ERROR, "AVB requires multislot support!\n"));
122 return EFI_LOAD_ERROR;
123 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700124
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700125 Info->BootState = RED;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700126
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700127 Status = gBS->LocateProtocol (&gEfiQcomVerifiedBootProtocolGuid, NULL,
128 (VOID **)&(Info->VbIntf));
129 if (Status != EFI_SUCCESS) {
130 DEBUG ((EFI_D_ERROR, "Unable to locate VB protocol: %r\n", Status));
Zhen Kongdb33a732017-07-10 12:23:00 -0700131 return Status;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700132 }
133
134 return Status;
Zhen Kongdb33a732017-07-10 12:23:00 -0700135}
136
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700137STATIC EFI_STATUS
138VBAllocateCmdLine (BootInfo *Info)
Zhen Kongdb33a732017-07-10 12:23:00 -0700139{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700140 EFI_STATUS Status = EFI_SUCCESS;
Zhen Kongdb33a732017-07-10 12:23:00 -0700141
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700142 /* allocate VB command line*/
143 Info->VBCmdLine = AllocatePool (DTB_PAD_SIZE);
144 if (Info->VBCmdLine == NULL) {
145 DEBUG ((EFI_D_ERROR, "VB CmdLine allocation failed!\n"));
146 Status = EFI_OUT_OF_RESOURCES;
Zhen Kongdb33a732017-07-10 12:23:00 -0700147 return Status;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700148 }
149 Info->VBCmdLineLen = DTB_PAD_SIZE;
150 Info->VBCmdLineFilledLen = 0;
151 Info->VBCmdLine[Info->VBCmdLineFilledLen] = '\0';
152
153 return Status;
Zhen Kongdb33a732017-07-10 12:23:00 -0700154}
155
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700156STATIC EFI_STATUS
157LoadImageNoAuth (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700158{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700159 EFI_STATUS Status = EFI_SUCCESS;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700160
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700161 if (Info->Images[0].ImageBuffer != NULL && Info->Images[0].ImageSize > 0) {
162 /* fastboot boot option image already loaded */
163 return Status;
164 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700165
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700166 Status = LoadImage (Info->Pname, (VOID **)&(Info->Images[0].ImageBuffer),
167 (UINT32 *)&(Info->Images[0].ImageSize));
168 if (Status != EFI_SUCCESS) {
169 DEBUG ((EFI_D_ERROR, "ERROR: Failed to load image from partition: %r\n",
170 Status));
171 return EFI_LOAD_ERROR;
172 }
173 Info->NumLoadedImages = 1;
174 Info->Images[0].Name = AllocatePool (StrLen (Info->Pname) + 1);
175 UnicodeStrToAsciiStr (Info->Pname, Info->Images[0].Name);
176 return Status;
177}
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700178
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700179STATIC EFI_STATUS
180LoadImageNoAuthWrapper (BootInfo *Info)
181{
182 EFI_STATUS Status = EFI_SUCCESS;
183 CHAR8 *SystemPath = NULL;
184 UINT32 SystemPathLen = 0;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700185
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700186 GUARD (VBAllocateCmdLine (Info));
187 GUARD (LoadImageNoAuth (Info));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700188
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700189 if (!IsBootDevImage ()) {
190 SystemPathLen = GetSystemPath (&SystemPath);
191 if (SystemPathLen == 0 || SystemPath == NULL) {
192 DEBUG ((EFI_D_ERROR, "GetSystemPath failed!\n"));
193 return EFI_LOAD_ERROR;
Zhen Kongdb33a732017-07-10 12:23:00 -0700194 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700195 GUARD (AppendVBCmdLine (Info, SystemPath));
196 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700197
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700198 return Status;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700199}
200
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700201STATIC EFI_STATUS
202LoadImageAndAuthVB1 (BootInfo *Info)
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700203{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700204 EFI_STATUS Status = EFI_SUCCESS;
205 CHAR8 StrPnameAscii[MAX_GPT_NAME_SIZE]; /* partition name starting with
206 / and no suffix */
207 CHAR8 PnameAscii[MAX_GPT_NAME_SIZE];
208 CHAR8 *SystemPath = NULL;
209 UINT32 SystemPathLen = 0;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700210
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700211 GUARD (VBCommonInit (Info));
212 GUARD (VBAllocateCmdLine (Info));
213 GUARD (LoadImageNoAuth (Info));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700214
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700215 device_info_vb_t DevInfo_vb;
216 DevInfo_vb.is_unlocked = IsUnlocked ();
217 DevInfo_vb.is_unlock_critical = IsUnlockCritical ();
218 Status = Info->VbIntf->VBDeviceInit (Info->VbIntf,
219 (device_info_vb_t *)&DevInfo_vb);
220 if (Status != EFI_SUCCESS) {
221 DEBUG ((EFI_D_ERROR, "Error during VBDeviceInit: %r\n", Status));
222 return Status;
223 }
224
225 AsciiStrnCpyS (StrPnameAscii, ARRAY_SIZE (StrPnameAscii), "/",
226 AsciiStrLen ("/"));
227 UnicodeStrToAsciiStr (Info->Pname, PnameAscii);
228 if (Info->MultiSlotBoot) {
229 AsciiStrnCatS (StrPnameAscii, ARRAY_SIZE (StrPnameAscii), PnameAscii,
230 AsciiStrLen (PnameAscii) - (MAX_SLOT_SUFFIX_SZ - 1));
231 } else {
232 AsciiStrnCatS (StrPnameAscii, ARRAY_SIZE (StrPnameAscii), PnameAscii,
233 AsciiStrLen (PnameAscii));
234 }
235
236 Status =
237 Info->VbIntf->VBVerifyImage (Info->VbIntf, (UINT8 *)StrPnameAscii,
238 (UINT8 *)Info->Images[0].ImageBuffer,
239 Info->Images[0].ImageSize, &Info->BootState);
240 if (Status != EFI_SUCCESS || Info->BootState == BOOT_STATE_MAX) {
241 DEBUG ((EFI_D_ERROR, "VBVerifyImage failed with: %r\n", Status));
242 return Status;
243 }
244
245 Status = Info->VbIntf->VBSendRot (Info->VbIntf);
246 if (Status != EFI_SUCCESS) {
247 DEBUG ((EFI_D_ERROR, "Error sending Rot : %r\n", Status));
248 return Status;
249 }
250
251 if (!IsBootDevImage ()) {
252 SystemPathLen = GetSystemPath (&SystemPath);
253 if (SystemPathLen == 0 || SystemPath == NULL) {
254 DEBUG ((EFI_D_ERROR, "GetSystemPath failed!\n"));
255 return EFI_LOAD_ERROR;
256 }
257 GUARD (AppendVBCmdLine (Info, SystemPath));
258 }
259 GUARD (AppendVBCommonCmdLine (Info));
260 GUARD (AppendVBCmdLine (Info, VerityMode));
261 GUARD (AppendVBCmdLine (Info, VbVm[IsEnforcing ()].name));
262
263 Info->VBData = NULL;
264 return Status;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700265}
266
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700267STATIC BOOLEAN
268ResultShouldContinue (AvbSlotVerifyResult Result)
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700269{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700270 switch (Result) {
271 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
272 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
273 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
274 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
275 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
276 return FALSE;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700277
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700278 case AVB_SLOT_VERIFY_RESULT_OK:
279 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
280 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
281 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
282 return TRUE;
283 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700284
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700285 return FALSE;
286}
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700287
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700288STATIC EFI_STATUS
289LoadImageAndAuthVB2 (BootInfo *Info)
290{
291 EFI_STATUS Status = EFI_SUCCESS;
292 AvbSlotVerifyResult Result;
293 AvbSlotVerifyData *SlotData = NULL;
294 VB2Data *VBData = NULL;
295 AvbOpsUserData *UserData = NULL;
296 AvbOps *Ops = NULL;
297 CHAR8 PnameAscii[MAX_GPT_NAME_SIZE] = {0};
298 CHAR8 *SlotSuffix = NULL;
299 BOOLEAN AllowVerificationError = IsUnlocked ();
300 CONST CHAR8 *RequestedPartitionAll[] = {"boot", "dtbo", NULL};
301 CONST CHAR8 *CONST *RequestedPartition = NULL;
302 UINTN NumRequestedPartition = 0;
303 UINT32 ImageHdrSize = 0;
304 UINT32 PageSize = 0;
305 UINT32 ImageSizeActual = 0;
306 VOID *ImageBuffer = NULL;
307 UINTN ImageSize = 0;
308 KMRotAndBootState Data = {0};
309 CONST boot_img_hdr *BootImgHdr = NULL;
310 AvbSlotVerifyFlags VerifyFlags =
311 AllowVerificationError ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
312 : AVB_SLOT_VERIFY_FLAGS_NONE;
313 AvbHashtreeErrorMode VerityFlags =
314 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700315
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700316 Info->BootState = RED;
317 GUARD (VBCommonInit (Info));
318 GUARD (VBAllocateCmdLine (Info));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700319
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700320 UserData = avb_calloc (sizeof (AvbOpsUserData));
321 if (UserData == NULL) {
322 DEBUG ((EFI_D_ERROR, "ERROR: Failed to allocate AvbOpsUserData\n"));
323 Status = EFI_OUT_OF_RESOURCES;
324 goto out;
325 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700326
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700327 Ops = AvbOpsNew (UserData);
328 if (Ops == NULL) {
329 DEBUG ((EFI_D_ERROR, "ERROR: Failed to allocate AvbOps\n"));
330 Status = EFI_OUT_OF_RESOURCES;
331 goto out;
332 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700333
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700334 UnicodeStrToAsciiStr (Info->Pname, PnameAscii);
335 if ((MAX_SLOT_SUFFIX_SZ + 1) > AsciiStrLen (PnameAscii)) {
336 DEBUG ((EFI_D_ERROR, "ERROR: Can not determine slot suffix\n"));
337 Status = EFI_INVALID_PARAMETER;
338 goto out;
339 }
340 SlotSuffix = &PnameAscii[AsciiStrLen (PnameAscii) - MAX_SLOT_SUFFIX_SZ + 1];
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700341
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700342 DEBUG ((EFI_D_VERBOSE, "Slot: %a, allow verification error: %a\n", SlotSuffix,
343 BooleanString[AllowVerificationError].name));
Shivaprasad Hongal39236ae2017-06-06 16:10:35 -0700344
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700345 RequestedPartition = RequestedPartitionAll;
346 NumRequestedPartition = ARRAY_SIZE (RequestedPartitionAll) - 1;
347 if (Info->NumLoadedImages) {
348 /* fastboot boot option, skip Index 0, as boot image already
349 * loaded */
350 RequestedPartition = &RequestedPartitionAll[1];
351 NumRequestedPartition--;
352 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700353
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700354 if (FixedPcdGetBool (AllowEio)) {
355 VerityFlags = IsEnforcing () ? AVB_HASHTREE_ERROR_MODE_RESTART
356 : AVB_HASHTREE_ERROR_MODE_EIO;
357 } else {
358 VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
359 }
360
361 Result = avb_slot_verify (Ops, RequestedPartition, SlotSuffix, VerifyFlags,
362 VerityFlags, &SlotData);
363
364 if (AllowVerificationError && ResultShouldContinue (Result)) {
365 DEBUG ((EFI_D_ERROR, "State: Unlocked, AvbSlotVerify returned "
366 "%a, continue boot\n",
367 avb_slot_verify_result_to_string (Result)));
368 } else if (Result != AVB_SLOT_VERIFY_RESULT_OK) {
369 DEBUG ((EFI_D_ERROR, "ERROR: Device State %a, AvbSlotVerify returned %a\n",
370 AllowVerificationError ? "Unlocked" : "Locked",
371 avb_slot_verify_result_to_string (Result)));
372 Status = EFI_LOAD_ERROR;
373 Info->BootState = RED;
374 goto out;
375 }
376
377 for (UINTN ReqIndex = 0; ReqIndex < NumRequestedPartition; ReqIndex++) {
378 DEBUG ((EFI_D_VERBOSE, "Requested Partition: %a\n",
379 RequestedPartition[ReqIndex]));
380 for (UINTN LoadedIndex = 0; LoadedIndex < SlotData->num_loaded_partitions;
381 LoadedIndex++) {
382 DEBUG ((EFI_D_VERBOSE, "Loaded Partition: %a\n",
383 SlotData->loaded_partitions[LoadedIndex].partition_name));
384 if (!AsciiStrnCmp (
385 RequestedPartition[ReqIndex],
386 SlotData->loaded_partitions[LoadedIndex].partition_name,
387 AsciiStrLen (
388 SlotData->loaded_partitions[LoadedIndex].partition_name))) {
389 if (Info->NumLoadedImages >= ARRAY_SIZE (Info->Images)) {
390 DEBUG ((EFI_D_ERROR, "NumLoadedPartition"
391 "(%d) too large "
392 "max images(%d)\n",
393 Info->NumLoadedImages, ARRAY_SIZE (Info->Images)));
394 Status = EFI_LOAD_ERROR;
395 Info->BootState = RED;
396 goto out;
397 }
398 Info->Images[Info->NumLoadedImages].Name =
399 SlotData->loaded_partitions[LoadedIndex].partition_name;
400 Info->Images[Info->NumLoadedImages].ImageBuffer =
401 SlotData->loaded_partitions[LoadedIndex].data;
402 Info->Images[Info->NumLoadedImages].ImageSize =
403 SlotData->loaded_partitions[LoadedIndex].data_size;
404 Info->NumLoadedImages++;
405 break;
406 }
407 }
408 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700409
Zhen Kong3b3a0df2017-10-04 19:00:09 -0700410 if (Info->NumLoadedImages < (ARRAY_SIZE (RequestedPartitionAll) - 1)) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700411 DEBUG ((EFI_D_ERROR, "ERROR: AvbSlotVerify slot data error: num of "
412 "loaded partitions %d, requested %d\n",
413 Info->NumLoadedImages, ARRAY_SIZE (RequestedPartitionAll) - 1));
Zhen Kong3b3a0df2017-10-04 19:00:09 -0700414 Status = EFI_LOAD_ERROR;
415 goto out;
416 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700417
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700418 DEBUG ((EFI_D_VERBOSE, "Total loaded partition %d\n", Info->NumLoadedImages));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700419
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700420 VBData = (VB2Data *)avb_calloc (sizeof (VB2Data));
421 if (VBData == NULL) {
422 DEBUG ((EFI_D_ERROR, "ERROR: Failed to allocate VB2Data\n"));
423 Status = EFI_OUT_OF_RESOURCES;
424 goto out;
425 }
426 VBData->Ops = Ops;
427 VBData->SlotData = SlotData;
428 Info->VBData = (VOID *)VBData;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700429
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700430 GetPageSize (&ImageHdrSize);
431 GUARD_OUT (GetImage (Info, &ImageBuffer, &ImageSize, "boot"));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700432
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700433 Status =
434 CheckImageHeader (ImageBuffer, ImageHdrSize, &ImageSizeActual, &PageSize);
435 if (Status != EFI_SUCCESS) {
436 DEBUG ((EFI_D_ERROR, "Invalid boot image header:%r\n", Status));
437 goto out;
438 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700439
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700440 if (ImageSizeActual > ImageSize) {
441 Status = EFI_BUFFER_TOO_SMALL;
442 DEBUG ((EFI_D_ERROR, "Boot size in vbmeta less than actual boot image size "
443 "flash corresponding vbmeta.img\n"));
444 goto out;
445 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700446
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700447 if (AllowVerificationError) {
448 Info->BootState = ORANGE;
449 } else {
450 if (UserData->IsUserKey) {
451 Info->BootState = YELLOW;
452 } else {
453 Info->BootState = GREEN;
454 }
455 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700456
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700457 /* command line */
458 GUARD_OUT (AppendVBCommonCmdLine (Info));
459 GUARD_OUT (AppendVBCmdLine (Info, SlotData->cmdline));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700460
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700461 /* Set Rot & Boot State*/
462 Data.Color = Info->BootState;
463 Data.IsUnlocked = AllowVerificationError;
464 Data.PublicKeyLength = UserData->PublicKeyLen;
465 Data.PublicKey = UserData->PublicKey;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700466
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700467 BootImgHdr = (struct boot_img_hdr *)ImageBuffer;
468 Data.SystemSecurityLevel = (BootImgHdr->os_version & 0x7FF);
469 Data.SystemVersion = (BootImgHdr->os_version & 0xFFFFF800) >> 11;
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700470
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700471 GUARD_OUT (KeyMasterSetRotAndBootState (&Data));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700472
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700473 DEBUG ((EFI_D_INFO, "VB2: Authenticate complete! boot state is: %a\n",
474 VbSn[Info->BootState].name));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700475
476out:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700477 if (Status != EFI_SUCCESS) {
478 if (SlotData != NULL) {
479 avb_slot_verify_data_free (SlotData);
480 }
481 if (Ops != NULL) {
482 AvbOpsFree (Ops);
483 }
484 if (UserData != NULL) {
485 avb_free (UserData);
486 }
487 if (VBData != NULL) {
488 avb_free (VBData);
489 }
490 Info->BootState = RED;
491 HandleActiveSlotUnbootable ();
492 /* HandleActiveSlotUnbootable should have swapped slots and
493 * reboot the device. If no bootable slot found, enter fastboot */
494 DEBUG ((EFI_D_WARN, "No bootable slots found enter fastboot mode\n"));
495 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700496
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700497 DEBUG ((EFI_D_ERROR, "VB2: boot state: %a(%d)\n", VbSn[Info->BootState].name,
498 Info->BootState));
499 return Status;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700500}
501
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700502STATIC EFI_STATUS
503DisplayVerifiedBootScreen (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700504{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700505 EFI_STATUS Status = EFI_SUCCESS;
506 CHAR8 FfbmStr[FFBM_MODE_BUF_SIZE] = {'\0'};
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700507
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700508 if (GetAVBVersion () < AVB_1) {
509 return EFI_SUCCESS;
510 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700511
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700512 if (!StrnCmp (Info->Pname, L"boot", StrLen (L"boot"))) {
513 Status = GetFfbmCommand (FfbmStr, FFBM_MODE_BUF_SIZE);
514 if (Status != EFI_SUCCESS) {
515 DEBUG ((EFI_D_VERBOSE, "No Ffbm cookie found, ignore: %r\n", Status));
516 FfbmStr[0] = '\0';
517 }
518 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700519
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700520 DEBUG ((EFI_D_VERBOSE, "Boot State is : %d\n", Info->BootState));
521 switch (Info->BootState) {
522 case RED:
523 Status = DisplayVerifiedBootMenu (DISPLAY_MENU_RED);
524 if (Status != EFI_SUCCESS) {
525 DEBUG ((EFI_D_INFO,
526 "Your device is corrupt. It can't be trusted and will not boot."
527 "\nYour device will shutdown in 30s\n"));
528 }
529 MicroSecondDelay (30000000);
530 ShutdownDevice ();
531 break;
532 case YELLOW:
533 Status = DisplayVerifiedBootMenu (DISPLAY_MENU_YELLOW);
534 if (Status == EFI_SUCCESS) {
535 WaitForExitKeysDetection ();
536 } else {
537 DEBUG ((EFI_D_INFO, "Your device has loaded a different operating system."
538 "\nWait for 5 seconds before proceeding\n"));
539 MicroSecondDelay (5000000);
540 }
541 break;
542 case ORANGE:
543 if (FfbmStr[0] != '\0' && !TargetBuildVariantUser ()) {
544 DEBUG ((EFI_D_VERBOSE, "Device will boot into FFBM mode\n"));
545 } else {
546 Status = DisplayVerifiedBootMenu (DISPLAY_MENU_ORANGE);
547 if (Status == EFI_SUCCESS) {
548 WaitForExitKeysDetection ();
549 } else {
550 DEBUG (
551 (EFI_D_INFO, "Device is unlocked, Skipping boot verification\n"));
552 MicroSecondDelay (5000000);
553 }
554 }
555 break;
556 default:
557 break;
558 }
559 return EFI_SUCCESS;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700560}
561
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700562EFI_STATUS
563LoadImageAndAuth (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700564{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700565 EFI_STATUS Status = EFI_SUCCESS;
566 BOOLEAN MdtpActive = FALSE;
567 QCOM_MDTP_PROTOCOL *MdtpProtocol;
568 UINT32 AVBVersion = NO_AVB;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700569
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700570 if (Info == NULL) {
571 DEBUG ((EFI_D_ERROR, "Invalid parameter Info\n"));
572 return EFI_INVALID_PARAMETER;
573 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700574
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700575 /* Get Partition Name*/
576 if (!Info->MultiSlotBoot) {
577 if (Info->BootIntoRecovery) {
578 DEBUG ((EFI_D_INFO, "Booting Into Recovery Mode\n"));
579 StrnCpyS (Info->Pname, ARRAY_SIZE (Info->Pname), L"recovery",
580 StrLen (L"recovery"));
581 } else {
582 DEBUG ((EFI_D_INFO, "Booting Into Mission Mode\n"));
583 StrnCpyS (Info->Pname, ARRAY_SIZE (Info->Pname), L"boot",
584 StrLen (L"boot"));
585 }
586 } else {
587 Slot CurrentSlot = {{0}};
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700588
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700589 GUARD (FindBootableSlot (&CurrentSlot));
590 if (IsSuffixEmpty (&CurrentSlot)) {
591 DEBUG ((EFI_D_ERROR, "No bootable slot\n"));
592 return EFI_LOAD_ERROR;
593 }
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700594
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700595 GUARD (StrnCpyS (Info->Pname, ARRAY_SIZE (Info->Pname), L"boot",
596 StrLen (L"boot")));
597 GUARD (StrnCatS (Info->Pname, ARRAY_SIZE (Info->Pname), CurrentSlot.Suffix,
598 StrLen (CurrentSlot.Suffix)));
599 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700600
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700601 DEBUG ((EFI_D_VERBOSE, "MultiSlot %a, partition name %s\n",
602 BooleanString[Info->MultiSlotBoot].name, Info->Pname));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700603
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700604 if (FixedPcdGetBool (EnableMdtpSupport)) {
605 Status = IsMdtpActive (&MdtpActive);
606 if (EFI_ERROR (Status)) {
607 DEBUG ((EFI_D_ERROR, "Failed to get activation state for MDTP, "
608 "Status=%r."
609 " Considering MDTP as active and continuing \n",
610 Status));
611 if (Status != EFI_NOT_FOUND)
612 MdtpActive = TRUE;
613 }
614 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700615
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700616 AVBVersion = GetAVBVersion ();
617 DEBUG ((EFI_D_VERBOSE, "AVB version %d\n", AVBVersion));
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700618
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700619 /* Load and Authenticate */
620 switch (AVBVersion) {
621 case NO_AVB:
622 return LoadImageNoAuthWrapper (Info);
623 break;
624 case AVB_1:
625 Status = LoadImageAndAuthVB1 (Info);
626 break;
627 case AVB_2:
628 Status = LoadImageAndAuthVB2 (Info);
629 break;
630 default:
631 DEBUG ((EFI_D_ERROR, "Unsupported AVB version %d\n", AVBVersion));
632 Status = EFI_UNSUPPORTED;
633 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700634
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700635 // if MDTP is active Display Recovery UI
636 if (Status != EFI_SUCCESS && MdtpActive) {
637 Status = gBS->LocateProtocol (&gQcomMdtpProtocolGuid, NULL,
638 (VOID **)&MdtpProtocol);
639 if (EFI_ERROR (Status)) {
640 DEBUG (
641 (EFI_D_ERROR, "Failed to locate MDTP protocol, Status=%r\n", Status));
642 return Status;
643 }
644 /* Perform Local Deactivation of MDTP */
645 Status = MdtpProtocol->MdtpDeactivate (MdtpProtocol, FALSE);
646 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700647
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700648 if (IsUnlocked () && Status != EFI_SUCCESS) {
649 DEBUG ((EFI_D_ERROR, "LoadImageAndAuth failed %r\n", Status));
650 return Status;
651 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700652
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700653 DisplayVerifiedBootScreen (Info);
654 DEBUG ((EFI_D_VERBOSE, "Sending Milestone Call\n"));
655 Status = Info->VbIntf->VBSendMilestone (Info->VbIntf);
656 if (Status != EFI_SUCCESS) {
657 DEBUG ((EFI_D_ERROR, "Error sending milestone call to TZ\n"));
658 return Status;
659 }
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700660
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700661 return Status;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700662}
663
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700664VOID
665FreeVerifiedBootResource (BootInfo *Info)
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700666{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700667 DEBUG ((EFI_D_VERBOSE, "FreeVerifiedBootResource\n"));
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700668
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700669 if (Info == NULL) {
670 return;
671 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700672
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700673 VB2Data *VBData = Info->VBData;
674 if (VBData != NULL) {
675 AvbOps *Ops = VBData->Ops;
676 if (Ops != NULL) {
677 if (Ops->user_data != NULL) {
678 avb_free (Ops->user_data);
679 }
680 AvbOpsFree (Ops);
681 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700682
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700683 AvbSlotVerifyData *SlotData = VBData->SlotData;
684 if (SlotData != NULL) {
685 avb_slot_verify_data_free (SlotData);
686 }
687 avb_free (VBData);
688 }
Shivaprasad Hongale3b53392017-04-27 17:32:47 -0700689
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700690 if (Info->VBCmdLine != NULL) {
691 FreePool (Info->VBCmdLine);
692 }
693 return;
Shivaprasad Hongala2c4dd72017-04-27 14:33:18 -0700694}
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700695
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700696EFI_STATUS
697GetCertFingerPrint (UINT8 *FingerPrint,
698 UINTN FingerPrintLen,
699 UINTN *FingerPrintLenOut)
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700700{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700701 EFI_STATUS Status = EFI_SUCCESS;
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700702
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700703 if (FingerPrint == NULL || FingerPrintLenOut == NULL ||
704 FingerPrintLen < AVB_SHA256_DIGEST_SIZE) {
705 DEBUG ((EFI_D_ERROR, "GetCertFingerPrint: Invalid parameters\n"));
706 return EFI_INVALID_PARAMETER;
707 }
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700708
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700709 if (GetAVBVersion () == AVB_1) {
710 QCOM_VERIFIEDBOOT_PROTOCOL *VbIntf = NULL;
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700711
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700712 Status = gBS->LocateProtocol (&gEfiQcomVerifiedBootProtocolGuid, NULL,
713 (VOID **)&VbIntf);
714 if (Status != EFI_SUCCESS) {
715 DEBUG ((EFI_D_ERROR, "Unable to locate VerifiedBoot Protocol\n"));
716 return Status;
717 }
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700718
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700719 if (VbIntf->Revision < QCOM_VERIFIEDBOOT_PROTOCOL_REVISION) {
720 DEBUG ((EFI_D_ERROR, "GetCertFingerPrint: VB1: not "
721 "supported for this revision\n"));
722 return EFI_UNSUPPORTED;
723 }
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700724
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700725 Status = VbIntf->VBGetCertFingerPrint (VbIntf, FingerPrint, FingerPrintLen,
726 FingerPrintLenOut);
727 if (Status != EFI_SUCCESS) {
728 DEBUG ((EFI_D_ERROR, "Failed Reading CERT FingerPrint\n"));
729 return Status;
730 }
731 } else if (GetAVBVersion () == AVB_2) {
732 CHAR8 *UserKeyBuffer = NULL;
733 UINT32 UserKeyLength = 0;
734 AvbSHA256Ctx UserKeyCtx = {{0}};
735 CHAR8 *UserKeyDigest = NULL;
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700736
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700737 GUARD (GetUserKey (&UserKeyBuffer, &UserKeyLength));
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700738
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700739 avb_sha256_init (&UserKeyCtx);
740 avb_sha256_update (&UserKeyCtx, (UINT8 *)UserKeyBuffer, UserKeyLength);
741 UserKeyDigest = (CHAR8 *)avb_sha256_final (&UserKeyCtx);
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700742
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700743 CopyMem (FingerPrint, UserKeyDigest, AVB_SHA256_DIGEST_SIZE);
744 *FingerPrintLenOut = AVB_SHA256_DIGEST_SIZE;
745 } else {
746 DEBUG ((EFI_D_ERROR, "GetCertFingerPrint: not supported\n"));
747 return EFI_UNSUPPORTED;
748 }
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700749
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700750 return Status;
Shivaprasad Hongal7fd6a522017-05-10 13:56:28 -0700751}