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>
52 // Names for the standard Attachment types
54 typedef StandardAttachment
<CSSM_SERVICE_CSP
, CSSM_SPI_CSP_FUNCS
> CSPAttachment
;
55 typedef StandardAttachment
<CSSM_SERVICE_DL
, CSSM_SPI_DL_FUNCS
> DLAttachment
;
56 typedef StandardAttachment
<CSSM_SERVICE_CL
, CSSM_SPI_CL_FUNCS
> CLAttachment
;
57 typedef StandardAttachment
<CSSM_SERVICE_AC
, CSSM_SPI_AC_FUNCS
> ACAttachment
;
58 typedef StandardAttachment
<CSSM_SERVICE_TP
, CSSM_SPI_TP_FUNCS
> TPAttachment
;
62 // A conditional locking class for always-right(TM) lock management.
66 Attachment
&attachment
;
68 TransitLock(Attachment
&att
) : attachment(att
)
70 attachment
.module.safeLock();
75 attachment
.module.safeUnlock();
82 // Context management functions
85 CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle
,
86 CSSM_ALGORITHMS AlgorithmID
,
87 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
89 CSSM_CC_HANDLE
*NewContextHandle
)
92 HandleContext::Maker
maker(CSPHandle
);
93 maker
.setup(AccessCred
);
94 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
96 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
97 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
98 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_SIGNATURE
, AlgorithmID
);
104 CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
105 CSSM_ALGORITHMS AlgorithmID
,
106 CSSM_ENCRYPT_MODE Mode
,
107 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
109 const CSSM_DATA
*InitVector
,
110 CSSM_PADDING Padding
,
112 CSSM_CC_HANDLE
*NewContextHandle
)
115 if (Reserved
!= NULL
)
116 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER
);
117 HandleContext::Maker
maker(CSPHandle
);
119 maker
.setup(AccessCred
);
121 maker
.setup(InitVector
);
122 maker
.setup(Padding
);
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
);
135 CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle
,
136 CSSM_ALGORITHMS AlgorithmID
,
137 CSSM_CC_HANDLE
*NewContextHandle
)
140 HandleContext::Maker
maker(CSPHandle
);
142 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_DIGEST
, AlgorithmID
);
148 CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle
,
149 CSSM_ALGORITHMS AlgorithmID
,
151 CSSM_CC_HANDLE
*NewContextHandle
)
154 HandleContext::Maker
maker(CSPHandle
);
155 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
157 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
158 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_MAC
, AlgorithmID
);
164 CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle
,
165 CSSM_ALGORITHMS AlgorithmID
,
166 const CSSM_CRYPTO_DATA
*Seed
,
168 CSSM_CC_HANDLE
*NewContextHandle
)
171 HandleContext::Maker
maker(CSPHandle
);
173 maker
.setup(Length
, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE
);
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
);
183 CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
184 CSSM_ALGORITHMS AlgorithmID
,
185 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
187 CSSM_PADDING Padding
,
188 CSSM_CC_HANDLE
*NewContextHandle
)
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
);
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
);
205 CSSM_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
)
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
);
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
);
239 CSSM_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
)
250 HandleContext::Maker
maker(CSPHandle
);
251 maker
.setup(KeySizeInBits
, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
254 maker
.setup(StartDate
);
255 maker
.setup(EndDate
);
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
);
270 CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle
,
272 CSSM_CC_HANDLE
*NewContextHandle
)
275 HandleContext::Maker
maker(CSPHandle
);
276 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
278 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
279 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_NONE
, CSSM_ALGID_NONE
);
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.
290 CSSM_GetContext (CSSM_CC_HANDLE CCHandle
,
291 CSSM_CONTEXT_PTR
*ContextP
)
294 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
295 Context
*newContext
= new(context
.attachment
) Context(context
.type(), context
.algorithm());
297 newContext
->CSPHandle
= context
.attachment
.handle();
298 newContext
->copyFrom(context
, context
.attachment
);
299 Required(ContextP
) = newContext
;
301 context
.attachment
.free(newContext
);
309 // Since we allocated all the data in one fell heap, our FreeContext
310 // function is disappointingly simple.
313 CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP
)
316 Context
*context
= &Context::required(ContextP
);
317 context
->destroy(context
, HandleObject::find
<CSPAttachment
>(context
->CSPHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
));
323 CSSM_SetContext (CSSM_CC_HANDLE CCHandle
,
324 const CSSM_CONTEXT
*ContextP
)
327 const Context
&source
= Context::required(ContextP
);
328 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
330 CSSM_CONTEXT_ATTRIBUTE
*oldAttributes
= context
.ContextAttributes
;
331 uint32 oldCount
= context
.NumberOfAttributes
;
332 CSSM_CONTEXT_TYPE oldType
= context
.ContextType
;
333 CSSM_ALGORITHMS oldAlgorithm
= context
.AlgorithmType
;
335 context
.copyFrom(source
, context
.attachment
);
336 context
.ContextType
= source
.ContextType
;
337 context
.AlgorithmType
= source
.AlgorithmType
;
339 if (CSSM_RETURN err
= context
.validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
340 context
.attachment
.free(context
.ContextAttributes
); // free rejected attribute blob
341 context
.ContextAttributes
= oldAttributes
; // restore...
342 context
.NumberOfAttributes
= oldCount
; // ... old
343 context
.ContextType
= oldType
; // ... values
344 context
.AlgorithmType
= oldAlgorithm
; // ... in context
345 CssmError::throwMe(err
); // tell the caller it failed
348 context
.attachment
.free(oldAttributes
);
354 CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle
)
357 HandleContext
&context
= enterContext(CCHandle
);
358 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
>
359 _(context
.attachment
, true);
361 // ignore error return from CSP event notify (can't decline deletion)
362 context
.validateChange(CSSM_CONTEXT_EVENT_DELETE
);
364 context
.destroy(&context
, context
.attachment
);
370 // The GetContextAttribute API is fatally flawed. The standard implies a deep
371 // copy of the attribute value, but no release function exists. Instead, we
372 // return a shallow copy (sharing structure) which you need not release, but
373 // which becomes invalid when the source Context is destroyed.
376 CSSM_GetContextAttribute (const CSSM_CONTEXT
*Context
,
377 uint32 AttributeType
,
378 CSSM_CONTEXT_ATTRIBUTE_PTR
*ContextAttribute
)
381 CSSM_ATTRIBUTE_TYPE type
= CSSM_ATTRIBUTE_TYPE(AttributeType
); // CDSA defect
382 Required(ContextAttribute
) = Context::required(Context
).find(type
);
388 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle
,
389 uint32 NumberAttributes
,
390 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
393 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
394 context
.mergeAttributes(ContextAttributes
, NumberAttributes
);
400 CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle
,
401 uint32 NumberOfAttributes
,
402 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
405 if (NumberOfAttributes
== 0)
406 return CSSM_OK
; // I suppose
407 Required(ContextAttributes
); // preflight
408 HandleContext
&context
= HandleObject::find
<HandleContext
>((CSSM_HANDLE
)CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
409 for (uint32 n
= 0; n
< NumberOfAttributes
; n
++)
410 context
.deleteAttribute(ContextAttributes
[n
].AttributeType
);
416 // Miscellaneous odds and ends - these functions just need a wee bit of
417 // manual massaging to fit.
420 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle
,
421 CSSM_CC_HANDLE
*newCCHandle
)
424 HandleContext
&context
= HandleObject::findAndLock
<HandleContext
>((CSSM_HANDLE
)ccHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
425 TransitLock
_(context
.attachment
);
426 HandleContext
*newContext
=
427 new(context
.attachment
) HandleContext(context
.attachment
, context
.type(), context
.algorithm());
429 newContext
->CSPHandle
= context
.attachment
.handle();
430 newContext
->copyFrom(context
, context
.attachment
);
431 context
.attachment
.downcalls
.DigestDataClone(context
.attachment
.handle(), ccHandle
, newContext
->handle());
432 Required(newCCHandle
) = newContext
->handle();
434 newContext
->destroy(newContext
, context
.attachment
);
442 CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle
,
443 CSSM_CC_HANDLE ccHandle
,
445 CSSM_KEY_SIZE_PTR keySize
)
447 //@@@ could afford not to lock attachment in have-CC case
451 CSPAttachment
*attachment
;
452 if (ccHandle
== (CSSM_CC_HANDLE
) HandleObject::invalidHandle
) {
453 // key specified by CSPHandle and Key
454 attachment
= &enterAttachment
<CSPAttachment
>(CSPHandle
);
457 // key specified by ccHandle
458 HandleContext
*ctx
= &enterContext(ccHandle
);
460 attachment
= &ctx
->attachment
;
462 CSPHandle
= context
->CSPHandle
;
463 key
= &context
->get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
,
464 CSSMERR_CSP_INVALID_KEY
);
470 TransitLock
_(*attachment
);
471 CSSM_RETURN result
= attachment
->downcalls
.QueryKeySizeInBits(CSPHandle
,
472 ccHandle
, context
, key
, keySize
);
479 CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle
,
484 // this function has more subtle locking than usual. Pay attention:
486 // (1) Resolve context and ensure attachment exit
487 HandleContext
&context
= enterContext(CCHandle
);
488 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
> _(context
.attachment
, true);
490 // (2) Call CSP, acquiring module safe-lock for a moment (only)
491 CSSM_CONTEXT_ATTRIBUTE_PTR attributes
;
494 StLock
<Module
, &Module::safeLock
, &Module::safeUnlock
> _(context
.attachment
.module);
495 if (CSSM_RETURN err
=
496 context
.attachment
.downcalls
.GenerateAlgorithmParams(context
.attachment
.handle(),
499 &count
, &attributes
))
500 CssmError::throwMe(err
);
503 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
505 context
.mergeAttributes(attributes
, count
);
506 // the memory at (attributes, count) belongs to the CSP; don't free it here
512 // Include the auto-generated functions
514 #include <derived_src/transition.gen>