2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // transition - transition layer for CSSM API/SPI calls.
22 // This file defines all functions that connect the CSSM API (CSSM_*)
23 // to a plugin's SPI (CSSM_SPI_*) functions. The bulk of these functions
24 // is automatically generated by the Perl script transition.pl (thanks, Larry!)
25 // from the cssm*.h official header files, under control of the configuration
26 // file transition.cfg. Those that need special magic are marked "custom" in
27 // transition.cfg and are defined here.
29 // @@@ Reconsider CSP locking for context operations
32 #include "attachfactory.h"
34 #include "cssmcontext.h"
35 #include <Security/cssmcspi.h>
36 #include <Security/cssmdli.h>
37 #include <Security/cssmcli.h>
38 #include <Security/cssmaci.h>
39 #include <Security/cssmtpi.h>
40 #include <Security/cssmkrapi.h>
41 #include <Security/cssmkrspi.h>
45 // Names for the standard Attachment types
47 typedef StandardAttachment
<CSSM_SERVICE_CSP
, CSSM_SPI_CSP_FUNCS
> CSPAttachment
;
48 typedef StandardAttachment
<CSSM_SERVICE_DL
, CSSM_SPI_DL_FUNCS
> DLAttachment
;
49 typedef StandardAttachment
<CSSM_SERVICE_CL
, CSSM_SPI_CL_FUNCS
> CLAttachment
;
50 typedef StandardAttachment
<CSSM_SERVICE_AC
, CSSM_SPI_AC_FUNCS
> ACAttachment
;
51 typedef StandardAttachment
<CSSM_SERVICE_TP
, CSSM_SPI_TP_FUNCS
> TPAttachment
;
55 // A conditional locking class for always-right(TM) lock management.
59 Attachment
&attachment
;
61 TransitLock(Attachment
&att
) : attachment(att
)
63 attachment
.module.safeLock();
68 attachment
.module.safeUnlock();
75 // Context management functions
78 CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle
,
79 CSSM_ALGORITHMS AlgorithmID
,
80 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
82 CSSM_CC_HANDLE
*NewContextHandle
)
85 HandleContext::Maker
maker(CSPHandle
);
86 maker
.setup(AccessCred
);
87 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
89 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
90 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
91 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_SIGNATURE
, AlgorithmID
);
97 CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
98 CSSM_ALGORITHMS AlgorithmID
,
99 CSSM_ENCRYPT_MODE Mode
,
100 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
102 const CSSM_DATA
*InitVector
,
103 CSSM_PADDING Padding
,
105 CSSM_CC_HANDLE
*NewContextHandle
)
108 if (Reserved
!= NULL
)
109 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER
);
110 HandleContext::Maker
maker(CSPHandle
);
112 maker
.setup(AccessCred
);
114 maker
.setup(InitVector
);
115 maker
.setup(Padding
);
117 maker
.put(CSSM_ATTRIBUTE_MODE
, Mode
);
118 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
119 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
120 maker
.put(CSSM_ATTRIBUTE_INIT_VECTOR
, InitVector
);
121 maker
.put(CSSM_ATTRIBUTE_PADDING
, Padding
);
122 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_SYMMETRIC
, AlgorithmID
);
128 CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle
,
129 CSSM_ALGORITHMS AlgorithmID
,
130 CSSM_CC_HANDLE
*NewContextHandle
)
133 HandleContext::Maker
maker(CSPHandle
);
135 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_DIGEST
, AlgorithmID
);
141 CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle
,
142 CSSM_ALGORITHMS AlgorithmID
,
144 CSSM_CC_HANDLE
*NewContextHandle
)
147 HandleContext::Maker
maker(CSPHandle
);
148 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
150 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
151 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_MAC
, AlgorithmID
);
157 CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle
,
158 CSSM_ALGORITHMS AlgorithmID
,
159 const CSSM_CRYPTO_DATA
*Seed
,
161 CSSM_CC_HANDLE
*NewContextHandle
)
164 HandleContext::Maker
maker(CSPHandle
);
166 maker
.setup(Length
, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE
);
168 maker
.put(CSSM_ATTRIBUTE_SEED
, Seed
);
169 maker
.put(CSSM_ATTRIBUTE_OUTPUT_SIZE
, Length
);
170 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_RANDOMGEN
, AlgorithmID
);
176 CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle
,
177 CSSM_ALGORITHMS AlgorithmID
,
178 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
180 CSSM_PADDING Padding
,
181 CSSM_CC_HANDLE
*NewContextHandle
)
184 HandleContext::Maker
maker(CSPHandle
);
185 maker
.setup(AccessCred
, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS
);
186 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
187 maker
.setup(Padding
);
189 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
190 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
191 maker
.put(CSSM_ATTRIBUTE_PADDING
, Padding
);
192 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_ASYMMETRIC
, AlgorithmID
);
198 CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle
,
199 CSSM_ALGORITHMS AlgorithmID
,
200 CSSM_KEY_TYPE DeriveKeyType
,
201 uint32 DeriveKeyLengthInBits
,
202 const CSSM_ACCESS_CREDENTIALS
*AccessCred
,
203 const CSSM_KEY
*BaseKey
,
204 uint32 IterationCount
,
205 const CSSM_DATA
*Salt
,
206 const CSSM_CRYPTO_DATA
*Seed
,
207 CSSM_CC_HANDLE
*NewContextHandle
)
210 HandleContext::Maker
maker(CSPHandle
);
211 maker
.setup(DeriveKeyType
, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE
);
212 maker
.setup(DeriveKeyLengthInBits
, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
213 maker
.setup(AccessCred
);
214 maker
.setup(BaseKey
);
215 maker
.setup(IterationCount
);
219 maker
.put(CSSM_ATTRIBUTE_KEY_TYPE
, DeriveKeyType
);
220 maker
.put(CSSM_ATTRIBUTE_KEY_LENGTH
, DeriveKeyLengthInBits
);
221 maker
.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS
, AccessCred
);
222 maker
.put(CSSM_ATTRIBUTE_KEY
, BaseKey
);
223 maker
.put(CSSM_ATTRIBUTE_ITERATION_COUNT
, IterationCount
);
224 maker
.put(CSSM_ATTRIBUTE_SALT
, Salt
);
225 maker
.put(CSSM_ATTRIBUTE_SEED
, Seed
);
226 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_DERIVEKEY
, AlgorithmID
);
232 CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle
,
233 CSSM_ALGORITHMS AlgorithmID
,
234 uint32 KeySizeInBits
,
235 const CSSM_CRYPTO_DATA
*Seed
,
236 const CSSM_DATA
*Salt
,
237 const CSSM_DATE
*StartDate
,
238 const CSSM_DATE
*EndDate
,
239 const CSSM_DATA
*Params
,
240 CSSM_CC_HANDLE
*NewContextHandle
)
243 HandleContext::Maker
maker(CSPHandle
);
244 maker
.setup(KeySizeInBits
, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
247 maker
.setup(StartDate
);
248 maker
.setup(EndDate
);
251 maker
.put(CSSM_ATTRIBUTE_KEY_LENGTH
, KeySizeInBits
);
252 maker
.put(CSSM_ATTRIBUTE_SEED
, Seed
);
253 maker
.put(CSSM_ATTRIBUTE_SALT
, Salt
);
254 maker
.put(CSSM_ATTRIBUTE_START_DATE
, StartDate
);
255 maker
.put(CSSM_ATTRIBUTE_END_DATE
, EndDate
);
256 maker
.put(CSSM_ATTRIBUTE_ALG_PARAMS
, Params
);
257 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_KEYGEN
, AlgorithmID
);
263 CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle
,
265 CSSM_CC_HANDLE
*NewContextHandle
)
268 HandleContext::Maker
maker(CSPHandle
);
269 maker
.setup(Key
, CSSMERR_CSP_MISSING_ATTR_KEY
);
271 maker
.put(CSSM_ATTRIBUTE_KEY
, Key
);
272 Required(NewContextHandle
) = maker(CSSM_ALGCLASS_NONE
, CSSM_ALGID_NONE
);
278 // CSSM_GetContext makes a deep copy of a CSP context and hands it to the
279 // caller. The result is NOT a HandleContext, but a bare Context that is
280 // in no dictionaries etc. User must delete it by calling CSSM_FreeContext.
283 CSSM_GetContext (CSSM_CC_HANDLE CCHandle
,
284 CSSM_CONTEXT_PTR
*ContextP
)
287 HandleContext
&context
= findHandle
<HandleContext
>(CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
288 Context
*newContext
= new(context
.attachment
) Context(context
.type(), context
.algorithm());
290 newContext
->CSPHandle
= context
.attachment
.handle();
291 newContext
->copyFrom(context
, context
.attachment
);
292 Required(ContextP
) = newContext
;
294 context
.attachment
.free(newContext
);
302 // Since we allocated all the data in one fell heap, our FreeContext
303 // function is disappointingly simple.
306 CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP
)
309 Context
*context
= &Context::required(ContextP
);
310 context
->destroy(context
, findHandle
<CSPAttachment
>(context
->CSPHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
));
316 CSSM_SetContext (CSSM_CC_HANDLE CCHandle
,
317 const CSSM_CONTEXT
*ContextP
)
320 const Context
&source
= Context::required(ContextP
);
321 HandleContext
&context
= findHandle
<HandleContext
>(CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
323 CSSM_CONTEXT_ATTRIBUTE
*oldAttributes
= context
.ContextAttributes
;
324 uint32 oldCount
= context
.NumberOfAttributes
;
325 CSSM_CONTEXT_TYPE oldType
= context
.ContextType
;
326 CSSM_ALGORITHMS oldAlgorithm
= context
.AlgorithmType
;
328 context
.copyFrom(source
, context
.attachment
);
329 context
.ContextType
= source
.ContextType
;
330 context
.AlgorithmType
= source
.AlgorithmType
;
332 if (CSSM_RETURN err
= context
.validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
333 context
.attachment
.free(context
.ContextAttributes
); // free rejected attribute blob
334 context
.ContextAttributes
= oldAttributes
; // restore...
335 context
.NumberOfAttributes
= oldCount
; // ... old
336 context
.ContextType
= oldType
; // ... values
337 context
.AlgorithmType
= oldAlgorithm
; // ... in context
338 CssmError::throwMe(err
); // tell the caller it failed
341 context
.attachment
.free(oldAttributes
);
347 CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle
)
350 HandleContext
&context
= enterContext(CCHandle
);
351 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
>
352 _(context
.attachment
, true);
354 // ignore error return from CSP event notify (can't decline deletion)
355 context
.validateChange(CSSM_CONTEXT_EVENT_DELETE
);
357 context
.destroy(&context
, context
.attachment
);
363 // The GetContextAttribute API is fatally flawed. The standard implies a deep
364 // copy of the attribute value, but no release function exists. Instead, we
365 // return a shallow copy (sharing structure) which you need not release, but
366 // which becomes invalid when the source Context is destroyed.
369 CSSM_GetContextAttribute (const CSSM_CONTEXT
*Context
,
370 uint32 AttributeType
,
371 CSSM_CONTEXT_ATTRIBUTE_PTR
*ContextAttribute
)
374 CSSM_ATTRIBUTE_TYPE type
= CSSM_ATTRIBUTE_TYPE(AttributeType
); // CDSA defect
375 Required(ContextAttribute
) = Context::required(Context
).find(type
);
381 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle
,
382 uint32 NumberAttributes
,
383 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
386 HandleContext
&context
= findHandle
<HandleContext
>(CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
387 context
.mergeAttributes(ContextAttributes
, NumberAttributes
);
393 CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle
,
394 uint32 NumberOfAttributes
,
395 const CSSM_CONTEXT_ATTRIBUTE
*ContextAttributes
)
398 if (NumberOfAttributes
== 0)
399 return CSSM_OK
; // I suppose
400 Required(ContextAttributes
); // preflight
401 HandleContext
&context
= findHandle
<HandleContext
>(CCHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
402 for (uint32 n
= 0; n
< NumberOfAttributes
; n
++)
403 context
.deleteAttribute(ContextAttributes
[n
].AttributeType
);
409 // Miscellaneous odds and ends - these functions just need a wee bit of
410 // manual massaging to fit.
413 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle
,
414 CSSM_CC_HANDLE
*newCCHandle
)
417 HandleContext
&context
= findHandleAndLock
<HandleContext
>(ccHandle
, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
);
418 TransitLock
_(context
.attachment
);
419 HandleContext
*newContext
=
420 new(context
.attachment
) HandleContext(context
.attachment
, context
.type(), context
.algorithm());
422 newContext
->CSPHandle
= context
.attachment
.handle();
423 newContext
->copyFrom(context
, context
.attachment
);
424 context
.attachment
.downcalls
.DigestDataClone(context
.attachment
.handle(), ccHandle
, newContext
->handle());
425 Required(newCCHandle
) = newContext
->handle();
427 newContext
->destroy(newContext
, context
.attachment
);
435 CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle
,
436 CSSM_CC_HANDLE ccHandle
,
438 CSSM_KEY_SIZE_PTR keySize
)
440 //@@@ could afford not to lock attachment in have-CC case
444 CSPAttachment
*attachment
;
445 if (ccHandle
== HandleObject::invalidHandle
) {
446 // key specified by CSPHandle and Key
447 attachment
= &enterAttachment
<CSPAttachment
>(CSPHandle
);
450 // key specified by ccHandle
451 HandleContext
*ctx
= &enterContext(ccHandle
);
453 attachment
= &ctx
->attachment
;
455 CSPHandle
= context
->CSPHandle
;
456 key
= &context
->get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
,
457 CSSMERR_CSP_INVALID_KEY
);
463 TransitLock
_(*attachment
);
464 CSSM_RETURN result
= attachment
->downcalls
.QueryKeySizeInBits(CSPHandle
,
465 ccHandle
, context
, key
, keySize
);
472 CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle
,
477 // this function has more subtle locking than usual. Pay attention:
479 // (1) Resolve context and ensure attachment exit
480 HandleContext
&context
= enterContext(CCHandle
);
481 StLock
<CountingMutex
, &CountingMutex::enter
, &CountingMutex::exit
> _(context
.attachment
, true);
483 // (2) Call CSP, acquiring module safe-lock for a moment (only)
484 CSSM_CONTEXT_ATTRIBUTE_PTR attributes
;
487 StLock
<Module
, &Module::safeLock
, &Module::safeUnlock
> _(context
.attachment
.module);
488 if (CSSM_RETURN err
=
489 context
.attachment
.downcalls
.GenerateAlgorithmParams(context
.attachment
.handle(),
492 &count
, &attributes
))
493 CssmError::throwMe(err
);
496 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
498 context
.mergeAttributes(attributes
, count
);
499 // the memory at (attributes, count) belongs to the CSP; don't free it here
505 // Include the auto-generated functions
507 #include "transition.gen"