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 */
33 	MK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, ST_NONE, \
34 			   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE ),
35 	MK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_NONE, ST_SESS_ANY, \
36 			   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE ),
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 */
42 	MK_DEPACL_EX( OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE, ST_NONE, \
43 				  OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE,
44 				  DEP_FLAG_UPDATEDEP ),
45 	MK_DEPACL_EX( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE, \
46 				  OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE, ST_NONE,
47 				  DEP_FLAG_UPDATEDEP ),
48 
49 	/* Contexts can have crypto devices attached */
50 	MK_DEPACL( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, ST_NONE, \
51 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_ANY_STD, ST_NONE ),
52 
53 	/* Hardware crypto devices can have PKCS #15 storage objects attached */
54 	MK_DEPACL( OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_HW, ST_NONE, \
55 			   OBJECT_TYPE_KEYSET, ST_NONE, ST_KEYSET_FILE, ST_NONE ),
56 
57 	/* Anything can have the system device attached, since all objects not
58 	   created via crypto devices are created via the system device */
59 	MK_DEPACL( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, ST_NONE, \
60 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
61 	MK_DEPACL( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE, \
62 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
63 	MK_DEPACL( OBJECT_TYPE_KEYSET, ST_NONE, ST_KEYSET_ANY, ST_NONE, \
64 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
65 	MK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, ST_NONE, \
66 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
67 	MK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_NONE, ST_SESS_ANY, \
68 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
69 	MK_DEPACL( OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_ANY_STD, ST_NONE, \
70 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
71 	MK_DEPACL( OBJECT_TYPE_USER, ST_NONE, ST_NONE, ST_USER_ANY, \
72 			   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),
73 
74 	/* End-of-ACL marker */
75 	MK_DEPACL_END(), MK_DEPACL_END()
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 \
updateActionPerms(IN_FLAGS (ACTION_PERM)int currentPerm,IN_FLAGS (ACTION_PERM)const int newPerm)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 \
updateDependentObjectPerms(IN_HANDLE const CRYPT_HANDLE objectHandle,IN_HANDLE const CRYPT_HANDLE dependentObject)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 		/* Note that the above macro gives initialised-but-not-referenced
148 		   warnings in release builds */
149 
150 	/* Preconditions: Objects are valid, one is a cert and the other a
151 	   context, and they aren't dependent on each other (which would create
152 	   a dependency update loop).  Note that these checks aren't performed
153 	   at runtime since they've already been performed by the calling
154 	   function, all we're doing here is establishing preconditions rather
155 	   than performing actual parameter checking */
156 	REQUIRES( isValidObject( objectHandle ) );
157 	REQUIRES( isValidHandle( dependentObject ) );
158 	REQUIRES( ( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT && \
159 				objectTable[ dependentObject ].type == OBJECT_TYPE_CERTIFICATE ) || \
160 			  ( objectTable[ objectHandle ].type == OBJECT_TYPE_CERTIFICATE && \
161 				objectTable[ dependentObject ].type == OBJECT_TYPE_CONTEXT ) );
162 	REQUIRES( objectTable[ objectHandle ].dependentObject != dependentObject || \
163 			  objectTable[ dependentObject ].dependentObject != objectHandle );
164 
165 	/* Since we're about to send messages to the dependent object, we have to
166 	   unlock the object table.  Since we're about to hand off control to
167 	   other threads, we clear any object-table references since we can't
168 	   rely on them to be consistent when we re-lock the table */
169 	objectTable = NULL;
170 	MUTEX_UNLOCK( objectTable );
171 
172 	/* Make sure that we're not making a private key dependent on a cert,
173 	   which is a public-key object.  We check this here rather than having
174 	   the caller check it because it requires having the object table
175 	   unlocked */
176 	if( objectType == OBJECT_TYPE_CERTIFICATE && \
177 		cryptStatusOK( \
178 			krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,
179 							 MESSAGE_CHECK_PKC_PRIVATE ) ) )
180 		{
181 		MUTEX_LOCK( objectTable );
182 		retIntError();
183 		}
184 
185 	/* For each action type, enable its continued use only if the cert
186 	   allows it.  Because the certificate may not have been fully
187 	   initialised yet (for example if we're attaching a context to a
188 	   cert that's in the process of being created), we have to perform
189 	   a passive-container action-available check that also works on a
190 	   low-state object rather than a standard active-object check.
191 
192 	   Because a key with a certificate attached indicates that it's
193 	   (probably) being used for some function that involves interaction
194 	   with a relying party (i.e. that it probably has more value than a raw
195 	   key with no strings attached), we set the action permission to
196 	   ACTION_PERM_NONE_EXTERNAL rather than allowing ACTION_PERM_ALL.  This
197 	   both ensures that it's only used in a safe manner via the cryptlib
198 	   internal mechanisms, and makes sure that it's not possible to utilize
199 	   the signature/encryption duality of some algorithms to create a
200 	   signature where it's been disallowed */
201 	if( cryptStatusOK( krnlSendMessage( certHandle,
202 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGN_AVAIL ) ) )
203 		actionFlags |= \
204 			MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );
205 	if( cryptStatusOK( krnlSendMessage( certHandle,
206 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGCHECK_AVAIL ) ) )
207 		actionFlags |= \
208 			MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL );
209 	if( cryptStatusOK( krnlSendMessage( certHandle,
210 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_ENCRYPT_AVAIL ) ) )
211 		actionFlags |= \
212 			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
213 	if( cryptStatusOK( krnlSendMessage( certHandle,
214 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_DECRYPT_AVAIL ) ) )
215 		actionFlags |= \
216 			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
217 	if( cryptStatusOK( krnlSendMessage( certHandle,
218 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL ) ) )
219 		actionFlags |= \
220 			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
221 	if( cryptStatusOK( krnlSendMessage( certHandle,
222 				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL ) ) )
223 		actionFlags |= \
224 			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
225 
226 	/* Inner precondition: The usage shouldn't be all-zero.  Technically it
227 	   can be since there are bound to be certs out there broken enough to do
228 	   this, and certainly under the stricter compliance levels this *will*
229 	   happen, so we make it a warning that's only produced in debug mode */
230 	if( actionFlags == 0 )
231 		{
232 		DEBUG_DIAG(( "Object %s is constrained by its associated "
233 					 "certificate object to not allow any actions",
234 					 getObjectDescriptionNT( objectHandle ) ));
235 		assert_nofuzz( DEBUG_WARN );
236 		}
237 
238 	/* We're done querying the dependent object, re-lock the object table,
239 	   reinitialise any references to it, and make sure that the original
240 	   object hasn't been touched */
241 	MUTEX_LOCK( objectTable );
242 	objectTable = krnlData->objectTable;
243 	if( objectTable[ objectHandle ].uniqueID != uniqueID )
244 		return( CRYPT_ERROR_SIGNALLED );
245 	if( actionFlags == 0 )
246 		{
247 		/* See the comment above, we can't continue at this point because we
248 		   can't set the action permissions attribute to nothing */
249 		return( CRYPT_ERROR_NOTAVAIL );
250 		}
251 	status = setPropertyAttribute( contextHandle, CRYPT_IATTRIBUTE_ACTIONPERMS,
252 								   &actionFlags );
253 
254 	/* Postcondition: The new permission is at least as restrictive (or more
255 	   so) than the old one */
256 	FORALL( i, 0, ACTION_PERM_COUNT,
257 			( objectTable[ contextHandle ].actionFlags & ( ACTION_PERM_MASK << ( i * 2 ) ) ) <= \
258 			( ORIGINAL_VALUE( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );
259 
260 	return( status );
261 	}
262 
263 
264 /* Convert an internal object reference to an external one */
265 
266 CHECK_RETVAL \
convertIntToExtRef(IN_HANDLE const int objectHandle)267 int convertIntToExtRef( IN_HANDLE const int objectHandle )
268 	{
269 	int status;
270 
271 	/* Preconditions */
272 	REQUIRES( isValidObject( objectHandle ) );
273 
274 	/* Convert at least one internal reference to the object to an external
275 	   one */
276 	status = incRefCount( objectHandle, 0, NULL, FALSE );
277 	if( cryptStatusOK( status ) )
278 		status = decRefCount( objectHandle, 0, NULL, TRUE );
279 	if( cryptStatusOK( status ) )
280 		return( status );
281 
282 	/* Recovering from an error at this point is tricky, it's a shouldn't-
283 	   occur condition in any case but if it does occur then the fact that
284 	   the object reference is in an unclear state means we can't do a
285 	   straight decRef().  The safest option seems to be to explicitly
286 	   destroy it, which usually produces the correct result but in the case
287 	   of something like fetching a certificate from a session or envelope
288 	   will lead to the session/envelope's reference being destroyed as
289 	   well */
290 	( void ) krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );
291 
292 	return( status );
293 	}
294 
295 /****************************************************************************
296 *																			*
297 *							Init/Shutdown Functions							*
298 *																			*
299 ****************************************************************************/
300 
301 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initInternalMsgs(INOUT KERNEL_DATA * krnlDataPtr)302 int initInternalMsgs( INOUT KERNEL_DATA *krnlDataPtr )
303 	{
304 	int i;
305 
306 	assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
307 
308 	/* If we're running a fuzzing build, skip the lengthy self-checks */
309 #ifdef CONFIG_FUZZ
310 	krnlData = krnlDataPtr;
311 	return( CRYPT_OK );
312 #endif /* CONFIG_FUZZ */
313 
314 	/* Perform a consistency check on the object dependency ACL */
315 	for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \
316 				i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL );
317 		 i++ )
318 		{
319 		const DEPENDENCY_ACL *dependencyACL = &dependencyACLTbl[ i ];
320 
321 		ENSURES( dependencyACL->type > OBJECT_TYPE_NONE && \
322 				 dependencyACL->type < OBJECT_TYPE_LAST && \
323 				 dependencyACL->dType > OBJECT_TYPE_NONE && \
324 				 dependencyACL->dType < OBJECT_TYPE_LAST );
325 		ENSURES( !( dependencyACL->subTypeA & ( SUBTYPE_CLASS_B | \
326 												SUBTYPE_CLASS_C ) ) && \
327 				 !( dependencyACL->subTypeB & ( SUBTYPE_CLASS_A | \
328 												SUBTYPE_CLASS_C ) ) && \
329 				 !( dependencyACL->subTypeC & ( SUBTYPE_CLASS_A | \
330 												SUBTYPE_CLASS_B ) ) );
331 		ENSURES( !( dependencyACL->dSubTypeA & ( SUBTYPE_CLASS_B | \
332 												 SUBTYPE_CLASS_C ) ) && \
333 				 !( dependencyACL->dSubTypeB & ( SUBTYPE_CLASS_A | \
334 												 SUBTYPE_CLASS_C ) ) && \
335 				 !( dependencyACL->dSubTypeC & ( SUBTYPE_CLASS_A | \
336 												 SUBTYPE_CLASS_B ) ) );
337 		}
338 	ENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );
339 
340 	/* Set up the reference to the kernel data block */
341 	krnlData = krnlDataPtr;
342 
343 	return( CRYPT_OK );
344 	}
345 
endInternalMsgs(void)346 void endInternalMsgs( void )
347 	{
348 	krnlData = NULL;
349 	}
350 
351 /****************************************************************************
352 *																			*
353 *							Get/Set Property Attributes						*
354 *																			*
355 ****************************************************************************/
356 
357 /* Get/set object property attributes.  We differentiate between a small
358    number of user-accessible properties such as the object's owner, and
359    properties that are only accessible by cryptlib.  The user-accessible
360    properties can be locked, which makes them immutable (at least to being
361    explicitly set, they can still be implicitly altered, for example setting
362    a new object owner decrements the forwardcount value) and also unreadable
363    by the user */
364 
365 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
getPropertyAttribute(IN_HANDLE const int objectHandle,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,OUT_BUFFER_FIXED_C (sizeof (int))void * messageDataPtr)366 int getPropertyAttribute( IN_HANDLE const int objectHandle,
367 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
368 						  OUT_BUFFER_FIXED_C( sizeof( int ) ) void *messageDataPtr )
369 	{
370 	const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
371 	int *valuePtr = ( int * ) messageDataPtr;
372 
373 	assert( isWritePtr( messageDataPtr, sizeof( int ) ) );
374 
375 	/* Preconditions */
376 	REQUIRES( isValidObject( objectHandle ) );
377 	REQUIRES( attribute == CRYPT_PROPERTY_OWNER || \
378 			  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
379 			  attribute == CRYPT_PROPERTY_LOCKED || \
380 			  attribute == CRYPT_PROPERTY_USAGECOUNT || \
381 			  attribute == CRYPT_IATTRIBUTE_TYPE || \
382 			  attribute == CRYPT_IATTRIBUTE_SUBTYPE || \
383 			  attribute == CRYPT_IATTRIBUTE_STATUS || \
384 			  attribute == CRYPT_IATTRIBUTE_INTERNAL || \
385 			  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
386 
387 	switch( attribute )
388 		{
389 		/* User-accessible properties */
390 		case CRYPT_PROPERTY_OWNER:
391 			/* We allow this to be read since its value can be determined
392 			   anyway with a trial access */
393 			if( !( objectInfoPtr->flags & OBJECT_FLAG_OWNED ) )
394 				return( CRYPT_ERROR_NOTINITED );
395 #ifdef USE_THREADS
396 			/* A small number of implementations use non-scalar thread IDs,
397 			   which we can't easily handle when all that we have is an
398 			   integer handle.  However, the need to bind threads to objects
399 			   only exists because of Win32 security holes arising from the
400 			   ability to perform thread injection, so this isn't a big
401 			   issue */
402   #ifdef NONSCALAR_HANDLES
403 			if( sizeof( objectInfoPtr->objectOwner ) > sizeof( int ) )
404 				return( CRYPT_ERROR_NOTAVAIL );
405   #endif /* NONSCALAR_HANDLES */
406 			*valuePtr = ( int ) objectInfoPtr->objectOwner;
407 #else
408 			*valuePtr = 0;
409 #endif /* USE_THREADS */
410 			break;
411 
412 		case CRYPT_PROPERTY_FORWARDCOUNT:
413 			if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
414 				return( CRYPT_ERROR_PERMISSION );
415 			*valuePtr = objectInfoPtr->forwardCount;
416 			break;
417 
418 		case CRYPT_PROPERTY_LOCKED:
419 			/* We allow this to be read since its value can be determined
420 			   anyway with a trial write */
421 			*( ( BOOLEAN * ) messageDataPtr ) = \
422 						( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED ) ? \
423 						TRUE : FALSE;
424 			break;
425 
426 		case CRYPT_PROPERTY_USAGECOUNT:
427 			*valuePtr = objectInfoPtr->usageCount;
428 			break;
429 
430 		/* Internal properties */
431 		case CRYPT_IATTRIBUTE_TYPE:
432 			*valuePtr = objectInfoPtr->type;
433 			break;
434 
435 		case CRYPT_IATTRIBUTE_SUBTYPE:
436 			*valuePtr = objectInfoPtr->subType;
437 			break;
438 
439 		case CRYPT_IATTRIBUTE_STATUS:
440 			*valuePtr = objectInfoPtr->flags & OBJECT_FLAGMASK_STATUS;
441 			break;
442 
443 		case CRYPT_IATTRIBUTE_INTERNAL:
444 			*( ( BOOLEAN * ) messageDataPtr ) = \
445 					( objectInfoPtr->flags & OBJECT_FLAG_INTERNAL ) ? \
446 					TRUE : FALSE;
447 			break;
448 
449 		case CRYPT_IATTRIBUTE_ACTIONPERMS:
450 			*valuePtr = objectInfoPtr->actionFlags;
451 			break;
452 
453 		default:
454 			retIntError();
455 		}
456 
457 	return( CRYPT_OK );
458 	}
459 
460 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
setPropertyAttribute(IN_HANDLE const int objectHandle,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,IN_BUFFER_C (sizeof (int))void * messageDataPtr)461 int setPropertyAttribute( IN_HANDLE const int objectHandle,
462 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
463 						  IN_BUFFER_C( sizeof( int ) ) void *messageDataPtr )
464 	{
465 	OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
466 	const int value = *( ( int * ) messageDataPtr );
467 
468 	assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
469 
470 	/* Preconditions */
471 	REQUIRES( isValidObject( objectHandle ) );
472 	REQUIRES( attribute == CRYPT_PROPERTY_HIGHSECURITY || \
473 			  attribute == CRYPT_PROPERTY_OWNER || \
474 			  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
475 			  attribute == CRYPT_PROPERTY_LOCKED || \
476 			  attribute == CRYPT_PROPERTY_USAGECOUNT || \
477 			  attribute == CRYPT_IATTRIBUTE_STATUS || \
478 			  attribute == CRYPT_IATTRIBUTE_INTERNAL || \
479 			  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS || \
480 			  attribute == CRYPT_IATTRIBUTE_LOCKED );
481 	REQUIRES( objectHandle >= NO_SYSTEM_OBJECTS || \
482 			  attribute == CRYPT_IATTRIBUTE_STATUS );
483 
484 	switch( attribute )
485 		{
486 		/* User-accessible properties */
487 		case CRYPT_PROPERTY_HIGHSECURITY:
488 			/* This is a combination property that makes an object owned,
489 			   non-forwardable, and locked */
490 			if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
491 				return( CRYPT_ERROR_PERMISSION );
492 #ifdef USE_THREADS
493 			objectInfoPtr->objectOwner = THREAD_SELF();
494 #endif /* USE_THREADS */
495 			objectInfoPtr->forwardCount = 0;
496 			objectInfoPtr->flags |= OBJECT_FLAG_ATTRLOCKED | OBJECT_FLAG_OWNED;
497 			break;
498 
499 		case CRYPT_PROPERTY_OWNER:
500 			/* This property can still be changed (even if the object is
501 			   locked) until the forwarding count drops to zero, otherwise
502 			   locking the object would prevent any forwarding */
503 			if( objectInfoPtr->forwardCount != CRYPT_UNUSED )
504 				{
505 				if( objectInfoPtr->forwardCount <= 0 )
506 					return( CRYPT_ERROR_PERMISSION );
507 				objectInfoPtr->forwardCount--;
508 				}
509 			if( value == CRYPT_UNUSED )
510 				objectInfoPtr->flags &= ~OBJECT_FLAG_OWNED;
511 			else
512 				{
513 #if defined( USE_THREADS )
514 				/* See the comment in getPropertyAttribute() about the use
515 				   of scalar vs. non-scalar thread types */
516   #ifdef NONSCALAR_HANDLES
517 				if( sizeof( objectInfoPtr->objectOwner ) <= sizeof( int ) )
518   #endif /* NONSCALAR_HANDLES */
519 					{
520 					objectInfoPtr->objectOwner = ( THREAD_HANDLE ) value;
521 					objectInfoPtr->flags |= OBJECT_FLAG_OWNED;
522 					}
523 #endif /* USE_THREADS */
524 				}
525 			break;
526 
527 		case CRYPT_PROPERTY_FORWARDCOUNT:
528 			if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
529 				return( CRYPT_ERROR_PERMISSION );
530 			if( objectInfoPtr->forwardCount != CRYPT_UNUSED && \
531 				objectInfoPtr->forwardCount < value )
532 				{
533 				/* Once set the forward count can only be decreased, never
534 				   increased */
535 				return( CRYPT_ERROR_PERMISSION );
536 				}
537 			objectInfoPtr->forwardCount = value;
538 			break;
539 
540 		case CRYPT_PROPERTY_LOCKED:
541 			/* Precondition: This property can only be set to true */
542 			REQUIRES( value != FALSE );
543 
544 			objectInfoPtr->flags |= OBJECT_FLAG_ATTRLOCKED;
545 			break;
546 
547 		case CRYPT_PROPERTY_USAGECOUNT:
548 			if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED || \
549 				( objectInfoPtr->usageCount != CRYPT_UNUSED && \
550 				  objectInfoPtr->usageCount < value ) )
551 				{
552 				/* Once set the usage count can only be decreased, never
553 				   increased */
554 				return( CRYPT_ERROR_PERMISSION );
555 				}
556 			objectInfoPtr->usageCount = value;
557 			break;
558 
559 		/* Internal properties */
560 		case CRYPT_IATTRIBUTE_STATUS:
561 			/* We're clearing an error/abnormal state */
562 			REQUIRES( value == CRYPT_OK );
563 
564 			if( isInvalidObjectState( objectHandle ) )
565 				{
566 				/* If the object is in an abnormal state, we can only (try to)
567 				   return it back to the normal state after the problem is
568 				   resolved */
569 				REQUIRES( value == CRYPT_OK );
570 
571 				/* If we're processing a notification from the caller that
572 				   the object init is complete and the object was destroyed
573 				   while it was being created (which sets its state to
574 				   CRYPT_ERROR_SIGNALLED), tell the caller to convert the
575 				   message to a destroy object message unless it's a system
576 				   object, which can't be explicitly destroyed.  In this case
577 				   we just return an error so the cryptlib init fails */
578 				if( objectInfoPtr->flags & OBJECT_FLAG_SIGNALLED )
579 					{
580 					return( ( objectHandle < NO_SYSTEM_OBJECTS ) ?
581 							CRYPT_ERROR_SIGNALLED : OK_SPECIAL );
582 					}
583 
584 				/* We're transitioning the object to the initialised state */
585 				REQUIRES( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED );
586 				objectInfoPtr->flags &= ~OBJECT_FLAG_NOTINITED;
587 				ENSURES( !( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED ) );
588 				break;
589 				}
590 
591 			/* Postcondition: The object is in a valid state */
592 			ENSURES( !isInvalidObjectState( objectHandle ) );
593 
594 			break;
595 
596 		case CRYPT_IATTRIBUTE_INTERNAL:
597 			{
598 			int status;
599 
600 			/* Internal objects can be made external after creation or fetch
601 			   from another object like a keyset, but not the other way
602 			   round */
603 			REQUIRES( value == FALSE );
604 
605 			/* Make the object externally accessible */
606 			REQUIRES( isInternalObject( objectHandle ) );
607 			objectInfoPtr->flags &= ~OBJECT_FLAG_INTERNAL;
608 
609 			/* Now that the object is external we need to convert at least
610 			   one internal reference to it to an external one */
611 			status = convertIntToExtRef( objectHandle );
612 			if( cryptStatusError( status ) )
613 				return( status );
614 
615 			break;
616 			}
617 
618 		case CRYPT_IATTRIBUTE_ACTIONPERMS:
619 			{
620 			const int newPerm = \
621 					updateActionPerms( objectInfoPtr->actionFlags, value );
622 
623 			if( cryptStatusError( newPerm ) )
624 				return( newPerm );
625 			objectInfoPtr->actionFlags = newPerm;
626 			break;
627 			}
628 
629 		case CRYPT_IATTRIBUTE_LOCKED:
630 			/* Incremement or decrement the object's lock count depending on
631 			   whether we're locking or unlocking it */
632 			if( value )
633 				{
634 				/* Precondition: The lock count is positive or zero */
635 				REQUIRES( objectInfoPtr->lockCount >= 0 );
636 
637 				objectInfoPtr->lockCount++;
638 
639 				ENSURES( objectInfoPtr->lockCount < MAX_INTLENGTH );
640 #ifdef USE_THREADS
641 				objectInfoPtr->lockOwner = THREAD_SELF();
642 #endif /* USE_THREADS */
643 				}
644 			else
645 				{
646 				/* Precondition: The lock count is positive */
647 				REQUIRES( objectInfoPtr->lockCount > 0 );
648 
649 				objectInfoPtr->lockCount--;
650 
651 				ENSURES( objectInfoPtr->lockCount >= 0 );
652 				}
653 
654 			/* If it's a certificate, notify it that it should save/restore
655 			   its internal state */
656 			if( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE )
657 				{
658 				const MESSAGE_FUNCTION messageFunction = \
659 								FNPTR_GET( objectInfoPtr->messageFunction );
660 
661 				ENSURES( messageFunction != NULL );
662 				( void ) messageFunction( objectInfoPtr->objectPtr,
663 										  MESSAGE_CHANGENOTIFY, messageDataPtr,
664 										  MESSAGE_CHANGENOTIFY_STATE );
665 				}
666 			break;
667 
668 		default:
669 			retIntError();
670 		}
671 
672 	return( CRYPT_OK );
673 	}
674 
675 /****************************************************************************
676 *																			*
677 *							Update Internal Properties						*
678 *																			*
679 ****************************************************************************/
680 
681 /* Increment/decrement the reference counts for an object.  Since references
682    can be either internal or external, we have to handle the two separately.
683    If the last external reference is removed then the object becomes
684    internal-only, if all references are removed then the object is
685    destroyed.
686 
687    There's an additional reference-count manipulation facility in the
688    attribute-handling mechanism for CRYPT_IATTRIBUTE_INTERNAL, which
689    transfers a reference from internal to external when making an object
690    external */
691 
692 CHECK_RETVAL \
incRefCount(IN_HANDLE const int objectHandle,STDC_UNUSED const int dummy1,STDC_UNUSED const void * dummy2,const BOOLEAN isInternal)693 int incRefCount( IN_HANDLE const int objectHandle,
694 				 STDC_UNUSED const int dummy1,
695 				 STDC_UNUSED const void *dummy2,
696 				 const BOOLEAN isInternal )
697 	{
698 	OBJECT_INFO *objectTable = krnlData->objectTable;
699 	int *referenceCountPtr = isInternal ? \
700 							 &objectTable[ objectHandle ].intRefCount : \
701 							 &objectTable[ objectHandle ].extRefCount;
702 	ORIGINAL_INT_VAR( oldRefCount, *referenceCountPtr );
703 
704 	/* Preconditions.  Since there are two reference counts, the one that
705 	   we're updating can be zero if the other one is nonzero */
706 	REQUIRES( isValidObject( objectHandle ) );
707 	REQUIRES( *referenceCountPtr >= 0 && \
708 			  *referenceCountPtr < MAX_INTLENGTH_SHORT );
709 
710 	/* Make sure that we don't try and increment a reference count a
711 	   suspicious number of times */
712 	if( *referenceCountPtr >= MAX_INTLENGTH_SHORT - 1 )
713 		return( CRYPT_ARGERROR_OBJECT );
714 
715 	/* Increment the object's reference count */
716 	( *referenceCountPtr )++;
717 
718 	/* Postcondition: We incremented the reference count and it's now greater
719 	   than zero (the ground state) */
720 	ENSURES( *referenceCountPtr >= 1 && \
721 			 *referenceCountPtr < MAX_INTLENGTH_SHORT );
722 	ENSURES( *referenceCountPtr == ORIGINAL_VALUE( oldRefCount ) + 1 );
723 
724 	return( CRYPT_OK );
725 	}
726 
727 CHECK_RETVAL \
decRefCount(IN_HANDLE const int objectHandle,STDC_UNUSED const int dummy1,STDC_UNUSED const void * dummy2,const BOOLEAN isInternal)728 int decRefCount( IN_HANDLE const int objectHandle,
729 				 STDC_UNUSED const int dummy1,
730 				 STDC_UNUSED const void *dummy2,
731 				 const BOOLEAN isInternal )
732 	{
733 	OBJECT_INFO *objectTable = krnlData->objectTable;
734 	int *referenceCountPtr = isInternal ? \
735 							 &objectTable[ objectHandle ].intRefCount : \
736 							 &objectTable[ objectHandle ].extRefCount;
737 	int status;
738 	ORIGINAL_INT_VAR( oldRefCount, *referenceCountPtr );
739 
740 	/* Preconditions */
741 	REQUIRES( isValidObject( objectHandle ) );
742 	REQUIRES( *referenceCountPtr >= 1 && \
743 			  *referenceCountPtr < MAX_INTLENGTH_SHORT );
744 
745 	/* If the last external reference is about to be destroyed, make the
746 	   object internal.  This marks it as invalid for any external access,
747 	   so that to the caller it looks like it's been destroyed even if its
748 	   internal reference count keeps it active */
749 	if( !isInternal && !isInternalObject( objectHandle ) && \
750 		*referenceCountPtr <= 1 )
751 		{
752 		objectTable[ objectHandle ].flags |= OBJECT_FLAG_INTERNAL;
753 		ENSURES( isInternalObject( objectHandle ) );
754 		}
755 
756 	/* Decrement the object's reference count */
757 	( *referenceCountPtr )--;
758 
759 	/* Postconditions: We decremented the reference count and it's greater
760 	   than or equal to zero (the ground state) */
761 	ENSURES( *referenceCountPtr >= 0 && \
762 			 *referenceCountPtr < MAX_INTLENGTH_SHORT - 1 );
763 	ENSURES( *referenceCountPtr == ORIGINAL_VALUE( oldRefCount ) - 1 );
764 
765 	/* If there are still references to the object present, there's nothing
766 	   further to do */
767 	if( objectTable[ objectHandle ].intRefCount > 0 || \
768 		objectTable[ objectHandle ].extRefCount > 0 )
769 		return( CRYPT_OK );
770 
771 	/* We're about to destroy the object, all references to it have been
772 	   removed */
773 	ENSURES( objectTable[ objectHandle ].extRefCount == 0 && \
774 			 objectTable[ objectHandle ].intRefCount == 0 );
775 
776 	/* Destroy the object.  Since this can entail arbitrary amounts of
777 	   processing during the object shutdown phase, we have to unlock the
778 	   object table around the call */
779 	MUTEX_UNLOCK( objectTable );
780 	status = krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );
781 	MUTEX_LOCK( objectTable );
782 
783 	return( status );
784 	}
785 
786 /* Get/set dependent objects for an object */
787 
788 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
getDependentObject(IN_HANDLE const int objectHandle,const int targetType,IN_BUFFER_C (sizeof (int))const void * messageDataPtr,STDC_UNUSED const BOOLEAN dummy)789 int getDependentObject( IN_HANDLE const int objectHandle,
790 						const int targetType,
791 						IN_BUFFER_C( sizeof( int ) ) \
792 							const void *messageDataPtr,
793 							/* This is a bit of a lie since we actually
794 							   return the dependent object through this
795 							   pointer, however making it non-const means
796 							   that we'd have to also un-const every other
797 							   use of this parameter in all other functions
798 							   accessed via this function pointer */
799 						STDC_UNUSED const BOOLEAN dummy )
800 	{
801 	int *valuePtr = ( int * ) messageDataPtr, status;
802 
803 	assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
804 
805 	/* Preconditions */
806 	REQUIRES( isValidObject( objectHandle ) );
807 	REQUIRES( isValidType( targetType ) );
808 
809 	/* Clear return value */
810 	*valuePtr = CRYPT_ERROR;
811 
812 	status = findTargetType( objectHandle, valuePtr, targetType );
813 	if( cryptStatusError( status ) )
814 		{
815 		/* Postconditions: No dependent object found */
816 		ENSURES( *valuePtr == CRYPT_ERROR );
817 
818 		return( CRYPT_ARGERROR_OBJECT );
819 		}
820 
821 	/* Postconditions: We found a dependent object */
822 	ENSURES( isValidObject( *valuePtr ) && \
823 			 isSameOwningObject( *valuePtr, objectHandle ) );
824 
825 	return( CRYPT_OK );
826 	}
827 
828 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
setDependentObject(IN_HANDLE const int objectHandle,IN_ENUM (SETDEP_OPTION)const int option,IN_BUFFER_C (sizeof (int))const void * messageDataPtr,STDC_UNUSED const BOOLEAN dummy)829 int setDependentObject( IN_HANDLE const int objectHandle,
830 						IN_ENUM( SETDEP_OPTION ) const int option,
831 						IN_BUFFER_C( sizeof( int ) ) \
832 								const void *messageDataPtr,
833 						STDC_UNUSED const BOOLEAN dummy )
834 	{
835 	OBJECT_INFO *objectTable = krnlData->objectTable;
836 	OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
837 	const OBJECT_INFO *dependentObjectInfoPtr;
838 	const int dependentObject = *( ( int * ) messageDataPtr );
839 	const DEPENDENCY_ACL *dependencyACL = NULL;
840 	int *objectHandlePtr, i, status;
841 
842 	assert( isReadPtr( messageDataPtr, sizeof( int ) ) );
843 
844 	/* Preconditions: Parameters are valid */
845 	REQUIRES( isValidObject( objectHandle ) );
846 	REQUIRES( option == SETDEP_OPTION_NOINCREF || \
847 			  option == SETDEP_OPTION_INCREF );
848 	REQUIRES( isValidHandle( dependentObject ) );
849 
850 	/* Make sure that the object is valid, it may have been signalled after
851 	   the message was sent */
852 	if( !isValidObject( dependentObject ) )
853 		return( CRYPT_ERROR_SIGNALLED );
854 	dependentObjectInfoPtr = &objectTable[ dependentObject ];
855 	if( dependentObjectInfoPtr->type == OBJECT_TYPE_DEVICE )
856 		objectHandlePtr = &objectInfoPtr->dependentDevice;
857 	else
858 		objectHandlePtr = &objectInfoPtr->dependentObject;
859 
860 	/* Basic validity checks: There can't already be a dependent object set */
861 	if( *objectHandlePtr != CRYPT_ERROR )
862 		{
863 		/* There's already a dependent object present and we're trying to
864 		   overwrite it with a new one, something is seriously wrong */
865 		retIntError();
866 		}
867 
868 	/* More complex validity checks to ensure that the object table is
869 	   consistent: The object isn't already dependent on the dependent object
870 	   (making the dependent object then dependent on the object would
871 	   create a loop), and the object won't be dependent on its own object
872 	   type unless it's a device dependent on the system device */
873 	if( ( ( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ? \
874 			  dependentObjectInfoPtr->dependentDevice : \
875 			  dependentObjectInfoPtr->dependentObject ) == objectHandle ) || \
876 		( objectInfoPtr->type == dependentObjectInfoPtr->type && \
877 		  dependentObject != SYSTEM_OBJECT_HANDLE ) )
878 		retIntError();
879 
880 	/* Find the dependency ACL entry for this object/dependent object
881 	   combination.  Since there can be more than one dependent object
882 	   type for an object, we check subtypes as well */
883 	for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \
884 				i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL );
885 		 i++ )
886 		{
887 		if( dependencyACLTbl[ i ].type == objectInfoPtr->type && \
888 			dependencyACLTbl[ i ].dType == dependentObjectInfoPtr->type && \
889 			( isValidSubtype( dependencyACLTbl[ i ].dSubTypeA, \
890 							  dependentObjectInfoPtr->subType ) || \
891 			  isValidSubtype( dependencyACLTbl[ i ].dSubTypeB, \
892 							  dependentObjectInfoPtr->subType ) || \
893 			  isValidSubtype( dependencyACLTbl[ i ].dSubTypeC, \
894 							  dependentObjectInfoPtr->subType ) ) )
895 			{
896 			dependencyACL = &dependencyACLTbl[ i ];
897 			break;
898 			}
899 		}
900 	ENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );
901 	ENSURES( dependencyACL != NULL );
902 
903 	/* Inner precondition: We have the appropriate ACL for this combination
904 	   of object and dependent object */
905 	REQUIRES( dependencyACL->type == objectInfoPtr->type && \
906 			  dependencyACL->dType == dependentObjectInfoPtr->type && \
907 			  ( isValidSubtype( dependencyACL->dSubTypeA, \
908 								dependentObjectInfoPtr->subType ) || \
909 				isValidSubtype( dependencyACL->dSubTypeB, \
910 								dependentObjectInfoPtr->subType ) || \
911 				isValidSubtype( dependencyACL->dSubTypeC, \
912 								dependentObjectInfoPtr->subType ) ) );
913 
914 	/* Type-specific checks.  For PKC context -> cert and cert -> PKC context
915 	   attaches we should also check that the primary PKC object is a
916 	   private-key object and the dependent PKC object is a public-key object
917 	   to catch things like a private key depending on a (public-key) cert,
918 	   however this requires unlocking the object table in order to send the
919 	   context a check message.  Since this requires additional precautions,
920 	   we leave it for updateDependentObjectPerms(), which has to unlock the
921 	   table for its own update operations */
922 	ENSURES( isValidSubtype( dependencyACL->subTypeA, \
923 							 objectInfoPtr->subType ) || \
924 			 isValidSubtype( dependencyACL->subTypeB, \
925 							 objectInfoPtr->subType ) || \
926 			 isValidSubtype( dependencyACL->subTypeC, \
927 							 objectInfoPtr->subType ) );
928 	ENSURES( isValidSubtype( dependencyACL->dSubTypeA, \
929 							 dependentObjectInfoPtr->subType ) || \
930 			 isValidSubtype( dependencyACL->dSubTypeB, \
931 							 dependentObjectInfoPtr->subType ) || \
932 			 isValidSubtype( dependencyACL->dSubTypeC, \
933 							 dependentObjectInfoPtr->subType ) );
934 
935 	/* Inner precondition */
936 	REQUIRES( *objectHandlePtr == CRYPT_ERROR );
937 	REQUIRES( isSameOwningObject( objectHandle, dependentObject ) );
938 
939 	/* Certs and contexts have special relationships in that the cert can
940 	   constrain the use of the context beyond its normal level.  If we're
941 	   performing this type of object attachment, we have to adjust one
942 	   object's behaviour based on the permissions of the other one.  We do
943 	   this before we increment the reference count because the latter can
944 	   never fail so we don't have to worry about undoing the update */
945 	if( dependencyACL->flags & DEP_FLAG_UPDATEDEP )
946 		{
947 		status = updateDependentObjectPerms( objectHandle, dependentObject );
948 		if( cryptStatusError( status ) )
949 			return( status );
950 		}
951 
952 	/* Update the dependent object's reference count if required and record
953 	   the new status in the object table.  Dependent objects can be
954 	   established in one of two ways, by taking an existing object and
955 	   attaching it to another object (which increments its reference count,
956 	   since it's now being referred to by the original owner and by the
957 	   object it's  attached to), or by creating a new object and attaching
958 	   it to another object (which doesn't increment the reference count
959 	   since it's only referred to by the controlling object).  An example of
960 	   the former operation is adding a context from a cert request to a cert
961 	   (the cert request is referenced by both the caller and the cert), an
962 	   example of the latter operation is attaching a data-only cert to a
963 	   context (the cert is only referenced by the context) */
964 	if( option == SETDEP_OPTION_INCREF )
965 		{
966 		status = incRefCount( dependentObject, 0, NULL, TRUE );
967 		if( cryptStatusError( status ) )
968 			return( status );
969 		}
970 	*objectHandlePtr = dependentObject;
971 
972 	/* Postconditions */
973 	ENSURES( isValidObject( *objectHandlePtr ) && \
974 			 isSameOwningObject( objectHandle, *objectHandlePtr ) );
975 
976 	return( CRYPT_OK );
977 	}
978 
979 /* Clone an object.  The older copy-on-write implementation didn't actually
980    do anything at this point except check that the access was valid and set
981    the aliased and cloned flags to indicate that the object needed to be
982    handled specially if a write access was made to it, but with the kernel
983    tracking instance data we can do a copy immediately to create two
984    distinct objects */
985 
986 CHECK_RETVAL \
cloneObject(IN_HANDLE const int objectHandle,IN_HANDLE const int clonedObject,STDC_UNUSED const void * dummy1,STDC_UNUSED const BOOLEAN dummy2)987 int cloneObject( IN_HANDLE const int objectHandle,
988 				 IN_HANDLE const int clonedObject,
989 				 STDC_UNUSED const void *dummy1,
990 				 STDC_UNUSED const BOOLEAN dummy2 )
991 	{
992 	OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
993 	OBJECT_INFO *clonedObjectInfoPtr = &krnlData->objectTable[ clonedObject ];
994 	const MESSAGE_FUNCTION messageFunction = \
995 							FNPTR_GET( objectInfoPtr->messageFunction );
996 	int actionFlags, status;
997 
998 	/* Preconditions */
999 	REQUIRES( isValidObject( objectHandle ) && \
1000 			  objectHandle >= NO_SYSTEM_OBJECTS );
1001 	REQUIRES( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );
1002 	REQUIRES( isValidObject( clonedObject ) && \
1003 			  clonedObject >= NO_SYSTEM_OBJECTS );
1004 	REQUIRES( clonedObjectInfoPtr->type == OBJECT_TYPE_CONTEXT );
1005 	REQUIRES( objectHandle != clonedObject );
1006 	REQUIRES( messageFunction != NULL );
1007 
1008 	/* Make sure that the original object is in the high state.  This will
1009 	   have been checked by the caller anyway, but we check again here to
1010 	   make sure */
1011 	if( !isInHighState( objectHandle ) )
1012 		return( CRYPT_ERROR_NOTINITED );
1013 
1014 	/* Cloning of non-native contexts is somewhat complex because we usually
1015 	   can't clone a device object, so we have to detect requests to clone
1016 	   these objects and increment their reference count instead.  This
1017 	   isn't a major problem because cryptlib always creates native contexts
1018 	   for clonable algorithms, if the user explicitly overrides this by
1019 	   using their own device-specific context then the usage will usually
1020 	   be create, add to envelope, destroy, so there's no need to clone the
1021 	   context anyway.  The only that time there's a potential problem is if
1022 	   they override the use of native contexts by adding device contexts to
1023 	   multiple envelopes, but in that case it's assumed that they'll be
1024 	   aware of potential problems with this approach */
1025 	if( objectInfoPtr->dependentDevice != SYSTEM_OBJECT_HANDLE )
1026 		return( incRefCount( objectHandle, 0, NULL, TRUE ) );
1027 
1028 	/* Since this is an internal-use-only object, lock down the action
1029 	   permissions so that only encryption and hash actions from internal
1030 	   sources are allowed (assuming they were allowed to begin with).
1031 	   Keygen is disabled entirely (there should already be a key loaded),
1032 	   and signing isn't possible with a non-PKC object anyway.  This takes
1033 	   advantage of the ratchet enforced for the action permissions, which
1034 	   can only make them more restrictive than the existing permissions, to
1035 	   avoid having to read and modify each permission individually */
1036 	actionFlags = \
1037 		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
1038 		MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
1039 		MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_NONE_EXTERNAL );
1040 	status = setPropertyAttribute( clonedObject, CRYPT_IATTRIBUTE_ACTIONPERMS,
1041 								   &actionFlags );
1042 	if( cryptStatusError( status ) )
1043 		return( status );
1044 
1045 	/* Postcondition: The cloned object can only be used internally */
1046 	ENSURES( ( clonedObjectInfoPtr->actionFlags & \
1047 								~ACTION_PERM_NONE_EXTERNAL_ALL ) == 0 );
1048 
1049 	/* Inner precondition: The instance data is valid and ready to be
1050 	   copied */
1051 	assert( isWritePtr( objectInfoPtr->objectPtr, objectInfoPtr->objectSize ) );
1052 	assert( isWritePtr( clonedObjectInfoPtr->objectPtr,
1053 						clonedObjectInfoPtr->objectSize ) );
1054 	REQUIRES( objectInfoPtr->objectSize == clonedObjectInfoPtr->objectSize );
1055 
1056 	/* Copy across the object contents and reset any instance-specific
1057 	   information.  We only update the owning object if required, in
1058 	   almost all cases this will be the system device so there's no need
1059 	   to perform the update */
1060 	memcpy( clonedObjectInfoPtr->objectPtr, objectInfoPtr->objectPtr,
1061 			objectInfoPtr->objectSize );
1062 	messageFunction( clonedObjectInfoPtr->objectPtr, MESSAGE_CHANGENOTIFY,
1063 					 ( MESSAGE_CAST ) &clonedObject,
1064 					 MESSAGE_CHANGENOTIFY_OBJHANDLE );
1065 	if( objectInfoPtr->owner != clonedObjectInfoPtr->owner )
1066 		{
1067 		messageFunction( clonedObjectInfoPtr->objectPtr, MESSAGE_CHANGENOTIFY,
1068 						 &clonedObjectInfoPtr->owner,
1069 						 MESSAGE_CHANGENOTIFY_OWNERHANDLE );
1070 		}
1071 
1072 	/* We've copied across the object's state, the cloned object is now
1073 	   initialised ready for use */
1074 	clonedObjectInfoPtr->flags |= OBJECT_FLAG_HIGH;
1075 
1076 	return( CRYPT_OK );
1077 	}
1078