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