]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si_77_SecAccessControl.c
1 /*
2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <Security/SecItem.h>
26 #include <Security/SecItemPriv.h>
27 #include <Security/SecAccessControl.h>
28 #include <Security/SecAccessControlPriv.h>
29 #include <Security/SecInternal.h>
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/array_size.h>
32 #include <utilities/der_plist.h>
33 #include <libaks_acl_cf_keys.h>
34 #include <ACMDefs.h>
35 #include <ACMAclDefs.h>
36
37 #if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR)
38 #define USE_KEYSTORE 1
39 #elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
40 #define USE_KEYSTORE 1
41 #else /* no keystore on this platform */
42 #define USE_KEYSTORE 0
43 #endif
44
45 #if USE_KEYSTORE
46 #include <Security/SecRandom.h>
47 #include <securityd/SecDbItem.h>
48 #include <coreauthd_spi.h>
49 #include <corecrypto/ccder.h>
50 #endif
51
52 #include "Security_regressions.h"
53
54 #if LA_CONTEXT_IMPLEMENTED
55 static bool aks_consistency_test(bool currentAuthDataFormat, kern_return_t expectedAksResult, SecAccessControlRef access_control, CFDataRef acm_context);
56 static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes);
57 static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes);
58 static int aks_crypt_acl(CFTypeRef operation, keybag_handle_t keybag,
59 keyclass_t keyclass, uint32_t textLength, const uint8_t *source,
60 CFMutableDataRef dest, CFDataRef auth_data, CFDataRef acm_context, CFDataRef caller_access_groups);
61 #endif
62
63 static void tests(void)
64 {
65 CFAllocatorRef allocator = kCFAllocatorDefault;
66 CFTypeRef protection = kSecAttrAccessibleAlwaysPrivate;
67 CFErrorRef error = NULL;
68
69 // Simple API tests:
70
71 // ACL with protection only
72 SecAccessControlRef acl = SecAccessControlCreateWithFlags(allocator, protection, 0, &error);
73 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
74 CFReleaseNull(error);
75 CFReleaseNull(acl);
76
77 // ACL with flags only (not allowed)
78 #pragma clang diagnostic push
79 #pragma clang diagnostic ignored "-Wnonnull"
80 // NULL passed as 'protection' newly generates a warning, we need to suppress it in order to compile
81 acl = SecAccessControlCreateWithFlags(allocator, NULL, kSecAccessControlUserPresence, &error);
82 #pragma clang diagnostic pop
83 ok(acl == NULL, "SecAccessControlCreateWithFlags");
84 CFReleaseNull(error);
85 CFReleaseNull(acl);
86
87 // ACL with protection and kSecAccessControlTouchIDCurrentSet
88 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlTouchIDCurrentSet, &error);
89 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
90 CFReleaseNull(error);
91 CFReleaseNull(acl);
92
93 // ACL with protection and flags
94 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlTouchIDAny | kSecAccessControlDevicePasscode | kSecAccessControlOr, &error);
95 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
96 CFReleaseNull(error);
97 CFReleaseNull(acl);
98
99 // ACL with protection and flags
100 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlTouchIDAny | kSecAccessControlDevicePasscode | kSecAccessControlAnd, &error);
101 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
102 CFReleaseNull(error);
103 CFReleaseNull(acl);
104
105 // ACL with protection and flags
106 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlTouchIDAny | kSecAccessControlDevicePasscode | kSecAccessControlAnd | kSecAccessControlApplicationPassword, &error);
107 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
108 CFReleaseNull(error);
109 CFReleaseNull(acl);
110
111 // ACL with protection and kSecAccessControlApplicationPassword
112 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlApplicationPassword, &error);
113 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
114 CFReleaseNull(error);
115 CFReleaseNull(acl);
116
117 // ACL with protection and, kSecAccessControlUserPresence can be in combination with kSecAccessControlApplicationPassword and kSecAccessControlPrivateKeyUsage
118 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlUserPresence | kSecAccessControlApplicationPassword | kSecAccessControlPrivateKeyUsage, &error);
119 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
120 CFReleaseNull(error);
121 CFReleaseNull(acl);
122
123 // negative test of ACL with protection and, kSecAccessControlUserPresence can be in combination with kSecAccessControlApplicationPassword and kSecAccessControlPrivateKeyUsage
124 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlUserPresence | kSecAccessControlTouchIDAny, &error);
125 ok(acl == NULL, "SecAccessControlCreateWithFlag wrong combination of flags");
126 CFReleaseNull(error);
127 CFReleaseNull(acl);
128
129 // ACL with protection and flags
130 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlUserPresence, &error);
131 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
132 CFReleaseNull(error);
133
134 // Extended API tests:
135
136 // Check created ACL
137 CFTypeRef aclProtection = SecAccessControlGetProtection(acl);
138 is(aclProtection, protection, "SecAccessControlGetProtection");
139
140 SecAccessConstraintRef aclConstraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt);
141 // Check created ACL
142 ok(aclConstraint != NULL && isDictionary(aclConstraint), "SecAccessControlGetConstraint");
143 eq_cf(CFDictionaryGetValue(aclConstraint, CFSTR(kACMKeyAclConstraintPolicy)), CFSTR(kACMPolicyDeviceOwnerAuthentication), "SecAccessControlGetConstraint");
144
145 CFReleaseNull(acl);
146
147 // Simple SPI tests:
148
149 // Empty ACL
150 acl = SecAccessControlCreate(allocator, &error);
151 ok(acl != NULL, "SecAccessControlCreate: %@", error);
152 CFReleaseNull(error);
153
154 // ACL protection
155 bool result = SecAccessControlSetProtection(acl, protection, &error);
156 ok(result, "SecAccessControlSetProtection: %@", error);
157 CFReleaseNull(error);
158
159 aclProtection = SecAccessControlGetProtection(acl);
160 // ACL protection
161 is(aclProtection, protection, "SecAccessControlGetProtection");
162
163 // Policy constraint
164 SecAccessConstraintRef policy = SecAccessConstraintCreatePolicy(allocator, CFSTR(kACMPolicyDeviceOwnerAuthentication), &error);
165 ok(policy != NULL, "SecAccessConstraintCreatePolicy: %@", error);
166 ok(isDictionary(policy), "SecAccessConstraintCreatePolicy");
167 is(CFDictionaryGetValue(policy, CFSTR(kACMKeyAclConstraintPolicy)), CFSTR(kACMPolicyDeviceOwnerAuthentication), "SecAccessConstraintCreatePolicy");
168 CFReleaseNull(error);
169 CFReleaseNull(policy);
170
171 // Passcode constraint
172 SecAccessConstraintRef passcode = SecAccessConstraintCreatePasscode(allocator);
173 ok(passcode != NULL && isDictionary(passcode), "SecAccessConstraintCreatePasscode");
174 is(CFDictionaryGetValue(passcode, CFSTR(kACMKeyAclConstraintUserPasscode)), kCFBooleanTrue, "SecAccessConstraintCreatePasscode");
175 // CFReleaseNull(passcode); passcode will be used in later tests
176
177 CFUUIDRef uuid = CFUUIDCreate(allocator);
178 CFStringRef uuidString = CFUUIDCreateString(allocator, uuid);
179 CFDataRef uuidData = CFStringCreateExternalRepresentation(allocator, uuidString, kCFStringEncodingUTF8, 0);
180 SecAccessConstraintRef touchID = SecAccessConstraintCreateTouchIDCurrentSet(allocator, uuidData, uuidData);
181 // TouchID constraint
182 ok(touchID != NULL, "SecAccessConstraintCreateTouchID: %@", error);
183 ok(isDictionary(touchID), "SecAccessConstraintCreateTouchID");
184 ok(CFDictionaryGetValue(touchID, CFSTR(kACMKeyAclConstraintBio)), "SecAccessConstraintCreateTouchID");
185 CFDictionaryRef bioRef = CFDictionaryGetValue(touchID, CFSTR(kACMKeyAclConstraintBio));
186 ok(isDictionary(bioRef), "SecAccessConstraintCreateTouchID");
187 is(CFDictionaryGetValue(bioRef, CFSTR(kACMKeyAclParamBioCatacombUUID)), uuidData, "SecAccessConstraintCreateTouchID");
188 is(CFDictionaryGetValue(bioRef, CFSTR(kACMKeyAclParamBioDatabaseHash)), uuidData, "SecAccessConstraintCreateTouchID");
189 CFReleaseNull(error);
190 CFReleaseNull(touchID);
191 CFReleaseNull(uuidData);
192 CFReleaseNull(uuidString);
193 CFReleaseNull(uuid);
194
195 uuid = CFUUIDCreate(allocator);
196 uuidString = CFUUIDCreateString(allocator, uuid);
197 uuidData = CFStringCreateExternalRepresentation(allocator, uuidString, kCFStringEncodingUTF8, 0);
198 touchID = SecAccessConstraintCreateTouchIDAny(allocator, uuidData);
199 // TouchID constraint
200 ok(touchID != NULL, "SecAccessConstraintCreateTouchID: %@", error);
201 ok(isDictionary(touchID), "SecAccessConstraintCreateTouchID");
202 ok(CFDictionaryGetValue(touchID, CFSTR(kACMKeyAclConstraintBio)), "SecAccessConstraintCreateTouchID");
203 bioRef = CFDictionaryGetValue(touchID, CFSTR(kACMKeyAclConstraintBio));
204 ok(isDictionary(bioRef), "SecAccessConstraintCreateTouchID");
205 is(CFDictionaryGetValue(bioRef, CFSTR(kACMKeyAclParamBioCatacombUUID)), uuidData, "SecAccessConstraintCreateTouchID");
206 CFReleaseNull(error);
207 // CFReleaseNull(touchID); touchID will be used in later tests
208 CFReleaseNull(uuidData);
209 CFReleaseNull(uuidString);
210 CFReleaseNull(uuid);
211
212 // KofN constraint
213 CFTypeRef constraints_array[] = { passcode, touchID };
214 CFArrayRef constraintsArray = CFArrayCreate(allocator, constraints_array, array_size(constraints_array), &kCFTypeArrayCallBacks);
215 SecAccessConstraintRef kofn = SecAccessConstraintCreateKofN(allocator, 1, constraintsArray, &error);
216 ok(kofn != NULL, "SecAccessConstraintCreateKofN: %@", error);
217 ok(isDictionary(kofn), "SecAccessConstraintCreateKofN");
218 CFTypeRef kofnConstraint = CFDictionaryGetValue(kofn, CFSTR(kACMKeyAclConstraintKofN));
219 ok(kofnConstraint != NULL && isDictionary(kofnConstraint), "SecAccessConstraintCreateKofN");
220 CFNumberRef required = CFNumberCreateWithCFIndex(allocator, 1);
221 is(CFDictionaryGetValue(kofnConstraint, CFSTR(kACMKeyAclParamKofN)), required, "SecAccessConstraintCreateKofN");
222 ok(CFDictionaryGetValue(kofnConstraint, CFSTR(kACMKeyAclConstraintBio)), "SecAccessConstraintCreateKofN");
223 is(CFDictionaryGetValue(kofnConstraint, CFSTR(kACMKeyAclConstraintUserPasscode)), kCFBooleanTrue, "SecAccessConstraintCreateKofN");
224 CFReleaseNull(error);
225 CFReleaseNull(kofn);
226 CFReleaseNull(required);
227 CFReleaseNull(constraintsArray);
228 CFReleaseNull(passcode);
229
230 // Add ACL constraint for operation
231 result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDecrypt, touchID, &error);
232 ok(result, "SecAccessControlAddConstraintForOperation: %@", error);
233 CFReleaseNull(error);
234
235 // Get ACL operation constraint
236 SecAccessConstraintRef constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt);
237 is(constraint, touchID, "SecAccessControlGetConstraint");
238 CFReleaseNull(touchID);
239
240 // Add ACL constraint for operation (kCFBooleanTrue)
241 result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDecrypt, kCFBooleanTrue, &error);
242 ok(result, "SecAccessControlAddConstraintForOperation: %@", error);
243 CFReleaseNull(error);
244
245 // Get ACL operation constraint (kCFBooleanTrue)
246 constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt);
247 is(constraint, kCFBooleanTrue, "SecAccessControlGetConstraint");
248
249 // Get ACL constraints
250 CFDictionaryRef constraints = SecAccessControlGetConstraints(acl);
251 ok(constraints != NULL && isDictionary(constraints), "SecAccessControlGetConstraints");
252 // Get ACL constraints
253 is(CFDictionaryGetValue(constraints, kAKSKeyOpDecrypt), kCFBooleanTrue, "SecAccessControlGetConstraints");
254
255 // ACL export and import
256 CFDataRef aclData = SecAccessControlCopyData(acl);
257 ok(aclData != NULL, "SecAccessControlCopyData");
258 SecAccessControlRef aclCopy = SecAccessControlCreateFromData(allocator, aclData, &error);
259 ok(aclCopy != NULL, "SecAccessControlCopyData: %@", error);
260 ok(CFEqual(aclCopy, acl), "SecAccessControlCopyData");
261 CFReleaseNull(error);
262 CFReleaseNull(aclCopy);
263 CFReleaseNull(aclData);
264
265 // Extended SPI tests:
266
267 // kAKSKeyDefaultOpAcl
268 result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, &error);
269 ok(result, "SecAccessControlAddConstraintForOperation: %@", error);
270 constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt);
271 is(constraint, kCFBooleanTrue, "SecAccessControlRemoveConstraintForOperation");
272 CFReleaseNull(error);
273
274 CFReleaseNull(acl);
275
276 #if LA_CONTEXT_IMPLEMENTED
277 // AKS consistency test:
278
279 acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlUserPresence, &error);
280 ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error);
281 CFReleaseNull(error);
282
283 SKIP: {
284 skip("SecAccessControlCreateWithFlags failed", 7, acl != NULL);
285
286 CFDataRef acm_context = NULL;
287 CFTypeRef auth_handle = NULL;
288
289 auth_handle = LACreateNewContextWithACMContext(NULL, &error);
290 ok(auth_handle != NULL, "LACreateNewContextWithACMContext: %@", error);
291 CFReleaseNull(error);
292
293 SKIP: {
294 skip("LACreateNewContextWithACMContext failed", 6, auth_handle != NULL);
295
296 acm_context = LACopyACMContext(auth_handle, &error);
297 ok(acm_context != NULL, "LACopyACMContext: %@", error);
298 CFReleaseNull(error);
299
300 CFReleaseNull(auth_handle);
301
302 SKIP: {
303 skip("LACopyACMContext failed", 5, acm_context != NULL);
304
305 ok(aks_consistency_test(true, kAKSReturnPolicyError, acl, acm_context), "AKS consistency negative test (current auth_data format)");
306 ok(aks_consistency_test(false, kAKSReturnPolicyError, acl, acm_context), "AKS consistency negative test (old auth_data format)");
307
308 bool decrypt_enabled = false;
309 CFDictionaryRef constraints = SecAccessControlGetConstraints(acl);
310 if (constraints) {
311 CFMutableDictionaryRef new_constraints = CFDictionaryCreateMutableCopy(NULL, 0, constraints);
312 if (new_constraints) {
313 CFDictionarySetValue(new_constraints, kAKSKeyOpDecrypt, kCFBooleanTrue);
314 SecAccessControlSetConstraints(acl, new_constraints);
315 CFReleaseSafe(new_constraints);
316 decrypt_enabled = true;
317 }
318 }
319 ok(decrypt_enabled, "Cannot enable decrypt operation for AKS consistency positive tests");
320
321 ok(aks_consistency_test(true, kAKSReturnSuccess, acl, acm_context), "AKS consistency positive test (current auth_data format)");
322 ok(aks_consistency_test(false, kAKSReturnSuccess, acl, acm_context), "AKS consistency positive test (old auth_data format)");
323
324 CFReleaseNull(acm_context);
325 }
326 }
327
328 CFReleaseNull(acl);
329 }
330 #endif
331
332 // kSecAccessControlPrivateKeyUsage
333 acl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, kSecAccessControlPrivateKeyUsage | kSecAccessControlDevicePasscode, NULL);
334 ok(acl, "kSecAccessControlPrivateKeyUsage ACL create with constraint");
335 ok(!SecAccessControlGetConstraint(acl, kAKSKeyOpEncrypt), "kAKSKeyOpEncrypt constraint");
336 ok(!SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt), "kAKSKeyOpDecrypt constraint");
337 ok(constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDelete), "kAKSKeyOpDelete constraint");
338 is(constraint, kCFBooleanTrue, "kAKSKeyOpDelete constraint value");
339 ok(constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpSign), "kAKSKeyOpSign constraint");
340 ok(constraint && isDictionary(constraint), "kAKSKeyOpSign constraint value");
341 CFReleaseNull(acl);
342
343 acl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, kSecAccessControlPrivateKeyUsage, NULL);
344 ok(acl, "kSecAccessControlPrivateKeyUsage ACL create without constraint");
345 ok(!SecAccessControlGetConstraint(acl, kAKSKeyOpEncrypt), "kAKSKeyOpEncrypt constraint");
346 ok(!SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt), "kAKSKeyOpDecrypt constraint");
347 ok(constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDelete), "kAKSKeyOpDelete constraint");
348 is(constraint, kCFBooleanTrue, "kAKSKeyOpDelete constraint value");
349 ok(constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpSign), "kAKSKeyOpSign constraint");
350 is(constraint, kCFBooleanTrue, "kAKSKeyOpSign constraint value");
351 CFReleaseNull(acl);
352 }
353
354 #if LA_CONTEXT_IMPLEMENTED
355
356 static bool aks_consistency_test(bool currentAuthDataFormat, kern_return_t expectedAksResult, SecAccessControlRef access_control, CFDataRef acm_context)
357 {
358 bool result = false;
359
360 const uint32_t bulkKeySize = 32;
361 const uint32_t maxKeyWrapOverHead = 8 + 32;
362 uint8_t bulkKey[bulkKeySize];
363 CFMutableDataRef bulkKeyWrapped = CFDataCreateMutable(NULL, 0);
364 CFDataSetLength(bulkKeyWrapped, bulkKeySize + maxKeyWrapOverHead);
365 CFMutableDataRef bulkKeyUnwrapped = CFDataCreateMutable(NULL, 0);
366 CFDataSetLength(bulkKeyUnwrapped, bulkKeySize);
367
368 CFDataRef auth_data = NULL;
369 CFMutableDictionaryRef auth_attribs = NULL;
370
371 require_noerr_string(SecRandomCopyBytes(kSecRandomDefault, bulkKeySize, bulkKey), out, "SecRandomCopyBytes failed");
372
373 auth_attribs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
374 if (currentAuthDataFormat) {
375 auth_data = kc_create_auth_data(access_control, auth_attribs);
376 }
377 else {
378 auth_data = kc_copy_constraints_data(access_control, auth_attribs);
379 }
380
381 require_string(aks_crypt_acl(kAKSKeyOpEncrypt, KEYBAG_DEVICE, key_class_dk, bulkKeySize, bulkKey, bulkKeyWrapped,
382 auth_data, acm_context, NULL) == kAKSReturnSuccess, out, "kAKSKeyOpEncrypt failed");
383
384 uint32_t blobLenWrapped = (uint32_t)CFDataGetLength(bulkKeyWrapped);
385 const uint8_t *cursor = CFDataGetBytePtr(bulkKeyWrapped);
386
387 require_string(aks_crypt_acl(kAKSKeyOpDecrypt, KEYBAG_DEVICE, key_class_dk, blobLenWrapped, cursor, bulkKeyUnwrapped,
388 auth_data, acm_context, NULL) == expectedAksResult, out, "kAKSKeyOpDecrypt finished with unexpected result");
389
390 result = true;
391
392 out:
393 CFReleaseSafe(bulkKeyUnwrapped);
394 CFReleaseSafe(bulkKeyWrapped);
395 CFReleaseSafe(auth_data);
396 CFReleaseSafe(auth_attribs);
397
398 return result;
399 }
400
401 static bool merge_der_in_to_data(const void *der1, size_t der1_len, const void *der2, size_t der2_len, CFMutableDataRef mergedData)
402 {
403 bool result = false;
404 CFPropertyListRef dict1 = NULL;
405 CFPropertyListRef dict2 = NULL;
406
407 der_decode_plist(NULL, kCFPropertyListImmutable, &dict1, NULL, der1, der1 + der1_len);
408 der_decode_plist(NULL, kCFPropertyListImmutable, &dict2, NULL, der2, der2 + der2_len);
409 if (dict1 && dict2) {
410 CFMutableDictionaryRef result_dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict1);
411 CFDictionaryForEach(dict2, ^(const void *key, const void *value) {
412 CFDictionaryAddValue(result_dict, key, value);
413 });
414
415 CFDataSetLength(mergedData, 0);
416 CFDataRef der_data = CFPropertyListCreateDERData(kCFAllocatorDefault, result_dict, NULL);
417 if (der_data) {
418 CFDataAppend(mergedData, der_data);
419 CFRelease(der_data);
420 result = CFDataGetLength(mergedData) > 0;
421 }
422 CFRelease(result_dict);
423 }
424
425 CFReleaseSafe(dict1);
426 CFReleaseSafe(dict2);
427 return result;
428 }
429
430 static int aks_crypt_acl(CFTypeRef operation, keybag_handle_t keybag,
431 keyclass_t keyclass, uint32_t textLength, const uint8_t *source,
432 CFMutableDataRef dest, CFDataRef auth_data, CFDataRef acm_context, CFDataRef caller_access_groups)
433 {
434 int aks_return = kAKSReturnSuccess;
435 void *params = NULL, *der = NULL;
436 const uint8_t *access_groups = caller_access_groups?CFDataGetBytePtr(caller_access_groups):NULL;
437 size_t params_len = 0, der_len = 0, access_groups_len = caller_access_groups?CFDataGetLength(caller_access_groups):0;
438 aks_ref_key_t key_handle = NULL;
439
440 if (CFEqual(operation, kAKSKeyOpEncrypt)) {
441 aks_operation_optional_params(0, 0, CFDataGetBytePtr(auth_data), CFDataGetLength(auth_data),
442 CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), &params, &params_len);
443
444 require_noerr_quiet(aks_return = aks_ref_key_create(keybag, keyclass, key_type_sym, params, params_len, &key_handle), out);
445 require_noerr_quiet(aks_return = aks_ref_key_encrypt(key_handle, params, params_len, source, textLength, &der, &der_len), out);
446 size_t key_blob_len;
447 const void *key_blob = aks_ref_key_get_blob(key_handle, &key_blob_len);
448 require_action_string(key_blob, out, aks_return = kAKSReturnError, "aks_ref_key_get_blob failed");
449 require_action_string(merge_der_in_to_data(der, der_len, key_blob, key_blob_len, dest), out, aks_return = kAKSReturnError, "merge_der_in_to_data failed");
450
451 } else if (CFEqual(operation, kAKSKeyOpDecrypt)) {
452 aks_operation_optional_params(access_groups, access_groups_len, 0, 0,
453 CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), (void**)&params, &params_len);
454 require_noerr_quiet(aks_return = aks_ref_key_create_with_blob(keybag, source, textLength, &key_handle), out);
455 require_noerr_quiet(aks_return = aks_ref_key_decrypt(key_handle, params, params_len, source, textLength, &der, &der_len), out);
456 require_action_string(der, out, aks_return = kAKSReturnError, "aks_ref_key_decrypt failed");
457
458 CFPropertyListRef decoded_data = NULL;
459 der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_data, NULL, der, der + der_len);
460 require_action_string(decoded_data, out, aks_return = kAKSReturnError, "der_decode_plist failed");
461 if (CFGetTypeID(decoded_data) == CFDataGetTypeID()) {
462 CFDataSetLength(dest, 0);
463 CFDataAppend(dest, decoded_data);
464 CFRelease(decoded_data);
465 }
466 else {
467 CFRelease(decoded_data);
468 require_action_string(false, out, aks_return = kAKSReturnError, "wrong decoded data type");
469 }
470 }
471
472 out:
473 if (key_handle) {
474 aks_ref_key_free(&key_handle);
475 }
476 if (params) {
477 free(params);
478 }
479 if (der) {
480 free(der);
481 }
482 return aks_return;
483 }
484
485 static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes)
486 {
487 CFDictionaryRef constraints = SecAccessControlGetConstraints(access_control);
488 CFMutableDictionaryRef auth_data = CFDictionaryCreateMutableCopy(NULL, 0, auth_attributes);
489 CFDictionarySetValue(auth_data, kAKSKeyAcl, constraints);
490 CFDataRef encoded = CFPropertyListCreateDERData(kCFAllocatorDefault, auth_data, NULL);
491 CFReleaseSafe(auth_data);
492 return encoded;
493 }
494
495 static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes)
496 {
497 CFDictionaryRef constraints = SecAccessControlGetConstraints(access_control);
498 CFMutableDictionaryRef auth_data = CFDictionaryCreateMutableCopy(NULL, 0, constraints);
499 if (auth_attributes) {
500 CFDictionaryForEach(auth_attributes, ^(const void *key, const void *value) {
501 CFDictionaryAddValue(auth_data, key, value);
502 });
503 }
504
505 CFDataRef encoded = CFPropertyListCreateDERData(kCFAllocatorDefault, auth_data, NULL);
506 CFReleaseSafe(auth_data);
507 return encoded;
508 }
509
510 #endif
511
512 int si_77_SecAccessControl(int argc, char *const *argv)
513 {
514 #if LA_CONTEXT_IMPLEMENTED
515 plan_tests(71);
516 #else
517 plan_tests(63);
518 #endif
519
520 tests();
521
522 return 0;
523 }