1/* 2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// transition - transition layer for CSSM API/SPI calls. 27// 28// This file defines all functions that connect the CSSM API (CSSM_*) 29// to a plugin's SPI (CSSM_SPI_*) functions. The bulk of these functions 30// is automatically generated by the Perl script transition.pl (thanks, Larry!) 31// from the cssm*.h official header files, under control of the configuration 32// file transition.cfg. Those that need special magic are marked "custom" in 33// transition.cfg and are defined here. 34// 35// @@@ Reconsider CSP locking for context operations 36// 37#include "cssmint.h" 38#include "attachfactory.h" 39#include "manager.h" 40#include "cssmcontext.h" 41#include <Security/cssmcspi.h> 42#include <Security/cssmdli.h> 43#include <Security/cssmcli.h> 44#include <Security/cssmaci.h> 45#include <Security/cssmtpi.h> 46#include <Security/cssmkrapi.h> 47#include <Security/cssmkrspi.h> 48#include <security_cdsa_utilities/cssmbridge.h> 49 50 51// 52// Names for the standard Attachment types 53// 54typedef StandardAttachment<CSSM_SERVICE_CSP, CSSM_SPI_CSP_FUNCS> CSPAttachment; 55typedef StandardAttachment<CSSM_SERVICE_DL, CSSM_SPI_DL_FUNCS> DLAttachment; 56typedef StandardAttachment<CSSM_SERVICE_CL, CSSM_SPI_CL_FUNCS> CLAttachment; 57typedef StandardAttachment<CSSM_SERVICE_AC, CSSM_SPI_AC_FUNCS> ACAttachment; 58typedef StandardAttachment<CSSM_SERVICE_TP, CSSM_SPI_TP_FUNCS> TPAttachment; 59 60 61// 62// A conditional locking class for always-right(TM) lock management. 63// 64class TransitLock { 65public: 66 Attachment &attachment; 67 68 TransitLock(Attachment &att) : attachment(att) 69 { 70 attachment.module.safeLock(); 71 } 72 73 ~TransitLock() 74 { 75 attachment.module.safeUnlock(); 76 attachment.exit(); 77 } 78}; 79 80 81// 82// Context management functions 83// 84CSSM_RETURN CSSMAPI 85CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle, 86 CSSM_ALGORITHMS AlgorithmID, 87 const CSSM_ACCESS_CREDENTIALS *AccessCred, 88 const CSSM_KEY *Key, 89 CSSM_CC_HANDLE *NewContextHandle) 90{ 91 BEGIN_API 92 HandleContext::Maker maker(CSPHandle); 93 maker.setup(AccessCred); 94 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 95 maker.make(); 96 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 97 maker.put(CSSM_ATTRIBUTE_KEY, Key); 98 Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID); 99 END_API(CSSM) 100} 101 102 103CSSM_RETURN CSSMAPI 104CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle, 105 CSSM_ALGORITHMS AlgorithmID, 106 CSSM_ENCRYPT_MODE Mode, 107 const CSSM_ACCESS_CREDENTIALS *AccessCred, 108 const CSSM_KEY *Key, 109 const CSSM_DATA *InitVector, 110 CSSM_PADDING Padding, 111 void *Reserved, 112 CSSM_CC_HANDLE *NewContextHandle) 113{ 114 BEGIN_API 115 if (Reserved != NULL) 116 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); 117 HandleContext::Maker maker(CSPHandle); 118 maker.setup(Mode); 119 maker.setup(AccessCred); 120 maker.setup(Key); 121 maker.setup(InitVector); 122 maker.setup(Padding); 123 maker.make(); 124 maker.put(CSSM_ATTRIBUTE_MODE, Mode); 125 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 126 maker.put(CSSM_ATTRIBUTE_KEY, Key); 127 maker.put(CSSM_ATTRIBUTE_INIT_VECTOR, InitVector); 128 maker.put(CSSM_ATTRIBUTE_PADDING, Padding); 129 Required(NewContextHandle) = maker(CSSM_ALGCLASS_SYMMETRIC, AlgorithmID); 130 END_API(CSSM) 131} 132 133 134CSSM_RETURN CSSMAPI 135CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle, 136 CSSM_ALGORITHMS AlgorithmID, 137 CSSM_CC_HANDLE *NewContextHandle) 138{ 139 BEGIN_API 140 HandleContext::Maker maker(CSPHandle); 141 maker.make(); 142 Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID); 143 END_API(CSSM) 144} 145 146 147CSSM_RETURN CSSMAPI 148CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle, 149 CSSM_ALGORITHMS AlgorithmID, 150 const CSSM_KEY *Key, 151 CSSM_CC_HANDLE *NewContextHandle) 152{ 153 BEGIN_API 154 HandleContext::Maker maker(CSPHandle); 155 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 156 maker.make(); 157 maker.put(CSSM_ATTRIBUTE_KEY, Key); 158 Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID); 159 END_API(CSSM) 160} 161 162 163CSSM_RETURN CSSMAPI 164CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle, 165 CSSM_ALGORITHMS AlgorithmID, 166 const CSSM_CRYPTO_DATA *Seed, 167 CSSM_SIZE Length, 168 CSSM_CC_HANDLE *NewContextHandle) 169{ 170 BEGIN_API 171 HandleContext::Maker maker(CSPHandle); 172 maker.setup(Seed); 173 maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE); 174 maker.make(); 175 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 176 maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length); 177 Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID); 178 END_API(CSSM) 179} 180 181 182CSSM_RETURN CSSMAPI 183CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle, 184 CSSM_ALGORITHMS AlgorithmID, 185 const CSSM_ACCESS_CREDENTIALS *AccessCred, 186 const CSSM_KEY *Key, 187 CSSM_PADDING Padding, 188 CSSM_CC_HANDLE *NewContextHandle) 189{ 190 BEGIN_API 191 HandleContext::Maker maker(CSPHandle); 192 maker.setup(AccessCred, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS); 193 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 194 maker.setup(Padding); 195 maker.make(); 196 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 197 maker.put(CSSM_ATTRIBUTE_KEY, Key); 198 maker.put(CSSM_ATTRIBUTE_PADDING, Padding); 199 Required(NewContextHandle) = maker(CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID); 200 END_API(CSSM) 201} 202 203 204CSSM_RETURN CSSMAPI 205CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle, 206 CSSM_ALGORITHMS AlgorithmID, 207 CSSM_KEY_TYPE DeriveKeyType, 208 uint32 DeriveKeyLengthInBits, 209 const CSSM_ACCESS_CREDENTIALS *AccessCred, 210 const CSSM_KEY *BaseKey, 211 uint32 IterationCount, 212 const CSSM_DATA *Salt, 213 const CSSM_CRYPTO_DATA *Seed, 214 CSSM_CC_HANDLE *NewContextHandle) 215{ 216 BEGIN_API 217 HandleContext::Maker maker(CSPHandle); 218 maker.setup(DeriveKeyType, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE); 219 maker.setup(DeriveKeyLengthInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); 220 maker.setup(AccessCred); 221 maker.setup(BaseKey); 222 maker.setup(IterationCount); 223 maker.setup(Salt); 224 maker.setup(Seed); 225 maker.make(); 226 maker.put(CSSM_ATTRIBUTE_KEY_TYPE, DeriveKeyType); 227 maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, DeriveKeyLengthInBits); 228 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 229 maker.put(CSSM_ATTRIBUTE_KEY, BaseKey); 230 maker.put(CSSM_ATTRIBUTE_ITERATION_COUNT, IterationCount); 231 maker.put(CSSM_ATTRIBUTE_SALT, Salt); 232 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 233 Required(NewContextHandle) = maker(CSSM_ALGCLASS_DERIVEKEY, AlgorithmID); 234 END_API(CSSM) 235} 236 237 238CSSM_RETURN CSSMAPI 239CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle, 240 CSSM_ALGORITHMS AlgorithmID, 241 uint32 KeySizeInBits, 242 const CSSM_CRYPTO_DATA *Seed, 243 const CSSM_DATA *Salt, 244 const CSSM_DATE *StartDate, 245 const CSSM_DATE *EndDate, 246 const CSSM_DATA *Params, 247 CSSM_CC_HANDLE *NewContextHandle) 248{ 249 BEGIN_API 250 HandleContext::Maker maker(CSPHandle); 251 maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); 252 maker.setup(Seed); 253 maker.setup(Salt); 254 maker.setup(StartDate); 255 maker.setup(EndDate); 256 maker.setup(Params); 257 maker.make(); 258 maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, KeySizeInBits); 259 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 260 maker.put(CSSM_ATTRIBUTE_SALT, Salt); 261 maker.put(CSSM_ATTRIBUTE_START_DATE, StartDate); 262 maker.put(CSSM_ATTRIBUTE_END_DATE, EndDate); 263 maker.put(CSSM_ATTRIBUTE_ALG_PARAMS, Params); 264 Required(NewContextHandle) = maker(CSSM_ALGCLASS_KEYGEN, AlgorithmID); 265 END_API(CSSM) 266} 267 268 269CSSM_RETURN CSSMAPI 270CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle, 271 const CSSM_KEY *Key, 272 CSSM_CC_HANDLE *NewContextHandle) 273{ 274 BEGIN_API 275 HandleContext::Maker maker(CSPHandle); 276 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 277 maker.make(); 278 maker.put(CSSM_ATTRIBUTE_KEY, Key); 279 Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE); 280 END_API(CSSM) 281} 282 283 284// 285// CSSM_GetContext makes a deep copy of a CSP context and hands it to the 286// caller. The result is NOT a HandleContext, but a bare Context that is 287// in no dictionaries etc. User must delete it by calling CSSM_FreeContext. 288// 289CSSM_RETURN CSSMAPI 290CSSM_GetContext (CSSM_CC_HANDLE CCHandle, 291 CSSM_CONTEXT_PTR *ContextP) 292{ 293 BEGIN_API 294#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE 295 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 296 Context *newContext = new(context.attachment) Context(context.type(), context.algorithm()); 297 try { 298 newContext->CSPHandle = context.attachment.handle(); 299 newContext->copyFrom(context, context.attachment); 300 Required(ContextP) = newContext; 301 } catch (...) { 302 context.attachment.free(newContext); 303 throw; 304 } 305 END_API(CSSM) 306} 307 308 309// 310// Since we allocated all the data in one fell heap, our FreeContext 311// function is disappointingly simple. 312// 313CSSM_RETURN CSSMAPI 314CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP) 315{ 316 BEGIN_API 317 Context *context = &Context::required(ContextP); 318 context->destroy(context, HandleObject::find<CSPAttachment>(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE)); 319 END_API(CSSM) 320} 321 322 323CSSM_RETURN CSSMAPI 324CSSM_SetContext (CSSM_CC_HANDLE CCHandle, 325 const CSSM_CONTEXT *ContextP) 326{ 327 BEGIN_API 328 const Context &source = Context::required(ContextP); 329#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE 330 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 331 332 CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes; 333 uint32 oldCount = context.NumberOfAttributes; 334 CSSM_CONTEXT_TYPE oldType = context.ContextType; 335 CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType; 336 337 context.copyFrom(source, context.attachment); 338 context.ContextType = source.ContextType; 339 context.AlgorithmType = source.AlgorithmType; 340 341 if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { 342 context.attachment.free(context.ContextAttributes); // free rejected attribute blob 343 context.ContextAttributes = oldAttributes; // restore... 344 context.NumberOfAttributes = oldCount; // ... old 345 context.ContextType = oldType; // ... values 346 context.AlgorithmType = oldAlgorithm; // ... in context 347 CssmError::throwMe(err); // tell the caller it failed 348 } 349 350 context.attachment.free(oldAttributes); 351 END_API(CSSM) 352} 353 354 355CSSM_RETURN CSSMAPI 356CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle) 357{ 358 BEGIN_API 359 HandleContext &context = enterContext(CCHandle); 360 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> 361 _(context.attachment, true); 362 363 // ignore error return from CSP event notify (can't decline deletion) 364 context.validateChange(CSSM_CONTEXT_EVENT_DELETE); 365 366 context.destroy(&context, context.attachment); 367 END_API(CSSM) 368} 369 370 371// 372// The GetContextAttribute API is fatally flawed. The standard implies a deep 373// copy of the attribute value, but no release function exists. Instead, we 374// return a shallow copy (sharing structure) which you need not release, but 375// which becomes invalid when the source Context is destroyed. 376// 377CSSM_RETURN CSSMAPI 378CSSM_GetContextAttribute (const CSSM_CONTEXT *Context, 379 uint32 AttributeType, 380 CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute) 381{ 382 BEGIN_API 383 CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect 384 Required(ContextAttribute) = Context::required(Context).find(type); 385 END_API(CSSM) 386} 387 388 389CSSM_RETURN CSSMAPI 390CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, 391 uint32 NumberAttributes, 392 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) 393{ 394 BEGIN_API 395#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE 396 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 397 context.mergeAttributes(ContextAttributes, NumberAttributes); 398 END_API(CSSM) 399} 400 401 402CSSM_RETURN CSSMAPI 403CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, 404 uint32 NumberOfAttributes, 405 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) 406{ 407 BEGIN_API 408 if (NumberOfAttributes == 0) 409 return CSSM_OK; // I suppose 410 Required(ContextAttributes); // preflight 411#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE 412 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 413 for (uint32 n = 0; n < NumberOfAttributes; n++) 414 context.deleteAttribute(ContextAttributes[n].AttributeType); 415 END_API(CSSM) 416} 417 418 419// 420// Miscellaneous odds and ends - these functions just need a wee bit of 421// manual massaging to fit. 422// 423CSSM_RETURN CSSMAPI 424CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle, 425 CSSM_CC_HANDLE *newCCHandle) 426{ 427 BEGIN_API 428#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE 429 HandleContext &context = HandleObject::findAndLock<HandleContext>((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 430 TransitLock _(context.attachment); 431 HandleContext *newContext = 432 new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm()); 433 try { 434 newContext->CSPHandle = context.attachment.handle(); 435 newContext->copyFrom(context, context.attachment); 436 context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle()); 437 Required(newCCHandle) = newContext->handle(); 438 } catch (...) { 439 newContext->destroy(newContext, context.attachment); 440 throw; 441 } 442 END_API(CSSM) 443} 444 445 446CSSM_RETURN CSSMAPI 447CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle, 448 CSSM_CC_HANDLE ccHandle, 449 const CSSM_KEY *key, 450 CSSM_KEY_SIZE_PTR keySize) 451{ 452 //@@@ could afford not to lock attachment in have-CC case 453 BEGIN_API 454 Required(keySize); 455 Context *context; 456 CSPAttachment *attachment; 457 if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) { 458 // key specified by CSPHandle and Key 459 attachment = &enterAttachment<CSPAttachment>(CSPHandle); 460 context = NULL; 461 } else { 462 // key specified by ccHandle 463 HandleContext *ctx = &enterContext(ccHandle); 464 try { 465 attachment = &ctx->attachment; 466 context = ctx; 467 CSPHandle = context->CSPHandle; 468 key = &context->get<CssmKey>(CSSM_ATTRIBUTE_KEY, 469 CSSMERR_CSP_INVALID_KEY); 470 } catch (...) { 471 attachment->exit(); 472 throw; 473 } 474 } 475 TransitLock _(*attachment); 476 CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle, 477 ccHandle, context, key, keySize); 478 return result; 479 END_API(CSSM) 480} 481 482 483CSSM_RETURN CSSMAPI 484CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle, 485 uint32 ParamBits, 486 CSSM_DATA_PTR Param) 487{ 488 BEGIN_API 489 // this function has more subtle locking than usual. Pay attention: 490 491 // (1) Resolve context and ensure attachment exit 492 HandleContext &context = enterContext(CCHandle); 493 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> _(context.attachment, true); 494 495 // (2) Call CSP, acquiring module safe-lock for a moment (only) 496 CSSM_CONTEXT_ATTRIBUTE_PTR attributes; 497 uint32 count; 498 { 499 StLock<Module, &Module::safeLock, &Module::safeUnlock> _(context.attachment.module); 500 if (CSSM_RETURN err = 501 context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(), 502 CCHandle, &context, 503 ParamBits, Param, 504 &count, &attributes)) 505 CssmError::throwMe(err); 506 } 507 508 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally 509 if (count) 510 context.mergeAttributes(attributes, count); 511 // the memory at (attributes, count) belongs to the CSP; don't free it here 512 END_API(CSSM) 513} 514 515 516// 517// Include the auto-generated functions 518// 519#include <derived_src/transition.gen> 520