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 * SecPkcs12.cpp
25 */
26
27#include "SecPkcs12.h"
28#include "pkcs12Coder.h"
29#include "pkcs12BagAttrs.h"
30#include "pkcs12SafeBag.h"
31#include "pkcs12Utils.h"
32#include <security_cdsa_utilities/cssmerrors.h>
33#include <Security/SecBasePriv.h>
34
35/*
36 * API function call wrappers, impermeable to C++ exceptions
37 */
38#define BEGIN_P12API \
39	try {
40
41#define END_P12API \
42	} \
43	catch (const MacOSError &err) { return err.osStatus(); } \
44	catch (const CommonError &err) { return SecKeychainErrFromOSStatus(err.osStatus()); } \
45	catch (const std::bad_alloc &) { return errSecAllocate; } \
46	catch (...) { return errSecInternalComponent; } \
47    return errSecSuccess;
48
49/* catch incoming NULL parameters */
50static inline void required(
51	const void *param)
52{
53	if(param == NULL) {
54		MacOSError::throwMe(errSecParam);
55	}
56}
57
58/*
59 * Standard means of casting a SecPkcs12CoderRef to a P12Coder *
60 */
61static inline P12Coder *P12CoderCast(
62	SecPkcs12CoderRef coder)
63{
64	required(coder);
65	return reinterpret_cast<P12Coder *>(coder);
66}
67
68/*
69 * Standard means of casting a SecPkcs12AttrsRef to a P12BagAttrs *
70 * This one uses the P12BagAttrsStandAlone version, not tied to
71 * a specific P12Coder (actually, to a P12Coder's SecNssCoder).
72 */
73static inline P12BagAttrsStandAlone *P12AttrsCast(
74	SecPkcs12AttrsRef attrs)
75{
76	if(attrs == NULL) {
77		MacOSError::throwMe(errSecParam);
78	}
79	return reinterpret_cast<P12BagAttrsStandAlone *>(attrs);
80}
81
82/* optional flavor used in SecPkcs12Add*() */
83static inline P12BagAttrs *P12AttrsCastOpt(
84	SecPkcs12AttrsRef attrs)
85{
86	return reinterpret_cast<P12BagAttrs *>(attrs);
87}
88
89#pragma mark --- SecPkcs12CoderRef create/destroy ---
90
91/*
92 * Basic SecPkcs12CoderRef create/destroy.
93 */
94OSStatus SecPkcs12CoderCreate(
95	SecPkcs12CoderRef	*coder)		// RETURNED
96{
97	BEGIN_P12API
98
99	required(coder);
100	P12Coder *p12coder = new P12Coder;
101	*coder = p12coder;
102
103	END_P12API
104}
105
106/*
107 * Destroy object created in SecPkcs12CoderCreate.
108 * This will go away if we make this object a CoreFoundation type.
109 */
110OSStatus SecPkcs12CoderRelease(
111	SecPkcs12CoderRef	coder)
112{
113	BEGIN_P12API
114
115	P12Coder *p12coder = P12CoderCast(coder);
116	delete p12coder;
117
118	END_P12API
119}
120
121OSStatus SecPkcs12SetMACPassphrase(
122	SecPkcs12CoderRef	coder,
123	CFStringRef			passphrase)
124{
125	BEGIN_P12API
126
127	P12Coder *p12coder = P12CoderCast(coder);
128	required(passphrase);
129	p12coder->setMacPassPhrase(passphrase);
130
131	END_P12API
132}
133
134OSStatus SecPkcs12SetMACPassKey(
135	SecPkcs12CoderRef	coder,
136	const CSSM_KEY		*passKey)
137{
138	BEGIN_P12API
139
140	P12Coder *p12coder = P12CoderCast(coder);
141	required(passKey);
142	p12coder->setMacPassKey(passKey);
143
144	END_P12API
145}
146
147/*
148 * Specify separate passphrase for encrypt/decrypt.
149 */
150OSStatus SecPkcs12SetCryptPassphrase(
151	SecPkcs12CoderRef	coder,
152	CFStringRef			passphrase)
153{
154	BEGIN_P12API
155
156	P12Coder *p12coder = P12CoderCast(coder);
157	required(passphrase);
158	p12coder->setEncrPassPhrase(passphrase);
159
160	END_P12API
161}
162
163OSStatus SecPkcs12SetCryptPassKey(
164	SecPkcs12CoderRef	coder,
165	const CSSM_KEY		*passKey)
166{
167	BEGIN_P12API
168
169	P12Coder *p12coder = P12CoderCast(coder);
170	required(passKey);
171	p12coder->setEncrPassKey(passKey);
172
173	END_P12API
174}
175
176
177/*
178 * Target location of decoded keys and certs.
179 */
180OSStatus SecPkcs12SetKeychain(
181	SecPkcs12CoderRef		coder,
182	SecKeychainRef			keychain)
183{
184	BEGIN_P12API
185
186	P12Coder *p12coder = P12CoderCast(coder);
187	required(keychain);
188	p12coder->setKeychain(keychain);
189
190	END_P12API
191}
192
193/*
194 * Required iff SecPkcs12SetKeychain() not called.
195 */
196OSStatus SecPkcs12SetCspHandle(
197	SecPkcs12CoderRef		coder,
198	CSSM_CSP_HANDLE			cspHandle)
199{
200	BEGIN_P12API
201
202	P12Coder *p12coder = P12CoderCast(coder);
203	p12coder->setCsp(cspHandle);
204
205	END_P12API
206}
207
208OSStatus SecPkcs12SetImportToKeychain(
209	SecPkcs12CoderRef		coder,
210	SecPkcs12ImportFlags	flags)
211{
212	BEGIN_P12API
213
214	P12Coder *p12coder = P12CoderCast(coder);
215	p12coder->importFlags(flags);
216
217	END_P12API
218}
219
220OSStatus SecPkcs12GetImportToKeychain(
221	SecPkcs12CoderRef		coder,
222	SecPkcs12ImportFlags	*flags)		// RETURNED
223{
224	BEGIN_P12API
225
226	P12Coder *p12coder = P12CoderCast(coder);
227	required(flags);
228	*flags = p12coder->importFlags();
229
230	END_P12API
231}
232
233OSStatus SecPkcs12ExportKeychainItems(
234	SecPkcs12CoderRef			coder,
235	CFArrayRef					items)
236{
237	BEGIN_P12API
238
239	P12Coder *p12coder = P12CoderCast(coder);
240	required(items);
241	p12coder->exportKeychainItems(items);
242
243	END_P12API
244}
245
246OSStatus SecPkcs12SetAccess(
247	SecPkcs12CoderRef		coder,
248	SecAccessRef			access)
249{
250	BEGIN_P12API
251
252	P12Coder *p12coder = P12CoderCast(coder);
253	p12coder->setAccess(access);
254
255	END_P12API
256}
257
258OSStatus SecPkcs12SetKeyUsage(
259	SecPkcs12CoderRef		coder,
260	CSSM_KEYUSE				keyUsage)
261{
262	BEGIN_P12API
263
264	P12Coder *p12coder = P12CoderCast(coder);
265	p12coder->setKeyUsage(keyUsage);
266
267	END_P12API
268}
269
270OSStatus SecPkcs12SetKeyAttrs(
271	SecPkcs12CoderRef		coder,
272	CSSM_KEYATTR_FLAGS		keyAttrs)
273{
274	BEGIN_P12API
275
276	P12Coder *p12coder = P12CoderCast(coder);
277	p12coder->setKeyAttrs(keyAttrs);
278
279	END_P12API
280}
281
282#pragma mark --- Decoder Functions ---
283
284/*
285 * Parse and decode.
286 */
287OSStatus SecPkcs12Decode(
288	SecPkcs12CoderRef		coder,
289	CFDataRef				pfx)
290{
291	BEGIN_P12API
292
293	P12Coder *p12coder = P12CoderCast(coder);
294	required(pfx);
295	try {
296		p12coder->decode(pfx);
297	}
298	catch(...) {
299		/* abort - clean up - delete stored keys */
300		p12coder->deleteDecodedItems();
301		throw;
302	}
303	END_P12API
304}
305
306/*
307 * Subsequent to decoding, obtain the components.
308 * These functions can also be used as "getter" functions while encoding.
309 *
310 * Certificates:
311 */
312OSStatus SecPkcs12CertificateCount(
313	SecPkcs12CoderRef		coder,
314	CFIndex					*numCerts)		// RETURNED
315{
316	BEGIN_P12API
317
318	P12Coder *p12coder = P12CoderCast(coder);
319	required(numCerts);
320	*numCerts = p12coder->numCerts();
321
322	END_P12API
323}
324
325OSStatus SecPkcs12CopyCertificate(
326	SecPkcs12CoderRef		coder,
327	CFIndex					certNum,
328	SecCertificateRef		*secCert,		// RETURNED
329	CFStringRef				*friendlyName,	// RETURNED
330	CFDataRef				*localKeyId,	// RETURNED
331	SecPkcs12AttrsRef		*attrs)			// RETURNED
332{
333	BEGIN_P12API
334
335	P12Coder *p12coder = P12CoderCast(coder);
336	required(secCert);
337	/* others are optional - if NULL, we don't return that param */
338	P12CertBag *bag = p12coder->getCert((unsigned)certNum);
339	*secCert = bag->getSecCert();
340
341	/* now the optional attrs */
342	P12BagAttrs *p12Attrs = NULL;
343	bag->copyAllAttrs(friendlyName, localKeyId,
344		attrs ? &p12Attrs : NULL);
345	if(p12Attrs) {
346		*attrs = p12Attrs;
347	}
348	END_P12API
349}
350
351/*
352 * CRLs. The might change if a SecCrl type is defined elsewhere.
353 * We'll typedef it here to preserve the semantics of this function.
354 */
355OSStatus SecPkcs12CrlCount(
356	SecPkcs12CoderRef		coder,
357	CFIndex					*numCrls)		// RETURNED
358{
359	BEGIN_P12API
360
361	P12Coder *p12coder = P12CoderCast(coder);
362	required(numCrls);
363	*numCrls = p12coder->numCrls();
364
365	END_P12API
366}
367
368OSStatus SecPkcs12CopyCrl(
369	SecPkcs12CoderRef		coder,
370	CFIndex					crlNum,
371	SecCrlRef				*crl,			// RETURNED
372	CFStringRef				*friendlyName,	// RETURNED
373	CFDataRef				*localKeyId,	// RETURNED
374	SecPkcs12AttrsRef		*attrs)			// RETURNED
375{
376	BEGIN_P12API
377
378	P12Coder *p12coder = P12CoderCast(coder);
379	required(crl);
380	/* others are optional - if NULL, we don't return that param */
381	P12CrlBag *bag = p12coder->getCrl((unsigned)crlNum);
382	*crl = p12CssmDataToCf(bag->crlData());
383
384	/* now the optional attrs */
385	P12BagAttrs *p12Attrs = NULL;
386	bag->copyAllAttrs(friendlyName, localKeyId,
387		attrs ? &p12Attrs : NULL);
388	if(p12Attrs) {
389		*attrs = p12Attrs;
390	}
391
392	END_P12API
393}
394
395/*
396 * Private keys.
397 */
398OSStatus SecPkcs12PrivateKeyCount(
399	SecPkcs12CoderRef		coder,
400	CFIndex					*numKeys)		// RETURNED
401{
402	BEGIN_P12API
403
404	P12Coder *p12coder = P12CoderCast(coder);
405	required(numKeys);
406	*numKeys = p12coder->numKeys();
407
408	END_P12API
409}
410
411OSStatus SecPkcs12CopyPrivateKey(
412	SecPkcs12CoderRef		coder,
413	CFIndex					keyNum,
414	SecKeyRef				*privateKey,	// RETURNED
415	CFStringRef				*friendlyName,	// RETURNED
416	CFDataRef				*localKeyId,	// RETURNED
417	SecPkcs12AttrsRef		*attrs)			// RETURNED
418{
419	BEGIN_P12API
420	/*P12Coder *p12coder = P12CoderCast(coder); */
421	return errSecUnimplemented;
422	END_P12API
423}
424
425OSStatus SecPkcs12GetCssmPrivateKey(
426	SecPkcs12CoderRef		coder,
427	CFIndex					keyNum,
428	CSSM_KEY_PTR			*privateKey,	// RETURNED
429	CFStringRef				*friendlyName,	// RETURNED
430	CFDataRef				*localKeyId,	// RETURNED
431	SecPkcs12AttrsRef		*attrs)			// RETURNED
432{
433	BEGIN_P12API
434	P12Coder *p12coder = P12CoderCast(coder);
435	required(privateKey);
436	/* others are optional - if NULL, we don't return that param */
437	P12KeyBag *bag = p12coder->getKey((unsigned)keyNum);
438	*privateKey = bag->key();
439
440	/* now the optional attrs */
441	P12BagAttrs *p12Attrs = NULL;
442	bag->copyAllAttrs(friendlyName, localKeyId,
443		attrs ? &p12Attrs : NULL);
444	if(p12Attrs) {
445		*attrs = p12Attrs;
446	}
447
448	END_P12API
449}
450
451/*
452 * Catch-all for other components not currently understood
453 * or supported by this library. An "opaque blob" component
454 * is identified by an OID and is obtained as an opaque data
455 * blob.
456 */
457OSStatus SecPkcs12OpaqueBlobCount(
458	SecPkcs12CoderRef		coder,
459	CFIndex					*numBlobs)		// RETURNED
460{
461	BEGIN_P12API
462
463	P12Coder *p12coder = P12CoderCast(coder);
464	required(numBlobs);
465	*numBlobs = p12coder->numOpaqueBlobs();
466
467	END_P12API
468}
469
470OSStatus SecPkcs12CopyOpaqueBlob(
471	SecPkcs12CoderRef		coder,
472	CFIndex					blobNum,
473	CFDataRef				*blobOid,		// RETURNED
474	CFDataRef				*opaqueBlob,	// RETURNED
475	CFStringRef				*friendlyName,	// RETURNED
476	CFDataRef				*localKeyId,	// RETURNED
477	SecPkcs12AttrsRef		*attrs)			// RETURNED
478{
479	BEGIN_P12API
480
481	P12Coder *p12coder = P12CoderCast(coder);
482	required(blobOid);
483	required(opaqueBlob);
484
485	/* others are optional - if NULL, we don't return that param */
486	P12OpaqueBag *bag = p12coder->getOpaque((unsigned)blobNum);
487	*opaqueBlob = p12CssmDataToCf(bag->blob());
488	*blobOid    = p12CssmDataToCf(bag->oid());
489
490	/* now the optional attrs */
491	P12BagAttrs *p12Attrs = NULL;
492	bag->copyAllAttrs(friendlyName, localKeyId,
493		attrs ? &p12Attrs : NULL);
494	if(p12Attrs) {
495		*attrs = p12Attrs;
496	}
497
498	END_P12API
499}
500
501#pragma mark --- Encoder Functions ---
502
503/*
504 * This the final step to create an encoded PKCS12 PFX blob,
505 * after calling some number of SecPkcs12Set* functions below.
506 * The result is a DER_encoded PFX in PKCS12 lingo.
507 */
508OSStatus SecPkcs12Encode(
509	SecPkcs12CoderRef		coder,
510	CFDataRef				*pfx)			// RETURNED
511{
512	BEGIN_P12API
513	P12Coder *p12coder = P12CoderCast(coder);
514	required(pfx);
515	p12coder->encode(pfx);
516	END_P12API
517}
518
519/*
520 * Add individual components. "Getter" functions are available
521 * as described above (under "Functions used for decoding").
522 */
523OSStatus SecPkcs12AddCertificate(
524	SecPkcs12CoderRef		coder,
525	SecCertificateRef		cert,
526	CFStringRef				friendlyName,	// optional
527	CFDataRef				localKeyId,		// optional
528	SecPkcs12AttrsRef		attrs)			// optional
529{
530	BEGIN_P12API
531	P12Coder *p12coder = P12CoderCast(coder);
532	required(cert);
533	CSSM_DATA certData;
534	OSStatus ortn = SecCertificateGetData(cert, &certData);
535	if(ortn) {
536		return ortn;
537	}
538	CSSM_CERT_TYPE certType;
539	ortn = SecCertificateGetType(cert, &certType);
540	if(ortn) {
541		return ortn;
542	}
543	NSS_P12_CertBagType type;
544	switch(certType) {
545		case CSSM_CERT_X_509v1:
546		case CSSM_CERT_X_509v2:
547		case CSSM_CERT_X_509v3:
548			type = CT_X509;
549			break;
550		case CSSM_CERT_SDSIv1:
551			type = CT_SDSI;
552			break;
553		default:
554			type = CT_Unknown;
555			break;
556	}
557	P12CertBag *bag = new P12CertBag(type, certData, friendlyName,
558		localKeyId, P12AttrsCastOpt(attrs), p12coder->coder());
559	p12coder->addCert(bag);
560	END_P12API
561}
562
563OSStatus SecPkcs12AddCrl(
564	SecPkcs12CoderRef		coder,
565	SecCrlRef				crl,
566	CFStringRef				friendlyName,	// optional
567	CFDataRef				localKeyId,		// optional
568	SecPkcs12AttrsRef		attrs)			// optional
569{
570	BEGIN_P12API
571	P12Coder *p12coder = P12CoderCast(coder);
572	required(crl);
573	P12CrlBag *bag = new P12CrlBag(CRT_X509, crl, friendlyName,
574		localKeyId, P12AttrsCastOpt(attrs), p12coder->coder());
575	p12coder->addCrl(bag);
576	END_P12API
577}
578
579OSStatus SecPkcs12AddPrivateKey(
580	SecPkcs12CoderRef		coder,
581	SecKeyRef				privateKey,
582	CFStringRef				friendlyName,	// optional
583	CFDataRef				localKeyId,		// optional
584	SecPkcs12AttrsRef		attrs)			// optional
585{
586	BEGIN_P12API
587
588	P12Coder *p12coder = P12CoderCast(coder);
589	required(privateKey);
590	const CSSM_KEY *cssmKey;
591	OSStatus ortn = SecKeyGetCSSMKey(privateKey, &cssmKey);
592	if(ortn) {
593		return ortn;
594	}
595	P12KeyBag *bag = new P12KeyBag(cssmKey, p12coder->cspHand(),
596		friendlyName, localKeyId, P12AttrsCastOpt(attrs), p12coder->coder());
597	p12coder->addKey(bag);
598
599	END_P12API
600}
601
602#if 0 /* Unused */
603OSStatus SecPkcs12AddCssmPrivateKey(
604	SecPkcs12CoderRef		coder,
605	CSSM_KEY_PTR			cssmKey,
606	CFStringRef				friendlyName,	// optional
607	CFDataRef				localKeyId,		// optional
608	SecPkcs12AttrsRef		attrs)			// optional
609{
610	BEGIN_P12API
611
612	P12Coder *p12coder = P12CoderCast(coder);
613	required(cssmKey);
614	P12KeyBag *bag = new P12KeyBag(cssmKey, p12coder->cspHand(),
615		friendlyName, localKeyId, P12AttrsCastOpt(attrs), p12coder->coder());
616	p12coder->addKey(bag);
617
618	END_P12API
619}
620#endif
621
622OSStatus SecPkcs12AddOpaqueBlob(
623	SecPkcs12CoderRef		coder,
624	CFDataRef				blobOid,
625	CFDataRef				opaqueBlob,
626	CFStringRef				friendlyName,	// optional
627	CFDataRef				localKeyId,		// optional
628	SecPkcs12AttrsRef		attrs)			// optional
629{
630	BEGIN_P12API
631
632	P12Coder *p12coder = P12CoderCast(coder);
633	required(blobOid);
634	required(opaqueBlob);
635	P12OpaqueBag *bag = new P12OpaqueBag(blobOid, opaqueBlob, friendlyName,
636		localKeyId, P12AttrsCastOpt(attrs), p12coder->coder());
637	p12coder->addOpaque(bag);
638
639	END_P12API
640}
641
642#pragma mark --- Optional Functions ---
643
644/***
645 *** SecPkcs12AttrsRef manipulation. Optional and in fact expected to
646 *** be rarely used, if ever.
647 ***/
648
649/*
650 * Create/destroy.
651 */
652OSStatus SecPkcs12AttrsCreate(
653	SecPkcs12AttrsRef	*attrs)		// RETURNED
654{
655	BEGIN_P12API
656
657	required(attrs);
658	P12BagAttrsStandAlone *bagAttrs = new P12BagAttrsStandAlone;
659	*attrs = (SecPkcs12AttrsRef)bagAttrs;
660
661	END_P12API
662}
663
664OSStatus SecPkcs12AttrsRelease(
665	SecPkcs12AttrsRef	attrs)
666{
667	BEGIN_P12API
668
669	P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs);
670	delete bagAttrs;
671
672	END_P12API
673}
674
675/*
676 * Add an OID/value set to an existing SecPkcs12AttrsRef.
677 * Values are a CFArray containing an arbitrary number of
678 * CFDataRefs.
679 */
680OSStatus SecPkcs12AttrsAddAttr(
681	SecPkcs12AttrsRef	attrs,
682	CFDataRef			attrOid,
683	CFArrayRef			attrValues)
684{
685	BEGIN_P12API
686
687	P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs);
688	bagAttrs->addAttr(attrOid, attrValues);
689
690	END_P12API
691}
692
693OSStatus SecPkcs12AttrCount(
694	SecPkcs12AttrsRef		attrs,
695	CFIndex					*numAttrs)		// RETURNED
696{
697	BEGIN_P12API
698
699	P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs);
700	required(numAttrs);
701	*numAttrs = bagAttrs->numAttrs();
702
703	END_P12API
704}
705
706/*
707 * Obtain n'th oid/value set from an existing SecPkcs12AttrsRef.
708 */
709OSStatus SecPkcs12AttrsGetAttr(
710	SecPkcs12AttrsRef	attrs,
711	CFIndex				attrNum,
712	CFDataRef			*attrOid,		// RETURNED
713	CFArrayRef			*attrValues)	// RETURNED
714{
715	BEGIN_P12API
716
717	P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs);
718	required(attrOid);
719	required(attrValues);
720	bagAttrs->getAttr((unsigned)attrNum, attrOid, attrValues);
721	END_P12API
722}
723
724OSStatus SecPkcs12SetIntegrityMode(
725	SecPkcs12CoderRef	coder,
726	SecPkcs12Mode		mode)
727{
728	BEGIN_P12API
729
730	P12Coder *p12coder = P12CoderCast(coder);
731	p12coder->integrityMode(mode);
732
733	END_P12API
734}
735
736OSStatus SecPkcs12GetIntegrityMode(
737	SecPkcs12CoderRef	coder,
738	SecPkcs12Mode		*mode)			// RETURNED
739{
740	BEGIN_P12API
741
742	P12Coder *p12coder = P12CoderCast(coder);
743	required(mode);
744	*mode = p12coder->integrityMode();
745
746	END_P12API
747}
748
749OSStatus SecPkcs12SetPrivacyMode(
750	SecPkcs12CoderRef	coder,
751	SecPkcs12Mode		mode)
752{
753	BEGIN_P12API
754
755	P12Coder *p12coder = P12CoderCast(coder);
756	p12coder->privacyMode(mode);
757
758	END_P12API
759}
760
761OSStatus SecPkcs12GetPrivacyMode(
762	SecPkcs12CoderRef	coder,
763	SecPkcs12Mode		*mode)			// RETURNED
764{
765	BEGIN_P12API
766
767	P12Coder *p12coder = P12CoderCast(coder);
768	required(mode);
769	*mode = p12coder->privacyMode();
770
771	END_P12API
772}
773
774/***
775 *** Encryption algorithms
776 ***/
777OSStatus SecPkcs12SetKeyEncryptionAlg(
778	SecPkcs12CoderRef	coder,
779	CFDataRef			encryptionAlg)
780{
781	BEGIN_P12API
782
783	P12Coder *p12coder = P12CoderCast(coder);
784	required(encryptionAlg);
785	p12coder->strongEncrAlg(encryptionAlg);
786
787	END_P12API
788}
789
790OSStatus SecPkcs12SetCertCrlEncryptionAlg(
791	SecPkcs12CoderRef	coder,
792	CFDataRef			encryptionAlg)
793{
794	BEGIN_P12API
795
796	P12Coder *p12coder = P12CoderCast(coder);
797	required(encryptionAlg);
798	p12coder->weakEncrAlg(encryptionAlg);
799
800	END_P12API
801}
802
803OSStatus SecPkcs12SetKeyEncryptionIterCount(
804	SecPkcs12CoderRef	coder,
805	unsigned			iterCount)
806{
807	BEGIN_P12API
808
809	P12Coder *p12coder = P12CoderCast(coder);
810	p12coder->strongEncrIterCount(iterCount);
811
812	END_P12API
813}
814
815OSStatus SecPkcs12SetCertCrlEncryptionIterCount(
816	SecPkcs12CoderRef	coder,
817	unsigned			iterCount)
818{
819	BEGIN_P12API
820
821	P12Coder *p12coder = P12CoderCast(coder);
822	p12coder->weakEncrIterCount(iterCount);
823
824	END_P12API
825}
826
827OSStatus SecPkcs12SetMacIterCount(
828	SecPkcs12CoderRef	coder,
829	unsigned			iterCount)
830{
831	BEGIN_P12API
832
833	P12Coder *p12coder = P12CoderCast(coder);
834	p12coder->macEncrIterCount(iterCount);
835
836	END_P12API
837}
838
839OSStatus SecPkcs12CopyKeyEncryptionAlg(
840	SecPkcs12CoderRef	coder,
841	CFDataRef			*encryptionAlg)			// RETURNED
842{
843	BEGIN_P12API
844
845	P12Coder *p12coder = P12CoderCast(coder);
846	required(encryptionAlg);
847	*encryptionAlg = p12coder->strongEncrAlg();
848
849	END_P12API
850}
851
852OSStatus SecPkcs12CopyCertCrlEncryptionAlg(
853	SecPkcs12CoderRef	coder,
854	CFDataRef			*encryptionAlg)			// RETURNED
855{
856	BEGIN_P12API
857
858	P12Coder *p12coder = P12CoderCast(coder);
859	required(encryptionAlg);
860	*encryptionAlg = p12coder->weakEncrAlg();
861
862	END_P12API
863}
864
865OSStatus SecPkcs12CopyKeyEncryptionIterCount(
866	SecPkcs12CoderRef	coder,
867	unsigned			*iterCount)				// RETURNED
868{
869	BEGIN_P12API
870
871	P12Coder *p12coder = P12CoderCast(coder);
872	required(iterCount);
873	*iterCount = p12coder->strongEncrIterCount();
874
875	END_P12API
876}
877
878OSStatus SecPkcs12CopyCertCrlEncryptionIterCount(
879	SecPkcs12CoderRef	coder,
880	unsigned			*iterCount)				// RETURNED
881{
882	BEGIN_P12API
883
884	P12Coder *p12coder = P12CoderCast(coder);
885	required(iterCount);
886	*iterCount = p12coder->weakEncrIterCount();
887
888	END_P12API
889}
890
891OSStatus SecPkcs12CopyMacIterCount(
892	SecPkcs12CoderRef	coder,
893	unsigned			*iterCount)				// RETURNED
894{
895	BEGIN_P12API
896
897	P12Coder *p12coder = P12CoderCast(coder);
898	required(iterCount);
899	*iterCount = p12coder->macEncrIterCount();
900
901	END_P12API
902}
903
904OSStatus SecPkcs12LimitPrivateKeyImport(
905	SecPkcs12CoderRef	coder,
906	bool				foundOneKey)
907{
908	BEGIN_P12API
909
910	P12Coder *p12coder = P12CoderCast(coder);
911	p12coder->limitPrivKeyImport(foundOneKey);
912
913	END_P12API
914}
915