]> git.saurik.com Git - apple/security.git/blob - cdsa/cssm/transition.cpp
Security-54.1.tar.gz
[apple/security.git] / cdsa / cssm / transition.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // transition - transition layer for CSSM API/SPI calls.
21 //
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.
28 //
29 // @@@ Reconsider CSP locking for context operations
30 //
31 #include "cssmint.h"
32 #include "attachfactory.h"
33 #include "manager.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>
42
43
44 //
45 // Names for the standard Attachment types
46 //
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;
52
53
54 //
55 // A conditional locking class for always-right(TM) lock management.
56 //
57 class TransitLock {
58 public:
59 Attachment &attachment;
60
61 TransitLock(Attachment &att) : attachment(att)
62 {
63 attachment.module.safeLock();
64 }
65
66 ~TransitLock()
67 {
68 attachment.module.safeUnlock();
69 attachment.exit();
70 }
71 };
72
73
74 //
75 // Context management functions
76 //
77 CSSM_RETURN CSSMAPI
78 CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle,
79 CSSM_ALGORITHMS AlgorithmID,
80 const CSSM_ACCESS_CREDENTIALS *AccessCred,
81 const CSSM_KEY *Key,
82 CSSM_CC_HANDLE *NewContextHandle)
83 {
84 BEGIN_API
85 HandleContext::Maker maker(CSPHandle);
86 maker.setup(AccessCred);
87 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
88 maker.make();
89 maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred);
90 maker.put(CSSM_ATTRIBUTE_KEY, Key);
91 Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID);
92 END_API(CSSM)
93 }
94
95
96 CSSM_RETURN CSSMAPI
97 CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle,
98 CSSM_ALGORITHMS AlgorithmID,
99 CSSM_ENCRYPT_MODE Mode,
100 const CSSM_ACCESS_CREDENTIALS *AccessCred,
101 const CSSM_KEY *Key,
102 const CSSM_DATA *InitVector,
103 CSSM_PADDING Padding,
104 void *Reserved,
105 CSSM_CC_HANDLE *NewContextHandle)
106 {
107 BEGIN_API
108 if (Reserved != NULL)
109 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER);
110 HandleContext::Maker maker(CSPHandle);
111 maker.setup(Mode);
112 maker.setup(AccessCred);
113 maker.setup(Key);
114 maker.setup(InitVector);
115 maker.setup(Padding);
116 maker.make();
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);
123 END_API(CSSM)
124 }
125
126
127 CSSM_RETURN CSSMAPI
128 CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle,
129 CSSM_ALGORITHMS AlgorithmID,
130 CSSM_CC_HANDLE *NewContextHandle)
131 {
132 BEGIN_API
133 HandleContext::Maker maker(CSPHandle);
134 maker.make();
135 Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID);
136 END_API(CSSM)
137 }
138
139
140 CSSM_RETURN CSSMAPI
141 CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle,
142 CSSM_ALGORITHMS AlgorithmID,
143 const CSSM_KEY *Key,
144 CSSM_CC_HANDLE *NewContextHandle)
145 {
146 BEGIN_API
147 HandleContext::Maker maker(CSPHandle);
148 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
149 maker.make();
150 maker.put(CSSM_ATTRIBUTE_KEY, Key);
151 Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID);
152 END_API(CSSM)
153 }
154
155
156 CSSM_RETURN CSSMAPI
157 CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle,
158 CSSM_ALGORITHMS AlgorithmID,
159 const CSSM_CRYPTO_DATA *Seed,
160 uint32 Length,
161 CSSM_CC_HANDLE *NewContextHandle)
162 {
163 BEGIN_API
164 HandleContext::Maker maker(CSPHandle);
165 maker.setup(Seed);
166 maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE);
167 maker.make();
168 maker.put(CSSM_ATTRIBUTE_SEED, Seed);
169 maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, Length);
170 Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID);
171 END_API(CSSM)
172 }
173
174
175 CSSM_RETURN CSSMAPI
176 CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle,
177 CSSM_ALGORITHMS AlgorithmID,
178 const CSSM_ACCESS_CREDENTIALS *AccessCred,
179 const CSSM_KEY *Key,
180 CSSM_PADDING Padding,
181 CSSM_CC_HANDLE *NewContextHandle)
182 {
183 BEGIN_API
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);
188 maker.make();
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);
193 END_API(CSSM)
194 }
195
196
197 CSSM_RETURN CSSMAPI
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)
208 {
209 BEGIN_API
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);
216 maker.setup(Salt);
217 maker.setup(Seed);
218 maker.make();
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);
227 END_API(CSSM)
228 }
229
230
231 CSSM_RETURN CSSMAPI
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)
241 {
242 BEGIN_API
243 HandleContext::Maker maker(CSPHandle);
244 maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
245 maker.setup(Seed);
246 maker.setup(Salt);
247 maker.setup(StartDate);
248 maker.setup(EndDate);
249 maker.setup(Params);
250 maker.make();
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);
258 END_API(CSSM)
259 }
260
261
262 CSSM_RETURN CSSMAPI
263 CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle,
264 const CSSM_KEY *Key,
265 CSSM_CC_HANDLE *NewContextHandle)
266 {
267 BEGIN_API
268 HandleContext::Maker maker(CSPHandle);
269 maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
270 maker.make();
271 maker.put(CSSM_ATTRIBUTE_KEY, Key);
272 Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE);
273 END_API(CSSM)
274 }
275
276
277 //
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.
281 //
282 CSSM_RETURN CSSMAPI
283 CSSM_GetContext (CSSM_CC_HANDLE CCHandle,
284 CSSM_CONTEXT_PTR *ContextP)
285 {
286 BEGIN_API
287 HandleContext &context = findHandle<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
288 Context *newContext = new(context.attachment) Context(context.type(), context.algorithm());
289 try {
290 newContext->CSPHandle = context.attachment.handle();
291 newContext->copyFrom(context, context.attachment);
292 Required(ContextP) = newContext;
293 } catch (...) {
294 context.attachment.free(newContext);
295 throw;
296 }
297 END_API(CSSM)
298 }
299
300
301 //
302 // Since we allocated all the data in one fell heap, our FreeContext
303 // function is disappointingly simple.
304 //
305 CSSM_RETURN CSSMAPI
306 CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP)
307 {
308 BEGIN_API
309 Context *context = &Context::required(ContextP);
310 context->destroy(context, findHandle<CSPAttachment>(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE));
311 END_API(CSSM)
312 }
313
314
315 CSSM_RETURN CSSMAPI
316 CSSM_SetContext (CSSM_CC_HANDLE CCHandle,
317 const CSSM_CONTEXT *ContextP)
318 {
319 BEGIN_API
320 const Context &source = Context::required(ContextP);
321 HandleContext &context = findHandle<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
322
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;
327
328 context.copyFrom(source, context.attachment);
329 context.ContextType = source.ContextType;
330 context.AlgorithmType = source.AlgorithmType;
331
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
339 }
340
341 free(oldAttributes);
342 END_API(CSSM)
343 }
344
345
346 CSSM_RETURN CSSMAPI
347 CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle)
348 {
349 BEGIN_API
350 HandleContext &context = enterContext(CCHandle);
351 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit>
352 _(context.attachment, true);
353
354 // ignore error return from CSP event notify (can't decline deletion)
355 context.validateChange(CSSM_CONTEXT_EVENT_DELETE);
356
357 context.destroy(&context, context.attachment);
358 END_API(CSSM)
359 }
360
361
362 //
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.
367 //
368 CSSM_RETURN CSSMAPI
369 CSSM_GetContextAttribute (const CSSM_CONTEXT *Context,
370 uint32 AttributeType,
371 CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute)
372 {
373 BEGIN_API
374 CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect
375 Required(ContextAttribute) = Context::required(Context).find(type);
376 END_API(CSSM)
377 }
378
379
380 CSSM_RETURN CSSMAPI
381 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle,
382 uint32 NumberAttributes,
383 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
384 {
385 BEGIN_API
386 HandleContext &context = findHandle<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
387 context.mergeAttributes(ContextAttributes, NumberAttributes);
388 END_API(CSSM)
389 }
390
391
392 CSSM_RETURN CSSMAPI
393 CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle,
394 uint32 NumberOfAttributes,
395 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
396 {
397 BEGIN_API
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);
404 END_API(CSSM)
405 }
406
407
408 //
409 // Miscellaneous odds and ends - these functions just need a wee bit of
410 // manual massaging to fit.
411 //
412 CSSM_RETURN CSSMAPI
413 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle,
414 CSSM_CC_HANDLE *newCCHandle)
415 {
416 BEGIN_API
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());
421 try {
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();
426 } catch (...) {
427 newContext->destroy(newContext, context.attachment);
428 throw;
429 }
430 END_API(CSSM)
431 }
432
433
434 CSSM_RETURN CSSMAPI
435 CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle,
436 CSSM_CC_HANDLE ccHandle,
437 const CSSM_KEY *key,
438 CSSM_KEY_SIZE_PTR keySize)
439 {
440 //@@@ could afford not to lock attachment in have-CC case
441 BEGIN_API
442 Required(keySize);
443 Context *context;
444 CSPAttachment *attachment;
445 if (ccHandle == HandleObject::invalidHandle) {
446 // key specified by CSPHandle and Key
447 attachment = &enterAttachment<CSPAttachment>(CSPHandle);
448 context = NULL;
449 } else {
450 // key specified by ccHandle
451 HandleContext *ctx = &enterContext(ccHandle);
452 try {
453 attachment = &ctx->attachment;
454 context = ctx;
455 CSPHandle = context->CSPHandle;
456 key = &context->get<CssmKey>(CSSM_ATTRIBUTE_KEY,
457 CSSMERR_CSP_INVALID_KEY);
458 } catch (...) {
459 attachment->exit();
460 throw;
461 }
462 }
463 TransitLock _(*attachment);
464 CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle,
465 ccHandle, context, key, keySize);
466 return result;
467 END_API(CSSM)
468 }
469
470
471 CSSM_RETURN CSSMAPI
472 CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle,
473 uint32 ParamBits,
474 CSSM_DATA_PTR Param)
475 {
476 BEGIN_API
477 // this function has more subtle locking than usual. Pay attention:
478
479 // (1) Resolve context and ensure attachment exit
480 HandleContext &context = enterContext(CCHandle);
481 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> _(context.attachment, true);
482
483 // (2) Call CSP, acquiring module safe-lock for a moment (only)
484 CSSM_CONTEXT_ATTRIBUTE_PTR attributes;
485 uint32 count;
486 {
487 StLock<Module, &Module::safeLock, &Module::safeUnlock> _(context.attachment.module);
488 if (CSSM_RETURN err =
489 context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(),
490 CCHandle, &context,
491 ParamBits, Param,
492 &count, &attributes))
493 CssmError::throwMe(err);
494 }
495
496 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
497 if (count)
498 context.mergeAttributes(attributes, count);
499 // the memory at (attributes, count) belongs to the CSP; don't free it here
500 END_API(CSSM)
501 }
502
503
504 //
505 // Include the auto-generated functions
506 //
507 #include "transition.gen"