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 ¶mObjectHandle,
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 ¶mObjectHandle,
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