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