payload.h   [plain text]


/*!
 * @header
 * Image4 payload interfaces. These interfaces provide a lightweight type for
 * working with an Image4 payload that is described by a separate manifest (e.g.
 * a .im4p file whose contents are described by an object in a manifest from a
 * .im4m file).
 *
 * No direct access is provided to the raw payload bytes encapsulated by the
 * Image4 payload by design. The intent is that in order to access the raw
 * bytes, the payload object must be validated against a manifest object using
 * the {@link img4_get_trusted_external_payload} interface.
 */
#ifndef __IMG4_PAYLOAD_H
#define __IMG4_PAYLOAD_H

#ifndef __IMG4_INDIRECT
#error "Please #include <img4/img4.h> instead of this file directly"
#endif // __IMG4_INDIRECT

#if IMG4_TAPI
#include "tapi.h"
#endif

/*!
 * @typedef img4_payload_flags_t
 * Flags modifying the behavior of an Image4 payload object.
 *
 * @const I4PLF_INIT
 * No flags set. This value is suitable for initialization purposes.
 *
 * @const I4PLF_UNWRAPPED
 * Indicates that the payload bytes are not wrapped in an Image4 payload object
 * (.im4p file). If this flag is given, the payload tag is ignored.
 *
 * This should be used in scenarios such as x86 SecureBoot, which use Image4 to
 * describe portable executable files which must be fed directly to the firmware
 * and cannot tolerate being wrapped in an intermediary format.
 */
OS_CLOSED_OPTIONS(img4_payload_flags, uint64_t,
	I4PLF_INIT = 0,
	I4PLF_UNWRAPPED = (1 << 0),
);

/*!
 * @function img4_payload_init
 * Initializes an Image4 payload object.
 *
 * @param i4p
 * A pointer to the payload object to initialize.
 *
 * @param tag
 * The expected tag for the payload.
 *
 * @param flags
 * Flags modifying the behavior of the payload object.
 *
 * @param bytes
 * The buffer containing the Image4 payload.
 *
 * @param len
 * The length of the buffer.
 *
 * @param destructor
 * A pointer to a routine to dispose of the buffer. May be NULL if the buffer
 * does not require explicit disposal (e.g. the buffer is stack memory).
 *
 * @result
 * Upon success, zero is returned. Otherwise, one of the following error codes:
 *
 *     [EILSEQ]     The data is not valid Image4 data
 *     [EFTYPE]     The data does not contain an Image4 payload
 *     [ENOENT]     The bytes do not contain a payload for the specified tag
 */
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20180112
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL4
errno_t
img4_payload_init(img4_payload_t *i4p, img4_tag_t tag,
		img4_payload_flags_t flags, const uint8_t *bytes, size_t len,
		img4_destructor_t destructor);
#else
#define img4_payload_init(...) img4if->i4if_payload_init(__VA_ARGS__)
#endif

/*!
 * @function img4_payload_init_with_vnode_4xnu
 * Initializes an Image4 payload object from a vnode.
 *
 * @param i4p
 * A pointer to the payload object to initialize.
 *
 * @param tag
 * The expected tag for the payload.
 *
 * @param vn
 * The vnode from which to initialize the payload.
 *
 * @param flags
 * Flags modifying the behavior of the payload object.
 *
 * @result
 * Upon success, zero is returned. Otherwise, one of the following error codes:
 *
 *     [ENOENT]     The vnode is either dead or in the process of being
 *                  recycled
 *     [EIO]        Reading from the vnode stalled repeatedly beyond the
 *                  implementation's tolerance
 *
 * Additionally, the implementation may return any error that vnode_ref() may
 * return.
 *
 * @discussion
 * Verification of a vnode is performed by reading in chunks of data, updating
 * an ongoing hash operation with that data, and then discarding it. Therefore,
 * payload objects created in this manner can only guarantee their validity at
 * the time the check was performed since the vnode's contents are not kept in
 * memory and may be tampered with after validation has been performed.
 *
 * Additionally, this operation requires the payload to be unwrapped, as it does
 * not parse or recognize any Image4 payload wrapper. Payloads created with this
 * interface are therefore implicitly created with the {@link I4PLF_UNWRAPPED}
 * flag.
 */

#if KERNEL
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20180112
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
errno_t
img4_payload_init_with_vnode_4xnu(img4_payload_t *i4p, img4_tag_t tag,
		vnode_t vn, img4_payload_flags_t flags);
#else
#define img4_payload_init_with_vnode_4xnu(...) \
		(img4if->i4if_v2.payload_init_with_vnode_4xnu(__VA_ARGS__))
#endif // !XNU_KERNEL_PRIVATE
#endif // KERNEL

/*!
 * @function img4_payload_init_with_fd_4MSM
 * Initializes an Image4 payload object from a file descriptor.
 *
 * @param i4p
 * A pointer to the payload object to initialize.
 *
 * @param tag
 * The expected tag for the payload.
 *
 * @param fd
 * The file descriptor from which to initialize the payload.
 *
 * @param flags
 * Flags modifying the behavior of the payload object.
 *
 * @result
 * Upon success, zero is returned. Otherwise, the implementation may return any
 * errno that is set by the dup(2) system call.
 *
 * @discussion
 * This interface is a userspace equivalent to
 * {@link img4_payload_init_with_vnode_4xnu}, and all the same caveats apply.
 */

#if !KERNEL
IMG4_API_AVAILABLE_20180112
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
errno_t
img4_payload_init_with_fd_4MSM(img4_payload_t *i4p, img4_tag_t tag,
		int fd, img4_payload_flags_t flags);
#endif // KERNEL

/*!
 * @function img4_payload_destroy
 * Disposes of the resources associated with the payload object.
 *
 * @param i4p
 * The payload object of which to dispose.
 *
 * @discussion
 * This routine does not deallocate the storage for the payload object itself,
 * only the associated resources. This routine will cause the destructor given
 * in {@link img4_payload_init} to be called, if any.
 */
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20180112
OS_EXPORT OS_NONNULL1
void
img4_payload_destroy(img4_payload_t *i4p);
#else
#define img4_payload_destroy(...) img4if->i4if_payload_destroy(__VA_ARGS__)
#endif

#endif // __IMG4_PAYLOAD_H