1/*
2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// CSPsession.h - Framework for CSP plugin modules
21//
22#ifndef _H_CSPSESSION
23#define _H_CSPSESSION
24
25#include <security_cdsa_plugin/CSPabstractsession.h>
26#include <map>
27
28
29namespace Security {
30
31//
32// The CSPPluginSession provides a general bed for CSP plugin session objects.
33// Derive from this if you want to write your CSP, effectively, from scratch.
34// We still provide a framework for managing local cryptographic contexts and
35// (module) logins.
36//
37class CSPPluginSession : public PluginSession, public CSPAbstractPluginSession {
38public:
39    CSPPluginSession(CSSM_MODULE_HANDLE theHandle,
40                    CssmPlugin &plug,
41                    const CSSM_VERSION &version,
42                    uint32 subserviceId,
43                    CSSM_SERVICE_TYPE subserviceType,
44                    CSSM_ATTACH_FLAGS attachFlags,
45                    const CSSM_UPCALLS &upcalls)
46      : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { }
47
48    // methods implemented here that you should not override in a subclass
49    void EventNotify(CSSM_CONTEXT_EVENT e,
50                     CSSM_CC_HANDLE ccHandle, const Context &context);
51    CSSM_MODULE_FUNCS_PTR construct();
52
53public:
54    class PluginContext {
55    public:
56        virtual bool changed(const Context &context);
57        virtual ~PluginContext();
58    };
59
60public:
61    bool loggedIn() const { return mLoggedIn; }
62    bool loggedIn(bool li) { bool old = mLoggedIn; mLoggedIn = li; return old; }
63
64    template <class Ctx> Ctx *getContext(CSSM_CC_HANDLE handle)
65    { StLock<Mutex> _(contextMapLock); return safe_cast<Ctx *>(contextMap[handle]); }
66
67    void setContext(CSSM_CC_HANDLE handle, PluginContext *ctx)
68    { StLock<Mutex> _(contextMapLock); contextMap[handle] = ctx; }
69
70public:
71    // context management methods - override as needed
72    virtual PluginContext *contextCreate(CSSM_CC_HANDLE handle, const Context &context);
73    virtual void contextUpdate(CSSM_CC_HANDLE handle,
74                               const Context &context, PluginContext * &ctx);
75    virtual void contextDelete(CSSM_CC_HANDLE handle, const Context &context, PluginContext *ctx);
76
77private:
78    bool mLoggedIn;
79
80    map<CSSM_CC_HANDLE, PluginContext *> contextMap;
81	Mutex contextMapLock;
82};
83
84
85//
86// On the other hand, for most CSP modules, this subclass of CSPPluginSession provides
87// much more convenient embedding facilities. The theory of operation is too complicated
88// to explain here; refer to the accompanying documentation.
89//
90class CSPFullPluginSession : public CSPPluginSession {
91public:
92    class CSPContext;
93    class AlgorithmFactory;
94
95    CSPFullPluginSession(CSSM_MODULE_HANDLE theHandle,
96                    CssmPlugin &plug,
97                    const CSSM_VERSION &version,
98                    uint32 subserviceId,
99                    CSSM_SERVICE_TYPE subserviceType,
100                    CSSM_ATTACH_FLAGS attachFlags,
101                    const CSSM_UPCALLS &upcalls)
102    : CSPPluginSession(theHandle, plug, version,
103                             subserviceId, subserviceType, attachFlags, upcalls) { }
104
105    // final context preparation (called by secondary transition layer)
106    CSPContext *init(CSSM_CC_HANDLE ccHandle, CSSM_CONTEXT_TYPE type,
107                     const Context &context, bool encoding = true);
108
109    // verify proper state on continuation (update/final) calls
110    CSPContext *getStagedContext(CSSM_CC_HANDLE ccHandle,
111                                 CSSM_CONTEXT_TYPE type, bool encoding = true);
112
113    static const uint32 CSSM_ALGCLASS_CRYPT = 1001;	// internally added to CONTEXT_TYPE
114
115protected:
116	// validate operation type against context class
117    void checkOperation(CSSM_CONTEXT_TYPE ctxType, CSSM_CONTEXT_TYPE opType);
118
119protected:
120	//
121	// The Writer class encapsulates staged-output destinations with optional overflow
122	//
123	class Writer {
124	public:
125		Writer(CssmData *v, uint32 n, CssmData *rem = NULL);
126
127		// can this buffer be extended?
128		bool isExtensible() const
129		{ return !*vec || (remData && !*remData); }
130
131		// increase size if necessary (and possible)
132		void allocate(size_t needed, Allocator &alloc);
133
134		// straight-forward buffer writing
135		void put(void *addr, size_t size);
136
137		// locate-mode output (deliver buffer mode)
138		void nextBlock(void * &p, size_t &sz);
139		void use(size_t sz);
140
141		// wrap up and return total number of bytes written
142		size_t close();
143
144	private:
145		CssmData *vec;						// current buffer descriptor (the one in use)
146        CssmData *firstVec;					// first buffer descriptor
147		CssmData *lastVec;					// last buffer descriptor (NOT one past it)
148		CssmData *remData;					// overflow buffer, if any
149
150		void *currentBuffer;				// next free byte in vec
151		size_t currentSize;					// free bytes in vec
152
153		size_t written;						// bytes written
154
155		void useData(CssmData *data)
156		{ currentBuffer = data->data(); currentSize = data->length(); }
157	};
158
159public:
160	// internal utilities (used by our own subclasses)
161	static CssmData makeBuffer(size_t size, Allocator &alloc);
162	static size_t totalBufferSize(const CssmData *data, uint32 count);
163    void setKey(CssmKey &key,
164                const Context &context, CSSM_KEYCLASS keyClass,
165                CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use);
166
167public:
168	//
169	// All contexts from CSPFullPluginSession's subclasses must derive from CSPContext.
170	// CSPFullPluginSession reformulates CSSM operations in terms of virtual methods of
171	// the context class.
172	//
173    class CSPContext : public PluginContext {
174        friend class CSPFullPluginSession;
175    public:
176        CSSM_CONTEXT_TYPE type() const { return mType; }
177        bool encoding() const { return mDirection; }
178
179        // init() is called for all algorithms
180        virtual void init(const Context &context, bool encoding = true);
181
182        // the following methods will be called for some but not all algorithms
183        virtual void update(const CssmData &data);	// all block-input algorithms
184        virtual void update(void *inp, size_t &inSize, void *outp, size_t &outSize); // cryption algs
185        virtual void final(CssmData &out);		// output-data producing algorithms
186        virtual void final(const CssmData &in);	// verifying algorithms
187        virtual void generate(const Context &context, CssmKey &pubKey, CssmKey &privKey);
188        virtual void generate(const Context &context, uint32,
189                              CssmData &params, uint32 &attrCount, Context::Attr * &attrs);
190		virtual CSPContext *clone(Allocator &);	// clone internal state
191		virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg);
192
193        virtual size_t inputSize(size_t outSize);	// input for given output size
194        virtual size_t outputSize(bool final = false, size_t inSize = 0); // output for given input size
195        virtual void minimumProgress(size_t &in, size_t &out); // minimum progress chunks
196
197    protected:
198        // convenience forms of the above
199        void update(const CssmData *in, uint32 inCount, Writer &writer);
200        void final(CssmData &out, Allocator &alloc);
201        void final(Writer &writer, Allocator &alloc);
202
203        void update(const CssmData *in, uint32 inCount)
204        { for (uint32 n = 0; n < inCount; n++) update(in[n]); }
205
206        void checkOperation(CSSM_CONTEXT_TYPE type);
207        void checkOperation(CSSM_CONTEXT_TYPE type, bool encode);
208
209        CSSM_CONTEXT_TYPE mType;		// CSSM context type
210        bool mDirection;			// operation direction (true if irrelevant)
211    };
212
213protected:
214    virtual void setupContext(CSPContext * &ctx, const Context &context, bool encoding) = 0;
215
216	virtual void getKeySize(const CssmKey &key, CSSM_KEY_SIZE &size);
217
218public:
219    // an algorithm factory. This is an optional feature
220    class AlgorithmFactory {
221    public:
222		virtual ~AlgorithmFactory();
223
224        // set ctx and return true if you can handle this
225        virtual bool setup(CSPContext * &ctx, const Context &context) = 0;
226    };
227
228public:
229    void EncryptData(CSSM_CC_HANDLE CCHandle,
230                     const Context &Context,
231                     const CssmData ClearBufs[],
232                     uint32 ClearBufCount,
233                     CssmData CipherBufs[],
234                     uint32 CipherBufCount,
235                     CSSM_SIZE &bytesEncrypted,
236                     CssmData &RemData,
237                     CSSM_PRIVILEGE Privilege);
238    void EncryptDataInit(CSSM_CC_HANDLE CCHandle,
239                         const Context &Context,
240                         CSSM_PRIVILEGE Privilege);
241    void EncryptDataUpdate(CSSM_CC_HANDLE CCHandle,
242                           const CssmData ClearBufs[],
243                           uint32 ClearBufCount,
244                           CssmData CipherBufs[],
245                           uint32 CipherBufCount,
246                           CSSM_SIZE &bytesEncrypted);
247    void EncryptDataFinal(CSSM_CC_HANDLE CCHandle,
248                          CssmData &RemData);
249
250    void DecryptData(CSSM_CC_HANDLE CCHandle,
251                     const Context &Context,
252                     const CssmData CipherBufs[],
253                     uint32 CipherBufCount,
254                     CssmData ClearBufs[],
255                     uint32 ClearBufCount,
256                     CSSM_SIZE &bytesDecrypted,
257                     CssmData &RemData,
258                     CSSM_PRIVILEGE Privilege);
259    void DecryptDataInit(CSSM_CC_HANDLE CCHandle,
260                         const Context &Context,
261                         CSSM_PRIVILEGE Privilege);
262    void DecryptDataUpdate(CSSM_CC_HANDLE CCHandle,
263                           const CssmData CipherBufs[],
264                           uint32 CipherBufCount,
265                           CssmData ClearBufs[],
266                           uint32 ClearBufCount,
267                           CSSM_SIZE &bytesDecrypted);
268    void DecryptDataFinal(CSSM_CC_HANDLE CCHandle,
269                          CssmData &RemData);
270
271	void QuerySize(CSSM_CC_HANDLE CCHandle,
272				  const Context &Context,
273				  CSSM_BOOL Encrypt,
274				  uint32 QuerySizeCount,
275				  QuerySizeData *DataBlock);
276
277	void WrapKey(CSSM_CC_HANDLE CCHandle,
278				const Context &Context,
279				const AccessCredentials &AccessCred,
280				const CssmKey &Key,
281				const CssmData *DescriptiveData,
282				CssmKey &WrappedKey,
283				CSSM_PRIVILEGE Privilege);
284	void UnwrapKey(CSSM_CC_HANDLE CCHandle,
285				const Context &Context,
286				const CssmKey *PublicKey,
287				const CssmKey &WrappedKey,
288				uint32 KeyUsage,
289				uint32 KeyAttr,
290				const CssmData *KeyLabel,
291				const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
292				CssmKey &UnwrappedKey,
293				CssmData &DescriptiveData,
294				CSSM_PRIVILEGE Privilege);
295	void DeriveKey(CSSM_CC_HANDLE CCHandle,
296				const Context &Context,
297				CssmData &Param,
298				uint32 KeyUsage,
299				uint32 KeyAttr,
300				const CssmData *KeyLabel,
301				const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
302				CssmKey &DerivedKey);
303
304    void GenerateMac(CSSM_CC_HANDLE CCHandle,
305                     const Context &Context,
306                     const CssmData DataBufs[],
307                     uint32 DataBufCount,
308                     CssmData &Mac);
309    void GenerateMacInit(CSSM_CC_HANDLE CCHandle,
310                                 const Context &Context);
311    void GenerateMacUpdate(CSSM_CC_HANDLE CCHandle,
312                                   const CssmData DataBufs[],
313                                   uint32 DataBufCount);
314    void GenerateMacFinal(CSSM_CC_HANDLE CCHandle,
315                                  CssmData &Mac);
316
317    void VerifyMac(CSSM_CC_HANDLE CCHandle,
318                   const Context &Context,
319                   const CssmData DataBufs[],
320                   uint32 DataBufCount,
321                   const CssmData &Mac);
322    virtual void VerifyMacInit(CSSM_CC_HANDLE CCHandle,
323                               const Context &Context);
324    virtual void VerifyMacUpdate(CSSM_CC_HANDLE CCHandle,
325                                 const CssmData DataBufs[],
326                                 uint32 DataBufCount);
327    virtual void VerifyMacFinal(CSSM_CC_HANDLE CCHandle,
328                                const CssmData &Mac);
329
330    void SignData(CSSM_CC_HANDLE CCHandle,
331                  const Context &Context,
332                  const CssmData DataBufs[],
333                  uint32 DataBufCount,
334                  CSSM_ALGORITHMS DigestAlgorithm,
335                  CssmData &Signature);
336    void SignDataInit(CSSM_CC_HANDLE CCHandle,
337                              const Context &Context);
338    void SignDataUpdate(CSSM_CC_HANDLE CCHandle,
339                                const CssmData DataBufs[],
340                                uint32 DataBufCount);
341    void SignDataFinal(CSSM_CC_HANDLE CCHandle,
342                               CssmData &Signature);
343
344    void VerifyData(CSSM_CC_HANDLE CCHandle,
345                    const Context &Context,
346                    const CssmData DataBufs[],
347                    uint32 DataBufCount,
348                    CSSM_ALGORITHMS DigestAlgorithm,
349                    const CssmData &Signature);
350    virtual void VerifyDataInit(CSSM_CC_HANDLE CCHandle,
351                                const Context &Context);
352    virtual void VerifyDataUpdate(CSSM_CC_HANDLE CCHandle,
353                                  const CssmData DataBufs[],
354                                  uint32 DataBufCount);
355    virtual void VerifyDataFinal(CSSM_CC_HANDLE CCHandle,
356                                 const CssmData &Signature);
357
358    void DigestData(CSSM_CC_HANDLE CCHandle,
359                    const Context &Context,
360                    const CssmData DataBufs[],
361                    uint32 DataBufCount,
362                    CssmData &Digest);
363    void DigestDataInit(CSSM_CC_HANDLE CCHandle,
364                                const Context &Context);
365    void DigestDataUpdate(CSSM_CC_HANDLE CCHandle,
366                                  const CssmData DataBufs[],
367                                  uint32 DataBufCount);
368    void DigestDataFinal(CSSM_CC_HANDLE CCHandle,
369                                 CssmData &Digest);
370    void DigestDataClone(CSSM_CC_HANDLE CCHandle,
371						CSSM_CC_HANDLE ClonedCCHandle);
372
373    void GenerateKey(CSSM_CC_HANDLE CCHandle,
374                             const Context &Context,
375                             uint32 KeyUsage,
376                             uint32 KeyAttr,
377                             const CssmData *KeyLabel,
378                             const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
379                             CssmKey &Key,
380                             CSSM_PRIVILEGE Privilege);
381    void GenerateKeyPair(CSSM_CC_HANDLE CCHandle,
382                                 const Context &Context,
383                                 uint32 PublicKeyUsage,
384                                 uint32 PublicKeyAttr,
385                                 const CssmData *PublicKeyLabel,
386                                 CssmKey &PublicKey,
387                                 uint32 PrivateKeyUsage,
388                                 uint32 PrivateKeyAttr,
389                                 const CssmData *PrivateKeyLabel,
390                                 const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
391                                 CssmKey &PrivateKey,
392                                 CSSM_PRIVILEGE Privilege);
393
394	void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey,
395									   CssmKey &PrivateKey);
396	void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle,
397							const Context *Context,
398							const CssmKey *Key,
399							CSSM_KEY_SIZE &KeySize);
400
401	void FreeKey(const AccessCredentials *AccessCred,
402				 CssmKey &KeyPtr,
403				 CSSM_BOOL Delete);
404
405    void GenerateRandom(CSSM_CC_HANDLE CCHandle,
406                                const Context &Context,
407                                CssmData &RandomNumber);
408    void GenerateAlgorithmParams(CSSM_CC_HANDLE CCHandle,
409                                         const Context &Context,
410                                         uint32 ParamBits,
411                                         CssmData &Param,
412                                         uint32 &NumberOfUpdatedAttibutes,
413                                         CSSM_CONTEXT_ATTRIBUTE_PTR &UpdatedAttributes);
414
415	void Login(const AccessCredentials &AccessCred,
416			   const CssmData *LoginName,
417			   const void *Reserved);
418	void Logout();
419	void VerifyDevice(const CssmData &DeviceCert);
420	void GetOperationalStatistics(CSPOperationalStatistics &Statistics);
421
422	void RetrieveCounter(CssmData &Counter);
423	void RetrieveUniqueId(CssmData &UniqueID);
424	void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData);
425
426	void GetKeyOwner(const CssmKey &Key,
427			CSSM_ACL_OWNER_PROTOTYPE &Owner);
428	void ChangeKeyOwner(const AccessCredentials &AccessCred,
429			const CssmKey &Key,
430			const CSSM_ACL_OWNER_PROTOTYPE &NewOwner);
431	void GetKeyAcl(const CssmKey &Key,
432			const CSSM_STRING *SelectionTag,
433			uint32 &NumberOfAclInfos,
434			CSSM_ACL_ENTRY_INFO_PTR &AclInfos);
435	void ChangeKeyAcl(const AccessCredentials &AccessCred,
436			const CSSM_ACL_EDIT &AclEdit,
437			const CssmKey &Key);
438
439	void GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner);
440	void ChangeLoginOwner(const AccessCredentials &AccessCred,
441			const CSSM_ACL_OWNER_PROTOTYPE &NewOwner);
442	void GetLoginAcl(const CSSM_STRING *SelectionTag,
443			uint32 &NumberOfAclInfos,
444			CSSM_ACL_ENTRY_INFO_PTR &AclInfos);
445	void ChangeLoginAcl(const AccessCredentials &AccessCred,
446			const CSSM_ACL_EDIT &AclEdit);
447
448	void PassThrough(CSSM_CC_HANDLE CCHandle,
449               const Context &Context,
450               uint32 PassThroughId,
451               const void *InData,
452               void **OutData);
453};
454
455
456//
457// Classes for dealing with reference keys.
458//
459
460// Forward declaration.
461class KeyPool;
462
463//
464// A ReferencedKey -- The private (to the CSP) part of a Reference Key.
465//
466class ReferencedKey
467{
468	friend class KeyPool; // So it can call deactivate()
469public:
470	// What we use to reference a ReferencedKey.
471	typedef CSSM_INTPTR KeyReference;
472	ReferencedKey(KeyPool &session); // Calls KeyPool::add()
473	virtual ~ReferencedKey(); // Calls KeyPool::erase()
474
475	KeyReference keyReference();
476	bool isActive() { return mKeyPool != NULL; }
477
478	template <class SubPool>
479	SubPool &keyPool() { assert(mKeyPool); return safer_cast<SubPool &>(*mKeyPool); }
480public:
481	// Making, retrieving and freeing CSSM_KEYBLOB_REF_FORMAT_INTEGER CSSM_KEY type reference keys
482	// NOTE: that none of these functions affect mKeyMap.
483	static void makeReferenceKey(Allocator &allocator, KeyReference keyReference, CSSM_KEY &ioKey);
484	static KeyReference keyReference(const CSSM_KEY &key);
485	static KeyReference freeReferenceKey(Allocator &allocator, CSSM_KEY &ioKey);
486
487private:
488	void deactivate() { mKeyPool = NULL; }
489
490	// Will be NULL iff this key is not active
491	KeyPool *mKeyPool;
492};
493
494
495//
496// KeyPool -- a mixin class to manage a pool of ReferencedKeys
497//
498class KeyPool
499{
500public:
501	friend class ReferencedKey; // So it can call add() and erase()
502public:
503	KeyPool();
504	virtual ~KeyPool();
505
506	// Type safe ReferencedKey subclass lookup
507	template <class Subclass>
508	Subclass &find(const CSSM_KEY &key) const;
509
510	// Free the ioKey, erase keyReference from mKeyMap, and delete the ReferencedKey
511	void freeKey(Allocator &allocator, CSSM_KEY &key);
512
513protected:
514	// Called by the constructor of ReferencedKey -- add referencedKey to mKeyMap
515 	void add(ReferencedKey &referencedKey);
516
517	ReferencedKey &findKey(const CSSM_KEY &key) const;
518	ReferencedKey &findKeyReference(ReferencedKey::KeyReference keyReference) const;
519
520	// Called by the destructor of ReferencedKey -- erase keyReference from mKeyMap
521 	void erase(ReferencedKey &referencedKey);
522
523	// Erase keyReference from mKeyMap, and return it (for deletion)
524 	ReferencedKey &erase(ReferencedKey::KeyReference keyReference);
525
526protected:
527	typedef map<ReferencedKey::KeyReference, ReferencedKey *> KeyMap;
528	KeyMap mKeyMap;
529	mutable Mutex mKeyMapLock;
530};
531
532// Implementation of type safe ReferencedKey subclass lookup.
533template <class Subclass>
534Subclass &
535KeyPool::find(const CSSM_KEY &key) const
536{
537    Subclass *sub;
538    if (!(sub = dynamic_cast<Subclass *>(&findKey(key))))
539        CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
540    return *sub;
541}
542
543} // end namespace Security
544
545#endif //_H_CSPSESSION
546