1/*
2 * Copyright (c) 2003-2004,2011-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 * 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>
33#include <Security/oidsalg.h>
34#include <Security/SecBase.h>
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
50P12Coder::P12Coder()
51{
52	init();
53}
54
55/* one-time init from all constructors */
56void 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
102P12Coder::~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
129void 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
144void 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
163void 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 */
175const 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
189const 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 */
206const CSSM_KEY *P12Coder::getMacPassKey()
207{
208	return mMacPassKey;
209}
210
211const 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 */
224CSSM_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
236CSSM_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 */
252void P12Coder::setMacPassPhrase(
253	CFStringRef				passphrase)
254{
255	CFRetain(passphrase);
256	mMacPassphrase = passphrase;
257}
258
259void P12Coder::setEncrPassPhrase(
260	CFStringRef				passphrase)
261{
262	CFRetain(passphrase);
263	mEncrPassPhrase = passphrase;
264}
265
266void P12Coder::setMacPassKey(
267	const CSSM_KEY  *passKey)
268{
269	mMacPassKey = passKey;
270}
271
272void P12Coder::setEncrPassKey(
273	const CSSM_KEY  *passKey)
274{
275	mEncrPassKey = passKey;
276}
277
278/* getters */
279unsigned P12Coder::numCerts()
280{
281	return (unsigned)mCerts.size();
282}
283
284unsigned P12Coder::numCrls()
285{
286	return (unsigned)mCrls.size();
287}
288
289unsigned P12Coder::numKeys()
290{
291	return (unsigned)mKeys.size();
292}
293
294unsigned P12Coder::numOpaqueBlobs()
295{
296	return (unsigned)mOpaques.size();
297}
298
299P12CertBag *P12Coder::getCert(
300	unsigned				dex)
301{
302	if(mCerts.size() < (dex + 1)) {
303		MacOSError::throwMe(errSecParam);
304	}
305	return mCerts[dex];
306}
307
308P12CrlBag *P12Coder::getCrl(
309	unsigned				dex)
310{
311	if(mCrls.size() < (dex + 1)) {
312		MacOSError::throwMe(errSecParam);
313	}
314	return mCrls[dex];
315}
316
317P12KeyBag *P12Coder::getKey(
318	unsigned				dex)
319{
320	if(mKeys.size() < (dex + 1)) {
321		MacOSError::throwMe(errSecParam);
322	}
323	return mKeys[dex];
324}
325
326P12OpaqueBag *P12Coder::getOpaque(
327	unsigned				dex)
328{
329	if(mOpaques.size() < (dex + 1)) {
330		MacOSError::throwMe(errSecParam);
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 */
339void P12Coder::addCert(
340	P12CertBag				*cert)
341{
342	mCerts.push_back(cert);
343}
344
345void P12Coder::addCrl(
346	P12CrlBag				*crl)
347{
348	mCrls.push_back(crl);
349}
350
351void P12Coder::addKey(
352	P12KeyBag				*key)
353{
354	mKeys.push_back(key);
355}
356
357void P12Coder::addOpaque(
358	P12OpaqueBag			*opaque)
359{
360	mOpaques.push_back(opaque);
361}
362
363
364/* little known, but public,  functions */
365void P12Coder::integrityMode(
366	SecPkcs12Mode			mode)
367{
368	if(mode != kSecPkcs12ModePassword) {
369		MacOSError::throwMe(errSecParam);
370	}
371	mIntegrityMode = mode;
372}
373
374void P12Coder::privacyMode(
375	SecPkcs12Mode			mode)
376{
377	if(mode != kSecPkcs12ModePassword) {
378		MacOSError::throwMe(errSecParam);
379	}
380	mPrivacyMode = mode;
381}
382
383CFDataRef P12Coder::weakEncrAlg()
384{
385	return p12CssmDataToCf(mWeakEncrAlg);
386}
387
388CFDataRef P12Coder::strongEncrAlg()
389{
390	return p12CssmDataToCf(mStrongEncrAlg);
391}
392
393void P12Coder::weakEncrAlg(
394	CFDataRef				alg)
395{
396	p12CfDataToCssm(alg, mWeakEncrAlg, mCoder);
397}
398
399void P12Coder::strongEncrAlg(
400	CFDataRef				alg)
401{
402	p12CfDataToCssm(alg, mStrongEncrAlg, mCoder);
403}
404
405void P12Coder::limitPrivKeyImport(
406	bool foundOneKey)
407{
408	if(foundOneKey) {
409		mPrivKeyImportState = PKIS_NoMore;
410	}
411	else {
412		mPrivKeyImportState = PKIS_AllowOne;
413	}
414}
415