]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-20-identity-persistent-refs.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-20-identity-persistent-refs.c
1 /*
2 * Copyright (c) 2016 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 xLicense.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import <Security/Security.h>
25
26 #include "keychain_regressions.h"
27 #include "kc-helpers.h"
28
29 // Tests the ability of SecItemCopyMatching to return a persistent ref for either a
30 // SecIdentityRef or a SecCertificateRef which happens to be part of an identity,
31 // then reconstitute the appropriate type of ref from the persistent reference.
32 //
33
34 #include <CoreFoundation/CoreFoundation.h>
35 #include <CoreServices/CoreServices.h>
36 #include <Security/Security.h>
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <syslog.h>
41 #include <unistd.h>
42 #include <time.h>
43 #include <sys/param.h>
44 #include "kc-identity-helpers.h"
45
46 #define MAXNAMELEN MAXPATHLEN
47 #define MAXITEMS INT32_MAX
48
49 static CFDataRef
50 copyPersistentReferenceForItem(CFTypeRef item)
51 {
52 // Given either a SecIdentityRef or SecCertificateRef item reference,
53 // return a persistent reference. Caller must release the reference.
54
55 OSStatus status;
56 CFDataRef persistentRef = NULL;
57 CFDictionaryRef query = NULL;
58
59 const void *keys[] = { kSecReturnPersistentRef, kSecValueRef };
60 const void *values[] = { kCFBooleanTrue, item };
61
62 query = CFDictionaryCreate(NULL, keys, values,
63 (sizeof(keys) / sizeof(*keys)), NULL, NULL);
64 status = SecItemCopyMatching(query, (CFTypeRef *)&persistentRef);
65 ok_status(status, "%s: SecItemCopyMatching (copyPersistentReferenceForItem)", testName);
66 CFRelease(query);
67 return persistentRef;
68 }
69
70 static CFTypeRef
71 copyItemForPersistentReference(CFDataRef persistentRef)
72 {
73 // Given a persistent reference, reconstitute it into an item
74 // reference. Depending on whether the persistent reference was
75 // originally made to a SecIdentityRef or SecCertificateRef, this
76 // should return the same item type as the original.
77 // Caller must release the reference.
78
79 OSStatus status;
80 CFTypeRef itemRef = NULL;
81 CFDictionaryRef query = NULL;
82 const void *keys[] = { kSecReturnRef, kSecValuePersistentRef };
83 const void *values[] = { kCFBooleanTrue, persistentRef };
84
85 query = CFDictionaryCreate(NULL, keys, values,
86 (sizeof(keys) / sizeof(*keys)), NULL, NULL);
87 status = SecItemCopyMatching(query, &itemRef);
88 ok_status(status, "%s: SecItemCopyMatching (copyItemForPersistentReference)", testName);
89 CFRelease(query);
90 return itemRef;
91 }
92
93 static void
94 testIdentityPersistence(SecKeychainRef kc)
95 {
96 startTest(__FUNCTION__);
97
98 // Step 1: get a SecIdentityRef
99 SecIdentityRef identity = copyFirstIdentity(kc);
100 is(CFGetTypeID(identity), SecIdentityGetTypeID(), "%s: retrieved identity is an identity", testName);
101
102 // Step 2: make a persistent reference for it
103 CFDataRef data = copyPersistentReferenceForItem((CFTypeRef)identity);
104
105 // Step 3: reconstitute the persistent reference
106 SecIdentityRef identity2 = (SecIdentityRef) copyItemForPersistentReference(data);
107 CFReleaseNull(data);
108
109 ok(identity2, "%s: retrieved an identity", testName);
110 if(identity2) {
111 is(CFGetTypeID(identity2), SecIdentityGetTypeID(), "%s: retrieved identity is an identity", testName);
112 } else {
113 fail("%s: no identity to test", testName);
114 }
115 eq_cf(identity2, identity, "%s: identities are equal", testName);
116
117 CFReleaseNull(identity);
118 CFReleaseNull(identity2);
119 }
120
121 static void
122 testCertificatePersistence(SecKeychainRef kc)
123 {
124 startTest(__FUNCTION__);
125
126 // Step 1: get a SecIdentityRef
127 SecIdentityRef identity = copyFirstIdentity(kc);
128
129 // Step 2: get a SecCertificateRef from it
130 SecCertificateRef cert = NULL, cert2 = NULL;
131 OSStatus status = SecIdentityCopyCertificate(identity, &cert);
132 ok_status(status, "%s: SecIdentityCopyCertificate", testName);
133 ok(cert, "%s: No certificate returned from SecIdentityCopyCertificate", testName);
134 CFReleaseNull(identity);
135
136 // Step 3: make a persistent reference for it
137 CFDataRef data = (CFDataRef) copyPersistentReferenceForItem(cert);
138
139 // Step 4: reconstitute the persistent reference
140 cert2 = (SecCertificateRef) copyItemForPersistentReference(data);
141
142 ok(cert2, "%s: retrieved a certificate", testName);
143 if(cert2) {
144 is(CFGetTypeID(cert2), SecCertificateGetTypeID(), "%s: returned value is a certificate", testName);
145 } else {
146 fail("%s: no certificate to test", testName);
147 }
148
149 eq_cf(cert2, cert, "%s: Certificates are equal", testName);
150
151 CFReleaseNull(data);
152 CFReleaseNull(cert);
153 CFReleaseNull(cert2);
154 }
155
156 int kc_20_identity_persistent_refs(int argc, char *const *argv)
157 {
158 plan_tests(18);
159 initializeKeychainTests(__FUNCTION__);
160
161 SecKeychainRef kc = getPopulatedTestKeychain();
162
163 // You cannot reconsitute a Persistent Reference for an identity if the keychain is not in the search list.
164 addToSearchList(kc);
165
166 testCertificatePersistence(kc);
167 testIdentityPersistence(kc);
168
169 ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName);
170 CFReleaseNull(kc);
171
172 deleteTestFiles();
173 return 0;
174 }