2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
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
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.
20 // CSPsession.h - Framework for CSP plugin modules
25 #include <security_cdsa_plugin/CSPabstractsession.h>
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
37 class CSPPluginSession
: public PluginSession
, public CSPAbstractPluginSession
{
39 CSPPluginSession(CSSM_MODULE_HANDLE theHandle
,
41 const CSSM_VERSION
&version
,
43 CSSM_SERVICE_TYPE subserviceType
,
44 CSSM_ATTACH_FLAGS attachFlags
,
45 const CSSM_UPCALLS
&upcalls
)
46 : PluginSession(theHandle
, plug
, version
, subserviceId
, subserviceType
, attachFlags
, upcalls
) { }
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();
56 virtual bool changed(const Context
&context
);
57 virtual ~PluginContext();
61 bool loggedIn() const { return mLoggedIn
; }
62 bool loggedIn(bool li
) { bool old
= mLoggedIn
; mLoggedIn
= li
; return old
; }
64 template <class Ctx
> Ctx
*getContext(CSSM_CC_HANDLE handle
)
65 { StLock
<Mutex
> _(contextMapLock
); return safe_cast
<Ctx
*>(contextMap
[handle
]); }
67 void setContext(CSSM_CC_HANDLE handle
, PluginContext
*ctx
)
68 { StLock
<Mutex
> _(contextMapLock
); contextMap
[handle
] = ctx
; }
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
);
80 map
<CSSM_CC_HANDLE
, PluginContext
*> contextMap
;
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.
90 class CSPFullPluginSession
: public CSPPluginSession
{
93 class AlgorithmFactory
;
95 CSPFullPluginSession(CSSM_MODULE_HANDLE theHandle
,
97 const CSSM_VERSION
&version
,
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
) { }
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);
109 // verify proper state on continuation (update/final) calls
110 CSPContext
*getStagedContext(CSSM_CC_HANDLE ccHandle
,
111 CSSM_CONTEXT_TYPE type
, bool encoding
= true);
113 static const uint32 CSSM_ALGCLASS_CRYPT
= 1001; // internally added to CONTEXT_TYPE
116 // validate operation type against context class
117 void checkOperation(CSSM_CONTEXT_TYPE ctxType
, CSSM_CONTEXT_TYPE opType
);
121 // The Writer class encapsulates staged-output destinations with optional overflow
125 Writer(CssmData
*v
, uint32 n
, CssmData
*rem
= NULL
);
127 // can this buffer be extended?
128 bool isExtensible() const
129 { return !*vec
|| (remData
&& !*remData
); }
131 // increase size if necessary (and possible)
132 void allocate(size_t needed
, Allocator
&alloc
);
134 // straight-forward buffer writing
135 void put(void *addr
, size_t size
);
137 // locate-mode output (deliver buffer mode)
138 void nextBlock(void * &p
, size_t &sz
);
141 // wrap up and return total number of bytes written
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
150 void *currentBuffer
; // next free byte in vec
151 size_t currentSize
; // free bytes in vec
153 size_t written
; // bytes written
155 void useData(CssmData
*data
)
156 { currentBuffer
= data
->data(); currentSize
= data
->length(); }
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
);
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.
173 class CSPContext
: public PluginContext
{
174 friend class CSPFullPluginSession
;
176 CSSM_CONTEXT_TYPE
type() const { return mType
; }
177 bool encoding() const { return mDirection
; }
179 // init() is called for all algorithms
180 virtual void init(const Context
&context
, bool encoding
= true);
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
¶ms
, uint32
&attrCount
, Context::Attr
* &attrs
);
190 virtual CSPContext
*clone(Allocator
&); // clone internal state
191 virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg
);
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
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
);
203 void update(const CssmData
*in
, uint32 inCount
)
204 { for (uint32 n
= 0; n
< inCount
; n
++) update(in
[n
]); }
206 void checkOperation(CSSM_CONTEXT_TYPE type
);
207 void checkOperation(CSSM_CONTEXT_TYPE type
, bool encode
);
209 CSSM_CONTEXT_TYPE mType
; // CSSM context type
210 bool mDirection
; // operation direction (true if irrelevant)
214 virtual void setupContext(CSPContext
* &ctx
, const Context
&context
, bool encoding
) = 0;
216 virtual void getKeySize(const CssmKey
&key
, CSSM_KEY_SIZE
&size
);
219 // an algorithm factory. This is an optional feature
220 class AlgorithmFactory
{
222 virtual ~AlgorithmFactory();
224 // set ctx and return true if you can handle this
225 virtual bool setup(CSPContext
* &ctx
, const Context
&context
) = 0;
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
,
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
,
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
,
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
,
271 void QuerySize(CSSM_CC_HANDLE CCHandle
,
272 const Context
&Context
,
274 uint32 QuerySizeCount
,
275 QuerySizeData
*DataBlock
);
277 void WrapKey(CSSM_CC_HANDLE CCHandle
,
278 const Context
&Context
,
279 const AccessCredentials
&AccessCred
,
281 const CssmData
*DescriptiveData
,
283 CSSM_PRIVILEGE Privilege
);
284 void UnwrapKey(CSSM_CC_HANDLE CCHandle
,
285 const Context
&Context
,
286 const CssmKey
*PublicKey
,
287 const CssmKey
&WrappedKey
,
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
,
300 const CssmData
*KeyLabel
,
301 const CSSM_RESOURCE_CONTROL_CONTEXT
*CredAndAclEntry
,
302 CssmKey
&DerivedKey
);
304 void GenerateMac(CSSM_CC_HANDLE CCHandle
,
305 const Context
&Context
,
306 const CssmData DataBufs
[],
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
,
317 void VerifyMac(CSSM_CC_HANDLE CCHandle
,
318 const Context
&Context
,
319 const CssmData DataBufs
[],
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
);
330 void SignData(CSSM_CC_HANDLE CCHandle
,
331 const Context
&Context
,
332 const CssmData DataBufs
[],
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
);
344 void VerifyData(CSSM_CC_HANDLE CCHandle
,
345 const Context
&Context
,
346 const CssmData DataBufs
[],
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
);
358 void DigestData(CSSM_CC_HANDLE CCHandle
,
359 const Context
&Context
,
360 const CssmData DataBufs
[],
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
,
370 void DigestDataClone(CSSM_CC_HANDLE CCHandle
,
371 CSSM_CC_HANDLE ClonedCCHandle
);
373 void GenerateKey(CSSM_CC_HANDLE CCHandle
,
374 const Context
&Context
,
377 const CssmData
*KeyLabel
,
378 const CSSM_RESOURCE_CONTROL_CONTEXT
*CredAndAclEntry
,
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
,
387 uint32 PrivateKeyUsage
,
388 uint32 PrivateKeyAttr
,
389 const CssmData
*PrivateKeyLabel
,
390 const CSSM_RESOURCE_CONTROL_CONTEXT
*CredAndAclEntry
,
392 CSSM_PRIVILEGE Privilege
);
394 void ObtainPrivateKeyFromPublicKey(const CssmKey
&PublicKey
,
395 CssmKey
&PrivateKey
);
396 void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle
,
397 const Context
*Context
,
399 CSSM_KEY_SIZE
&KeySize
);
401 void FreeKey(const AccessCredentials
*AccessCred
,
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
,
412 uint32
&NumberOfUpdatedAttibutes
,
413 CSSM_CONTEXT_ATTRIBUTE_PTR
&UpdatedAttributes
);
415 void Login(const AccessCredentials
&AccessCred
,
416 const CssmData
*LoginName
,
417 const void *Reserved
);
419 void VerifyDevice(const CssmData
&DeviceCert
);
420 void GetOperationalStatistics(CSPOperationalStatistics
&Statistics
);
422 void RetrieveCounter(CssmData
&Counter
);
423 void RetrieveUniqueId(CssmData
&UniqueID
);
424 void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm
, CssmData
&TimeData
);
426 void GetKeyOwner(const CssmKey
&Key
,
427 CSSM_ACL_OWNER_PROTOTYPE
&Owner
);
428 void ChangeKeyOwner(const AccessCredentials
&AccessCred
,
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
,
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
);
448 void PassThrough(CSSM_CC_HANDLE CCHandle
,
449 const Context
&Context
,
450 uint32 PassThroughId
,
457 // Classes for dealing with reference keys.
460 // Forward declaration.
464 // A ReferencedKey -- The private (to the CSP) part of a Reference Key.
468 friend class KeyPool
; // So it can call deactivate()
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()
475 KeyReference
keyReference();
476 bool isActive() { return mKeyPool
!= NULL
; }
478 template <class SubPool
>
479 SubPool
&keyPool() { assert(mKeyPool
); return safer_cast
<SubPool
&>(*mKeyPool
); }
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
);
488 void deactivate() { mKeyPool
= NULL
; }
490 // Will be NULL iff this key is not active
496 // KeyPool -- a mixin class to manage a pool of ReferencedKeys
501 friend class ReferencedKey
; // So it can call add() and erase()
506 // Type safe ReferencedKey subclass lookup
507 template <class Subclass
>
508 Subclass
&find(const CSSM_KEY
&key
) const;
510 // Free the ioKey, erase keyReference from mKeyMap, and delete the ReferencedKey
511 void freeKey(Allocator
&allocator
, CSSM_KEY
&key
);
514 // Called by the constructor of ReferencedKey -- add referencedKey to mKeyMap
515 void add(ReferencedKey
&referencedKey
);
517 ReferencedKey
&findKey(const CSSM_KEY
&key
) const;
518 ReferencedKey
&findKeyReference(ReferencedKey::KeyReference keyReference
) const;
520 // Called by the destructor of ReferencedKey -- erase keyReference from mKeyMap
521 void erase(ReferencedKey
&referencedKey
);
523 // Erase keyReference from mKeyMap, and return it (for deletion)
524 ReferencedKey
&erase(ReferencedKey::KeyReference keyReference
);
527 typedef map
<ReferencedKey::KeyReference
, ReferencedKey
*> KeyMap
;
529 mutable Mutex mKeyMapLock
;
532 // Implementation of type safe ReferencedKey subclass lookup.
533 template <class Subclass
>
535 KeyPool::find(const CSSM_KEY
&key
) const
538 if (!(sub
= dynamic_cast<Subclass
*>(&findKey(key
))))
539 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
);
543 } // end namespace Security
545 #endif //_H_CSPSESSION