xref: /xnu-10002.81.5/osfmk/vm/pmap_cs.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*
2  * Copyright (c) 2021 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * The contents of this file constitute Original Code as defined in and
7  * are subject to the Apple Public Source License Version 1.1 (the
8  * "License").  You may not use this file except in compliance with the
9  * License.  Please obtain a copy of the License at
10  * http://www.apple.com/publicsource and read it before using this file.
11  *
12  * This Original Code and all software distributed under the License are
13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17  * License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * @APPLE_LICENSE_HEADER_END@
21  */
22 
23 #ifndef _VM_PMAP_CS_H_
24 #define _VM_PMAP_CS_H_
25 
26 #ifdef KERNEL_PRIVATE
27 /*
28  * All of PMAP_CS definitions are private and should remain accessible only within XNU
29  * and Apple internal kernel extensions.
30  */
31 
32 #include <mach/kern_return.h>
33 #include <mach/vm_param.h>
34 #include <mach/vm_types.h>
35 #include <mach/boolean.h>
36 #include <img4/firmware.h>
37 #include <img4/nonce.h>
38 
39 __BEGIN_DECLS
40 
41 #if XNU_KERNEL_PRIVATE
42 /*
43  * Any declarations for types or functions which don't need to be exported to kernel
44  * extensions should go here. Naturally, this means this section can also include
45  * headers which may not be available to kernel extensions.
46  */
47 
48 #if defined(__arm64__)
49 #include <pexpert/arm64/board_config.h>
50 #endif
51 
52 #include <vm/pmap.h>
53 #include <kern/lock_rw.h>
54 #include <TrustCache/API.h>
55 
56 
57 #if PMAP_CS
58 #define PMAP_CS_INCLUDE_CODE_SIGNING 1
59 #endif
60 
61 #if   XNU_MONITOR
62 #define PMAP_CS_PPL_MONITOR 1
63 #else
64 #define PMAP_CS_PPL_MONITOR 0
65 #endif
66 
67 #if PMAP_CS_PPL_MONITOR
68 
69 /*
70  * XNU_MONITOR and PMAP_CS are both defined for the same targets in board_config.h.
71  * As a result, whenever XNU_MONITOR is defined, so is PMAP_CS. In an ideal world, we
72  * can remove the use of PMAP_CS macro and simply use XNU_MONITOR, but that would
73  * require a lot of changes throughout the codebase.
74  *
75  * PMAP_CS_PPL_MONITOR is defined when we have XNU_MONITOR _and_ we explicitly don't
76  * have . This effectively means that whenever we have PMAP_CS_PPL_MONITOR,
77  * we should also always have PMAP_CS_INCLUDE_CODE_SIGNING. Lets enforce this with a
78  * build check.
79  */
80 #if !PMAP_CS_INCLUDE_CODE_SIGNING
81 #error "PMAP_CS_INCLUDE_CODE_SIGNING not defined when under PMAP_CS_PPL_MONITOR"
82 #endif
83 
84 /* Immutable part of the trust cache runtime */
85 extern TrustCacheRuntime_t ppl_trust_cache_rt;
86 
87 /* Mutable part of the trust cache runtime */
88 extern TrustCacheMutableRuntime_t ppl_trust_cache_mut_rt;
89 
90 /* Lock for the trust cache runtime */
91 extern lck_rw_t ppl_trust_cache_rt_lock;
92 
93 typedef struct _pmap_img4_payload {
94 	/* The trust cache data structure which wraps the payload */
95 	TrustCache_t trust_cache;
96 
97 	/* The actual image4 trust cache payload */
98 	uint8_t img4_payload[0];
99 } pmap_img4_payload_t;
100 
101 /* State for whether developer mode has been set or not */
102 extern bool ppl_developer_mode_set;
103 
104 /* State of developer mode on the system */
105 extern bool ppl_developer_mode_storage;
106 
107 /**
108  * Check the PPL trust cache runtime if a particular trust cache has already been
109  * loaded based on its UUID. The PPL trust cache runtime is kept locked as shared
110  * during the function.
111  */
112 kern_return_t
113 pmap_check_trust_cache_runtime_for_uuid(
114 	const uint8_t check_uuid[kUUIDSize]);
115 
116 /**
117  * Load an image4 trust cache of a particular type into the PPL. If validation succeeds,
118  * the payload will remain locked, but the other artifacts will be unlocked. If validation
119  * fails, all artifacts will be unlocked.
120  *
121  * All the lengths passed in will first be rounded up to page-size, so it is expected that
122  * the caller allocates page-aligned data.
123  *
124  * Upon successful validation, the trust cache is added to the runtime maintained by the
125  * PPL.
126  */
127 kern_return_t
128 pmap_load_trust_cache_with_type(
129 	TCType_t type,
130 	const vm_address_t pmap_img4_payload, const vm_size_t pmap_img4_payload_len,
131 	const vm_address_t img4_manifest, const vm_size_t img4_manifest_len,
132 	const vm_address_t img4_aux_manifest, const vm_size_t img4_aux_manifest_len);
133 
134 /*
135  * Query a trust cache from within the PPL. This function can only be called when within
136  * the PPL and does not pin the query_token passed in.
137  */
138 kern_return_t
139 pmap_query_trust_cache_safe(
140 	TCQueryType_t query_type,
141 	const uint8_t cdhash[kTCEntryHashSize],
142 	TrustCacheQueryToken_t *query_token);
143 
144 /**
145  * Query a trust cache of a particular type from the PPL. The query_token passed in will
146  * be pinned by the PPL runtime when the PPL is attempting to write to it. This is an API
147  * which can be used for callers external to the PPL.
148  */
149 kern_return_t
150 pmap_query_trust_cache(
151 	TCQueryType_t query_type,
152 	const uint8_t cdhash[kTCEntryHashSize],
153 	TrustCacheQueryToken_t *query_token);
154 
155 /**
156  * Toggle the state of developer mode on the system. This function can only be called with
157  * a true value once in the lifecycle of a boot.
158  *
159  * Until this function is called once to set the state, the PPL will block non-platform
160  * code and JIT on the system.
161  */
162 void
163 pmap_toggle_developer_mode(
164 	bool state);
165 
166 #endif /* PMAP_CS_PPL_MONITOR */
167 
168 #if PMAP_CS_INCLUDE_CODE_SIGNING
169 
170 #define CORE_ENTITLEMENTS_I_KNOW_WHAT_IM_DOING
171 
172 #include <CoreEntitlements/CoreEntitlementsPriv.h>
173 #include <kern/cs_blobs.h>
174 #include <libkern/tree.h>
175 #include <libkern/crypto/sha1.h>
176 #include <libkern/crypto/sha2.h>
177 #include <libkern/coretrust/coretrust.h>
178 
179 /* Validation data for a provisioning profile */
180 typedef struct _pmap_cs_profile {
181 	/*
182 	 * The PPL uses the physical aperture mapping to write to this structure. But
183 	 * we need to save a pointer to the original mapping for when we are going to
184 	 * unregister this profile from the PPL.
185 	 */
186 	void *original_payload;
187 
188 	/* A CoreEntitlements context for querying the profile */
189 	der_vm_context_t profile_ctx_storage;
190 	const der_vm_context_t *profile_ctx;
191 
192 	/*
193 	 * Critical information regarding the profile. If a profile has not been verified,
194 	 * it cannot be associated with a code signature. Development profiles are only
195 	 * allowed under certain circumstances.
196 	 */
197 	bool profile_validated;
198 	bool development_profile;
199 
200 	/*
201 	 * Reference count for the number of code signatures which are currently using
202 	 * this provisioning profile for their constraint validation.
203 	 */
204 	uint32_t reference_count;
205 
206 	/*
207 	 * The list of entitlements which are provisioned by this provisioning profile.
208 	 * If this list allows the debuggee entitlements, then this profile is considered
209 	 * a development profile.
210 	 */
211 	struct CEQueryContext entitlements_ctx_storage;
212 	struct CEQueryContext *entitlements_ctx;
213 
214 	/* Red-black tree linkage */
215 	RB_ENTRY(_pmap_cs_profile) link;
216 } pmap_cs_profile_t;
217 
218 /* This is how we expect the kernel to hand us provisioning profiles */
219 typedef struct _pmap_profile_payload {
220 	/* Storage for the provisioning profile */
221 	pmap_cs_profile_t profile_obj_storage;
222 
223 	/* Size of the signed profile blob */
224 	vm_size_t profile_blob_size;
225 
226 	/* The signed profile blob itself */
227 	uint8_t profile_blob[0];
228 } pmap_profile_payload_t;
229 
230 /* Trust levels are ordered, i.e. higher is more trust */
231 typedef enum {
232 	PMAP_CS_UNTRUSTED = 0,
233 
234 	/*
235 	 * Trust level given to code directory entries which have been retired and are
236 	 * no longer valid to be used for any purpose. These code directores are freed
237 	 * when their reference count touches 0.
238 	 */
239 	PMAP_CS_RETIRED,
240 
241 	/*
242 	 * This trust level signifies that an application has been verified through the
243 	 * profile based certificate chain, but the profile in question itself has not
244 	 * been verified. Code directories with this trust aren't allowed to be run
245 	 * or mapped.
246 	 */
247 	PMAP_CS_PROFILE_PREFLIGHT,
248 
249 	/*
250 	 * Signatures provided through the compilation service. These signatures are meant
251 	 * to only apply to loadable libraries, and therefore have the lowest acceptable trust.
252 	 */
253 	PMAP_CS_COMPILATION_SERVICE,
254 
255 	/*
256 	 * Signature for out-of-process JIT. These can only be loaded by an entitled process
257 	 * and have a special library validation policy for being mapped within other processes.
258 	 * These represent a safer version of JIT.
259 	 */
260 	PMAP_CS_OOP_JIT,
261 
262 	/*
263 	 * These signatures are those which are trusted because they have been signed by the
264 	 * device local signing key.
265 	 */
266 	PMAP_CS_LOCAL_SIGNING,
267 
268 	/*
269 	 * These signatures belong to applications which are profile validated, and for those
270 	 * whose profiles have also been verified.
271 	 */
272 	PMAP_CS_PROFILE_VALIDATED,
273 
274 	/*
275 	 * These signatures are those belonging to the app store.
276 	 */
277 	PMAP_CS_APP_STORE,
278 
279 #if PMAP_CS_INCLUDE_INTERNAL_CODE
280 	/*
281 	 * Engineering roots which are still Apple signed. These don't need to be platform
282 	 * because they are backed by a CMS signature and therefore would've never been
283 	 * platform anyways.
284 	 */
285 	PMAP_CS_ENGINEERING_SIGNED_WITH_CMS,
286 #endif
287 
288 	/*
289 	 * These signatures represent platform binaries which have the highest trust level.
290 	 */
291 	PMAP_CS_IN_LOADED_TRUST_CACHE,
292 	PMAP_CS_IN_STATIC_TRUST_CACHE,
293 
294 #if PMAP_CS_INCLUDE_INTERNAL_CODE
295 	/*
296 	 * Engineering roots installed by engineers for development. These are given the
297 	 * highest trust level.
298 	 */
299 	PMAP_CS_ENGINEERING_SIGNED,
300 #endif
301 } pmap_cs_trust_t;
302 
303 /* Everything with greater or equal trust is a platform binary */
304 #define PMAP_CS_LOWEST_PLATFORM_BINARY_TRUST PMAP_CS_IN_LOADED_TRUST_CACHE
305 
306 /* Minimum trust level of a code signature to be run/mapped */
307 #define PMAP_CS_LOWEST_ACCEPTABLE_TRUST PMAP_CS_COMPILATION_SERVICE
308 
309 typedef struct pmap_cs_code_directory {
310 	union {
311 		struct {
312 			/* red-black tree linkage */
313 			RB_ENTRY(pmap_cs_code_directory) link;
314 
315 			/*
316 			 * Blobs which are small enough are allocated and managed by the PPL. This field
317 			 * is NULL for large blobs.
318 			 */
319 			struct pmap_cs_blob *managed_blob;
320 			bool managed;
321 
322 			/*
323 			 * The superblob of the code signature. The length we store here is the length of the
324 			 * memory allocated by the kernel itself, which may be greater than the actual length
325 			 * of the code signature.
326 			 */
327 			CS_SuperBlob *superblob;
328 			vm_size_t superblob_size;
329 			bool superblob_validated;
330 
331 			/*
332 			 * Code directories can be arbitrarily large, and hashing them can take a long time. We
333 			 * usually hash code directories in a continuable way, yielding our execution context
334 			 * after hashing some amount of the bytes.
335 			 */
336 			union {
337 				SHA384_CTX sha384_ctx;
338 				SHA256_CTX sha256_ctx;
339 				SHA1_CTX sha1_ctx;
340 			};
341 			uint32_t cd_length_hashed;
342 
343 			/*
344 			 * The best code directory is just an offset away from the superblob. This code directory
345 			 * is extensively validated for all of its fields.
346 			 */
347 			const CS_CodeDirectory *cd;
348 			bool cd_offset_matched;
349 
350 			/*
351 			 * The first code directory is used when validating the CMS blob attached to a code signature
352 			 * and is often not the best code directory.
353 			 */
354 			bool first_cd_initialized;
355 			bool first_cd_hashed;
356 			uint8_t first_cdhash[CS_HASH_MAX_SIZE];
357 			const uint8_t *first_cd;
358 			size_t first_cd_length;
359 			const uint8_t *cms_blob;
360 			size_t cms_blob_length;
361 			CoreTrustDigestType ct_digest_type;
362 
363 			/*
364 			 * Frequently accessed information from the code directory kept here as a cache.
365 			 */
366 			const char *identifier;
367 			const char *teamid;
368 			bool main_binary;
369 
370 			/*
371 			 * The DER entitlements blob and CoreEntitlements context for querying this code
372 			 * signature for entitlements.
373 			 */
374 			struct CEQueryContext core_entitlements_ctx;
375 			struct CEQueryContext *ce_ctx;
376 			const CS_GenericBlob *der_entitlements;
377 			uint32_t der_entitlements_size;
378 
379 			/*
380 			 * This is parhaps the most important field in this structure. It signifies what
381 			 * level of confidence we have in this code directory and this trust level
382 			 * defines execution/mapping policies for this code directory.
383 			 */
384 			pmap_cs_trust_t trust;
385 
386 			/*
387 			 * Reference count of how many regions this code directory is associated with through
388 			 * pmap_cs_associate.
389 			 */
390 			uint32_t reference_count;
391 
392 			/*
393 			 * We maintain this field as it allows us to quickly index into a bucket of supported
394 			 * hash types, and choose the correct hashing algorithm for this code directory.
395 			 */
396 			unsigned int hash_type;
397 
398 			/* Lock on this code directory */
399 			decl_lck_rw_data(, rwlock);
400 
401 			/*
402 			 * The PPL may transform the code directory (e.g. for multilevel hashing),
403 			 * which changes its cdhash. We retain the cdhash of the original, canonical
404 			 * code directory here.
405 			 */
406 			uint8_t cdhash[CS_CDHASH_LEN];
407 
408 			/*
409 			 * For performing provisioning profile validation in the PPL, we store the profile as
410 			 * PPL owned data so it cannot be changed during the validation time period.
411 			 *
412 			 * This interface for profile validation is deprecated.
413 			 */
414 			struct {
415 				/* The provisioning profile and its size */
416 				const uint8_t *profile;
417 				vm_size_t profile_size;
418 
419 				/* Size of memory allocated to hold the profile */
420 				vm_size_t allocation_size;
421 			} profile_data;
422 
423 			/*
424 			 * The provisioning profile object used for validating constrainst for profile validates
425 			 * signatures. This is the newer interface the PPL uses.
426 			 */
427 			pmap_cs_profile_t *profile_obj;
428 
429 			/*
430 			 * The leaf certificate for CMS blobs as returned to us by CoreTrust. This is used when
431 			 * verifying a signature against a provisioning profile.
432 			 */
433 			const uint8_t *cms_leaf;
434 			vm_size_t cms_leaf_size;
435 
436 			/*
437 			 * A pointer to the entitlements structure maintained by the kernel. We don't really
438 			 * care about this other than maintaing a link to it in memory which isn't writable
439 			 * by the kernel.
440 			 */
441 			const void *kernel_entitlements;
442 
443 			/*
444 			 * The UBC layer may request the PPL to unlock the unneeded part of the code signature.
445 			 * We hold this boolean to track whether we have unlocked those unneeded bits already or
446 			 * not.
447 			 */
448 			bool unneeded_code_signature_unlocked;
449 		};
450 
451 		/* Free list linkage */
452 		struct pmap_cs_code_directory *pmap_cs_code_directory_next;
453 	};
454 } pmap_cs_code_directory_t;
455 
456 typedef struct pmap_cs_lookup_results {
457 	/* Start of the code region */
458 	vm_map_address_t region_addr;
459 
460 	/* Size of the code region */
461 	vm_map_size_t region_size;
462 
463 	/* Code signature backing the code region */
464 	struct pmap_cs_code_directory *region_sig;
465 } pmap_cs_lookup_results_t;
466 
467 typedef struct _pmap_cs_ce_acceleration_buffer {
468 	/* Magic to identify this structure */
469 	uint16_t magic;
470 
471 	/*
472 	 * The acceleration buffer can come from one of two places. First, it can come
473 	 * from the extra space present within the locked down code signature as not
474 	 * all of it is used all the time. In this case, we don't need to free the
475 	 * buffer once we're done using it. Second, it can come from the bucket allocator
476 	 * within the PPL, in which case we need to deallocate this after we're done with
477 	 * it.
478 	 */
479 	union {
480 		uint16_t unused0;
481 		bool allocated;
482 	};
483 
484 	/* The length of the acceleration buffer */
485 	uint32_t length;
486 
487 	/* The embedded buffer bytes */
488 	uint8_t buffer[0];
489 } __attribute__((packed)) pmap_cs_ce_acceleration_buffer_t;
490 
491 /* Ensure we have a known overhead here */
492 _Static_assert(sizeof(pmap_cs_ce_acceleration_buffer_t) == 8,
493     "sizeof(pmap_cs_ce_acceleration_buffer_t) != 8");
494 
495 #define PMAP_CS_ACCELERATION_BUFFER_MAGIC (0x1337u)
496 
497 #define PMAP_CS_ASSOCIATE_JIT ((void *) -1)
498 #define PMAP_CS_ASSOCIATE_COW ((void *) -2)
499 #define PMAP_CS_LOCAL_SIGNING_KEY_SIZE 97
500 
501 /* Maximum blob sized managed by the PPL on its own */
502 extern const size_t pmap_cs_blob_limit;
503 
504 /**
505  * Initialize the red-black tree and the locks for managing provisioning profiles within
506  * the PPL.
507  *
508  * This function doesn't trap into the PPL but writes to PPL protected data. Hence, this
509  * function needs to be called before the PPL is locked down, asn otherwise it will cause
510  * a system panic.
511  */
512 void
513 pmap_initialize_provisioning_profiles(void);
514 
515 /**
516  * Register a provisioning profile with the PPL. The payload address and size are both
517  * expected to be page aligned. The PPL will attempt to lockdown the address range before
518  * the profile validation.
519  *
520  * After validation, the profile will be added to an internal red-black tree, allowing
521  * the PPL to safely enumerate all registered profiles.
522  */
523 kern_return_t
524 pmap_register_provisioning_profile(
525 	const vm_address_t payload_addr,
526 	const vm_size_t payload_size);
527 
528 /**
529  * Unregister a provisioning profile from the PPL. The payload which was registered is
530  * unlocked, and the caller is free to do whatever they want with it. Unregistration is
531  * only successful when there are no reference counts on the profile object.
532  */
533 kern_return_t
534 pmap_unregister_provisioning_profile(
535 	pmap_cs_profile_t *profile_obj);
536 
537 /**
538  * Associate a PPL profile object with a PPL code signature object. A code signature
539  * object can only have a single profile associated with it, and a successful association
540  * increments the reference count on the profile object.
541  */
542 kern_return_t
543 pmap_associate_provisioning_profile(
544 	pmap_cs_code_directory_t *cd_entry,
545 	pmap_cs_profile_t *profile_obj);
546 
547 /**
548  * Disassociate a PPL profile object from a PPL code signature object. Disassociation
549  * through this code path is only successful when the code signature object has been
550  * verified.
551  *
552  * This decrements the reference count on the profile object, potentially allowing it
553  * to be unregistered if the reference count hits zero.
554  */
555 kern_return_t
556 pmap_disassociate_provisioning_profile(
557 	pmap_cs_code_directory_t *cd_entry);
558 
559 /**
560  * Store the compilation service CDHash within the PPL storage so that it may not be
561  * modified by an attacker. The CDHash being stored must represent a library and this
562  * is enforced during signature validation when a signature is trusted because it
563  * matched the compilation service CDHash.
564  */
565 void
566 pmap_set_compilation_service_cdhash(const uint8_t cdhash[CS_CDHASH_LEN]);
567 
568 /**
569  * Match a specified CDHash against the stored compilation service CDHash. The CDHash
570  * is protected with a lock, and that lock is held when the matching takes place in
571  * order to ensure we don't compare against a CDHash which is in the process of changing.
572  */
573 bool
574 pmap_match_compilation_service_cdhash(const uint8_t cdhash[CS_CDHASH_LEN]);
575 
576 /**
577  * Store the local signing public key in secured storage within the PPL. The PPL only
578  * allows setting a key once, and subsequent attempts to do this will panic the system.
579  *
580  * This key is used during CoreTrust validation of signatures during code signature
581  * verification.
582  */
583 void
584 pmap_set_local_signing_public_key(
585 	const uint8_t public_key[PMAP_CS_LOCAL_SIGNING_KEY_SIZE]);
586 
587 /**
588  * Acquire the local signing public key which was previusly stored within the PPL. If
589  * there is no key stored in the PPL, then this function shall return NULL.
590  */
591 uint8_t*
592 pmap_get_local_signing_public_key(void);
593 
594 /**
595  * All locally signed main binaries need to be authorixed explicitly before they are
596  * allowed to run. As part of this, this API allows an application to register a CDHash
597  * for the main binary it is intending to run.
598  *
599  * Use of this API requires the appropriate entitlement.
600  */
601 void
602 pmap_unrestrict_local_signing(
603 	const uint8_t cdhash[CS_CDHASH_LEN]);
604 
605 /**
606  * Register a code signature blob with the PPL. If the blob size is small enough, the
607  * PPL will copy the entire blob into its own allocated memory. On the other hand, if
608  * the blob is large, the PPL will attempt to lockdown the passed in blob, and doing
609  * so will require that the address and size provided are page aligned.
610  *
611  * After validation, the signature will be added to an internal red-black tree, allowing
612  * the PPL to safely enumerate all registered code signatures.
613  */
614 kern_return_t
615 pmap_cs_register_code_signature_blob(
616 	vm_address_t blob_addr,
617 	vm_size_t blob_size,
618 	vm_offset_t code_directory_offset,
619 	pmap_cs_code_directory_t **cd_entry);
620 
621 /**
622  * Unregister a code signature blob from the PPL. The signature address is either freed
623  * in case it was owned by the PPL, or it is unlocked in case it was XNU-owned by was PPL
624  * locked.
625  *
626  * If the memory is unlocked, then the kernel is free to do with the memory as it pleases.
627  * Note that this function may not deallocate the cd_entry itself, in case the cd_entry
628  * has any reference counts on it. In that case, the cd_entry is retired, and finally
629  * freed when the final code region which references the cd_entry is freed.
630  */
631 kern_return_t
632 pmap_cs_unregister_code_signature_blob(
633 	pmap_cs_code_directory_t *cd_entry);
634 
635 /**
636  * Verify a signature within the PPL. Once a signature has been verified, it gets assigned
637  * a trust level, and based on that trust level, the cd_entry is then allowed to be
638  * associated with address spaces.
639  */
640 kern_return_t
641 pmap_cs_verify_code_signature_blob(
642 	pmap_cs_code_directory_t *cd_entry);
643 
644 /**
645  * Once we've verified a code signature, not all blobs from the signature are required
646  * going forward. This function can be used to unlock parts of the code signature which
647  * can then be freed by the kernel to conserve memory.
648  */
649 kern_return_t
650 pmap_cs_unlock_unneeded_code_signature(
651 	pmap_cs_code_directory_t *cd_entry,
652 	vm_address_t *unneeded_addr,
653 	vm_size_t *unneeded_size);
654 
655 /**
656  * Create an association of a cd_entry within a code region in the pmap. If the cd_entry
657  * is a main binary, then it is set as the main region of the pmap, otherwise the cd_entry
658  * is evaluated for a library validation policy against the main binary of the pmap.
659  */
660 kern_return_t
661 pmap_cs_associate(
662 	pmap_t pmap,
663 	pmap_cs_code_directory_t *cd_entry,
664 	vm_map_address_t vaddr,
665 	vm_map_size_t vsize,
666 	vm_object_offset_t offset);
667 
668 /**
669  * Iterate through the code regions present in the SPLAY tree for checking if the specified
670  * address intersects with any code region or not.
671  */
672 void
673 pmap_cs_lookup(
674 	pmap_t pmap,
675 	vm_map_address_t vaddr,
676 	pmap_cs_lookup_results_t *results);
677 
678 /**
679  * Let the PPL know that the associated pmap needs to be debugged and therefore it needs
680  * to allow invalid code to be mapped in. PPL shall only allow this when the pmap posseses
681  * the appropriate debuggee entitlement.
682  */
683 kern_return_t
684 pmap_cs_allow_invalid(pmap_t pmap);
685 
686 /**
687  * Acquire the trust level which is put onto a pmap based on the code signature associated
688  * with the main region. This function does NOT take a lock on the pmap and does not trap
689  * into the PPL.
690  */
691 kern_return_t
692 pmap_get_trust_level_kdp(
693 	pmap_t pmap,
694 	pmap_cs_trust_t *trust_level);
695 
696 /**
697  * Copy over the main binary association from the old address space to the new address
698  * space. This is required since a fork copies over all associations from one address space
699  * to another, and we need to make sure the main binary association is made before any
700  * libraries are mapped in.
701  */
702 kern_return_t
703 pmap_cs_fork_prepare(
704 	pmap_t old_pmap,
705 	pmap_t new_pmap);
706 
707 /**
708  * Keep a reference to the kernel entitlements data structure within the cd_entry in
709  * order to establish a read-only chain for the kernel to query in order to resolve the
710  * entitlements on an address space.
711  */
712 kern_return_t
713 pmap_associate_kernel_entitlements(
714 	pmap_cs_code_directory_t *cd_entry,
715 	const void *kernel_entitlements);
716 
717 /**
718  * Resolve the kernel entitlements object attached to the main binary of an address space
719  * and return it back to the kernel.
720  */
721 kern_return_t
722 pmap_resolve_kernel_entitlements(
723 	pmap_t pmap,
724 	const void **kernel_entitlements);
725 
726 /**
727  * Accelerate the CoreEntitlements context for a particular cd_entry. This operation can
728  * only be performed on reconstituted code signatures, and accelerates the context using
729  * memory which is locked by the PPL.
730  *
731  * If the code signature pages have enough space left within them, then that extra space
732  * is used for allocating the acceleration buffer, otherwise we tap into the allocator
733  * for it.
734  */
735 kern_return_t
736 pmap_accelerate_entitlements(
737 	pmap_cs_code_directory_t *cd_entry);
738 
739 #endif /* PMAP_CS_INCLUDE_CODE_SIGNING */
740 
741 #endif /* XNU_KERNEL_PRIVATE */
742 
743 /* Availability macros for AppleImage4 */
744 #if defined(__arm__) || defined(__arm64__)
745 #define PMAP_SUPPORTS_IMAGE4_NONCE 1
746 #define PMAP_SUPPORTS_IMAGE4_OBJECT_EXECUTION 1
747 #endif
748 
749 /* Availability macros for developer mode */
750 #define PMAP_SUPPORTS_DEVELOPER_MODE 1
751 
752 /**
753  * Check if the PPL based code signing is enabled on the system or not.
754  */
755 bool
756 pmap_cs_enabled(void);
757 
758 /**
759  * The PPl allocates some space for AppleImage4 to store some of its data. It needs to
760  * allocate this space since this region needs to be PPL protected, and the macro which
761  * makes a region PPL protected isn't available to kernel extensions.
762  *
763  * This function can be used to acquire the memory region which is PPL protected.
764  */
765 void*
766 pmap_image4_pmap_data(
767 	size_t *allocated_size);
768 
769 /**
770  * Use the AppleImage4 API to set a nonce value based on a particular nonce index.
771  * AppleImage4 ensures that a particular nonce domain value can only be set once
772  * during the boot of the system.
773  */
774 void
775 pmap_image4_set_nonce(
776 	const img4_nonce_domain_index_t ndi,
777 	const img4_nonce_t *nonce);
778 
779 /**
780  * Use the AppleImage4 API to roll the nonce associated with a particular domain to
781  * make the nonce invalid.
782  */
783 void
784 pmap_image4_roll_nonce(
785 	const img4_nonce_domain_index_t ndi);
786 
787 /**
788  * Use the AppleImage4 API to copy the nonce value associated with a particular domain.
789  *
790  * The PPL will attempt to "pin" the nonce_out parameter before writing to it.
791  */
792 errno_t
793 pmap_image4_copy_nonce(
794 	const img4_nonce_domain_index_t ndi,
795 	img4_nonce_t *nonce_out);
796 
797 /**
798  * Use the AppleImage4 API to perform object execution of a particular known object type.
799  *
800  * These are the supported object types:
801  * - IMG4_RUNTIME_OBJECT_SPEC_INDEX_SUPPLEMENTAL_ROOT
802  */
803 errno_t
804 pmap_image4_execute_object(
805 	img4_runtime_object_spec_index_t obj_spec_index,
806 	const img4_buff_t *payload,
807 	const img4_buff_t *manifest);
808 
809 /**
810  * Use the AppleImage4 API to copy an executed objects contents into provided memroy.
811  *
812  * The PPL will attempt to "pin" the object_out parameter before writing to it.
813  */
814 errno_t
815 pmap_image4_copy_object(
816 	img4_runtime_object_spec_index_t obj_spec_index,
817 	vm_address_t object_out,
818 	size_t *object_length);
819 
820 __END_DECLS
821 
822 #endif /* KERNEL_PRIVATE */
823 #endif /* _VM_PMAP_CS_H_ */
824