cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
certm_acl.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Cert Management ACLs *
4 * Copyright Peter Gutmann 1997-2005 *
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 /* Macro to access the secondary parameter ACL information for a given
19  parameter in a list of parameter ACLs */
20 
21 #define secParamInfo( parentACL, paramNo ) parentACL->secParamACL[ paramNo ]
22 
23 /* A pointer to the kernel data block */
24 
25 static KERNEL_DATA *krnlData = NULL;
26 
27 /****************************************************************************
28 * *
29 * Cert Management ACLs *
30 * *
31 ****************************************************************************/
32 
33 /* The ACL tables for each cert management action */
34 
35 static const CERTMGMT_ACL FAR_BSS certMgmtACLTbl[] = {
36  /* Create cert store */
38  ACTION_PERM_NONE, /* Cert dbx.use only */
39  { MKACP_END() } },
40 
41  /* Connect to cert store */
43  ACTION_PERM_NONE, /* Cert dbx.use only */
44  { MKACP_END() } },
45 
46  /* Disconnect from cert store */
48  ACTION_PERM_NONE, /* Cert dbx.use only */
49  { MKACP_END() } },
50 
51  /* Error information */
53  ACTION_PERM_NONE, /* Cert dbx.use only */
54  { MKACP_END() } },
55 
56  /* Add PKI user */
58  ACTION_PERM_NONE, /* Cert dbx.use only */
59  { MKACP_END() } },
60 
61  /* Cert request */
63  ACTION_PERM_NONE, /* Cert dbx.use only */
64  { MKACP_END() } },
65 
66  /* Cert renewal request */
68  ACTION_PERM_NONE, /* Cert dbx.use only */
69  { MKACP_END() } },
70 
71  /* Cert revocation request */
73  ACTION_PERM_NONE, /* Cert dbx.use only */
74  { MKACP_END() } },
75 
76  /* Cert creation */
78  ACTION_PERM_NONE_EXTERNAL, /* Cert mgmt.use only */
79  { MKACP_O( ST_CTX_PKC, /* CA key w/cert (see below) */
81  MKACP_O( ST_CERT_CERTREQ | ST_CERT_REQ_CERT,/* Cert request */
83  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN, /* CA cert */
84  ACL_FLAG_HIGH_STATE ) } },
85 
86  /* Confirmation of cert creation */
88  ACTION_PERM_NONE_EXTERNAL, /* Cert mgmt.use only */
89  { MKACP_UNUSED(),
90  MKACP_O( ST_CERT_CERT, /* Completed cert */
91  ACL_FLAG_HIGH_STATE ) } },
92 
93  /* Cancellation of cert creation */
95  ACTION_PERM_NONE_EXTERNAL, /* Cert mgmt.use only */
96  { MKACP_UNUSED(),
97  MKACP_O( ST_CERT_CERT, /* Completed cert */
98  ACL_FLAG_HIGH_STATE ) } },
99 
100  /* Cancel of creation w.revocation */
102  ACTION_PERM_NONE_EXTERNAL, /* Cert mgmt.use only */
103  { MKACP_UNUSED(),
104  MKACP_O( ST_CERT_CERT, /* Completed cert */
105  ACL_FLAG_HIGH_STATE ) } },
106 
107  /* Delete reqs after restart */
109  ACTION_PERM_NONE, /* Cert dbx.use only */
110  { MKACP_END() } },
111 
112  /* Complete revocation after restart */
114  ACTION_PERM_NONE, /* Cert dbx.use only */
115  { MKACP_END() } },
116 
117  /* Cert issue */
119  ACTION_PERM_ALL, /* Any access */
120  { MKACP_O( ST_CTX_PKC, /* CA key w/cert (see below) */
122  MKACP_O( ST_CERT_CERTREQ | ST_CERT_REQ_CERT,/* Cert request */
124  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN, /* CA cert */
125  ACL_FLAG_HIGH_STATE ) } },
126 
127  /* CRL issue */
129  ACTION_PERM_ALL, /* Any access */
130  { MKACP_O( ST_CTX_PKC, /* CA key w/cert (see below) */
132  MKACP_UNUSED() },
133  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN, /* CA cert */
134  ACL_FLAG_HIGH_STATE ) } },
135 
136  /* Cert revocation */
138  ACTION_PERM_ALL, /* Any access */
139  { MKACP_UNUSED(),
140  MKACP_O( ST_CERT_REQ_REV, /* Rev.request. Rev.reqs are usually */
141  ACL_FLAG_ANY_STATE ) } },/* unsigned, but may be in the high
142  state if imported from an external
143  source */
144 
145  /* Cert expiry */
147  ACTION_PERM_ALL, /* Any access */
148  { MKACP_UNUSED(),
149  MKACP_UNUSED() } },
150 
151  /* Clean up on restart */
153  ACTION_PERM_ALL, /* Any access */
154  { MKACP_UNUSED(),
155  MKACP_UNUSED() } },
156 
157  /* End-of-ACL marker */
160  { MKACP_END() } },
163  { MKACP_END() } }
164  };
165 
166 /****************************************************************************
167 * *
168 * Init/Shutdown Functions *
169 * *
170 ****************************************************************************/
171 
173 int initCertMgmtACL( INOUT KERNEL_DATA *krnlDataPtr )
174  {
175  int i;
176 
177  assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
178 
179  /* Perform a consistency check on the cert management ACLs */
180  for( i = 0; certMgmtACLTbl[ i ].action != MECHANISM_NONE && \
181  i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ); i++ )
182  {
183  const CERTMGMT_ACL *certMgmtACL = &certMgmtACLTbl[ i ];
184 
185  /* Actions and permissions are consistent */
186  ENSURES( certMgmtACL->action > CRYPT_CERTACTION_NONE && \
187  certMgmtACL->action < CRYPT_CERTACTION_LAST );
188  ENSURES( certMgmtACL->access == ACTION_PERM_NONE || \
189  certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL || \
190  certMgmtACL->access == ACTION_PERM_ALL );
191 
192  /* If it's a no-access ACL, all mechanisms should be blocked */
193  if( certMgmtACL->access == ACTION_PERM_NONE )
194  {
195  ENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_NONE );
196  continue;
197  }
198 
199  /* If it's an internal-only ACL, it always needs a request
200  parameter */
201  if( certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL )
202  {
203  if( paramInfo( certMgmtACL, 1 ).valueType != PARAM_VALUE_OBJECT || \
204  ( paramInfo( certMgmtACL, 1 ).subTypeA & \
206  ST_CERT_REQ_REV | ST_CERT_CERT ) ) || \
207  paramInfo( certMgmtACL, 1 ).subTypeB != ST_NONE || \
208  paramInfo( certMgmtACL, 1 ).subTypeC != ST_NONE )
209  {
210  DEBUG_DIAG(( "Certificate management ACLs inconsistent" ));
211  retIntError();
212  }
213  }
214 
215  /* If it requires a CA key parameter, it must be a private-key
216  context with the key loaded and an attached CA certificate */
217  if( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )
218  {
219  ENSURES( paramInfo( certMgmtACL, 0 ).subTypeA == ST_CTX_PKC && \
220  paramInfo( certMgmtACL, 0 ).subTypeB == ST_NONE && \
221  paramInfo( certMgmtACL, 0 ).subTypeC == ST_NONE && \
222  paramInfo( certMgmtACL, 0 ).flags == ACL_FLAG_HIGH_STATE );
223  if( ( secParamInfo( certMgmtACL, 0 ).subTypeA & \
224  ~( ST_CERT_CERT | ST_CERT_CERTCHAIN ) ) || \
225  secParamInfo( certMgmtACL, 0 ).subTypeB != ST_NONE || \
226  secParamInfo( certMgmtACL, 0 ).subTypeC != ST_NONE || \
227  secParamInfo( certMgmtACL, 0 ).flags != ACL_FLAG_HIGH_STATE )
228  {
229  DEBUG_DIAG(( "Certificate management ACLs inconsistent" ));
230  retIntError();
231  }
232  continue;
233  }
234  ENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_UNUSED );
235  }
236  ENSURES( i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ) );
237 
238  /* Set up the reference to the kernel data block */
239  krnlData = krnlDataPtr;
240 
241  return( CRYPT_OK );
242  }
243 
244 void endCertMgmtACL( void )
245  {
246  krnlData = NULL;
247  }
248 
249 /****************************************************************************
250 * *
251 * Cert Management ACL Check Functions *
252 * *
253 ****************************************************************************/
254 
255 /* Functions to implement the checks in the cert management ACL tables */
256 
258 int preDispatchCheckCertMgmtAccess( IN_HANDLE const int objectHandle,
260  IN_BUFFER_C( sizeof( MESSAGE_CERTMGMT_INFO ) ) \
261  const void *messageDataPtr,
262  IN_ENUM( CRYPT_CERTACTION ) \
263  const int messageValue,
264  STDC_UNUSED const void *dummy )
265  {
267  ( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;
268  const CERTMGMT_ACL *certMgmtACL = certMgmtACLTbl;
269  const OBJECT_INFO *objectTable = krnlData->objectTable;
270  int i;
271 
272  assert( isReadPtr( messageDataPtr, sizeof( MESSAGE_CERTMGMT_INFO ) ) );
273 
274  /* Precondition */
275  REQUIRES( isValidObject( objectHandle ) );
276  REQUIRES( message == MESSAGE_KEY_CERTMGMT || message == IMESSAGE_KEY_CERTMGMT );
277  REQUIRES( messageValue > CRYPT_CERTACTION_NONE && \
278  messageValue < CRYPT_CERTACTION_LAST );
279 
280  /* Find the appropriate ACL for this mechanism */
281  for( i = 0; certMgmtACL[ i ].action != messageValue && \
282  certMgmtACL[ i ].action != MECHANISM_NONE && \
283  i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL );
284  i++ );
285  ENSURES( i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ) );
286  ENSURES( certMgmtACL[ i ].action != MECHANISM_NONE );
287  certMgmtACL = &certMgmtACL[ i ];
288 
289  /* Make sure that the access is valid. Most cert management actions can
290  never be initiated explicitly (they're only used internally by the
291  cert management code), a few can be initiated explicitly but only
292  internally by some cert management protocols, and an even smaller
293  number can be initiated externally */
294  switch( certMgmtACL->access )
295  {
296  case ACTION_PERM_ALL:
297  /* Any access is valid */
298  break;
299 
301  /* Only internal access (e.g. from a cert management protocol)
302  is permitted */
303  if( !isInternalMessage( message ) )
304  return( CRYPT_ARGERROR_VALUE );
305  break;
306 
307  case ACTION_PERM_NONE:
308  /* No access is permitted, it's a value used only by the cert
309  management code */
310  return( CRYPT_ARGERROR_VALUE );
311 
312  default:
313  retIntError();
314  }
315 
316  /* Check the mechanism parameters */
317  if( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )
318  {
319  if( !fullObjectCheck( mechanismInfo->caKey, message ) || \
320  !isSameOwningObject( objectHandle, mechanismInfo->caKey ) )
321  return( CRYPT_ARGERROR_NUM1 );
322  if( !checkParamObject( paramInfo( certMgmtACL, 0 ), \
323  mechanismInfo->caKey ) )
324  return( CRYPT_ARGERROR_NUM1 );
325 
326  /* If there's a secondary parameter present, check it agains the
327  dependent object. We perform a basic isValidObject() check
328  rather than a fullObjectCheck() since the dependent object is
329  usually internal, and this would fail with an external message */
330  if( secParamInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )
331  {
332  const int dependentObject = \
333  objectTable[ mechanismInfo->caKey ].dependentObject;
334 
335  if( !isValidObject( dependentObject ) )
336  return( CRYPT_ARGERROR_NUM1 );
337  if( !checkParamObject( secParamInfo( certMgmtACL, 0 ), \
338  dependentObject ) )
339  return( CRYPT_ARGERROR_NUM1 );
340  }
341  }
342  else
343  {
344  REQUIRES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_UNUSED );
345 
346  if( mechanismInfo->caKey != CRYPT_UNUSED )
347  return( CRYPT_ARGERROR_NUM1 );
348  }
349  if( paramInfo( certMgmtACL, 1 ).valueType == PARAM_VALUE_OBJECT )
350  {
351  if( !fullObjectCheck( mechanismInfo->request, message ) || \
352  !isSameOwningObject( objectHandle, mechanismInfo->request ) )
353  return( CRYPT_ARGERROR_NUM2 );
354  if( !checkParamObject( paramInfo( certMgmtACL, 1 ), \
355  mechanismInfo->request ) )
356  return( CRYPT_ARGERROR_NUM2 );
357  }
358  else
359  {
360  REQUIRES( paramInfo( certMgmtACL, 1 ).valueType == PARAM_VALUE_UNUSED );
361 
362  if( mechanismInfo->request != CRYPT_UNUSED )
363  return( CRYPT_ARGERROR_NUM2 );
364  }
365 
366  return( CRYPT_OK );
367  }