]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecImportExport.c
Security-59306.80.4.tar.gz
[apple/security.git] / OSX / sec / Security / SecImportExport.c
1 /*
2 * Copyright (c) 2007-2008,2012-2013 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 <Security/SecBase.h>
25 #include <Security/SecBasePriv.h>
26 #include <Security/SecItem.h>
27 #include <Security/SecRSAKey.h>
28 #include <Security/SecECKey.h>
29 #include <Security/SecCertificate.h>
30 #include <Security/SecIdentityPriv.h>
31 #include <Security/SecPolicy.h>
32 #include <Security/SecTrust.h>
33 #include <Security/SecInternal.h>
34 #include <libDER/oids.h>
35
36 #include <AssertMacros.h>
37
38 #include "p12import.h"
39 #include <Security/SecImportExportPriv.h>
40
41 #if !TARGET_OS_OSX
42 const CFStringRef kSecImportExportPassphrase = CFSTR("passphrase");
43 const CFStringRef kSecImportItemLabel = CFSTR("label");
44 const CFStringRef kSecImportItemKeyID = CFSTR("keyid");
45 const CFStringRef kSecImportItemTrust = CFSTR("trust");
46 const CFStringRef kSecImportItemCertChain = CFSTR("chain");
47 const CFStringRef kSecImportItemIdentity = CFSTR("identity");
48 #endif
49
50 typedef struct {
51 CFMutableArrayRef certs;
52 p12_error *status;
53 } collect_certs_context;
54
55
56 static void collect_certs(const void *key, const void *value, void *context)
57 {
58 if (!CFDictionaryContainsKey(value, CFSTR("key"))) {
59 CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert"));
60 if (!cert_bytes)
61 return;
62 collect_certs_context *a_collect_certs_context = (collect_certs_context *)context;
63 SecCertificateRef cert =
64 SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes);
65 if (!cert) {
66 *a_collect_certs_context->status = p12_decodeErr;
67 return;
68 }
69 CFMutableArrayRef cert_array = a_collect_certs_context->certs;
70 CFArrayAppendValue(cert_array, cert);
71 CFRelease(cert);
72 }
73 }
74
75 typedef struct {
76 CFMutableArrayRef identities;
77 CFArrayRef certs;
78 p12_error *status;
79 } build_trust_chains_context;
80
81 static void build_trust_chains(const void *key, const void *value,
82 void *context)
83 {
84 CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
85 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
86 SecKeyRef private_key = NULL;
87 SecCertificateRef cert = NULL;
88 SecIdentityRef identity = NULL;
89 SecPolicyRef policy = NULL;
90 CFMutableArrayRef cert_chain = NULL, eval_chain = NULL;
91 SecTrustRef trust = NULL;
92 build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context;
93
94 CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key"));
95 require(key_bytes, out);
96 CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert"));
97 require(cert_bytes, out);
98 CFDataRef algoid_bytes = CFDictionaryGetValue(value, CFSTR("algid"));
99
100
101 DERItem algorithm = { (DERByte *)CFDataGetBytePtr(algoid_bytes), CFDataGetLength(algoid_bytes) };
102 if (DEROidCompare(&oidEcPubKey, &algorithm)) {
103 require (private_key = SecKeyCreateECPrivateKey(kCFAllocatorDefault,
104 CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes),
105 kSecKeyEncodingPkcs1), out);
106 } else if (DEROidCompare(&oidRsa, &algorithm)) {
107 require (private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault,
108 CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes),
109 kSecKeyEncodingPkcs1), out);
110 } else {
111 *a_build_trust_chains_context->status = p12_decodeErr;
112 goto out;
113 }
114
115 require_action(cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes), out,
116 *a_build_trust_chains_context->status = p12_decodeErr);
117 require_action(identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key), out,
118 *a_build_trust_chains_context->status = p12_decodeErr);
119 CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity);
120
121 eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
122 require(eval_chain, out);
123 CFArrayAppendValue(eval_chain, cert);
124 CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) };
125 CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs);
126 require(policy = SecPolicyCreateBasicX509(), out);
127 SecTrustResultType result;
128 SecTrustCreateWithCertificates(eval_chain, policy, &trust);
129 require(trust, out);
130 SecTrustEvaluate(trust, &result);
131 CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust);
132
133 require(cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), out);
134 CFIndex cert_chain_length = SecTrustGetCertificateCount(trust);
135 int i;
136 for (i = 0; i < cert_chain_length; i++)
137 CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i));
138 CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain);
139
140 CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict);
141 out:
142 CFReleaseSafe(identity_dict);
143 CFReleaseSafe(identity);
144 CFReleaseSafe(private_key);
145 CFReleaseSafe(cert);
146 CFReleaseSafe(policy);
147 CFReleaseSafe(cert_chain);
148 CFReleaseSafe(eval_chain);
149 CFReleaseSafe(trust);
150 }
151
152 #if TARGET_OS_OSX
153 OSStatus SecPKCS12Import_ios(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items)
154 #else
155 OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items)
156 #endif
157 {
158 pkcs12_context context = {};
159 SecAsn1CoderCreate(&context.coder);
160 if (options)
161 context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase);
162 context.items = CFDictionaryCreateMutable(kCFAllocatorDefault,
163 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
164 p12_error status = p12decode(&context, pkcs12_data);
165 if (!status) {
166 CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
167 collect_certs_context a_collect_certs_context = { certs, &status };
168 CFDictionaryApplyFunction(context.items, collect_certs, &a_collect_certs_context);
169
170 if (!status) {
171 CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
172 build_trust_chains_context a_build_trust_chains_context = { identities, certs, &status };
173 CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context);
174 CFReleaseSafe(certs);
175
176 /* ignoring certs that weren't picked up as part of the certchain for found keys */
177 *items = identities;
178 }
179 }
180
181 CFReleaseSafe(context.items);
182 SecAsn1CoderRelease(context.coder);
183
184 switch (status) {
185 case p12_noErr: return errSecSuccess;
186 case p12_passwordErr: return errSecAuthFailed;
187 case p12_decodeErr: return errSecDecode;
188 default: return errSecInternal;
189 };
190 return errSecSuccess;
191 }
192