X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_cdsa_plugin/lib/CSPsession.h diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.h b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.h new file mode 100644 index 00000000..b755bf77 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.h @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2000-2001,2011-2012,2014 Apple 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. + */ + + +// +// CSPsession.h - Framework for CSP plugin modules +// +#ifndef _H_CSPSESSION +#define _H_CSPSESSION + +#include +#include + + +namespace Security { + +// +// The CSPPluginSession provides a general bed for CSP plugin session objects. +// Derive from this if you want to write your CSP, effectively, from scratch. +// We still provide a framework for managing local cryptographic contexts and +// (module) logins. +// +class CSPPluginSession : public PluginSession, public CSPAbstractPluginSession { +public: + CSPPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { } + + // methods implemented here that you should not override in a subclass + void EventNotify(CSSM_CONTEXT_EVENT e, + CSSM_CC_HANDLE ccHandle, const Context &context); + CSSM_MODULE_FUNCS_PTR construct(); + +public: + class PluginContext { + public: + virtual bool changed(const Context &context); + virtual ~PluginContext(); + }; + +public: + bool loggedIn() const { return mLoggedIn; } + bool loggedIn(bool li) { bool old = mLoggedIn; mLoggedIn = li; return old; } + + template Ctx *getContext(CSSM_CC_HANDLE handle) + { StLock _(contextMapLock); return safe_cast(contextMap[handle]); } + + void setContext(CSSM_CC_HANDLE handle, PluginContext *ctx) + { StLock _(contextMapLock); contextMap[handle] = ctx; } + +public: + // context management methods - override as needed + virtual PluginContext *contextCreate(CSSM_CC_HANDLE handle, const Context &context); + virtual void contextUpdate(CSSM_CC_HANDLE handle, + const Context &context, PluginContext * &ctx); + virtual void contextDelete(CSSM_CC_HANDLE handle, const Context &context, PluginContext *ctx); + +private: + bool mLoggedIn; + + map contextMap; + Mutex contextMapLock; +}; + + +// +// On the other hand, for most CSP modules, this subclass of CSPPluginSession provides +// much more convenient embedding facilities. The theory of operation is too complicated +// to explain here; refer to the accompanying documentation. +// +class CSPFullPluginSession : public CSPPluginSession { +public: + class CSPContext; + class AlgorithmFactory; + + CSPFullPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : CSPPluginSession(theHandle, plug, version, + subserviceId, subserviceType, attachFlags, upcalls) { } + + // final context preparation (called by secondary transition layer) + CSPContext *init(CSSM_CC_HANDLE ccHandle, CSSM_CONTEXT_TYPE type, + const Context &context, bool encoding = true); + + // verify proper state on continuation (update/final) calls + CSPContext *getStagedContext(CSSM_CC_HANDLE ccHandle, + CSSM_CONTEXT_TYPE type, bool encoding = true); + + static const uint32 CSSM_ALGCLASS_CRYPT = 1001; // internally added to CONTEXT_TYPE + +protected: + // validate operation type against context class + void checkOperation(CSSM_CONTEXT_TYPE ctxType, CSSM_CONTEXT_TYPE opType); + +protected: + // + // The Writer class encapsulates staged-output destinations with optional overflow + // + class Writer { + public: + Writer(CssmData *v, uint32 n, CssmData *rem = NULL); + + // can this buffer be extended? + bool isExtensible() const + { return !*vec || (remData && !*remData); } + + // increase size if necessary (and possible) + void allocate(size_t needed, Allocator &alloc); + + // straight-forward buffer writing + void put(void *addr, size_t size); + + // locate-mode output (deliver buffer mode) + void nextBlock(void * &p, size_t &sz); + void use(size_t sz); + + // wrap up and return total number of bytes written + size_t close(); + + private: + CssmData *vec; // current buffer descriptor (the one in use) + CssmData *firstVec; // first buffer descriptor + CssmData *lastVec; // last buffer descriptor (NOT one past it) + CssmData *remData; // overflow buffer, if any + + void *currentBuffer; // next free byte in vec + size_t currentSize; // free bytes in vec + + size_t written; // bytes written + + void useData(CssmData *data) + { currentBuffer = data->data(); currentSize = data->length(); } + }; + +public: + // internal utilities (used by our own subclasses) + static CssmData makeBuffer(size_t size, Allocator &alloc); + static size_t totalBufferSize(const CssmData *data, uint32 count); + void setKey(CssmKey &key, + const Context &context, CSSM_KEYCLASS keyClass, + CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use); + +public: + // + // All contexts from CSPFullPluginSession's subclasses must derive from CSPContext. + // CSPFullPluginSession reformulates CSSM operations in terms of virtual methods of + // the context class. + // + class CSPContext : public PluginContext { + friend class CSPFullPluginSession; + public: + CSSM_CONTEXT_TYPE type() const { return mType; } + bool encoding() const { return mDirection; } + + // init() is called for all algorithms + virtual void init(const Context &context, bool encoding = true); + + // the following methods will be called for some but not all algorithms + virtual void update(const CssmData &data); // all block-input algorithms + virtual void update(void *inp, size_t &inSize, void *outp, size_t &outSize); // cryption algs + virtual void final(CssmData &out); // output-data producing algorithms + virtual void final(const CssmData &in); // verifying algorithms + virtual void generate(const Context &context, CssmKey &pubKey, CssmKey &privKey); + virtual void generate(const Context &context, uint32, + CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs); + virtual CSPContext *clone(Allocator &); // clone internal state + virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg); + + virtual size_t inputSize(size_t outSize); // input for given output size + virtual size_t outputSize(bool final = false, size_t inSize = 0); // output for given input size + virtual void minimumProgress(size_t &in, size_t &out); // minimum progress chunks + + protected: + // convenience forms of the above + void update(const CssmData *in, uint32 inCount, Writer &writer); + void final(CssmData &out, Allocator &alloc); + void final(Writer &writer, Allocator &alloc); + + void update(const CssmData *in, uint32 inCount) + { for (uint32 n = 0; n < inCount; n++) update(in[n]); } + + void checkOperation(CSSM_CONTEXT_TYPE type); + void checkOperation(CSSM_CONTEXT_TYPE type, bool encode); + + CSSM_CONTEXT_TYPE mType; // CSSM context type + bool mDirection; // operation direction (true if irrelevant) + }; + +protected: + virtual void setupContext(CSPContext * &ctx, const Context &context, bool encoding) = 0; + + virtual void getKeySize(const CssmKey &key, CSSM_KEY_SIZE &size); + +public: + // an algorithm factory. This is an optional feature + class AlgorithmFactory { + public: + virtual ~AlgorithmFactory(); + + // set ctx and return true if you can handle this + virtual bool setup(CSPContext * &ctx, const Context &context) = 0; + }; + +public: + void EncryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege); + void EncryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege); + void EncryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted); + void EncryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData); + + void DecryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege); + void DecryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege); + void DecryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted); + void DecryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData); + + void QuerySize(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + QuerySizeData *DataBlock); + + void WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + void UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege); + void DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey); + + void GenerateMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Mac); + void GenerateMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void GenerateMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void GenerateMacFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Mac); + + void VerifyMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + const CssmData &Mac); + virtual void VerifyMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + virtual void VerifyMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + virtual void VerifyMacFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Mac); + + void SignData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CssmData &Signature); + void SignDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void SignDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void SignDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Signature); + + void VerifyData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CssmData &Signature); + virtual void VerifyDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + virtual void VerifyDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + virtual void VerifyDataFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Signature); + + void DigestData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Digest); + void DigestDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void DigestDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void DigestDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Digest); + void DigestDataClone(CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE ClonedCCHandle); + + void GenerateKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &Key, + CSSM_PRIVILEGE Privilege); + void GenerateKeyPair(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CssmData *PublicKeyLabel, + CssmKey &PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CssmData *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &PrivateKey, + CSSM_PRIVILEGE Privilege); + + void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey); + void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, + const Context *Context, + const CssmKey *Key, + CSSM_KEY_SIZE &KeySize); + + void FreeKey(const AccessCredentials *AccessCred, + CssmKey &KeyPtr, + CSSM_BOOL Delete); + + void GenerateRandom(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &RandomNumber); + void GenerateAlgorithmParams(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 ParamBits, + CssmData &Param, + uint32 &NumberOfUpdatedAttibutes, + CSSM_CONTEXT_ATTRIBUTE_PTR &UpdatedAttributes); + + void Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved); + void Logout(); + void VerifyDevice(const CssmData &DeviceCert); + void GetOperationalStatistics(CSPOperationalStatistics &Statistics); + + void RetrieveCounter(CssmData &Counter); + void RetrieveUniqueId(CssmData &UniqueID); + void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData); + + void GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key); + + void GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit); + + void PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData); +}; + + +// +// Classes for dealing with reference keys. +// + +// Forward declaration. +class KeyPool; + +// +// A ReferencedKey -- The private (to the CSP) part of a Reference Key. +// +class ReferencedKey +{ + friend class KeyPool; // So it can call deactivate() +public: + // What we use to reference a ReferencedKey. + typedef CSSM_INTPTR KeyReference; + ReferencedKey(KeyPool &session); // Calls KeyPool::add() + virtual ~ReferencedKey(); // Calls KeyPool::erase() + + KeyReference keyReference(); + bool isActive() { return mKeyPool != NULL; } + + template + SubPool &keyPool() { assert(mKeyPool); return safer_cast(*mKeyPool); } +public: + // Making, retrieving and freeing CSSM_KEYBLOB_REF_FORMAT_INTEGER CSSM_KEY type reference keys + // NOTE: that none of these functions affect mKeyMap. + static void makeReferenceKey(Allocator &allocator, KeyReference keyReference, CSSM_KEY &ioKey); + static KeyReference keyReference(const CSSM_KEY &key); + static KeyReference freeReferenceKey(Allocator &allocator, CSSM_KEY &ioKey); + +private: + void deactivate() { mKeyPool = NULL; } + + // Will be NULL iff this key is not active + KeyPool *mKeyPool; +}; + + +// +// KeyPool -- a mixin class to manage a pool of ReferencedKeys +// +class KeyPool +{ +public: + friend class ReferencedKey; // So it can call add() and erase() +public: + KeyPool(); + virtual ~KeyPool(); + + // Type safe ReferencedKey subclass lookup + template + Subclass &find(const CSSM_KEY &key) const; + + // Free the ioKey, erase keyReference from mKeyMap, and delete the ReferencedKey + void freeKey(Allocator &allocator, CSSM_KEY &key); + +protected: + // Called by the constructor of ReferencedKey -- add referencedKey to mKeyMap + void add(ReferencedKey &referencedKey); + + ReferencedKey &findKey(const CSSM_KEY &key) const; + ReferencedKey &findKeyReference(ReferencedKey::KeyReference keyReference) const; + + // Called by the destructor of ReferencedKey -- erase keyReference from mKeyMap + void erase(ReferencedKey &referencedKey); + + // Erase keyReference from mKeyMap, and return it (for deletion) + ReferencedKey &erase(ReferencedKey::KeyReference keyReference); + +protected: + typedef map KeyMap; + KeyMap mKeyMap; + mutable Mutex mKeyMapLock; +}; + +// Implementation of type safe ReferencedKey subclass lookup. +template +Subclass & +KeyPool::find(const CSSM_KEY &key) const +{ + Subclass *sub; + if (!(sub = dynamic_cast(&findKey(key)))) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + return *sub; +} + +} // end namespace Security + +#endif //_H_CSPSESSION