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