]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-43-seckey-interop.m
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-43-seckey-interop.m
1 /*
2 * Copyright (c) 2007-2009,2013-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 <TargetConditionals.h>
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <Foundation/Foundation.h>
28 #include <Security/Security.h>
29 #include <Security/SecRandom.h>
30 #include <Security/SecKeyPriv.h>
31 #include <Security/SecItem.h>
32 #include <Security/SecItemPriv.h>
33 #include <Security/SecIdentityPriv.h>
34 #include <Security/SecKeychainItem.h>
35
36 #include "keychain_regressions.h"
37 #include "utilities/SecCFRelease.h"
38 #include "utilities/array_size.h"
39
40 #if !TARGET_OS_IPHONE
41 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
42 {
43 if (left == NULL || right == NULL)
44 return left == right;
45 else
46 return CFEqual(left, right);
47 }
48 #endif
49
50 static const int kTestGenerateNoLegacyCount = 11;
51 static void test_generate_nolegacy() {
52 NSDictionary *query, *params = @{
53 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
54 (id)kSecAttrKeySizeInBits: @1024,
55 (id)kSecAttrNoLegacy: @YES,
56 (id)kSecAttrIsPermanent: @YES,
57 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
58 };
59
60 SecKeyRef pubKey = NULL, privKey = NULL, key = NULL;
61 ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey));
62
63 query = @{
64 (id)kSecClass: (id)kSecClassKey,
65 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
66 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
67 (id)kSecAttrNoLegacy: @YES,
68 (id)kSecReturnRef: @YES,
69 };
70 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key));
71 eq_cf(key, pubKey);
72 CFReleaseNull(key);
73
74 query = @{
75 (id)kSecClass: (id)kSecClassKey,
76 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
77 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
78 (id)kSecAttrNoLegacy: @YES,
79 (id)kSecReturnRef: @YES,
80 };
81 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key));
82 eq_cf(key, privKey);
83 CFReleaseNull(key);
84
85 query = @{
86 (id)kSecClass: (id)kSecClassKey,
87 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
88 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
89 (id)kSecAttrNoLegacy: @YES,
90 (id)kSecReturnRef: @YES,
91 };
92 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key));
93 eq_cf(key, pubKey);
94 CFReleaseNull(key);
95
96 query = @{
97 (id)kSecClass: (id)kSecClassKey,
98 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
99 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
100 (id)kSecAttrNoLegacy: @YES,
101 (id)kSecReturnRef: @YES,
102 };
103 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key));
104 eq_cf(key, privKey);
105 CFReleaseNull(key);
106
107 query = @{
108 (id)kSecClass: (id)kSecClassKey,
109 (id)kSecAttrLabel: @"sectests:generate-no-legacy",
110 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
111 (id)kSecAttrNoLegacy: @YES,
112 };
113 ok_status(SecItemDelete((__bridge CFDictionaryRef)query));
114 is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound);
115
116 CFReleaseNull(privKey);
117 CFReleaseNull(pubKey);
118 }
119
120 #if !RC_HIDE_J79 && !RC_HIDE_J80
121 static const int kTestGenerateAccessControlCount = 4;
122 static void test_generate_access_control() {
123 SecAccessControlRef ac = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleAlways,
124 0 /* | kSecAccessControlPrivateKeyUsage */, NULL);
125 NSDictionary *params = @{
126 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
127 (id)kSecAttrKeySizeInBits: @1024,
128 (id)kSecAttrAccessControl: (id)ac,
129 (id)kSecAttrIsPermanent: @YES,
130 (id)kSecAttrLabel: @"sectests:generate-access-control",
131 };
132
133 SecKeyRef pubKey, privKey;
134 ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey));
135
136 NSDictionary *query = @{
137 (id)kSecClass: (id)kSecClassKey,
138 (id)kSecAttrLabel: @"sectests:generate-access-control",
139 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
140 (id)kSecAttrNoLegacy: @YES,
141 };
142 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL));
143
144 ok_status(SecItemDelete((__bridge CFDictionaryRef)query));
145
146 is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound);
147
148 CFReleaseSafe(ac);
149 CFReleaseSafe(privKey);
150 CFReleaseSafe(pubKey);
151 }
152 #else
153 static const int kTestGenerateAccessControlCount = 0;
154 #endif
155
156 static const int kTestAddIOSKeyCount = 6;
157 static void test_add_ios_key() {
158 NSDictionary *params = @{
159 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
160 (id)kSecAttrKeySizeInBits: @1024,
161 (id)kSecAttrNoLegacy: @YES,
162 (id)kSecAttrIsPermanent: @NO,
163 };
164
165 SecKeyRef pubKey, privKey;
166 ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey));
167
168 NSDictionary *attrs = @{
169 (id)kSecValueRef: (id)privKey,
170 (id)kSecAttrLabel: @"sectests:add-ios-key",
171 };
172 ok_status(SecItemAdd((__bridge CFDictionaryRef)attrs, NULL));
173
174 NSDictionary *query = @{
175 (id)kSecClass: (id)kSecClassKey,
176 (id)kSecAttrLabel: @"sectests:add-ios-key",
177 (id)kSecAttrNoLegacy: @YES,
178 (id)kSecReturnRef: @YES,
179 };
180 SecKeyRef key = NULL;
181 ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key));
182 eq_cf(key, privKey);
183 CFReleaseNull(key);
184
185 query = @{
186 (id)kSecClass: (id)kSecClassKey,
187 (id)kSecAttrLabel: @"sectests:add-ios-key",
188 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
189 (id)kSecAttrNoLegacy: @YES,
190 };
191 ok_status(SecItemDelete((__bridge CFDictionaryRef)query));
192 is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound);
193
194 CFReleaseNull(pubKey);
195 CFReleaseNull(privKey);
196 }
197
198 static const char *certDataBase64 = "\
199 MIIEQjCCAyqgAwIBAgIJAJdFadWqNIfiMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAkNaMQ8wDQYD\
200 VQQHEwZQcmFndWUxFTATBgNVBAoTDENvc21vcywgSW5jLjEXMBUGA1UEAxMOc3VuLmNvc21vcy5nb2Qx\
201 IzAhBgkqhkiG9w0BCQEWFHRoaW5nQHN1bi5jb3Ntb3MuZ29kMB4XDTE2MDIyNjE0NTQ0OVoXDTE4MTEy\
202 MjE0NTQ0OVowczELMAkGA1UEBhMCQ1oxDzANBgNVBAcTBlByYWd1ZTEVMBMGA1UEChMMQ29zbW9zLCBJ\
203 bmMuMRcwFQYDVQQDEw5zdW4uY29zbW9zLmdvZDEjMCEGCSqGSIb3DQEJARYUdGhpbmdAc3VuLmNvc21v\
204 cy5nb2QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5u9gnYEDzQIVu7yC40VcXTZ01D9CJ\
205 oD/mH62tebEHEdfVPLWKeq+uAHnJ6fTIJQvksaISOxwiOosFjtI30mbe6LZ/oK22wYX+OUwKhAYjZQPy\
206 RYfuaJe/52F0zmfUSJ+KTbUZrXbVVFma4xPfpg4bptvtGkFJWnufvEEHimOGmO5O69lXA0Hit1yLU0/A\
207 MQrIMmZT8gb8LMZGPZearT90KhCbTHAxjcBfswZYeL8q3xuEVHXC7EMs6mq8IgZL7mzSBmrCfmBAIO0V\
208 jW2kvmy0NFxkjIeHUShtYb11oYYyfHuz+1vr1y6FIoLmDejKVnwfcuNb545m26o+z/m9Lv9bAgMBAAGj\
209 gdgwgdUwHQYDVR0OBBYEFGDdpPELS92xT+Hkh/7lcc+4G56VMIGlBgNVHSMEgZ0wgZqAFGDdpPELS92x\
210 T+Hkh/7lcc+4G56VoXekdTBzMQswCQYDVQQGEwJDWjEPMA0GA1UEBxMGUHJhZ3VlMRUwEwYDVQQKEwxD\
211 b3Ntb3MsIEluYy4xFzAVBgNVBAMTDnN1bi5jb3Ntb3MuZ29kMSMwIQYJKoZIhvcNAQkBFhR0aGluZ0Bz\
212 dW4uY29zbW9zLmdvZIIJAJdFadWqNIfiMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAFYi\
213 Zu/dfAMOrD51bYxP88Wu6iDGBe9nMG/0lkKgnX5JQKCxfxFMk875rfa+pljdUMOaPxegOXq1DrYmQB9O\
214 /pHI+t7ozuWHRj2zKkVgMWAygNWDPcoqBEus53BdAgA644aPN2JvnE4NEPCllOMKftPoIWbd/5ZjCx3a\
215 bCuxBdXq5YSmiEnOdGfKeXjeeEiIDgARb4tLgH5rkOpB1uH/ZCWn1hkiajBhrGhhPhpA0zbkZg2Ug+8g\
216 XPlx1yQB1VOJkj2Z8dUEXCaRRijInCJ2eU+pgJvwLV7mxmSED7DEJ+b+opxJKYrsdKBU6RmYpPrDa+KC\
217 /Yfu88P9hKKj0LmBiREA\
218 ";
219
220 static const char *keyDataBase64 = "\
221 MIIEogIBAAKCAQEAubvYJ2BA80CFbu8guNFXF02dNQ/QiaA/5h+trXmxBxHX1Ty1inqvrgB5yen0yCUL\
222 5LGiEjscIjqLBY7SN9Jm3ui2f6CttsGF/jlMCoQGI2UD8kWH7miXv+dhdM5n1Eifik21Ga121VRZmuMT\
223 36YOG6bb7RpBSVp7n7xBB4pjhpjuTuvZVwNB4rdci1NPwDEKyDJmU/IG/CzGRj2Xmq0/dCoQm0xwMY3A\
224 X7MGWHi/Kt8bhFR1wuxDLOpqvCIGS+5s0gZqwn5gQCDtFY1tpL5stDRcZIyHh1EobWG9daGGMnx7s/tb\
225 69cuhSKC5g3oylZ8H3LjW+eOZtuqPs/5vS7/WwIDAQABAoIBAGcwmQAPdyZus3OVwa1NCUD2KyB+39KG\
226 yNmWwgx+br9Jx4s+RnJghVh8BS4MIKZOBtSRaEUOuCvAMNrupZbD+8leq34vDDRcQpCizr+M6Egj6FRj\
227 Ewl+7Mh+yeN2hbMoghL552MTv9D4Iyxteu4nuPDd/JQ3oQwbDFIL6mlBFtiBDUr9ndemmcJ0WKuzor6a\
228 3rgsygLs8SPyMefwIKjh5rJZls+iv3AyVEoBdCbHBz0HKgLVE9ZNmY/gWqda2dzAcJxxMdafeNVwHovv\
229 BtyyRGnA7Yikx2XT4WLgKfuUsYLnDWs4GdAa738uxPBfiddQNeRjN7jRT1GZIWCk0P29rMECgYEA8jWi\
230 g1Dph+4VlESPOffTEt1aCYQQWtHs13Qex95HrXX/L49fs6cOE7pvBh7nVzaKwBnPRh5+3bCPsPmRVb7h\
231 k/GreOriCjTZtyt2XGp8eIfstfirofB7c1lNBjT61BhgjJ8Moii5c2ksNIOOZnKtD53n47mf7hiarYkw\
232 xFEgU6ECgYEAxE8Js3gIPOBjsSw47XHuvsjP880nZZx/oiQ4IeJb/0rkoDMVJjU69WQu1HTNNAnMg4/u\
233 RXo31h+gDZOlE9t9vSXHdrn3at67KAVmoTbRknGxZ+8tYpRJpPj1hyufynBGcKwevv3eHJHnE5eDqbHx\
234 ynZFkXemzT9aMy3R4CCFMXsCgYAYyZpnG/m6WohE0zthMFaeoJ6dSLGvyboWVqDrzXjCbMf/4wllRlxv\
235 cm34T2NXjpJmlH2c7HQJVg9uiivwfYdyb5If3tHhP4VkdIM5dABnCWoVOWy/NvA7XtE+KF/fItuGqKRP\
236 WCGaiRHoEeqZ23SQm5VmvdF7OXNi/R5LiQ3o4QKBgAGX8qg2TTrRR33ksgGbbyi1UJrWC3/TqWWTjbEY\
237 uU51OS3jvEQ3ImdjjM3EtPW7LqHSxUhjGZjvYMk7bZefrIGgkOHx2IRRkotcn9ynKURbD+mcE249beuc\
238 6cFTJVTrXGcFvqomPWtV895A2JzECQZvt1ja88uuu/i2YoHDQdGJAoGAL2TEgiMXiunb6PzYMMKKa+mx\
239 mFnagF0Ek3UJ9ByXKoLz3HFEl7cADIkqyenXFsAER/ifMyCoZp/PDBd6ZkpqLTdH0jQ2Yo4SllLykoiZ\
240 fBWMfjRu4iw9E0MbPB3blmtzfv53BtWKy0LUOlN4juvpqryA7TgaUlZkfMT+T1TC7xU=\
241 ";
242
243 static const int kTestStoreCertToIOS = 5;
244 static void test_store_cert_to_ios() {
245 // Create certificate instance.
246 NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64]
247 options:NSDataBase64DecodingIgnoreUnknownCharacters];
248 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
249 ok(cert != NULL, "create certificate from data");
250
251 // Store certificate to modern keychain.
252 NSDictionary *attrs = @{
253 (id)kSecValueRef: (id)cert,
254 (id)kSecAttrLabel: @"sectests:store_cert_to_ios",
255 (id)kSecAttrNoLegacy: @YES,
256 (id)kSecReturnPersistentRef: @YES,
257 };
258 id persistentRef;
259 ok_status(SecItemAdd((CFDictionaryRef)attrs, (void *)&persistentRef), "store certificate into iOS keychain");
260
261 // Query certificate, without specification of the keychain.
262 NSDictionary *query = @{
263 (id)kSecClass: (id)kSecClassCertificate,
264 (id)kSecAttrLabel: @"sectests:store_cert_to_ios",
265 (id)kSecReturnRef: @YES,
266 };
267 SecCertificateRef queriedCert = NULL;
268 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (void *)&queriedCert), "query certificate back");
269 eq_cf(cert, queriedCert, "stored and retrieved certificates are the same");
270
271 ok_status(SecItemDelete((CFDictionaryRef)@{ (id)kSecValuePersistentRef: persistentRef }),
272 "delete certificate from keychain");
273 CFReleaseNull(cert);
274 }
275
276 static const int kTestStoreIdentityToIOS = 6;
277 static void test_store_identity_to_ios() {
278 // Create certificate instance.
279 NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64]
280 options:NSDataBase64DecodingIgnoreUnknownCharacters];
281 SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
282 ok(certificate != NULL, "create certificate from data");
283
284 // Create private key instance.
285 NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64]
286 options:NSDataBase64DecodingIgnoreUnknownCharacters];
287 NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048,
288 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate };
289 SecKeyRef privateKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL);
290 ok(privateKey != NULL, "create private key from data");
291
292 // Create identity from certificate and private key.
293 SecIdentityRef identity = SecIdentityCreate(kCFAllocatorDefault, certificate, privateKey);
294
295 // Store identity to the iOS keychain.
296 NSDictionary *attrs = @{
297 (id)kSecValueRef: (id)identity,
298 (id)kSecAttrLabel: @"sectests:store_identity_to_ios",
299 (id)kSecAttrNoLegacy: @YES,
300 (id)kSecReturnPersistentRef: @YES,
301 };
302 id persistentRef;
303 ok_status(SecItemAdd((CFDictionaryRef)attrs, (void *)&persistentRef), "store identity into iOS keychain");
304
305 NSDictionary *query = @{
306 (id)kSecClass: (id)kSecClassIdentity,
307 (id)kSecAttrLabel: @"sectests:store_identity_to_ios",
308 (id)kSecReturnRef: @YES,
309 };
310 SecIdentityRef queriedIdentity = NULL;
311 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (void *)&queriedIdentity), "query identity from keychain");
312 eq_cf(identity, queriedIdentity, "stored and retrieved identities are identical");
313
314 // Cleanup identity.
315 ok_status(SecItemDelete((CFDictionaryRef)@{ (id)kSecValuePersistentRef: persistentRef}),
316 "delete identity from iOS keychain");
317
318 CFReleaseNull(identity);
319 CFReleaseNull(privateKey);
320 CFReleaseNull(certificate);
321 }
322
323 static const int kTestTransformWithIOSKey = 9;
324 static void test_transform_with_ioskey() {
325 // Create private key instance.
326 NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64]
327 options:NSDataBase64DecodingIgnoreUnknownCharacters];
328 NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048,
329 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate };
330 SecKeyRef privateKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL);
331 ok(privateKey != NULL, "create private key from data");
332
333 // Create signature transform with private key
334 NSData *testData = [NSData dataWithBytes:"test" length:4];
335 SecTransformRef signer = SecSignTransformCreate(privateKey, NULL);
336 ok(signer != NULL, "create signing transform");
337 ok(SecTransformSetAttribute(signer, kSecTransformInputAttributeName, (CFDataRef)testData, NULL),
338 "set input data to verify transform");
339 NSData *signature = (NSData *)SecTransformExecute(signer, NULL);
340 ok(signature != nil, "create signature with transform");
341
342 // Create verify transform with public key.
343 SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);
344 ok(publicKey != NULL, "get public key from private key");
345 SecTransformRef verifier = SecVerifyTransformCreate(publicKey, (CFDataRef)signature, NULL);
346 ok(verifier, "create verification transform");
347 ok(SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, (CFDataRef)testData, NULL),
348 "set input data to verify transform");
349
350 NSNumber *result = (NSNumber *)SecTransformExecute(verifier, NULL);
351 ok(result != nil, "transform execution succeeded");
352 ok(result.boolValue, "transform verified signature");
353
354 CFReleaseNull(signer);
355 CFReleaseNull(verifier);
356 CFReleaseNull(publicKey);
357 CFReleaseNull(privateKey);
358 }
359
360 static const int kTestConvertKeyToPersistentRef = 11;
361 static void test_convert_key_to_persistent_ref() {
362 NSString *label = @"sectests:convert-key-to-persistent-ref";
363
364 // Create
365 SecKeyRef privKey = NULL;
366 {
367 NSDictionary *query = @{
368 (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
369 (id)kSecAttrKeySizeInBits: @1024,
370 (id)kSecAttrNoLegacy: @YES,
371 (id)kSecAttrIsPermanent: @NO,
372 };
373 SecKeyRef pubKey = NULL;
374 ok_status(SecKeyGeneratePair((CFDictionaryRef)query, &pubKey, &privKey));
375 CFReleaseNull(pubKey);
376 }
377
378 // Store
379 {
380 NSDictionary *query = @{
381 (id)kSecAttrLabel: label,
382 (id)kSecValueRef: (id)privKey,
383 (id)kSecAttrNoLegacy: @YES,
384 };
385 ok_status(SecItemAdd((CFDictionaryRef)query, NULL));
386 }
387
388 // Convert & Compare
389 CFDataRef queriedPersistentKeyRef = NULL;
390 SecKeyRef queriedKeyRef = NULL;
391 {
392 NSDictionary *query = @{
393 (id)kSecValueRef: (id)privKey,
394 (id)kSecReturnPersistentRef: @YES,
395 (id)kSecAttrNoLegacy: @YES,
396 };
397 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentKeyRef));
398 }{
399 NSDictionary *query = @{
400 (id)kSecValuePersistentRef: (id)queriedPersistentKeyRef,
401 (id)kSecReturnRef: @YES,
402 (id)kSecAttrNoLegacy: @YES,
403 };
404 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedKeyRef));
405 }{
406 CFDataRef persistentKeyRef = NULL;
407 SecKeychainItemRef keyRef = NULL;
408 ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)privKey, &persistentKeyRef));
409 ok_status(SecKeychainItemCopyFromPersistentReference(persistentKeyRef, &keyRef));
410 eq_cf(privKey, queriedKeyRef);
411 eq_cf(keyRef, privKey);
412 eq_cf(persistentKeyRef, queriedPersistentKeyRef);
413 CFReleaseNull(persistentKeyRef);
414 CFReleaseNull(keyRef);
415 }
416 CFReleaseNull(queriedPersistentKeyRef);
417 CFReleaseNull(queriedKeyRef);
418
419 // Cleanup
420 CFReleaseNull(privKey);
421 {
422 NSDictionary *query = @{
423 (id)kSecClass: (id)kSecClassKey,
424 (id)kSecAttrLabel: label,
425 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
426 };
427 ok_status(SecItemDelete((CFDictionaryRef)query));
428 is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound);
429 }
430 }
431
432 static const int kTestConvertCertToPersistentRef = 11;
433 static void test_convert_cert_to_persistent_ref() {
434 NSString *label = @"sectests:convert-cert-to-persistent-ref";
435
436 // Create
437 SecCertificateRef cert = NULL;
438 {
439 NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64]
440 options:NSDataBase64DecodingIgnoreUnknownCharacters];
441 cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
442 ok(cert);
443 }
444
445 // Store
446 {
447 NSDictionary *query = @{
448 (id)kSecAttrLabel: label,
449 (id)kSecValueRef: (id)cert,
450 (id)kSecAttrNoLegacy: @YES,
451 };
452 ok_status(SecItemAdd((CFDictionaryRef)query, NULL));
453 }
454
455 // Convert & Compare
456 CFDataRef queriedPersistentCertRef = NULL;
457 SecCertificateRef queriedCertRef = NULL;
458 {
459 NSDictionary *query = @{
460 (id)kSecValueRef: (id)cert,
461 (id)kSecReturnPersistentRef: @YES,
462 (id)kSecAttrNoLegacy: @YES,
463 };
464 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentCertRef));
465 }{
466 NSDictionary *query = @{
467 (id)kSecValuePersistentRef: (id)queriedPersistentCertRef,
468 (id)kSecReturnRef: @YES,
469 (id)kSecAttrNoLegacy: @YES,
470 };
471 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedCertRef));
472 }{
473 CFDataRef persistentCertRef = NULL;
474 SecKeychainItemRef certRef = NULL;
475 ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert, &persistentCertRef));
476 ok_status(SecKeychainItemCopyFromPersistentReference(persistentCertRef, &certRef));
477 eq_cf(cert, queriedCertRef);
478 eq_cf(certRef, cert);
479 eq_cf(persistentCertRef, queriedPersistentCertRef);
480 CFReleaseNull(persistentCertRef);
481 CFReleaseNull(certRef);
482 }
483 CFReleaseNull(queriedPersistentCertRef);
484 CFReleaseNull(queriedCertRef);
485
486 // Cleanup
487 CFReleaseNull(cert);
488 {
489 NSDictionary *query = @{
490 (id)kSecClass: (id)kSecClassCertificate,
491 (id)kSecAttrLabel: label,
492 (id)kSecMatchLimit: (id)kSecMatchLimitAll,
493 };
494 ok_status(SecItemDelete((CFDictionaryRef)query));
495 is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound);
496 }
497 }
498
499 static const int kTestConvertIdentityToPersistentRef = 12;
500 static void test_convert_identity_to_persistent_ref() {
501 NSString *label = @"sectests:convert-identity-to-persistent-ref";
502
503 // Create
504 SecIdentityRef idnt = NULL;
505 {
506 NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64]
507 options:NSDataBase64DecodingIgnoreUnknownCharacters];
508 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
509 ok(cert);
510 NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64]
511 options:NSDataBase64DecodingIgnoreUnknownCharacters];
512 NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
513 (id)kSecAttrKeySizeInBits: @2048,
514 (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate };
515 SecKeyRef privKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL);
516 ok(privKey);
517 idnt = SecIdentityCreate(kCFAllocatorDefault, cert, privKey);
518 CFReleaseNull(cert);
519 CFReleaseNull(privKey);
520 }
521
522 // Store
523 {
524 NSDictionary *query = @{
525 (id)kSecAttrLabel: label,
526 (id)kSecValueRef: (id)idnt,
527 (id)kSecAttrNoLegacy: @YES,
528 };
529 ok_status(SecItemAdd((CFDictionaryRef)query, NULL));
530 }
531
532 // Convert & Compare
533 CFDataRef queriedPersistentIdntRef = NULL;
534 SecIdentityRef queriedIdntRef = NULL;
535 {
536 NSDictionary *query = @{
537 (id)kSecValueRef: (id)idnt,
538 (id)kSecReturnPersistentRef: @YES,
539 (id)kSecAttrNoLegacy: @YES,
540 };
541 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentIdntRef));
542 }{
543 NSDictionary *query = @{
544 (id)kSecValuePersistentRef: (id)queriedPersistentIdntRef,
545 (id)kSecReturnRef: @YES,
546 (id)kSecAttrNoLegacy: @YES,
547 };
548 ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedIdntRef));
549 }{
550 CFDataRef persistentIdntRef = NULL;
551 SecKeychainItemRef idntRef = NULL;
552 ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)idnt, &persistentIdntRef));
553 ok_status(SecKeychainItemCopyFromPersistentReference(persistentIdntRef, &idntRef));
554 eq_cf(idnt, queriedIdntRef);
555 eq_cf(idntRef, idnt);
556 eq_cf(persistentIdntRef, queriedPersistentIdntRef);
557 CFReleaseNull(persistentIdntRef);
558 CFReleaseNull(idntRef);
559 }
560 CFReleaseNull(queriedPersistentIdntRef);
561 CFReleaseNull(queriedIdntRef);
562
563 // Cleanup
564 {
565 NSDictionary *query = @{
566 // identities can't be filtered out using 'label', so we will use directly the ValueRef here:
567 (id)kSecValueRef: (id)idnt,
568 (id)kSecAttrNoLegacy: @YES,
569 };
570 ok_status(SecItemDelete((CFDictionaryRef)query));
571 is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound);
572 }
573 CFReleaseNull(idnt);
574 }
575
576 static const int kTestCount =
577 kTestGenerateNoLegacyCount +
578 kTestGenerateAccessControlCount +
579 kTestAddIOSKeyCount +
580 kTestStoreCertToIOS +
581 kTestStoreIdentityToIOS +
582 kTestTransformWithIOSKey +
583 kTestConvertKeyToPersistentRef +
584 kTestConvertCertToPersistentRef +
585 kTestConvertIdentityToPersistentRef;
586
587 int kc_43_seckey_interop(int argc, char *const *argv) {
588 plan_tests(kTestCount);
589
590 test_generate_nolegacy();
591 #if !RC_HIDE_J79 && !RC_HIDE_J80
592 test_generate_access_control();
593 #endif
594 test_add_ios_key();
595 test_store_cert_to_ios();
596 test_store_identity_to_ios();
597 test_transform_with_ioskey();
598 test_convert_key_to_persistent_ref();
599 test_convert_cert_to_persistent_ref();
600 test_convert_identity_to_persistent_ref();
601
602 return 0;
603 }