Add OcAppleChunklistLib

This commit is contained in:
Goldfish64 2019-01-19 15:06:38 -06:00
parent 8edacb0ad1
commit 29dbbcc313
6 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,65 @@
/** @file
Copyright (C) 2019, Goldfish64. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef APPLE_CHUNKLIST_H_
#define APPLE_CHUNKLIST_H_
#pragma pack(1)
//
// Magic number used to identify chunklist.
//
#define APPLE_CHUNKLIST_MAGIC 0x4C4B4E43 // "CNKL"
//
// Supported chunklist versions.
//
#define APPLE_CHUNKLIST_FILE_VERSION_10 0x1
#define APPLE_CHUNKLIST_CHUNK_METHOD_10 0x1
#define APPLE_CHUNKLIST_SIG_METHOD_10 0x1
#define APPLE_CHUNKLIST_CHECKSUM_LENGTH 32
#define APPLE_CHUNKLIST_SIG_LENGTH 256
//
// Chunklist chunk.
//
typedef struct {
UINT32 Length;
UINT8 Checksum[APPLE_CHUNKLIST_CHECKSUM_LENGTH];
} APPLE_CHUNKLIST_CHUNK;
//
// Chunklist signature.
//
typedef struct {
UINT8 Signature[APPLE_CHUNKLIST_SIG_LENGTH];
} APPLE_CHUNKLIST_SIG;
//
// Chunklist header.
//
typedef struct {
UINT32 Magic;
UINT32 Length;
UINT8 FileVersion;
UINT8 ChunkMethod;
UINT8 SigMethod;
UINT8 Unused;
UINT64 ChunkCount;
UINT64 ChunkOffset;
UINT64 SigOffset;
} APPLE_CHUNKLIST_HEADER;
#pragma pack()
#endif

View File

@ -0,0 +1,69 @@
/** @file
Copyright (C) 2019, Goldfish64. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef APPLE_CHUNKLIST_LIB_H_
#define APPLE_CHUNKLIST_LIB_H_
#include <IndustryStandard/AppleChunklist.h>
//
// Chunklist context.
//
typedef struct {
APPLE_CHUNKLIST_HEADER *Header;
UINTN FileSize;
APPLE_CHUNKLIST_CHUNK *Chunks;
APPLE_CHUNKLIST_SIG *Signature;
} OC_APPLE_CHUNKLIST_CONTEXT;
//
// Chunklist functions.
//
/**
Initializes a chunklist context.
@param[in] Buffer A pointer to a buffer containing the chunklist data.
@param[in] Length The length of the buffer specified in Buffer.
@param[out] Context The Context to initialize.
@retval EFI_SUCCESS The Context was intialized successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_UNSUPPORTED The chunklist is unsupported.
**/
EFI_STATUS
EFIAPI
OcAppleChunklistInitializeContext(
IN VOID *Buffer,
IN UINTN Length,
OUT OC_APPLE_CHUNKLIST_CONTEXT *Context);
/**
Verifies the specified data against a chunklist context.
@param[in] Context The Context to verify against.
@param[in] Buffer A pointer to a buffer containing the data to be verified.
@param[in] Length The length of the buffer specified in Buffer.
@retval EFI_SUCCESS The data was verified successfully.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_END_OF_FILE The end of Buffer was reached.
@retval EFI_COMPROMISED_DATA The data failed verification.
**/
EFI_STATUS
EFIAPI
OcAppleChunklistVerifyData(
IN OC_APPLE_CHUNKLIST_CONTEXT *Context,
IN VOID *Buffer,
IN UINTN Length);
#endif

View File

