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