]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cdsa_plugin/lib/CSPsession.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cdsa_plugin / lib / CSPsession.h
diff --git a/Security/libsecurity_cdsa_plugin/lib/CSPsession.h b/Security/libsecurity_cdsa_plugin/lib/CSPsession.h
new file mode 100644 (file)
index 0000000..b755bf7
--- /dev/null
@@ -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 <security_cdsa_plugin/CSPabstractsession.h>
+#include <map>
+
+
+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 <class Ctx> Ctx *getContext(CSSM_CC_HANDLE handle)
+    { StLock<Mutex> _(contextMapLock); return safe_cast<Ctx *>(contextMap[handle]); }
+
+    void setContext(CSSM_CC_HANDLE handle, PluginContext *ctx)
+    { StLock<Mutex> _(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<CSSM_CC_HANDLE, PluginContext *> 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 &params, 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 <class SubPool>
+       SubPool &keyPool() { assert(mKeyPool); return safer_cast<SubPool &>(*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 <class Subclass>
+       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<ReferencedKey::KeyReference, ReferencedKey *> KeyMap;
+       KeyMap mKeyMap;
+       mutable Mutex mKeyMapLock;
+};
+
+// Implementation of type safe ReferencedKey subclass lookup.
+template <class Subclass>
+Subclass &
+KeyPool::find(const CSSM_KEY &key) const
+{
+    Subclass *sub;
+    if (!(sub = dynamic_cast<Subclass *>(&findKey(key))))
+        CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
+    return *sub;
+}
+
+} // end namespace Security
+
+#endif //_H_CSPSESSION