OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleImg4Lib.c
Go to the documentation of this file.
1
14#include <Uefi.h>
15
16#include <Guid/AppleVariable.h>
17
19
20#include <Library/BaseLib.h>
21#include <Library/BaseMemoryLib.h>
22#include <Library/DebugLib.h>
23#include <Library/MemoryAllocationLib.h>
25#include <Library/OcCryptoLib.h>
27#include <Library/OcMiscLib.h>
28#include <Library/UefiBootServicesTableLib.h>
29#include <Library/UefiRuntimeServicesTableLib.h>
30
31#include "libDER/oids.h"
33#include "libDERImg4/Img4oids.h"
34
35GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 *DERImg4RootCertificate = gAppleX86SecureBootRootCaCert;
36GLOBAL_REMOVE_IF_UNREFERENCED const UINTN *DERImg4RootCertificateSize = &gAppleX86SecureBootRootCaCertSize;
37
38typedef struct OC_SB_MODEL_DESC_ {
39 CONST CHAR8 *HardwareModel;
40 UINT32 BoardId;
42
43STATIC CHAR8 mCryptoDigestMethod[16] = "sha2-384";
50 { "j132", 0x0C },
51 { "j137", 0x0A },
52 { "j140a", 0x37 },
53 { "j140k", 0x17 },
54 { "j152f", 0x3A },
55 { "j160", 0x0F },
56 { "j174", 0x0E },
57 { "j185", 0x22 },
58 { "j185f", 0x23 },
59 { "j213", 0x18 },
60 { "j214k", 0x3E },
61 { "j215", 0x38 },
62 { "j223", 0x3B },
63 { "j230k", 0x3F },
64 { "j680", 0x0B },
65 { "j780", 0x07 },
66 { OC_SB_MODEL_LEGACY, 0xF0 },
67};
68
69STATIC BOOLEAN mHasDigestOverride;
72
73STATIC
76 IN CONST CHAR8 *Model
77 )
78{
79 UINTN Start;
80 UINTN End;
81 UINTN Curr;
82 INTN Cmp;
83
84 //
85 // Classic binary search in a sorted string list.
86 //
87 Start = 0;
89
90 while (Start <= End) {
91 Curr = (Start + End) / 2;
92 Cmp = AsciiStrCmp (mModelInformation[Curr].HardwareModel, Model);
93
94 if (Cmp == 0) {
95 return &mModelInformation[Curr];
96 } else if (Cmp < 0) {
97 Start = Curr + 1;
98 } else if (Curr > 0) {
99 End = Curr - 1;
100 } else {
101 //
102 // Even the first element does not match, required due to unsigned End.
103 //
104 return NULL;
105 }
106 }
107
108 return NULL;
109}
110
111bool
113 DERByte *Modulus,
114 DERSize ModulusSize,
115 uint32_t Exponent,
116 const uint8_t *Signature,
117 size_t SignatureSize,
118 uint8_t *Data,
119 size_t DataSize,
120 const DERItem *AlgoOid
121 )
122{
123 OC_SIG_HASH_TYPE AlgoType;
124
125 ASSERT (Modulus != NULL);
126 ASSERT (ModulusSize > 0);
127 ASSERT (Signature != NULL);
128 ASSERT (SignatureSize > 0);
129 ASSERT (Data != NULL);
130 ASSERT (DataSize > 0);
131 ASSERT (AlgoOid != NULL);
132
133 if (DEROidCompare (AlgoOid, &oidSha512Rsa)) {
134 AlgoType = OcSigHashTypeSha512;
135 } else if (DEROidCompare (AlgoOid, &oidSha384Rsa)) {
136 AlgoType = OcSigHashTypeSha384;
137 } else if (DEROidCompare (AlgoOid, &oidSha256Rsa)) {
138 AlgoType = OcSigHashTypeSha256;
139 } else {
140 return false;
141 }
142
144 Modulus,
145 ModulusSize,
146 Exponent,
147 Signature,
148 SignatureSize,
149 Data,
150 DataSize,
151 AlgoType
152 );
153}
154
155CONST CHAR8 *
157 IN CONST CHAR8 *ModelRequest
158 )
159{
160 OC_SB_MODEL_DESC *ModelInfo;
161
162 ModelInfo = InternalGetModelInfo (ModelRequest);
163 if (ModelInfo != NULL) {
164 return ModelInfo->HardwareModel;
165 }
166
167 return NULL;
168}
169
170EFI_STATUS
171EFIAPI
174 IN UINT32 ObjType,
175 IN CONST VOID *ImageBuffer,
176 IN UINTN ImageSize,
177 IN UINT8 SbMode,
178 IN CONST VOID *ManifestBuffer,
179 IN UINTN ManifestSize,
180 OUT UINT8 **HashDigest OPTIONAL,
181 OUT UINTN *DigestSize OPTIONAL
182 )
183{
184 DERReturn DerResult;
185 INTN CmpResult;
186 UINT8 Digest[SHA384_DIGEST_SIZE];
187
188 DERImg4ManifestInfo ManInfo;
189
190 if ( ((ImageBuffer == NULL) || (ImageSize == 0))
191 || ((ManifestBuffer == NULL) || (ManifestSize == 0))
192 || ((HashDigest == NULL) && (DigestSize != NULL))
193 || ((HashDigest != NULL) && (DigestSize == NULL))
194 || ( (SbMode != AppleImg4SbModeMedium)
195 && (SbMode != AppleImg4SbModeFull)))
196 {
197 return EFI_INVALID_PARAMETER;
198 }
199
200 DerResult = DERImg4ParseManifest (
201 &ManInfo,
202 ManifestBuffer,
203 ManifestSize,
204 ObjType
205 );
206 if (DerResult != DR_Success) {
207 DEBUG ((
208 DEBUG_INFO,
209 "OCI4: Manifest (%u) for %08X parse fail with code %d\n",
210 ManifestSize,
211 ObjType,
212 DerResult
213 ));
214 return EFI_SECURITY_VIOLATION;
215 }
216
217 CmpResult = -1;
218
219 DEBUG ((
220 DEBUG_INFO,
221 "OCI4: Verifying digest %u (%02X%02X%02X%02X) override %d %u (%02X%02X%02X%02X)\n",
222 ManInfo.imageDigestSize,
223 ManInfo.imageDigest[0],
224 ManInfo.imageDigest[1],
225 ManInfo.imageDigest[2],
226 ManInfo.imageDigest[3],
233 ));
234
235 //
236 // Provide a route to accept our modified kernel as long as we can trust it is really it.
237 //
239 && (ManInfo.imageDigestSize == SHA384_DIGEST_SIZE)
240 && (CompareMem (mOriginalDigest, ManInfo.imageDigest, sizeof (mOriginalDigest)) == 0))
241 {
242 Sha384 (Digest, ImageBuffer, ImageSize);
243 CmpResult = CompareMem (Digest, mOverrideDigest, sizeof (mOverrideDigest));
244 DEBUG ((
245 DEBUG_INFO,
246 "OCI4: Matching override %02X%02X%02X%02X with %02X%02X%02X%02X - %a\n",
251 Digest[0],
252 Digest[1],
253 Digest[2],
254 Digest[3],
255 CmpResult == 0 ? "success" : "failure"
256 ));
257 if (CmpResult == 0) {
258 mHasDigestOverride = FALSE;
259 }
260 }
261
262 //
263 // As ManInfo.imageDigest is a buffer of static size, the bounds check to
264 // retrieve it acts as implicit sanitizing of ManInfo.imageDigestSize which
265 // can be considered trusted at this point.
266 //
267 if (CmpResult != 0) {
268 CmpResult = SigVerifyShaHashBySize (
269 ImageBuffer,
270 ImageSize,
271 ManInfo.imageDigest,
272 ManInfo.imageDigestSize
273 );
274 }
275
276 if (CmpResult != 0) {
277 return EFI_SECURITY_VIOLATION;
278 }
279
280 if (SbMode == AppleImg4SbModeMedium) {
281 if ( ManInfo.hasEcid
282 || !ManInfo.hasXugs || (ManInfo.environment.xugs != mEnvInfo.xugs)
285 {
286 return EFI_SECURITY_VIOLATION;
287 }
288 } else if (SbMode == AppleImg4SbModeFull) {
289 if ( !ManInfo.hasEcid || (ManInfo.environment.ecid != mEnvInfo.ecid)
290 || ManInfo.hasXugs
292 {
293 return EFI_SECURITY_VIOLATION;
294 }
295 }
296
297 if ( (ManInfo.environment.boardId != mEnvInfo.boardId)
298 || (ManInfo.environment.chipId != mEnvInfo.chipId)
305 || ( ManInfo.hasEffectiveSecurityMode
307 )
308 {
309 return EFI_SECURITY_VIOLATION;
310 }
311
312 if (HashDigest != NULL) {
313 *HashDigest = AllocateCopyPool (ManInfo.imageDigestSize, ManInfo.imageDigest);
314 if (*HashDigest == NULL) {
315 return EFI_OUT_OF_RESOURCES;
316 }
317
318 *DigestSize = ManInfo.imageDigestSize;
319 }
320
321 return EFI_SUCCESS;
322}
323
324VOID
326 IN CONST UINT8 *OriginalDigest,
327 IN CONST UINT8 *Image,
328 IN UINT32 ImageSize
329 )
330{
331 ASSERT (OriginalDigest != NULL);
332 ASSERT (Image != NULL);
333 ASSERT (ImageSize > 0);
334
335 mHasDigestOverride = TRUE;
336 CopyMem (mOriginalDigest, OriginalDigest, sizeof (mOriginalDigest));
337 Sha384 (mOverrideDigest, Image, ImageSize);
338}
339
340EFI_STATUS
342 IN CONST CHAR8 *Model,
343 IN UINT64 Ecid OPTIONAL
344 )
345{
346 EFI_STATUS Status;
347 OC_SB_MODEL_DESC *SbInfo;
348 UINT8 Tmp;
349
350 ASSERT (Model != NULL);
351 SbInfo = InternalGetModelInfo (Model);
352 ASSERT (SbInfo != NULL);
353
354 //
355 // Predefine most of the values as they are common for all the models.
356 //
357 mEnvInfo.ecid = Ecid;
358 mEnvInfo.boardId = SbInfo->BoardId;
359 mEnvInfo.chipId = 0x8012;
366 mEnvInfo.internalUseOnlyUnit = AsciiStrCmp (Model, OC_SB_MODEL_LEGACY) == 0;
367 mEnvInfo.xugs = 1;
368 mEnvInfo.allowMixNMatch = FALSE;
369
370 //
371 // Expose all the variables via NVRAM.
372 //
373 Status = gRT->SetVariable (
374 L"ApECID",
376 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
377 sizeof (mEnvInfo.ecid),
379 );
380 if (EFI_ERROR (Status)) {
381 return Status;
382 }
383
384 Status = gRT->SetVariable (
385 L"ApChipID",
387 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
388 sizeof (mEnvInfo.chipId),
390 );
391 if (EFI_ERROR (Status)) {
392 return Status;
393 }
394
395 Tmp = (UINT8)mEnvInfo.certificateEpoch;
396 Status = gRT->SetVariable (
397 L"CertificateEpoch",
399 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
400 sizeof (Tmp),
401 &Tmp
402 );
403 if (EFI_ERROR (Status)) {
404 return Status;
405 }
406
407 Status = gRT->SetVariable (
408 L"ApBoardID",
410 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
411 sizeof (mEnvInfo.boardId),
413 );
414 if (EFI_ERROR (Status)) {
415 return Status;
416 }
417
418 Status = gRT->SetVariable (
419 L"ApSecurityDomain",
421 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
422 sizeof (mEnvInfo.securityDomain),
424 );
425 if (EFI_ERROR (Status)) {
426 return Status;
427 }
428
429 Status = gRT->SetVariable (
430 L"ApProductionStatus",
432 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
433 sizeof (mEnvInfo.productionStatus),
435 );
436 if (EFI_ERROR (Status)) {
437 return Status;
438 }
439
440 Status = gRT->SetVariable (
441 L"ApSecurityMode",
443 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
444 sizeof (mEnvInfo.securityMode),
446 );
447 if (EFI_ERROR (Status)) {
448 return Status;
449 }
450
451 Status = gRT->SetVariable (
452 L"EffectiveProductionStatus",
454 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
457 );
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461
462 Status = gRT->SetVariable (
463 L"EffectiveSecurityMode",
465 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
468 );
469 if (EFI_ERROR (Status)) {
470 return Status;
471 }
472
473 Status = gRT->SetVariable (
474 L"InternalUseOnlyUnit",
476 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
479 );
480 if (EFI_ERROR (Status)) {
481 return Status;
482 }
483
484 Tmp = (UINT8)mEnvInfo.allowMixNMatch;
485 Status = gRT->SetVariable (
486 L"MixNMatchPreventionStatus",
488 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
489 sizeof (Tmp),
490 &Tmp
491 );
492 if (EFI_ERROR (Status)) {
493 return Status;
494 }
495
496 Status = gRT->SetVariable (
497 L"CryptoDigestMethod",
499 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
500 sizeof (mCryptoDigestMethod),
502 );
503 if (EFI_ERROR (Status)) {
504 return Status;
505 }
506
507 return EFI_SUCCESS;
508}
509
512 IN BOOLEAN Reinstall
513 )
514{
515 STATIC APPLE_IMG4_VERIFICATION_PROTOCOL Img4Verification = {
518 };
519
520 EFI_STATUS Status;
522 EFI_HANDLE Handle;
523
524 if (Reinstall) {
526 if (EFI_ERROR (Status)) {
527 DEBUG ((DEBUG_ERROR, "OCI4: Uninstall failed - %r\n", Status));
528 return NULL;
529 }
530 } else {
531 Status = gBS->LocateProtocol (
533 NULL,
534 (VOID **)&Protocol
535 );
536 if (!EFI_ERROR (Status)) {
537 return Protocol;
538 }
539 }
540
541 Handle = NULL;
542 Status = gBS->InstallMultipleProtocolInterfaces (
543 &Handle,
545 (VOID **)&Img4Verification,
546 NULL
547 );
548 if (EFI_ERROR (Status)) {
549 return NULL;
550 }
551
552 return &Img4Verification;
553}
#define APPLE_IMG4_VERIFICATION_PROTOCOL_REVISION
EFI_GUID gAppleImg4VerificationProtocolGuid
@ AppleImg4SbModeFull
@ AppleImg4SbModeMedium
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
UINT64 Start
EFI_DEVICE_PATH_PROTOCOL End
EFI_GUID gAppleSecureBootVariableGuid
UINT8 Signature[8]
Definition BiosId.h:67
DERReturn DERImg4ParseManifest(DERImg4ManifestInfo *ManInfo, const void *ManBuffer, size_t ManSize, uint32_t ObjType)
const DERItem oidSha512Rsa
Definition Img4oids.c:43
const DERItem oidSha384Rsa
Definition Img4oids.c:39
VOID OcAppleImg4RegisterOverride(IN CONST UINT8 *OriginalDigest, IN CONST UINT8 *Image, IN UINT32 ImageSize)
CONST CHAR8 * OcAppleImg4GetHardwareModel(IN CONST CHAR8 *ModelRequest)
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 * DERImg4RootCertificate
STATIC UINT8 mOriginalDigest[SHA384_DIGEST_SIZE]
STATIC UINT8 mOverrideDigest[SHA384_DIGEST_SIZE]
STATIC BOOLEAN mHasDigestOverride
EFI_STATUS EFIAPI OcAppleImg4Verify(IN APPLE_IMG4_VERIFICATION_PROTOCOL *This, IN UINT32 ObjType, IN CONST VOID *ImageBuffer, IN UINTN ImageSize, IN UINT8 SbMode, IN CONST VOID *ManifestBuffer, IN UINTN ManifestSize, OUT UINT8 **HashDigest OPTIONAL, OUT UINTN *DigestSize OPTIONAL)
STATIC CHAR8 mCryptoDigestMethod[16]
STATIC OC_SB_MODEL_DESC mModelInformation[]
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN * DERImg4RootCertificateSize
APPLE_IMG4_VERIFICATION_PROTOCOL * OcAppleImg4VerificationInstallProtocol(IN BOOLEAN Reinstall)
STATIC DERImg4Environment mEnvInfo
EFI_STATUS OcAppleImg4BootstrapValues(IN CONST CHAR8 *Model, IN UINT64 Ecid OPTIONAL)
STATIC OC_SB_MODEL_DESC * InternalGetModelInfo(IN CONST CHAR8 *Model)
struct OC_SB_MODEL_DESC_ OC_SB_MODEL_DESC
bool DERImg4VerifySignature(DERByte *Modulus, DERSize ModulusSize, uint32_t Exponent, const uint8_t *Signature, size_t SignatureSize, uint8_t *Data, size_t DataSize, const DERItem *AlgoOid)
#define OC_SB_MODEL_LEGACY
CONST UINT8 gAppleX86SecureBootRootCaCert[]
CONST UINTN gAppleX86SecureBootRootCaCertSize
EFI_BOOT_SERVICES * gBS
VOID Sha384(UINT8 *Hash, CONST UINT8 *Data, UINTN Len)
INTN SigVerifyShaHashBySize(IN CONST VOID *Data, IN UINTN DataSize, IN CONST UINT8 *Hash, IN UINTN HashSize)
enum OC_SIG_HASH_TYPE_ OC_SIG_HASH_TYPE
BOOLEAN RsaVerifySigDataFromData(IN CONST UINT8 *Modulus, IN UINTN ModulusSize, IN UINT32 Exponent, IN CONST UINT8 *Signature, IN UINTN SignatureSize, IN CONST UINT8 *Data, IN UINTN DataSize, IN OC_SIG_HASH_TYPE Algorithm)
@ OcSigHashTypeSha384
@ OcSigHashTypeSha512
@ OcSigHashTypeSha256
#define SHA384_DIGEST_SIZE
Definition OcCryptoLib.h:46
EFI_STATUS OcUninstallAllProtocolInstances(EFI_GUID *Protocol)
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
#define ASSERT(x)
Definition coder.h:55
DERReturn
Definition libDER.h:20
@ DR_Success
Definition libDER.h:21
size_t DERSize
UINT8 uint8_t
uint8_t DERByte
UINT32 uint32_t
const DERItem oidSha256Rsa
Definition oids.c:272
bool DEROidCompare(const DERItem *oid1, const DERItem *oid2)
Definition oids.c:454
bool effectiveProductionStatus
Definition libDERImg4.h:36
uint32_t allowMixNMatch
Definition libDERImg4.h:41
uint32_t securityDomain
Definition libDERImg4.h:33
uint32_t certificateEpoch
Definition libDERImg4.h:32
uint8_t imageDigest[DER_IMG4_MAX_DIGEST_SIZE]
Definition libDERImg4.h:51
bool hasEffectiveSecurityMode
Definition libDERImg4.h:48
DERImg4Environment environment
Definition libDERImg4.h:45
bool hasEffectiveProductionStatus
Definition libDERImg4.h:47
CONST CHAR8 * HardwareModel