X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp?ds=sidebyside diff --git a/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp b/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp new file mode 100644 index 00000000..2d5e02f7 --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * SecPkcs12.cpp + */ + +#include "SecPkcs12.h" +#include "pkcs12Coder.h" +#include "pkcs12BagAttrs.h" +#include "pkcs12SafeBag.h" +#include "pkcs12Utils.h" +#include +#include + +/* + * API function call wrappers, impermeable to C++ exceptions + */ +#define BEGIN_P12API \ + try { + +#define END_P12API \ + } \ + catch (const MacOSError &err) { return err.osStatus(); } \ + catch (const CommonError &err) { return SecKeychainErrFromOSStatus(err.osStatus()); } \ + catch (const std::bad_alloc &) { return errSecAllocate; } \ + catch (...) { return errSecInternalComponent; } \ + return errSecSuccess; + +/* catch incoming NULL parameters */ +static inline void required( + const void *param) +{ + if(param == NULL) { + MacOSError::throwMe(errSecParam); + } +} + +/* + * Standard means of casting a SecPkcs12CoderRef to a P12Coder * + */ +static inline P12Coder *P12CoderCast( + SecPkcs12CoderRef coder) +{ + required(coder); + return reinterpret_cast(coder); +} + +/* + * Standard means of casting a SecPkcs12AttrsRef to a P12BagAttrs * + * This one uses the P12BagAttrsStandAlone version, not tied to + * a specific P12Coder (actually, to a P12Coder's SecNssCoder). + */ +static inline P12BagAttrsStandAlone *P12AttrsCast( + SecPkcs12AttrsRef attrs) +{ + if(attrs == NULL) { + MacOSError::throwMe(errSecParam); + } + return reinterpret_cast(attrs); +} + +/* optional flavor used in SecPkcs12Add*() */ +static inline P12BagAttrs *P12AttrsCastOpt( + SecPkcs12AttrsRef attrs) +{ + return reinterpret_cast(attrs); +} + +#pragma mark --- SecPkcs12CoderRef create/destroy --- + +/* + * Basic SecPkcs12CoderRef create/destroy. + */ +OSStatus SecPkcs12CoderCreate( + SecPkcs12CoderRef *coder) // RETURNED +{ + BEGIN_P12API + + required(coder); + P12Coder *p12coder = new P12Coder; + *coder = p12coder; + + END_P12API +} + +/* + * Destroy object created in SecPkcs12CoderCreate. + * This will go away if we make this object a CoreFoundation type. + */ +OSStatus SecPkcs12CoderRelease( + SecPkcs12CoderRef coder) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + delete p12coder; + + END_P12API +} + +OSStatus SecPkcs12SetMACPassphrase( + SecPkcs12CoderRef coder, + CFStringRef passphrase) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(passphrase); + p12coder->setMacPassPhrase(passphrase); + + END_P12API +} + +OSStatus SecPkcs12SetMACPassKey( + SecPkcs12CoderRef coder, + const CSSM_KEY *passKey) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(passKey); + p12coder->setMacPassKey(passKey); + + END_P12API +} + +/* + * Specify separate passphrase for encrypt/decrypt. + */ +OSStatus SecPkcs12SetCryptPassphrase( + SecPkcs12CoderRef coder, + CFStringRef passphrase) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(passphrase); + p12coder->setEncrPassPhrase(passphrase); + + END_P12API +} + +OSStatus SecPkcs12SetCryptPassKey( + SecPkcs12CoderRef coder, + const CSSM_KEY *passKey) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(passKey); + p12coder->setEncrPassKey(passKey); + + END_P12API +} + + +/* + * Target location of decoded keys and certs. + */ +OSStatus SecPkcs12SetKeychain( + SecPkcs12CoderRef coder, + SecKeychainRef keychain) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(keychain); + p12coder->setKeychain(keychain); + + END_P12API +} + +/* + * Required iff SecPkcs12SetKeychain() not called. + */ +OSStatus SecPkcs12SetCspHandle( + SecPkcs12CoderRef coder, + CSSM_CSP_HANDLE cspHandle) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->setCsp(cspHandle); + + END_P12API +} + +OSStatus SecPkcs12SetImportToKeychain( + SecPkcs12CoderRef coder, + SecPkcs12ImportFlags flags) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->importFlags(flags); + + END_P12API +} + +OSStatus SecPkcs12GetImportToKeychain( + SecPkcs12CoderRef coder, + SecPkcs12ImportFlags *flags) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(flags); + *flags = p12coder->importFlags(); + + END_P12API +} + +OSStatus SecPkcs12ExportKeychainItems( + SecPkcs12CoderRef coder, + CFArrayRef items) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(items); + p12coder->exportKeychainItems(items); + + END_P12API +} + +OSStatus SecPkcs12SetAccess( + SecPkcs12CoderRef coder, + SecAccessRef access) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->setAccess(access); + + END_P12API +} + +OSStatus SecPkcs12SetKeyUsage( + SecPkcs12CoderRef coder, + CSSM_KEYUSE keyUsage) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->setKeyUsage(keyUsage); + + END_P12API +} + +OSStatus SecPkcs12SetKeyAttrs( + SecPkcs12CoderRef coder, + CSSM_KEYATTR_FLAGS keyAttrs) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->setKeyAttrs(keyAttrs); + + END_P12API +} + +#pragma mark --- Decoder Functions --- + +/* + * Parse and decode. + */ +OSStatus SecPkcs12Decode( + SecPkcs12CoderRef coder, + CFDataRef pfx) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(pfx); + try { + p12coder->decode(pfx); + } + catch(...) { + /* abort - clean up - delete stored keys */ + p12coder->deleteDecodedItems(); + throw; + } + END_P12API +} + +/* + * Subsequent to decoding, obtain the components. + * These functions can also be used as "getter" functions while encoding. + * + * Certificates: + */ +OSStatus SecPkcs12CertificateCount( + SecPkcs12CoderRef coder, + CFIndex *numCerts) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(numCerts); + *numCerts = p12coder->numCerts(); + + END_P12API +} + +OSStatus SecPkcs12CopyCertificate( + SecPkcs12CoderRef coder, + CFIndex certNum, + SecCertificateRef *secCert, // RETURNED + CFStringRef *friendlyName, // RETURNED + CFDataRef *localKeyId, // RETURNED + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(secCert); + /* others are optional - if NULL, we don't return that param */ + P12CertBag *bag = p12coder->getCert((unsigned)certNum); + *secCert = bag->getSecCert(); + + /* now the optional attrs */ + P12BagAttrs *p12Attrs = NULL; + bag->copyAllAttrs(friendlyName, localKeyId, + attrs ? &p12Attrs : NULL); + if(p12Attrs) { + *attrs = p12Attrs; + } + END_P12API +} + +/* + * CRLs. The might change if a SecCrl type is defined elsewhere. + * We'll typedef it here to preserve the semantics of this function. + */ +OSStatus SecPkcs12CrlCount( + SecPkcs12CoderRef coder, + CFIndex *numCrls) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(numCrls); + *numCrls = p12coder->numCrls(); + + END_P12API +} + +OSStatus SecPkcs12CopyCrl( + SecPkcs12CoderRef coder, + CFIndex crlNum, + SecCrlRef *crl, // RETURNED + CFStringRef *friendlyName, // RETURNED + CFDataRef *localKeyId, // RETURNED + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(crl); + /* others are optional - if NULL, we don't return that param */ + P12CrlBag *bag = p12coder->getCrl((unsigned)crlNum); + *crl = p12CssmDataToCf(bag->crlData()); + + /* now the optional attrs */ + P12BagAttrs *p12Attrs = NULL; + bag->copyAllAttrs(friendlyName, localKeyId, + attrs ? &p12Attrs : NULL); + if(p12Attrs) { + *attrs = p12Attrs; + } + + END_P12API +} + +/* + * Private keys. + */ +OSStatus SecPkcs12PrivateKeyCount( + SecPkcs12CoderRef coder, + CFIndex *numKeys) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(numKeys); + *numKeys = p12coder->numKeys(); + + END_P12API +} + +OSStatus SecPkcs12CopyPrivateKey( + SecPkcs12CoderRef coder, + CFIndex keyNum, + SecKeyRef *privateKey, // RETURNED + CFStringRef *friendlyName, // RETURNED + CFDataRef *localKeyId, // RETURNED + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + /*P12Coder *p12coder = P12CoderCast(coder); */ + return errSecUnimplemented; + END_P12API +} + +OSStatus SecPkcs12GetCssmPrivateKey( + SecPkcs12CoderRef coder, + CFIndex keyNum, + CSSM_KEY_PTR *privateKey, // RETURNED + CFStringRef *friendlyName, // RETURNED + CFDataRef *localKeyId, // RETURNED + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + P12Coder *p12coder = P12CoderCast(coder); + required(privateKey); + /* others are optional - if NULL, we don't return that param */ + P12KeyBag *bag = p12coder->getKey((unsigned)keyNum); + *privateKey = bag->key(); + + /* now the optional attrs */ + P12BagAttrs *p12Attrs = NULL; + bag->copyAllAttrs(friendlyName, localKeyId, + attrs ? &p12Attrs : NULL); + if(p12Attrs) { + *attrs = p12Attrs; + } + + END_P12API +} + +/* + * Catch-all for other components not currently understood + * or supported by this library. An "opaque blob" component + * is identified by an OID and is obtained as an opaque data + * blob. + */ +OSStatus SecPkcs12OpaqueBlobCount( + SecPkcs12CoderRef coder, + CFIndex *numBlobs) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(numBlobs); + *numBlobs = p12coder->numOpaqueBlobs(); + + END_P12API +} + +OSStatus SecPkcs12CopyOpaqueBlob( + SecPkcs12CoderRef coder, + CFIndex blobNum, + CFDataRef *blobOid, // RETURNED + CFDataRef *opaqueBlob, // RETURNED + CFStringRef *friendlyName, // RETURNED + CFDataRef *localKeyId, // RETURNED + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(blobOid); + required(opaqueBlob); + + /* others are optional - if NULL, we don't return that param */ + P12OpaqueBag *bag = p12coder->getOpaque((unsigned)blobNum); + *opaqueBlob = p12CssmDataToCf(bag->blob()); + *blobOid = p12CssmDataToCf(bag->oid()); + + /* now the optional attrs */ + P12BagAttrs *p12Attrs = NULL; + bag->copyAllAttrs(friendlyName, localKeyId, + attrs ? &p12Attrs : NULL); + if(p12Attrs) { + *attrs = p12Attrs; + } + + END_P12API +} + +#pragma mark --- Encoder Functions --- + +/* + * This the final step to create an encoded PKCS12 PFX blob, + * after calling some number of SecPkcs12Set* functions below. + * The result is a DER_encoded PFX in PKCS12 lingo. + */ +OSStatus SecPkcs12Encode( + SecPkcs12CoderRef coder, + CFDataRef *pfx) // RETURNED +{ + BEGIN_P12API + P12Coder *p12coder = P12CoderCast(coder); + required(pfx); + p12coder->encode(pfx); + END_P12API +} + +/* + * Add individual components. "Getter" functions are available + * as described above (under "Functions used for decoding"). + */ +OSStatus SecPkcs12AddCertificate( + SecPkcs12CoderRef coder, + SecCertificateRef cert, + CFStringRef friendlyName, // optional + CFDataRef localKeyId, // optional + SecPkcs12AttrsRef attrs) // optional +{ + BEGIN_P12API + P12Coder *p12coder = P12CoderCast(coder); + required(cert); + CSSM_DATA certData; + OSStatus ortn = SecCertificateGetData(cert, &certData); + if(ortn) { + return ortn; + } + CSSM_CERT_TYPE certType; + ortn = SecCertificateGetType(cert, &certType); + if(ortn) { + return ortn; + } + NSS_P12_CertBagType type; + switch(certType) { + case CSSM_CERT_X_509v1: + case CSSM_CERT_X_509v2: + case CSSM_CERT_X_509v3: + type = CT_X509; + break; + case CSSM_CERT_SDSIv1: + type = CT_SDSI; + break; + default: + type = CT_Unknown; + break; + } + P12CertBag *bag = new P12CertBag(type, certData, friendlyName, + localKeyId, P12AttrsCastOpt(attrs), p12coder->coder()); + p12coder->addCert(bag); + END_P12API +} + +OSStatus SecPkcs12AddCrl( + SecPkcs12CoderRef coder, + SecCrlRef crl, + CFStringRef friendlyName, // optional + CFDataRef localKeyId, // optional + SecPkcs12AttrsRef attrs) // optional +{ + BEGIN_P12API + P12Coder *p12coder = P12CoderCast(coder); + required(crl); + P12CrlBag *bag = new P12CrlBag(CRT_X509, crl, friendlyName, + localKeyId, P12AttrsCastOpt(attrs), p12coder->coder()); + p12coder->addCrl(bag); + END_P12API +} + +OSStatus SecPkcs12AddPrivateKey( + SecPkcs12CoderRef coder, + SecKeyRef privateKey, + CFStringRef friendlyName, // optional + CFDataRef localKeyId, // optional + SecPkcs12AttrsRef attrs) // optional +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(privateKey); + const CSSM_KEY *cssmKey; + OSStatus ortn = SecKeyGetCSSMKey(privateKey, &cssmKey); + if(ortn) { + return ortn; + } + P12KeyBag *bag = new P12KeyBag(cssmKey, p12coder->cspHand(), + friendlyName, localKeyId, P12AttrsCastOpt(attrs), p12coder->coder()); + p12coder->addKey(bag); + + END_P12API +} + +#if 0 /* Unused */ +OSStatus SecPkcs12AddCssmPrivateKey( + SecPkcs12CoderRef coder, + CSSM_KEY_PTR cssmKey, + CFStringRef friendlyName, // optional + CFDataRef localKeyId, // optional + SecPkcs12AttrsRef attrs) // optional +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(cssmKey); + P12KeyBag *bag = new P12KeyBag(cssmKey, p12coder->cspHand(), + friendlyName, localKeyId, P12AttrsCastOpt(attrs), p12coder->coder()); + p12coder->addKey(bag); + + END_P12API +} +#endif + +OSStatus SecPkcs12AddOpaqueBlob( + SecPkcs12CoderRef coder, + CFDataRef blobOid, + CFDataRef opaqueBlob, + CFStringRef friendlyName, // optional + CFDataRef localKeyId, // optional + SecPkcs12AttrsRef attrs) // optional +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(blobOid); + required(opaqueBlob); + P12OpaqueBag *bag = new P12OpaqueBag(blobOid, opaqueBlob, friendlyName, + localKeyId, P12AttrsCastOpt(attrs), p12coder->coder()); + p12coder->addOpaque(bag); + + END_P12API +} + +#pragma mark --- Optional Functions --- + +/*** + *** SecPkcs12AttrsRef manipulation. Optional and in fact expected to + *** be rarely used, if ever. + ***/ + +/* + * Create/destroy. + */ +OSStatus SecPkcs12AttrsCreate( + SecPkcs12AttrsRef *attrs) // RETURNED +{ + BEGIN_P12API + + required(attrs); + P12BagAttrsStandAlone *bagAttrs = new P12BagAttrsStandAlone; + *attrs = (SecPkcs12AttrsRef)bagAttrs; + + END_P12API +} + +OSStatus SecPkcs12AttrsRelease( + SecPkcs12AttrsRef attrs) +{ + BEGIN_P12API + + P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs); + delete bagAttrs; + + END_P12API +} + +/* + * Add an OID/value set to an existing SecPkcs12AttrsRef. + * Values are a CFArray containing an arbitrary number of + * CFDataRefs. + */ +OSStatus SecPkcs12AttrsAddAttr( + SecPkcs12AttrsRef attrs, + CFDataRef attrOid, + CFArrayRef attrValues) +{ + BEGIN_P12API + + P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs); + bagAttrs->addAttr(attrOid, attrValues); + + END_P12API +} + +OSStatus SecPkcs12AttrCount( + SecPkcs12AttrsRef attrs, + CFIndex *numAttrs) // RETURNED +{ + BEGIN_P12API + + P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs); + required(numAttrs); + *numAttrs = bagAttrs->numAttrs(); + + END_P12API +} + +/* + * Obtain n'th oid/value set from an existing SecPkcs12AttrsRef. + */ +OSStatus SecPkcs12AttrsGetAttr( + SecPkcs12AttrsRef attrs, + CFIndex attrNum, + CFDataRef *attrOid, // RETURNED + CFArrayRef *attrValues) // RETURNED +{ + BEGIN_P12API + + P12BagAttrsStandAlone *bagAttrs = P12AttrsCast(attrs); + required(attrOid); + required(attrValues); + bagAttrs->getAttr((unsigned)attrNum, attrOid, attrValues); + END_P12API +} + +OSStatus SecPkcs12SetIntegrityMode( + SecPkcs12CoderRef coder, + SecPkcs12Mode mode) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->integrityMode(mode); + + END_P12API +} + +OSStatus SecPkcs12GetIntegrityMode( + SecPkcs12CoderRef coder, + SecPkcs12Mode *mode) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(mode); + *mode = p12coder->integrityMode(); + + END_P12API +} + +OSStatus SecPkcs12SetPrivacyMode( + SecPkcs12CoderRef coder, + SecPkcs12Mode mode) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->privacyMode(mode); + + END_P12API +} + +OSStatus SecPkcs12GetPrivacyMode( + SecPkcs12CoderRef coder, + SecPkcs12Mode *mode) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(mode); + *mode = p12coder->privacyMode(); + + END_P12API +} + +/*** + *** Encryption algorithms + ***/ +OSStatus SecPkcs12SetKeyEncryptionAlg( + SecPkcs12CoderRef coder, + CFDataRef encryptionAlg) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(encryptionAlg); + p12coder->strongEncrAlg(encryptionAlg); + + END_P12API +} + +OSStatus SecPkcs12SetCertCrlEncryptionAlg( + SecPkcs12CoderRef coder, + CFDataRef encryptionAlg) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(encryptionAlg); + p12coder->weakEncrAlg(encryptionAlg); + + END_P12API +} + +OSStatus SecPkcs12SetKeyEncryptionIterCount( + SecPkcs12CoderRef coder, + unsigned iterCount) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->strongEncrIterCount(iterCount); + + END_P12API +} + +OSStatus SecPkcs12SetCertCrlEncryptionIterCount( + SecPkcs12CoderRef coder, + unsigned iterCount) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->weakEncrIterCount(iterCount); + + END_P12API +} + +OSStatus SecPkcs12SetMacIterCount( + SecPkcs12CoderRef coder, + unsigned iterCount) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->macEncrIterCount(iterCount); + + END_P12API +} + +OSStatus SecPkcs12CopyKeyEncryptionAlg( + SecPkcs12CoderRef coder, + CFDataRef *encryptionAlg) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(encryptionAlg); + *encryptionAlg = p12coder->strongEncrAlg(); + + END_P12API +} + +OSStatus SecPkcs12CopyCertCrlEncryptionAlg( + SecPkcs12CoderRef coder, + CFDataRef *encryptionAlg) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(encryptionAlg); + *encryptionAlg = p12coder->weakEncrAlg(); + + END_P12API +} + +OSStatus SecPkcs12CopyKeyEncryptionIterCount( + SecPkcs12CoderRef coder, + unsigned *iterCount) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(iterCount); + *iterCount = p12coder->strongEncrIterCount(); + + END_P12API +} + +OSStatus SecPkcs12CopyCertCrlEncryptionIterCount( + SecPkcs12CoderRef coder, + unsigned *iterCount) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(iterCount); + *iterCount = p12coder->weakEncrIterCount(); + + END_P12API +} + +OSStatus SecPkcs12CopyMacIterCount( + SecPkcs12CoderRef coder, + unsigned *iterCount) // RETURNED +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + required(iterCount); + *iterCount = p12coder->macEncrIterCount(); + + END_P12API +} + +OSStatus SecPkcs12LimitPrivateKeyImport( + SecPkcs12CoderRef coder, + bool foundOneKey) +{ + BEGIN_P12API + + P12Coder *p12coder = P12CoderCast(coder); + p12coder->limitPrivKeyImport(foundOneKey); + + END_P12API +}