OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleChunklistLib.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
15#include <Library/BaseMemoryLib.h>
16#include <Library/BaseOverflowLib.h>
17#include <Library/DebugLib.h>
18#include <Library/MemoryAllocationLib.h>
21#include <Library/OcCryptoLib.h>
22
23BOOLEAN
25 OUT OC_APPLE_CHUNKLIST_CONTEXT *Context,
26 IN OUT VOID *Buffer,
27 IN UINT32 BufferSize
28 )
29{
30 APPLE_CHUNKLIST_HEADER *ChunklistHeader;
31 UINTN DataEnd;
32 UINT8 *Signature;
33 UINT32 SigLength;
34 UINT32 Index;
35 UINT8 SwapValue;
36
37 ASSERT (Buffer != NULL);
38 ASSERT (BufferSize > 0);
39 ASSERT (Context != NULL);
40
41 ChunklistHeader = (APPLE_CHUNKLIST_HEADER *)Buffer;
42
43 if (BufferSize < sizeof (APPLE_CHUNKLIST_HEADER)) {
44 return FALSE;
45 }
46
47 //
48 // Ensure the header is compatible.
49 //
50 if ( (ChunklistHeader->Magic != APPLE_CHUNKLIST_MAGIC)
51 || (ChunklistHeader->Length != sizeof (APPLE_CHUNKLIST_HEADER))
52 || (ChunklistHeader->FileVersion != APPLE_CHUNKLIST_FILE_VERSION_10)
53 || (ChunklistHeader->ChunkMethod != APPLE_CHUNKLIST_CHUNK_METHOD_10)
54 || (ChunklistHeader->SigMethod != APPLE_CHUNKLIST_SIG_METHOD_10))
55 {
56 return FALSE;
57 }
58
59 //
60 // Ensure that chunk and signature addresses are valid in the first place.
61 //
62 if ( BaseOverflowAddUN ((UINTN)Buffer, (UINTN)ChunklistHeader->ChunkOffset, (UINTN *)&Context->Chunks)
63 || BaseOverflowAddUN ((UINTN)Buffer, (UINTN)ChunklistHeader->SigOffset, (UINTN *)&Context->Signature))
64 {
65 return FALSE;
66 }
67
68 //
69 // Ensure that chunks and signature reside within Buffer.
70 //
71 if (ChunklistHeader->ChunkCount > MAX_UINTN) {
72 return FALSE;
73 }
74
75 Context->ChunkCount = (UINTN)ChunklistHeader->ChunkCount;
76
77 if ( BaseOverflowMulAddUN (sizeof (APPLE_CHUNKLIST_CHUNK), Context->ChunkCount, (UINTN)Context->Chunks, &DataEnd)
78 || (DataEnd > (UINTN)Buffer + BufferSize)
79 || BaseOverflowAddUN (sizeof (APPLE_CHUNKLIST_SIG), (UINTN)Context->Signature, &DataEnd)
80 || (DataEnd != (UINTN)Buffer + BufferSize))
81 {
82 return FALSE;
83 }
84
85 //
86 // Prepare signature verification data.
87 //
88 Sha256 (Context->Hash, (UINT8 *)ChunklistHeader, (UINTN)ChunklistHeader->SigOffset);
89
90 Signature = Context->Signature->Signature;
91 SigLength = sizeof (Context->Signature->Signature);
92
93 for (Index = 0; Index < (SigLength / 2); ++Index) {
94 SwapValue = Signature[Index];
95 Signature[Index] = Signature[SigLength - Index - 1];
96 Signature[SigLength - Index - 1] = SwapValue;
97 }
98
99 return TRUE;
100}
101
102BOOLEAN
104 IN OUT OC_APPLE_CHUNKLIST_CONTEXT *Context,
105 IN CONST OC_RSA_PUBLIC_KEY *PublicKey
106 )
107{
108 BOOLEAN Result;
109
110 ASSERT (Context != NULL);
111 ASSERT (Context->Signature != NULL);
112
114 PublicKey,
115 Context->Signature->Signature,
116 sizeof (Context->Signature->Signature),
117 Context->Hash,
118 sizeof (Context->Hash),
120 );
121
122 DEBUG_CODE_BEGIN ();
123 if (Result) {
124 Context->Signature = NULL;
125 }
126
127 DEBUG_CODE_END ();
128
129 return Result;
130}
131
132BOOLEAN
134 IN OUT OC_APPLE_CHUNKLIST_CONTEXT *Context,
136 )
137{
138 BOOLEAN Result;
139
140 UINTN Index;
141 UINT8 ChunkHash[SHA256_DIGEST_SIZE];
142 CONST APPLE_CHUNKLIST_CHUNK *CurrentChunk;
143 UINTN CurrentOffset;
144
145 UINT32 ChunkDataSize;
146 VOID *ChunkData;
147
148 ASSERT (Context != NULL);
149 ASSERT (Context->Chunks != NULL);
150 ASSERT (ExtentTable != NULL);
151
152 DEBUG_CODE (
153 ASSERT (Context->Signature == NULL);
154 );
155
156 ChunkDataSize = 0;
157 for (Index = 0; Index < Context->ChunkCount; ++Index) {
158 CurrentChunk = &Context->Chunks[Index];
159 if (ChunkDataSize < CurrentChunk->Length) {
160 ChunkDataSize = CurrentChunk->Length;
161 }
162 }
163
164 ChunkData = AllocatePool (ChunkDataSize);
165 if (ChunkData == NULL) {
166 return FALSE;
167 }
168
169 CurrentOffset = 0;
170 for (Index = 0; Index < Context->ChunkCount; Index++) {
171 CurrentChunk = &Context->Chunks[Index];
172
173 Result = OcAppleRamDiskRead (
175 CurrentOffset,
176 CurrentChunk->Length,
177 ChunkData
178 );
179 if (!Result) {
180 FreePool (ChunkData);
181 return FALSE;
182 }
183
184 //
185 // Calculate checksum of data and ensure they match.
186 //
187 DEBUG ((
188 DEBUG_VERBOSE,
189 "OCCL: Validating chunk %lu of %lu\n",
190 (UINT64)Index + 1,
191 (UINT64)Context->ChunkCount
192 ));
193 Sha256 (ChunkHash, ChunkData, CurrentChunk->Length);
194 if (CompareMem (ChunkHash, CurrentChunk->Checksum, SHA256_DIGEST_SIZE) != 0) {
195 FreePool (ChunkData);
196 return FALSE;
197 }
198
199 CurrentOffset += CurrentChunk->Length;
200 }
201
202 FreePool (ChunkData);
203 return TRUE;
204}
#define APPLE_CHUNKLIST_SIG_METHOD_10
#define APPLE_CHUNKLIST_CHUNK_METHOD_10
#define APPLE_CHUNKLIST_MAGIC
#define APPLE_CHUNKLIST_FILE_VERSION_10
APPLE_RAM_DISK_EXTENT_TABLE ExtentTable
UINT64 Length
PACKED struct @54 APPLE_RAM_DISK_EXTENT_TABLE
UINT8 Signature[8]
Definition BiosId.h:67
BOOLEAN OcAppleChunklistVerifySignature(IN OUT OC_APPLE_CHUNKLIST_CONTEXT *Context, IN CONST OC_RSA_PUBLIC_KEY *PublicKey)
BOOLEAN OcAppleChunklistInitializeContext(OUT OC_APPLE_CHUNKLIST_CONTEXT *Context, IN OUT VOID *Buffer, IN UINT32 BufferSize)
BOOLEAN OcAppleChunklistVerifyData(IN OUT OC_APPLE_CHUNKLIST_CONTEXT *Context, IN CONST APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable)
BOOLEAN OcAppleRamDiskRead(IN CONST APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable, IN UINTN Offset, IN UINTN Size, OUT VOID *Buffer)
BOOLEAN RsaVerifySigHashFromKeyDynalloc(IN CONST OC_RSA_PUBLIC_KEY *Key, IN CONST UINT8 *Signature, IN UINTN SignatureSize, IN CONST UINT8 *Hash, IN UINTN HashSize, IN OC_SIG_HASH_TYPE Algorithm)
#define SHA256_DIGEST_SIZE
Definition OcCryptoLib.h:45
@ OcSigHashTypeSha256
VOID Sha256(UINT8 *Hash, CONST UINT8 *Data, UINTN Len)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55