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