/* * Copyright (c) 2003-2004 Apple Computer, 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.h - main PKCS12 encode/decode engine. This class * corresponds to a SecPkcs12CoderRef in the public API. */ #ifndef _PKCS12_CODER_H_ #define _PKCS12_CODER_H_ #include #include #include /* * This class essentially consists of the following: * * -- bags of certs, CRLs, keys, and opaque blobs in the * form of P12SafeBag subclasses. * * -- getters and setters to let the app access those bags. * * -- a decode routine which takes an encoded PFX, rips it apart, * and drops what it finds into the bags of cert, CRLS, etc. * * -- an encode routine which takes the contents of the bag and * creates an encoded PFX. * * Everything else is ephemera supporting the above four things. * * Memory usage: * ------------- * * Memory allocation is done in three flavors: * * 1. Via CF objects, when exporting contents of bags to the app. * 2. Via our own member variable SecNssCoder. This is used to allocate * the contents of the bags (certs, etc.) which persist across * API calls. * 3. "Local" SecNssCoders for encode and decode. Allocated in the * stack for those two exported functions and used for all decoding * and encoding. * * The contents of the bags persist as long as an instance of * P12Coder does. * * CF objects the app gives us (e..g, passphrases) * are retained when get them and released in our destructor. * * CF objects we give the app are, of course, the app's responsibility. * * Everything else is allocd locally via the SecNssCoders in encode() * and decode() and has a scope not exceeding those functions. */ class P12Coder { public: /* only constructor */ P12Coder(); ~P12Coder(); /* * These public functions more or less correspond to * the public functions in SecPkcs12.h. */ void setMacPassPhrase( CFStringRef passphrase); void setEncrPassPhrase( CFStringRef passphrase); void setMacPassKey( const CSSM_KEY *passKey); void setEncrPassKey( const CSSM_KEY *passKey); /* main decode function */ void decode( CFDataRef pfx); /* * CSP and DLDB associated with keys. * CSP handle is required, DLDB optional. */ void setKeychain( SecKeychainRef keychain); void setCsp( CSSM_CSP_HANDLE cspHand) { mCspHand = cspHand; } void setDlDb( CSSM_DL_DB_HANDLE dlDbHand) { mDlDbHand = dlDbHand; } CSSM_CSP_HANDLE cspHand() { return mCspHand; } /* High-level import/export */ void importFlags( SecPkcs12ImportFlags flags) { mImportFlags = flags; } SecPkcs12ImportFlags importFlags() { return mImportFlags; } void exportKeychainItems( CFArrayRef items); /* getters */ unsigned numCerts(); unsigned numCrls(); unsigned numKeys(); unsigned numOpaqueBlobs(); P12CertBag *getCert( unsigned dex); P12CrlBag *getCrl( unsigned dex); P12KeyBag *getKey( unsigned dex); P12OpaqueBag *getOpaque( unsigned dex); /* encoding */ void encode( CFDataRef *pfx); // RETURNED void addCert( P12CertBag *cert); void addCrl( P12CrlBag *crl); void addKey( P12KeyBag *key); void addOpaque( P12OpaqueBag *opaque); /* little known, but public, functions */ SecPkcs12Mode integrityMode() { return mIntegrityMode; } SecPkcs12Mode privacyMode() { return mPrivacyMode; } void integrityMode( SecPkcs12Mode mode); void privacyMode( SecPkcs12Mode mode); /* * Public API calls use our coder to create P12SafeBags */ SecNssCoder &coder() { return mCoder; } /* encryption parameter getters/setters */ unsigned weakEncrIterCount() { return mWeakEncrIterCount; } unsigned strongEncrIterCount() { return mStrongEncrIterCount; } unsigned macEncrIterCount() { return mMacIterCount; } void weakEncrIterCount( unsigned ic) { mWeakEncrIterCount = ic; } void strongEncrIterCount( unsigned ic) { mStrongEncrIterCount = ic; } void macEncrIterCount( unsigned ic) { mMacIterCount = ic; } CFDataRef weakEncrAlg(); CFDataRef strongEncrAlg(); void weakEncrAlg( CFDataRef alg); void strongEncrAlg( CFDataRef alg); /* panic button, delete anything stored in a DB during decode */ void deleteDecodedItems(); void limitPrivKeyImport( bool foundOneKey); private: void init(); // one-time init from all constructors /* * Passphrase handling. * * These two convert the app-supplied CFStringRefs into * CSSM_DATAs; if PassKeys are used, these just NULL out * the returned data. */ const CSSM_DATA *getMacPassPhrase(); const CSSM_DATA *getEncrPassPhrase(); /* * These return a CSSM_KEY_PTR is the app had specified * PassKeys, else they return NULL. */ const CSSM_KEY *getMacPassKey(); const CSSM_KEY *getEncrPassKey(); /* in pkcs12Keychain.cpp */ void storeDecodeResults(); void setPrivateKeyHashes(); void notifyKeyImport(); P12CertBag *findCertForKey( P12KeyBag *keyBag); void addSecKey( SecKeyRef keyRef); void addSecCert( SecCertificateRef certRef); /* Lazy evaluation of module handles. */ CSSM_CSP_HANDLE rawCspHand(); CSSM_CL_HANDLE clHand(); /* * A bunch of private encode/decode methods. This makes me * long for ObjC-style categories so these would not * have to appear in this file. * * See implementation for comments and descriptions. */ void encryptedDataDecrypt( const NSS_P7_EncryptedData &edata, SecNssCoder &localCdr, NSS_P12_PBE_Params *pbep, CSSM_DATA &ptext); void algIdParse( const CSSM_X509_ALGORITHM_IDENTIFIER &algId, NSS_P12_PBE_Params *pbeParams, SecNssCoder &localCdr); void encryptedDataParse( const NSS_P7_EncryptedData &edata, SecNssCoder &localCdr, NSS_P12_PBE_Params *pbep); void shroudedKeyBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void keyBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void certBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void crlBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void secretBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void safeContentsBagParse( const NSS_P12_SafeBag &safeBag, SecNssCoder &localCdr); void safeContentsParse( const CSSM_DATA &contentsBlob, SecNssCoder &localCdr); void authSafeElementParse( const NSS_P7_DecodedContentInfo *info, SecNssCoder &localCdr); void macParse( const NSS_P12_MacData &macData, SecNssCoder &localCdr); void authSafeParse( const CSSM_DATA &authSafeBlob, SecNssCoder &localCdr); /* private encoding routines */ NSS_P7_DecodedContentInfo *safeContentsBuild( NSS_P12_SafeBag **bags, NSS_P7_CI_Type type, // CT_Data, CT_EncryptedData CSSM_OID *encrOid, // only for CT_EncryptedData unsigned iterCount, // ditto SecNssCoder &localCdr); void authSafeBuild( NSS_P7_DecodedContentInfo &authSafe, SecNssCoder &localCdr); void encryptData( const CSSM_DATA &ptext, CSSM_OID &encrOid, unsigned iterCount, NSS_P7_EncryptedData &ed, SecNssCoder &localCdr); void algIdBuild( CSSM_X509_ALGORITHM_IDENTIFIER &algId, const CSSM_OID &algOid, const CSSM_DATA &salt, unsigned iterCount, SecNssCoder &localCdr); void macSignPfx( NSS_P12_DecodedPFX &pfx, SecNssCoder &localCdr); NSS_P12_SafeBag *certBagBuild( P12CertBag *cert, SecNssCoder &localCdr); NSS_P12_SafeBag *crlBagBuild( P12CrlBag *crl, SecNssCoder &localCdr); NSS_P12_SafeBag *keyBagBuild( P12KeyBag *key, SecNssCoder &localCdr); NSS_P12_SafeBag *opaqueBagBuild( P12OpaqueBag *op, SecNssCoder &localCdr); /* member variables */ SecPkcs12Mode mPrivacyMode; SecPkcs12Mode mIntegrityMode; /* passwords - as app gave us, and translated into ready-to-use * unicode strings */ CFStringRef mMacPassphrase; CFStringRef mEncrPassPhrase; CSSM_DATA mMacPassData; CSSM_DATA mEncrPassData; /* passphrases in key form */ const CSSM_KEY *mMacPassKey; const CSSM_KEY *mEncrPassKey; /* * App has to either set mKeychain or mCspHand. In the former * case we infer both mCspHand and mDlDbHand from the keychainRef. */ SecKeychainRef mKeychain; CSSM_CSP_HANDLE mCspHand; CSSM_DL_DB_HANDLE mDlDbHand; /* * LimitPrivateKeyImport mechanism */ typedef enum { PKIS_NoLimit, // no limit PKIS_AllowOne, // allow import of at most one PKIS_NoMore // found one, no more allowed } p12PrivKeyImportState; p12PrivKeyImportState mPrivKeyImportState; /* * Encryption/MAC parameters */ CSSM_OID mWeakEncrAlg; // for certs and CRLs CSSM_OID mStrongEncrAlg; unsigned mWeakEncrIterCount; unsigned mStrongEncrIterCount; unsigned mMacIterCount; /* * Import flags */ SecPkcs12ImportFlags mImportFlags; /* * Four individual piles of safe bags */ vector mCerts; vector mCrls; vector mKeys; vector mOpaques; /* * Internal CSSM module handles, lazily evaluated. */ CSSM_CSP_HANDLE mRawCspHand; CSSM_CL_HANDLE mClHand; /* * The source of most (all?) of our privately allocated data */ SecNssCoder mCoder; }; #endif /* _PKCS12_CODER_H_ */