xref: /xnu-11417.140.69/EXTERNAL_HEADERS/CoreEntitlements/der_vm.h (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 //
2 //  der_vm.h
3 //  CoreEntitlements
4 //
5 
6 #ifndef CORE_ENTITLEMENTS_DER_VM_H
7 #define CORE_ENTITLEMENTS_DER_VM_H
8 
9 #include <CoreEntitlements/CoreEntitlements.h>
10 #include <stdint.h>
11 #include <stdbool.h>
12 
13 __ptrcheck_abi_assume_single();
14 
15 // The kernel doesn't have access to this one
16 #if __has_include (<corecrypto/ccder.h>)
17 #include <corecrypto/ccder.h>
18 #else
19 typedef unsigned long ccder_tag;
20 #endif
21 
22 
23 /*!
24  * @typedef der_vm_context_t
25  * Represents the current execution state of the DERQL interpreter.
26  * The context can be initialized with der_vm_context_create  and subsequently used in invocations of der_vm_execute.
27  * This object is passed by value and the functions that operate on the der_vm_context_t do not modify it but instead return a copy.
28  * As a consequence, the state of the interpreter can be captured at any execution point by holding on to the context.
29  */
30 typedef struct der_vm_context {
31     CERuntime_t runtime;
32 #if CE_ACCELERATION_SUPPORTED
33     struct CEAccelerationContext lookup;
34 #endif
35     ccder_tag dictionary_tag;
36     bool sorted;
37     bool valid;
38     union {
39         // the one you should use
40         ccder_read_blob ccstate;
41 
42         // for compatibility
43         struct {
44             const uint8_t *__ended_by(der_end) der_start;
45             const uint8_t *der_end;
46         } state;
47     };
48 } der_vm_context_t;
49 
50 /*!
51  * @function der_vm_context_create
52  * Returns an initialized, valid,  der_vm_context_t against which query operations may be performed
53  * @param rt
54  * Active runtime
55  * @param dictionary_tag
56  * Which DER tag should be used when matching dictionaries
57  * @param sorted_keys
58  * Whether the VM can assume that the keys are sorted
59  * @param der
60  * Pointer to the start of a DER object
61  * @param der_end
62  * Pointer to one byte past the end of the DER object
63  * @discussion
64  * The caller must ensure that the memory pointed to by der remains valid as long as the der_vm_context_t is used.
65  * The caller must ensure that the DER object has been validated.
66  */
67 der_vm_context_t der_vm_context_create(const CERuntime_t rt, ccder_tag dictionary_tag, bool sorted_keys, const uint8_t *__ended_by(der_end) der, const uint8_t *der_end);
68 
69 /*!
70  * @function der_vm_execute
71  * Returns a new context that is derived by applying the op to the passed in context
72  *
73  * @param context
74  * Context to execute against
75  *
76  * @param op
77  * An operation to be performed against the context
78  * This op should be created by one of the CEMatch* or CESelect* functions
79  *
80  * @discussion
81  * If the VM encounters:
82  *      1. Invalid operation
83  *      2. An operation that fails to execute
84  *      3. Invalid state
85  * The VM will attempt to return an invalid context.
86  * If the VM encounters an operation that it does not understand, the runtime's abort function will be executed.
87  */
88 der_vm_context_t der_vm_execute(const der_vm_context_t context, CEQueryOperation_t op);
89 
90 /*!
91  * @function der_vm_execute_nocopy
92  * Returns a new context that is derived by applying the op to the passed in context
93  *
94  * @param context
95  * Context to execute against
96  *
97  * @param op
98  * An operation to be performed against the context
99  * This op should be created by one of the CEMatch* or CESelect* functions
100  * The operation may be modified after execution and should not be re-used
101  *
102  * @discussion
103  * If the VM encounters:
104  *      1. Invalid operation
105  *      2. An operation that fails to execute
106  *      3. Invalid state
107  * The VM will attempt to return an invalid context.
108  * If the VM encounters an operation that it does not understand, the runtime's abort function will be executed.
109  */
110 der_vm_context_t der_vm_execute_nocopy(const der_vm_context_t context, const CEQueryOperation_t* op);
111 
112 /*!
113  * @function der_vm_execute_seq_nocopy
114  * Returns a new context that is derived by applying the operation sequence to the passed in context
115  *
116  * @param context
117  * Context to execute against
118  *
119  * @param query
120  * Operations to be performed against the context, see der_vm_execute_nocopy for more
121  *
122  * @param queryLength
123  * Number of operations in the query
124  *
125  */
126 der_vm_context_t der_vm_execute_seq_nocopy(const der_vm_context_t context, const CEQueryOperation_t *__counted_by(queryLength) query, size_t queryLength);
127 
128 /*!
129  * @typedef der_vm_iteration_context
130  * Iteration context that gets passed in on every call
131  *
132  * @field original
133  * The original DER VM context (the container over which we are iterating)
134  *
135  * @field active
136  * The actively selected DER VM context (i.e. the value)
137  *
138  * @field parent_type
139  * The type of object being iterated over (dictionary or array)
140  *
141  * @field active_type
142  * The type of the selected object
143  *
144  * @field user_data
145  * The object you passed in the call to der_vm_iterate
146  */
147 typedef struct {
148     der_vm_context_t original;
149     der_vm_context_t active;
150     CEType_t parent_type;
151     CEType_t active_type;
152     void* user_data;
153 } der_vm_iteration_context;
154 
155 /*!
156  * @typedef der_vm_iteration_callback
157  *
158  * @brief Function definition for the callback that der_vm_iterate uses
159  *
160  * @param ctx The information about the iterable is stored here
161  */
162 typedef bool (*der_vm_iteration_callback)(der_vm_iteration_context ctx);
163 
164 
165 
166 /*!
167  * @function der_vm_iterate
168  * @brief Iterates over a DER container, caliing the callback for every element
169  *
170  * @param context The context that points to a container
171  * @param user_data This will be passed in verbatim in the der_vm_iteration_context
172  * @param callback This function is called for every element
173  *
174  * @returns kCENoError if the function exited normally
175  */
176 CEError_t der_vm_iterate(const der_vm_context_t context, void* user_data, der_vm_iteration_callback callback);
177 
178 #ifdef __BLOCKS__
179 /*!
180  * @typedef der_vm_iteration_block
181  *
182  * @brief Function definition for the callback that der_vm_iterate_b uses
183  *
184  * @param ctx The information about the iterable is stored here, you may modify it
185  */
186 typedef bool (^der_vm_iteration_block)(der_vm_iteration_context* ctx);
187 
188 /*!
189  * @function der_vm_iterate_b
190  * @brief Iterates over a DER container, calling the block for every element
191  * @note dev_vm_iterate is implemented using the block interface. Using this function directly is more efficient.
192  * @param context The context that points to a container
193  * @param callback This block is called for every element
194  *
195  * @returns kCENoError if the function exited normally
196  */
197 CEError_t der_vm_iterate_b(const der_vm_context_t* context, der_vm_iteration_block callback);
198 #endif
199 
200 /*!
201  * @function der_vm_context_is_valid
202  * Returns a boolean indication if a particular context is valid
203  *
204  * @param context
205  * The context in question
206  *
207  * @discussion
208  * It is generally safe to execute any operation against an invalid context
209  * However the resulting context will also be invalid
210  */
211 bool der_vm_context_is_valid(const der_vm_context_t context);
212 
213 /*!
214  * @function der_vm_CEType_from_context
215  * Returns a CEType_t corresponding to the item currently pointed to by the context's DER state
216  *
217  * @param context
218  * The context in question
219  * @param tag
220  * Nullable pointer to where to store the decoded DER tag
221  */
222 CEType_t der_vm_CEType_from_context(const der_vm_context_t context, ccder_tag* tag);
223 
224 /*!
225  * @function der_vm_CEType_from_ccder_tag
226  * Returns a CEType_t corresponding to the tag value, without touching the context's DER state
227  *
228  * @param context
229  * The context in question
230  * @param tag
231  * Nullable pointer to where to store the decoded DER tag
232  */
233 CEType_t der_vm_CEType_from_ccder_tag(const der_vm_context_t context, ccder_tag tag);
234 
235 /*!
236  * @function der_vm_integer_from_context
237  * Returns the number selected by the current context
238  */
239 int64_t der_vm_integer_from_context(const der_vm_context_t context);
240 
241 /*!
242  * @function der_vm_string_from_context
243  * Returns the string selected by the current context
244  */
245 CEBuffer der_vm_string_from_context(const der_vm_context_t context);
246 
247 /*!
248  * @function der_vm_bool_from_context
249  * Returns the bool selected by the current context
250  */
251 bool der_vm_bool_from_context(const der_vm_context_t context);
252 
253 /*!
254  * @function der_vm_data_from_context
255  * Returns the data selected by the current context
256  */
257 CEBuffer der_vm_data_from_context(const der_vm_context_t context);
258 
259 /*!
260  * @function der_vm_buffer_from_context
261  * Returns the content described by the tag in the context
262  */
263 CEBuffer der_vm_buffer_from_context(const der_vm_context_t context);
264 
265 /*!
266  * @function CEBuffer_cmp
267  * Does a memcmp like match between two CEBuffers
268  */
269 int CEBuffer_cmp(const CEBuffer left, const CEBuffer right);
270 
271 #endif
272