SecureBoot.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. # Copyright (c) 2014-2018, Linaro Limited. All rights reserved.
  3. #
  4. # SPDX-License-Identifier: BSD-2-Clause-Patent
  5. #
  6. */
  7. #include <RdkBootManagerLib.h>
  8. typedef enum KEY
  9. {
  10. PK_KEY=1,
  11. KEK_KEY,
  12. DB_KEY,
  13. DBX_KEY
  14. } eKey;
  15. /* ************************** */
  16. STATIC
  17. EFI_STATUS
  18. OpenFileByDevicePath(
  19. IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
  20. OUT EFI_FILE_HANDLE *FileHandle,
  21. IN UINT64 OpenMode,
  22. IN UINT64 Attributes
  23. )
  24. {
  25. EFI_STATUS Status;
  26. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
  27. EFI_FILE_PROTOCOL *Handle1;
  28. EFI_FILE_PROTOCOL *Handle2;
  29. EFI_HANDLE DeviceHandle;
  30. if (FilePath == NULL) {
  31. return EFI_INVALID_PARAMETER;
  32. }
  33. Status = gBS->LocateDevicePath (
  34. &gEfiSimpleFileSystemProtocolGuid,
  35. FilePath,
  36. &DeviceHandle
  37. );
  38. if (EFI_ERROR (Status)) {
  39. return Status;
  40. }
  41. Status = gBS->OpenProtocol (
  42. DeviceHandle,
  43. &gEfiSimpleFileSystemProtocolGuid,
  44. (VOID**)&EfiSimpleFileSystemProtocol,
  45. gImageHandle,
  46. NULL,
  47. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  48. );
  49. if (EFI_ERROR (Status)) {
  50. return Status;
  51. }
  52. Status = EfiSimpleFileSystemProtocol->OpenVolume (\
  53. EfiSimpleFileSystemProtocol, &Handle1);
  54. if (EFI_ERROR (Status)) {
  55. FileHandle = NULL;
  56. return Status;
  57. }
  58. //
  59. // go down directories one node at a time.
  60. //
  61. while (!IsDevicePathEnd (*FilePath)) {
  62. //
  63. // For file system access each node should be a file path component
  64. //
  65. if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
  66. DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
  67. ) {
  68. FileHandle = NULL;
  69. return (EFI_INVALID_PARAMETER);
  70. }
  71. //
  72. // Open this file path node
  73. //
  74. Handle2 = Handle1;
  75. Handle1 = NULL;
  76. //
  77. // Try to test opening an existing file
  78. //
  79. Status = Handle2->Open (
  80. Handle2,
  81. &Handle1,
  82. ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
  83. OpenMode &~EFI_FILE_MODE_CREATE,
  84. 0
  85. );
  86. //
  87. // see if the error was that it needs to be created
  88. //
  89. if ((EFI_ERROR (Status)) &&
  90. (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
  91. Status = Handle2->Open (
  92. Handle2,
  93. &Handle1,
  94. ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
  95. OpenMode,
  96. Attributes
  97. );
  98. }
  99. //
  100. // Close the last node
  101. //
  102. Handle2->Close (Handle2);
  103. if (EFI_ERROR (Status)) {
  104. return (Status);
  105. }
  106. //
  107. // Get the next node
  108. //
  109. *FilePath = NextDevicePathNode (*FilePath);
  110. }
  111. //
  112. // This is a weak spot since if the undefined
  113. // SHELL_FILE_HANDLE format changes this must change also!
  114. //
  115. *FileHandle = (VOID*)Handle1;
  116. return EFI_SUCCESS;
  117. }
  118. EFI_STATUS
  119. GetFileHandler (
  120. OUT EFI_FILE_HANDLE *FileHandle,
  121. IN CONST CHAR16 *Path,
  122. IN UINT64 OpenMode
  123. )
  124. {
  125. EFI_STATUS Status;
  126. EFI_DEVICE_PATH_PROTOCOL *KeyFileDevicePath;
  127. EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevicePathFromTextProtocol;
  128. Status = EFI_SUCCESS;
  129. KeyFileDevicePath = NULL;
  130. Status = gBS->LocateProtocol (
  131. &gEfiDevicePathFromTextProtocolGuid,
  132. NULL,
  133. (VOID**)&DevicePathFromTextProtocol
  134. );
  135. ASSERT_EFI_ERROR (Status);
  136. KeyFileDevicePath = DevicePathFromTextProtocol->ConvertTextToDevicePath (Path);
  137. if (KeyFileDevicePath != NULL)
  138. {
  139. Status = OpenFileByDevicePath (&KeyFileDevicePath, FileHandle, OpenMode, 0);
  140. if (Status != EFI_SUCCESS)
  141. {
  142. DEBUG ((DEBUG_ERROR, "Getting FileHandle of %s Failed\n",Path));
  143. }
  144. }
  145. return Status;
  146. }
  147. STATIC
  148. EFI_STATUS
  149. CreateTimeBasedPayload (
  150. IN OUT UINTN *DataSize,
  151. IN OUT UINT8 **Data
  152. )
  153. {
  154. EFI_STATUS Status;
  155. UINT8 *NewData;
  156. UINT8 *Payload;
  157. UINTN PayloadSize;
  158. EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
  159. UINTN DescriptorSize;
  160. EFI_TIME Time;
  161. if (Data == NULL || DataSize == NULL) {
  162. return EFI_INVALID_PARAMETER;
  163. }
  164. //
  165. // In Setup mode or Custom mode, the variable does not need to be signed but the
  166. // parameters to the SetVariable() call still need to be prepared as authenticated
  167. // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
  168. // data in it.
  169. //
  170. Payload = *Data;
  171. PayloadSize = *DataSize;
  172. DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + \
  173. OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
  174. NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
  175. if (NewData == NULL) {
  176. return EFI_OUT_OF_RESOURCES;
  177. }
  178. if ((Payload != NULL) && (PayloadSize != 0)) {
  179. CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
  180. }
  181. DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
  182. ZeroMem (&Time, sizeof (EFI_TIME));
  183. Status = gRT->GetTime (&Time, NULL);
  184. if (EFI_ERROR (Status)) {
  185. FreePool(NewData);
  186. return Status;
  187. }
  188. Time.Pad1 = 0;
  189. Time.Nanosecond = 0;
  190. Time.TimeZone = 0;
  191. Time.Daylight = 0;
  192. Time.Pad2 = 0;
  193. CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
  194. DescriptorData->AuthInfo.Hdr.dwLength = \
  195. OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
  196. DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
  197. DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
  198. CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
  199. if (Payload != NULL) {
  200. FreePool(Payload);
  201. }
  202. *DataSize = DescriptorSize + PayloadSize;
  203. *Data = NewData;
  204. return EFI_SUCCESS;
  205. }
  206. STATIC
  207. EFI_STATUS
  208. SetBootMode (
  209. IN UINT8 SecureBootMode
  210. )
  211. {
  212. return gRT->SetVariable (
  213. EFI_CUSTOM_MODE_NAME,
  214. &gEfiCustomModeEnableGuid,
  215. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  216. sizeof (UINT8),
  217. &SecureBootMode
  218. );
  219. }
  220. STATIC
  221. EFI_STATUS
  222. SetVariable (
  223. IN EFI_SIGNATURE_LIST *PkCert,
  224. IN UINTN DataSize,
  225. IN eKey KeyType
  226. )
  227. {
  228. UINT32 Attr;
  229. EFI_STATUS Status;
  230. Status = EFI_SUCCESS;
  231. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
  232. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  233. if (KeyType == PK_KEY)
  234. {
  235. DEBUG ((DEBUG_INFO, "Setting PK Key\n"));
  236. Status = gRT->SetVariable (
  237. EFI_PLATFORM_KEY_NAME,
  238. &gEfiGlobalVariableGuid,
  239. Attr,
  240. DataSize,
  241. PkCert
  242. );
  243. }
  244. else if (KeyType == KEK_KEY)
  245. {
  246. DEBUG ((DEBUG_INFO, "Setting KEK Key\n"));
  247. Status = gRT->SetVariable (
  248. EFI_KEY_EXCHANGE_KEY_NAME,
  249. &gEfiGlobalVariableGuid,
  250. Attr,
  251. DataSize,
  252. PkCert
  253. );
  254. Status = gRT->SetVariable (
  255. EFI_IMAGE_SECURITY_DATABASE,
  256. &gEfiImageSecurityDatabaseGuid,
  257. Attr,
  258. DataSize,
  259. PkCert
  260. );
  261. }
  262. else
  263. {
  264. ASSERT(FALSE);
  265. }
  266. return Status;
  267. }
  268. STATIC
  269. VOID
  270. PopulateCert (
  271. OUT EFI_SIGNATURE_LIST **Cert,
  272. IN UINTN DataSize,
  273. IN UINT8 *Data
  274. )
  275. {
  276. EFI_SIGNATURE_DATA *CertData = NULL;
  277. if ((*Cert) == NULL)
  278. {
  279. (*Cert) = (EFI_SIGNATURE_LIST*) AllocateZeroPool (sizeof (EFI_SIGNATURE_LIST)
  280. + sizeof(EFI_SIGNATURE_DATA) - 1
  281. + DataSize );
  282. ASSERT ((*Cert) != NULL);
  283. }
  284. (*Cert)->SignatureListSize = (UINT32) (sizeof (EFI_SIGNATURE_LIST)
  285. + sizeof (EFI_SIGNATURE_DATA) - 1
  286. + DataSize);
  287. (*Cert)->SignatureSize = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + DataSize);
  288. (*Cert)->SignatureHeaderSize = 0;
  289. CopyGuid (&(*Cert)->SignatureType, &gEfiCertX509Guid);
  290. CertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*Cert) + \
  291. sizeof(EFI_SIGNATURE_LIST) + (*Cert)->SignatureHeaderSize);
  292. ASSERT (CertData != NULL);
  293. CopyGuid (&CertData->SignatureOwner, &gEfiGlobalVariableGuid);
  294. CopyMem (&CertData->SignatureData, Data, DataSize);
  295. }
  296. STATIC
  297. EFI_STATUS
  298. RegisterCert (
  299. IN UINT8 *KeyData,
  300. IN UINTN KeySize,
  301. IN eKey KeyType
  302. )
  303. {
  304. EFI_STATUS Status;
  305. EFI_SIGNATURE_LIST *Cert;
  306. Cert = NULL;
  307. Status = SetBootMode (CUSTOM_SECURE_BOOT_MODE);
  308. ASSERT_EFI_ERROR (Status);
  309. PopulateCert (&Cert, KeySize, KeyData);
  310. KeySize = Cert->SignatureListSize;
  311. Status = CreateTimeBasedPayload (&KeySize, (UINT8**) &Cert);
  312. ASSERT_EFI_ERROR (Status);
  313. Status = SetVariable (Cert, KeySize, KeyType);
  314. return Status;
  315. }
  316. STATIC
  317. VOID
  318. RdkSetVariable (
  319. VOID
  320. )
  321. {
  322. CONST CHAR16 *KeyPath;
  323. EFI_STATUS Status;
  324. UINT8 *KekKey, *PkKey, *KekCrtData;
  325. UINTN KekKeySize, PkKeySize, KekCrtSize;
  326. INT8* SetupMode;
  327. eKey KeyType;
  328. KeyPath = NULL;
  329. SetupMode = NULL;
  330. KekKey = PkKey = KekCrtData = NULL;
  331. KekKeySize = PkKeySize = KekCrtSize = 0;
  332. Status = GetRdkVariable (L"ROOTCERT", &KeyPath);
  333. //set only if the Kek Crt file mentioned in the configuration file
  334. if (KeyPath != NULL) {
  335. Status = RdkReadFile (
  336. KeyPath,
  337. (VOID **)&KekCrtData,
  338. &KekCrtSize
  339. );
  340. ASSERT_EFI_ERROR (Status);
  341. Status = gRT->SetVariable (
  342. L"RdkRootCertificate",
  343. &gRdkGlobalVariableGuid,
  344. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  345. KekCrtSize,
  346. KekCrtData
  347. );
  348. ASSERT_EFI_ERROR (Status);
  349. if (KekCrtData) FreePool (KekCrtData);
  350. }
  351. Status = GetRdkVariable (L"KEKCERT", &KeyPath);
  352. ASSERT_EFI_ERROR (Status);
  353. Status = RdkReadFile (
  354. KeyPath,
  355. (VOID **)&KekKey,
  356. &KekKeySize
  357. );
  358. ASSERT_EFI_ERROR (Status);
  359. Status = GetRdkVariable (L"PKCERT", &KeyPath);
  360. ASSERT_EFI_ERROR (Status);
  361. Status = RdkReadFile (
  362. KeyPath,
  363. (VOID **)&PkKey,
  364. &PkKeySize
  365. );
  366. ASSERT_EFI_ERROR (Status);
  367. KeyType = PK_KEY;
  368. Status = RegisterCert (PkKey, PkKeySize, KeyType);
  369. GetEfiGlobalVariable2 (L"SetupMode", (VOID**)&SetupMode, NULL);
  370. if (*SetupMode == 0)
  371. {
  372. DEBUG ((DEBUG_INFO, "PK Key Got Registered. Now System in User Mode\n"));
  373. KeyType = KEK_KEY;
  374. Status = RegisterCert (KekKey, KekKeySize, KeyType);
  375. }
  376. else if(*SetupMode == 1)
  377. {
  378. DEBUG ((DEBUG_INFO, "System in Standard System Mode ::: Secure Boot Not enabled\n"));
  379. ASSERT_EFI_ERROR (Status);
  380. }
  381. if ( PkKey ) FreePool (PkKey);
  382. if ( KekKey ) FreePool (KekKey);
  383. }
  384. EFI_STATUS
  385. RdkSecureBoot (
  386. EFI_HANDLE ImageHandle,
  387. EFI_BOOT_SERVICES *BootServices
  388. )
  389. {
  390. UINTN ExitDataSize;
  391. CHAR16 *ExitData;
  392. CHAR16 LoadOption[128];
  393. CONST CHAR8 *CmdLine;
  394. CHAR16 *ImagePath;
  395. UINT8 *FdtData;
  396. CONST CHAR16 *DtbPath;
  397. EFI_STATUS Status;
  398. EFI_HANDLE Handle;
  399. EFI_DEVICE_PATH_PROTOCOL *FilePath;
  400. EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
  401. EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevicePathFromTextProtocol;
  402. FilePath = NULL;
  403. ExitData = NULL;
  404. CmdLine = (CONST CHAR8 *)FixedPcdGetPtr (PcdRdkCmdLineArgs);
  405. if (FixedPcdGetBool (PcdDtbAvailable)) {
  406. FdtData = NULL;
  407. DtbPath = NULL;
  408. Status = GetRdkVariable (L"DTB", &DtbPath);
  409. ASSERT_EFI_ERROR (Status);
  410. Status = RdkReadFile (DtbPath, (VOID**) &FdtData, NULL);
  411. ASSERT_EFI_ERROR (Status);
  412. Status = gBS->InstallConfigurationTable (&gFdtTableGuid,(VOID*)FdtData);
  413. ASSERT_EFI_ERROR (Status);
  414. }
  415. RdkSetVariable ();
  416. Status = GetRdkVariable (L"IMAGE", (CONST CHAR16**)&ImagePath);
  417. ASSERT_EFI_ERROR (Status);
  418. Status = gBS->LocateProtocol (
  419. &gEfiDevicePathFromTextProtocolGuid,
  420. NULL,
  421. (VOID**)&DevicePathFromTextProtocol
  422. );
  423. ASSERT_EFI_ERROR (Status);
  424. FilePath = DevicePathFromTextProtocol->ConvertTextToDevicePath (ImagePath);
  425. ASSERT(NULL != FilePath);
  426. Status = BootServices->LoadImage (
  427. TRUE,
  428. ImageHandle,
  429. FilePath,
  430. NULL,
  431. 0,
  432. &Handle
  433. );
  434. ASSERT_EFI_ERROR (Status);
  435. UnicodeSPrintAsciiFormat (LoadOption, sizeof (LoadOption), CmdLine);
  436. Status = BootServices->HandleProtocol (\
  437. Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
  438. ASSERT_EFI_ERROR (Status);
  439. ImageInfo->LoadOptionsSize = sizeof (LoadOption);
  440. ImageInfo->LoadOptions = LoadOption;
  441. Status = BootServices->StartImage (Handle, &ExitDataSize, &ExitData);
  442. ASSERT_EFI_ERROR (Status);
  443. return Status;
  444. }