1/*
2 * Copyright (c) 2003-2004 Apple Computer, 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.h - main PKCS12 encode/decode engine. This class
26 *				   corresponds to a SecPkcs12CoderRef in the public API.
27 */
28
29#ifndef	_PKCS12_CODER_H_
30#define _PKCS12_CODER_H_
31
32#include <security_pkcs12/SecPkcs12.h>
33#include <security_pkcs12/pkcs12SafeBag.h>
34#include <vector>
35
36/*
37 * This class essentially consists of the following:
38 *
39 * -- bags of certs, CRLs, keys, and opaque blobs in the
40 *    form of P12SafeBag subclasses.
41 *
42 * -- getters and setters to let the app access those bags.
43 *
44 * -- a decode routine which takes an encoded PFX, rips it apart,
45 *    and drops what it finds into the bags of cert, CRLS, etc.
46 *
47 * -- an encode routine which takes the contents of the bag and
48 *    creates an encoded PFX.
49 *
50 * Everything else is ephemera supporting the above four things.
51 *
52 * Memory usage:
53 * -------------
54 *
55 * Memory allocation is done in three flavors:
56 *
57 * 1. Via CF objects, when exporting contents of bags to the app.
58 * 2. Via our own member variable SecNssCoder. This is used to allocate
59 *    the contents of the bags (certs, etc.) which persist across
60 *    API calls.
61 * 3. "Local" SecNssCoders for encode and decode. Allocated in the
62 *    stack for those two exported functions and used for all decoding
63 *    and encoding.
64 *
65 * The contents of the bags persist as long as an instance of
66 * P12Coder does.
67 *
68 * CF objects the app gives us (e..g, passphrases)
69 * are retained when get them and released in our destructor.
70 *
71 * CF objects we give the app are, of course, the app's responsibility.
72 *
73 * Everything else is allocd locally via the SecNssCoders in encode()
74 * and decode() and has a scope not exceeding those functions.
75 */
76
77class P12Coder {
78public:
79	/* only constructor */
80	P12Coder();
81	~P12Coder();
82
83	/*
84	 * These public functions more or less correspond to
85	 * the public functions in SecPkcs12.h.
86	 */
87	void setMacPassPhrase(
88		CFStringRef				passphrase);
89	void setEncrPassPhrase(
90		CFStringRef				passphrase);
91	void setMacPassKey(
92		const CSSM_KEY			*passKey);
93	void setEncrPassKey(
94		const CSSM_KEY			*passKey);
95
96	/* main decode function */
97	void decode(
98		CFDataRef				pfx);
99
100	/*
101	 * CSP and DLDB associated with keys.
102	 * CSP handle is required, DLDB optional.
103	*/
104	void setKeychain(
105		SecKeychainRef			keychain);
106	void setCsp(
107		CSSM_CSP_HANDLE			cspHand)	{ mCspHand = cspHand; }
108	void setDlDb(
109		CSSM_DL_DB_HANDLE		dlDbHand)	{ mDlDbHand = dlDbHand; }
110
111	CSSM_CSP_HANDLE	cspHand()				{ return mCspHand; }
112
113	/* private key import attributes */
114	void setAccess(
115		SecAccessRef			access);
116	void setKeyUsage(
117		CSSM_KEYUSE				keyUsage)	{ mKeyUsage = keyUsage; }
118	void setKeyAttrs(
119		CSSM_KEYATTR_FLAGS		keyAttrs);
120
121	/* High-level import/export */
122	void importFlags(
123		SecPkcs12ImportFlags flags)			{ mImportFlags = flags; }
124	SecPkcs12ImportFlags importFlags()
125											{ return mImportFlags; }
126
127	void exportKeychainItems(
128		CFArrayRef				items);
129
130	/* getters */
131	unsigned numCerts();
132	unsigned numCrls();
133	unsigned numKeys();
134	unsigned numOpaqueBlobs();
135
136	P12CertBag *getCert(
137		unsigned				dex);
138	P12CrlBag *getCrl(
139		unsigned				dex);
140	P12KeyBag *getKey(
141		unsigned				dex);
142	P12OpaqueBag *getOpaque(
143		unsigned				dex);
144
145	/* encoding */
146	void encode(
147		CFDataRef				*pfx);		// RETURNED
148
149	void addCert(
150		P12CertBag				*cert);
151	void addCrl(
152		P12CrlBag				*crl);
153	void addKey(
154		P12KeyBag				*key);
155	void addOpaque(
156		P12OpaqueBag			*opaque);
157
158	/* little known, but public,  functions */
159	SecPkcs12Mode integrityMode()		{ return mIntegrityMode; }
160	SecPkcs12Mode privacyMode()			{ return mPrivacyMode; }
161	void integrityMode(
162		SecPkcs12Mode			mode);
163	void privacyMode(
164		SecPkcs12Mode			mode);
165
166	/*
167	 * Public API calls use our coder to create P12SafeBags
168	 */
169	SecNssCoder	&coder()			{ return mCoder; }
170
171	/* encryption parameter getters/setters */
172	unsigned weakEncrIterCount()	{ return mWeakEncrIterCount; }
173	unsigned strongEncrIterCount()	{ return mStrongEncrIterCount; }
174	unsigned macEncrIterCount()		{ return mMacIterCount; }
175
176	void weakEncrIterCount(
177		unsigned ic)				{ mWeakEncrIterCount = ic; }
178	void strongEncrIterCount(
179		unsigned ic)				{ mStrongEncrIterCount = ic; }
180	void macEncrIterCount(
181		unsigned ic)				{ mMacIterCount = ic; }
182
183	CFDataRef weakEncrAlg();
184	CFDataRef strongEncrAlg();
185
186	void weakEncrAlg(
187		CFDataRef				alg);
188	void strongEncrAlg(
189		CFDataRef				alg);
190
191	/* panic button, delete anything stored in a DB during decode */
192	void deleteDecodedItems();
193
194	void limitPrivKeyImport(
195		bool foundOneKey);
196
197private:
198	void init();					// one-time init from all constructors
199
200	/*
201	 * Passphrase handling.
202	 *
203	 * These two convert the app-supplied CFStringRefs into
204	 * CSSM_DATAs; if PassKeys are used, these just NULL out
205	 * the returned data.
206	 */
207	const CSSM_DATA *getMacPassPhrase();
208	const CSSM_DATA *getEncrPassPhrase();
209
210	/*
211	 * These return a CSSM_KEY_PTR is the app had specified
212	 * PassKeys, else they return NULL.
213	 */
214	const CSSM_KEY *getMacPassKey();
215	const CSSM_KEY *getEncrPassKey();
216
217	/* in pkcs12Keychain.cpp */
218	void storeDecodeResults();
219	void setPrivateKeyHashes();
220	void notifyKeyImport();
221	P12CertBag *findCertForKey(
222		P12KeyBag 				*keyBag);
223
224	void addSecKey(
225		SecKeyRef				keyRef);
226	void addSecCert(
227		SecCertificateRef		certRef);
228
229	/* Lazy evaluation of module handles. */
230	CSSM_CSP_HANDLE rawCspHand();
231	CSSM_CL_HANDLE 	clHand();
232
233	/*
234	 * A bunch of private encode/decode methods. This makes me
235	 * long for ObjC-style categories so these would not
236	 * have to appear in this file.
237	 *
238	 * See implementation for comments and descriptions.
239	 */
240	void encryptedDataDecrypt(
241		const NSS_P7_EncryptedData 	&edata,
242		SecNssCoder 				&localCdr,
243		NSS_P12_PBE_Params 			*pbep,
244		CSSM_DATA 					&ptext);
245
246	void algIdParse(
247		const CSSM_X509_ALGORITHM_IDENTIFIER &algId,
248		NSS_P12_PBE_Params 			*pbeParams,
249		SecNssCoder 				&localCdr);
250
251	void encryptedDataParse(
252		const NSS_P7_EncryptedData 	&edata,
253		SecNssCoder 				&localCdr,
254		NSS_P12_PBE_Params 			*pbep);
255
256	void shroudedKeyBagParse(
257		const NSS_P12_SafeBag 		&safeBag,
258		SecNssCoder 				&localCdr);
259
260	void keyBagParse(
261		const NSS_P12_SafeBag 		&safeBag,
262		SecNssCoder 				&localCdr);
263
264	void certBagParse(
265		const NSS_P12_SafeBag 		&safeBag,
266		SecNssCoder 				&localCdr);
267
268	void crlBagParse(
269		const NSS_P12_SafeBag 		&safeBag,
270		SecNssCoder 				&localCdr);
271
272	void secretBagParse(
273		const NSS_P12_SafeBag 		&safeBag,
274		SecNssCoder 				&localCdr);
275
276	void safeContentsBagParse(
277		const NSS_P12_SafeBag 		&safeBag,
278		SecNssCoder 				&localCdr);
279
280	void safeContentsParse(
281		const CSSM_DATA 			&contentsBlob,
282		SecNssCoder 				&localCdr);
283
284	void authSafeElementParse(
285		const NSS_P7_DecodedContentInfo *info,
286		SecNssCoder 				&localCdr);
287
288	void macParse(
289		const NSS_P12_MacData 		&macData,
290		SecNssCoder					&localCdr);
291
292	void authSafeParse(
293		const CSSM_DATA 			&authSafeBlob,
294		SecNssCoder 				&localCdr);
295
296	/* private encoding routines */
297	NSS_P7_DecodedContentInfo *safeContentsBuild(
298		NSS_P12_SafeBag				**bags,
299		NSS_P7_CI_Type 				type,		// CT_Data, CT_EncryptedData
300		CSSM_OID 					*encrOid,	// only for CT_EncryptedData
301		unsigned 					iterCount,	// ditto
302		SecNssCoder					&localCdr);
303
304	void authSafeBuild(
305		NSS_P7_DecodedContentInfo 	&authSafe,
306		SecNssCoder 				&localCdr);
307
308	void encryptData(
309		const CSSM_DATA				&ptext,
310		CSSM_OID 					&encrOid,
311		unsigned 					iterCount,
312		NSS_P7_EncryptedData		&ed,
313		SecNssCoder					&localCdr);
314
315	void algIdBuild(
316		CSSM_X509_ALGORITHM_IDENTIFIER	&algId,
317		const CSSM_OID 				&algOid,
318		const CSSM_DATA 			&salt,
319		unsigned 					iterCount,
320		SecNssCoder 				&localCdr);
321
322	void macSignPfx(
323		NSS_P12_DecodedPFX 			&pfx,
324		SecNssCoder 				&localCdr);
325
326	NSS_P12_SafeBag *certBagBuild(
327		P12CertBag 					*cert,
328		SecNssCoder 				&localCdr);
329
330	NSS_P12_SafeBag *crlBagBuild(
331		P12CrlBag 					*crl,
332		SecNssCoder 				&localCdr);
333
334	NSS_P12_SafeBag *keyBagBuild(
335		P12KeyBag 					*key,
336		SecNssCoder 				&localCdr);
337
338	NSS_P12_SafeBag *opaqueBagBuild(
339		P12OpaqueBag				*op,
340		SecNssCoder 				&localCdr);
341
342	/* member variables */
343	SecPkcs12Mode				mPrivacyMode;
344	SecPkcs12Mode				mIntegrityMode;
345
346	/* passwords - as app gave us, and translated into ready-to-use
347	 * unicode strings */
348	CFStringRef					mMacPassphrase;
349	CFStringRef					mEncrPassPhrase;
350	CSSM_DATA					mMacPassData;
351	CSSM_DATA					mEncrPassData;
352
353	/* passphrases in key form */
354	const CSSM_KEY				*mMacPassKey;
355	const CSSM_KEY				*mEncrPassKey;
356
357	/*
358	 * App has to either set mKeychain or mCspHand. In the former
359	 * case we infer both mCspHand and mDlDbHand from the keychainRef.
360	 */
361	SecKeychainRef				mKeychain;
362	CSSM_CSP_HANDLE				mCspHand;
363	CSSM_DL_DB_HANDLE			mDlDbHand;
364
365	/*
366	 * LimitPrivateKeyImport mechanism
367	 */
368	typedef enum {
369		PKIS_NoLimit,			// no limit
370		PKIS_AllowOne,			// allow import of at most one
371		PKIS_NoMore				// found one, no more allowed
372	} p12PrivKeyImportState;
373
374	p12PrivKeyImportState		mPrivKeyImportState;
375
376	/*
377	 * Encryption/MAC parameters
378	 */
379	CSSM_OID					mWeakEncrAlg;		// for certs and CRLs
380	CSSM_OID					mStrongEncrAlg;
381	unsigned					mWeakEncrIterCount;
382	unsigned					mStrongEncrIterCount;
383	unsigned					mMacIterCount;
384
385	/*
386	 * Import flags
387	 */
388	SecPkcs12ImportFlags		mImportFlags;
389
390	/*
391	 * Four individual piles of safe bags
392	 */
393	vector<P12CertBag *>		mCerts;
394	vector<P12CrlBag *>			mCrls;
395	vector<P12KeyBag *>			mKeys;
396	vector<P12OpaqueBag *>		mOpaques;
397
398	/*
399	 * Internal CSSM module handles, lazily evaluated.
400	 */
401	CSSM_CSP_HANDLE				mRawCspHand;
402	CSSM_CL_HANDLE				mClHand;
403
404	/*
405	 * Imported private key attributes
406	 */
407	SecAccessRef				mAccess;
408	bool						mNoAcl;		/* true when NULL passed to setAccess() */
409	CSSM_KEYUSE					mKeyUsage;
410	CSSM_KEYATTR_FLAGS			mKeyAttrs;
411
412	/*
413	 * The source of most (all?) of our privately allocated data
414	 */
415	SecNssCoder					mCoder;
416};
417
418#endif	/* _PKCS12_CODER_H_ */
419
420