2 * Copyright (c) 2015 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include "keychain_regressions.h"
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <Security/Security.h>
28 #include <Security/SecBase.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecKeychainPriv.h>
31 #include <TargetConditionals.h>
32 #include <Security/cssmapi.h>
35 #include "kc-30-xara-item-helpers.h"
36 #include "kc-30-xara-key-helpers.h"
37 #include "kc-30-xara-upgrade-helpers.h"
41 #pragma clang diagnostic push
42 #pragma clang diagnostic ignored "-Wunused-variable"
43 #pragma clang diagnostic ignored "-Wunused-function"
45 /* Test basic add delete update copy matching stuff. */
48 /* Standard memory functions required by CSSM. */
49 static void *cssmMalloc(CSSM_SIZE size
, void *allocRef
) { return malloc(size
); }
50 static void cssmFree(void *mem_ptr
, void *allocRef
) { free(mem_ptr
); return; }
51 static void *cssmRealloc(void *ptr
, CSSM_SIZE size
, void *allocRef
) { return realloc( ptr
, size
); }
52 static void *cssmCalloc(uint32 num
, CSSM_SIZE size
, void *allocRef
) { return calloc( num
, size
); }
53 static CSSM_API_MEMORY_FUNCS memFuncs
= { cssmMalloc
, cssmFree
, cssmRealloc
, cssmCalloc
, NULL
};
55 static CSSM_DL_DB_HANDLE
initializeDL() {
56 CSSM_VERSION version
= { 2, 0 };
57 CSSM_DL_DB_HANDLE dldbHandle
;
58 CSSM_GUID myGuid
= { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
59 CSSM_PVC_MODE pvcPolicy
= CSSM_PVC_NONE
;
61 ok_status(CSSM_Init(&version
, CSSM_PRIVILEGE_SCOPE_NONE
, &myGuid
, CSSM_KEY_HIERARCHY_NONE
, &pvcPolicy
, NULL
), "cssm_init");
62 ok_status(CSSM_ModuleLoad(&gGuidAppleFileDL
, CSSM_KEY_HIERARCHY_NONE
, NULL
, NULL
), "module_load");
63 ok_status(CSSM_ModuleAttach(&gGuidAppleFileDL
, &version
, &memFuncs
, 0, CSSM_SERVICE_DL
, 0, CSSM_KEY_HIERARCHY_NONE
, NULL
, 0, NULL
, &dldbHandle
.DLHandle
), "module_attach");
67 #define initializeDLTests 3
69 static void unloadDL(CSSM_DL_DB_HANDLE
* dldbHandle
) {
70 ok_status(CSSM_ModuleDetach(dldbHandle
->DLHandle
), "detach");
71 ok_status(CSSM_ModuleUnload(&gGuidAppleFileDL
, NULL
, NULL
), "unload");
72 ok_status(CSSM_Terminate(), "terminate");
74 #define unloadDLTests 3
76 static void modifyAttributeInKeychain(char * name
, CSSM_DL_DB_HANDLE dldbHandle
, char * keychainName
, CSSM_DB_RECORDTYPE recordType
, char* attributeName
, char* newValue
, size_t len
) {
77 CSSM_RETURN status
= CSSM_OK
;
78 ok_status(CSSM_DL_DbOpen(dldbHandle
.DLHandle
, keychainName
,
80 CSSM_DB_ACCESS_READ
| CSSM_DB_ACCESS_WRITE
,
81 NULL
, /* Access cred? */
82 NULL
, /* Open Parameters? */
83 &dldbHandle
.DBHandle
), "%s: CSSM_DL_DbOpen", name
);
85 CSSM_QUERY queryAll
= {};
86 queryAll
.RecordType
= recordType
;
88 CSSM_HANDLE results
= 0;
90 CSSM_DB_UNIQUE_RECORD_PTR uniqueIdPtr
= NULL
;
92 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes
= {};
93 attributes
.NumberOfAttributes
= 1;
94 attributes
.AttributeData
= malloc(sizeof(CSSM_DB_ATTRIBUTE_DATA
) * attributes
.NumberOfAttributes
);
95 attributes
.AttributeData
[0].Info
.Label
.AttributeName
= attributeName
;
96 attributes
.AttributeData
[0].Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
98 attributes
.AttributeData
[0].NumberOfValues
= 1;
99 attributes
.AttributeData
[0].Value
= malloc(sizeof(CSSM_DATA
)*attributes
.AttributeData
[0].NumberOfValues
);
102 status
= CSSM_DL_DataGetFirst(dldbHandle
, &queryAll
, &results
, &attributes
, &data
, &uniqueIdPtr
);
103 while(status
== CSSM_OK
) {
104 // I'm sure it has one thing and that thing needs to change.
105 attributes
.AttributeData
[0].Value
[0].Data
= (void*)newValue
;
106 attributes
.AttributeData
[0].Value
[0].Length
= strlen(newValue
);
108 CSSM_DL_DataModify(dldbHandle
,
109 attributes
.DataRecordType
,
112 NULL
, // no data modification
113 CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
115 CSSM_DL_FreeUniqueRecord(dldbHandle
, uniqueIdPtr
);
116 status
= CSSM_DL_DataGetNext(dldbHandle
, results
, &attributes
, &data
, &uniqueIdPtr
);
118 ok_status(CSSM_DL_DbClose(dldbHandle
), "%s: CSSM_DL_DbClose", name
);
120 #define modifyAttributeInKeychainTests 2
122 static void testAttackItem(CSSM_DL_DB_HANDLE dldbHandle
) {
123 char * name
= "testAttackItem";
124 secdebugfunc("integrity", "************************************* %s", name
);
126 SecKeychainRef kc
= newKeychain(name
);
127 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 0);
129 makeItemWithIntegrity(name
, kc
, kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
130 SecKeychainItemRef item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
133 char * modification
= "evil_application";
134 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_GENERIC_PASSWORD
, "PrintName", modification
, strlen(modification
));
136 kc
= openKeychain(name
);
137 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 0);
138 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
140 #define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
142 static void testAttackKey(CSSM_DL_DB_HANDLE dldbHandle
) {
143 char * name
= "testAttackKey";
144 secdebugfunc("integrity", "************************************* %s", name
);
146 SecKeychainRef kc
= newKeychain(name
);
147 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 0);
149 makeKeyWithIntegrity(name
, kc
, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
150 SecKeychainItemRef item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 1);
153 char * modification
= "evil_application";
154 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_SYMMETRIC_KEY
, "Label", modification
, strlen(modification
));
156 kc
= openKeychain(name
);
157 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 0);
158 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
160 #define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
163 static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle
) {
164 char * name
= "testAddAfterCorruptItem";
165 secdebugfunc("integrity", "************************************* %s", name
);
167 SecKeychainRef kc
= newKeychain(name
);
168 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 0);
170 makeCustomItemWithIntegrity(name
, kc
, kSecClassGenericPassword
, CFSTR("test_label"), CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
171 SecKeychainItemRef item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
174 makeDuplicateItem(name
, kc
, kSecClassGenericPassword
);
177 char * modification
= "evil_application";
178 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_GENERIC_PASSWORD
, "PrintName", modification
, strlen(modification
));
180 kc
= openKeychain(name
);
181 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 0);
183 makeCustomItemWithIntegrity(name
, kc
, kSecClassGenericPassword
, CFSTR("evil_application"), CFSTR("d2aa97b30a1f96f9e61fcade2b00d9f4284976a83a5b68392251ee5ec827f8cc"));
184 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
185 makeCustomDuplicateItem(name
, kc
, kSecClassGenericPassword
, CFSTR("evil_application"));
186 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
188 #define testAddAfterCorruptItemTests (newKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeDuplicateItemTests \
189 + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1)
191 static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle
) {
192 char * name
= "testAddAfterCorruptKey";
193 secdebugfunc("integrity", "************************************* %s", name
);
195 SecKeychainRef kc
= newKeychain(name
);
196 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 0);
197 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 0);
198 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 0);
200 // Make a symmetric key
201 makeCustomKeyWithIntegrity(name
, kc
, CFSTR("test_key"), CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
203 SecKeychainItemRef item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 1);
204 makeCustomDuplicateKey(name
, kc
, CFSTR("test_key"));
210 makeCustomKeyPair(name
, kc
, CFSTR("test_key_pair"), &pub
, &priv
);
211 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 1);
212 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 1);
216 ok_status(SecKeychainListRemoveKeychain(&kc
), "%s: SecKeychainListRemoveKeychain", name
);
218 char * modification
= "evil_application";
219 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_SYMMETRIC_KEY
, "PrintName", modification
, strlen(modification
));
220 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_PUBLIC_KEY
, "PrintName", modification
, strlen(modification
));
221 modifyAttributeInKeychain(name
, dldbHandle
, keychainFile
, CSSM_DL_DB_RECORD_PRIVATE_KEY
, "PrintName", modification
, strlen(modification
));
223 kc
= openKeychain(name
);
224 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 0);
225 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 0);
226 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 0);
228 makeCustomKeyWithIntegrity(name
, kc
, CFSTR("evil_application"), CFSTR("ca6d90a0b053113e43bbb67f64030230c96537f77601f66bdf821d8684431dfc"));
229 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 1);
231 makeCustomDuplicateKey(name
, kc
, CFSTR("evil_application"));
233 makeCustomKeyPair(name
, kc
, CFSTR("evil_application"), &pub
, &priv
);
234 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 1);
235 checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 1);
237 // We cannot create a duplicate key pair, so don't try.
240 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
242 #define testAddAfterCorruptKeyTests (newKeychainTests \
243 + checkNTests + checkNTests + checkNTests \
244 + makeCustomKeyWithIntegrityTests + checkNTests + makeCustomDuplicateKeyTests \
245 + makeCustomKeyPairTests + checkNTests + checkNTests \
247 + modifyAttributeInKeychainTests \
248 + modifyAttributeInKeychainTests \
249 + modifyAttributeInKeychainTests \
250 + openKeychainTests \
251 + checkNTests + checkNTests + checkNTests \
252 + makeCustomKeyWithIntegrityTests + checkNTests \
253 + makeCustomDuplicateKeyTests \
254 + makeCustomKeyPairTests + checkNTests + checkNTests \
258 static void testKeychainUpgrade() {
260 sprintf(name
, "testKeychainUpgrade");
261 secdebugfunc("integrity", "************************************* %s", name
);
263 writeOldKeychain(name
, keychainFile
);
264 SecKeychainRef kc
= openCustomKeychain(name
, "test.keychain", "password");
266 SecKeychainItemRef item
;
268 item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
269 checkIntegrityHash(name
, item
, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
270 makeCustomDuplicateItem(name
, kc
, kSecClassGenericPassword
, CFSTR("test_generic"));
272 item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassInternetPassword
), 1);
273 checkIntegrityHash(name
, item
, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
274 makeCustomDuplicateItem(name
, kc
, kSecClassInternetPassword
, CFSTR("test_internet"));
276 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 1);
277 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
279 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 1);
280 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
282 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 1);
283 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
285 // Now close the keychain and open it again
287 kc
= openCustomKeychain(name
, "test.keychain", "password");
289 item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
290 checkIntegrityHash(name
, item
, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
291 makeCustomDuplicateItem(name
, kc
, kSecClassGenericPassword
, CFSTR("test_generic"));
293 item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassInternetPassword
), 1);
294 checkIntegrityHash(name
, item
, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
295 makeCustomDuplicateItem(name
, kc
, kSecClassInternetPassword
, CFSTR("test_internet"));
297 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassSymmetric
), 1);
298 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
300 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPublic
), 1);
301 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
303 item
= checkN(name
, makeQueryKeyDictionary(kc
, kSecAttrKeyClassPrivate
), 1);
304 checkIntegrityHash(name
, (SecKeychainItemRef
) item
, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
306 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
308 #define testKeychainUpgradeTests (openCustomKeychainTests \
309 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
310 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
311 + checkNTests + checkIntegrityHashTests + \
312 + checkNTests + checkIntegrityHashTests + \
313 + checkNTests + checkIntegrityHashTests + \
314 + openCustomKeychainTests \
315 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
316 + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
317 + checkNTests + checkIntegrityHashTests +\
318 + checkNTests + checkIntegrityHashTests +\
319 + checkNTests + checkIntegrityHashTests +\
322 static SecAccessRef
makeUidAccess(uid_t uid
)
324 // make the "uid/gid" ACL subject
325 // this is a CSSM_LIST_ELEMENT chain
326 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector
= {
327 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
, // selector version
328 CSSM_ACL_MATCH_UID
, // set mask: match uids (only)
330 0 // gid (not matched here)
332 CSSM_LIST_ELEMENT subject2
= { NULL
, 0 };
333 subject2
.Element
.Word
.Data
= (UInt8
*)&selector
;
334 subject2
.Element
.Word
.Length
= sizeof(selector
);
335 CSSM_LIST_ELEMENT subject1
= {
336 &subject2
, CSSM_ACL_SUBJECT_TYPE_PROCESS
, CSSM_LIST_ELEMENT_WORDID
339 // rights granted (replace with individual list if desired)
340 CSSM_ACL_AUTHORIZATION_TAG rights
[] = {
341 CSSM_ACL_AUTHORIZATION_ANY
// everything
343 // owner component (right to change ACL)
344 CSSM_ACL_OWNER_PROTOTYPE owner
= {
346 { CSSM_LIST_TYPE_UNKNOWN
, &subject1
, &subject2
},
350 // ACL entries (any number, just one here)
351 CSSM_ACL_ENTRY_INFO acls
[] = {
356 { CSSM_LIST_TYPE_UNKNOWN
, &subject1
, &subject2
},
358 // rights for this entry
359 { sizeof(rights
) / sizeof(rights
[0]), rights
},
366 SecAccessCreateFromOwnerAndACL(&owner
, sizeof(acls
) / sizeof(acls
[0]), acls
, &access
);
370 static void checkAccessLength(const char * name
, SecAccessRef access
, int expected
) {
371 CFArrayRef acllist
= NULL
;
372 ok_status(SecAccessCopyACLList(access
, &acllist
), "%s: SecAccessCopyACLList", name
);
374 // Count the number of non-integrity ACLs in this access
376 CFStringRef output
= NULL
;
379 for(int i
= 0; i
< CFArrayGetCount(acllist
); i
++) {
380 SecACLRef acl
= (SecACLRef
) CFArrayGetValueAtIndex(acllist
, i
);
382 CFArrayRef auths
= SecACLCopyAuthorizations(acl
);
383 CFRange searchrange
= CFRangeMake(0, CFArrayGetCount(auths
));
384 if(!CFArrayContainsValue(auths
, searchrange
, kSecACLAuthorizationIntegrity
) &&
385 !CFArrayContainsValue(auths
, searchrange
, kSecACLAuthorizationPartitionID
)) {
390 CFReleaseNull(auths
);
393 CFReleaseNull(acllist
);
395 is(aclsFound
, expected
, "%s: ACL has correct number of entries", name
);
397 #define checkAccessLengthTests 2
399 static void testUidAccess() {
401 sprintf(name
, "testUidAccess");
402 secdebugfunc("integrity", "************************************* %s", name
);
404 SecAccessRef access
= makeUidAccess(getuid());
406 SecKeychainRef kc
= newKeychain(name
);
407 CFMutableDictionaryRef query
= makeAddItemDictionary(kc
, kSecClassGenericPassword
, CFSTR("test label"));
408 CFDictionarySetValue(query
, kSecAttrAccess
, access
);
410 CFTypeRef result
= NULL
;
411 ok_status(SecItemAdd(query
, &result
), "%s: SecItemAdd", name
);
412 ok(result
!= NULL
, "%s: SecItemAdd returned a result", name
);
414 SecKeychainItemRef item
= checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
416 ok_status(SecKeychainItemSetAccess(item
, access
), "%s: SecKeychainItemSetAccess", name
);
417 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
419 // Check to make sure the ACL stays
421 ok_status(SecKeychainItemCopyAccess(item
, &access
), "%s: SecKeychainItemCopyAccess", name
);
422 checkAccessLength(name
, access
, 2);
424 const char * newPassword
= "newPassword";
425 ok_status(SecKeychainItemModifyContent(item
, NULL
, (UInt32
) strlen(newPassword
), newPassword
), "%s: SecKeychainItemModifyContent", name
);
428 ok_status(SecKeychainItemCopyAccess(item
, &access
), "%s: SecKeychainItemCopyAccess", name
);
429 checkAccessLength(name
, access
, 2);
431 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
433 #define testUidAccessTests (newKeychainTests + 2 + checkNTests + 1 + checkNTests + 1 + checkAccessLengthTests \
434 + 2 + checkAccessLengthTests + 1)
437 static SecAccessRef
makeMultipleUidAccess(uid_t
* uids
, uint32 count
)
439 // rights granted (replace with individual list if desired)
440 CSSM_ACL_AUTHORIZATION_TAG rights
[] =
442 CSSM_ACL_AUTHORIZATION_ANY
// everything
444 size_t numRights
= sizeof(rights
) / sizeof(rights
[0]);
446 // allocate the arrays of objects used to define the ACL
447 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selectors
[count
];
448 CSSM_LIST_ELEMENT heads
[count
], tails
[count
];
449 CSSM_ACL_ENTRY_INFO acls
[count
];
450 // clear all the ACL objects
451 memset(heads
, 0, sizeof(heads
));
452 memset(acls
, 0, sizeof(acls
));
457 // make the "uid/gid" ACL subject
458 selectors
[i
].version
= CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
;
459 selectors
[i
].mask
= CSSM_ACL_MATCH_UID
; // set mask: match uids (only)
460 selectors
[i
].uid
= uids
[i
]; // uid to match
461 selectors
[i
].gid
= 0; // gid (not matched here)
463 // this is a CSSM_LIST_ELEMENT chain
464 heads
[i
].NextElement
= &(tails
[i
]);
465 heads
[i
].WordID
= CSSM_ACL_SUBJECT_TYPE_PROCESS
;
466 heads
[i
].ElementType
= CSSM_LIST_ELEMENT_WORDID
;
469 tails
[i
].NextElement
= NULL
;
470 tails
[i
].WordID
= CSSM_WORDID__NLU_
;
471 tails
[i
].ElementType
= CSSM_LIST_ELEMENT_DATUM
;
472 tails
[i
].Element
.Word
.Data
= (UInt8
*)&selectors
[i
];
473 tails
[i
].Element
.Word
.Length
= sizeof(selectors
[i
]);
476 acls
[i
].EntryPublicInfo
.TypedSubject
.ListType
= CSSM_LIST_TYPE_UNKNOWN
;
477 acls
[i
].EntryPublicInfo
.TypedSubject
.Head
= &heads
[i
];
478 acls
[i
].EntryPublicInfo
.TypedSubject
.Tail
= &tails
[i
];
479 acls
[i
].EntryPublicInfo
.Delegate
= CSSM_FALSE
;
480 acls
[i
].EntryPublicInfo
.Authorization
.NumberOfAuthTags
= (uint32
) numRights
;
482 acls
[i
].EntryPublicInfo
.Authorization
.AuthTags
= rights
;
483 acls
[i
].EntryHandle
= i
;
486 // owner component (right to change ACL)
487 CSSM_ACL_OWNER_PROTOTYPE owner
;
488 owner
.TypedSubject
= acls
[0].EntryPublicInfo
.TypedSubject
;
489 owner
.Delegate
= acls
[0].EntryPublicInfo
.Delegate
;
492 SecAccessCreateFromOwnerAndACL(&owner
, count
, acls
, &access
);
495 static void testMultipleUidAccess() {
497 sprintf(name
, "testMultipleUidAccess");
498 secdebugfunc("integrity", "************************************* %s", name
);
507 SecAccessRef access
= makeMultipleUidAccess(uids
, 5);
509 SecKeychainRef kc
= newKeychain(name
);
510 CFMutableDictionaryRef query
= makeAddItemDictionary(kc
, kSecClassGenericPassword
, CFSTR("test label"));
511 CFDictionarySetValue(query
, kSecAttrAccess
, access
);
513 CFTypeRef result
= NULL
;
514 ok_status(SecItemAdd(query
, &result
), "%s: SecItemAdd", name
);
515 ok(result
!= NULL
, "%s: SecItemAdd returned a result", name
);
517 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
519 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
521 #define testMultipleUidAccessTests (newKeychainTests + checkNTests + 3)
523 static void testRootUidAccess() {
525 sprintf(name
, "testRootUidAccess");
526 secdebugfunc("integrity", "************************************* %s", name
);
528 SecAccessRef access
= SecAccessCreateWithOwnerAndACL(getuid(), 0, (kSecUseOnlyUID
| kSecHonorRoot
), NULL
, NULL
);
530 SecKeychainRef kc
= newKeychain(name
);
531 CFMutableDictionaryRef query
= makeAddItemDictionary(kc
, kSecClassGenericPassword
, CFSTR("test label"));
532 CFDictionarySetValue(query
, kSecAttrAccess
, access
);
534 CFTypeRef result
= NULL
;
535 ok_status(SecItemAdd(query
, &result
), "%s: SecItemAdd", name
);
536 ok(result
!= NULL
, "%s: SecItemAdd returned a result", name
);
538 query
= makeQueryItemDictionary(kc
, kSecClassGenericPassword
);
540 SecKeychainItemRef item
= checkN(name
, query
, 1);
542 ok_status(SecKeychainItemSetAccess(item
, access
), "%s: SecKeychainItemSetAccess", name
);
543 checkN(name
, makeQueryItemDictionary(kc
, kSecClassGenericPassword
), 1);
545 ok_status(SecKeychainDelete(kc
), "%s: SecKeychainDelete", name
);
547 #define testRootUidAccessTests (newKeychainTests + checkNTests + 4 + checkNTests)
549 #define kTestCount (0 \
552 + testCopyMatchingItemTests \
553 + testCopyMatchingItemTests \
554 + testUpdateItemTests \
555 + testUpdateItemTests \
556 + testAddDuplicateItemTests \
557 + testAddDuplicateItemTests \
558 + testDeleteItemTests \
559 + testDeleteItemTests \
560 + testUpdateRetainedItemTests \
561 + testUpdateRetainedItemTests \
564 + testAddFreeKeyTests \
565 + testCopyMatchingKeyTests \
566 + testUpdateKeyTests \
567 + testAddDuplicateKeyTests \
569 + testExportImportKeyPairTests \
571 + initializeDLTests \
572 + testAttackItemTests \
573 + testAttackKeyTests \
574 + testAddAfterCorruptItemTests \
575 + testAddAfterCorruptKeyTests \
578 + testKeychainUpgradeTests \
579 + testUidAccessTests \
580 + testMultipleUidAccessTests \
581 + testRootUidAccessTests \
584 static void tests(void)
586 const char *home_dir
= getenv("HOME");
587 sprintf(keychainFile
, "%s/Library/Keychains/test.keychain", home_dir
);
588 sprintf(keychainName
, "test.keychain");
590 testAddItem(kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
591 testAddItem(kSecClassInternetPassword
, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
593 testCopyMatchingItem(kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
594 testCopyMatchingItem(kSecClassInternetPassword
, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
596 testUpdateItem(kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"),
597 CFSTR("7b7be2fd6ee9f81ba4c5575ea451f2c21117fc0f241625a6cf90c65180b8c9f5"));
598 testUpdateItem(kSecClassInternetPassword
, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"),
599 CFSTR("d71af9e4d54127a5dbc10c5ec097b828065cfbaf2b775caf1a3c4e3410f80851"));
601 testAddDuplicateItem(kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
602 testAddDuplicateItem(kSecClassInternetPassword
, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
604 testDeleteItem(kSecClassGenericPassword
, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
605 testDeleteItem(kSecClassInternetPassword
, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
607 testUpdateRetainedItem(kSecClassGenericPassword
);
608 testUpdateRetainedItem(kSecClassInternetPassword
);
610 testAddKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
611 testAddFreeKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
612 testCopyMatchingKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
613 testUpdateKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"),
614 CFSTR("a744ce6db8359ad264ed5f4a35ecfcc8b6599b89319e7ea316035acd3fb02c22"));
615 testAddDuplicateKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
616 testAddDuplicateFreeKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
619 testExportImportKeyPair();
621 CSSM_DL_DB_HANDLE dldbHandle
= initializeDL();
622 testAttackItem(dldbHandle
);
623 testAttackKey(dldbHandle
);
625 testAddAfterCorruptItem(dldbHandle
);
626 testAddAfterCorruptKey(dldbHandle
);
627 unloadDL(&dldbHandle
);
629 testKeychainUpgrade();
631 testMultipleUidAccess();
634 //makeOldKeychainBlob();
640 #define kTestCount (0)
643 static void tests(void)
647 #endif /* TARGET_OS_MAC */
650 int kc_30_xara(int argc
, char *const *argv
)
652 plan_tests(kTestCount
);