iBoot/lib/image/image3/Image3.h

384 lines
8.8 KiB
C

/*
* Copyright (C) 2007-2011 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef _IMAGE3_H_
#define _IMAGE3_H_
#include <stdint.h>
#include <sys/types.h>
#ifndef false
# include <stdbool.h>
#endif
/*
* All Image3 operations use an Image3ObjectHandle to refer to the image being worked on.
*/
struct _Image3InternalState;
typedef struct _Image3InternalState *Image3ObjectHandle;
/*
* Discards an Image3 image.
*/
extern void
image3Discard(
Image3ObjectHandle *withHandle);
#ifdef IMAGE3_CREATOR
/*
* Create a new Image3 working object.
*
* Returns:
* 0 Success
* ENOMEM Unable to allocate memory
*/
extern int
image3InstantiateNew(
Image3ObjectHandle *newHandle,
size_t initialAllocation,
u_int32_t imageType);
/*
* Finalises an image.
*
* If signImage is set, hashes and signs the image. Reservation length, if non-zero, indicates that the final signed image
* will include tags not currently present in the image. A partial digest is computed, but the size of the reservation is
* required so that ihSignedLength can be set properly for inclusion in the partial hash state. The partial digest is
* constrained to conclude on a 64 byte boundary by adding the appropriate padding following the last tag in the signed portion
* of a finalised image.
*
* Returns:
* 0 Success
*/
extern int
image3Finalize(
const Image3ObjectHandle withHandle,
void **objectBuffer,
size_t *objectSize,
bool signImage,
size_t reservationSize);
/*
* Set a numeric tag.
*
* Returns:
* 0 Success
* ENOMEM Unable to allocate memory
*/
extern int
image3SetTagSignedNumber(
const Image3ObjectHandle withHandle,
u_int32_t withTag,
int64_t withValue);
extern int
image3SetTagUnsignedNumber(
const Image3ObjectHandle withHandle,
u_int32_t withTag,
u_int64_t withValue);
/*
* Set a string tag.
*
* Returns:
* 0 Success
* ENOMEM Unable to allocate memory
*/
extern int
image3SetTagString(
const Image3ObjectHandle withHandle,
u_int32_t withTag,
char *withValue);
/*
* Set a structure tag.
*
* Note that the withAlignment field aligns the structure, not the tag.
*
* Returns:
* 0 Success
* ENOMEM Unable to allocate memory
*/
extern int
image3SetTagStructure(
const Image3ObjectHandle withHandle,
u_int32_t withTag,
const void *withValue,
size_t withSize,
int withAlignment);
/*
* Advances the cursor with zero padding.
*
* Returns:
* 0 Success
* ENOMEM Unable to allocate memory
* EROFS Image is read-only
*/
extern int
image3AdvanceCursorWithZeroPad(
const Image3ObjectHandle withHandle,
int withSize);
#endif /* IMAGE3_CREATOR */
/*
* Take a data buffer that might contain an Image3 object and get a handle to it.
*
* Note that no security-relatd validation is performed by this operation.
*
* If IMAGE3_CREATOR is defined and the image is mutable, or if copyBuffer is
* true, then the image buffer is copied. Otherwise the image directly references
* the supplied buffer.
*
* Returns:
* 0 Success.
* EINVAL The contents of the buffer are malformed
*/
extern int
image3InstantiateFromBuffer(
Image3ObjectHandle *newHandle,
const void *fromBuffer,
const size_t bufferSize,
bool copyBuffer);
/*
* Validate the signature on an Image3 object.
*
* Note that images from untrusted sources should be handled with *extreme caution*
* until this operation has reported success.
*
* If the object was loaded from local storage where it was expected that it was
* personalised for the device (normally the case) then the kImage3ValidateLocalStorage
* option should be supplied.
*
* If the object's validity can only be asserted via the ticket API,
* kImage3ValidateRequireTicket should be supplied.
*
* The result of the validation operation is cached, so it is safe to call this function
* multiple times. Once the initial validation operation is performed, the validation
* options are ignored, so knowledge of the source of the object is not required in this
* case.
*
* Returns:
* 0 Success.
* EINVAL The contents of the buffer are malformed or otherwise cannot be validated.
* EPERM Validation failed, the image cannot be trusted.
*/
#define kImage3ValidateLocalStorage (1<<0)
#define kImage3ValidateRequireTicket (1<<2)
extern int
image3ValidateSignature(
const Image3ObjectHandle withHandle,
const u_int32_t expectedType,
const u_int32_t validationOptions,
bool *validatedWithEmbeddedSignature);
/*
* Test for the presence of a tag in an image.
*
* Returns:
* 0 Success
* EINVAL The buffer is malformed.
* ENOENT The tag was not found.
*/
extern int
image3TagIsPresent(
const Image3ObjectHandle withHandle,
const u_int32_t withTag);
/*
* Fetch a numeric tag's value.
*
* Returns:
* 0 Success
* EINVAL The buffer is malformed.
* ENOENT The tag was not found.
*/
extern int
image3GetTagSignedNumber(
const Image3ObjectHandle withHandle,
const u_int32_t withTag,
int64_t *toNumber,
int skipCount);
extern int
image3GetTagUnsignedNumber(
const Image3ObjectHandle withHandle,
const u_int32_t withTag,
u_int64_t *toNumber,
int skipCount);
/*
* Fetch a string tag's value.
*
* Returns:
* 0 Success. *toBuffer contains an ASCIIZ string that must be freed by the caller.
* EINVAL The buffer is malformed.
* ENOENT The tag was not found.
*/
extern int
image3GetTagString(
const Image3ObjectHandle withHandle,
const u_int32_t withTag,
char **toBuffer,
int skipCount);
/*
* Fetch a direct pointer to a structure tag. Note that this points into the image itself
* and should be used with some caution.
*
* The skipCount argument may be used to specify a number of matching tags to be ignored.
*
* Returns:
* 0 Success.
* EINVAL The buffer is malformed.
* ENOENT The tag was not found.
*/
extern int
image3GetTagStruct(
const Image3ObjectHandle withHandle,
const u_int32_t withTag,
void **structPtr,
size_t *structSize,
int skipCount);
/*
* Compute the digest to be signed into the root ticket. If the image has been previously
* personalized with the old method (with a signature covering an added ECID tag), the digest
* excludes the personalized region.
*
* Although the underlying image3 buffer is returned unmodified, this function may
* temporarily modify the buffer when computing the hash. The buffer must therefore be in a
* writable region of memory.
*/
extern int
image3GetPrePersonalizedDigest(
const Image3ObjectHandle withHandle,
uint8_t *hashBuffer,
size_t hashBufferLength);
/*
* Return the nested image's handle (if one exists).
*
* Note that the nested image is only discoverable if an image is authenticated.
*/
Image3ObjectHandle
image3GetNestedImage(const Image3ObjectHandle withHandle);
#ifdef IMAGE3_DEBUG
extern void
_image3PrintImage(Image3ObjectHandle withHandle);
#ifdef IMAGE3_UTILITY
int
_image3WriteData(Image3ObjectHandle withHandle, const char *path);
#endif /* IMAGE3_UTILITY */
#endif /* IMAGE3_DEBUG */
/*
* Prototypes for external functions that must be supplied.
*/
/*
* Generate a SHA-1 hash of the supplied buffer.
*/
extern void
image3SHA1Generate(void *dataBuffer, size_t dataSize, void *hashBuffer);
#ifdef IMAGE3_CREATOR
/*
* Generate a partial SHA-1 hash of the supplied buffer.
*/
void
image3SHA1Partial(void *dataBuffer, size_t dataSize, void *hashBuffer);
#endif /* IMAGE3_CREATOR */
/*
* Sign a hash.
*/
extern int
image3PKISignHash(
void *hashBuffer,
size_t hashSize,
void **resultPointer,
size_t *resultSize,
void **certBlobPointer,
size_t *certBlobSize);
/*
* Verify the signature on a hash.
*
* Returns:
* 0 - image is valid and can be trusted
* EPERM - image is valid but cannot be trusted
* EINVAL - image is not valid, cannot be trusted
*/
extern int
image3PKIVerifyHash(
void *hashBuffer,
size_t hashSize,
void *signedHashBuffer,
size_t signedHashSize,
void *certBlobBuffer,
size_t certBlobSize,
void **certCustomData,
size_t *certCustomDataSize);
/*
* Validate an image hash using the ticket database.
*
* Returns:
* 0 - image is valid and can be trusted
* EPERM - image is valid but cannot be trusted
* EINVAL - image is not valid, cannot be trusted
*/
extern int
image3TicketVerifyHash(
void *hashBuffer,
size_t hashSize,
uint32_t imageType,
uint32_t expectedType);
/*
* Decrypt a buffer in-place using AES and a local unit-specific key.
*/
extern int
image3AESDecryptUsingLocalKey(void *buffer, size_t length);
/*
* Encrypt a buffer in-place using AES and a local unit-specific key.
*/
extern void
image3AESEncryptUsingLocalKey(void *buffer, size_t length);
/*
* Memory allocator
*/
extern void *
image3Malloc(size_t size);
/*
* Memory de-allocator
*/
extern void
image3Free(void *ptr, size_t size);
#endif /* _IMAGE3_H_ */