1 /****************************************************************************
2 *																			*
3 *									Keyset ACLs								*
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 #ifdef USE_KEYSETS
19 
20 /* A pointer to the kernel data block */
21 
22 static KERNEL_DATA *krnlData = NULL;
23 
24 /****************************************************************************
25 *																			*
26 *									Keyset ACLs								*
27 *																			*
28 ****************************************************************************/
29 
30 /* ID information.  This defines the ID types that are valid for retrieving
31    each object type;
32 
33 	Public/private keys: Any ID is valid.  There's some overlap here because
34 		in some cases the private key is retrieved by first locating the
35 		corresponding public key (which is what the ID actually points to)
36 		and then using that to find the matching private key.
37 
38 	Secret keys: Only lookups by name or keyID are possible (all other ID
39 		types are PKC-related).
40 
41 	Cert requests: Lookups by name or URI are allowed for the user-level
42 		CACertManagement() functions, lookups by certID are used for
43 		cryptlib-internal access.
44 
45 	PKI users: Lookups by name or URI are allowed for the user-level
46 		CACertManagement() functions, lookups by keyID and certID are used
47 		for cryptlib-internal access.  PKI users don't really have a keyID
48 		in the sense of a subjectKeyIdentifier, in this case it's a
49 		randomly-generated value that's unique for each PKI user.
50 
51 	Revocation info: Lookups by certID and issuerID are used for cryptlib-
52 		internal access.
53 
54 	Data: No ID is used, data objects are implicitly identified by type */
55 
56 static const CRYPT_KEYID_TYPE pubKeyIDs[] = {
57 		CRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID,
58 		CRYPT_IKEYID_PGPKEYID, CRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID,
59 		CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
60 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
61 static const CRYPT_KEYID_TYPE privKeyIDs[] = {
62 		CRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID,
63 		CRYPT_IKEYID_PGPKEYID, CRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID,
64 		CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
65 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
66 static const CRYPT_KEYID_TYPE secKeyIDs[] = {
67 		CRYPT_KEYID_NAME, CRYPT_IKEYID_KEYID,
68 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
69 static const CRYPT_KEYID_TYPE certReqIDs[] = {
70 		CRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_CERTID,
71 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
72 static const CRYPT_KEYID_TYPE revReqIDs[] = {
73 		CRYPT_KEYID_NAME, CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
74 static const CRYPT_KEYID_TYPE pkiUserIDs[] = {
75 		CRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID,
76 		CRYPT_IKEYID_CERTID,
77 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
78 static const CRYPT_KEYID_TYPE revInfoIDs[] = {
79 		CRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID,
80 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
81 static const CRYPT_KEYID_TYPE dataIDs[] = {
82 		CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };
83 
84 /* Key management ACL information.  These work in the same general way as the
85    crypto mechanism ACL checks enforced by the kernel.  The ACL entries are:
86 
87 	Valid keyset types for R/W/D access.
88 	Valid keyset types for getFirst/Next access.
89 	Valid keyset types for query access.
90 	Valid object types to write.
91 	Valid key IDs for read/getFirst/query access.
92 	Valid key management flags in the mechanism info.
93 	Access type for which an ID parameter is required.
94 	Access type for which a password (or other aux.info) is required
95 	[ Specific object types requires for some keyset types ]
96 
97   The access-type entries are used for parameter checking and represent all
98   access types for which these parameters are required, even if those
99   access types aren't currently allowed by the valid access types entry.
100   This is to allow them to be enabled by changing only the valid access
101   types entry without having to update the other two entries as well.
102 
103   In addition, there are a few access types (specifically getFirst/Next and
104   private key reads) for which the semantics of password/aux info use are
105   complex enough that we have to hardcode them, leaving only a
106   representative entry in the ACL definition.  Examples of this are keyset
107   vs. crypto device reads (keysets usually need passwords while a logged-
108   in device doesn't), speculative reads from the keyset to determine
109   presence (which don't require a password), and so on.
110 
111   The key ID values are the union of the key ID types that are valid for
112   all of the keysets that can store the given object type.  These are
113   used to implement a two-level check, first the main ACL checks whether
114   this ID type is valid for this object type, and then a secondary ACL
115   is used to determine whether the ID type is valid for the source that
116   the object is being read from.
117 
118   The (optional) specific object types entry is required for some keysets
119   that require a specific object (typically a certificate or cert chain)
120   rather than just a generic PKC context for the overall keyset item type.
121 
122   The file keysets have three different subtypes, full-featured ones for
123   which any access is allowed (KEYSET_FILE), mininmal ones for which only
124   a single key can be written but that don't contain enough information
125   for deletion, find-first/find-next, or storage of anything other than
126   public/private keys (KEYSET_FILE_PARTIAL), and ones whose format is
127   sufficiently oddball that only read access is allowed (KEYSET_RO).  The
128   schema for these is as follows (+ = all types, F = full only, - = no
129   access):
130 
131 			|	R	|	W	|	D	| FF/FN	|	Q	|
132 	--------+-------+-------+-------+-------+-------+
133 	Pubkey	|	+	|  P/F	|	F	|	F	|	-	|
134 	Privkey	|	+	|  P/F	|	F	|	-	|	-	|
135 	Secret	|	F	|	F	|	F	|	-	|	-	|
136 	Metadata|	-	|	F	|	-	|	-	|	-	|
137 	--------+-------+-------+-------+-------+-------+ */
138 
139 static const KEYMGMT_ACL FAR_BSS keyManagementACL[] = {
140 	/* Access public key */
141 	MK_KEYACL_EX( KEYMGMT_ITEM_PUBLICKEY,
142 		/* R */	ST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
143 		/* W */	ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_DBMS | \
144 				ST_KEYSET_LDAP | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
145 		/* D */	ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_LDAP | \
146 				ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
147 		/* Fn*/	ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | \
148 				ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
149 		/* Q */	ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_LDAP,
150 		/*Obj*/	ST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN,
151 		/*IDs*/	pubKeyIDs,
152 		/*Flg*/	KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY | \
153 				KEYMGMT_MASK_CERTOPTIONS,
154 		ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx,
155 		ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_LDAP | \
156 						 ST_DEV_P11 | ST_DEV_CAPI,
157 		ST_CERT_CERT | ST_CERT_CERTCHAIN ),
158 
159 	/* Access private key */
160 	MK_KEYACL_RWD( KEYMGMT_ITEM_PRIVATEKEY,
161 		/* R */	ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \
162 				ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
163 		/* W */	ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_DEV_P11 | \
164 				ST_DEV_CAPI | ST_DEV_HW,
165 		/* D */	ST_KEYSET_FILE | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,
166 		/*FnQ*/	ST_NONE, ST_NONE,
167 		/*Obj*/	ST_CTX_PKC,
168 		/*IDs*/	privKeyIDs,
169 		/*Flg*/	KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY | \
170 				KEYMGMT_MASK_USAGEOPTIONS,
171 		ACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxXXx ),
172 
173 	/* Access secret key */
174 	MK_KEYACL( KEYMGMT_ITEM_SECRETKEY,
175 		/*RWD*/	ST_KEYSET_FILE | ST_DEV_P11,
176 		/*FnQ*/	ST_NONE,
177 		/*Obj*/	ST_CTX_CONV,
178 		/*IDs*/	secKeyIDs,
179 		/*Flg*/	KEYMGMT_FLAG_CHECK_ONLY,
180 		ACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxXXx ),
181 
182 	/* Access certificate request/revocation request */
183 	MK_KEYACL_RWD( KEYMGMT_ITEM_REQUEST,
184 		/*RWD*/	ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,
185 		/*FnQ*/	ST_NONE, ST_KEYSET_DBMS_STORE,
186 		/*Obj*/	ST_CERT_CERTREQ | ST_CERT_REQ_CERT,
187 		/*IDs*/	certReqIDs,
188 		/*Flg*/	KEYMGMT_FLAG_UPDATE | KEYMGMT_FLAG_INITIALOP,
189 		ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
190 	MK_KEYACL_RWD( KEYMGMT_ITEM_REVREQUEST,
191 		/*RWD*/	ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,
192 		/*FnQ*/	ST_NONE, ST_KEYSET_DBMS_STORE,
193 		/*Obj*/	ST_CERT_REQ_REV,
194 		/*IDs*/	revReqIDs,
195 		/*Flg*/	KEYMGMT_FLAG_NONE,
196 		ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
197 
198 	/* Access PKI user info */
199 	MK_KEYACL_RWD( KEYMGMT_ITEM_PKIUSER,
200 		/*RWD*/	ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE,
201 		/*FnQ*/	ST_NONE, ST_NONE,
202 		/*Obj*/	ST_CERT_PKIUSER,
203 		/*IDs*/	pkiUserIDs,
204 		/*Flg*/	KEYMGMT_FLAG_GETISSUER,
205 		ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
206 
207 	/* Access revocation information/CRL */
208 	MK_KEYACL_RWD( KEYMGMT_ITEM_REVOCATIONINFO,
209 		/*RWD*/	ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS, ST_NONE,
210 		/*FnQ*/	ST_NONE, ST_NONE,
211 		/*Obj*/	ST_CERT_CRL,
212 		/*IDs*/	revInfoIDs,
213 		/*Flg*/	KEYMGMT_FLAG_CHECK_ONLY,
214 		ACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),
215 
216 	/* Access key metadata for dummy contexts */
217 	MK_KEYACL_RWD( KEYMGMT_ITEM_KEYMETADATA,
218 		/*RWD*/	ST_NONE, ST_KEYSET_FILE, ST_NONE,
219 		/*FnQ*/	ST_NONE, ST_NONE,
220 		/*Obj*/	ST_CTX_PKC,
221 		/*IDs*/	privKeyIDs,
222 		/*Flg*/	KEYMGMT_FLAG_NONE,
223 		ACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxxxx ),
224 
225 	/* Other data (for PKCS #15 tokens) */
226 	MK_KEYACL_RWD( KEYMGMT_ITEM_DATA,
227 		/*RWD*/	ST_KEYSET_FILE, ST_KEYSET_FILE, ST_NONE,
228 		/*FnQ*/	ST_NONE, ST_NONE,
229 		/*Obj*/	ST_NONE,
230 		/*IDs*/	dataIDs,
231 		/*Flg*/	KEYMGMT_FLAG_NONE,
232 		ACCESS_KEYSET_xxRWD, ACCESS_KEYSET_FNxxx ),
233 
234 	/* Last item type */
235 	MK_KEYACL( KEYMGMT_ITEM_NONE, ST_NONE, ST_NONE, ST_NONE, NULL,
236 		KEYMGMT_FLAG_NONE, ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx ),
237 	MK_KEYACL( KEYMGMT_ITEM_NONE, ST_NONE, ST_NONE, ST_NONE, NULL,
238 		KEYMGMT_FLAG_NONE, ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx )
239 	};
240 
241 /* A secondary ACL matching key ID types with keyset types.  This is a
242    refinement of the generic list of permitted IDs per object type to
243    read, since this is actually a three-way match of
244    keysetType :: itemType :: idType.  The keyManagementACL is used to
245    check itemType :: idType, this supplementary ACL takes the result
246    of that check and checks it against keysetType */
247 
248 typedef struct {
249 	const CRYPT_KEYID_TYPE idType;
250 	const OBJECT_SUBTYPE keysetSubTypeB;
251 	} IDTYPE_ACL;
252 
253 static const IDTYPE_ACL idTypeACL[] = {
254 	{ CRYPT_KEYID_NAME,
255 	  ST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW },
256 	{ CRYPT_KEYID_URI,
257 	  ST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_HW },
258 	{ CRYPT_IKEYID_KEYID,
259 	  ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \
260 		ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_P11 | ST_DEV_HW },
261 	{ CRYPT_IKEYID_PGPKEYID,
262 	  ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \
263 		ST_DEV_HW },
264 	{ CRYPT_IKEYID_CERTID,
265 	  ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE },
266 	{ CRYPT_IKEYID_ISSUERID,
267 	  ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_HW },
268 	{ CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
269 	  ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_P11 | \
270 		ST_DEV_HW },
271 	{ CRYPT_KEYID_NONE, ST_NONE },
272 		{ CRYPT_KEYID_NONE, ST_NONE }
273 	};
274 
275 /****************************************************************************
276 *																			*
277 *							Init/Shutdown Functions							*
278 *																			*
279 ****************************************************************************/
280 
281 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initKeymgmtACL(INOUT KERNEL_DATA * krnlDataPtr)282 int initKeymgmtACL( INOUT KERNEL_DATA *krnlDataPtr )
283 	{
284 	int i;
285 
286 	assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
287 
288 	/* If we're running a fuzzing build, skip the lengthy self-checks */
289 #ifdef CONFIG_FUZZ
290 	krnlData = krnlDataPtr;
291 	return( CRYPT_OK );
292 #endif /* CONFIG_FUZZ */
293 
294 	/* Perform a consistency check on the key management ACLs */
295 	for( i = 0; keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE && \
296 				i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL );
297 		 i++ )
298 		{
299 		const KEYMGMT_ACL *keyMgmtACL = &keyManagementACL[ i ];
300 		int j;
301 
302 		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
303 			( keyMgmtACL->keysetR_subTypeB & ( SUBTYPE_CLASS_A | \
304 											   SUBTYPE_CLASS_C ) ) || \
305 			( keyMgmtACL->keysetR_subTypeB & \
306 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
307 									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
308 			keyMgmtACL->keysetR_subTypeC != ST_NONE )
309 			{
310 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
311 			retIntError();
312 			}
313 
314 		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
315 			( keyMgmtACL->keysetW_subTypeB & ( SUBTYPE_CLASS_A | \
316 											   SUBTYPE_CLASS_C ) ) || \
317 			( keyMgmtACL->keysetW_subTypeB & \
318 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
319 									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
320 			keyMgmtACL->keysetW_subTypeC != ST_NONE )
321 			{
322 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
323 			retIntError();
324 			}
325 
326 		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
327 			( keyMgmtACL->keysetD_subTypeB & ( SUBTYPE_CLASS_A | \
328 											   SUBTYPE_CLASS_C ) ) || \
329 			( keyMgmtACL->keysetD_subTypeB & \
330 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
331 									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
332 			keyMgmtACL->keysetD_subTypeC != ST_NONE )
333 			{
334 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
335 			retIntError();
336 			}
337 
338 		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
339 			( keyMgmtACL->keysetFN_subTypeB & ( SUBTYPE_CLASS_A | \
340 											    SUBTYPE_CLASS_C ) ) || \
341 			( keyMgmtACL->keysetFN_subTypeB & \
342 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
343 									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \
344 			keyMgmtACL->keysetFN_subTypeC != ST_NONE )
345 			{
346 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
347 			retIntError();
348 			}
349 
350 		if( keyMgmtACL->keysetR_subTypeA != ST_NONE || \
351 			( keyMgmtACL->keysetQ_subTypeB & ( SUBTYPE_CLASS_A | \
352 											   SUBTYPE_CLASS_C ) ) || \
353 			( keyMgmtACL->keysetQ_subTypeB & \
354 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY ) ) != 0 || \
355 			keyMgmtACL->keysetQ_subTypeC != ST_NONE )
356 			{
357 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
358 			retIntError();
359 			}
360 
361 		if( ( keyMgmtACL->objSubTypeA & ( SUBTYPE_CLASS_B | \
362 										  SUBTYPE_CLASS_C ) ) || \
363 			( keyMgmtACL->objSubTypeA & \
364 				~( SUBTYPE_CLASS_A | ST_CERT_ANY | ST_CTX_PKC | \
365 									 ST_CTX_CONV ) ) != 0 || \
366 			keyMgmtACL->objSubTypeB != ST_NONE || \
367 			keyMgmtACL->objSubTypeC != ST_NONE )
368 			{
369 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
370 			retIntError();
371 			}
372 
373 		ENSURES( keyMgmtACL->allowedKeyIDs != NULL );
374 		for( j = 0; keyMgmtACL->allowedKeyIDs[ j ] != CRYPT_KEYID_NONE && \
375 					j < FAILSAFE_ITERATIONS_SMALL; j++ )
376 			{
377 			ENSURES( keyMgmtACL->allowedKeyIDs[ j ] > CRYPT_KEYID_NONE && \
378 					 keyMgmtACL->allowedKeyIDs[ j ] < CRYPT_KEYID_LAST );
379 			}
380 		ENSURES( j < FAILSAFE_ITERATIONS_SMALL );
381 
382 		ENSURES( keyMgmtACL->allowedFlags >= KEYMGMT_FLAG_NONE && \
383 				 keyMgmtACL->allowedFlags < KEYMGMT_FLAG_MAX );
384 
385 		if( keyMgmtACL->specificKeysetSubTypeA != ST_NONE || \
386 			( keyMgmtACL->specificKeysetSubTypeB & ( SUBTYPE_CLASS_A | \
387 													 SUBTYPE_CLASS_C ) ) || \
388 			( keyMgmtACL->specificKeysetSubTypeB & \
389 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
390 									 ST_DEV_CAPI ) ) != 0 || \
391 			keyMgmtACL->specificKeysetSubTypeC != ST_NONE )
392 			{
393 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
394 			retIntError();
395 			}
396 
397 		if( ( keyMgmtACL->specificObjSubTypeA & ( SUBTYPE_CLASS_B | \
398 												  SUBTYPE_CLASS_C ) ) || \
399 			( keyMgmtACL->specificObjSubTypeA & \
400 				~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) != 0 || \
401 			keyMgmtACL->specificObjSubTypeB != ST_NONE || \
402 			keyMgmtACL->specificObjSubTypeC != ST_NONE )
403 			{
404 			DEBUG_DIAG(( "Key management ACLs inconsistent" ));
405 			retIntError();
406 			}
407 		}
408 	ENSURES( i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ) );
409 
410 	/* Perform a consistency check on the supplementary ID ACLs */
411 	for( i = 0; idTypeACL[ i ].idType != CRYPT_KEYID_NONE && \
412 				i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL );
413 		 i++ )
414 		{
415 		const IDTYPE_ACL *idACL = &idTypeACL[ i ];
416 
417 		ENSURES( idACL->idType > CRYPT_KEYID_NONE && \
418 				 idACL->idType < CRYPT_KEYID_LAST );
419 
420 		if( ( idACL->keysetSubTypeB & \
421 				~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \
422 									 ST_DEV_CAPI | ST_DEV_HW ) ) != 0 )
423 			{
424 			DEBUG_DIAG(( "Key management supplementary ACLs inconsistent" ));
425 			retIntError();
426 			}
427 		}
428 	ENSURES( i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ) );
429 
430 	/* Set up the reference to the kernel data block */
431 	krnlData = krnlDataPtr;
432 
433 	return( CRYPT_OK );
434 	}
435 
endKeymgmtACL(void)436 void endKeymgmtACL( void )
437 	{
438 	krnlData = NULL;
439 	}
440 
441 /****************************************************************************
442 *																			*
443 *							Keyset ACL Check Functions						*
444 *																			*
445 ****************************************************************************/
446 
447 /* It's a keyset action message, check the access conditions for the mechanism
448    objects */
449 
450 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
preDispatchCheckKeysetAccess(IN_HANDLE const int objectHandle,IN_MESSAGE const MESSAGE_TYPE message,IN_BUFFER_C (sizeof (MESSAGE_KEYMGMT_INFO))const void * messageDataPtr,IN_ENUM (KEYMGMT_ITEM)const int messageValue,STDC_UNUSED const void * dummy)451 int preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,
452 								  IN_MESSAGE const MESSAGE_TYPE message,
453 								  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \
454 										const void *messageDataPtr,
455 								  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,
456 								  STDC_UNUSED const void *dummy )
457 	{
458 	const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
459 	const MESSAGE_KEYMGMT_INFO *mechanismInfo = \
460 		  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
461 	const KEYMGMT_ACL *keymgmtACL;
462 	const int accessType = \
463 			( localMessage == MESSAGE_KEY_GETKEY ) ? ACCESS_FLAG_R : \
464 			( localMessage == MESSAGE_KEY_SETKEY ) ? ACCESS_FLAG_W : \
465 			( localMessage == MESSAGE_KEY_DELETEKEY ) ? ACCESS_FLAG_D : \
466 			( localMessage == MESSAGE_KEY_GETFIRSTCERT ) ? ACCESS_FLAG_F : \
467 			( localMessage == MESSAGE_KEY_GETNEXTCERT ) ? ACCESS_FLAG_N : 0;
468 	const OBJECT_INFO *objectTable = krnlData->objectTable;
469 	OBJECT_SUBTYPE subType;
470 	int paramObjectHandle, i, status;
471 
472 	assert( isReadPtr( messageDataPtr, sizeof( MESSAGE_KEYMGMT_INFO ) ) );
473 
474 	/* Preconditions */
475 	REQUIRES( isValidObject( objectHandle ) );
476 	REQUIRES( localMessage == MESSAGE_KEY_GETKEY || \
477 			  localMessage == MESSAGE_KEY_SETKEY || \
478 			  localMessage == MESSAGE_KEY_DELETEKEY || \
479 			  localMessage == MESSAGE_KEY_GETFIRSTCERT || \
480 			  localMessage == MESSAGE_KEY_GETNEXTCERT );
481 	REQUIRES( messageValue > KEYMGMT_ITEM_NONE && \
482 			  messageValue < KEYMGMT_ITEM_LAST );
483 	REQUIRES( accessType != 0 );
484 
485 	/* Find the appropriate ACL for this mechanism */
486 	for( i = 0; keyManagementACL[ i ].itemType != messageValue && \
487 				keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE && \
488 				i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL );
489 		 i++ );
490 	ENSURES( i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ) );
491 	ENSURES( keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE );
492 	keymgmtACL = &keyManagementACL[ i ];
493 
494 	/* Perform a combined check to ensure that the item type being accessed
495 	   is appropriate for this keyset type and the access type is valid */
496 	subType = objectST( objectHandle );
497 	switch( localMessage )
498 		{
499 		case MESSAGE_KEY_GETKEY:
500 			if( !isValidSubtype( keymgmtACL->keysetR_subTypeA, subType ) && \
501 				!isValidSubtype( keymgmtACL->keysetR_subTypeB, subType ) && \
502 				!isValidSubtype( keymgmtACL->keysetR_subTypeC, subType ) )
503 				return( CRYPT_ARGERROR_OBJECT );
504 			break;
505 
506 		case MESSAGE_KEY_SETKEY:
507 			if( !isValidSubtype( keymgmtACL->keysetW_subTypeA, subType ) && \
508 				!isValidSubtype( keymgmtACL->keysetW_subTypeB, subType ) && \
509 				!isValidSubtype( keymgmtACL->keysetW_subTypeC, subType ) )
510 				return( CRYPT_ARGERROR_OBJECT );
511 			break;
512 
513 		case MESSAGE_KEY_DELETEKEY:
514 			if( !isValidSubtype( keymgmtACL->keysetD_subTypeA, subType ) && \
515 				!isValidSubtype( keymgmtACL->keysetD_subTypeB, subType ) && \
516 				!isValidSubtype( keymgmtACL->keysetD_subTypeC, subType ) )
517 				return( CRYPT_ARGERROR_OBJECT );
518 			break;
519 
520 		case MESSAGE_KEY_GETFIRSTCERT:
521 		case MESSAGE_KEY_GETNEXTCERT:
522 			/* The two special-purpose accesses are differentiated by whether
523 			   there's state information provided.  For a general query the
524 			   result set is determined by an initially-submitted query
525 			   which is followed by a sequence of fetches.  For a getFirst/
526 			   getNext the results are determined by a cert identifier with
527 			   state held externally in the location pointed to by the
528 			   auxiliary info pointer */
529 			if( mechanismInfo->auxInfo == NULL )
530 				{
531 				/* Keyset query.  We report this as an arg error since we'll
532 				   have been passed a CRYPT_KEYID_NONE or empty keyID, this
533 				   is more sensible than an object error since there's
534 				   nothing wrong with the object, the problem is that
535 				   there's no keyID present */
536 				if( !isValidSubtype( keymgmtACL->keysetQ_subTypeA, subType ) && \
537 					!isValidSubtype( keymgmtACL->keysetQ_subTypeB, subType ) && \
538 					!isValidSubtype( keymgmtACL->keysetQ_subTypeC, subType ) )
539 					return( ( mechanismInfo->keyIDtype == CRYPT_KEYID_NONE ) ? \
540 							CRYPT_ARGERROR_NUM1 : CRYPT_ARGERROR_STR1 );
541 				}
542 			else
543 				{
544 				/* getFirst/next.  We can report an object error here since
545 				   this message is only sent internally */
546 				if( !isValidSubtype( keymgmtACL->keysetFN_subTypeA, subType ) && \
547 					!isValidSubtype( keymgmtACL->keysetFN_subTypeB, subType ) && \
548 					!isValidSubtype( keymgmtACL->keysetFN_subTypeC, subType ) )
549 					return( CRYPT_ARGERROR_OBJECT );
550 
551 				/* Inner precondition: The state information points to an
552 				   integer value containing a reference to the currently
553 				   fetched object */
554 				assert( isReadPtr( mechanismInfo->auxInfo, sizeof( int ) ) );
555 
556 				REQUIRES( mechanismInfo->auxInfoLength == sizeof( int ) );
557 				}
558 			break;
559 
560 		default:
561 			retIntError();
562 		}
563 
564 	/* Make sure that there's appropriate ID information present if
565 	   required */
566 	if( keymgmtACL->idUseFlags & accessType )
567 		{
568 		const IDTYPE_ACL *idACL = NULL;
569 		const int minKeyIDsize = \
570 					( mechanismInfo->keyIDtype == CRYPT_IKEYID_KEYID ) ? \
571 					  1 : MIN_NAME_LENGTH;
572 					/* The keyID can be as little as a single byte when it's
573 					   stored in a keyset/device from a non-cryptlib source */
574 		BOOLEAN keyIdOK = FALSE;
575 		int index;
576 
577 		/* Make sure that the ID information is present and valid */
578 		if( mechanismInfo->keyIDtype <= CRYPT_KEYID_NONE || \
579 			mechanismInfo->keyIDtype >= CRYPT_KEYID_LAST )
580 			return( CRYPT_ARGERROR_NUM1 );
581 		if( !isInternalMessage( message ) && \
582 			mechanismInfo->keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
583 			return( CRYPT_ARGERROR_NUM1 );
584 		if( mechanismInfo->keyIDlength < minKeyIDsize || \
585 			mechanismInfo->keyIDlength >= MAX_ATTRIBUTE_SIZE || \
586 			!isReadPtr( mechanismInfo->keyID, mechanismInfo->keyIDlength ) )
587 			return( CRYPT_ARGERROR_STR1 );
588 
589 		/* Make sure that the key ID is of an appropriate type */
590 		for( index = 0; \
591 			 keymgmtACL->allowedKeyIDs[ index ] != CRYPT_KEYID_NONE && \
592 				index < FAILSAFE_ITERATIONS_SMALL; index++ )
593 			{
594 			if( keymgmtACL->allowedKeyIDs[ index ] == mechanismInfo->keyIDtype )
595 				{
596 				keyIdOK = TRUE;
597 				break;
598 				}
599 			}
600 		ENSURES( index < FAILSAFE_ITERATIONS_SMALL );
601 		if( !keyIdOK )
602 			{
603 			/* If we try and retrieve an object using an inappropriate ID
604 			   type then this is a programming error, but not a fatal one,
605 			   so we just report it as an unable-to-find object error */
606 			DEBUG_DIAG(( "Tried to retrieve object using inappropriate ID "
607 						 "type %d", mechanismInfo->keyIDtype ));
608 			assert( DEBUG_WARN );
609 			return( CRYPT_ERROR_NOTFOUND );
610 			}
611 
612 		/* Finally, check that the keyID is valid for the keyset type.  This
613 		   implements the third stage of the three-way check
614 		   keysetType :: itemType :: idType */
615 		for( index = 0; idTypeACL[ index ].idType != CRYPT_KEYID_NONE && \
616 						index < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL );
617 			 index++ )
618 			{
619 			if( idTypeACL[ index ].idType == mechanismInfo->keyIDtype )
620 				{
621 				idACL = &idTypeACL[ index ];
622 				break;
623 				}
624 			}
625 		ENSURES( index < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ) );
626 		if( idACL == NULL || \
627 			!isValidSubtype( idACL->keysetSubTypeB, subType ) )
628 			{
629 			/* As before if we try and retrieve an object by an
630 			   inappropriate ID type then this is a nonfatal programming
631 			   error so we warn in the debug build but otherwise just report
632 			   it as an unable-to-find object error */
633 			DEBUG_DIAG(( "Tried to retrieve object using inappropriate ID "
634 						 "type %d", mechanismInfo->keyIDtype ));
635 			assert( DEBUG_WARN );
636 			return( CRYPT_ERROR_NOTFOUND );
637 			}
638 		}
639 
640 	/* Make sure that there's a password present/not present if required.
641 	   We only check for incorrect parameters here if they were supplied by
642 	   the user, non-user-supplied parameters (which come from within
643 	   cryptlib) are checked by an assertion later on.  For keyset objects
644 	   the password is optional on reads since it may be a label-only read
645 	   or an opportunistic read that tries to read the key without a
646 	   password initially and falls back to retrying with a password if this
647 	   fails, for device objects the password is never used since it was
648 	   supplied when the user logged on to the device.
649 
650 	   Since the semantics of passwords for private keys are too complex to
651 	   express with a simple ACL entry, this check is hardcoded */
652 	if( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \
653 		messageValue == KEYMGMT_ITEM_SECRETKEY )
654 		{
655 		if( objectTable[ objectHandle ].type == OBJECT_TYPE_KEYSET )
656 			{
657 			if( localMessage == MESSAGE_KEY_SETKEY && \
658 				( mechanismInfo->auxInfo == NULL || \
659 				  mechanismInfo->auxInfoLength < MIN_NAME_LENGTH ||
660 				  mechanismInfo->auxInfoLength >= MAX_ATTRIBUTE_SIZE ) )
661 				{
662 				/* Private/secret key writes to a keyset must provide a
663 				   password */
664 				return( CRYPT_ARGERROR_STR1 );
665 				}
666 			}
667 		else
668 			{
669 			REQUIRES( objectTable[ objectHandle ].type == OBJECT_TYPE_DEVICE );
670 
671 			if( ( mechanismInfo->flags != KEYMGMT_FLAG_LABEL_ONLY ) && \
672 				( mechanismInfo->auxInfo != NULL || \
673 				  mechanismInfo->auxInfoLength != 0 ) )
674 				{
675 				/* Private/secret key access to a device doesn't use a
676 				   password, however the auxInfo parameter is also used to
677 				   contain the label for key label reads so we only check
678 				   it if it's a standard key read */
679 				return( ( keymgmtACL->idUseFlags & accessType ) ? \
680 						CRYPT_ARGERROR_STR2 : CRYPT_ARGERROR_STR1 );
681 				}
682 			}
683 		}
684 
685 	/* Inner precondition: Only allowed flags are set, there's only one of
686 	   the usage preference flags set, and the object handle to get/set is
687 	   not present if not required (the presence and validity check when it
688 	   is required is performed further down) */
689 	REQUIRES( !( ~keymgmtACL->allowedFlags & mechanismInfo->flags ) );
690 	REQUIRES( mechanismInfo->flags >= KEYMGMT_FLAG_NONE && \
691 			  mechanismInfo->flags < KEYMGMT_FLAG_MAX );
692 	REQUIRES( ( mechanismInfo->flags & KEYMGMT_MASK_USAGEOPTIONS ) != \
693 			  KEYMGMT_MASK_USAGEOPTIONS );
694 	REQUIRES( localMessage == MESSAGE_KEY_SETKEY || \
695 			  mechanismInfo->cryptHandle == CRYPT_ERROR );
696 
697 	/* Inner precondition: There's ID information and a password/aux.data
698 	   present/not present as required.  For a private key read the password
699 	   is optional so we don't check it, for a getFirst/getNext the aux.data
700 	   (a pointer to query state) is used when assembling a cert chain (state
701 	   held in the cert) and not used when performing a general query (state
702 	   held in the keyset) */
703 	assert( ( ( keymgmtACL->idUseFlags & accessType ) && \
704 			  mechanismInfo->keyIDtype != CRYPT_KEYID_NONE && \
705 			  isReadPtr( mechanismInfo->keyID, \
706 						 mechanismInfo->keyIDlength ) ) ||
707 			( !( keymgmtACL->idUseFlags & accessType ) && \
708 			  mechanismInfo->keyIDtype == CRYPT_KEYID_NONE && \
709 			  mechanismInfo->keyID == NULL && \
710 			  mechanismInfo->keyIDlength == 0 ) );
711 	assert( ( ( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \
712 				messageValue == KEYMGMT_ITEM_SECRETKEY ) && \
713 			  localMessage == MESSAGE_KEY_GETKEY ) ||
714 			  localMessage == MESSAGE_KEY_GETFIRSTCERT ||
715 			  localMessage == MESSAGE_KEY_GETNEXTCERT ||
716 			( ( keymgmtACL->pwUseFlags & accessType ) && \
717 			  isReadPtr( mechanismInfo->auxInfo, \
718 						 mechanismInfo->auxInfoLength ) ) ||
719 			( !( keymgmtACL->pwUseFlags & accessType ) && \
720 			  mechanismInfo->auxInfo == NULL && \
721 			  mechanismInfo->auxInfoLength == 0 ) );
722 	assert( !( mechanismInfo->flags & KEYMGMT_FLAG_LABEL_ONLY ) || \
723 			isReadPtr( mechanismInfo->auxInfo, \
724 					   mechanismInfo->auxInfoLength ) );
725 
726 	REQUIRES( ( ( keymgmtACL->idUseFlags & accessType ) && \
727 				mechanismInfo->keyIDtype != CRYPT_KEYID_NONE && \
728 				mechanismInfo->keyID != NULL && \
729 				mechanismInfo->keyIDlength > 0 && \
730 				mechanismInfo->keyIDlength < MAX_INTLENGTH_SHORT ) ||
731 			  ( !( keymgmtACL->idUseFlags & accessType ) && \
732 				mechanismInfo->keyIDtype == CRYPT_KEYID_NONE && \
733 				mechanismInfo->keyID == NULL && \
734 				mechanismInfo->keyIDlength == 0 ) );
735 	REQUIRES( ( ( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \
736 				messageValue == KEYMGMT_ITEM_SECRETKEY ) && \
737 				localMessage == MESSAGE_KEY_GETKEY ) ||
738 			  localMessage == MESSAGE_KEY_GETFIRSTCERT ||
739 			  localMessage == MESSAGE_KEY_GETNEXTCERT ||
740 			  ( ( keymgmtACL->pwUseFlags & accessType ) && \
741 				mechanismInfo->auxInfo != NULL && \
742 				mechanismInfo->auxInfoLength > 0 && \
743 				mechanismInfo->auxInfoLength < MAX_INTLENGTH_SHORT ) ||
744 			  ( !( keymgmtACL->pwUseFlags & accessType ) && \
745 				mechanismInfo->auxInfo == NULL && \
746 				mechanismInfo->auxInfoLength == 0 ) );
747 	REQUIRES( !( mechanismInfo->flags & KEYMGMT_FLAG_LABEL_ONLY ) || \
748 			  ( mechanismInfo->auxInfo != NULL && \
749 				mechanismInfo->auxInfoLength > 0 && \
750 				mechanismInfo->auxInfoLength < MAX_INTLENGTH_SHORT ) );
751 
752 	/* Perform message-type-specific checking of parameters */
753 	switch( localMessage )
754 		{
755 		case MESSAGE_KEY_GETKEY:
756 			break;
757 
758 		case MESSAGE_KEY_SETKEY:
759 			/* Make sure that the object being set is valid and its type is
760 			   appropriate for this key management item (and via previous
761 			   checks, keyset) type.  Note that this checks for inclusion in
762 			   the set of valid objects, in particular a public-key context
763 			   can have almost any type of certificate object attached but
764 			   will still be regarded as valid since the context meets the
765 			   check requirements.  More specific object checks are performed
766 			   further on */
767 			paramObjectHandle = mechanismInfo->cryptHandle;
768 			if( !isValidObject( paramObjectHandle ) || \
769 				!isSameOwningObject( objectHandle, paramObjectHandle ) )
770 				return( CRYPT_ARGERROR_NUM1 );
771 			subType = objectST( paramObjectHandle );
772 			if( !isValidSubtype( keymgmtACL->objSubTypeA, subType ) && \
773 				!isValidSubtype( keymgmtACL->objSubTypeB, subType ) && \
774 				!isValidSubtype( keymgmtACL->objSubTypeC, subType ) )
775 				{
776 				/* If we're only allowed to add contexts, this could be a
777 				   cert object with an associated context, in which case
778 				   we look for an associated context and try again */
779 				if( keymgmtACL->objSubTypeA != ST_CTX_PKC )
780 					return( CRYPT_ARGERROR_NUM1 );
781 				status = findTargetType( paramObjectHandle,
782 										 &paramObjectHandle,
783 										 OBJECT_TYPE_CONTEXT );
784 				if( cryptStatusError( status ) || \
785 					objectST( paramObjectHandle ) != ST_CTX_PKC )
786 					return( CRYPT_ARGERROR_NUM1 );
787 				}
788 			if( !isInHighState( paramObjectHandle ) && \
789 				!( subType == ST_CERT_PKIUSER || \
790 				   subType == ST_CERT_REQ_REV || \
791 				   messageValue == KEYMGMT_ITEM_KEYMETADATA ) )
792 				{
793 				/* PKI user info and revocation requests aren't signed, and
794 				   key metadata is contained in a dummy context that may not
795 				   be in the high state yet.  Like private key password
796 				   semantics these are a bit too complex to express in the
797 				   ACL so they're hardcoded */
798 				return( CRYPT_ARGERROR_NUM1 );
799 				}
800 
801 			/* If we don't need to perform an specific-object check, we're
802 			   done */
803 			subType = objectST( objectHandle );
804 			if( !isValidSubtype( keymgmtACL->specificKeysetSubTypeA, subType ) && \
805 				!isValidSubtype( keymgmtACL->specificKeysetSubTypeB, subType ) && \
806 				!isValidSubtype( keymgmtACL->specificKeysetSubTypeC, subType ) )
807 				break;
808 
809 			/* We need a specific cert type for this keyset, make sure that
810 			   we've been passed this and not just a generic PKC-equivalent
811 			   object */
812 			status = findTargetType( mechanismInfo->cryptHandle,
813 									 &paramObjectHandle,
814 									 OBJECT_TYPE_CERTIFICATE );
815 			if( cryptStatusError( status ) )
816 				return( CRYPT_ARGERROR_NUM1 );
817 			subType = objectST( paramObjectHandle );
818 			if( !isValidSubtype( keymgmtACL->specificObjSubTypeA, subType ) && \
819 				!isValidSubtype( keymgmtACL->specificObjSubTypeB, subType ) && \
820 				!isValidSubtype( keymgmtACL->specificObjSubTypeC, subType ) )
821 				return( CRYPT_ARGERROR_NUM1 );
822 			if( !isInHighState( paramObjectHandle ) )
823 				return( CRYPT_ARGERROR_NUM1 );
824 			break;
825 
826 		case MESSAGE_KEY_DELETEKEY:
827 			break;
828 
829 		case MESSAGE_KEY_GETFIRSTCERT:
830 			break;
831 
832 		case MESSAGE_KEY_GETNEXTCERT:
833 			break;
834 
835 		default:
836 			retIntError();
837 		}
838 
839 	/* Postcondition: The access and parameters are valid and the object
840 	   being passed in is of the correct type if present.  We don't
841 	   explicitly state this since it's just regurgitating the checks
842 	   already performed above */
843 
844 	return( CRYPT_OK );
845 	}
846 #else
847 
848 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
preDispatchCheckKeysetAccess(IN_HANDLE const int objectHandle,IN_MESSAGE const MESSAGE_TYPE message,IN_BUFFER_C (sizeof (MESSAGE_KEYMGMT_INFO))const void * messageDataPtr,IN_ENUM (KEYMGMT_ITEM)const int messageValue,STDC_UNUSED const void * dummy)849 int preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,
850 								  IN_MESSAGE const MESSAGE_TYPE message,
851 								  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \
852 										const void *messageDataPtr,
853 								  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,
854 								  STDC_UNUSED const void *dummy )
855 	{
856 	UNUSED_ARG( messageDataPtr );
857 
858 	return( CRYPT_ERROR_PERMISSION );
859 	}
860 #endif /* USE_KEYSETS */
861