@ -0,0 +1,98 @@
/** @file
Copyright (C) 2019, Goldfish64. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcAppleChunklistLib.h>
#include <Library/OcCryptoLib.h>
#include <Library/UefiLib.h>
EFI_STATUS
EFIAPI
OcAppleChunklistInitializeContext(
IN VOID *Buffer,
IN UINTN Length,
OUT OC_APPLE_CHUNKLIST_CONTEXT *Context) {
// Create variables.
APPLE_CHUNKLIST_HEADER *ChunklistHeader = NULL;
// Check if parameters are valid.
if (!Buffer || !Length || !Context)
return EFI_INVALID_PARAMETER;
if (Length < sizeof(APPLE_CHUNKLIST_HEADER))
return EFI_INVALID_PARAMETER;
// Get header and ensure it is valid.
ChunklistHeader = (APPLE_CHUNKLIST_HEADER*)Buffer;
if ((ChunklistHeader->Magic != APPLE_CHUNKLIST_MAGIC) ||
(ChunklistHeader->Length != sizeof(APPLE_CHUNKLIST_HEADER)) ||
(ChunklistHeader->FileVersion != APPLE_CHUNKLIST_FILE_VERSION_10) ||
(ChunklistHeader->ChunkMethod != APPLE_CHUNKLIST_CHUNK_METHOD_10) ||
(ChunklistHeader->SigMethod != APPLE_CHUNKLIST_SIG_METHOD_10))
return EFI_UNSUPPORTED;
// Get chunklist data.
ZeroMem(Context, sizeof(OC_APPLE_CHUNKLIST_CONTEXT));
Context->Header = ChunklistHeader;
Context->FileSize = Length;
Context->Chunks = (APPLE_CHUNKLIST_CHUNK*)(((UINT8*)Buffer) + ReadUnaligned64(&(ChunklistHeader->ChunkOffset)));
Context->Signature = (APPLE_CHUNKLIST_SIG*)(((UINT8*)Buffer) + ReadUnaligned64(&(ChunklistHeader->SigOffset)));
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
OcAppleChunklistVerifyData(
IN OC_APPLE_CHUNKLIST_CONTEXT *Context,
IN VOID *Buffer,
IN UINTN Length) {
// Create variables.
UINT8 *BufferCurrent = NULL;
UINTN RemainingLength = 0;
APPLE_CHUNKLIST_CHUNK *Chunks;
UINT64 ChunkCount;
UINT8 ChunkHash[SHA256_DIGEST_SIZE];
// Check if parameters are valid.
if (!Context || !Buffer || !Length)
return EFI_INVALID_PARAMETER;
// Get chunklist info.
Chunks = Context->Chunks;
ChunkCount = ReadUnaligned64(&(Context->Header->ChunkCount));
// Hash each chunk and validate checksums are the same.
BufferCurrent = (UINT8*)Buffer;
RemainingLength = Length;
for (UINT64 i = 0; i < ChunkCount; i++) {
// Ensure length of chunk is valid.
if (Chunks[i].Length > RemainingLength)
return EFI_END_OF_FILE;
// Calculate checksum of data and ensure they match.
DEBUG((DEBUG_INFO, "AppleChunklistVerifyData(): Validating chunk %lu of %lu\n", i, ChunkCount));
Sha256(ChunkHash, BufferCurrent, Chunks[i].Length);
if (CompareMem(ChunkHash, Chunks[i].Checksum, SHA256_DIGEST_SIZE))
return EFI_COMPROMISED_DATA;
// Move to next chunk.
BufferCurrent += Chunks[i].Length;
RemainingLength -= Chunks[i].Length;
}
// Success.
return EFI_SUCCESS;
}

View File

@ -0,0 +1,33 @@
## @file
# Copyright (C) 2019, Goldfish64. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OcAppleChunklistLib
FILE_GUID = D891DF81-0C83-47FF-ABAD-546050E1A07F
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = OcAppleChunklistLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION DXE_SMM_DRIVER
[Packages]
MdePkg/MdePkg.dec
OcSupportPkg/OcSupportPkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
OcCryptoLib
UefiLib
[Sources]
OcAppleChunklistLib.c

View File

@ -57,6 +57,9 @@
## @libraryclass
OcAppleBootPolicyLib|Include/Library/OcAppleBootPolicyLib.h
## @libraryclass
OcAppleChunklistLib|Include/Library/OcAppleChunklistLib.h
## @libraryclass
OcAppleImageVerificationLib|Include/Library/OcAppleImageVerificationLib.h

View File

@ -49,6 +49,7 @@
[Components]
OcSupportPkg/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.inf
OcSupportPkg/Library/OcAppleChunklistLib/OcAppleChunklistLib.inf
OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf
OcSupportPkg/Library/OcCryptoLib/OcCryptoLib.inf
OcSupportPkg/Library/OcGuardLib/OcGuardLib.inf