]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cssm/lib/transition.cpp
Security-58286.1.32.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
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 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)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 //
312 CSSM_RETURN CSSMAPI
313 CSSM_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
322 CSSM_RETURN CSSMAPI
323 CSSM_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>((CSSM_HANDLE)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
353 CSSM_RETURN CSSMAPI
354 CSSM_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 //
375 CSSM_RETURN CSSMAPI
376 CSSM_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
387 CSSM_RETURN CSSMAPI
388 CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle,
389 uint32 NumberAttributes,
390 const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
391 {
392 BEGIN_API
393 HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
394 context.mergeAttributes(ContextAttributes, NumberAttributes);
395 END_API(CSSM)
396 }
397
398
399 CSSM_RETURN CSSMAPI
400 CSSM_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>((CSSM_HANDLE)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 //
419 CSSM_RETURN CSSMAPI
420 CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle,
421 CSSM_CC_HANDLE *newCCHandle)
422 {
423 BEGIN_API
424 HandleContext &context = HandleObject::findAndLock<HandleContext>((CSSM_HANDLE)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
441 CSSM_RETURN CSSMAPI
442 CSSM_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
478 CSSM_RETURN CSSMAPI
479 CSSM_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>