]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-30-xara-key-helpers.h
1 /*
2 * Copyright (c) 2015 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 #include "kc-30-xara-helpers.h"
25 #include "kc-key-helpers.h"
26
27 #ifndef kc_30_xara_key_helpers_h
28 #define kc_30_xara_key_helpers_h
29
30 #if TARGET_OS_MAC
31
32 static void makeCustomKeyWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef label, CFStringRef expectedHash) {
33 SecKeyRef key = makeCustomKey(name, kc, label);
34 checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash);
35 checkPartitionIDs(name, (SecKeychainItemRef) key, 1);
36 CFReleaseNull(key);
37 }
38 #define makeCustomKeyWithIntegrityTests (makeCustomKeyTests + checkIntegrityHashTests + checkPartitionIDsTests)
39
40 static void makeKeyWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef expectedHash) {
41 makeCustomKeyWithIntegrity(name, kc, CFSTR("test_key"), expectedHash);
42 }
43 #define makeKeyWithIntegrityTests makeCustomKeyWithIntegrityTests
44
45 // Note that this is nearly useless, as key pairs will never have stable hashes
46 static void makeKeyPairWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef expectedPubHash, CFStringRef expectedPrivHash) {
47 SecKeyRef pub;
48 SecKeyRef priv;
49 makeKeyPair(name, kc, &pub, &priv);
50
51 checkIntegrityHash(name, (SecKeychainItemRef) pub, expectedPubHash);
52 checkIntegrityHash(name, (SecKeychainItemRef) priv, expectedPrivHash);
53 }
54 #define makeKeyPairWithIntegrityTests (makeKeyTests + checkIntegrityHashTests)
55
56 // And now for the actual tests
57
58 static void testAddKey(CFStringRef expectedHash) {
59 char* name = "testAddKey";
60 SecKeychainRef kc = newKeychain(name);
61 makeKeyWithIntegrity(name, kc, expectedHash);
62 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
63 CFReleaseNull(kc);
64 }
65 #define testAddKeyTests (newKeychainTests + makeKeyWithIntegrityTests + 1)
66
67 static void testAddFreeKey(CFStringRef expectedHash) {
68 // Due to <rdar://problem/8431281> SecItemAdd() will not add a generated symmetric key to the keychain
69 // we can't actually run this test. Code is included here as a reference.
70 //char* name = "testAddFreeKey";
71 //SecKeychainRef kc = newKeychain(name);
72
73 //SecKeyRef key = makeFreeKey(name, kc);
74 //checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash);
75
76 //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
77 //CFReleaseNull(kc);
78 }
79 //#define testAddFreeKeyTests (newKeychainTests + makeFreeKeyTests + checkIntegrityHashTests + 1)
80 #define testAddFreeKeyTests 0
81
82 static void testCopyMatchingKey(CFStringRef expectedHash) {
83 char* name = "testCopyMatchingKey";
84 secnotice("integrity", "************************************* %s", name);
85
86 SecKeychainRef kc = newKeychain(name);
87 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
88
89 makeKeyWithIntegrity(name, kc, expectedHash);
90
91 SecKeyRef item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
92 checkIntegrityHash(name, (SecKeychainItemRef) item, expectedHash);
93 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
94 CFReleaseNull(kc);
95 }
96 #define testCopyMatchingKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1)
97
98
99 static void testUpdateKey(CFStringRef expectedHash, CFStringRef expectedHashAfter) {
100 char * name = "testUpdateKey";
101 secnotice("integrity", "************************************* %s", name);
102
103 SecKeychainRef kc = newKeychain(name);
104 makeKeyWithIntegrity(name, kc, expectedHash);
105 SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
106 CFReleaseNull(item);
107
108 CFStringRef label = CFSTR("a modified label");
109
110 CFMutableDictionaryRef query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric);
111 CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
112 CFDictionarySetValue(update, kSecAttrLabel, label);
113 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name);
114
115 CFReleaseNull(query);
116 CFReleaseNull(update);
117
118 // Find the item again.
119 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric);
120 CFDictionarySetValue(query, kSecAttrLabel, label);
121 item = checkN(name, query, 1);
122 checkIntegrityHash(name, item, expectedHashAfter);
123 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
124 CFReleaseNull(kc);
125 }
126 #define testUpdateKeyTests (newKeychainTests + makeKeyWithIntegrityTests + checkNTests + 1 + checkNTests + checkIntegrityHashTests + 1)
127
128 // Key Pairs have non-predictable hashes, since they receive an attribute kSecKeyLabel that is
129 // the hash of the public key. Since the key is generated randomly, so is the label.
130 //
131 // We can't do our normal "add", "copymatching", "update" tests here, so do
132 // something special...
133
134 static void testKeyPair() {
135 char* name = "testKeyPair";
136 secnotice("integrity", "************************************* %s", name);
137
138 SecKeychainRef kc = newKeychain(name);
139 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
140 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
141
142 SecKeyRef pub;
143 SecKeyRef priv;
144 makeKeyPair(name, kc, &pub, &priv);
145
146 // Now that we have the key pair, make sure we can pull the individual keys
147 // out (and the hashes match)
148
149 CFStringRef label = CFSTR("a modified label");
150 CFMutableDictionaryRef query;
151 CFMutableDictionaryRef update;
152
153 // Ensure that the public key still exists and can be updated
154
155 SecKeyRef item;
156 item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
157 checkHashesMatch(name, (SecKeychainItemRef)pub, (SecKeychainItemRef)item);
158
159 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic);
160 CFDictionarySetValue(query, kSecAttrLabel, label);
161 item = (SecKeyRef) checkN(name, query, 0);
162
163 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic);
164 update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
165 CFDictionarySetValue(update, kSecAttrLabel, label);
166 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate (public key)", name);
167
168 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic);
169 CFDictionarySetValue(query, kSecAttrLabel, label);
170 item = (SecKeyRef) checkN(name, query, 1);
171 CFReleaseNull(item);
172
173 // Ensure that the private key still exists and can be updated
174
175 item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
176 checkHashesMatch(name, (SecKeychainItemRef)priv, (SecKeychainItemRef)item);
177
178 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate);
179 CFDictionarySetValue(query, kSecAttrLabel, label);
180 item = (SecKeyRef) checkN(name, query, 0);
181
182 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate);
183 update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
184 CFDictionarySetValue(update, kSecAttrLabel, label);
185 ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate (private key)", name);
186
187 query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate);
188 CFDictionarySetValue(query, kSecAttrLabel, label);
189 item = (SecKeyRef) checkN(name, query, 1);
190 CFReleaseNull(item);
191
192 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
193 CFReleaseNull(kc);
194 }
195 #define testKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \
196 + checkNTests + checkHashesMatchTests \
197 + checkNTests + 1 + checkNTests \
198 + checkNTests + checkHashesMatchTests \
199 + checkNTests + 1 + checkNTests \
200 + 1)
201
202 static void testAddDuplicateKey(CFStringRef expectedHash) {
203 char * name = "testAddDuplicateKey";
204 secnotice("integrity", "************************************* %s", name);
205
206 SecKeychainRef kc = newKeychain(name);
207 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
208
209 makeKeyWithIntegrity(name, kc, expectedHash);
210
211 SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
212 makeDuplicateKey(name, kc);
213 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
214
215 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
216 CFReleaseNull(kc);
217 }
218 #define testAddDuplicateKeyTests (newKeychainTests + checkNTests +makeKeyWithIntegrityTests + checkNTests + makeDuplicateKeyTests + checkNTests + 1)
219
220 static void testAddDuplicateFreeKey(CFStringRef expectedHash) {
221 // Due to <rdar://problem/8431281> SecItemAdd() will not add a generated symmetric key to the keychain
222 // we can't actually run this test. Code is included here as a reference.
223 //char * name = "testAddDuplicateFreeKey";
224 //secnotice("integrity", "************************************* %s", name);
225 //SecKeychainRef kc = newKeychain(name);
226 //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
227
228 //SecKeyRef key = makeFreeKey(name, kc);
229 //checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash);
230 //SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
231
232 //makeDuplicateFreeKey(name, kc);
233 //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
234
235 //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
236 //CFReleaseNull(kc);
237 }
238 //#define testAddDuplicateFreeKeyTests (newKeychainTests + checkNTests + makeFreeKeyTests + checkIntegrityHashTests + checkNTests \
239 // + makeDuplicateKeyTests + checkNTests + 1)
240 #define testAddDuplicateFreeKeyTests 0
241
242 // testAddDuplicateKeyPair:
243 //
244 // By use of the Sec* APIs, you will almost certainly never get an
245 // errSecDuplicateItem out of SecKeychainGeneratePair. Since it sets a primary
246 // key attribute as the hash of the public key, it just will never generate a
247 // duplicate item.
248
249 static void testExportImportKeyPair() {
250 char* name = "testExportImportKeyPair";
251 secnotice("integrity", "************************************* %s", name);
252
253 SecKeychainRef kc = newKeychain(name);
254 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
255 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
256
257 SecKeyRef pub;
258 SecKeyRef priv;
259 makeKeyPair(name, kc, &pub, &priv);
260
261 // Now that we have the key pair, make sure we can pull the individual keys out
262
263 SecKeyRef item;
264 item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
265 checkHashesMatch(name, (SecKeychainItemRef)pub, (SecKeychainItemRef)item);
266
267 item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
268 checkHashesMatch(name, (SecKeychainItemRef)priv, (SecKeychainItemRef)item);
269
270 CFMutableArrayRef applications = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
271 SecTrustedApplicationRef app = NULL;
272
273 ok_status(SecTrustedApplicationCreateFromPath(NULL, &app), "%s: SecTrustedApplicationCreateFromPath", name);
274 CFArrayAppendValue(applications, app);
275
276 ok_status(SecTrustedApplicationCreateFromPath("/usr/bin/codesign", &app), "%s: SecTrustedApplicationCreateFromPath", name);
277 CFArrayAppendValue(applications, app);
278
279 SecAccessRef accessRef = NULL;
280 ok_status(SecAccessCreate(CFSTR("accessDescription"), applications, &accessRef), "%s: SecAccessCreate", name);
281
282 const SecItemImportExportKeyParameters keyParams =
283 {
284 SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
285 0,
286 CFSTR( "" ),
287 CFSTR( "" ),
288 CFSTR( "" ),
289 accessRef, 0, 0
290 };
291 CFArrayRef items = NULL;
292
293 CFDataRef keyData = NULL;
294 ok_status(SecItemExport(pub, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name);
295 ok_status(SecKeychainItemDelete((SecKeychainItemRef)pub), "%s: SecKeychainItemDelete", name);;
296 CFRelease(pub);
297 pub = NULL;
298
299 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
300 ok_status(SecItemImport(keyData, NULL, NULL, NULL, kSecItemPemArmour, &keyParams, kc, &items), "%s: SecItemImport", name);
301 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
302
303
304 ok_status(SecItemExport(priv, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name);
305 ok_status(SecKeychainItemDelete((SecKeychainItemRef)priv), "%s: SecKeychainItemDelete", name);;
306 CFRelease(priv);
307 priv = NULL;
308
309 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
310
311 ok_status(SecItemImport(keyData, NULL, NULL, NULL, kSecItemPemArmour, &keyParams, kc, &items), "%s: SecItemImport", name);
312
313 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
314
315 SecAccessRef newRef = NULL;
316 ok_status(SecKeychainItemCopyAccess((SecKeychainItemRef) CFArrayGetValueAtIndex(items, 0), &newRef), "%s:SecKeychainItemCopyAccess", name);
317
318 SecKeyRef importedKey = items && CFArrayGetCount(items) > 0 ? (SecKeyRef)CFArrayGetValueAtIndex(items, 0) : NULL;
319 if (importedKey) {
320 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
321 CFDictionaryAddValue(query, kSecClass, kSecClassKey);
322 CFDictionaryAddValue(query, kSecValueRef, importedKey);
323
324 CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
325 CFDictionaryAddValue(attrs, kSecAttrLabel, CFSTR("private key custom label"));
326
327 ok_status( SecItemUpdate(query, attrs), "%s: SecItemUpdate", name);
328 } else {
329 fail("%s: Didn't have an item to update", name);
330 }
331
332 ok_status(SecKeychainItemCopyAccess((SecKeychainItemRef) CFArrayGetValueAtIndex(items, 0), &newRef), "%s:SecKeychainItemCopyAccess", name);
333 // TODO: should probably check this AccessRef object to make sure it's simple
334
335 checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
336
337 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
338 CFReleaseNull(kc);
339 }
340 #define testExportImportKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \
341 + checkNTests + checkHashesMatchTests \
342 + checkNTests + checkHashesMatchTests \
343 + 5 + checkNTests + 1 + checkNTests \
344 + 2 + checkNTests + 1 + checkNTests + 1 + 1 + 1 + checkNTests\
345 + 1)
346
347
348 #else
349
350 #endif /* TARGET_OS_MAC */
351
352
353 #endif /* kc_30_xara_key_helpers_h */