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