X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp diff --git a/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp new file mode 100644 index 00000000..c1bb44ec --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp @@ -0,0 +1,414 @@ +/* + * 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@ + */ + +/* + * pkcs12Coder.cpp - Public P12Coder coder functions. + */ + +#include "pkcs12Coder.h" +#include "pkcs12Debug.h" +#include "pkcs12Utils.h" +#include +#include +#include +#include +/* + * Default encryption parameters + */ +#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 + +/* + * Default import flags. + */ +#define P12_KC_IMPORT_DEFAULT (kSecImportCertificates | \ + kSecImportCRLs | \ + kSecImportKeys) + +P12Coder::P12Coder() +{ + init(); +} + +/* one-time init from all constructors */ +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; /* default */ + /* default key attrs; we add CSSM_KEYATTR_PERMANENT if importing to + * a keychain */ + mKeyAttrs = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE; +} + +/* + * FIXME - can't we get vector's destructor to do this? + */ +#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 { + /* NULL ==> no ACL */ + 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) +{ + /* ensure we're generating a ref key no matter what caller asks for */ + mKeyAttrs = keyAttrs; + mKeyAttrs &= ~SEC_KEYATTR_RETURN_MASK; + mKeyAttrs |= CSSM_KEYATTR_RETURN_REF; +} + +/* + * Private methods for obtaining passprases in CSSM_DATA form. + */ +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; + } + /* no separate passphrase found, use MAC passphrase */ + return getMacPassPhrase(); +} + +/* + * These return a CSSM_KEY_PTR is the app had specified + * PassKeys, else they return NULL. + */ +const CSSM_KEY *P12Coder::getMacPassKey() +{ + return mMacPassKey; +} + +const CSSM_KEY *P12Coder::getEncrPassKey() +{ + if(mEncrPassKey != NULL) { + return mEncrPassKey; + } + else { + return getMacPassKey(); + } +} + +/* + * Lazy evaluation of module handles. + */ +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; +} + +/* + * These public functions more or less correspond to + * the public functions in SecPkcs12.h. + */ +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; +} + +/* getters */ +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]; +} + +/* + * These four "add" functions are invoked by the app prior to encoding + * and by our decoder while decoding. + */ +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); +} + + +/* little known, but public, functions */ +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; + } +}