cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
int_msg.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Internal Message Handlers *
4 * Copyright Peter Gutmann 1997-2004 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "acl.h"
11  #include "kernel.h"
12 #else
13  #include "crypt.h"
14  #include "kernel/acl.h"
15  #include "kernel/kernel.h"
16 #endif /* Compiler-specific includes */
17 
18 /* A pointer to the kernel data block */
19 
20 static KERNEL_DATA *krnlData = NULL;
21 
22 /****************************************************************************
23 * *
24 * Dependency ACLs *
25 * *
26 ****************************************************************************/
27 
28 /* The ACL tables for each object dependency type */
29 
30 static const DEPENDENCY_ACL FAR_BSS dependencyACLTbl[] = {
31  /* Envelopes and sessions can have conventional encryption and MAC
32  contexts attached */
37 
38  /* PKC contexts can have certs attached and vice versa. Since the
39  certificate can change the permissions on the context, we set the
40  DEP_FLAG_UPDATEDEP flag to ensure that the cert permissions get
41  reflected onto the context */
48 
49  /* Contexts can have crypto devices attached */
52 
53  /* Hardware crypto devices can have PKCS #15 storage objects attached */
56 
57  /* Anything can have the system device attached, since all objects not
58  created via crypto devices are created via the system device */
73 
74  /* End-of-ACL marker */
76  };
77 
78 /****************************************************************************
79 * *
80 * Utility Functions *
81 * *
82 ****************************************************************************/
83 
84 /* Update an action permission. This implements a ratchet that only allows
85  permissions to be made more restrictive after they've initially been set,
86  so that once a permission is set to a given level it can't be set back to
87  a less restrictive one (i.e. it's a write-up policy) */
88 
89 CHECK_RETVAL \
90 static int updateActionPerms( IN_FLAGS( ACTION_PERM ) int currentPerm,
91  IN_FLAGS( ACTION_PERM ) const int newPerm )
92  {
93  int permMask = ACTION_PERM_MASK, i;
94 
95  /* Preconditions: The permissions are valid */
96  REQUIRES( currentPerm > 0 && currentPerm <= ACTION_PERM_ALL_MAX );
97  REQUIRES( newPerm > 0 && newPerm <= ACTION_PERM_ALL_MAX );
98 
99  /* For each permission, update its value if the new setting is more
100  restrictive than the current one. Since smaller values are more
101  restrictive, we can do a simple range comparison and replace the
102  existing value if it's larger than the new one */
103  for( i = 0; i < ACTION_PERM_COUNT; i++ )
104  {
105  if( ( newPerm & permMask ) < ( currentPerm & permMask ) )
106  currentPerm = ( currentPerm & ~permMask ) | ( newPerm & permMask );
107  permMask <<= ACTION_PERM_BITS;
108  }
109 
110  /* Postcondition: The new permission is at least as restrictive (or more
111  so) than the old one */
112  FORALL( i, 0, ACTION_PERM_COUNT,
113  ( currentPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) <= \
114  ( newPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) );
115 
116  return( currentPerm );
117  }
118 
119 /* Update the action permissions for an object based on the composite
120  permissions for it and a dependent object. This is a special-case
121  function because it has to operate with the object table unlocked. This
122  is necessary because the dependent object may be owned by another thread,
123  and if we were to leave the object table locked the two would deadlock if
124  we were sending the object a message while owning the object table at the
125  same time that the other thread was sending a message while owning the
126  object.
127 
128  There is one (rather unlikely) potential race condition possible here in
129  which the object is destroyed and replaced by a new one while the object
130  table is unlocked, so we end up updating the action permissions for a
131  different object. To protect against this, we check the unique ID after
132  we re-lock the object table to make sure that it's the same object */
133 
134 CHECK_RETVAL \
135 static int updateDependentObjectPerms( IN_HANDLE const CRYPT_HANDLE objectHandle,
136  IN_HANDLE const CRYPT_HANDLE dependentObject )
137  {
138  const OBJECT_INFO *objectTable = krnlData->objectTable;
139  const OBJECT_TYPE objectType = objectTable[ objectHandle ].type;
140  const CRYPT_CONTEXT contextHandle = \
141  ( objectType == OBJECT_TYPE_CONTEXT ) ? objectHandle : dependentObject;
142  const CRYPT_CERTIFICATE certHandle = \
143  ( objectType == OBJECT_TYPE_CERTIFICATE ) ? objectHandle : dependentObject;
144  const int uniqueID = objectTable[ objectHandle ].uniqueID;
145  int actionFlags = 0, status;
146  ORIGINAL_INT_VAR( oldPerm, objectTable[ contextHandle ].actionFlags );
147 
148  /* Preconditions: Objects are valid, one is a cert and the other a
149  context, and they aren't dependent on each other (which would create
150  a dependency update loop). Note that these checks aren't performed
151  at runtime since they've already been performed by the calling
152  function, all we're doing here is establishing preconditions rather
153  than performing actual parameter checking */
154  REQUIRES( isValidObject( objectHandle ) );
155  REQUIRES( isValidHandle( dependentObject ) );
156  REQUIRES( ( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT && \
157  objectTable[ dependentObject ].type == OBJECT_TYPE_CERTIFICATE ) || \
158  ( objectTable[ objectHandle ].type == OBJECT_TYPE_CERTIFICATE && \
159  objectTable[ dependentObject ].type == OBJECT_TYPE_CONTEXT ) );
160  REQUIRES( objectTable[ objectHandle ].dependentObject != dependentObject || \
161  objectTable[ dependentObject ].dependentObject != objectHandle );
162 
163  /* Since we're about to send messages to the dependent object, we have to
164  unlock the object table. Since we're about to hand off control to
165  other threads, we clear any object-table references since we can't
166  rely on them to be consistent when we re-lock the table */
167  objectTable = NULL;
168  MUTEX_UNLOCK( objectTable );
169 
170  /* Make sure that we're not making a private key dependent on a cert,
171  which is a public-key object. We check this here rather than having
172  the caller check it because it requires having the object table
173  unlocked */
174  if( objectType == OBJECT_TYPE_CERTIFICATE && \
175  cryptStatusOK( \
176  krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,
178  {
179  MUTEX_LOCK( objectTable );
180  retIntError();
181  }
182 
183  /* For each action type, enable its continued use only if the cert
184  allows it. Because the certificate may not have been fully
185  initialised yet (for example if we're attaching a context to a
186  cert that's in the process of being created), we have to perform
187  a passive-container action-available check that also works on a
188  low-state object rather than a standard active-object check.
189 
190  Because a key with a certificate attached indicates that it's
191  (probably) being used for some function that involves interaction
192  with a relying party (i.e. that it probably has more value than a raw
193  key with no strings attached), we set the action permission to
194  ACTION_PERM_NONE_EXTERNAL rather than allowing ACTION_PERM_ALL. This
195  both ensures that it's only used in a safe manner via the cryptlib
196  internal mechanisms, and makes sure that it's not possible to utilize
197  the signature/encryption duality of some algorithms to create a
198  signature where it's been disallowed */
199  if( cryptStatusOK( krnlSendMessage( certHandle,
201  actionFlags |= \
202  MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );
203  if( cryptStatusOK( krnlSendMessage( certHandle,
205  actionFlags |= \
207  if( cryptStatusOK( krnlSendMessage( certHandle,
209  actionFlags |= \
211  if( cryptStatusOK( krnlSendMessage( certHandle,
213  actionFlags |= \
215  if( cryptStatusOK( krnlSendMessage( certHandle,
217  actionFlags |= \
219  if( cryptStatusOK( krnlSendMessage( certHandle,
221  actionFlags |= \
223 
224  /* Inner precondition: The usage shouldn't be all-zero. Technically it
225  can be since there are bound to be certs out there broken enough to do
226  this, and certainly under the stricter compliance levels this *will*
227  happen, so we make it a warning that's only produced in debug mode */
228  REQUIRES( actionFlags != 0 );
229 
230  /* We're done querying the dependent object, re-lock the object table,
231  reinitialise any references to it, and make sure that the original
232  object hasn't been touched */
233  MUTEX_LOCK( objectTable );
234  objectTable = krnlData->objectTable;
235  if( objectTable[ objectHandle ].uniqueID != uniqueID )
236  return( CRYPT_ERROR_SIGNALLED );
237  status = setPropertyAttribute( contextHandle, CRYPT_IATTRIBUTE_ACTIONPERMS,
238  &actionFlags );
239 
240  /* Postcondition: The new permission is at least as restrictive (or more
241  so) than the old one */
242  FORALL( i, 0, ACTION_PERM_COUNT,
243  ( objectTable[ contextHandle ].actionFlags & ( ACTION_PERM_MASK << ( i * 2 ) ) ) <= \
244  ( ORIGINAL_VALUE( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );
245 
246  return( status );
247  }
248 
249 /****************************************************************************
250 * *
251 * Init/Shutdown Functions *
252 * *
253 ****************************************************************************/
254 
256 int initInternalMsgs( INOUT KERNEL_DATA *krnlDataPtr )
257  {
258  int i;
259 
260  assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
261 
262  /* Perform a consistency check on the object dependency ACL */
263  for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \
264  i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL );
265  i++ )
266  {
267  const DEPENDENCY_ACL *dependencyACL = &dependencyACLTbl[ i ];
268 
269  ENSURES( dependencyACL->type > OBJECT_TYPE_NONE && \
270  dependencyACL->type < OBJECT_TYPE_LAST && \
271  dependencyACL->dType > OBJECT_TYPE_NONE && \
272  dependencyACL->dType < OBJECT_TYPE_LAST );
273  ENSURES( !( dependencyACL->subTypeA & ( SUBTYPE_CLASS_B | \
274  SUBTYPE_CLASS_C ) ) && \
275  !( dependencyACL->subTypeB & ( SUBTYPE_CLASS_A | \
276  SUBTYPE_CLASS_C ) ) && \
277  !( dependencyACL->subTypeC & ( SUBTYPE_CLASS_A | \
278  SUBTYPE_CLASS_B ) ) );
279  ENSURES( !( dependencyACL->dSubTypeA & ( SUBTYPE_CLASS_B | \
280  SUBTYPE_CLASS_C ) ) && \
281  !( dependencyACL->dSubTypeB & ( SUBTYPE_CLASS_A | \
282  SUBTYPE_CLASS_C ) ) && \
283  !( dependencyACL->dSubTypeC & ( SUBTYPE_CLASS_A | \
284  SUBTYPE_CLASS_B ) ) );
285  }
286  ENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );
287 
288  /* Set up the reference to the kernel data block */
289  krnlData = krnlDataPtr;
290 
291  return( CRYPT_OK );
292  }
293 
294 void endInternalMsgs( void )
295  {
296  krnlData = NULL;
297  }
298 
299 /****************************************************************************
300 * *
301 * Get/Set Property Attributes *
302 * *
303 ****************************************************************************/
304 
305 /* Get/set object property attributes. We differentiate between a small
306  number of user-accessible properties such as the object's owner, and
307  properties that are only accessible by cryptlib. The user-accessible
308  properties can be locked, which makes them immutable (at least to being
309  explicitly set, they can still be implicitly altered, for example setting
310  a new object owner decrements the forwardcount value) and also unreadable
311  by the user */
312 
314 int getPropertyAttribute( IN_HANDLE const int objectHandle,
316  OUT_BUFFER_FIXED_C( sizeof( int ) ) void *messageDataPtr )
317  {
318  const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
319  int *valuePtr = ( int * ) messageDataPtr;
320 
321  assert( isWritePtr( messageDataPtr, sizeof( int ) ) );
322 
323  /* Preconditions */
324  REQUIRES( isValidObject( objectHandle ) );
325  REQUIRES( attribute == CRYPT_PROPERTY_OWNER || \
326  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
327  attribute == CRYPT_PROPERTY_LOCKED || \
328  attribute == CRYPT_PROPERTY_USAGECOUNT || \
329  attribute == CRYPT_IATTRIBUTE_TYPE || \
330  attribute == CRYPT_IATTRIBUTE_SUBTYPE || \
331  attribute == CRYPT_IATTRIBUTE_STATUS || \
332  attribute == CRYPT_IATTRIBUTE_INTERNAL || \
333  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
334 
335  switch( attribute )
336  {
337  /* User-accessible properties */
339  /* We allow this to be read since its value can be determined
340  anyway with a trial access */
341  if( !( objectInfoPtr->flags & OBJECT_FLAG_OWNED ) )
342  return( CRYPT_ERROR_NOTINITED );
343 #ifdef USE_THREADS
344  /* A small number of implementations use non-scalar thread IDs,
345  which we can't easily handle when all that we have is an
346  integer handle. However, the need to bind threads to objects
347  only exists because of Win32 security holes arising from the
348  ability to perform thread injection, so this isn't a big
349  issue */
350  #ifdef NONSCALAR_THREADS
351  if( sizeof( objectInfoPtr->objectOwner ) > sizeof( int ) )
352  return( CRYPT_ERROR_NOTAVAIL );
353  #endif /* NONSCALAR_THREADS */
354  *valuePtr = ( int ) objectInfoPtr->objectOwner;
355 #else
356  *valuePtr = 0;
357 #endif /* USE_THREADS */
358  break;
359 
361  if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
362  return( CRYPT_ERROR_PERMISSION );
363  *valuePtr = objectInfoPtr->forwardCount;
364  break;
365 
367  /* We allow this to be read since its value can be determined
368  anyway with a trial write */
369  *( ( BOOLEAN * ) messageDataPtr ) = \
370  ( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED ) ? \
371  TRUE : FALSE;
372  break;
373 
375  *valuePtr = objectInfoPtr->usageCount;
376  break;
377 
378  /* Internal properties */
379  case CRYPT_IATTRIBUTE_TYPE:
380  *valuePtr = objectInfoPtr->type;
381  break;
382 
383  case CRYPT_IATTRIBUTE_SUBTYPE:
384  *valuePtr = objectInfoPtr->subType;
385  break;
386 
387  case CRYPT_IATTRIBUTE_STATUS:
388  *valuePtr = objectInfoPtr->flags & OBJECT_FLAGMASK_STATUS;
389  break;
390 
391  case CRYPT_IATTRIBUTE_INTERNAL:
392  *( ( BOOLEAN * ) messageDataPtr ) = \
393  ( objectInfoPtr->flags & OBJECT_FLAG_INTERNAL ) ? \
394  TRUE : FALSE;
395  break;
396 
397  case CRYPT_IATTRIBUTE_ACTIONPERMS:
398  *valuePtr = objectInfoPtr->actionFlags;
399  break;
400 
401  default:
402  retIntError();
403  }
404 
405  return( CRYPT_OK );
406  }
407 
409 int setPropertyAttribute( IN_HANDLE const int objectHandle,
410  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
411  IN_BUFFER_C( sizeof( int ) ) void *messageDataPtr )
412  {
413  OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
414  const int value = *( ( int * ) messageDataPtr );
415 
416  assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
417 
418  /* Preconditions */
419  REQUIRES( isValidObject( objectHandle ) );
420  REQUIRES( attribute == CRYPT_PROPERTY_HIGHSECURITY || \
421  attribute == CRYPT_PROPERTY_OWNER || \
422  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
423  attribute == CRYPT_PROPERTY_LOCKED || \
424  attribute == CRYPT_PROPERTY_USAGECOUNT || \
425  attribute == CRYPT_IATTRIBUTE_STATUS || \
426  attribute == CRYPT_IATTRIBUTE_INTERNAL || \
427  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS || \
428  attribute == CRYPT_IATTRIBUTE_LOCKED );
429  REQUIRES( objectHandle >= NO_SYSTEM_OBJECTS || \
430  attribute == CRYPT_IATTRIBUTE_STATUS );
431 
432  switch( attribute )
433  {
434  /* User-accessible properties */
436  /* This is a combination property that makes an object owned,
437  non-forwardable, and locked */
438  if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
439  return( CRYPT_ERROR_PERMISSION );
440 #ifdef USE_THREADS
441  objectInfoPtr->objectOwner = THREAD_SELF();
442 #endif /* USE_THREADS */
443  objectInfoPtr->forwardCount = 0;
444  objectInfoPtr->flags |= OBJECT_FLAG_ATTRLOCKED | OBJECT_FLAG_OWNED;
445  break;
446 
448  /* This property can still be changed (even if the object is
449  locked) until the forwarding count drops to zero, otherwise
450  locking the object would prevent any forwarding */
451  if( objectInfoPtr->forwardCount != CRYPT_UNUSED )
452  {
453  if( objectInfoPtr->forwardCount <= 0 )
454  return( CRYPT_ERROR_PERMISSION );
455  objectInfoPtr->forwardCount--;
456  }
457  if( value == CRYPT_UNUSED )
458  objectInfoPtr->flags &= ~OBJECT_FLAG_OWNED;
459  else
460  {
461 #if defined( USE_THREADS )
462  /* See the comment in getPropertyAttribute() about the use
463  of scalar vs. non-scalar thread types */
464  #ifdef NONSCALAR_THREADS
465  if( sizeof( objectInfoPtr->objectOwner ) <= sizeof( int ) )
466  #endif /* NONSCALAR_THREADS */
467  {
468  objectInfoPtr->objectOwner = ( THREAD_HANDLE ) value;
469  objectInfoPtr->flags |= OBJECT_FLAG_OWNED;
470  }
471 #endif /* USE_THREADS */
472  }
473  break;
474 
476  if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
477  return( CRYPT_ERROR_PERMISSION );
478  if( objectInfoPtr->forwardCount != CRYPT_UNUSED && \
479  objectInfoPtr->forwardCount < value )
480  {
481  /* Once set the forward count can only be decreased, never
482  increased */
483  return( CRYPT_ERROR_PERMISSION );
484  }
485  objectInfoPtr->forwardCount = value;
486  break;
487 
489  /* Precondition: This property can only be set to true */
490  REQUIRES( value != FALSE );
491 
492  objectInfoPtr->flags |= OBJECT_FLAG_ATTRLOCKED;
493  break;
494 
496  if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED || \
497  ( objectInfoPtr->usageCount != CRYPT_UNUSED && \
498  objectInfoPtr->usageCount < value ) )
499  {
500  /* Once set the usage count can only be decreased, never
501  increased */
502  return( CRYPT_ERROR_PERMISSION );
503  }
504  objectInfoPtr->usageCount = value;
505  break;
506 
507  /* Internal properties */
508  case CRYPT_IATTRIBUTE_STATUS:
509  /* We're clearing an error/abnormal state */
510  REQUIRES( value == CRYPT_OK );
511 
512  if( isInvalidObjectState( objectHandle ) )
513  {
514  /* If the object is in an abnormal state, we can only (try to)
515  return it back to the normal state after the problem is
516  resolved */
517  REQUIRES( value == CRYPT_OK );
518 
519  /* If we're processing a notification from the caller that
520  the object init is complete and the object was destroyed
521  while it was being created (which sets its state to
522  CRYPT_ERROR_SIGNALLED), tell the caller to convert the
523  message to a destroy object message unless it's a system
524  object, which can't be explicitly destroyed. In this case
525  we just return an error so the cryptlib init fails */
526  if( objectInfoPtr->flags & OBJECT_FLAG_SIGNALLED )
527  {
528  return( ( objectHandle < NO_SYSTEM_OBJECTS ) ?
530  }
531 
532  /* We're transitioning the object to the initialised state */
533  REQUIRES( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED );
534  objectInfoPtr->flags &= ~OBJECT_FLAG_NOTINITED;
535  ENSURES( !( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED ) );
536  break;
537  }
538 
539  /* Postcondition: The object is in a valid state */
540  ENSURES( !isInvalidObjectState( objectHandle ) );
541 
542  break;
543 
544  case CRYPT_IATTRIBUTE_INTERNAL:
545  if( value )
546  {
547  REQUIRES( !( objectInfoPtr->flags & OBJECT_FLAG_INTERNAL ) );
548 
549  objectInfoPtr->flags |= OBJECT_FLAG_INTERNAL;
550  }
551  else
552  {
553  REQUIRES( objectInfoPtr->flags & OBJECT_FLAG_INTERNAL );
554 
555  objectInfoPtr->flags &= ~OBJECT_FLAG_INTERNAL;
556  }
557  break;
558 
559  case CRYPT_IATTRIBUTE_ACTIONPERMS:
560  {
561  const int newPerm = \
562  updateActionPerms( objectInfoPtr->actionFlags, value );
563 
564  if( cryptStatusError( newPerm ) )
565  return( newPerm );
566  objectInfoPtr->actionFlags = newPerm;
567  break;
568  }
569 
570  case CRYPT_IATTRIBUTE_LOCKED:
571  /* Incremement or decrement the object's lock count depending on
572  whether we're locking or unlocking it */
573  if( value )
574  {
575  /* Precondition: The lock count is positive or zero */
576  REQUIRES( objectInfoPtr->lockCount >= 0 );
577 
578  objectInfoPtr->lockCount++;
579 
580  ENSURES( objectInfoPtr->lockCount < MAX_INTLENGTH );
581 #ifdef USE_THREADS
582  objectInfoPtr->lockOwner = THREAD_SELF();
583 #endif /* USE_THREADS */
584  }
585  else
586  {
587  /* Precondition: The lock count is positive */
588  REQUIRES( objectInfoPtr->lockCount > 0 );
589 
590  objectInfoPtr->lockCount--;
591 
592  ENSURES( objectInfoPtr->lockCount >= 0 );
593  }
594 
595  /* If it's a certificate, notify it that it should save/restore
596  its internal state */
597  if( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE )
598  {
599  objectInfoPtr->messageFunction( objectInfoPtr->objectPtr,
600  MESSAGE_CHANGENOTIFY, messageDataPtr,
602  }
603  break;
604 
605  default:
606  retIntError();
607  }
608 
609  return( CRYPT_OK );
610  }
611 
612 /****************************************************************************
613 * *
614 * Update Internal Properties *
615 * *
616 ****************************************************************************/
617 
618 /* Increment/decrement the reference count for an object. This adjusts the
619  reference count as appropriate and sends destroy messages if the reference
620  count goes negative */
621 
622 CHECK_RETVAL \
623 int incRefCount( IN_HANDLE const int objectHandle,
624  STDC_UNUSED const int dummy1,
625  STDC_UNUSED const void *dummy2,
626  STDC_UNUSED const BOOLEAN dummy3 )
627  {
628  OBJECT_INFO *objectTable = krnlData->objectTable;
629  ORIGINAL_INT_VAR( refCt, objectTable[ objectHandle ].referenceCount );
630 
631  /* Preconditions */
632  REQUIRES( isValidObject( objectHandle ) );
633  REQUIRES( objectTable[ objectHandle ].referenceCount >= 0 );
634 
635  /* Increment an object's reference count */
636  objectTable[ objectHandle ].referenceCount++;
637 
638  /* Postcondition: We incremented the reference count and it's now greater
639  than zero (the ground state) */
640  ENSURES( objectTable[ objectHandle ].referenceCount >= 1 );
641  ENSURES( objectTable[ objectHandle ].referenceCount == \
642  ORIGINAL_VALUE( refCt ) + 1 );
643 
644  return( CRYPT_OK );
645  }
646 
647 CHECK_RETVAL \
648 int decRefCount( IN_HANDLE const int objectHandle,
649  STDC_UNUSED const int dummy1,
650  STDC_UNUSED const void *dummy2,
651  const BOOLEAN isInternal )
652  {
653  OBJECT_INFO *objectTable = krnlData->objectTable;
654  int status;
655  ORIGINAL_INT_VAR( refCt, objectTable[ objectHandle ].referenceCount );
656 
657  /* Preconditions */
658  REQUIRES( isValidObject( objectHandle ) );
659 
660  /* If the message is coming from an external source (in other words if
661  it's an external caller destroying the object), make the object
662  internal. This marks it as invalid for any external access, so that
663  to the caller it looks like it's been destroyed even if its reference
664  count keeps it active */
665  if( !isInternal )
666  {
667  REQUIRES( !isInternalObject( objectHandle ) );
668 
669  objectTable[ objectHandle ].flags |= OBJECT_FLAG_INTERNAL;
670 
671  ENSURES( isInternalObject( objectHandle ) );
672  }
673 
674  /* Decrement an object's reference count */
675  if( objectTable[ objectHandle ].referenceCount > 0 )
676  {
677  objectTable[ objectHandle ].referenceCount--;
678 
679  /* Postconditions: We decremented the reference count and it's
680  greater than or equal to zero (the ground state) */
681  ENSURES( objectTable[ objectHandle ].referenceCount >= 0 );
682  ENSURES( objectTable[ objectHandle ].referenceCount == \
683  ORIGINAL_VALUE( refCt ) - 1 );
684 
685  return( CRYPT_OK );
686  }
687 
688  /* We're already at a single reference, destroy the object. Since this
689  can entail arbitrary amounts of processing during the object shutdown
690  phase, we have to unlock the object table around the call */
691  MUTEX_UNLOCK( objectTable );
692  status = krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );
693  MUTEX_LOCK( objectTable );
694 
695  return( status );
696  }
697 
698 /* Get/set dependent objects for an object */
699 
701 int getDependentObject( IN_HANDLE const int objectHandle,
702  const int targetType,
703  IN_BUFFER_C( sizeof( int ) ) \
704  const void *messageDataPtr,
705  /* This is a bit of a lie since we actually
706  return the dependent object through this
707  pointer, however making it non-const means
708  that we'd have to also un-const every other
709  use of this parameter in all other functions
710  accessed via this function pointer */
711  STDC_UNUSED const BOOLEAN dummy )
712  {
713  int *valuePtr = ( int * ) messageDataPtr, localObjectHandle;
714 
715  assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
716 
717  /* Preconditions */
718  REQUIRES( isValidObject( objectHandle ) );
719  REQUIRES( isValidType( targetType ) );
720 
721  /* Clear return value */
722  *valuePtr = CRYPT_ERROR;
723 
724  localObjectHandle = findTargetType( objectHandle, targetType );
725  if( cryptStatusError( localObjectHandle ) )
726  {
727  /* Postconditions: No dependent object found */
728  ENSURES( *valuePtr == CRYPT_ERROR );
729 
730  return( CRYPT_ARGERROR_OBJECT );
731  }
732  *valuePtr = localObjectHandle;
733 
734  /* Postconditions: We found a dependent object */
735  ENSURES( isValidObject( *valuePtr ) && \
736  isSameOwningObject( *valuePtr, objectHandle ) );
737 
738  return( CRYPT_OK );
739  }
740 
742 int setDependentObject( IN_HANDLE const int objectHandle,
743  IN_ENUM( SETDEP_OPTION ) const int option,
744  IN_BUFFER_C( sizeof( int ) ) \
745  const void *messageDataPtr,
746  STDC_UNUSED const BOOLEAN dummy )
747  {
748  OBJECT_INFO *objectTable = krnlData->objectTable;
749  OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
750  const OBJECT_INFO *dependentObjectInfoPtr;
751  const int dependentObject = *( ( int * ) messageDataPtr );
752  const DEPENDENCY_ACL *dependencyACL = NULL;
753  int *objectHandlePtr, i, status;
754 
755  assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
756 
757  /* Preconditions: Parameters are valid */
758  REQUIRES( isValidObject( objectHandle ) );
759  REQUIRES( option == SETDEP_OPTION_NOINCREF || \
760  option == SETDEP_OPTION_INCREF );
761  REQUIRES( isValidHandle( dependentObject ) );
762 
763  /* Make sure that the object is valid, it may have been signalled after
764  the message was sent */
765  if( !isValidObject( dependentObject ) )
766  return( CRYPT_ERROR_SIGNALLED );
767  dependentObjectInfoPtr = &objectTable[ dependentObject ];
768  if( dependentObjectInfoPtr->type == OBJECT_TYPE_DEVICE )
769  objectHandlePtr = &objectInfoPtr->dependentDevice;
770  else
771  objectHandlePtr = &objectInfoPtr->dependentObject;
772 
773  /* Basic validity checks: There can't already be a dependent object set */
774  if( *objectHandlePtr != CRYPT_ERROR )
775  {
776  /* There's already a dependent object present and we're trying to
777  overwrite it with a new one, something is seriously wrong */
778  retIntError();
779  }
780 
781  /* More complex validity checks to ensure that the object table is
782  consistent: The object isn't already dependent on the dependent object
783  (making the dependent object then dependent on the object would
784  create a loop), and the object won't be dependent on its own object
785  type unless it's a device dependent on the system device */
786  if( ( ( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ? \
787  dependentObjectInfoPtr->dependentDevice : \
788  dependentObjectInfoPtr->dependentObject ) == objectHandle ) || \
789  ( objectInfoPtr->type == dependentObjectInfoPtr->type && \
790  dependentObject != SYSTEM_OBJECT_HANDLE ) )
791  retIntError();
792 
793  /* Find the dependency ACL entry for this object/dependent object
794  combination. Since there can be more than one dependent object
795  type for an object, we check subtypes as well */
796  for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \
797  i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL );
798  i++ )
799  {
800  if( dependencyACLTbl[ i ].type == objectInfoPtr->type && \
801  dependencyACLTbl[ i ].dType == dependentObjectInfoPtr->type && \
802  ( isValidSubtype( dependencyACLTbl[ i ].dSubTypeA, \
803  dependentObjectInfoPtr->subType ) || \
804  isValidSubtype( dependencyACLTbl[ i ].dSubTypeB, \
805  dependentObjectInfoPtr->subType ) || \
806  isValidSubtype( dependencyACLTbl[ i ].dSubTypeC, \
807  dependentObjectInfoPtr->subType ) ) )
808  {
809  dependencyACL = &dependencyACLTbl[ i ];
810  break;
811  }
812  }
813  ENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );
814  ENSURES( dependencyACL != NULL );
815 
816  /* Inner precondition: We have the appropriate ACL for this combination
817  of object and dependent object */
818  REQUIRES( dependencyACL->type == objectInfoPtr->type && \
819  dependencyACL->dType == dependentObjectInfoPtr->type && \
820  ( isValidSubtype( dependencyACL->dSubTypeA, \
821  dependentObjectInfoPtr->subType ) || \
822  isValidSubtype( dependencyACL->dSubTypeB, \
823  dependentObjectInfoPtr->subType ) || \
824  isValidSubtype( dependencyACL->dSubTypeC, \
825  dependentObjectInfoPtr->subType ) ) );
826 
827  /* Type-specific checks. For PKC context -> cert and cert -> PKC context
828  attaches we should also check that the primary PKC object is a
829  private-key object and the dependent PKC object is a public-key object
830  to catch things like a private key depending on a (public-key) cert,
831  however this requires unlocking the object table in order to send the
832  context a check message. Since this requires additional precautions,
833  we leave it for updateDependentObjectPerms(), which has to unlock the
834  table for its own update operations */
835  ENSURES( isValidSubtype( dependencyACL->subTypeA, \
836  objectInfoPtr->subType ) || \
837  isValidSubtype( dependencyACL->subTypeB, \
838  objectInfoPtr->subType ) || \
839  isValidSubtype( dependencyACL->subTypeC, \
840  objectInfoPtr->subType ) );
841  ENSURES( isValidSubtype( dependencyACL->dSubTypeA, \
842  dependentObjectInfoPtr->subType ) || \
843  isValidSubtype( dependencyACL->dSubTypeB, \
844  dependentObjectInfoPtr->subType ) || \
845  isValidSubtype( dependencyACL->dSubTypeC, \
846  dependentObjectInfoPtr->subType ) );
847 
848  /* Inner precondition */
849  REQUIRES( *objectHandlePtr == CRYPT_ERROR );
850  REQUIRES( isSameOwningObject( objectHandle, dependentObject ) );
851 
852  /* Certs and contexts have special relationships in that the cert can
853  constrain the use of the context beyond its normal level. If we're
854  performing this type of object attachment, we have to adjust one
855  object's behaviour based on the permissions of the other one. We do
856  this before we increment the reference count because the latter can
857  never fail so we don't have to worry about undoing the update */
858  if( dependencyACL->flags & DEP_FLAG_UPDATEDEP )
859  {
860  status = updateDependentObjectPerms( objectHandle, dependentObject );
861  if( cryptStatusError( status ) )
862  return( status );
863  }
864 
865  /* Update the dependent object's reference count if required and record
866  the new status in the object table. Dependent objects can be
867  established in one of two ways, by taking an existing object and
868  attaching it to another object (which increments its reference count,
869  since it's now being referred to by the original owner and by the
870  object it's attached to), or by creating a new object and attaching
871  it to another object (which doesn't increment the reference count
872  since it's only referred to by the controlling object). An example of
873  the former operation is adding a context from a cert request to a cert
874  (the cert request is referenced by both the caller and the cert), an
875  example of the latter operation is attaching a data-only cert to a
876  context (the cert is only referenced by the context) */
877  if( option == SETDEP_OPTION_INCREF )
878  {
879  status = incRefCount( dependentObject, 0, NULL, TRUE );
880  if( cryptStatusError( status ) )
881  return( status );
882  }
883  *objectHandlePtr = dependentObject;
884 
885  /* Postconditions */
886  ENSURES( isValidObject( *objectHandlePtr ) && \
887  isSameOwningObject( objectHandle, *objectHandlePtr ) );
888 
889  return( CRYPT_OK );
890  }
891 
892 /* Clone an object. The older copy-on-write implementation didn't actually
893  do anything at this point except check that the access was valid and set
894  the aliased and cloned flags to indicate that the object needed to be
895  handled specially if a write access was made to it, but with the kernel
896  tracking instance data we can do a copy immediately to create two
897  distinct objects */
898 
899 CHECK_RETVAL \
900 int cloneObject( IN_HANDLE const int objectHandle,
901  IN_HANDLE const int clonedObject,
902  STDC_UNUSED const void *dummy1,
903  STDC_UNUSED const BOOLEAN dummy2 )
904  {
905  OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
906  OBJECT_INFO *clonedObjectInfoPtr = &krnlData->objectTable[ clonedObject ];
907  int actionFlags, status;
908 
909  /* Preconditions */
910  REQUIRES( isValidObject( objectHandle ) && \
911  objectHandle >= NO_SYSTEM_OBJECTS );
912  REQUIRES( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );
913  REQUIRES( isValidObject( clonedObject ) && \
914  clonedObject >= NO_SYSTEM_OBJECTS );
915  REQUIRES( clonedObjectInfoPtr->type == OBJECT_TYPE_CONTEXT );
916  REQUIRES( objectHandle != clonedObject );
917 
918  /* Make sure that the original object is in the high state. This will
919  have been checked by the caller anyway, but we check again here to
920  make sure */
921  if( !isInHighState( objectHandle ) )
922  return( CRYPT_ERROR_NOTINITED );
923 
924  /* Cloning of non-native contexts is somewhat complex because we usually
925  can't clone a device object, so we have to detect requests to clone
926  these objects and increment their reference count instead. This
927  isn't a major problem because cryptlib always creates native contexts
928  for clonable algorithms, if the user explicitly overrides this by
929  using their own device-specific context then the usage will usually
930  be create, add to envelope, destroy, so there's no need to clone the
931  context anyway. The only that time there's a potential problem is if
932  they override the use of native contexts by adding device contexts to
933  multiple envelopes, but in that case it's assumed that they'll be
934  aware of potential problems with this approach */
935  if( objectInfoPtr->dependentDevice != SYSTEM_OBJECT_HANDLE )
936  return( incRefCount( objectHandle, 0, NULL, TRUE ) );
937 
938  /* Since this is an internal-use-only object, lock down the action
939  permissions so that only encryption and hash actions from internal
940  sources are allowed (assuming they were allowed to begin with).
941  Keygen is disabled entirely (there should already be a key loaded),
942  and signing isn't possible with a non-PKC object anyway. This takes
943  advantage of the ratchet enforced for the action permissions, which
944  can only make them more restrictive than the existing permissions, to
945  avoid having to read and modify each permission individually */
946  actionFlags = \
947  MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
948  MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
949  MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_NONE_EXTERNAL );
950  status = setPropertyAttribute( clonedObject, CRYPT_IATTRIBUTE_ACTIONPERMS,
951  &actionFlags );
952  if( cryptStatusError( status ) )
953  return( status );
954 
955  /* Postcondition: The cloned object can only be used internally */
956  ENSURES( ( clonedObjectInfoPtr->actionFlags & \
958 
959  /* Inner precondition: The instance data is valid and ready to be
960  copied */
961  assert( isWritePtr( objectInfoPtr->objectPtr, objectInfoPtr->objectSize ) );
962  assert( isWritePtr( clonedObjectInfoPtr->objectPtr,
963  clonedObjectInfoPtr->objectSize ) );
964  REQUIRES( objectInfoPtr->objectSize == clonedObjectInfoPtr->objectSize );
965 
966  /* Copy across the object contents and reset any instance-specific
967  information. We only update the owning object if required, in
968  almost all cases this will be the system device so there's no need
969  to perform the update */
970  memcpy( clonedObjectInfoPtr->objectPtr, objectInfoPtr->objectPtr,
971  objectInfoPtr->objectSize );
972  objectInfoPtr->messageFunction( clonedObjectInfoPtr->objectPtr,
974  ( MESSAGE_CAST ) &clonedObject,
976  if( objectInfoPtr->owner != clonedObjectInfoPtr->owner )
977  {
978  objectInfoPtr->messageFunction( clonedObjectInfoPtr->objectPtr,
980  &clonedObjectInfoPtr->owner,
982  }
983 
984  /* We've copied across the object's state, the cloned object is now
985  initialised ready for use */
986  clonedObjectInfoPtr->flags |= OBJECT_FLAG_HIGH;
987 
988  return( CRYPT_OK );
989  }