]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / 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 (file)
index 0000000..c1bb44e
--- /dev/null
@@ -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 <Security/cssmerr.h>
+#include <security_cdsa_utils/cuCdsaUtils.h>
+#include <Security/oidsalg.h>
+#include <Security/SecBase.h>
+/*
+ * 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;
+       }
+}