#include "pkcs12Coder.h"
#include "pkcs12Debug.h"
#include "pkcs12Utils.h"
#include <Security/cssmerr.h>
#include <security_cdsa_utils/cuCdsaUtils.h>
#include <Security/oidsalg.h>
#include <Security/SecBase.h>
#define P12_ENCR_ITER_COUNT 2048
#define P12_MAC_ITER_COUNT 1
#define P12_WEAK_ENCR_ALG CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC
#define P12_STRONG_ENCR_ALG CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC
#define P12_KC_IMPORT_DEFAULT (kSecImportCertificates | \
kSecImportCRLs | \
kSecImportKeys)
P12Coder::P12Coder()
{
init();
}
void P12Coder::init()
{
mPrivacyMode = kSecPkcs12ModePassword;
mIntegrityMode = kSecPkcs12ModePassword;
mMacPassphrase = NULL;
mEncrPassPhrase = NULL;
mMacPassData.Data = NULL;
mMacPassData.Length = 0;
mEncrPassData.Data = NULL;
mEncrPassData.Length = 0;
mMacPassKey = NULL;
mEncrPassKey = NULL;
mKeychain = NULL;
mCspHand = 0;
mDlDbHand.DLHandle = 0;
mDlDbHand.DBHandle = 0;
mPrivKeyImportState = PKIS_NoLimit;
mWeakEncrAlg = P12_WEAK_ENCR_ALG;
mStrongEncrAlg = P12_STRONG_ENCR_ALG;
mWeakEncrIterCount = P12_ENCR_ITER_COUNT;
mStrongEncrIterCount = P12_ENCR_ITER_COUNT;
mMacIterCount = P12_MAC_ITER_COUNT;
mImportFlags = P12_KC_IMPORT_DEFAULT;
mRawCspHand = 0;
mClHand = 0;
mAccess = NULL;
mNoAcl = false;
mKeyUsage = CSSM_KEYUSE_ANY;
mKeyAttrs = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE |
CSSM_KEYATTR_SENSITIVE;
}
#define deleteVect(v) \
{ \
while(v.size()) { \
delete v[0]; \
v.erase(v.begin()); \
} \
v.clear(); \
}
P12Coder::~P12Coder()
{
if(mMacPassphrase) {
CFRelease(mMacPassphrase);
}
if(mEncrPassPhrase) {
CFRelease(mEncrPassPhrase);
}
if(mAccess) {
CFRelease(mAccess);
}
deleteVect(mCerts);
deleteVect(mCrls);
deleteVect(mKeys);
deleteVect(mOpaques);
if(mKeychain) {
CFRelease(mKeychain);
}
if(mRawCspHand) {
cuCspDetachUnload(mRawCspHand, CSSM_TRUE);
}
if(mClHand) {
cuClDetachUnload(mClHand);
}
}
void P12Coder::setKeychain(
SecKeychainRef keychain)
{
OSStatus ortn = SecKeychainGetCSPHandle(keychain, &mCspHand);
if(ortn) {
MacOSError::throwMe(ortn);
}
ortn = SecKeychainGetDLDBHandle(keychain, &mDlDbHand);
if(ortn) {
MacOSError::throwMe(ortn);
}
CFRetain(keychain);
mKeychain = keychain;
}
void P12Coder::setAccess(
SecAccessRef access)
{
if(mAccess) {
CFRelease(mAccess);
}
mAccess = access;
if(mAccess) {
CFRetain(mAccess);
}
else {
mNoAcl = true;
}
}
#define SEC_KEYATTR_RETURN_MASK \
(CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_NONE)
void P12Coder::setKeyAttrs(
CSSM_KEYATTR_FLAGS keyAttrs)
{
mKeyAttrs = keyAttrs;
mKeyAttrs &= ~SEC_KEYATTR_RETURN_MASK;
mKeyAttrs |= CSSM_KEYATTR_RETURN_REF;
}
const CSSM_DATA *P12Coder::getMacPassPhrase()
{
if(mMacPassData.Data != NULL) {
return &mMacPassData;
}
else if (mMacPassphrase) {
p12ImportPassPhrase(mMacPassphrase, mCoder, mMacPassData);
return &mMacPassData;
}
else {
return NULL;
}
}
const CSSM_DATA *P12Coder::getEncrPassPhrase()
{
if(mEncrPassData.Data != NULL) {
return &mEncrPassData;
}
else if (mEncrPassPhrase) {
p12ImportPassPhrase(mEncrPassPhrase, mCoder, mEncrPassData);
return &mEncrPassData;
}
return getMacPassPhrase();
}
const CSSM_KEY *P12Coder::getMacPassKey()
{
return mMacPassKey;
}
const CSSM_KEY *P12Coder::getEncrPassKey()
{
if(mEncrPassKey != NULL) {
return mEncrPassKey;
}
else {
return getMacPassKey();
}
}
CSSM_CSP_HANDLE P12Coder::rawCspHand()
{
if(mRawCspHand != 0) {
return mRawCspHand;
}
mRawCspHand = cuCspStartup(CSSM_TRUE);
if(mRawCspHand == 0) {
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
return mRawCspHand;
}
CSSM_CL_HANDLE P12Coder::clHand()
{
if(mClHand != 0) {
return mClHand;
}
mClHand = cuClStartup();
if(mClHand == 0) {
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
return mClHand;
}
void P12Coder::setMacPassPhrase(
CFStringRef passphrase)
{
CFRetain(passphrase);
mMacPassphrase = passphrase;
}
void P12Coder::setEncrPassPhrase(
CFStringRef passphrase)
{
CFRetain(passphrase);
mEncrPassPhrase = passphrase;
}
void P12Coder::setMacPassKey(
const CSSM_KEY *passKey)
{
mMacPassKey = passKey;
}
void P12Coder::setEncrPassKey(
const CSSM_KEY *passKey)
{
mEncrPassKey = passKey;
}
unsigned P12Coder::numCerts()
{
return (unsigned)mCerts.size();
}
unsigned P12Coder::numCrls()
{
return (unsigned)mCrls.size();
}
unsigned P12Coder::numKeys()
{
return (unsigned)mKeys.size();
}
unsigned P12Coder::numOpaqueBlobs()
{
return (unsigned)mOpaques.size();
}
P12CertBag *P12Coder::getCert(
unsigned dex)
{
if(mCerts.size() < (dex + 1)) {
MacOSError::throwMe(errSecParam);
}
return mCerts[dex];
}
P12CrlBag *P12Coder::getCrl(
unsigned dex)
{
if(mCrls.size() < (dex + 1)) {
MacOSError::throwMe(errSecParam);
}
return mCrls[dex];
}
P12KeyBag *P12Coder::getKey(
unsigned dex)
{
if(mKeys.size() < (dex + 1)) {
MacOSError::throwMe(errSecParam);
}
return mKeys[dex];
}
P12OpaqueBag *P12Coder::getOpaque(
unsigned dex)
{
if(mOpaques.size() < (dex + 1)) {
MacOSError::throwMe(errSecParam);
}
return mOpaques[dex];
}
void P12Coder::addCert(
P12CertBag *cert)
{
mCerts.push_back(cert);
}
void P12Coder::addCrl(
P12CrlBag *crl)
{
mCrls.push_back(crl);
}
void P12Coder::addKey(
P12KeyBag *key)
{
mKeys.push_back(key);
}
void P12Coder::addOpaque(
P12OpaqueBag *opaque)
{
mOpaques.push_back(opaque);
}
void P12Coder::integrityMode(
SecPkcs12Mode mode)
{
if(mode != kSecPkcs12ModePassword) {
MacOSError::throwMe(errSecParam);
}
mIntegrityMode = mode;
}
void P12Coder::privacyMode(
SecPkcs12Mode mode)
{
if(mode != kSecPkcs12ModePassword) {
MacOSError::throwMe(errSecParam);
}
mPrivacyMode = mode;
}
CFDataRef P12Coder::weakEncrAlg()
{
return p12CssmDataToCf(mWeakEncrAlg);
}
CFDataRef P12Coder::strongEncrAlg()
{
return p12CssmDataToCf(mStrongEncrAlg);
}
void P12Coder::weakEncrAlg(
CFDataRef alg)
{
p12CfDataToCssm(alg, mWeakEncrAlg, mCoder);
}
void P12Coder::strongEncrAlg(
CFDataRef alg)
{
p12CfDataToCssm(alg, mStrongEncrAlg, mCoder);
}
void P12Coder::limitPrivKeyImport(
bool foundOneKey)
{
if(foundOneKey) {
mPrivKeyImportState = PKIS_NoMore;
}
else {
mPrivKeyImportState = PKIS_AllowOne;
}
}