]> git.saurik.com Git - apple/security.git/blame - libsecurity_cssm/lib/transition.cpp
Security-55179.13.tar.gz
[apple/security.git] / libsecurity_cssm / lib / transition.cpp
CommitLineData
b1ab9ed8
A
1/*
2 * Copyright (c) 2000-2004 Apple Computer, 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//
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);
176 maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, Length);
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
294 HandleContext &context = HandleObject::find<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
295 Context *newContext = new(context.attachment) Context(context.type(), context.algorithm());
296 try {
297 newContext->CSPHandle = context.attachment.handle();
298 newContext->copyFrom(context, context.attachment);
299 Required(ContextP) = newContext;
300 } catch (...) {
301 context.attachment.free(newContext);
302 throw;
303 }
304 END_API(CSSM)
305}
306
307
308//
309// Since we allocated all the data in one fell heap, our FreeContext
310// function is disappointingly simple.
311//
312CSSM_RETURN CSSMAPI
313CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP)
314{
315 BEGIN_API
316 Context *context = &Context::required(ContextP);
317 context->destroy(context, HandleObject::find<CSPAttachment>(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE));
318 END_API(CSSM)
319}
320
321
322CSSM_RETURN CSSMAPI
323CSSM_SetContext (CSSM_CC_HANDLE CCHandle,
324 const CSSM_CONTEXT *ContextP)
325{
326 BEGIN_API
327 const Context &source = Context::required(ContextP);
328 HandleContext &context = HandleObject::find<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
329
330 CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes;
331 uint32 oldCount = context.NumberOfAttributes;
332 CSSM_CONTEXT_TYPE oldType = context.ContextType;
333 CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType;
334
335 context.copyFrom(source, context.attachment);
336 context.ContextType = source.ContextType;
337 context.AlgorithmType = source.AlgorithmType;
338
339 if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) {
340 context.attachment.free(context.ContextAttributes); // free rejected attribute blob
341 context.ContextAttributes = oldAttributes; // restore...
342 context.NumberOfAttributes = oldCount; // ... old
343 context.ContextType = oldType; // ... values
344 context.AlgorithmType = oldAlgorithm; // ... in context
345 CssmError::throwMe(err); // tell the caller it failed
346 }
347
348 context.attachment.free(oldAttributes);
349 END_API(CSSM)
350}
351
352
353CSSM_RETURN CSSMAPI
354CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle)
355{
356 BEGIN_API
357 HandleContext &context = enterContext(CCHandle);
358 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit>
359 _(context.attachment, true);
360
361 // ignore error return from CSP event notify (can't decline deletion)
362 context.validateChange(CSSM_CONTEXT_EVENT_DELETE);
363
364 context.destroy(&context, context.attachment);
365 END_API(CSSM)
366}
367
368
369//
370// The GetContextAttribute API is fatally flawed. The standard implies a deep
371// copy of the attribute value, but no release function exists. Instead, we
372// return a shallow copy (sharing structure) which you need not release, but
373// which becomes invalid when the source Context is destroyed.
374//
375CSSM_RETURN CSSMAPI
376CSSM_GetContextAttribute (const CSSM_CONTEXT *Context,
377 uint32 AttributeType,
378 CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute)
379{
380 BEGIN_API
381 CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect
382 Required(ContextAttribute) = Context::required(Context).find(type);
383 END_API(CSSM)
384}
385
386
387CSSM_RETURN CSSMAPI
388CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle,
389 uint32 NumberAttributes,
390 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
391{
392 BEGIN_API
393 HandleContext &context = HandleObject::find<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
394 context.mergeAttributes(ContextAttributes, NumberAttributes);
395 END_API(CSSM)
396}
397
398
399CSSM_RETURN CSSMAPI
400CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle,
401 uint32 NumberOfAttributes,
402 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
403{
404 BEGIN_API
405 if (NumberOfAttributes == 0)
406 return CSSM_OK; // I suppose
407 Required(ContextAttributes); // preflight
408 HandleContext &context = HandleObject::find<HandleContext>(CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
409 for (uint32 n = 0; n < NumberOfAttributes; n++)
410 context.deleteAttribute(ContextAttributes[n].AttributeType);
411 END_API(CSSM)
412}
413
414
415//
416// Miscellaneous odds and ends - these functions just need a wee bit of
417// manual massaging to fit.
418//
419CSSM_RETURN CSSMAPI
420CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle,
421 CSSM_CC_HANDLE *newCCHandle)
422{
423 BEGIN_API
424 HandleContext &context = HandleObject::findAndLock<HandleContext>(ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
425 TransitLock _(context.attachment);
426 HandleContext *newContext =
427 new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm());
428 try {
429 newContext->CSPHandle = context.attachment.handle();
430 newContext->copyFrom(context, context.attachment);
431 context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle());
432 Required(newCCHandle) = newContext->handle();
433 } catch (...) {
434 newContext->destroy(newContext, context.attachment);
435 throw;
436 }
437 END_API(CSSM)
438}
439
440
441CSSM_RETURN CSSMAPI
442CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle,
443 CSSM_CC_HANDLE ccHandle,
444 const CSSM_KEY *key,
445 CSSM_KEY_SIZE_PTR keySize)
446{
447 //@@@ could afford not to lock attachment in have-CC case
448 BEGIN_API
449 Required(keySize);
450 Context *context;
451 CSPAttachment *attachment;
452 if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) {
453 // key specified by CSPHandle and Key
454 attachment = &enterAttachment<CSPAttachment>(CSPHandle);
455 context = NULL;
456 } else {
457 // key specified by ccHandle
458 HandleContext *ctx = &enterContext(ccHandle);
459 try {
460 attachment = &ctx->attachment;
461 context = ctx;
462 CSPHandle = context->CSPHandle;
463 key = &context->get<CssmKey>(CSSM_ATTRIBUTE_KEY,
464 CSSMERR_CSP_INVALID_KEY);
465 } catch (...) {
466 attachment->exit();
467 throw;
468 }
469 }
470 TransitLock _(*attachment);
471 CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle,
472 ccHandle, context, key, keySize);
473 return result;
474 END_API(CSSM)
475}
476
477
478CSSM_RETURN CSSMAPI
479CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle,
480 uint32 ParamBits,
481 CSSM_DATA_PTR Param)
482{
483 BEGIN_API
484 // this function has more subtle locking than usual. Pay attention:
485
486 // (1) Resolve context and ensure attachment exit
487 HandleContext &context = enterContext(CCHandle);
488 StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> _(context.attachment, true);
489
490 // (2) Call CSP, acquiring module safe-lock for a moment (only)
491 CSSM_CONTEXT_ATTRIBUTE_PTR attributes;
492 uint32 count;
493 {
494 StLock<Module, &Module::safeLock, &Module::safeUnlock> _(context.attachment.module);
495 if (CSSM_RETURN err =
496 context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(),
497 CCHandle, &context,
498 ParamBits, Param,
499 &count, &attributes))
500 CssmError::throwMe(err);
501 }
502
503 // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
504 if (count)
505 context.mergeAttributes(attributes, count);
506 // the memory at (attributes, count) belongs to the CSP; don't free it here
507 END_API(CSSM)
508}
509
510
511//
512// Include the auto-generated functions
513//
514#include <derived_src/transition.gen>