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//
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, (uint32_t)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#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//
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);
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
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
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
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
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//
423CSSM_RETURN CSSMAPI
424CSSM_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
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>
520