2 * Copyright (c) 2008-2010,2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
25 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
32 #include <sys/types.h>
38 #include <CoreFoundation/CFData.h>
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFNumber.h>
41 #include <CoreFoundation/CFString.h>
42 #include <Security/SecImportExport.h>
43 #include <Security/SecItem.h>
44 #include <Security/SecCertificate.h>
45 #include <Security/SecIdentity.h>
46 #include <Security/SecTrust.h>
47 #include <Security/SecInternal.h>
48 #include <utilities/array_size.h>
50 #include "SecurityCommands.h"
51 #include "SecurityTool/sharedTool/print_cert.h"
54 read_file(const char * filename
, size_t * data_length
)
62 if (stat(filename
, &sb
) < 0)
64 if (sb
.st_size
> INT32_MAX
)
66 len
= (uint32_t)sb
.st_size
;
74 fd
= open(filename
, O_RDONLY
);
78 if (read(fd
, data
, len
) != len
) {
91 add_cert_item(SecCertificateRef cert
)
96 dict
= CFDictionaryCreate(NULL
,
97 (const void * *)&kSecValueRef
,
98 (const void * *)&cert
, 1,
99 &kCFTypeDictionaryKeyCallBacks
,
100 &kCFTypeDictionaryValueCallBacks
);
101 status
= SecItemAdd(dict
, NULL
);
107 remove_cert_item(SecCertificateRef cert
)
109 CFDictionaryRef dict
;
112 dict
= CFDictionaryCreate(NULL
,
113 (const void * *)&kSecValueRef
,
114 (const void * *)&cert
, 1,
115 &kCFTypeDictionaryKeyCallBacks
,
116 &kCFTypeDictionaryValueCallBacks
);
117 status
= SecItemDelete(dict
);
119 if (status
== errSecItemNotFound
)
120 status
= errSecSuccess
; /* already gone, no problem */
125 PKCS12FileCreateArray(const char * filename
, const char * password
)
127 void * file_data
= NULL
;
128 size_t file_data_length
;
129 CFArrayRef items
= NULL
;
130 CFDictionaryRef options
= NULL
;
131 CFDataRef pkcs12_data
= NULL
;
132 CFStringRef password_cf
= NULL
;
134 file_data
= read_file(filename
, &file_data_length
);
135 if (file_data
== NULL
) {
136 int this_error
= errno
;
138 fprintf(stderr
, "failed to read file '%s', %s\n",
139 filename
, strerror(this_error
));
142 pkcs12_data
= CFDataCreate(NULL
, file_data
, file_data_length
);
144 = CFStringCreateWithCString(NULL
, password
, kCFStringEncodingUTF8
);
146 options
= CFDictionaryCreate(NULL
,
147 (const void * *)&kSecImportExportPassphrase
,
148 (const void * *)&password_cf
, 1,
149 &kCFTypeDictionaryKeyCallBacks
,
150 &kCFTypeDictionaryValueCallBacks
);
151 if (SecPKCS12Import(pkcs12_data
, options
, &items
) != 0) {
152 fprintf(stderr
, "failed to import PKCS12 '%s'\n",
156 if (file_data
!= NULL
) {
159 CFReleaseNull(pkcs12_data
);
160 CFReleaseNull(password_cf
);
161 CFReleaseNull(options
);
166 find_identity_using_handle(CFTypeRef identity_handle
)
168 CFDictionaryRef dict
;
169 CFTypeRef identity_ref
;
170 const void * keys
[] = { kSecClass
,
172 kSecValuePersistentRef
};
173 const void * values
[] = { kSecClassIdentity
,
178 /* find the identity using the persistent handle */
179 dict
= CFDictionaryCreate(NULL
, keys
, values
,
181 &kCFTypeDictionaryKeyCallBacks
,
182 &kCFTypeDictionaryValueCallBacks
);
183 status
= SecItemCopyMatching(dict
, &identity_ref
);
185 if (status
!= errSecSuccess
) {
186 fprintf(stderr
, "SecItemCopyMatching() failed %d\n",
190 printf("Found identity:\n");
193 CFShow(identity_ref
);
194 CFReleaseNull(identity_ref
);
200 PKCS12ArrayAddSecItems(CFArrayRef items
, bool verbose
)
206 count
= CFArrayGetCount(items
);
207 for (i
= 0; i
< count
; i
++) {
208 SecTrustRef trust_ref
;
209 SecIdentityRef identity
;
210 CFDictionaryRef item_dict
= CFArrayGetValueAtIndex(items
, 0);
214 identity
= (SecIdentityRef
)CFDictionaryGetValue(item_dict
, kSecImportItemIdentity
);
215 if (identity
!= NULL
) {
217 SecCertificateRef cert
= NULL
;
218 SecIdentityCopyCertificate(identity
, &cert
);
219 print_cert(cert
, false);
222 CFDictionaryRef dict
;
223 CFTypeRef identity_handle
= NULL
;
224 const void * keys
[] = { kSecReturnPersistentRef
,
226 const void * values
[] = { kCFBooleanTrue
,
228 dict
= CFDictionaryCreate(NULL
,
231 &kCFTypeDictionaryKeyCallBacks
,
232 &kCFTypeDictionaryValueCallBacks
);
233 status
= SecItemAdd(dict
, &identity_handle
);
234 if (identity_handle
!= NULL
) {
235 find_identity_using_handle(identity_handle
);
237 CFReleaseNull(identity_handle
);
238 if (status
!= errSecSuccess
) {
239 fprintf(stderr
, "SecItemAdd(identity) failed %d\n",
247 trust_ref
= (SecTrustRef
)CFDictionaryGetValue(item_dict
, kSecImportItemTrust
);
248 if (trust_ref
!= NULL
) {
252 cert_count
= SecTrustGetCertificateCount(trust_ref
);
253 for (cert_index
= 1; cert_index
< cert_count
; cert_index
++) {
254 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust_ref
, cert_index
);
256 print_cert(cert
, false);
257 status
= add_cert_item(cert
);
258 if (status
!= errSecSuccess
) {
259 fprintf(stderr
, "add_cert_item %d failed %d\n", (int)cert_index
, (int)status
);
269 PKCS12ArrayRemoveSecItems(CFArrayRef items
, bool verbose
)
275 count
= CFArrayGetCount(items
);
276 for (i
= 0; i
< count
; i
++) {
277 CFTypeRef cert_chain
;
278 SecIdentityRef identity
;
279 CFDictionaryRef item_dict
= CFArrayGetValueAtIndex(items
, i
);
282 /* remove identity */
283 identity
= (SecIdentityRef
)CFDictionaryGetValue(item_dict
,
284 kSecImportItemIdentity
);
285 if (identity
!= NULL
) {
287 SecCertificateRef cert
= NULL
;
288 SecIdentityCopyCertificate(identity
, &cert
);
289 print_cert(cert
, false);
292 CFDictionaryRef dict
;
294 dict
= CFDictionaryCreate(NULL
,
295 (const void * *)&kSecValueRef
,
296 (const void * *)&identity
, 1,
297 &kCFTypeDictionaryKeyCallBacks
,
298 &kCFTypeDictionaryValueCallBacks
);
299 status
= SecItemDelete(dict
);
300 if (status
!= errSecSuccess
) {
301 fprintf(stderr
, "SecItemDelete(identity) failed %d\n",
307 /* remove cert chain */
308 cert_chain
= CFDictionaryGetValue(item_dict
, kSecImportItemCertChain
);
309 if (cert_chain
!= NULL
) {
313 cert_count
= CFArrayGetCount(cert_chain
);
314 for (cert_index
= 0; cert_index
< cert_count
; cert_index
++) {
315 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(cert_chain
, cert_index
);
317 print_cert(cert
, false);
318 status
= remove_cert_item(cert
);
319 if (status
!= errSecSuccess
) {
320 fprintf(stderr
, "remove_cert_item %d failed %d\n", (int)cert_index
, (int)status
);
330 extern int pkcs12_util(int argc
, char * const *argv
)
333 const char * filename
= NULL
;
334 const char * passphrase
= NULL
;
336 bool verbose
= false;
339 while ((ch
= getopt(argc
, argv
, "p:dv")) != -1)
353 return SHOW_USAGE_MESSAGE
;
360 if (argc
!= 1 || !passphrase
)
361 return SHOW_USAGE_MESSAGE
;
364 array
= PKCS12FileCreateArray(filename
, passphrase
);
368 bool success
= false;
370 success
= PKCS12ArrayRemoveSecItems(array
, verbose
);
372 success
= PKCS12ArrayAddSecItems(array
, verbose
);
374 CFReleaseNull(array
);
376 return success
? 0 : -1;
379 #endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR