/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This 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. */ #ifdef BSAFE_CSP_ENABLE // // bsafecspi - implementation layer for C++ BSafe 4 interface // #ifndef _H_BSAFECSPI #define _H_BSAFECSPI #include #include "bsobjects.h" #include "AppleCSPContext.h" #include "AppleCSPSession.h" #include #include // // The BSafe class is more of a namespace than anything else. // Just think of it as the "static binder" for BSafe's objects. // Note that we keep a global, static allocator. We have to; BSafe // doesn't have any state management at that level. // class BSafe { class BSafeContext; friend class BSafeContext; class BSafeFactory; friend class BSafeFactory; public: static void setNormAllocator(CssmAllocator *alloc) { assert(!normAllocator); normAllocator = alloc; } static void setPrivAllocator(CssmAllocator *alloc) { assert(!privAllocator); privAllocator = alloc; } static bool setup( AppleCSPSession &session, CSPFullPluginSession::CSPContext * &cspCtx, const Context &context); private: // BSafe's memory allocators static CssmAllocator *normAllocator; static CssmAllocator *privAllocator; friend POINTER T_malloc(unsigned int); friend void T_free(POINTER); friend POINTER T_realloc(POINTER, unsigned int); static const B_ALGORITHM_METHOD * const bsChooser[]; private: // BSafe-specific BinaryKey class. class BSafeBinaryKey : public BinaryKey { public: BSafeBinaryKey( bool isPub, uint32 alg); // CSSM_ALGID_{RSA,DSA} ~BSafeBinaryKey(); void generateKeyBlob( CssmAllocator &allocator, CssmData &blob, CSSM_KEYBLOB_FORMAT &format, AppleCSPSession &session, const CssmKey *paramKey, /* optional, unused here */ CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ bool isPublic() { return mIsPublic; } uint32 alg() { return mAlg; } B_KEY_OBJ bsKey() { return mBsKey; } private: bool mIsPublic; uint32 mAlg; // CSSM_ALGID_{RSA,DSA} B_KEY_OBJ mBsKey; }; private: // // The BSafeContext class is the parent of all BSafe-used CSPContext objects. // It implements the CSPContext operation functions (init, update, ...) in terms // of pointer-to-member fields set by its subclasses. This may not be pretty, but // it avoids every subclass having to re-implement all CSPContext operations. // Beyond that, we implement a raftload of utility methods for our children. // class BSafeContext : public AppleCSPContext { friend class BSafe; public: BSafeContext(AppleCSPSession &session); virtual ~BSafeContext(); // called by CSPFullPluginSession void init(const Context &context, bool encoding = true); void update(const CssmData &data); void update(void *inp, size_t &inSize, void *outp, size_t &outSize); void final(CssmData &out); void final(const CssmData &in); size_t outputSize(bool final, size_t inSize); protected: // install a BSafe algorithm into bsAlgorithm void setAlgorithm(B_INFO_TYPE bAlgType, const void *info = NULL); // safely create bsKey void createBsKey(); // set bsKey. The different versions are equivalent void setKeyAtom(B_INFO_TYPE bKeyInfo, const void *info); void setKeyFromItem(B_INFO_TYPE bKeyInfo, const BSafeItem &item) { setKeyAtom(bKeyInfo, &item); } void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo, const CssmKey &key) { BSafeItem item(key.KeyData); setKeyAtom(bKeyInfo, &item); } void setKeyFromCssmData(B_INFO_TYPE bKeyInfo, const CssmData &keyData) { BSafeItem item(keyData); setKeyAtom(bKeyInfo, &item); } void setKeyFromContext(const Context &context, bool required = true); void setRefKey(CssmKey &key); void setRsaOutSize(bool isPubKey); // create mRandom to be a suitable random-generator BSafe object (if it isn't yet) void setRandom(); // trackUpdate is called during crypto-output. Hook it to keep track of data flow virtual void trackUpdate(size_t in, size_t out); // destroy bsAlgorithm and bsKey so we can start over making them void reset(); // clear key state void destroyBsKey(); // determine if we can reuse the current bsAlgorithm bool reusing(bool encode = true) { if (initialized && !opStarted && (encode == encoding)) return true; encoding = encode; return false; } public: // // These pointers-to-member are called by the BSafeContext operations // (update, final). They must be set by a subclasses's init() method. // Not all members are used by all types of operations - check the // source when in doubt. // int (*inUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); int (*inOutUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); int (*inFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); int (*inFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); int (*outFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); int (*outFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, A_SURRENDER_CTX *); protected: // un-consted bsChooser for BSafe's consumption. BSafe's Bad static B_ALGORITHM_METHOD **chooser() { return const_cast(bsChooser); } // a placeholder for a surrender context. Not currently used // @@@ should perhaps test for pthread cancel? --> thread abstraction static A_SURRENDER_CTX * const bsSurrender; protected: B_ALGORITHM_OBJ bsAlgorithm; // BSafe algorithm object or NULL B_ALGORITHM_OBJ bsRandom; // PRNG algorithm bool encoding; // encoding direction bool initialized; // method init() has completed bool opStarted; // method update() has been called // generally means that we can't reuse // the current bsAlgorithm // // We have a binKey only if the caller passed in a reference // key. In that case we avoid deleting bsKey - which is a copy // of binKey.bsKey - because a BinaryKey is persistent // relative to this context. // BSafeBinaryKey *bsBinKey; B_KEY_OBJ bsKey; // BSafe key object or NULL size_t mOutSize; // simple output size, if applicable }; /* BSafeContext */ // contexts for BSafe digest operations class DigestContext : public BSafeContext { public: // do all work in constructor. We have no directions; thus default init() works fine DigestContext( AppleCSPSession &session, const Context &, B_INFO_TYPE bAlgInfo, size_t sz); }; // common context features for BSafe cipher operations (both symmetric and asymmetric) class CipherContext : public BSafeContext { public: CipherContext( AppleCSPSession &session) : BSafeContext(session), pending(0) {} protected: size_t pending; // bytes not eaten still pending (staged only) public: void cipherInit(); // common init code (must be called from init()) }; // contexts for block cipher operations using symmetric algorithms class BlockCipherContext : public CipherContext { size_t blockSize; uint32 cssmAlg; uint32 cssmMode; bool padEnable; public: BlockCipherContext( AppleCSPSession &session, const Context &, size_t sz) : CipherContext(session), blockSize(sz) { } void init(const Context &context, bool encrypting); size_t inputSize(size_t outSize); size_t outputSize(bool final, size_t inSize); void minimumProgress(size_t &in, size_t &out); void trackUpdate(size_t in, size_t out); private: // special case for RC4 void RC4init(const Context &context); }; // context for generating public/private key pairs class BSafeKeyPairGenContext : public BSafeContext, private AppleKeyPairGenContext { public: BSafeKeyPairGenContext( AppleCSPSession &session, const Context &) : BSafeContext(session) {} // generate alg params, not handled by PublicKeyGenerateContext // For DSA only. void generate( const Context &context, uint32 bitSize, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs); // this one is specified in CSPFullPluginSession void generate( const Context &context, CssmKey &pubKey, CssmKey &privKey); // this one in AppleKeyPairGenContext void generate( const Context &context, BinaryKey &pubBinKey, BinaryKey &privBinKey, uint32 &keySize); private: void setupAlgorithm( const Context &context, uint32 &keySize); }; /* BSafeKeyPairGenContext */ // public key cipher operations class PublicKeyCipherContext : public CipherContext { public: PublicKeyCipherContext( AppleCSPSession &session, const Context &) : CipherContext(session) { } void init(const Context &context, bool encrypting); size_t inputSize(size_t outSize); // unlimited }; // contexts for BSafe signing/verifying operations class SigningContext : public BSafeContext { B_INFO_TYPE algorithm; public: SigningContext( AppleCSPSession &session, const Context &, B_INFO_TYPE bAlg, size_t sz) : BSafeContext(session), algorithm(bAlg) { mOutSize = sz; } void init(const Context &context, bool signing); }; // contexts for BSafe MAC generation and verification class MacContext : public BSafeContext { B_INFO_TYPE algorithm; public: MacContext( AppleCSPSession &session, const Context &, B_INFO_TYPE bAlg, size_t sz) : BSafeContext(session), algorithm(bAlg) { mOutSize = sz; } void init(const Context &context, bool signing); void final(const CssmData &in); }; // contexts for BSafe's random number generation class RandomContext : public BSafeContext { B_INFO_TYPE algorithm; public: RandomContext( AppleCSPSession &session, const Context &, B_INFO_TYPE alg) : BSafeContext(session), algorithm(alg) { } void init(const Context &context, bool); void final(CssmData &data); }; // symmetric key generation context class SymmetricKeyGenContext : public BSafeContext, private AppleSymmKeyGenContext { public: SymmetricKeyGenContext( AppleCSPSession &session, const Context &ctx, uint32 minSizeInBits, uint32 maxSizeInBits, bool mustBeByteSized) : BSafeContext(session), AppleSymmKeyGenContext( minSizeInBits, maxSizeInBits, mustBeByteSized) { } void generate( const Context &context, CssmKey &symKey, CssmKey &dummyKey); }; public: /* * Stateless, private function to map a CSSM alg and pub/priv state * to B_INFO_TYPE and format. Returns true on success, false on * "I don't understand this algorithm". */ static bool bsafeAlgToInfoType( CSSM_ALGORITHMS alg, bool isPublic, B_INFO_TYPE &infoType, // RETURNED CSSM_KEYBLOB_FORMAT &format); // RETURNED /* check result of a BSafe call and throw on error */ static void check(int status, bool isKeyOp = false); /* moved here from BSafeContext - now works on any key */ template static KI_Type *getKey(B_KEY_OBJ bKey, B_INFO_TYPE type) { POINTER p; check(B_GetKeyInfo(&p, bKey, type), true); return reinterpret_cast(p); } // // The context generation table - see algmaker.cpp. // public: // Base class for Maker classes class MakerBase { public: virtual ~MakerBase() { } virtual BSafeContext *make( AppleCSPSession &session, const Context &context) const = 0; }; // One entry in Maker table struct MakerTable { CSSM_ALGORITHMS algorithmId; CSSM_CONTEXT_TYPE algClass; const MakerBase *maker; ~MakerTable() { delete maker; } }; private: static bug_const MakerTable algorithms[]; static const unsigned int algorithmCount; /* * CSPKeyInfoProvider for BSafe keys */ class BSafeKeyInfoProvider : public CSPKeyInfoProvider { private: BSafeKeyInfoProvider( const CssmKey &cssmKey, AppleCSPSession &session); public: static CSPKeyInfoProvider *provider( const CssmKey &cssmKey, AppleCSPSession &session); ~BSafeKeyInfoProvider() { } void CssmKeyToBinary( CssmKey *paramKey, // optional CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT BinaryKey **binKey); // RETURNED void QueryKeySizeInBits( CSSM_KEY_SIZE &keySize); // RETURNED }; }; /* BSAFE namespace */ /* * BSAFE Key Info types. */ #define BLOB_IS_PUB_KEY_INFO 0 #if BLOB_IS_PUB_KEY_INFO /* X beta values */ #define RSA_PUB_KEYINFO_TYPE KI_RSAPublicBER #define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER #define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER #define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER #else /* BLOB_IS_PUB_KEY_INFO */ #define RSA_PUB_KEYINFO_TYPE KI_RSAPublic #define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER #define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER #define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER #endif #endif //_H_BSAFECSP #endif /* BSAFE_CSP_ENABLE */