xref: /xnu-8792.41.9/osfmk/vm/pmap_cs.h (revision 5c2921b07a2480ab43ec66f5b9e41cb872bc554f)
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 <kern/lock_rw.h>
53 #include <TrustCache/API.h>
54 
55 
56 #if PMAP_CS
57 #define PMAP_CS_INCLUDE_CODE_SIGNING 1
58 #endif
59 
60 #if   XNU_MONITOR
61 #define PMAP_CS_PPL_MONITOR 1
62 #else
63 #define PMAP_CS_PPL_MONITOR 0
64 #endif
65 
66 #if PMAP_CS_PPL_MONITOR
67 
68 /*
69  * XNU_MONITOR and PMAP_CS are both defined for the same targets in board_config.h.
70  * As a result, whenever XNU_MONITOR is defined, so is PMAP_CS. In an ideal world, we
71  * can remove the use of PMAP_CS macro and simply use XNU_MONITOR, but that would
72  * require a lot of changes throughout the codebase.
73  *
74  * PMAP_CS_PPL_MONITOR is defined when we have XNU_MONITOR _and_ we explicitly don't
75  * have . This effectively means that whenever we have PMAP_CS_PPL_MONITOR,
76  * we should also always have PMAP_CS_INCLUDE_CODE_SIGNING. Lets enforce this with a
77  * build check.
78  */
79 #if !PMAP_CS_INCLUDE_CODE_SIGNING
80 #error "PMAP_CS_INCLUDE_CODE_SIGNING not defined when under PMAP_CS_PPL_MONITOR"
81 #endif
82 
83 /* Immutable part of the trust cache runtime */
84 extern TrustCacheRuntime_t ppl_trust_cache_rt;
85 
86 /* Mutable part of the trust cache runtime */
87 extern TrustCacheMutableRuntime_t ppl_trust_cache_mut_rt;
88 
89 /* Lock for the trust cache runtime */
90 extern lck_rw_t ppl_trust_cache_rt_lock;
91 
92 typedef struct _pmap_img4_payload {
93 	/* The trust cache data structure which wraps the payload */
94 	TrustCache_t trust_cache;
95 
96 	/* The actual image4 trust cache payload */
97 	uint8_t img4_payload[0];
98 } pmap_img4_payload_t;
99 
100 /* State for whether developer mode has been set or not */
101 extern bool ppl_developer_mode_set;
102 
103 /* State of developer mode on the system */
104 extern bool ppl_developer_mode_storage;
105 
106 /**
107  * Load an image4 trust cache of a particular type into the PPL. If validation succeeds,
108  * the payload will remain locked, but the other artifacts will be unlocked. If validation
109  * fails, all artifacts will be unlocked.
110  *
111  * All the lengths passed in will first be rounded up to page-size, so it is expected that
112  * the caller allocates page-aligned data.
113  *
114  * Upon successful validation, the trust cache is added to the runtime maintained by the
115  * PPL.
116  */
117 kern_return_t
118 pmap_load_trust_cache_with_type(
119 	TCType_t type,
120 	const vm_address_t pmap_img4_payload, const vm_size_t pmap_img4_payload_len,
121 	const vm_address_t img4_manifest, const vm_size_t img4_manifest_len,
122 	const vm_address_t img4_aux_manifest, const vm_size_t img4_aux_manifest_len);
123 
124 /*
125  * Query a trust cache from within the PPL. This function can only be called when within
126  * the PPL and does not pin the query_token passed in.
127  */
128 kern_return_t
129 pmap_query_trust_cache_safe(
130 	TCQueryType_t query_type,
131 	const uint8_t cdhash[kTCEntryHashSize],
132 	TrustCacheQueryToken_t *query_token);
133 
134 /**
135  * Query a trust cache of a particular type from the PPL. The query_token passed in will
136  * be pinned by the PPL runtime when the PPL is attempting to write to it. This is an API
137  * which can be used for callers external to the PPL.
138  */
139 kern_return_t
140 pmap_query_trust_cache(
141 	TCQueryType_t query_type,
142 	const uint8_t cdhash[kTCEntryHashSize],
143 	TrustCacheQueryToken_t *query_token);
144 
145 /**
146  * Toggle the state of developer mode on the system. This function can only be called with
147  * a true value once in the lifecycle of a boot.
148  *
149  * Until this function is called once to set the state, the PPL will block non-platform
150  * code and JIT on the system.
151  */
152 void
153 pmap_toggle_developer_mode(
154 	bool state);
155 
156 #endif /* PMAP_CS_PPL_MONITOR */
157 
158 #if PMAP_CS_INCLUDE_CODE_SIGNING
159 
160 #define CORE_ENTITLEMENTS_I_KNOW_WHAT_IM_DOING
161 
162 #include <CoreEntitlements/CoreEntitlementsPriv.h>
163 #include <kern/cs_blobs.h>
164 #include <libkern/tree.h>
165 #include <libkern/crypto/sha1.h>
166 #include <libkern/crypto/sha2.h>
167 #include <libkern/coretrust/coretrust.h>
168 
169 /* Validation data for a provisioning profile */
170 typedef struct _pmap_cs_profile {
171 	/*
172 	 * The PPL uses the physical aperture mapping to write to this structure. But
173 	 * we need to save a pointer to the original mapping for when we are going to
174 	 * unregister this profile from the PPL.
175 	 */
176 	void *original_payload;
177 
178 	/* A CoreEntitlements context for querying the profile */
179 	der_vm_context_t profile_ctx_storage;
180 	const der_vm_context_t *profile_ctx;
181 
182 	/*
183 	 * Critical information regarding the profile. If a profile has not been verified,
184 	 * it cannot be associated with a code signature. Development profiles are only
185 	 * allowed under certain circumstances.
186 	 */
187 	bool profile_validated;
188 	bool development_profile;
189 
190 	/*
191 	 * Reference count for the number of code signatures which are currently using
192 	 * this provisioning profile for their constraint validation.
193 	 */
194 	uint32_t reference_count;
195 
196 	/*
197 	 * The list of entitlements which are provisioned by this provisioning profile.
198 	 * If this list allows the debuggee entitlements, then this profile is considered
199 	 * a development profile.
200 	 */
201 	struct CEQueryContext entitlements_ctx_storage;
202 	struct CEQueryContext *entitlements_ctx;
203 
204 	/* Red-black tree linkage */
205 	RB_ENTRY(_pmap_cs_profile) link;
206 } pmap_cs_profile_t;
207 
208 /* This is how we expect the kernel to hand us provisioning profiles */
209 typedef struct _pmap_profile_payload {
210 	/* Storage for the provisioning profile */
211 	pmap_cs_profile_t profile_obj_storage;
212 
213 	/* Size of the signed profile blob */
214 	vm_size_t profile_blob_size;
215 
216 	/* The signed profile blob itself */
217 	uint8_t profile_blob[0];
218 } pmap_profile_payload_t;
219 
220 /* Trust levels are ordered, i.e. higher is more trust */
221 typedef enum {
222 	PMAP_CS_UNTRUSTED = 0,
223 
224 	/*
225 	 * Trust level given to code directory entries which have been retired and are
226 	 * no longer valid to be used for any purpose. These code directores are freed
227 	 * when their reference count touches 0.
228 	 */
229 	PMAP_CS_RETIRED,
230 
231 	/*
232 	 * This trust level signifies that an application has been verified through the
233 	 * profile based certificate chain, but the profile in question itself has not
234 	 * been verified. Code directories with this trust aren't allowed to be run
235 	 * or mapped.
236 	 */
237 	PMAP_CS_PROFILE_PREFLIGHT,
238 
239 	/*
240 	 * Signatures provided through the compilation service. These signatures are meant
241 	 * to only apply to loadable libraries, and therefore have the lowest acceptable trust.
242 	 */
243 	PMAP_CS_COMPILATION_SERVICE,
244 
245 	/*
246 	 * Signature for out-of-process JIT. These can only be loaded by an entitled process
247 	 * and have a special library validation policy for being mapped within other processes.
248 	 * These represent a safer version of JIT.
249 	 */
250 	PMAP_CS_OOP_JIT,
251 
252 	/*
253 	 * These signatures are those which are trusted because they have been signed by the
254 	 * device local signing key.
255 	 */
256 	PMAP_CS_LOCAL_SIGNING,
257 
258 	/*
259 	 * These signatures belong to applications which are profile validated, and for those
260 	 * whose profiles have also been verified.
261 	 */
262 	PMAP_CS_PROFILE_VALIDATED,
263 
264 	/*
265 	 * These signatures are those belonging to the app store.
266 	 */
267 	PMAP_CS_APP_STORE,
268 
269 #if PMAP_CS_INCLUDE_INTERNAL_CODE
270 	/*
271 	 * Engineering roots which are still Apple signed. These don't need to be platform
272 	 * because they are backed by a CMS signature and therefore would've never been
273 	 * platform anyways.
274 	 */
275 	PMAP_CS_ENGINEERING_SIGNED_WITH_CMS,
276 #endif
277 
278 	/*
279 	 * These signatures represent platform binaries which have the highest trust level.
280 	 */
281 	PMAP_CS_IN_LOADED_TRUST_CACHE,
282 	PMAP_CS_IN_STATIC_TRUST_CACHE,
283 
284 #if PMAP_CS_INCLUDE_INTERNAL_CODE
285 	/*
286 	 * Engineering roots installed by engineers for development. These are given the
287 	 * highest trust level.
288 	 */
289 	PMAP_CS_ENGINEERING_SIGNED,
290 #endif
291 } pmap_cs_trust_t;
292 
293 /* Everything with greater or equal trust is a platform binary */
294 #define PMAP_CS_LOWEST_PLATFORM_BINARY_TRUST PMAP_CS_IN_LOADED_TRUST_CACHE
295 
296 /* Minimum trust level of a code signature to be run/mapped */
297 #define PMAP_CS_LOWEST_ACCEPTABLE_TRUST PMAP_CS_COMPILATION_SERVICE
298 
299 typedef struct pmap_cs_code_directory {
300 	union {
301 		struct {
302 			/* red-black tree linkage */
303 			RB_ENTRY(pmap_cs_code_directory) link;
304 
305 			/*
306 			 * Blobs which are small enough are allocated and managed by the PPL. This field
307 			 * is NULL for large blobs.
308 			 */
309 			struct pmap_cs_blob *managed_blob;
310 			bool managed;
311 
312 			/*
313 			 * The superblob of the code signature. The length we store here is the length of the
314 			 * memory allocated by the kernel itself, which may be greater than the actual length
315 			 * of the code signature.
316 			 */
317 			CS_SuperBlob *superblob;
318 			vm_size_t superblob_size;
319 			bool superblob_validated;
320 
321 			/*
322 			 * Code directories can be arbitrarily large, and hashing them can take a long time. We
323 			 * usually hash code directories in a continuable way, yielding our execution context
324 			 * after hashing some amount of the bytes.
325 			 */
326 			union {
327 				SHA384_CTX sha384_ctx;
328 				SHA256_CTX sha256_ctx;
329 				SHA1_CTX sha1_ctx;
330 			};
331 			uint32_t cd_length_hashed;
332 
333 			/*
334 			 * The best code directory is just an offset away from the superblob. This code directory
335 			 * is extensively validated for all of its fields.
336 			 */
337 			const CS_CodeDirectory *cd;
338 			bool cd_offset_matched;
339 
340 			/*
341 			 * The first code directory is used when validating the CMS blob attached to a code signature
342 			 * and is often not the best code directory.
343 			 */
344 			bool first_cd_initialized;
345 			bool first_cd_hashed;
346 			uint8_t first_cdhash[CS_HASH_MAX_SIZE];
347 			const uint8_t *first_cd;
348 			size_t first_cd_length;
349 			const uint8_t *cms_blob;
350 			size_t cms_blob_length;
351 			CoreTrustDigestType ct_digest_type;
352 
353 			/*
354 			 * Frequently accessed information from the code directory kept here as a cache.
355 			 */
356 			const char *identifier;
357 			const char *teamid;
358 			bool main_binary;
359 
360 			/*
361 			 * The DER entitlements blob and CoreEntitlements context for querying this code
362 			 * signature for entitlements.
363 			 */
364 			struct CEQueryContext core_entitlements_ctx;
365 			struct CEQueryContext *ce_ctx;
366 			const CS_GenericBlob *der_entitlements;
367 			uint32_t der_entitlements_size;
368 
369 			/*
370 			 * This is parhaps the most important field in this structure. It signifies what
371 			 * level of confidence we have in this code directory and this trust level
372 			 * defines execution/mapping policies for this code directory.
373 			 */
374 			pmap_cs_trust_t trust;
375 
376 			/*
377 			 * Reference count of how many regions this code directory is associated with through
378 			 * pmap_cs_associate.
379 			 */
380 			uint32_t reference_count;
381 
382 			/*
383 			 * We maintain this field as it allows us to quickly index into a bucket of supported
384 			 * hash types, and choose the correct hashing algorithm for this code directory.
385 			 */
386 			unsigned int hash_type;
387 
388 			/* Lock on this code directory */
389 			decl_lck_rw_data(, rwlock);
390 
391 			/*
392 			 * The PPL may transform the code directory (e.g. for multilevel hashing),
393 			 * which changes its cdhash. We retain the cdhash of the original, canonical
394 			 * code directory here.
395 			 */
396 			uint8_t cdhash[CS_CDHASH_LEN];
397 
398 			/*
399 			 * For performing provisioning profile validation in the PPL, we store the profile as
400 			 * PPL owned data so it cannot be changed during the validation time period.
401 			 *
402 			 * This interface for profile validation is deprecated.
403 			 */
404 			struct {
405 				/* The provisioning profile and its size */
406 				const uint8_t *profile;
407 				vm_size_t profile_size;
408 
409 				/* Size of memory allocated to hold the profile */
410 				vm_size_t allocation_size;
411 			} profile_data;
412 
413 			/*
414 			 * The provisioning profile object used for validating constrainst for profile validates
415 			 * signatures. This is the newer interface the PPL uses.
416 			 */
417 			pmap_cs_profile_t *profile_obj;
418 
419 			/*
420 			 * The leaf certificate for CMS blobs as returned to us by CoreTrust. This is used when
421 			 * verifying a signature against a provisioning profile.
422 			 */
423 			const uint8_t *cms_leaf;
424 			vm_size_t cms_leaf_size;
425 
426 			/*
427 			 * The UBC layer may request the PPL to unlock the unneeded part of the code signature.
428 			 * We hold this boolean to track whether we have unlocked those unneeded bits already or
429 			 * not.
430 			 */
431 			bool unneeded_code_signature_unlocked;
432 		};
433 
434 		/* Free list linkage */
435 		struct pmap_cs_code_directory *pmap_cs_code_directory_next;
436 	};
437 } pmap_cs_code_directory_t;
438 
439 /**
440  * Initialize the red-black tree and the locks for managing provisioning profiles within
441  * the PPL.
442  *
443  * This function doesn't trap into the PPL but writes to PPL protected data. Hence, this
444  * function needs to be called before the PPL is locked down, asn otherwise it will cause
445  * a system panic.
446  */
447 void
448 pmap_initialize_provisioning_profiles(void);
449 
450 /**
451  * Register a provisioning profile with the PPL. The payload address and size are both
452  * expected to be page aligned. The PPL will attempt to lockdown the address range before
453  * the profile validation.
454  *
455  * After validation, the profile will be added to an internal red-black tree, allowing
456  * the PPL to safely enumerate all registered profiles.
457  */
458 kern_return_t
459 pmap_register_provisioning_profile(
460 	const vm_address_t payload_addr,
461 	const vm_size_t payload_size);
462 
463 /**
464  * Unregister a provisioning profile from the PPL. The payload which was registered is
465  * unlocked, and the caller is free to do whatever they want with it. Unregistration is
466  * only successful when there are no reference counts on the profile object.
467  */
468 kern_return_t
469 pmap_unregister_provisioning_profile(
470 	pmap_cs_profile_t *profile_obj);
471 
472 /**
473  * Associate a PPL profile object with a PPL code signature object. A code signature
474  * object can only have a single profile associated with it, and a successful association
475  * increments the reference count on the profile object.
476  */
477 kern_return_t
478 pmap_associate_provisioning_profile(
479 	pmap_cs_code_directory_t *cd_entry,
480 	pmap_cs_profile_t *profile_obj);
481 
482 /**
483  * Disassociate a PPL profile object from a PPL code signature object. Disassociation
484  * through this code path is only successful when the code signature object has been
485  * verified.
486  *
487  * This decrements the reference count on the profile object, potentially allowing it
488  * to be unregistered if the reference count hits zero.
489  */
490 kern_return_t
491 pmap_disassociate_provisioning_profile(
492 	pmap_cs_code_directory_t *cd_entry);
493 
494 #endif /* PMAP_CS_INCLUDE_CODE_SIGNING */
495 
496 #endif /* XNU_KERNEL_PRIVATE */
497 
498 /* Availability macros for AppleImage4 */
499 #if defined(__arm__) || defined(__arm64__)
500 #define PMAP_SUPPORTS_IMAGE4_NONCE 1
501 #define PMAP_SUPPORTS_IMAGE4_OBJECT_EXECUTION 1
502 #endif
503 
504 /* Availability macros for developer mode */
505 #define PMAP_SUPPORTS_DEVELOPER_MODE 1
506 
507 /**
508  * The PPl allocates some space for AppleImage4 to store some of its data. It needs to
509  * allocate this space since this region needs to be PPL protected, and the macro which
510  * makes a region PPL protected isn't available to kernel extensions.
511  *
512  * This function can be used to acquire the memory region which is PPL protected.
513  */
514 void*
515 pmap_image4_pmap_data(
516 	size_t *allocated_size);
517 
518 /**
519  * Use the AppleImage4 API to set a nonce value based on a particular nonce index.
520  * AppleImage4 ensures that a particular nonce domain value can only be set once
521  * during the boot of the system.
522  */
523 void
524 pmap_image4_set_nonce(
525 	const img4_nonce_domain_index_t ndi,
526 	const img4_nonce_t *nonce);
527 
528 /**
529  * Use the AppleImage4 API to roll the nonce associated with a particular domain to
530  * make the nonce invalid.
531  */
532 void
533 pmap_image4_roll_nonce(
534 	const img4_nonce_domain_index_t ndi);
535 
536 /**
537  * Use the AppleImage4 API to copy the nonce value associated with a particular domain.
538  *
539  * The PPL will attempt to "pin" the nonce_out parameter before writing to it.
540  */
541 errno_t
542 pmap_image4_copy_nonce(
543 	const img4_nonce_domain_index_t ndi,
544 	img4_nonce_t *nonce_out);
545 
546 /**
547  * Use the AppleImage4 API to perform object execution of a particular known object type.
548  *
549  * These are the supported object types:
550  * - IMG4_RUNTIME_OBJECT_SPEC_INDEX_SUPPLEMENTAL_ROOT
551  */
552 errno_t
553 pmap_image4_execute_object(
554 	img4_runtime_object_spec_index_t obj_spec_index,
555 	const img4_buff_t *payload,
556 	const img4_buff_t *manifest);
557 
558 /**
559  * Use the AppleImage4 API to copy an executed objects contents into provided memroy.
560  *
561  * The PPL will attempt to "pin" the object_out parameter before writing to it.
562  */
563 errno_t
564 pmap_image4_copy_object(
565 	img4_runtime_object_spec_index_t obj_spec_index,
566 	vm_address_t object_out,
567 	size_t *object_length);
568 
569 __END_DECLS
570 
571 #endif /* KERNEL_PRIVATE */
572 #endif /* _VM_PMAP_CS_H_ */
573