transition.cpp
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 #include "LegacyAPICounts.h" 50 51 52 // 53 // Names for the standard Attachment types 54 // 55 typedef StandardAttachment<CSSM_SERVICE_CSP, CSSM_SPI_CSP_FUNCS> CSPAttachment; 56 typedef StandardAttachment<CSSM_SERVICE_DL, CSSM_SPI_DL_FUNCS> DLAttachment; 57 typedef StandardAttachment<CSSM_SERVICE_CL, CSSM_SPI_CL_FUNCS> CLAttachment; 58 typedef StandardAttachment<CSSM_SERVICE_AC, CSSM_SPI_AC_FUNCS> ACAttachment; 59 typedef StandardAttachment<CSSM_SERVICE_TP, CSSM_SPI_TP_FUNCS> TPAttachment; 60 61 62 // 63 // A conditional locking class for always-right(TM) lock management. 64 // 65 class TransitLock { 66 public: 67 Attachment &attachment; 68 69 TransitLock(Attachment &att) : attachment(att) 70 { 71 attachment.module.safeLock(); 72 } 73 74 ~TransitLock() 75 { 76 attachment.module.safeUnlock(); 77 attachment.exit(); 78 } 79 }; 80 81 82 // 83 // Context management functions 84 // 85 CSSM_RETURN CSSMAPI 86 CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle, 87 CSSM_ALGORITHMS AlgorithmID, 88 const CSSM_ACCESS_CREDENTIALS *AccessCred, 89 const CSSM_KEY *Key, 90 CSSM_CC_HANDLE *NewContextHandle) 91 { 92 BEGIN_API 93 HandleContext::Maker maker(CSPHandle); 94 maker.setup(AccessCred); 95 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 96 maker.make(); 97 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 98 maker.put(CSSM_ATTRIBUTE_KEY, Key); 99 Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID); 100 END_API(CSSM) 101 } 102 103 104 CSSM_RETURN CSSMAPI 105 CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle, 106 CSSM_ALGORITHMS AlgorithmID, 107 CSSM_ENCRYPT_MODE Mode, 108 const CSSM_ACCESS_CREDENTIALS *AccessCred, 109 const CSSM_KEY *Key, 110 const CSSM_DATA *InitVector, 111 CSSM_PADDING Padding, 112 void *Reserved, 113 CSSM_CC_HANDLE *NewContextHandle) 114 { 115 BEGIN_API 116 if (Reserved != NULL) 117 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); 118 HandleContext::Maker maker(CSPHandle); 119 maker.setup(Mode); 120 maker.setup(AccessCred); 121 maker.setup(Key); 122 maker.setup(InitVector); 123 maker.setup(Padding); 124 maker.make(); 125 maker.put(CSSM_ATTRIBUTE_MODE, Mode); 126 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 127 maker.put(CSSM_ATTRIBUTE_KEY, Key); 128 maker.put(CSSM_ATTRIBUTE_INIT_VECTOR, InitVector); 129 maker.put(CSSM_ATTRIBUTE_PADDING, Padding); 130 Required(NewContextHandle) = maker(CSSM_ALGCLASS_SYMMETRIC, AlgorithmID); 131 END_API(CSSM) 132 } 133 134 135 CSSM_RETURN CSSMAPI 136 CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle, 137 CSSM_ALGORITHMS AlgorithmID, 138 CSSM_CC_HANDLE *NewContextHandle) 139 { 140 BEGIN_API 141 HandleContext::Maker maker(CSPHandle); 142 maker.make(); 143 Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID); 144 END_API(CSSM) 145 } 146 147 148 CSSM_RETURN CSSMAPI 149 CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle, 150 CSSM_ALGORITHMS AlgorithmID, 151 const CSSM_KEY *Key, 152 CSSM_CC_HANDLE *NewContextHandle) 153 { 154 BEGIN_API 155 HandleContext::Maker maker(CSPHandle); 156 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 157 maker.make(); 158 maker.put(CSSM_ATTRIBUTE_KEY, Key); 159 Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID); 160 END_API(CSSM) 161 } 162 163 164 CSSM_RETURN CSSMAPI 165 CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle, 166 CSSM_ALGORITHMS AlgorithmID, 167 const CSSM_CRYPTO_DATA *Seed, 168 CSSM_SIZE Length, 169 CSSM_CC_HANDLE *NewContextHandle) 170 { 171 BEGIN_API 172 HandleContext::Maker maker(CSPHandle); 173 maker.setup(Seed); 174 maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE); 175 maker.make(); 176 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 177 maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length); 178 Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID); 179 END_API(CSSM) 180 } 181 182 183 CSSM_RETURN CSSMAPI 184 CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle, 185 CSSM_ALGORITHMS AlgorithmID, 186 const CSSM_ACCESS_CREDENTIALS *AccessCred, 187 const CSSM_KEY *Key, 188 CSSM_PADDING Padding, 189 CSSM_CC_HANDLE *NewContextHandle) 190 { 191 BEGIN_API 192 HandleContext::Maker maker(CSPHandle); 193 maker.setup(AccessCred, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS); 194 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 195 maker.setup(Padding); 196 maker.make(); 197 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 198 maker.put(CSSM_ATTRIBUTE_KEY, Key); 199 maker.put(CSSM_ATTRIBUTE_PADDING, Padding); 200 Required(NewContextHandle) = maker(CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID); 201 END_API(CSSM) 202 } 203 204 205 CSSM_RETURN CSSMAPI 206 CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle, 207 CSSM_ALGORITHMS AlgorithmID, 208 CSSM_KEY_TYPE DeriveKeyType, 209 uint32 DeriveKeyLengthInBits, 210 const CSSM_ACCESS_CREDENTIALS *AccessCred, 211 const CSSM_KEY *BaseKey, 212 uint32 IterationCount, 213 const CSSM_DATA *Salt, 214 const CSSM_CRYPTO_DATA *Seed, 215 CSSM_CC_HANDLE *NewContextHandle) 216 { 217 BEGIN_API 218 HandleContext::Maker maker(CSPHandle); 219 maker.setup(DeriveKeyType, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE); 220 maker.setup(DeriveKeyLengthInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); 221 maker.setup(AccessCred); 222 maker.setup(BaseKey); 223 maker.setup(IterationCount); 224 maker.setup(Salt); 225 maker.setup(Seed); 226 maker.make(); 227 maker.put(CSSM_ATTRIBUTE_KEY_TYPE, DeriveKeyType); 228 maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, DeriveKeyLengthInBits); 229 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); 230 maker.put(CSSM_ATTRIBUTE_KEY, BaseKey); 231 maker.put(CSSM_ATTRIBUTE_ITERATION_COUNT, IterationCount); 232 maker.put(CSSM_ATTRIBUTE_SALT, Salt); 233 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 234 Required(NewContextHandle) = maker(CSSM_ALGCLASS_DERIVEKEY, AlgorithmID); 235 END_API(CSSM) 236 } 237 238 239 CSSM_RETURN CSSMAPI 240 CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle, 241 CSSM_ALGORITHMS AlgorithmID, 242 uint32 KeySizeInBits, 243 const CSSM_CRYPTO_DATA *Seed, 244 const CSSM_DATA *Salt, 245 const CSSM_DATE *StartDate, 246 const CSSM_DATE *EndDate, 247 const CSSM_DATA *Params, 248 CSSM_CC_HANDLE *NewContextHandle) 249 { 250 BEGIN_API 251 HandleContext::Maker maker(CSPHandle); 252 maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); 253 maker.setup(Seed); 254 maker.setup(Salt); 255 maker.setup(StartDate); 256 maker.setup(EndDate); 257 maker.setup(Params); 258 maker.make(); 259 maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, KeySizeInBits); 260 maker.put(CSSM_ATTRIBUTE_SEED, Seed); 261 maker.put(CSSM_ATTRIBUTE_SALT, Salt); 262 maker.put(CSSM_ATTRIBUTE_START_DATE, StartDate); 263 maker.put(CSSM_ATTRIBUTE_END_DATE, EndDate); 264 maker.put(CSSM_ATTRIBUTE_ALG_PARAMS, Params); 265 Required(NewContextHandle) = maker(CSSM_ALGCLASS_KEYGEN, AlgorithmID); 266 END_API(CSSM) 267 } 268 269 270 CSSM_RETURN CSSMAPI 271 CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle, 272 const CSSM_KEY *Key, 273 CSSM_CC_HANDLE *NewContextHandle) 274 { 275 BEGIN_API 276 HandleContext::Maker maker(CSPHandle); 277 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); 278 maker.make(); 279 maker.put(CSSM_ATTRIBUTE_KEY, Key); 280 Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE); 281 END_API(CSSM) 282 } 283 284 285 // 286 // CSSM_GetContext makes a deep copy of a CSP context and hands it to the 287 // caller. The result is NOT a HandleContext, but a bare Context that is 288 // in no dictionaries etc. User must delete it by calling CSSM_FreeContext. 289 // 290 CSSM_RETURN CSSMAPI 291 CSSM_GetContext (CSSM_CC_HANDLE CCHandle, 292 CSSM_CONTEXT_PTR *ContextP) 293 { 294 BEGIN_API 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 // 313 CSSM_RETURN CSSMAPI 314 CSSM_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 323 CSSM_RETURN CSSMAPI 324 CSSM_SetContext (CSSM_CC_HANDLE CCHandle, 325 const CSSM_CONTEXT *ContextP) 326 { 327 BEGIN_API 328 const Context &source = Context::required(ContextP); 329 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 330 331 CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes; 332 uint32 oldCount = context.NumberOfAttributes; 333 CSSM_CONTEXT_TYPE oldType = context.ContextType; 334 CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType; 335 336 context.copyFrom(source, context.attachment); 337 context.ContextType = source.ContextType; 338 context.AlgorithmType = source.AlgorithmType; 339 340 if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { 341 context.attachment.free(context.ContextAttributes); // free rejected attribute blob 342 context.ContextAttributes = oldAttributes; // restore... 343 context.NumberOfAttributes = oldCount; // ... old 344 context.ContextType = oldType; // ... values 345 context.AlgorithmType = oldAlgorithm; // ... in context 346 CssmError::throwMe(err); // tell the caller it failed 347 } 348 349 context.attachment.free(oldAttributes); 350 END_API(CSSM) 351 } 352 353 354 CSSM_RETURN CSSMAPI 355 CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle) 356 { 357 BEGIN_API 358 HandleContext &context = enterContext(CCHandle); 359 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> 360 _(context.attachment, true); 361 362 // ignore error return from CSP event notify (can't decline deletion) 363 context.validateChange(CSSM_CONTEXT_EVENT_DELETE); 364 365 context.destroy(&context, context.attachment); 366 END_API(CSSM) 367 } 368 369 370 // 371 // The GetContextAttribute API is fatally flawed. The standard implies a deep 372 // copy of the attribute value, but no release function exists. Instead, we 373 // return a shallow copy (sharing structure) which you need not release, but 374 // which becomes invalid when the source Context is destroyed. 375 // 376 CSSM_RETURN CSSMAPI 377 CSSM_GetContextAttribute (const CSSM_CONTEXT *Context, 378 uint32 AttributeType, 379 CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute) 380 { 381 BEGIN_API 382 CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect 383 Required(ContextAttribute) = Context::required(Context).find(type); 384 END_API(CSSM) 385 } 386 387 388 CSSM_RETURN CSSMAPI 389 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, 390 uint32 NumberAttributes, 391 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) 392 { 393 BEGIN_API 394 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 395 context.mergeAttributes(ContextAttributes, NumberAttributes); 396 END_API(CSSM) 397 } 398 399 400 CSSM_RETURN CSSMAPI 401 CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, 402 uint32 NumberOfAttributes, 403 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) 404 { 405 BEGIN_API 406 if (NumberOfAttributes == 0) 407 return CSSM_OK; // I suppose 408 Required(ContextAttributes); // preflight 409 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 410 for (uint32 n = 0; n < NumberOfAttributes; n++) 411 context.deleteAttribute(ContextAttributes[n].AttributeType); 412 END_API(CSSM) 413 } 414 415 416 // 417 // Miscellaneous odds and ends - these functions just need a wee bit of 418 // manual massaging to fit. 419 // 420 CSSM_RETURN CSSMAPI 421 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle, 422 CSSM_CC_HANDLE *newCCHandle) 423 { 424 BEGIN_API 425 HandleContext &context = HandleObject::findAndLock<HandleContext>((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); 426 TransitLock _(context.attachment); 427 HandleContext *newContext = 428 new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm()); 429 try { 430 newContext->CSPHandle = context.attachment.handle(); 431 newContext->copyFrom(context, context.attachment); 432 context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle()); 433 Required(newCCHandle) = newContext->handle(); 434 } catch (...) { 435 newContext->destroy(newContext, context.attachment); 436 throw; 437 } 438 END_API(CSSM) 439 } 440 441 442 CSSM_RETURN CSSMAPI 443 CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle, 444 CSSM_CC_HANDLE ccHandle, 445 const CSSM_KEY *key, 446 CSSM_KEY_SIZE_PTR keySize) 447 { 448 //@@@ could afford not to lock attachment in have-CC case 449 BEGIN_API 450 Required(keySize); 451 Context *context; 452 CSPAttachment *attachment; 453 if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) { 454 // key specified by CSPHandle and Key 455 attachment = &enterAttachment<CSPAttachment>(CSPHandle); 456 context = NULL; 457 } else { 458 // key specified by ccHandle 459 HandleContext *ctx = &enterContext(ccHandle); 460 try { 461 attachment = &ctx->attachment; 462 context = ctx; 463 CSPHandle = context->CSPHandle; 464 key = &context->get<CssmKey>(CSSM_ATTRIBUTE_KEY, 465 CSSMERR_CSP_INVALID_KEY); 466 } catch (...) { 467 attachment->exit(); 468 throw; 469 } 470 } 471 TransitLock _(*attachment); 472 CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle, 473 ccHandle, context, key, keySize); 474 return result; 475 END_API(CSSM) 476 } 477 478 479 CSSM_RETURN CSSMAPI 480 CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle, 481 uint32 ParamBits, 482 CSSM_DATA_PTR Param) 483 { 484 BEGIN_API 485 // this function has more subtle locking than usual. Pay attention: 486 487 // (1) Resolve context and ensure attachment exit 488 HandleContext &context = enterContext(CCHandle); 489 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> _(context.attachment, true); 490 491 // (2) Call CSP, acquiring module safe-lock for a moment (only) 492 CSSM_CONTEXT_ATTRIBUTE_PTR attributes; 493 uint32 count; 494 { 495 StLock<Module, &Module::safeLock, &Module::safeUnlock> _(context.attachment.module); 496 if (CSSM_RETURN err = 497 context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(), 498 CCHandle, &context, 499 ParamBits, Param, 500 &count, &attributes)) 501 CssmError::throwMe(err); 502 } 503 504 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally 505 if (count) 506 context.mergeAttributes(attributes, count); 507 // the memory at (attributes, count) belongs to the CSP; don't free it here 508 END_API(CSSM) 509 } 510 511 512 // 513 // Include the auto-generated functions 514 // 515 #include <derived_src/transition.gen>