/ OSX / libsecurity_cssm / lib / transition.cpp
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>