3 * Provides an interface for managing nonces to govern the lifetime of a
4 * personalization performed with Tatsu. A nonce managed by this interface may
5 * be used in a Tatsu signing request as the value for the BNCH tag.
7 * These interfaces require the caller to possess the
9 * com.apple.private.security.AppleImage4.user-client
13 * @section Threat Model
14 * The adversary possesses the following:
16 * 1. a manifest which was previously valid but has since been invalidated
17 * by rolling the nonce associated with it
18 * 2. user-level code execution
19 * 3. knowledge of the raw nonce value for the previously-valid manifest
21 * The defense against this adversary is a system in which knowledge of the raw
22 * nonce is insufficient to impact the evaluation of a personalization. This
23 * system has the following characteristics:
25 * 1. A nonce seed is stored in an nvram variable which is only writable by
27 * 2. When making a new signing request, the nonce seed is encrypted by a
28 * UID1-derived key in-kernel and then hashed -- the output of this
29 * operation the nonce to be used in the signing request
30 * 3. On boot, AppleImage4 obtains the nonce seed from nvram and stores it
31 * in a data structure which will be covered by KTRR
32 * 4. When evaluating a manifest, AppleImage4 reads the raw nonce from the
33 * KTRR-covered data structure and validates it with the same
34 * transformation as was done in (2)
35 * 5. When the nonce is to be invalidated, AppleImage4 sets a flag in an
36 * nvram variable which is only writable by the kernel
37 * 6. On the subsequent boot, AppleImage4 notices the flag, generates a new
38 * nonce and repeats the procedure in (3)
40 * In this system, the raw nonce seed never leaves the kernel, and the nonce
41 * itself is a non-reversible representation of the seed.
45 #ifndef __IMG4_NONCE_H
46 #define __IMG4_NONCE_H
48 #ifndef __IMG4_INDIRECT
49 #error "Please #include <img4/img4.h> instead of this file directly"
50 #endif // __IMG4_INDIRECT
53 * @typedef img4_nonce_domain_t
54 * An opaque type describing a nonce domain.
56 IMG4_API_AVAILABLE_20181106
57 typedef struct _img4_nonce_domain img4_nonce_domain_t
;
60 * @const IMG4_NONCE_VERSION
61 * The version of the {@link img4_nonce_t} structure supported by the
64 #define IMG4_NONCE_VERSION ((img4_struct_version_t)0)
67 * @const IMG4_NONCE_MAX_LENGTH
68 * The maximum length of a nonce. Currently, this is the length of a SHA2-384
71 #define IMG4_NONCE_MAX_LENGTH (48)
74 * @typedef img4_nonce_t
75 * A structure describing a nonce.
78 * The version of the structure. When declaring this structure, you must
79 * initialize this field to {@link IMG4_NONCE_VERSION}.
82 * The bytes comprising the nonce.
85 * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}.
87 IMG4_API_AVAILABLE_20181106
88 typedef struct _img4_nonce
{
89 img4_struct_version_t i4n_version
;
90 const uint8_t i4n_nonce
[IMG4_NONCE_MAX_LENGTH
];
95 * @const IMG4_NONCE_INIT
96 * A convenience initializer for {@link img4_nonce_t} which ensures that the
97 * {@link i4n_version} field is properly initialized.
99 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
100 #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_VERSION}
101 #elif defined(__cplusplus) && __cplusplus >= 201103L
102 #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_VERSION})
103 #elif defined(__cplusplus)
104 #define IMG4_NONCE_INIT \
105 (img4_nonce_t((img4_nonce_t){IMG4_NONCE_VERSION}))
107 #define IMG4_NONCE_INIT {IMG4_NONCE_VERSION}
111 * @const IMG4_NONCE_DOMAIN_TRUST_CACHE
112 * The nonce domain governing trust cache personalizations. Use of this domain
115 * com.apple.private.img4.nonce.trust-cache
119 #if !MACH_KERNEL_PRIVATE
120 IMG4_API_AVAILABLE_20181106
122 const struct _img4_nonce_domain _img4_nonce_domain_trust_cache
;
123 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache)
125 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache)
129 * @function img4_nonce_domain_copy_nonce
130 * Copies the current value of the nonce in the given domain.
136 * Upon successful return, storage that will contain the current nonce. The
137 * provided structure's {@link i4n_version} must be initialized to
138 * {@link IMG4_NONCE_VERSION}.
141 * Upon success, zero is returned. The implementation may also return one of the
142 * following error codes directly:
144 * [ESTALE] The nonce for the given domain has been invalidated, and the
145 * host must reboot in order to generate a new one
146 * [EPERM] The caller lacked the entitlement necessary to read the
149 #if !MACH_KERNEL_PRIVATE
150 IMG4_API_AVAILABLE_20181106
151 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
153 img4_nonce_domain_copy_nonce(const img4_nonce_domain_t
*nd
, img4_nonce_t
*n
);
155 #define img4_nonce_domain_copy_nonce(...) \
156 (i4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__))
160 * @function img4_nonce_domain_roll_nonce
161 * Invalidates the current nonce for the given domain and forces a re-generation
162 * of the domain's nonce seed at the next boot.
168 * Upon success, zero is returned. The kernel implementation will never return
169 * a non-zero code. The userspace implementation may return one of the following
170 * error codes directly:
172 * [EPERM] The caller lacked the entitlement necessary to roll the
175 #if !MACH_KERNEL_PRIVATE
176 IMG4_API_AVAILABLE_20181106
177 OS_EXPORT OS_NONNULL1
179 img4_nonce_domain_roll_nonce(const img4_nonce_domain_t
*nd
);
181 #define img4_nonce_domain_roll_nonce(...) \
182 (i4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__))
185 #endif // __IMG4_NONCE_H