1 /*! 2 * @header 3 * Provides an interface for managing nonces to govern the lifetime of a 4 * personalization performed with TSS. A nonce managed by this interface may 5 * be used in a TSS signing request as the value for the BNCH tag. 6 * 7 * These interfaces require the caller to possess the 8 * 9 * com.apple.private.security.AppleImage4.user-client 10 * 11 * entitlement. 12 * 13 * @section Threat Model 14 * The adversary possesses the following: 15 * 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 20 * 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: 24 * 25 * 1. A nonce seed is stored in an nvram variable which is only writable by 26 * the kernel 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) 39 * 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. 42 */ 43 44 45 #ifndef __IMG4_NONCE_H 46 #define __IMG4_NONCE_H 47 48 #ifndef __IMG4_INDIRECT 49 #error "Please #include <img4/firmware.h> instead of this file directly" 50 #endif // __IMG4_INDIRECT 51 52 /*! 53 * @typedef img4_nonce_domain_t 54 * An opaque type describing a nonce domain. 55 */ 56 IMG4_API_AVAILABLE_20181106 57 typedef struct _img4_nonce_domain img4_nonce_domain_t; 58 59 /*! 60 * @const IMG4_NONCE_STRUCT_VERSION 61 * The version of the {@link img4_nonce_t} structure supported by the 62 * implementation. 63 */ 64 #define IMG4_NONCE_STRUCT_VERSION ((img4_struct_version_t)0) 65 #define IMG4_NONCE_VERSION IMG4_NONCE_STRUCT_VERSION 66 67 /*! 68 * @const IMG4_NONCE_MAX_LENGTH 69 * The maximum length of a nonce. Currently, this is the length of a SHA2-384 70 * hash. 71 */ 72 #define IMG4_NONCE_MAX_LENGTH (48u) 73 74 /*! 75 * @typedef img4_nonce_domain_index_t 76 * An enumeration describing nonce domains. 77 * 78 * @const IMG4_NONCE_DOMAIN_INDEX_TEST 79 * The enumerated constant corresponding to the internal test nonce domain. 80 * 81 * @const IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE 82 * The enumerated constant corresponding to 83 * {@link IMG4_NONCE_DOMAIN_TRUST_CACHE}. 84 * 85 * @const IMG4_NONCE_DOMAIN_INDEX_PDI 86 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_TRUST_PDI}. 87 * 88 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX 89 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_CRYPTEX}. 90 * 91 * @const IMG4_NONCE_DOMAIN_INDEX_DDI 92 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_DDI}. 93 * 94 * @const IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX 95 * The enumerated constant corresponding to 96 * {@link IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX}. 97 * 98 * @const _IMG4_NONCE_DOMAIN_INDEX_CNT 99 * A sentinel value indicating the number of nonce domains. 100 */ 101 IMG4_API_AVAILABLE_20210521 102 OS_CLOSED_ENUM(img4_nonce_domain_index, uint64_t, 103 IMG4_NONCE_DOMAIN_INDEX_TEST = 0, 104 IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE, 105 IMG4_NONCE_DOMAIN_INDEX_PDI, 106 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX, 107 IMG4_NONCE_DOMAIN_INDEX_DDI, 108 IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX, 109 _IMG4_NONCE_DOMAIN_INDEX_CNT, 110 ); 111 112 /*! 113 * @typedef img4_nonce_t 114 * A structure describing a nonce. 115 * 116 * @field i4n_version 117 * The version of the structure. When declaring this structure, you must 118 * initialize this field to {@link IMG4_NONCE_VERSION}. 119 * 120 * @field i4n_nonce 121 * The bytes comprising the nonce. 122 * 123 * @field i4n_length 124 * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}. 125 */ 126 IMG4_API_AVAILABLE_20181106 127 typedef struct _img4_nonce { 128 img4_struct_version_t i4n_version; 129 const uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH]; 130 uint32_t i4n_length; 131 } img4_nonce_t; 132 133 /*! 134 * @const IMG4_NONCE_INIT 135 * A convenience initializer for {@link img4_nonce_t} which ensures that the 136 * {@link i4n_version} field is properly initialized. 137 */ 138 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 139 #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION} 140 #elif defined(__cplusplus) && __cplusplus >= 201103L 141 #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION}) 142 #elif defined(__cplusplus) 143 #define IMG4_NONCE_INIT \ 144 (img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION})) 145 #else 146 #define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION} 147 #endif 148 149 /*! 150 * @const IMG4_NONCE_ZERO 151 * A convenience initializer for {@link img4_nonce_t} which initializes a 48- 152 * byte nonce of all zeroes. 153 */ 154 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 155 #define IMG4_NONCE_ZERO (img4_nonce_t){ \ 156 .i4n_version = IMG4_NONCE_STRUCT_VERSION, \ 157 .i4n_nonce = {0}, \ 158 .i4n_length = IMG4_NONCE_MAX_LENGTH, \ 159 } 160 #endif 161 162 /*! 163 * @const IMG4_NONCE_DOMAIN_TRUST_CACHE 164 * The nonce domain governing trust cache personalizations. Use of this domain 165 * requires the 166 * 167 * com.apple.private.img4.nonce.trust-cache 168 * 169 * entitlement. 170 */ 171 #if !XNU_KERNEL_PRIVATE 172 IMG4_API_AVAILABLE_20181106 173 OS_EXPORT 174 const struct _img4_nonce_domain _img4_nonce_domain_trust_cache; 175 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache) 176 #else 177 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache) 178 #endif 179 180 /*! 181 * @const IMG4_NONCE_DOMAIN_PDI 182 * The nonce domain governing disk image personalizations. Use of this domain 183 * requires the 184 * 185 * com.apple.private.img4.nonce.pdi 186 * 187 * entitlement. The nonce for this domain is regenerated once every boot. 188 */ 189 #if !XNU_KERNEL_PRIVATE 190 IMG4_API_AVAILABLE_20181106 191 OS_EXPORT 192 const struct _img4_nonce_domain _img4_nonce_domain_pdi; 193 #define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi) 194 #else 195 #define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi) 196 #endif 197 198 /*! 199 * @const IMG4_NONCE_DOMAIN_CRYPTEX 200 * The nonce domain governing cryptex personalizations. Use of this domain 201 * requires the 202 * 203 * com.apple.private.img4.nonce.cryptex 204 * 205 * entitlement. 206 */ 207 #if !XNU_KERNEL_PRIVATE 208 IMG4_API_AVAILABLE_20181106 209 OS_EXPORT 210 const struct _img4_nonce_domain _img4_nonce_domain_cryptex; 211 #define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex) 212 #else 213 #define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex) 214 #endif 215 216 /*! 217 * @const IMG4_NONCE_DOMAIN_DDI 218 * The nonce domain governing developer disk image personalizations. Use of this 219 * domain requires the 220 * 221 * com.apple.private.img4.nonce.ddi 222 * 223 * entitlement. 224 */ 225 #if !XNU_KERNEL_PRIVATE 226 IMG4_API_AVAILABLE_20181106 227 OS_EXPORT 228 const struct _img4_nonce_domain _img4_nonce_domain_ddi; 229 #define IMG4_NONCE_DOMAIN_DDI (&_img4_nonce_domain_ddi) 230 #else 231 #define IMG4_NONCE_DOMAIN_DDI (img4if->i4if_v12.nonce_domain_ddi) 232 #endif 233 234 /*! 235 * @const IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX 236 * The nonce domain governing ephemeral cryptex personalizations. Use of this 237 * domain requires the 238 * 239 * com.apple.private.img4.nonce.ephemeral-cryptex 240 * 241 * entitlement. 242 */ 243 #if !XNU_KERNEL_PRIVATE 244 IMG4_API_AVAILABLE_20210305 245 OS_EXPORT 246 const struct _img4_nonce_domain _img4_nonce_domain_ephemeral_cryptex; 247 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \ 248 (&_img4_nonce_domain_ephemeral_cryptex) 249 #else 250 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \ 251 (img4if->i4if_v12.nonce_domain_ephemeral_cryptex) 252 #endif 253 254 /*! 255 * @function img4_nonce_domain_copy_nonce 256 * Copies the current value of the nonce in the given domain. 257 * 258 * @param nd 259 * The nonce domain. 260 * 261 * @param n 262 * Upon successful return, storage that will contain the current nonce. The 263 * provided structure's {@link i4n_version} must be initialized to 264 * {@link IMG4_NONCE_VERSION}. 265 * 266 * @result 267 * Upon success, zero is returned. The implementation may also return one of the 268 * following error codes directly: 269 * 270 * [ESTALE] The nonce for the given domain has been invalidated, and the 271 * host must reboot in order to generate a new one 272 * [EPERM] The caller lacked the entitlement necessary to read the 273 * given nonce 274 */ 275 #if !XNU_KERNEL_PRIVATE 276 IMG4_API_AVAILABLE_20210305 277 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 278 errno_t 279 img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n); 280 #else 281 #define img4_nonce_domain_copy_nonce(...) \ 282 (img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__)) 283 #endif 284 285 /*! 286 * @function img4_nonce_domain_roll_nonce 287 * Invalidates the current nonce for the given domain and forces a re-generation 288 * of the domain's nonce seed at the next boot. 289 * 290 * @param nd 291 * The nonce domain. 292 * 293 * @result 294 * Upon success, zero is returned. The kernel implementation will never return 295 * a non-zero code. The userspace implementation may return one of the following 296 * error codes directly: 297 * 298 * [EPERM] The caller lacked the entitlement necessary to roll the 299 * given nonce 300 */ 301 #if !XNU_KERNEL_PRIVATE 302 IMG4_API_AVAILABLE_20181106 303 OS_EXPORT OS_NONNULL1 304 errno_t 305 img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd); 306 #else 307 #define img4_nonce_domain_roll_nonce(...) \ 308 (img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__)) 309 #endif 310 311 #endif // __IMG4_NONCE_H 312