]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 | * pkcs12Coder.cpp - Public P12Coder coder functions. | |
26 | */ | |
27 | ||
28 | #include "pkcs12Coder.h" | |
29 | #include "pkcs12Debug.h" | |
30 | #include "pkcs12Utils.h" | |
31 | #include <Security/cssmerr.h> | |
32 | #include <security_cdsa_utils/cuCdsaUtils.h> | |
b1ab9ed8 | 33 | #include <Security/oidsalg.h> |
427c49bc | 34 | #include <Security/SecBase.h> |
b1ab9ed8 A |
35 | /* |
36 | * Default encryption parameters | |
37 | */ | |
38 | #define P12_ENCR_ITER_COUNT 2048 | |
39 | #define P12_MAC_ITER_COUNT 1 | |
40 | #define P12_WEAK_ENCR_ALG CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC | |
41 | #define P12_STRONG_ENCR_ALG CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC | |
42 | ||
43 | /* | |
44 | * Default import flags. | |
45 | */ | |
46 | #define P12_KC_IMPORT_DEFAULT (kSecImportCertificates | \ | |
47 | kSecImportCRLs | \ | |
48 | kSecImportKeys) | |
49 | ||
50 | P12Coder::P12Coder() | |
51 | { | |
52 | init(); | |
53 | } | |
54 | ||
55 | /* one-time init from all constructors */ | |
56 | void P12Coder::init() | |
57 | { | |
58 | mPrivacyMode = kSecPkcs12ModePassword; | |
59 | mIntegrityMode = kSecPkcs12ModePassword; | |
60 | mMacPassphrase = NULL; | |
61 | mEncrPassPhrase = NULL; | |
62 | mMacPassData.Data = NULL; | |
63 | mMacPassData.Length = 0; | |
64 | mEncrPassData.Data = NULL; | |
65 | mEncrPassData.Length = 0; | |
66 | mMacPassKey = NULL; | |
67 | mEncrPassKey = NULL; | |
68 | mKeychain = NULL; | |
69 | mCspHand = 0; | |
70 | mDlDbHand.DLHandle = 0; | |
71 | mDlDbHand.DBHandle = 0; | |
72 | mPrivKeyImportState = PKIS_NoLimit; | |
73 | mWeakEncrAlg = P12_WEAK_ENCR_ALG; | |
74 | mStrongEncrAlg = P12_STRONG_ENCR_ALG; | |
75 | mWeakEncrIterCount = P12_ENCR_ITER_COUNT; | |
76 | mStrongEncrIterCount = P12_ENCR_ITER_COUNT; | |
77 | mMacIterCount = P12_MAC_ITER_COUNT; | |
78 | mImportFlags = P12_KC_IMPORT_DEFAULT; | |
79 | mRawCspHand = 0; | |
80 | mClHand = 0; | |
81 | mAccess = NULL; | |
82 | mNoAcl = false; | |
83 | mKeyUsage = CSSM_KEYUSE_ANY; /* default */ | |
84 | /* default key attrs; we add CSSM_KEYATTR_PERMANENT if importing to | |
85 | * a keychain */ | |
86 | mKeyAttrs = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | | |
87 | CSSM_KEYATTR_SENSITIVE; | |
88 | } | |
89 | ||
90 | /* | |
91 | * FIXME - can't we get vector's destructor to do this? | |
92 | */ | |
93 | #define deleteVect(v) \ | |
94 | { \ | |
95 | while(v.size()) { \ | |
96 | delete v[0]; \ | |
97 | v.erase(v.begin()); \ | |
98 | } \ | |
99 | v.clear(); \ | |
100 | } | |
101 | ||
102 | P12Coder::~P12Coder() | |
103 | { | |
104 | if(mMacPassphrase) { | |
105 | CFRelease(mMacPassphrase); | |
106 | } | |
107 | if(mEncrPassPhrase) { | |
108 | CFRelease(mEncrPassPhrase); | |
109 | } | |
110 | if(mAccess) { | |
111 | CFRelease(mAccess); | |
112 | } | |
113 | deleteVect(mCerts); | |
114 | deleteVect(mCrls); | |
115 | deleteVect(mKeys); | |
116 | deleteVect(mOpaques); | |
117 | ||
118 | if(mKeychain) { | |
119 | CFRelease(mKeychain); | |
120 | } | |
121 | if(mRawCspHand) { | |
122 | cuCspDetachUnload(mRawCspHand, CSSM_TRUE); | |
123 | } | |
124 | if(mClHand) { | |
125 | cuClDetachUnload(mClHand); | |
126 | } | |
127 | } | |
128 | ||
129 | void P12Coder::setKeychain( | |
130 | SecKeychainRef keychain) | |
131 | { | |
132 | OSStatus ortn = SecKeychainGetCSPHandle(keychain, &mCspHand); | |
133 | if(ortn) { | |
134 | MacOSError::throwMe(ortn); | |
135 | } | |
136 | ortn = SecKeychainGetDLDBHandle(keychain, &mDlDbHand); | |
137 | if(ortn) { | |
138 | MacOSError::throwMe(ortn); | |
139 | } | |
140 | CFRetain(keychain); | |
141 | mKeychain = keychain; | |
142 | } | |
143 | ||
144 | void P12Coder::setAccess( | |
145 | SecAccessRef access) | |
146 | { | |
147 | if(mAccess) { | |
148 | CFRelease(mAccess); | |
149 | } | |
150 | mAccess = access; | |
151 | if(mAccess) { | |
152 | CFRetain(mAccess); | |
153 | } | |
154 | else { | |
155 | /* NULL ==> no ACL */ | |
156 | mNoAcl = true; | |
157 | } | |
158 | } | |
159 | ||
160 | #define SEC_KEYATTR_RETURN_MASK \ | |
161 | (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_NONE) | |
162 | ||
163 | void P12Coder::setKeyAttrs( | |
164 | CSSM_KEYATTR_FLAGS keyAttrs) | |
165 | { | |
166 | /* ensure we're generating a ref key no matter what caller asks for */ | |
167 | mKeyAttrs = keyAttrs; | |
168 | mKeyAttrs &= ~SEC_KEYATTR_RETURN_MASK; | |
169 | mKeyAttrs |= CSSM_KEYATTR_RETURN_REF; | |
170 | } | |
171 | ||
172 | /* | |
173 | * Private methods for obtaining passprases in CSSM_DATA form. | |
174 | */ | |
175 | const CSSM_DATA *P12Coder::getMacPassPhrase() | |
176 | { | |
177 | if(mMacPassData.Data != NULL) { | |
178 | return &mMacPassData; | |
179 | } | |
180 | else if (mMacPassphrase) { | |
181 | p12ImportPassPhrase(mMacPassphrase, mCoder, mMacPassData); | |
182 | return &mMacPassData; | |
183 | } | |
184 | else { | |
185 | return NULL; | |
186 | } | |
187 | } | |
188 | ||
189 | const CSSM_DATA *P12Coder::getEncrPassPhrase() | |
190 | { | |
191 | if(mEncrPassData.Data != NULL) { | |
192 | return &mEncrPassData; | |
193 | } | |
194 | else if (mEncrPassPhrase) { | |
195 | p12ImportPassPhrase(mEncrPassPhrase, mCoder, mEncrPassData); | |
196 | return &mEncrPassData; | |
197 | } | |
198 | /* no separate passphrase found, use MAC passphrase */ | |
199 | return getMacPassPhrase(); | |
200 | } | |
201 | ||
202 | /* | |
203 | * These return a CSSM_KEY_PTR is the app had specified | |
204 | * PassKeys, else they return NULL. | |
205 | */ | |
206 | const CSSM_KEY *P12Coder::getMacPassKey() | |
207 | { | |
208 | return mMacPassKey; | |
209 | } | |
210 | ||
211 | const CSSM_KEY *P12Coder::getEncrPassKey() | |
212 | { | |
213 | if(mEncrPassKey != NULL) { | |
214 | return mEncrPassKey; | |
215 | } | |
216 | else { | |
217 | return getMacPassKey(); | |
218 | } | |
219 | } | |
220 | ||
221 | /* | |
222 | * Lazy evaluation of module handles. | |
223 | */ | |
224 | CSSM_CSP_HANDLE P12Coder::rawCspHand() | |
225 | { | |
226 | if(mRawCspHand != 0) { | |
227 | return mRawCspHand; | |
228 | } | |
229 | mRawCspHand = cuCspStartup(CSSM_TRUE); | |
230 | if(mRawCspHand == 0) { | |
231 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
232 | } | |
233 | return mRawCspHand; | |
234 | } | |
235 | ||
236 | CSSM_CL_HANDLE P12Coder::clHand() | |
237 | { | |
238 | if(mClHand != 0) { | |
239 | return mClHand; | |
240 | } | |
241 | mClHand = cuClStartup(); | |
242 | if(mClHand == 0) { | |
243 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
244 | } | |
245 | return mClHand; | |
246 | } | |
247 | ||
248 | /* | |
249 | * These public functions more or less correspond to | |
250 | * the public functions in SecPkcs12.h. | |
251 | */ | |
252 | void P12Coder::setMacPassPhrase( | |
253 | CFStringRef passphrase) | |
254 | { | |
255 | CFRetain(passphrase); | |
256 | mMacPassphrase = passphrase; | |
257 | } | |
258 | ||
259 | void P12Coder::setEncrPassPhrase( | |
260 | CFStringRef passphrase) | |
261 | { | |
262 | CFRetain(passphrase); | |
263 | mEncrPassPhrase = passphrase; | |
264 | } | |
265 | ||
266 | void P12Coder::setMacPassKey( | |
267 | const CSSM_KEY *passKey) | |
268 | { | |
269 | mMacPassKey = passKey; | |
270 | } | |
271 | ||
272 | void P12Coder::setEncrPassKey( | |
273 | const CSSM_KEY *passKey) | |
274 | { | |
275 | mEncrPassKey = passKey; | |
276 | } | |
277 | ||
278 | /* getters */ | |
279 | unsigned P12Coder::numCerts() | |
280 | { | |
427c49bc | 281 | return (unsigned)mCerts.size(); |
b1ab9ed8 A |
282 | } |
283 | ||
284 | unsigned P12Coder::numCrls() | |
285 | { | |
427c49bc | 286 | return (unsigned)mCrls.size(); |
b1ab9ed8 A |
287 | } |
288 | ||
289 | unsigned P12Coder::numKeys() | |
290 | { | |
427c49bc | 291 | return (unsigned)mKeys.size(); |
b1ab9ed8 A |
292 | } |
293 | ||
294 | unsigned P12Coder::numOpaqueBlobs() | |
295 | { | |
427c49bc | 296 | return (unsigned)mOpaques.size(); |
b1ab9ed8 A |
297 | } |
298 | ||
299 | P12CertBag *P12Coder::getCert( | |
300 | unsigned dex) | |
301 | { | |
302 | if(mCerts.size() < (dex + 1)) { | |
427c49bc | 303 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
304 | } |
305 | return mCerts[dex]; | |
306 | } | |
307 | ||
308 | P12CrlBag *P12Coder::getCrl( | |
309 | unsigned dex) | |
310 | { | |
311 | if(mCrls.size() < (dex + 1)) { | |
427c49bc | 312 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
313 | } |
314 | return mCrls[dex]; | |
315 | } | |
316 | ||
317 | P12KeyBag *P12Coder::getKey( | |
318 | unsigned dex) | |
319 | { | |
320 | if(mKeys.size() < (dex + 1)) { | |
427c49bc | 321 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
322 | } |
323 | return mKeys[dex]; | |
324 | } | |
325 | ||
326 | P12OpaqueBag *P12Coder::getOpaque( | |
327 | unsigned dex) | |
328 | { | |
329 | if(mOpaques.size() < (dex + 1)) { | |
427c49bc | 330 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
331 | } |
332 | return mOpaques[dex]; | |
333 | } | |
334 | ||
335 | /* | |
336 | * These four "add" functions are invoked by the app prior to encoding | |
337 | * and by our decoder while decoding. | |
338 | */ | |
339 | void P12Coder::addCert( | |
340 | P12CertBag *cert) | |
341 | { | |
342 | mCerts.push_back(cert); | |
343 | } | |
344 | ||
345 | void P12Coder::addCrl( | |
346 | P12CrlBag *crl) | |
347 | { | |
348 | mCrls.push_back(crl); | |
349 | } | |
350 | ||
351 | void P12Coder::addKey( | |
352 | P12KeyBag *key) | |
353 | { | |
354 | mKeys.push_back(key); | |
355 | } | |
356 | ||
357 | void P12Coder::addOpaque( | |
358 | P12OpaqueBag *opaque) | |
359 | { | |
360 | mOpaques.push_back(opaque); | |
361 | } | |
362 | ||
363 | ||
364 | /* little known, but public, functions */ | |
365 | void P12Coder::integrityMode( | |
366 | SecPkcs12Mode mode) | |
367 | { | |
368 | if(mode != kSecPkcs12ModePassword) { | |
427c49bc | 369 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
370 | } |
371 | mIntegrityMode = mode; | |
372 | } | |
373 | ||
374 | void P12Coder::privacyMode( | |
375 | SecPkcs12Mode mode) | |
376 | { | |
377 | if(mode != kSecPkcs12ModePassword) { | |
427c49bc | 378 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
379 | } |
380 | mPrivacyMode = mode; | |
381 | } | |
382 | ||
383 | CFDataRef P12Coder::weakEncrAlg() | |
384 | { | |
385 | return p12CssmDataToCf(mWeakEncrAlg); | |
386 | } | |
387 | ||
388 | CFDataRef P12Coder::strongEncrAlg() | |
389 | { | |
390 | return p12CssmDataToCf(mStrongEncrAlg); | |
391 | } | |
392 | ||
393 | void P12Coder::weakEncrAlg( | |
394 | CFDataRef alg) | |
395 | { | |
396 | p12CfDataToCssm(alg, mWeakEncrAlg, mCoder); | |
397 | } | |
398 | ||
399 | void P12Coder::strongEncrAlg( | |
400 | CFDataRef alg) | |
401 | { | |
402 | p12CfDataToCssm(alg, mStrongEncrAlg, mCoder); | |
403 | } | |
404 | ||
405 | void P12Coder::limitPrivKeyImport( | |
406 | bool foundOneKey) | |
407 | { | |
408 | if(foundOneKey) { | |
409 | mPrivKeyImportState = PKIS_NoMore; | |
410 | } | |
411 | else { | |
412 | mPrivKeyImportState = PKIS_AllowOne; | |
413 | } | |
414 | } |