2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // transition - transition layer for CSSM API/SPI calls.
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.
35 // @@@ Reconsider CSP locking for context operations
38 #include "attachfactory.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"
53 // Names for the standard Attachment types
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
;
63 // A conditional locking class for always-right(TM) lock management.
67 Attachment
&attachment
;
69 TransitLock(Attachment
&att
) : attachment(att
)
71 attachment
.module.safeLock();
76 attachment
.module.safeUnlock();
83 // Context management functions
86 CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle
,
87 CSSM_ALGORITHMS AlgorithmID
,
88 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
90 CSSM_CC_HANDLE
*NewContextHandle
)
93 HandleContext::Maker
maker(CSPHandle
);
94 maker
.setup(AccessCred
);
95 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
97 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
98 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
99 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_SIGNATURE
, AlgorithmID
);
105 CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
106 CSSM_ALGORITHMS AlgorithmID
,
107 CSSM_ENCRYPT_MODE Mode
,
108 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
110 const CSSM_DATA
*InitVector
,
111 CSSM_PADDING Padding
,
113 CSSM_CC_HANDLE
*NewContextHandle
)
116 if (Reserved
!= NULL
)
117 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER
);
118 HandleContext::Maker
maker(CSPHandle
);
120 maker
.setup(AccessCred
);
122 maker
.setup(InitVector
);
123 maker
.setup(Padding
);
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
);
136 CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle
,
137 CSSM_ALGORITHMS AlgorithmID
,
138 CSSM_CC_HANDLE
*NewContextHandle
)
141 HandleContext::Maker
maker(CSPHandle
);
143 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_DIGEST
, AlgorithmID
);
149 CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle
,
150 CSSM_ALGORITHMS AlgorithmID
,
152 CSSM_CC_HANDLE
*NewContextHandle
)
155 HandleContext::Maker
maker(CSPHandle
);
156 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
158 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
159 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_MAC
, AlgorithmID
);
165 CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle
,
166 CSSM_ALGORITHMS AlgorithmID
,
167 const CSSM_CRYPTO_DATA
*Seed
,
169 CSSM_CC_HANDLE
*NewContextHandle
)
172 HandleContext::Maker
maker(CSPHandle
);
174 maker
.setup(Length
, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE
);
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
);
184 CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
185 CSSM_ALGORITHMS AlgorithmID
,
186 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
188 CSSM_PADDING Padding
,
189 CSSM_CC_HANDLE
*NewContextHandle
)
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
);
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
);
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
)
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
);
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
);
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
)
251 HandleContext::Maker
maker(CSPHandle
);
252 maker
.setup(KeySizeInBits
, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
255 maker
.setup(StartDate
);
256 maker
.setup(EndDate
);
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
);
271 CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle
,
273 CSSM_CC_HANDLE
*NewContextHandle
)
276 HandleContext::Maker
maker(CSPHandle
);
277 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
279 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
280 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_NONE
, CSSM_ALGID_NONE
);
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.
291 CSSM_GetContext (CSSM_CC_HANDLE CCHandle
,
292 CSSM_CONTEXT_PTR
*ContextP
)
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());
298 newContext
->CSPHandle
= context
.attachment
.handle();
299 newContext
->copyFrom(context
, context
.attachment
);
300 Required(ContextP
) = newContext
;
302 context
.attachment
.free(newContext
);
310 // Since we allocated all the data in one fell heap, our FreeContext
311 // function is disappointingly simple.
314 CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP
)
317 Context
*context
= &Context::required(ContextP
);
318 context
->destroy(context
, HandleObject::find
<CSPAttachment
>(context
->CSPHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
));
324 CSSM_SetContext (CSSM_CC_HANDLE CCHandle
,
325 const CSSM_CONTEXT
*ContextP
)
328 const Context
&source
= Context::required(ContextP
);
329 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
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
;
336 context
.copyFrom(source
, context
.attachment
);
337 context
.ContextType
= source
.ContextType
;
338 context
.AlgorithmType
= source
.AlgorithmType
;
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
349 context
.attachment
.free(oldAttributes
);
355 CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle
)
358 HandleContext
&context
= enterContext(CCHandle
);
359 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
>
360 _(context
.attachment
, true);
362 // ignore error return from CSP event notify (can't decline deletion)
363 context
.validateChange(CSSM_CONTEXT_EVENT_DELETE
);
365 context
.destroy(&context
, context
.attachment
);
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.
377 CSSM_GetContextAttribute (const CSSM_CONTEXT
*Context
,
378 uint32 AttributeType
,
379 CSSM_CONTEXT_ATTRIBUTE_PTR
*ContextAttribute
)
382 CSSM_ATTRIBUTE_TYPE type
= CSSM_ATTRIBUTE_TYPE(AttributeType
); // CDSA defect
383 Required(ContextAttribute
) = Context::required(Context
).find(type
);
389 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle
,
390 uint32 NumberAttributes
,
391 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
394 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
395 context
.mergeAttributes(ContextAttributes
, NumberAttributes
);
401 CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle
,
402 uint32 NumberOfAttributes
,
403 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
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
);
417 // Miscellaneous odds and ends - these functions just need a wee bit of
418 // manual massaging to fit.
421 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle
,
422 CSSM_CC_HANDLE
*newCCHandle
)
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());
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();
435 newContext
->destroy(newContext
, context
.attachment
);
443 CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle
,
444 CSSM_CC_HANDLE ccHandle
,
446 CSSM_KEY_SIZE_PTR keySize
)
448 //@@@ could afford not to lock attachment in have-CC case
452 CSPAttachment
*attachment
;
453 if (ccHandle
== (CSSM_CC_HANDLE
) HandleObject::invalidHandle
) {
454 // key specified by CSPHandle and Key
455 attachment
= &enterAttachment
<CSPAttachment
>(CSPHandle
);
458 // key specified by ccHandle
459 HandleContext
*ctx
= &enterContext(ccHandle
);
461 attachment
= &ctx
->attachment
;
463 CSPHandle
= context
->CSPHandle
;
464 key
= &context
->get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
,
465 CSSMERR_CSP_INVALID_KEY
);
471 TransitLock
_(*attachment
);
472 CSSM_RETURN result
= attachment
->downcalls
.QueryKeySizeInBits(CSPHandle
,
473 ccHandle
, context
, key
, keySize
);
480 CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle
,
485 // this function has more subtle locking than usual. Pay attention:
487 // (1) Resolve context and ensure attachment exit
488 HandleContext
&context
= enterContext(CCHandle
);
489 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
> _(context
.attachment
, true);
491 // (2) Call CSP, acquiring module safe-lock for a moment (only)
492 CSSM_CONTEXT_ATTRIBUTE_PTR attributes
;
495 StLock
<Module
, &Module::safeLock
, &Module::safeUnlock
> _(context
.attachment
.module);
496 if (CSSM_RETURN err
=
497 context
.attachment
.downcalls
.GenerateAlgorithmParams(context
.attachment
.handle(),
500 &count
, &attributes
))
501 CssmError::throwMe(err
);
504 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
506 context
.mergeAttributes(attributes
, count
);
507 // the memory at (attributes, count) belongs to the CSP; don't free it here
513 // Include the auto-generated functions
515 #include <derived_src/transition.gen>