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 ¶ms, 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