5 // Created by Michael Brouwer on 8/1/13.
6 // Copyright (c) 2013 Apple Inc. All Rights Reserved.
10 #include <CoreFoundation/CoreFoundation.h>
11 #include <Security/SecCertificate.h>
12 #include <Security/SecItem.h>
13 #include <Security/SecItemPriv.h>
14 #include <Security/SecBase.h>
15 #include <utilities/array_size.h>
16 #include <utilities/SecCFWrappers.h>
20 #include "Security_regressions.h"
23 static void persistentRefIs(CFDataRef pref
, CFDataRef data
) {
24 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
25 CFTypeRef result
= NULL
;
26 CFDictionaryAddValue(dict
, kSecValuePersistentRef
, pref
);
27 CFDictionaryAddValue(dict
, kSecReturnData
, kCFBooleanTrue
);
28 ok_status(SecItemCopyMatching(dict
, &result
), "lookup item data by persistent ref");
29 ok(CFEqual(data
, result
), "result %@ equals expected data %@", result
, data
);
30 CFReleaseNull(result
);
42 kAccessabilityItemAttr
,
46 static void WithEachString(void(^each
)(CFStringRef attr
, enum ItemAttrType atype
), ...) {
50 while((attr
= va_arg(ap
, CFStringRef
)) != NULL
) {
51 enum ItemAttrType atype
= va_arg(ap
, enum ItemAttrType
);
58 static void ItemForEachAttr(CFMutableDictionaryRef item
, void(^each
)(CFStringRef attr
, enum ItemAttrType atype
)) {
59 CFStringRef iclass
= CFDictionaryGetValue(item
, kSecClass
);
62 } else if (CFEqual(iclass
, kSecClassGenericPassword
)) {
64 kSecAttrAccessible
, kAccessabilityItemAttr
,
65 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
66 kSecAttrCreationDate
, kDateItemAttr
,
67 kSecAttrModificationDate
, kDateItemAttr
,
68 kSecAttrDescription
, kStringItemAttr
,
69 kSecAttrComment
, kStringItemAttr
,
70 kSecAttrCreator
, kNumberItemAttr
,
71 kSecAttrType
, kNumberItemAttr
,
72 kSecAttrLabel
, kStringItemAttr
,
73 kSecAttrIsInvisible
, kBoolItemAttr
,
74 kSecAttrIsNegative
, kBoolItemAttr
,
75 kSecAttrAccount
, kStringItemAttr
,
76 kSecAttrService
, kStringItemAttr
,
77 kSecAttrGeneric
, kDataItemAttr
,
78 kSecAttrSynchronizable
, kBoolItemAttr
,
80 } else if (CFEqual(iclass
, kSecClassInternetPassword
)) {
82 kSecAttrAccessible
, kAccessabilityItemAttr
,
83 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
84 kSecAttrCreationDate
, kDateItemAttr
,
85 kSecAttrModificationDate
, kDateItemAttr
,
86 kSecAttrDescription
, kStringItemAttr
,
87 kSecAttrComment
, kStringItemAttr
,
88 kSecAttrCreator
, kNumberItemAttr
,
89 kSecAttrType
, kNumberItemAttr
,
90 kSecAttrLabel
, kStringItemAttr
,
91 kSecAttrIsInvisible
, kBoolItemAttr
,
92 kSecAttrIsNegative
, kBoolItemAttr
,
93 kSecAttrAccount
, kStringItemAttr
,
94 kSecAttrSecurityDomain
, kStringItemAttr
,
95 kSecAttrServer
, kStringItemAttr
,
96 kSecAttrProtocol
, kNumberItemAttr
,
97 kSecAttrAuthenticationType
, kNumberItemAttr
,
98 kSecAttrPort
, kNumberItemAttr
,
99 kSecAttrPath
, kStringItemAttr
,
100 kSecAttrSynchronizable
, kBoolItemAttr
,
102 } else if (CFEqual(iclass
, kSecClassCertificate
)) {
104 kSecAttrAccessible
, kAccessabilityItemAttr
,
105 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
106 kSecAttrCertificateType
, kNumberItemAttr
,
107 kSecAttrCertificateEncoding
, kNumberItemAttr
,
108 kSecAttrLabel
, kStringItemAttr
,
109 kSecAttrSubject
, kDataItemAttr
,
110 kSecAttrIssuer
, kDataItemAttr
,
111 kSecAttrSerialNumber
, kDataItemAttr
,
112 kSecAttrSubjectKeyID
, kDataItemAttr
,
113 kSecAttrPublicKeyHash
, kDataItemAttr
,
114 kSecAttrSynchronizable
, kBoolItemAttr
,
116 } else if (CFEqual(iclass
, kSecClassKey
)) {
118 kSecAttrAccessible
, kAccessabilityItemAttr
,
119 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
120 kSecAttrKeyClass
, kStringItemAttr
, // Might be Number on replies
121 kSecAttrLabel
, kStringItemAttr
,
122 kSecAttrApplicationLabel
, kDataItemAttr
,
123 kSecAttrIsPermanent
, kBoolItemAttr
,
124 kSecAttrApplicationTag
, kDataItemAttr
,
125 kSecAttrKeyType
, kNumberItemAttr
,
126 kSecAttrKeySizeInBits
, kNumberItemAttr
,
127 kSecAttrEffectiveKeySize
, kNumberItemAttr
,
128 kSecAttrCanEncrypt
, kBoolItemAttr
,
129 kSecAttrCanDecrypt
, kBoolItemAttr
,
130 kSecAttrCanDerive
, kBoolItemAttr
,
131 kSecAttrCanSign
, kBoolItemAttr
,
132 kSecAttrCanVerify
, kBoolItemAttr
,
133 kSecAttrCanWrap
, kBoolItemAttr
,
134 kSecAttrCanUnwrap
, kBoolItemAttr
,
135 kSecAttrStartDate
, kDateItemAttr
,
136 kSecAttrEndDate
, kDateItemAttr
,
137 kSecAttrSynchronizable
, kBoolItemAttr
,
139 } else if (CFEqual(iclass
, kSecClassIdentity
)) {
141 kSecAttrAccessible
, kAccessabilityItemAttr
,
142 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
143 kSecAttrCertificateType
, kNumberItemAttr
,
144 kSecAttrCertificateEncoding
, kNumberItemAttr
,
145 kSecAttrLabel
, kStringItemAttr
,
146 kSecAttrSubject
, kDataItemAttr
,
147 kSecAttrIssuer
, kDataItemAttr
,
148 kSecAttrSerialNumber
, kDataItemAttr
,
149 kSecAttrSubjectKeyID
, kDataItemAttr
,
150 kSecAttrPublicKeyHash
, kDataItemAttr
,
151 kSecAttrKeyClass
, kStringItemAttr
, // Might be Number on replies
152 kSecAttrApplicationLabel
, kDataItemAttr
,
153 kSecAttrIsPermanent
, kBoolItemAttr
,
154 kSecAttrApplicationTag
, kDataItemAttr
,
155 kSecAttrKeyType
, kNumberItemAttr
,
156 kSecAttrKeySizeInBits
, kNumberItemAttr
,
157 kSecAttrEffectiveKeySize
, kNumberItemAttr
,
158 kSecAttrCanEncrypt
, kBoolItemAttr
,
159 kSecAttrCanDecrypt
, kBoolItemAttr
,
160 kSecAttrCanDerive
, kBoolItemAttr
,
161 kSecAttrCanSign
, kBoolItemAttr
,
162 kSecAttrCanVerify
, kBoolItemAttr
,
163 kSecAttrCanWrap
, kBoolItemAttr
,
164 kSecAttrCanUnwrap
, kBoolItemAttr
,
165 kSecAttrStartDate
, kDateItemAttr
,
166 kSecAttrEndDate
, kDateItemAttr
,
167 kSecAttrSynchronizable
, kBoolItemAttr
,
173 static void ItemForEachPKAttr(CFMutableDictionaryRef item
, void(^each
)(CFStringRef attr
, enum ItemAttrType atype
)) {
174 CFStringRef iclass
= CFDictionaryGetValue(item
, kSecClass
);
177 } else if (CFEqual(iclass
, kSecClassGenericPassword
)) {
179 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
180 kSecAttrAccount
, kStringItemAttr
,
181 kSecAttrService
, kStringItemAttr
,
182 kSecAttrSynchronizable
, kBoolItemAttr
,
184 } else if (CFEqual(iclass
, kSecClassInternetPassword
)) {
186 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
187 kSecAttrAccount
, kStringItemAttr
,
188 kSecAttrSecurityDomain
, kStringItemAttr
,
189 kSecAttrServer
, kStringItemAttr
,
190 kSecAttrProtocol
, kNumberItemAttr
,
191 kSecAttrAuthenticationType
, kNumberItemAttr
,
192 kSecAttrPort
, kNumberItemAttr
,
193 kSecAttrPath
, kStringItemAttr
,
194 kSecAttrSynchronizable
, kBoolItemAttr
,
196 } else if (CFEqual(iclass
, kSecClassCertificate
)) {
198 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
199 kSecAttrCertificateType
, kNumberItemAttr
,
200 kSecAttrIssuer
, kDataItemAttr
,
201 kSecAttrSerialNumber
, kDataItemAttr
,
202 kSecAttrSynchronizable
, kBoolItemAttr
,
204 } else if (CFEqual(iclass
, kSecClassKey
)) {
206 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
207 kSecAttrKeyClass
, kStringItemAttr
, // kNumberItemAttr on replies
208 kSecAttrApplicationLabel
, kDataItemAttr
,
209 kSecAttrApplicationTag
, kDataItemAttr
,
210 kSecAttrKeyType
, kNumberItemAttr
,
211 kSecAttrKeySizeInBits
, kNumberItemAttr
,
212 kSecAttrEffectiveKeySize
, kNumberItemAttr
,
213 kSecAttrStartDate
, kDateItemAttr
,
214 kSecAttrEndDate
, kDateItemAttr
,
215 kSecAttrSynchronizable
, kBoolItemAttr
,
217 } else if (CFEqual(iclass
, kSecClassIdentity
)) {
219 kSecAttrAccessGroup
, kAccessGroupItemAttr
,
220 kSecAttrCertificateType
, kNumberItemAttr
,
221 kSecAttrIssuer
, kDataItemAttr
,
222 kSecAttrSerialNumber
, kDataItemAttr
,
223 kSecAttrSynchronizable
, kBoolItemAttr
,
224 kSecAttrKeyClass
, kStringItemAttr
, // kNumberItemAttr on replies
225 kSecAttrApplicationLabel
, kDataItemAttr
,
226 kSecAttrApplicationTag
, kDataItemAttr
,
227 kSecAttrKeyType
, kNumberItemAttr
,
228 kSecAttrKeySizeInBits
, kNumberItemAttr
,
229 kSecAttrEffectiveKeySize
, kNumberItemAttr
,
230 kSecAttrStartDate
, kDateItemAttr
,
231 kSecAttrEndDate
, kDateItemAttr
,
232 kSecAttrSynchronizable
, kBoolItemAttr
,
237 static CFMutableDictionaryRef
ItemCreate(int num
) {
238 CFStringRef iclass
= NULL
;
241 iclass
= kSecClassInternetPassword
;
244 iclass
= kSecClassGenericPassword
;
247 iclass
= kSecClassKey
;
250 iclass
= kSecClassCertificate
;
253 return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault
, kSecClass
, iclass
, NULL
);
256 /* Test add api in all it's variants. */
257 static void tests(void)
259 for (int num
= 0 ; num
< 8; ++num
) {
260 CFMutableDictionaryRef item
= ItemCreate(num
);
261 ItemForEachPKAttr(item
, ^(CFStringRef attr
, enum ItemAttrType atype
) {
262 CFTypeRef value
= NULL
;
265 value
= (num
% 2 == 0 ? kCFBooleanTrue
: kCFBooleanFalse
);
268 case kNumberItemAttr
:
269 value
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &num
);
271 case kStringItemAttr
:
273 value
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("string-%d"), num
);
278 int len
= snprintf(buf
, sizeof(buf
), "data-%d", num
);
279 value
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)buf
, len
);
283 value
= NULL
; // Don't mess with dates on create.
285 case kAccessabilityItemAttr
:
287 CFStringRef accessabilites
[] = {
288 kSecAttrAccessibleWhenUnlocked
,
289 kSecAttrAccessibleAfterFirstUnlock
,
290 kSecAttrAccessibleAlways
,
291 kSecAttrAccessibleWhenUnlockedThisDeviceOnly
,
292 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
,
293 kSecAttrAccessibleAlwaysThisDeviceOnly
,
295 value
= accessabilites
[num
% array_size(accessabilites
)];
298 case kAccessGroupItemAttr
:
300 CFStringRef accessGroups
[] = {
306 CFSTR("lockdown-identities"),
310 CFSTR("com.apple.security.sos"), // Secd internally uses this
312 CFSTR("com.apple.security.regressions"), // SecurityTestApp is in this group.
315 value
= accessGroups
[num
% array_size(accessGroups
)];
320 CFDictionarySetValue(item
, attr
, value
);
321 CFReleaseSafe(value
);
324 CFDictionarySetValue(item
, kSecAttrSynchronizable
, kCFBooleanTrue
);
325 ok_status(SecItemAdd(item
, NULL
), "add sync");
327 CFDictionarySetValue(item
, kSecUseTombstones
, kCFBooleanTrue
);
328 ok_status(SecItemDelete(item
), "delete sync");
330 CFDictionarySetValue(item
, kSecAttrTombstone
, kCFBooleanTrue
);
331 ok_status(SecItemCopyMatching(item
, NULL
), "find tombstone after delete sync");
332 ok_status(SecItemDelete(item
), "delete sync tombstone");
333 CFDictionaryRemoveValue(item
, kSecAttrTombstone
);
335 ok_status(SecItemAdd(item
, NULL
), "add sync again");
337 CFDictionarySetValue(item
, kSecUseTombstones
, kCFBooleanFalse
);
338 ok_status(SecItemDelete(item
), "delete sync without leaving a tombstone behind");
339 CFDictionaryRemoveValue(item
, kSecUseTombstones
);
341 CFDictionarySetValue(item
, kSecAttrTombstone
, kCFBooleanTrue
);
342 is_status(SecItemCopyMatching(item
, NULL
), errSecItemNotFound
, "do not find tombstone after delete sync with kSecUseTombstones=false");
344 CFDictionaryRemoveValue(item
, kSecAttrSynchronizable
);
345 ok_status(SecItemAdd(item
, NULL
), "add local");
346 ok_status(SecItemDelete(item
), "delete local");
348 CFDictionarySetValue(item
, kSecAttrTombstone
, kCFBooleanTrue
);
349 is_status(SecItemCopyMatching(item
, NULL
), errSecItemNotFound
, "do not find tombstone after delete local");
350 is_status(SecItemDelete(item
), errSecItemNotFound
, "do not delete tombstone after delete local");
351 CFDictionaryRemoveValue(item
, kSecAttrTombstone
);
353 ok_status(SecItemAdd(item
, NULL
), "add local again");
355 CFDictionarySetValue(item
, kSecUseTombstones
, kCFBooleanTrue
);
356 ok_status(SecItemDelete(item
), "delete local and leave a tombstone behind");
357 CFDictionaryRemoveValue(item
, kSecUseTombstones
);
359 CFDictionarySetValue(item
, kSecAttrTombstone
, kCFBooleanTrue
);
360 ok_status(SecItemCopyMatching(item
, NULL
), "find tombstone after delete sync with kSecUseTombstones=true");
362 CFDictionarySetValue(item
, kSecUseTombstones
, kCFBooleanTrue
);
363 ok_status(SecItemDelete(item
), "delete local tombstone kSecUseTombstones=true");
364 CFDictionaryRemoveValue(item
, kSecUseTombstones
);
366 ok_status(SecItemCopyMatching(item
, NULL
), "find tombstone after delete local tombstone with kSecUseTombstones=true");
367 ok_status(SecItemDelete(item
), "delete local tombstone");
368 is_status(SecItemCopyMatching(item
, NULL
), errSecItemNotFound
, "do not find tombstone after delete local");
374 int si_12_item_stress(int argc
, char *const *argv
)