]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_cssm/lib/transition.cpp
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_cssm / lib / transition.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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//
54typedef StandardAttachment<CSSM_SERVICE_CSP, CSSM_SPI_CSP_FUNCS> CSPAttachment;
55typedef StandardAttachment<CSSM_SERVICE_DL, CSSM_SPI_DL_FUNCS> DLAttachment;
56typedef StandardAttachment<CSSM_SERVICE_CL, CSSM_SPI_CL_FUNCS> CLAttachment;
57typedef StandardAttachment<CSSM_SERVICE_AC, CSSM_SPI_AC_FUNCS> ACAttachment;
58typedef StandardAttachment<CSSM_SERVICE_TP, CSSM_SPI_TP_FUNCS> TPAttachment;
59
60
61//
62// A conditional locking class for always-right(TM) lock management.
63//
64class TransitLock {
65public:
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//
84CSSM_RETURN CSSMAPI
85CSSM_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
103CSSM_RETURN CSSMAPI
104CSSM_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
134CSSM_RETURN CSSMAPI
135CSSM_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
147CSSM_RETURN CSSMAPI
148CSSM_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
163CSSM_RETURN CSSMAPI
164CSSM_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);
427c49bc 176 maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length);
b1ab9ed8
A
177 Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID);
178 END_API(CSSM)
179}
180
181
182CSSM_RETURN CSSMAPI
183CSSM_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
204CSSM_RETURN CSSMAPI
205CSSM_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
238CSSM_RETURN CSSMAPI
239CSSM_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
269CSSM_RETURN CSSMAPI
270CSSM_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//
289CSSM_RETURN CSSMAPI
290CSSM_GetContext (CSSM_CC_HANDLE CCHandle,
291 CSSM_CONTEXT_PTR *ContextP)
292{
293 BEGIN_API
427c49bc
A
294#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
295 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
b1ab9ed8
A
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//
313CSSM_RETURN CSSMAPI
314CSSM_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
323CSSM_RETURN CSSMAPI
324CSSM_SetContext (CSSM_CC_HANDLE CCHandle,
325 const CSSM_CONTEXT *ContextP)
326{
327 BEGIN_API
328 const Context &source = Context::required(ContextP);
427c49bc
A
329#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
330 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
b1ab9ed8
A
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
355CSSM_RETURN CSSMAPI
356CSSM_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//
377CSSM_RETURN CSSMAPI
378CSSM_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
389CSSM_RETURN CSSMAPI
390CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle,
391 uint32 NumberAttributes,
392 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
393{
394 BEGIN_API
427c49bc
A
395#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
396 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
b1ab9ed8
A
397 context.mergeAttributes(ContextAttributes, NumberAttributes);
398 END_API(CSSM)
399}
400
401
402CSSM_RETURN CSSMAPI
403CSSM_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
427c49bc
A
411#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
412 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
b1ab9ed8
A
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//
423CSSM_RETURN CSSMAPI
424CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle,
425 CSSM_CC_HANDLE *newCCHandle)
426{
427 BEGIN_API
427c49bc
A
428#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
429 HandleContext &context = HandleObject::findAndLock<HandleContext>((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
b1ab9ed8
A
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
446CSSM_RETURN CSSMAPI
447CSSM_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
483CSSM_RETURN CSSMAPI
484CSSM_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>