/ OSX / libsecurity_pkcs12 / lib / SecPkcs12.cpp
SecPkcs12.cpp
  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   * 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 */
 50  static 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   */
 61  static 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   */
 73  static 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*() */
 83  static 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   */
 94  OSStatus 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   */
110  OSStatus SecPkcs12CoderRelease(
111  	SecPkcs12CoderRef	coder)
112  {
113  	BEGIN_P12API
114  	
115  	P12Coder *p12coder = P12CoderCast(coder);
116  	delete p12coder;
117  	
118  	END_P12API
119  }
120  
121  OSStatus 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  
134  OSStatus 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   */
150  OSStatus 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  
163  OSStatus 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   */
180  OSStatus 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   */
196  OSStatus 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  
208  OSStatus 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  	
220  OSStatus 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  
233  OSStatus 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  
246  OSStatus 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  
258  OSStatus 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  	
270  OSStatus 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   */
287  OSStatus 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   */
312  OSStatus 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  
325  OSStatus 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   */
355  OSStatus 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  
368  OSStatus 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   */
398  OSStatus 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  
411  OSStatus 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  
425  OSStatus 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   */
457  OSStatus 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  
470  OSStatus 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   */
508  OSStatus 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   */
523  OSStatus 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  
563  OSStatus 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  
579  OSStatus 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 */
603  OSStatus 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  
622  OSStatus 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   */
652  OSStatus 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  
664  OSStatus 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   */
680  OSStatus 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  
693  OSStatus 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   */
709  OSStatus 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  
724  OSStatus 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  
736  OSStatus 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  
749  OSStatus 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  
761  OSStatus 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   ***/
777  OSStatus 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  
790  OSStatus 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  
803  OSStatus 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  
815  OSStatus 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  
827  OSStatus 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  
839  OSStatus 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  
852  OSStatus 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  
865  OSStatus 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  
878  OSStatus 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  
891  OSStatus 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  
904  OSStatus 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  }