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 __BEGIN_DECLS 53 OS_ASSUME_NONNULL_BEGIN 54 OS_ASSUME_PTR_ABI_SINGLE_BEGIN 55 56 /*! 57 * @typedef img4_nonce_domain_t 58 * An opaque type describing a nonce domain. 59 */ 60 IMG4_API_AVAILABLE_20181106 61 typedef struct _img4_nonce_domain img4_nonce_domain_t; 62 63 /*! 64 * @const IMG4_NONCE_STRUCT_VERSION 65 * The version of the {@link img4_nonce_t} structure supported by the 66 * implementation. 67 */ 68 #define IMG4_NONCE_STRUCT_VERSION ((img4_struct_version_t)0) 69 #define IMG4_NONCE_VERSION IMG4_NONCE_STRUCT_VERSION 70 71 /*! 72 * @const IMG4_NONCE_MAX_LENGTH 73 * The maximum length of a nonce. Currently, this is the length of a SHA2-384 74 * hash. 75 */ 76 #define IMG4_NONCE_MAX_LENGTH (48u) 77 78 /*! 79 * @typedef img4_nonce_domain_index_t 80 * An enumeration describing nonce domains. 81 * 82 * @const IMG4_NONCE_DOMAIN_INDEX_TEST 83 * The enumerated constant corresponding to the internal test nonce domain. 84 * 85 * @const IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE 86 * The enumerated constant corresponding to 87 * {@link IMG4_NONCE_DOMAIN_TRUST_CACHE}. 88 * 89 * @const IMG4_NONCE_DOMAIN_INDEX_PDI 90 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_TRUST_PDI}. 91 * 92 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX 93 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_CRYPTEX}. 94 * 95 * @const IMG4_NONCE_DOMAIN_INDEX_DDI 96 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_DDI}. 97 * 98 * @const IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX 99 * The enumerated constant corresponding to 100 * {@link IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX}. 101 * 102 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB 103 * The enumerated constant corresponding to 104 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB}. 105 * 106 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT 107 * The enumerated constant corresponding to 108 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT}. 109 * 110 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET 111 * The enumerated constant corresponding to 112 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET}. 113 * 114 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_GENERIC 115 * The enumerated constant corresponding to 116 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC}. 117 * 118 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SIMULATOR 119 * The enumerated constant corresponding to 120 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR}. 121 * 122 * @const _IMG4_NONCE_DOMAIN_INDEX_CNT 123 * A sentinel value indicating the number of nonce domains. 124 */ 125 IMG4_API_AVAILABLE_20210521 126 OS_CLOSED_ENUM(img4_nonce_domain_index, uint64_t, 127 IMG4_NONCE_DOMAIN_INDEX_TEST = 0, 128 IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE, 129 IMG4_NONCE_DOMAIN_INDEX_PDI, 130 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX, 131 IMG4_NONCE_DOMAIN_INDEX_DDI, 132 IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX, 133 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB, 134 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT, 135 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET, 136 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_GENERIC, 137 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SIMULATOR, 138 _IMG4_NONCE_DOMAIN_INDEX_CNT, 139 ); 140 141 /*! 142 * @typedef img4_nonce_t 143 * A structure describing a nonce. 144 * 145 * @field i4n_version 146 * The version of the structure. When declaring this structure, you must 147 * initialize this field to {@link IMG4_NONCE_VERSION}. 148 * 149 * @field i4n_nonce 150 * The bytes comprising the nonce. 151 * 152 * @field i4n_length 153 * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}. 154 * 155 * @discussion 156 * The {@link i4n_nonce} field was previously const. This was a terrible idea, 157 * and the const storage qualifier was removed without adjusting the structure 158 * version. 159 */ 160 IMG4_API_AVAILABLE_20181106 161 typedef struct _img4_nonce { 162 img4_struct_version_t i4n_version; 163 uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH]; 164 uint32_t i4n_length; 165 } img4_nonce_t; 166 167 /*! 168 * @const IMG4_NONCE_INIT 169 * A convenience initializer for {@link img4_nonce_t} which ensures that the 170 * {@link i4n_version} field is properly initialized. 171 */ 172 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 173 #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION} 174 #elif defined(__cplusplus) && __cplusplus >= 201103L 175 #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION}) 176 #elif defined(__cplusplus) 177 #define IMG4_NONCE_INIT \ 178 (img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION})) 179 #else 180 #define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION} 181 #endif 182 183 /*! 184 * @const IMG4_NONCE_ZERO 185 * A convenience initializer for {@link img4_nonce_t} which initializes a 48- 186 * byte nonce of all zeroes. 187 */ 188 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 189 #define IMG4_NONCE_ZERO (img4_nonce_t){ \ 190 .i4n_version = IMG4_NONCE_STRUCT_VERSION, \ 191 .i4n_nonce = {0}, \ 192 .i4n_length = IMG4_NONCE_MAX_LENGTH, \ 193 } 194 #endif 195 196 /*! 197 * @const IMG4_NONCE_DOMAIN_TRUST_CACHE 198 * The nonce domain governing trust cache personalizations. Use of this domain 199 * requires the 200 * 201 * com.apple.private.img4.nonce.trust-cache 202 * 203 * entitlement. 204 */ 205 #if !XNU_KERNEL_PRIVATE 206 IMG4_API_AVAILABLE_20181106 207 OS_EXPORT 208 const struct _img4_nonce_domain _img4_nonce_domain_trust_cache; 209 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache) 210 #else 211 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache) 212 #endif 213 214 /*! 215 * @const IMG4_NONCE_DOMAIN_PDI 216 * The nonce domain governing disk image personalizations. Use of this domain 217 * requires the 218 * 219 * com.apple.private.img4.nonce.pdi 220 * 221 * entitlement. The nonce for this domain is regenerated once every boot. 222 */ 223 #if !XNU_KERNEL_PRIVATE 224 IMG4_API_AVAILABLE_20181106 225 OS_EXPORT 226 const struct _img4_nonce_domain _img4_nonce_domain_pdi; 227 #define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi) 228 #else 229 #define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi) 230 #endif 231 232 /*! 233 * @const IMG4_NONCE_DOMAIN_CRYPTEX 234 * The nonce domain governing cryptex personalizations. Use of this domain 235 * requires the 236 * 237 * com.apple.private.img4.nonce.cryptex 238 * 239 * entitlement. 240 */ 241 #if !XNU_KERNEL_PRIVATE 242 IMG4_API_AVAILABLE_20181106 243 OS_EXPORT 244 const struct _img4_nonce_domain _img4_nonce_domain_cryptex; 245 #define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex) 246 #else 247 #define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex) 248 #endif 249 250 /*! 251 * @const IMG4_NONCE_DOMAIN_DDI 252 * The nonce domain governing developer disk image personalizations. Use of this 253 * domain requires the 254 * 255 * com.apple.private.img4.nonce.ddi 256 * 257 * entitlement. 258 */ 259 #if !XNU_KERNEL_PRIVATE 260 IMG4_API_AVAILABLE_20181106 261 OS_EXPORT 262 const struct _img4_nonce_domain _img4_nonce_domain_ddi; 263 #define IMG4_NONCE_DOMAIN_DDI (&_img4_nonce_domain_ddi) 264 #else 265 #define IMG4_NONCE_DOMAIN_DDI (img4if->i4if_v12.nonce_domain_ddi) 266 #endif 267 268 /*! 269 * @const IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX 270 * The nonce domain governing ephemeral cryptex personalizations. Use of this 271 * domain requires the 272 * 273 * com.apple.private.img4.nonce.ephemeral-cryptex 274 * 275 * entitlement. 276 */ 277 #if !XNU_KERNEL_PRIVATE 278 IMG4_API_AVAILABLE_20210305 279 OS_EXPORT 280 const struct _img4_nonce_domain _img4_nonce_domain_ephemeral_cryptex; 281 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \ 282 (&_img4_nonce_domain_ephemeral_cryptex) 283 #else 284 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \ 285 (img4if->i4if_v12.nonce_domain_ephemeral_cryptex) 286 #endif 287 288 /*! 289 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB 290 * The nonce domain which acts as a null stub for the snuf value for Cryptex1 291 * processors. This domain corresponds to a value of 0 for the 292 * Cryptex1,NonceDomain tag. Use of this domain requires the 293 * 294 * com.apple.private.img4.nonce.cryptex1.snuf-stub 295 * 296 * entitlement. 297 */ 298 #if !XNU_KERNEL_PRIVATE 299 IMG4_API_AVAILABLE_20220322 300 OS_EXPORT 301 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_snuf_stub; 302 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \ 303 (&_img4_nonce_domain_cryptex1_snuf_stub) 304 #else 305 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \ 306 (img4if->i4if_v18.nonce_domain_cryptex1_snuf_stub) 307 #endif 308 309 /*! 310 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT 311 * The nonce domain governing personalizations for the virtual Cryptex1 312 * coprocessor's boot objects. This domain corresponds to a value of 1 for the 313 * Cryptex1,NonceDomain tag. Use of this domain requires the 314 * 315 * com.apple.private.img4.nonce.cryptex1.boot 316 * 317 * entitlement. 318 */ 319 #if !XNU_KERNEL_PRIVATE 320 IMG4_API_AVAILABLE_20211112 321 OS_EXPORT 322 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_boot; 323 #define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \ 324 (&_img4_nonce_domain_cryptex1_boot) 325 #else 326 #define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \ 327 (img4if->i4if_v16.nonce_domain_cryptex1_boot) 328 #endif 329 330 /*! 331 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET 332 * The nonce domain governing personalizations for the virtual Cryptex1 333 * coprocessor's asset brain objects. This domain corresponds to a value of 2 334 * for the Cryptex1,NonceDomain tag. Use of this domain requires the 335 * 336 * com.apple.private.img4.nonce.cryptex1.asset 337 * 338 * entitlement. 339 */ 340 #if !XNU_KERNEL_PRIVATE 341 IMG4_API_AVAILABLE_20211112 342 OS_EXPORT 343 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_asset; 344 #define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \ 345 (&_img4_nonce_domain_cryptex1_asset) 346 #else 347 #define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \ 348 (img4if->i4if_v16.nonce_domain_cryptex1_asset) 349 #endif 350 351 /*! 352 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC 353 * The nonce domain governing personalizations for the virtual Cryptex1 354 * coprocessor's generic supplemental objects. This domain corresponds to a 355 * value of 3 for the Cryptex1,NonceDomain tag. Use of this domain requires the 356 * 357 * com.apple.private.img4.nonce.cryptex1.supplemental 358 * 359 * entitlement. 360 */ 361 #if !XNU_KERNEL_PRIVATE 362 IMG4_API_AVAILABLE_20221202 363 OS_EXPORT 364 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_generic; 365 #define IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC \ 366 (&_img4_nonce_domain_cryptex1_generic) 367 #else 368 #define IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC \ 369 (img4if->i4if_v20.nonce_domain_cryptex1_generic) 370 #endif 371 372 /*! 373 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR 374 * The nonce domain governing personalizations for the virtual Cryptex1 375 * coprocessor's Simulator runtime objects. This domain corresponds to a value 376 * of 4 for the Cryptex1,NonceDomain tag. Use of this domain requires the 377 * 378 * com.apple.private.img4.nonce.cryptex1.simulator 379 * 380 * entitlement. 381 */ 382 #if !XNU_KERNEL_PRIVATE 383 IMG4_API_AVAILABLE_20221202 384 OS_EXPORT 385 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_simulator; 386 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR \ 387 (&_img4_nonce_domain_cryptex1_simulator) 388 #else 389 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR \ 390 (img4if->i4if_v20.nonce_domain_cryptex1_simulator) 391 #endif 392 393 /*! 394 * @function img4_nonce_domain_copy_nonce 395 * Copies the current value of the nonce in the given domain. 396 * 397 * @param nd 398 * The nonce domain. 399 * 400 * @param n 401 * Upon successful return, storage that will contain the current nonce. The 402 * provided structure's {@link i4n_version} must be initialized to 403 * {@link IMG4_NONCE_VERSION}. 404 * 405 * @result 406 * Upon success, zero is returned. The implementation may also return one of the 407 * following error codes directly: 408 * 409 * [ESTALE] The nonce for the given domain has been invalidated, and the 410 * host must reboot in order to generate a new one 411 * [EPERM] The caller lacked the entitlement necessary to read the 412 * given nonce 413 * [ENOTSUP] Nonce management is not available on the host 414 * [EACCES] The nonce requested is not accessible in this environment 415 */ 416 #if !XNU_KERNEL_PRIVATE 417 IMG4_API_AVAILABLE_20210305 418 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 419 errno_t 420 img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n); 421 #else 422 #define img4_nonce_domain_copy_nonce(...) \ 423 (img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__)) 424 #endif 425 426 /*! 427 * @function img4_nonce_domain_roll_nonce 428 * Invalidates the current nonce for the given domain and forces a re-generation 429 * of the domain's nonce seed at the next boot. 430 * 431 * @param nd 432 * The nonce domain. 433 * 434 * @result 435 * Upon success, zero is returned. The kernel implementation will never return 436 * a non-zero code. The userspace implementation may return one of the following 437 * error codes directly: 438 * 439 * [EPERM] The caller lacked the entitlement necessary to roll the 440 * given nonce 441 * [EROFS] The boot mode didn't allow committing to non-volatile storage 442 * [ENOTSUP] Nonce management is not available on the host 443 * [EACCES] The nonce requested is not accessible in this environment 444 */ 445 #if !XNU_KERNEL_PRIVATE 446 IMG4_API_AVAILABLE_20181106 447 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 448 errno_t 449 img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd); 450 #else 451 #define img4_nonce_domain_roll_nonce(...) \ 452 (img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__)) 453 #endif 454 455 /*! 456 * @function img4_nonce_domain_preroll_nonce 457 * Generates a new nonce seed and returns the resulting hash. The new nonce seed 458 * will be in force at the next reboot if and only if the boot manifest hash 459 * changes. Otherwise, the current nonce seed value will remain stable (modulo 460 * the regeneration policy associated with its domain). 461 * 462 * @param nd 463 * The nonce domain. 464 * 465 * @param n 466 * Upon successful return, storage that will contain the current nonce. The 467 * provided structure's {@link i4n_version} must be initialized to 468 * {@link IMG4_NONCE_VERSION}. 469 * 470 * @result 471 * Upon success, zero is returned. The kernel implementation will never return 472 * a non-zero code. The userspace implementation may return one of the following 473 * error codes directly: 474 * 475 * [EPERM] The caller lacked the entitlement necessary to roll the 476 * given nonce 477 * [EROFS] The boot mode didn't allow committing to non-volatile storage 478 * [ENOTSUP] Nonce management is not available on the host 479 * [EACCES] The nonce requested is not accessible in this environment 480 */ 481 #if !XNU_KERNEL_PRIVATE 482 IMG4_API_AVAILABLE_FALL_2021_B 483 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 484 errno_t 485 img4_nonce_domain_preroll_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n); 486 #else 487 #define img4_nonce_domain_preroll_nonce(...) \ 488 (img4if->i4if_v14.nonce_domain_preroll_nonce(__VA_ARGS__)) 489 #endif 490 491 /*! 492 * @function img4_nonce_domain_peek_nonce 493 * Copies the current proposed value of a nonce domain. 494 * 495 * @param nd 496 * The nonce domain. 497 * 498 * @param n 499 * Upon successful return, storage that will contain the current proposed 500 * nonce. The provided structure's {@link i4n_version} must be initialized to 501 * {@link IMG4_NONCE_VERSION}. 502 * 503 * @result 504 * Upon success, zero is returned. The implementation may also return one of the 505 * following error codes directly: 506 * 507 * [EPERM] The caller lacked the entitlement necessary to roll the 508 * given nonce 509 * [ENOENT] The nonce doesn't have a proposed value 510 * [ENOTSUP] Nonce management is not available on the host 511 * [EACCES] The nonce requested is not accessible in this environment 512 */ 513 #if !XNU_KERNEL_PRIVATE 514 IMG4_API_AVAILABLE_20220714 515 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 516 errno_t 517 img4_nonce_domain_peek_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n); 518 #else 519 #define img4_nonce_domain_peek_nonce(...) \ 520 (img4if->i4if_v19.nonce_domain_peek_nonce(__VA_ARGS__)) 521 #endif 522 523 /*! 524 * @function img4_nonce_domain_get_from_handle 525 * Obtains the nonce domain for the given integer handle. 526 * 527 * @param handle 528 * The nonce domain handle. 529 * 530 * @result 531 * The nonce domain associated with the provided handle. If no domain is 532 * associated with the handle, NULL is returned. 533 */ 534 #if !XNU_KERNEL_PRIVATE 535 IMG4_API_AVAILABLE_20221202 536 OS_EXPORT OS_WARN_RESULT 537 const img4_nonce_domain_t *_Nullable 538 img4_nonce_domain_get_from_handle(uint32_t handle); 539 #else 540 #define img4_nonce_domain_get_from_handle(...) \ 541 (img4if->i4if_v20.nonce_domain_get_from_handle(__VA_ARGS__)) 542 #endif 543 544 OS_ASSUME_PTR_ABI_SINGLE_END 545 OS_ASSUME_NONNULL_END 546 __END_DECLS 547 548 #endif // __IMG4_NONCE_H 549