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