cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cryptapi.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib External API Interface *
4 * Copyright Peter Gutmann 1997-2008 *
5 * *
6 ****************************************************************************/
7 
8 /* NSA motto: In God we trust... all others we monitor.
9  -- Stanley Miller */
10 #include "crypt.h"
11 #if defined( INC_ALL )
12  #include "rpc.h"
13 #else
14  #include "misc/rpc.h"
15 #endif /* Compiler-specific includes */
16 
17 /* Handlers for the various commands */
18 
19 static int cmdCertCheck( void *stateInfo, COMMAND_INFO *cmd )
20  {
21  assert( cmd->type == COMMAND_CERTCHECK );
22  assert( cmd->flags == COMMAND_FLAG_NONE );
23  assert( cmd->noArgs == 2 );
24  assert( cmd->noStrArgs == 0 );
25 
26  UNUSED_ARG( stateInfo );
27 
28  /* Perform basic server-side error checking */
29  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
30  return( CRYPT_ARGERROR_OBJECT );
31  if( !isHandleRangeValid( cmd->arg[ 1 ] ) && \
32  ( cmd->arg[ 1 ] != CRYPT_UNUSED ) )
33  return( CRYPT_ARGERROR_NUM1 );
34 
35  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_SIGCHECK, NULL,
36  cmd->arg[ 1 ] ) );
37  }
38 
39 static int cmdCertMgmt( void *stateInfo, COMMAND_INFO *cmd )
40  {
41  MESSAGE_CERTMGMT_INFO certMgmtInfo;
42  int status;
43 
44  assert( cmd->type == COMMAND_CERTMGMT );
45  assert( cmd->flags == COMMAND_FLAG_NONE || \
46  cmd->flags == COMMAND_FLAG_RET_NONE );
47  assert( cmd->noArgs == 4 );
48  assert( cmd->noStrArgs == 0 );
49 
50  UNUSED_ARG( stateInfo );
51 
52  /* Perform basic server-side error checking */
53  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
54  return( CRYPT_ARGERROR_OBJECT );
55  if( cmd->arg[ 1 ] < CRYPT_CERTACTION_FIRST_USER || \
56  cmd->arg[ 1 ] > CRYPT_CERTACTION_LAST_USER )
57  return( CRYPT_ARGERROR_VALUE );
58  if( !isHandleRangeValid( cmd->arg[ 2 ] ) && \
59  !( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \
60  cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \
61  cmd->arg[ 2 ] == CRYPT_UNUSED ) )
62  return( CRYPT_ARGERROR_NUM1 );
63  if( !isHandleRangeValid( cmd->arg[ 3 ] ) && \
64  !( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_ISSUE_CRL || \
65  cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \
66  cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \
67  cmd->arg[ 3 ] == CRYPT_UNUSED ) )
68  return( CRYPT_ARGERROR_NUM2 );
69 
70  setMessageCertMgmtInfo( &certMgmtInfo, cmd->arg[ 2 ], cmd->arg[ 3 ] );
71  if( cmd->flags == COMMAND_FLAG_RET_NONE )
72  /* If we aren't interested in the return value, set the crypt handle
73  to CRYPT_UNUSED to indicate that there's no need to return the
74  created cert object */
75  certMgmtInfo.cryptCert = CRYPT_UNUSED;
76  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_CERTMGMT,
77  &certMgmtInfo, cmd->arg[ 1 ] );
78  if( cryptStatusOK( status ) && cmd->flags != COMMAND_FLAG_RET_NONE )
79  cmd->arg[ 0 ] = certMgmtInfo.cryptCert;
80  return( status );
81  }
82 
83 static int cmdCertSign( void *stateInfo, COMMAND_INFO *cmd )
84  {
85  assert( cmd->type == COMMAND_CERTSIGN );
86  assert( cmd->flags == COMMAND_FLAG_NONE );
87  assert( cmd->noArgs == 2 );
88  assert( cmd->noStrArgs == 0 );
89 
90  UNUSED_ARG( stateInfo );
91 
92  /* Perform basic server-side error checking */
93  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
94  return( CRYPT_ARGERROR_OBJECT );
95  if( !isHandleRangeValid( cmd->arg[ 1 ] ) )
96  return( CRYPT_ARGERROR_NUM1 );
97 
98  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_SIGN, NULL,
99  cmd->arg[ 1 ] ) );
100  }
101 
102 static int cmdCreateObject( void *stateInfo, COMMAND_INFO *cmd )
103  {
104  MESSAGE_CREATEOBJECT_INFO createInfo;
105  BOOLEAN bindToOwner = FALSE, hasStrArg = FALSE;
106  int owner = DUMMY_INIT, status;
107 
108  assert( cmd->type == COMMAND_CREATEOBJECT );
109  assert( cmd->flags == COMMAND_FLAG_NONE );
110  assert( cmd->noArgs >= 2 && cmd->noArgs <= 4 );
111  assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 2 );
112 
113  UNUSED_ARG( stateInfo );
114 
115  /* Perform basic server-side error checking */
116  if( !isHandleRangeValid( cmd->arg[ 0 ] ) && \
117  cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
118  return( CRYPT_ARGERROR_OBJECT );
119  if( cmd->arg[ 1 ] <= OBJECT_TYPE_NONE || \
120  cmd->arg[ 1 ] >= OBJECT_TYPE_LAST )
121  return( CRYPT_ERROR_FAILED ); /* Internal error */
122  switch( cmd->arg[ 1 ] )
123  {
124  case OBJECT_TYPE_CONTEXT:
125  assert( cmd->noArgs == 3 );
126  assert( cmd->noStrArgs == 0 );
127  if( ( cmd->arg[ 2 ] <= CRYPT_ALGO_NONE || \
128  cmd->arg[ 2 ] >= CRYPT_ALGO_LAST_EXTERNAL ) && \
129  cmd->arg[ 2 ] != CRYPT_USE_DEFAULT )
130  return( CRYPT_ARGERROR_NUM1 );
131  break;
132 
134  assert( cmd->noArgs == 3 );
135  assert( cmd->noStrArgs == 0 );
136  if( cmd->arg[ 2 ] <= CRYPT_CERTTYPE_NONE || \
137  cmd->arg[ 2 ] >= CRYPT_CERTTYPE_LAST_EXTERNAL )
138  return( CRYPT_ARGERROR_NUM1 );
139  break;
140 
141  case OBJECT_TYPE_DEVICE:
142  assert( cmd->noArgs == 3 );
143  assert( cmd->noStrArgs == 1 );
144  if( cmd->arg[ 2 ] <= CRYPT_DEVICE_NONE || \
145  cmd->arg[ 2 ] >= CRYPT_DEVICE_LAST )
146  return( CRYPT_ARGERROR_NUM1 );
147  if( cmd->arg[ 2 ] == CRYPT_DEVICE_PKCS11 || \
148  cmd->arg[ 2 ] == CRYPT_DEVICE_CRYPTOAPI )
149  {
150  if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
151  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
152  return( CRYPT_ARGERROR_STR1 );
153  hasStrArg = TRUE;
154  }
155  break;
156 
157  case OBJECT_TYPE_KEYSET:
158  assert( cmd->noArgs == 4 );
159  assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );
160  if( cmd->arg[ 2 ] <= CRYPT_KEYSET_NONE || \
161  cmd->arg[ 2 ] >= CRYPT_KEYSET_LAST )
162  return( CRYPT_ARGERROR_NUM1 );
163  if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
164  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
165  return( CRYPT_ARGERROR_STR1 );
166  if( cmd->arg[ 3 ] < CRYPT_KEYOPT_NONE || \
167  cmd->arg[ 3 ] >= CRYPT_KEYOPT_LAST_EXTERNAL )
168  {
169  /* CRYPT_KEYOPT_NONE is a valid setting for this parameter */
170  return( CRYPT_ARGERROR_NUM2 );
171  }
172  hasStrArg = TRUE;
173  break;
174 
176  assert( cmd->noArgs == 3 );
177  assert( cmd->noStrArgs == 0 );
178  if( cmd->arg[ 2 ] <= CRYPT_FORMAT_NONE || \
179  cmd->arg[ 2 ] >= CRYPT_FORMAT_LAST_EXTERNAL )
180  return( CRYPT_ARGERROR_NUM1 );
181  break;
182 
183  case OBJECT_TYPE_SESSION:
184  assert( cmd->noArgs == 3 );
185  assert( cmd->noStrArgs == 0 );
186  if( cmd->arg[ 2 ] <= CRYPT_SESSION_NONE || \
187  cmd->arg[ 2 ] >= CRYPT_SESSION_LAST )
188  return( CRYPT_ARGERROR_NUM1 );
189  break;
190 
191  case OBJECT_TYPE_USER:
192  assert( cmd->noArgs == 2 );
193  assert( cmd->noStrArgs == 2 );
194  if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
195  cmd->strArgLen[ 0 ] >= CRYPT_MAX_TEXTSIZE )
196  return( CRYPT_ARGERROR_STR1 );
197  if( cmd->strArgLen[ 1 ] < MIN_NAME_LENGTH || \
198  cmd->strArgLen[ 1 ] >= CRYPT_MAX_TEXTSIZE )
199  return( CRYPT_ARGERROR_STR2 );
200  hasStrArg = TRUE;
201  break;
202 
203  default:
204  retIntError();
205  }
206 
207  /* If we're creating the object via a device, we should set the new
208  object owner to the device owner */
209  if( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
210  {
211  bindToOwner = TRUE;
212  owner = cmd->arg[ 0 ];
213  }
214 
215  /* Create the object via the device. Since we're usually doing this via
216  the system object which is invisible to the user, we have to use an
217  internal message for this one case */
218  setMessageCreateObjectInfo( &createInfo, cmd->arg[ 2 ] );
219  if( cmd->noArgs == 4 )
220  createInfo.arg2 = cmd->arg[ 3 ];
221  if( hasStrArg )
222  {
223  createInfo.strArg1 = cmd->strArg[ 0 ];
224  createInfo.strArgLen1 = cmd->strArgLen[ 0 ];
225  if( cmd->noStrArgs > 1 )
226  {
227  createInfo.strArg2 = cmd->strArg[ 1 ];
228  createInfo.strArgLen2 = cmd->strArgLen[ 1 ];
229  }
230  }
231  if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
232  {
234  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
235  cmd->arg[ 1 ] );
236  }
237  else
238  {
239  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DEV_CREATEOBJECT,
240  &createInfo, cmd->arg[ 1 ] );
241  }
242  if( cryptStatusError( status ) )
243  return( status );
244 
245  /* If the device used to create the object is bound to a thread, bind the
246  created object to the thread as well. If this fails, we don't return
247  the object to the caller since it would be returned in a potentially
248  unbound state */
249  if( bindToOwner )
250  {
251  int ownerID;
252 
253  status = krnlSendMessage( owner, IMESSAGE_GETATTRIBUTE, &ownerID,
255  if( cryptStatusOK( status ) )
256  status = krnlSendMessage( createInfo.cryptHandle,
257  IMESSAGE_SETATTRIBUTE, &ownerID,
259  if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )
260  {
262  return( status );
263  }
264  }
265 
266  /* Make the newly-created object externally visible if necessary. This
267  is only required when we're creating the object via the system
268  handle, which requires an internal message that leaves the object
269  internal */
270  if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
271  {
273  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
274  }
275  cmd->arg[ 0 ] = createInfo.cryptHandle;
276  return( CRYPT_OK );
277  }
278 
279 static int cmdCreateObjectIndirect( void *stateInfo, COMMAND_INFO *cmd )
280  {
281  MESSAGE_CREATEOBJECT_INFO createInfo;
282  int status;
283 
284  assert( cmd->type == COMMAND_CREATEOBJECT_INDIRECT );
285  assert( cmd->flags == COMMAND_FLAG_NONE );
286  assert( cmd->noArgs == 2 );
287  assert( cmd->noStrArgs == 1 );
288 
289  UNUSED_ARG( stateInfo );
290 
291  /* Perform basic server-side error checking */
292  if( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
293  return( CRYPT_ERROR_FAILED ); /* Internal error */
294  if( cmd->arg[ 1 ] != OBJECT_TYPE_CERTIFICATE )
295  return( CRYPT_ERROR_FAILED ); /* Internal error */
296  if( cmd->strArgLen[ 0 ] < MIN_CERTSIZE || \
297  cmd->strArgLen[ 0 ] >= MAX_INTLENGTH )
298  return( CRYPT_ARGERROR_STR1 );
299 
300  /* Create the object via the device. Since we're usually doing this via
301  the system object which is invisible to the user, we have to use an
302  internal message for this one case */
303  setMessageCreateObjectIndirectInfo( &createInfo, cmd->strArg[ 0 ],
304  cmd->strArgLen[ 0 ],
306  if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
307  {
310  &createInfo, OBJECT_TYPE_CERTIFICATE );
311  }
312  else
313  {
314  status = krnlSendMessage( cmd->arg[ 0 ],
316  &createInfo, OBJECT_TYPE_CERTIFICATE );
317  }
318  if( cryptStatusError( status ) )
319  return( status );
320 
321  /* Make the newly-created object externally visible */
323  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
324  cmd->arg[ 0 ] = createInfo.cryptHandle;
325  return( status );
326  }
327 
328 static int cmdDecrypt( void *stateInfo, COMMAND_INFO *cmd )
329  {
330  int algorithm, mode = CRYPT_MODE_NONE, status; /* int vs.enum */
331 
332  assert( cmd->type == COMMAND_DECRYPT );
333  assert( cmd->flags == COMMAND_FLAG_NONE );
334  assert( cmd->noArgs == 1 );
335  assert( cmd->noStrArgs == 1 );
336 
337  UNUSED_ARG( stateInfo );
338 
339  /* Perform basic server-side error checking */
340  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
341  &algorithm, CRYPT_CTXINFO_ALGO );
342  if( cryptStatusError( status ) )
343  return( status );
344  if( algorithm <= CRYPT_ALGO_LAST_CONVENTIONAL )
345  {
346  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
347  &mode, CRYPT_CTXINFO_MODE );
348  if( cryptStatusError( status ) )
349  return( status );
350  }
351  else
352  {
353  if( algorithm <= CRYPT_ALGO_LAST_PKC )
354  {
355  int blockSize;
356 
357  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
358  &blockSize, CRYPT_CTXINFO_KEYSIZE );
359  if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )
360  status = CRYPT_ARGERROR_NUM1;
361  if( cryptStatusError( status ) )
362  return( status );
363  }
364  }
365  if( cmd->strArgLen[ 0 ] < 0 )
366  return( CRYPT_ARGERROR_NUM1 );
367  if( mode == CRYPT_MODE_ECB || mode == CRYPT_MODE_CBC )
368  {
369  int blockSize;
370 
371  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
372  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
373  if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )
374  status = CRYPT_ARGERROR_NUM1;
375  if( cryptStatusError( status ) )
376  return( status );
377  }
378 
379  /* Make sure the IV has been set */
380  if( needsIV( mode ) && !isStreamCipher( algorithm ) )
381  {
383 
384  setMessageData( &msgData, NULL, 0 );
385  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,
386  &msgData, CRYPT_CTXINFO_IV );
387  if( cryptStatusError( status ) )
388  return( status );
389  }
390 
391  status = krnlSendMessage( cmd->arg[ 0 ],
392  ( isHashAlgo( algorithm ) || \
393  isMacAlgo( algorithm ) ) ? \
395  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : "",
396  cmd->strArgLen[ 0 ] );
397  if( isHashAlgo( algorithm ) || isMacAlgo( algorithm ) )
398  {
399  /* There's no data to return since the hashing doesn't change it */
400  cmd->strArgLen[ 0 ] = 0;
401  }
402  return( status );
403  }
404 
405 static int cmdDeleteAttribute( void *stateInfo, COMMAND_INFO *cmd )
406  {
407  assert( cmd->type == COMMAND_DELETEATTRIBUTE );
408  assert( cmd->flags == COMMAND_FLAG_NONE );
409  assert( cmd->noArgs == 2 );
410  assert( cmd->noStrArgs == 0 );
411 
412  UNUSED_ARG( stateInfo );
413 
414  /* Perform basic server-side error checking */
415  if( !isHandleRangeValid( cmd->arg[ 0 ] ) && \
416  cmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )
417  return( CRYPT_ARGERROR_OBJECT );
418  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
419  {
420  if( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \
421  cmd->arg[ 1 ] >= CRYPT_OPTION_LAST )
422  return( CRYPT_ARGERROR_NUM1 );
423  }
424  else
425  {
426  if( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \
427  cmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )
428  return( CRYPT_ARGERROR_NUM1 );
429  }
430 
431  /* Delete the attribute. Since we're usually doing this via the default
432  user object which is invisible to the user, we have to use an internal
433  message for this one case */
434  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
435  {
438  cmd->arg[ 1 ] ) );
439  }
440  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DELETEATTRIBUTE, NULL,
441  cmd->arg[ 1 ] ) );
442  }
443 
444 static int cmdDeleteKey( void *stateInfo, COMMAND_INFO *cmd )
445  {
446  MESSAGE_KEYMGMT_INFO deletekeyInfo;
447  int itemType = KEYMGMT_ITEM_PUBLICKEY;
448 
449  assert( cmd->type == COMMAND_DELETEKEY );
450  assert( cmd->flags == COMMAND_FLAG_NONE );
451  assert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );
452  assert( cmd->noStrArgs == 1 );
453 
454  UNUSED_ARG( stateInfo );
455 
456  /* Perform basic server-side error checking */
457  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
458  return( CRYPT_ARGERROR_OBJECT );
459  if( cmd->arg[ 1 ] <= CRYPT_KEYID_NONE || \
460  cmd->arg[ 1 ] >= CRYPT_KEYID_LAST_EXTERNAL )
461  return( CRYPT_ARGERROR_NUM1 );
462  if( cmd->arg[ 2 ] )
463  {
464  /* It's a special-case object being fetched from a CA store */
465  if( cmd->arg[ 2 ] == CRYPT_CERTTYPE_REQUEST_CERT )
466  itemType = KEYMGMT_ITEM_REQUEST;
467  else
468  {
469  if( cmd->arg[ 2 ] == CRYPT_CERTTYPE_PKIUSER )
470  itemType = KEYMGMT_ITEM_PKIUSER;
471  else
472  return( CRYPT_ARGERROR_NUM2 );
473  }
474  }
475  if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
476  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
477  return( CRYPT_ARGERROR_STR1 );
478 
479  /* Delete the key from the keyset. Unless the user has explicitly
480  specified a CA item to delete, we set the item type to delete to
481  public-key since private-key keysets will interpret this correctly
482  to mean they should also delete the associated private key */
483  setMessageKeymgmtInfo( &deletekeyInfo, cmd->arg[ 1 ], cmd->strArg[ 0 ],
484  cmd->strArgLen[ 0 ], NULL, 0, KEYMGMT_FLAG_NONE );
485  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_DELETEKEY,
486  &deletekeyInfo, itemType ) );
487  }
488 
489 static int cmdDestroyObject( void *stateInfo, COMMAND_INFO *cmd )
490  {
491  assert( cmd->type == COMMAND_DESTROYOBJECT );
492  assert( cmd->flags == COMMAND_FLAG_NONE );
493  assert( cmd->noArgs == 1 );
494  assert( cmd->noStrArgs == 0 );
495 
496  UNUSED_ARG( stateInfo );
497 
498  /* Perform basic server-side error checking */
499  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
500  return( CRYPT_ARGERROR_OBJECT );
501 
502  /* Decrement the object's reference count, which may or may not actually
503  destroy it (the kernel marks it as internal so it appears destroyed
504  to the caller) */
505  return( krnlSendNotifier( cmd->arg[ 0 ], MESSAGE_DECREFCOUNT ) );
506  }
507 
508 static int cmdEncrypt( void *stateInfo, COMMAND_INFO *cmd )
509  {
510  int algorithm, mode = CRYPT_MODE_NONE, status; /* int vs.enum */
511 
512  assert( cmd->type == COMMAND_ENCRYPT );
513  assert( cmd->flags == COMMAND_FLAG_NONE );
514  assert( cmd->noArgs == 1 );
515  assert( cmd->noStrArgs == 1 );
516 
517  UNUSED_ARG( stateInfo );
518 
519  /* Perform basic server-side error checking */
520  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
521  &algorithm, CRYPT_CTXINFO_ALGO );
522  if( cryptStatusError( status ) )
523  return( status );
524  if( algorithm <= CRYPT_ALGO_LAST_CONVENTIONAL )
525  {
526  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
527  &mode, CRYPT_CTXINFO_MODE );
528  if( cryptStatusError( status ) )
529  return( status );
530  }
531  else
532  {
533  if( algorithm <= CRYPT_ALGO_LAST_PKC )
534  {
535  int blockSize;
536 
537  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
538  &blockSize, CRYPT_CTXINFO_KEYSIZE );
539  if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )
540  status = CRYPT_ARGERROR_NUM1;
541  if( cryptStatusError( status ) )
542  return( status );
543  }
544  }
545  if( isHashAlgo( algorithm ) || isMacAlgo( algorithm ) )
546  {
547  /* For hash and MAC operations a length of zero is valid since this
548  is an indication to wrap up the hash operation */
549  if( cmd->strArgLen[ 0 ] < 0 )
550  return( CRYPT_ARGERROR_NUM1 );
551  }
552  else
553  {
554  if( cmd->strArgLen[ 0 ] <= 0 )
555  return( CRYPT_ARGERROR_NUM1 );
556  }
557  if( mode == CRYPT_MODE_ECB || mode == CRYPT_MODE_CBC )
558  {
559  int blockSize;
560 
561  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
562  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
563  if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )
564  status = CRYPT_ARGERROR_NUM1;
565  if( cryptStatusError( status ) )
566  return( status );
567  }
568 
569  /* If there's no IV set, generate one ourselves */
570  if( needsIV( mode ) && !isStreamCipher( algorithm ) )
571  {
573 
574  setMessageData( &msgData, NULL, 0 );
575  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,
576  &msgData, CRYPT_CTXINFO_IV );
577  if( cryptStatusError( status ) )
578  {
579  if( status == CRYPT_ERROR_NOTINITED )
580  krnlSendNotifier( cmd->arg[ 0 ], MESSAGE_CTX_GENIV );
581  else
582  return( status );
583  }
584  }
585 
586  status = krnlSendMessage( cmd->arg[ 0 ],
587  ( isHashAlgo( algorithm ) || \
588  isMacAlgo( algorithm ) ) ? \
590  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : "",
591  cmd->strArgLen[ 0 ] );
592  if( isHashAlgo( algorithm ) || isMacAlgo( algorithm ) )
593  {
594  /* There's no data to return since the hashing doesn't change it */
595  cmd->strArgLen[ 0 ] = 0;
596  }
597  return( status );
598  }
599 
600 static int cmdExportObject( void *stateInfo, COMMAND_INFO *cmd )
601  {
603  int status;
604 
605  assert( cmd->type == COMMAND_EXPORTOBJECT );
606  assert( cmd->flags == COMMAND_FLAG_NONE || \
607  cmd->flags == COMMAND_FLAG_RET_LENGTH );
608  assert( cmd->noArgs == 2 );
609  assert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \
610  ( cmd->flags == COMMAND_FLAG_RET_LENGTH && cmd->noStrArgs == 0 ) );
611  assert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \
612  cmd->strArg[ 0 ] != NULL );
613 
614  UNUSED_ARG( stateInfo );
615 
616  /* Perform basic server-side error checking */
617  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
618  return( CRYPT_ARGERROR_OBJECT );
619  if( cmd->arg[ 1 ] <= CRYPT_CERTFORMAT_NONE || \
620  cmd->arg[ 1 ] >= CRYPT_CERTFORMAT_LAST_EXTERNAL )
621  {
622  /* At the moment the only object that we can export is a cert, so we
623  make sure that the format type is valid for this */
624  return( CRYPT_ARGERROR_NUM1 );
625  }
626 
627  /* Export the cert */
628  if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
629  {
630  setMessageData( &msgData, NULL, 0 );
631  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_EXPORT,
632  &msgData, cmd->arg[ 1 ] );
633  if( cryptStatusOK( status ) )
634  cmd->arg[ 0 ] = msgData.length;
635  }
636  else
637  {
638  setMessageData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
639  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_EXPORT,
640  &msgData, cmd->arg[ 1 ] );
641  if( cryptStatusOK( status ) )
642  cmd->strArgLen[ 0 ] = msgData.length;
643  }
644 
645  /* If we try and export using a disallowed format (e.g. a
646  CRYPT_CERTFORMAT_CERTCHAIN from a cert request) we'll get an argument
647  value error that we need to convert into something more sensible.
648  The error type to report is somewhat debatable since either the
649  format type or the object can be regarded as being wrong, for example
650  when exporting a cert request as a cert chain the format is wrong but
651  when exporting a data-only object as anything the object is wrong.
652  To handle this, we report an argument value error as a numeric
653  parameter error for cases where the format is incorrect for the
654  object type, and a permission error for cases where the object can't
655  be exported externally */
656  if( status == CRYPT_ARGERROR_VALUE )
657  {
658  int type;
659 
660  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE, &type,
662  if( cryptStatusError( status ) )
663  return( CRYPT_ARGERROR_OBJECT );
664  status = ( type == CRYPT_CERTTYPE_CERTIFICATE || \
665  type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
666  type == CRYPT_CERTTYPE_CERTCHAIN || \
667  type == CRYPT_CERTTYPE_CERTREQUEST || \
668  type == CRYPT_CERTTYPE_CRL ) ? \
670  }
671 
672  return( status );
673  }
674 
675 static int cmdFlushData( void *stateInfo, COMMAND_INFO *cmd )
676  {
678  int status;
679 
680  assert( cmd->type == COMMAND_FLUSHDATA );
681  assert( cmd->flags == COMMAND_FLAG_NONE );
682  assert( cmd->noArgs == 1 );
683  assert( cmd->noStrArgs == 0 );
684 
685  UNUSED_ARG( stateInfo );
686 
687  /* Perform basic server-side error checking */
688  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
689  return( CRYPT_ARGERROR_OBJECT );
690 
691  /* Send the flush data command to the object */
692  setMessageData( &msgData, NULL, 0 );
693  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_PUSHDATA,
694  &msgData, 0 );
695  return( status );
696  }
697 
698 static int cmdGenKey( void *stateInfo, COMMAND_INFO *cmd )
699  {
700  assert( cmd->type == COMMAND_GENKEY );
701  assert( cmd->flags == COMMAND_FLAG_NONE );
702  assert( cmd->noArgs == 1 );
703  assert( cmd->noStrArgs == 0 );
704 
705  UNUSED_ARG( stateInfo );
706 
707  /* Perform basic server-side error checking */
708  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
709  return( CRYPT_ARGERROR_OBJECT );
710 
711  return( krnlSendNotifier( cmd->arg[ 0 ], MESSAGE_CTX_GENKEY ) );
712  }
713 
714 static int cmdGetAttribute( void *stateInfo, COMMAND_INFO *cmd )
715  {
717  int status;
718 
719  assert( cmd->type == COMMAND_GETATTRIBUTE );
720  assert( cmd->flags == COMMAND_FLAG_NONE || \
721  cmd->flags == COMMAND_FLAG_RET_LENGTH );
722  assert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );
723  assert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \
724  ( ( cmd->noArgs == 2 || cmd->flags == COMMAND_FLAG_RET_LENGTH ) && \
725  cmd->noStrArgs == 0 ) );
726 
727  UNUSED_ARG( stateInfo );
728 
729  /* Perform basic server-side error checking */
730  if( !isHandleRangeValid( cmd->arg[ 0 ] ) && \
731  cmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )
732  return( CRYPT_ARGERROR_OBJECT );
733  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
734  {
735  if( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \
736  cmd->arg[ 1 ] >= CRYPT_OPTION_LAST )
737  return( CRYPT_ARGERROR_NUM1 );
738  }
739  else
740  {
741  if( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \
742  cmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )
743  return( CRYPT_ARGERROR_NUM1 );
744  }
745 
746  /* Get the attribute data from the object. If it's a config option,
747  we're usually doing this via the default user object which is
748  invisible to the user, so we have to use an internal message for this
749  one case.
750 
751  This is further complicated by the fact that the kernel checks that
752  the destination memory is writeable and either returns an error (for
753  an external message) or throws an exception (for the internal message
754  required to access the user object) if it isn't. Since the external
755  API doesn't allow the specification of the returned data length, it
756  uses a worst-case estimate which may be much larger than the actual
757  buffer size, which the kernel will refuse to write to. To handle
758  this we first read the actual length and then ask for only that much
759  data, which the caller should have made available for the output */
760  if( cmd->noArgs == 2 )
761  {
762  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
763  {
765  IMESSAGE_GETATTRIBUTE, &cmd->arg[ 0 ],
766  cmd->arg[ 1 ] ) );
767  }
768  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
769  &cmd->arg[ 0 ], cmd->arg[ 1 ] ) );
770  }
771  setMessageData( &msgData, NULL, 0 );
772  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
773  {
775  IMESSAGE_GETATTRIBUTE_S, &msgData,
776  cmd->arg[ 1 ] );
777  }
778  else
779  {
780  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,
781  &msgData, cmd->arg[ 1 ] );
782  }
783  if( cryptStatusError( status ) )
784  return( status );
785  if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
786  {
787  cmd->arg[ 0 ] = msgData.length;
788  return( CRYPT_OK );
789  }
790  msgData.data = cmd->strArg[ 0 ];
791  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
792  {
794  IMESSAGE_GETATTRIBUTE_S, &msgData,
795  cmd->arg[ 1 ] );
796  }
797  else
798  {
799  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,
800  &msgData, cmd->arg[ 1 ] );
801  }
802  if( cryptStatusOK( status ) )
803  cmd->strArgLen[ 0 ] = msgData.length;
804  return( status );
805  }
806 
807 static int cmdGetKey( void *stateInfo, COMMAND_INFO *cmd )
808  {
809  MESSAGE_KEYMGMT_INFO getkeyInfo;
810  int messageType = ( cmd->arg[ 2 ] == CRYPT_KEYID_NONE ) ? \
812  int owner, status;
813 
814  assert( cmd->type == COMMAND_GETKEY );
815  assert( cmd->flags == COMMAND_FLAG_NONE );
816  assert( cmd->noArgs == 3 );
817  assert( cmd->noStrArgs >= 1 && cmd->noStrArgs <= 2 );
818 
819  UNUSED_ARG( stateInfo );
820 
821  /* Perform basic server-side error checking. Because of keyset queries
822  we have to accept CRYPT_KEYID_NONE as well as obviously valid key
823  ID's. In addition if we find a missing ID we pass the request in as
824  a keyset query (this is matched to an implicit GetFirstCert performed
825  by setting the query attribute, this isn't really possible using the
826  external API) */
827  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
828  return( CRYPT_ARGERROR_OBJECT );
829  if( cmd->arg[ 1 ] <= KEYMGMT_ITEM_NONE || \
830  cmd->arg[ 1 ] >= KEYMGMT_ITEM_REVOCATIONINFO )
831  {
832  /* Item can only be a public key, private key, secret key, CA
833  request, or CA PKI user info */
834  return( CRYPT_ARGERROR_NUM1 );
835  }
836  if( cmd->arg[ 2 ] < CRYPT_KEYID_NONE || \
837  cmd->arg[ 2 ] >= CRYPT_KEYID_LAST_EXTERNAL )
838  return( CRYPT_ARGERROR_NUM2 );
839  if( cmd->arg[ 2 ] == CRYPT_KEYID_NONE )
840  {
841  if( cmd->arg[ 1 ] != KEYMGMT_ITEM_PUBLICKEY )
842  {
843  /* If we're doing a keyset query, it has to be for a
844  certificate */
845  return( CRYPT_ARGERROR_NUM1 );
846  }
847  if( cmd->strArgLen[ 0 ] )
848  return( CRYPT_ARGERROR_NUM1 );
849  }
850  else
851  {
852  if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
853  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
854  return( CRYPT_ARGERROR_STR1 );
855  }
856 
857  /* Read the key from the keyset */
858  setMessageKeymgmtInfo( &getkeyInfo, cmd->arg[ 2 ],
859  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL,
860  cmd->strArgLen[ 0 ],
861  cmd->strArgLen[ 1 ] ? cmd->strArg[ 1 ] : NULL,
862  cmd->strArgLen[ 1 ], KEYMGMT_FLAG_NONE );
863  status = krnlSendMessage( cmd->arg[ 0 ], messageType, &getkeyInfo,
864  cmd->arg[ 1 ] );
865  if( cryptStatusError( status ) )
866  return( status );
867 
868  /* If the keyset is bound to a thread, bind the key read from it to the
869  thread as well. If this fails, we don't return the imported key to
870  the caller since it would be returned in a potentially unbound state */
871  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE, &owner,
873  if( cryptStatusOK( status ) )
874  {
875  status = krnlSendMessage( getkeyInfo.cryptHandle,
876  IMESSAGE_SETATTRIBUTE, &owner,
878  }
879  if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )
880  {
882  return( status );
883  }
884 
885  cmd->arg[ 0 ] = getkeyInfo.cryptHandle;
886  return( CRYPT_OK );
887  }
888 
889 static int cmdPopData( void *stateInfo, COMMAND_INFO *cmd )
890  {
892  int status;
893 
894  assert( cmd->type == COMMAND_POPDATA );
895  assert( cmd->flags == COMMAND_FLAG_NONE );
896  assert( cmd->noArgs == 2 );
897  assert( cmd->noStrArgs == 1 );
898 
899  UNUSED_ARG( stateInfo );
900 
901  /* Perform basic server-side error checking */
902  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
903  return( CRYPT_ARGERROR_OBJECT );
904  if( cmd->arg[ 1 ] < 1 )
905  return( CRYPT_ARGERROR_NUM1 );
906 
907  /* Get the data from the object. We always copy out the byte count value
908  because it's valid even if an error occurs */
909  setMessageData( &msgData, cmd->strArg[ 0 ], cmd->arg[ 1 ] );
910  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_POPDATA,
911  &msgData, 0 );
912  cmd->strArgLen[ 0 ] = msgData.length;
913  return( status );
914  }
915 
916 static int cmdPushData( void *stateInfo, COMMAND_INFO *cmd )
917  {
919  int status;
920 
921  assert( cmd->type == COMMAND_PUSHDATA );
922  assert( cmd->flags == COMMAND_FLAG_NONE );
923  assert( cmd->noArgs == 1 );
924  assert( cmd->noStrArgs == 1 );
925 
926  UNUSED_ARG( stateInfo );
927 
928  /* Perform basic server-side error checking */
929  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
930  return( CRYPT_ARGERROR_OBJECT );
931  if( cmd->strArgLen[ 0 ] < 0 )
932  return( CRYPT_ARGERROR_NUM1 );
933 
934  /* Send the data to the object. We always copy out the byte count value
935  because it's valid even if an error occurs */
936  setMessageData( &msgData, cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL,
937  cmd->strArgLen[ 0 ] );
938  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_PUSHDATA, &msgData,
939  0 );
940  cmd->arg[ 0 ] = msgData.length;
941  return( status );
942  }
943 
944 static int cmdQueryCapability( void *stateInfo, COMMAND_INFO *cmd )
945  {
947  int status;
948 
949  assert( cmd->type == COMMAND_QUERYCAPABILITY );
950  assert( cmd->flags == COMMAND_FLAG_NONE || \
951  cmd->flags == COMMAND_FLAG_RET_LENGTH );
952  assert( cmd->noArgs == 2 );
953  assert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \
954  ( cmd->flags == COMMAND_FLAG_RET_LENGTH && cmd->noStrArgs == 0 ) );
955  assert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \
956  cmd->strArg[ 0 ] != NULL );
957 
958  UNUSED_ARG( stateInfo );
959 
960  /* Perform basic server-side error checking */
961  if( !isHandleRangeValid( cmd->arg[ 0 ] ) && \
962  cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
963  return( CRYPT_ARGERROR_OBJECT );
964  if( cmd->arg[ 1 ] < CRYPT_ALGO_NONE || \
965  cmd->arg[ 1 ] >= CRYPT_ALGO_LAST_EXTERNAL )
966  return( CRYPT_ARGERROR_NUM1 );
967 
968  /* Query the device for information on the given algorithm and mode.
969  Since we're usually doing this via the system object which is
970  invisible to the user, we have to use an internal message for this
971  one case */
972  if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
973  {
975  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
976  cmd->arg[ 1 ] );
977  }
978  else
979  {
980  status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DEV_QUERYCAPABILITY,
981  &queryInfo, cmd->arg[ 1 ] );
982  }
983  if( cryptStatusOK( status ) )
984  {
985  /* Return either the length or the full capability into on what the
986  caller has asked for */
987  if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
988  cmd->arg[ 0 ] = sizeof( CRYPT_QUERY_INFO );
989  else
990  {
991  memcpy( cmd->strArg[ 0 ], &queryInfo,
992  sizeof( CRYPT_QUERY_INFO ) );
993  cmd->strArgLen[ 0 ] = sizeof( CRYPT_QUERY_INFO );
994  }
995  }
996 
997  return( status );
998  }
999 
1000 #ifdef USE_RPCAPI
1001 
1002 static int cmdServerQuery( void *stateInfo, COMMAND_INFO *cmd )
1003  {
1004  int value;
1005 
1006  assert( cmd->type == COMMAND_SERVERQUERY );
1007  assert( cmd->flags == COMMAND_FLAG_NONE );
1008  assert( cmd->noArgs == 0 );
1009  assert( cmd->noStrArgs == 0 );
1010 
1011  UNUSED_ARG( stateInfo );
1012 
1013  /* Return information about the server */
1018 
1019  return( CRYPT_OK );
1020  }
1021 #endif /* USE_RPCAPI */
1022 
1023 static int cmdSetAttribute( void *stateInfo, COMMAND_INFO *cmd )
1024  {
1026 
1027  assert( cmd->type == COMMAND_SETATTRIBUTE );
1028  assert( cmd->flags == COMMAND_FLAG_NONE );
1029  assert( ( cmd->noArgs == 3 && cmd->noStrArgs == 0 ) ||
1030  ( cmd->noArgs == 2 && cmd->noStrArgs == 1 ) );
1031 
1032  UNUSED_ARG( stateInfo );
1033 
1034  /* Perform basic server-side error checking */
1035  if( !isHandleRangeValid( cmd->arg[ 0 ] ) && \
1036  cmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )
1037  return( CRYPT_ARGERROR_OBJECT );
1038  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
1039  {
1040  if( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \
1041  cmd->arg[ 1 ] >= CRYPT_OPTION_LAST )
1042  return( CRYPT_ARGERROR_NUM1 );
1043  }
1044  else
1045  {
1046  if( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \
1047  cmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )
1048  return( CRYPT_ARGERROR_NUM1 );
1049  }
1050  if( cmd->noStrArgs == 1 )
1051  {
1052  if( cmd->arg[ 1 ] == CRYPT_CTXINFO_KEY_COMPONENTS )
1053  {
1054  /* Public key components constitute a special case since the
1055  composite structures used are quite large */
1056  if( cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_RSA ) && \
1057  cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_DLP ) && \
1058  cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_ECC ) )
1059  return( CRYPT_ARGERROR_NUM2 );
1060  }
1061  else
1062  {
1063  if( cmd->strArgLen[ 0 ] < 1 || \
1064  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
1065  return( CRYPT_ARGERROR_NUM2 );
1066  }
1067  }
1068 
1069  /* Send the attribute data to the object, mapping the return code to the
1070  correct value if necessary. If it's a config option, we're usually
1071  doing this via the default user object which is invisible to the user,
1072  so we have to use an internal message for this one case */
1073  if( cmd->noStrArgs == 0 )
1074  {
1075  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
1076  {
1079  ( MESSAGE_CAST ) &cmd->arg[ 2 ],
1080  cmd->arg[ 1 ] ) );
1081  }
1082  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_SETATTRIBUTE,
1083  ( MESSAGE_CAST ) &cmd->arg[ 2 ], cmd->arg[ 1 ] ) );
1084  }
1085  setMessageData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
1086  if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
1087  {
1089  IMESSAGE_SETATTRIBUTE_S, &msgData,
1090  cmd->arg[ 1 ] ) );
1091  }
1092  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_SETATTRIBUTE_S,
1093  &msgData, cmd->arg[ 1 ] ) );
1094  }
1095 
1096 static int cmdSetKey( void *stateInfo, COMMAND_INFO *cmd )
1097  {
1098  MESSAGE_KEYMGMT_INFO setkeyInfo;
1099  int itemType = ( cmd->noStrArgs == 1 ) ? \
1101 
1102  assert( cmd->type == COMMAND_SETKEY );
1103  assert( cmd->flags == COMMAND_FLAG_NONE );
1104  assert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );
1105  assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );
1106 
1107  UNUSED_ARG( stateInfo );
1108 
1109  /* Perform basic server-side error checking */
1110  if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
1111  return( CRYPT_ARGERROR_OBJECT );
1112  if( !isHandleRangeValid( cmd->arg[ 1 ] ) )
1113  return( CRYPT_ARGERROR_NUM1 );
1114  if( cmd->noStrArgs == 1 && \
1115  ( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
1116  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE ) )
1117  return( CRYPT_ARGERROR_STR1 );
1118  if( cmd->arg[ 2 ] )
1119  {
1120  int value;
1121 
1122  /* It's a cert management item request being added to a CA store,
1123  usually this is a request but it may also be PKI user info */
1124  itemType = KEYMGMT_ITEM_REQUEST;
1125  if( cryptStatusOK( krnlSendMessage( cmd->arg[ 1 ],
1126  MESSAGE_GETATTRIBUTE, &value,
1127  CRYPT_CERTINFO_CERTTYPE ) ) && \
1128  value == CRYPT_CERTTYPE_PKIUSER )
1129  itemType = KEYMGMT_ITEM_PKIUSER;
1130  }
1131  else
1132  {
1133  int value;
1134 
1135  /* If we're adding a CRL, add it as revocation information rather
1136  than as a generic public-key object */
1137  if( itemType != KEYMGMT_ITEM_PRIVATEKEY && \
1138  cryptStatusOK( krnlSendMessage( cmd->arg[ 1 ],
1139  MESSAGE_GETATTRIBUTE, &value,
1140  CRYPT_CERTINFO_CERTTYPE ) ) && \
1141  value == CRYPT_CERTTYPE_CRL )
1142  itemType = KEYMGMT_ITEM_REVOCATIONINFO;
1143  }
1144 
1145  /* Add the key */
1146  setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
1147  ( cmd->noStrArgs == 1 ) ? cmd->strArg[ 0 ] : NULL,
1148  cmd->strArgLen[ 0 ], KEYMGMT_FLAG_NONE );
1149  setkeyInfo.cryptHandle = cmd->arg[ 1 ];
1150  return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_SETKEY,
1151  &setkeyInfo, itemType ) );
1152  }
1153 
1154 #ifdef USE_RPCAPI
1155 
1156 /* Process a command from the client and send it to the appropriate handler */
1157 
1158 static const COMMAND_HANDLER commandHandlers[] = {
1159  NULL, NULL, cmdServerQuery, cmdCreateObject, cmdCreateObjectIndirect,
1160  cmdExportObject, cmdDestroyObject, cmdQueryCapability, cmdGenKey,
1161  cmdEncrypt, cmdDecrypt, cmdGetAttribute, cmdSetAttribute,
1162  cmdDeleteAttribute, cmdGetKey, cmdSetKey, cmdDeleteKey, cmdPushData,
1163  cmdPopData, cmdFlushData, cmdCertSign, cmdCertCheck, cmdCertMgmt };
1164 
1165 static void processCommand( BYTE *buffer )
1166  {
1167  COMMAND_INFO cmd = { 0 };
1168  BYTE header[ COMMAND_FIXED_DATA_SIZE ], *bufPtr;
1169  long totalLength;
1170  int i, status;
1171 
1172  /* Read the client's message header */
1173  memcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );
1174 
1175  /* Process the fixed message header and make sure it's valid */
1176  getMessageType( header, cmd.type, cmd.flags, cmd.noArgs, cmd.noStrArgs );
1177  totalLength = getMessageLength( header + COMMAND_WORDSIZE );
1178  if( !checkCommandInfo( &cmd, totalLength ) || \
1179  cmd.type == COMMAND_RESULT )
1180  {
1181  assert( DEBUG_WARN );
1182 
1183  /* Return an invalid result message */
1184  putMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );
1185  putMessageLength( buffer + COMMAND_WORDSIZE, 0 );
1186  return;
1187  }
1188 
1189  /* Read the rest of the clients message */
1190  bufPtr = buffer + COMMAND_FIXED_DATA_SIZE;
1191  for( i = 0; i < cmd.noArgs; i++ )
1192  {
1193  cmd.arg[ i ] = getMessageWord( bufPtr );
1194  bufPtr += COMMAND_WORDSIZE;
1195  }
1196  for( i = 0; i < cmd.noStrArgs; i++ )
1197  {
1198  cmd.strArgLen[ i ] = getMessageWord( bufPtr );
1199  cmd.strArg[ i ] = bufPtr + COMMAND_WORDSIZE;
1200  bufPtr += COMMAND_WORDSIZE + cmd.strArgLen[ i ];
1201  }
1202  if( !checkCommandConsistency( &cmd, totalLength ) )
1203  {
1204  assert( DEBUG_WARN );
1205 
1206  /* Return an invalid result message */
1207  putMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );
1208  putMessageLength( buffer + COMMAND_WORDSIZE, 0 );
1209  return;
1210  }
1211 
1212  /* If it's a command that returns a string value, obtain the returned
1213  data in the buffer. Normally we limit the size to the maximum
1214  attribute size, however encoded objects and data popped from
1215  envelopes/sessions can be larger than this so we use the entire buffer
1216  minus a safety margin */
1217  if( cmd.type == COMMAND_POPDATA || \
1218  ( cmd.flags != COMMAND_FLAG_RET_LENGTH && \
1219  ( cmd.type == COMMAND_EXPORTOBJECT || \
1220  cmd.type == COMMAND_QUERYCAPABILITY || \
1221  ( cmd.type == COMMAND_GETATTRIBUTE && \
1222  cmd.noArgs == 3 ) ) ) )
1223  {
1224  cmd.noStrArgs = 1;
1225  cmd.strArg[ 0 ] = bufPtr;
1226  if( cmd.type == COMMAND_EXPORTOBJECT || cmd.type == COMMAND_POPDATA )
1227  {
1228  cmd.strArgLen[ 0 ] = RPC_IO_BUFSIZE - 16 - ( bufPtr - buffer );
1229  assert( cmd.type != COMMAND_POPDATA || \
1230  cmd.strArgLen[ 0 ] >= MAX_FRAGMENT_SIZE );
1231  }
1232  else
1233  cmd.strArgLen[ 0 ] = MAX_ATTRIBUTE_SIZE;
1234  }
1235 
1236  /* Process the command and copy any return information back to the
1237  caller */
1238  status = commandHandlers[ cmd.type ]( NULL, &cmd );
1239  bufPtr = buffer;
1240  if( cryptStatusError( status ) )
1241  {
1242  /* The push data command is a special case since an error can occur
1243  after some data has been processed, so we still need to copy back
1244  a result even if we get an error status */
1245  if( cmd.type == COMMAND_PUSHDATA )
1246  {
1247  putMessageType( bufPtr, COMMAND_RESULT, 0, 2, 0 );
1249  putMessageWord( bufPtr + COMMAND_WORD1_OFFSET, status );
1250  putMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );
1251  return;
1252  }
1253 
1254  /* The command failed, return a simple status value */
1255  putMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );
1257  putMessageWord( bufPtr + COMMAND_WORD1_OFFSET, status );
1258  return;
1259  }
1260  if( cmd.type == COMMAND_CREATEOBJECT || \
1262  cmd.type == COMMAND_GETKEY || \
1263  cmd.type == COMMAND_PUSHDATA || \
1264  ( ( cmd.type == COMMAND_EXPORTOBJECT || \
1265  cmd.type == COMMAND_QUERYCAPABILITY ) && \
1266  cmd.flags == COMMAND_FLAG_RET_LENGTH ) || \
1267  ( cmd.type == COMMAND_GETATTRIBUTE && \
1268  ( cmd.noArgs == 2 || cmd.flags == COMMAND_FLAG_RET_LENGTH ) ) || \
1269  ( cmd.type == COMMAND_CERTMGMT && cmd.flags != COMMAND_FLAG_RET_NONE ) )
1270  {
1271  /* Return object handle or numeric value or string length */
1272  putMessageType( bufPtr, COMMAND_RESULT, 0, 2, 0 );
1275  putMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );
1276  return;
1277  }
1278  if( cmd.type == COMMAND_ENCRYPT || \
1279  cmd.type == COMMAND_DECRYPT || \
1280  cmd.type == COMMAND_POPDATA || \
1281  cmd.type == COMMAND_EXPORTOBJECT || \
1282  cmd.type == COMMAND_QUERYCAPABILITY || \
1283  cmd.type == COMMAND_GETATTRIBUTE )
1284  {
1285  const long dataLength = cmd.strArgLen[ 0 ];
1286 
1287  /* Return capability info or attribute data and length */
1288  putMessageType( bufPtr, COMMAND_RESULT, 0, 1, 1 );
1290  ( COMMAND_WORDSIZE * 2 ) + cmd.strArgLen[ 0 ] );
1292  putMessageWord( bufPtr + COMMAND_WORD2_OFFSET, dataLength );
1293  if( dataLength )
1294  memmove( bufPtr + COMMAND_WORD3_OFFSET, cmd.strArg[ 0 ],
1295  dataLength );
1296  return;
1297  }
1298  putMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );
1301  }
1302 
1303 /* Dummy forwarding procedure to take the place of the comms channel between
1304  client and server */
1305 
1306 static void serverTransact( void *clientBuffer )
1307  {
1308 #ifdef CONFIG_CONSERVE_MEMORY
1309  static BYTE *serverBuffer = NULL;
1310 #else
1311  BYTE serverBuffer[ RPC_IO_BUFSIZE ];
1312 #endif /* Memory-starved systems */
1313  int length;
1314 
1315  /* On memory-starved systems (typically older ones limited to a maximum
1316  of 64K of stack) we have to malloc() this on demand. Since there's
1317  no threading this is OK since there won't be any race conditions.
1318  Note that there's no way to free this, but it'll be automatically
1319  freed when the OS reclaims the application heap */
1320 #ifdef CONFIG_CONSERVE_MEMORY
1321  if( serverBuffer == NULL && \
1322  ( serverBuffer = clAlloc( "serverTransact", \
1323  RPC_IO_BUFSIZE ) ) == NULL )
1324  {
1325  memset( clientBuffer, 0, 16 );
1326  return;
1327  }
1328 #endif /* Memory-starved systems */
1329 
1330  /* Copy the command to the server buffer, process it, and copy the result
1331  back to the client buffer to emulate the client <-> server
1332  transmission */
1333  length = getMessageLength( ( BYTE * ) clientBuffer + COMMAND_WORDSIZE );
1334  memcpy( serverBuffer, clientBuffer, length + COMMAND_FIXED_DATA_SIZE );
1335  processCommand( serverBuffer );
1336  length = getMessageLength( ( BYTE * ) serverBuffer + COMMAND_WORDSIZE );
1337  memcpy( clientBuffer, serverBuffer, length + COMMAND_FIXED_DATA_SIZE );
1338  }
1339 
1340 /* Dispatch a command to the server */
1341 
1342 static int dispatchCommand( COMMAND_INFO *cmd )
1343  {
1344  COMMAND_INFO sentCmd = *cmd;
1345  BYTE buffer[ RPC_IO_BUFSIZE ], *bufPtr = buffer;
1346  BYTE header[ COMMAND_FIXED_DATA_SIZE ];
1347  BYTE *payloadStartPtr, *payloadPtr;
1348  const BOOLEAN isPushPop = \
1349  ( cmd->type == COMMAND_PUSHDATA || cmd->type == COMMAND_POPDATA ) ? \
1350  TRUE : FALSE;
1351  const BOOLEAN isDataCommand = \
1352  ( cmd->type == COMMAND_ENCRYPT || cmd->type == COMMAND_DECRYPT || \
1353  isPushPop ) ? TRUE : FALSE;
1354  const long payloadLength = ( cmd->noArgs * COMMAND_WORDSIZE ) + \
1355  ( cmd->noStrArgs * COMMAND_WORDSIZE ) + \
1356  cmd->strArgLen[ 0 ] + cmd->strArgLen[ 1 ];
1357  long dataLength = ( cmd->type == COMMAND_POPDATA ) ? \
1358  cmd->arg[ 1 ] : cmd->strArgLen[ 0 ], resultLength;
1359  int i;
1360 
1361  assert( checkCommandInfo( cmd, 0 ) );
1362 
1363  /* Clear the return value */
1364  memset( cmd, 0, sizeof( COMMAND_INFO ) );
1365 
1366  /* Make sure the data will fit into the buffer */
1367  if( !isDataCommand && \
1368  ( COMMAND_FIXED_DATA_SIZE + payloadLength ) > RPC_IO_BUFSIZE )
1369  {
1370  long maxLength = dataLength;
1371  int maxPos = 0;
1372 
1373  /* Find the longest arg (the one that contributes most to the
1374  problem) and report it as an error. We report the problem
1375  as being with the numeric rather than the string arg since
1376  string args with implicit lengths (e.g.text strings) have
1377  their length check in the API function, and all other string
1378  args are given as (data, length) pairs */
1379  for( i = 0; i < sentCmd.noStrArgs; i++ )
1380  {
1381  if( sentCmd.strArgLen[ i ] > maxLength )
1382  {
1383  maxLength = sentCmd.strArgLen[ i ];
1384  maxPos = i;
1385  }
1386  }
1387  return( CRYPT_ARGERROR_NUM1 - maxPos );
1388  }
1389 
1390  /* If it's a short-datasize command, process it and return immediately */
1391  if( !isDataCommand || ( dataLength < MAX_FRAGMENT_SIZE ) )
1392  {
1393  /* Write the header and message fields to the buffer */
1394  putMessageType( bufPtr, sentCmd.type, sentCmd.flags,
1395  sentCmd.noArgs, sentCmd.noStrArgs );
1396  putMessageLength( bufPtr + COMMAND_WORDSIZE, payloadLength );
1397  bufPtr += COMMAND_FIXED_DATA_SIZE;
1398  for( i = 0; i < sentCmd.noArgs; i++ )
1399  {
1400  putMessageWord( bufPtr, sentCmd.arg[ i ] );
1401  bufPtr += COMMAND_WORDSIZE;
1402  }
1403  for( i = 0; i < sentCmd.noStrArgs; i++ )
1404  {
1405  const int argLength = sentCmd.strArgLen[ i ];
1406 
1407  putMessageWord( bufPtr, argLength );
1408  if( argLength > 0 )
1409  memcpy( bufPtr + COMMAND_WORDSIZE, sentCmd.strArg[ i ],
1410  argLength );
1411  bufPtr += COMMAND_WORDSIZE + argLength;
1412  }
1413 
1414  /* Send the command to the server and read the servers message header */
1415  serverTransact( buffer );
1416  memcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );
1417 
1418  /* Process the fixed message header and make sure that it's valid */
1419  getMessageType( header, cmd->type, cmd->flags,
1420  cmd->noArgs, cmd->noStrArgs );
1421  resultLength = getMessageLength( header + COMMAND_WORDSIZE );
1422  if( !checkCommandInfo( cmd, resultLength ) || \
1423  cmd->type != COMMAND_RESULT )
1424  {
1425  assert( DEBUG_WARN );
1426  return( CRYPT_ERROR );
1427  }
1428 
1429  /* Read the rest of the server's message */
1430  bufPtr = buffer + COMMAND_FIXED_DATA_SIZE;
1431  for( i = 0; i < cmd->noArgs; i++ )
1432  {
1433  cmd->arg[ i ] = getMessageWord( bufPtr );
1434  bufPtr += COMMAND_WORDSIZE;
1435  }
1436  for( i = 0; i < cmd->noStrArgs; i++ )
1437  {
1438  cmd->strArgLen[ i ] = getMessageWord( bufPtr );
1439  cmd->strArg[ i ] = bufPtr + COMMAND_WORDSIZE;
1440  bufPtr += COMMAND_WORDSIZE + cmd->strArgLen[ i ];
1441  }
1442 
1443  /* The first value returned is the status code, if it's nonzero return
1444  it to the caller, otherwise move the other values down */
1445  if( cryptStatusError( cmd->arg[ 0 ] ) )
1446  {
1447  /* The push data command is a special case since it returns a
1448  bytes copied value even if an error occurs */
1449  if( sentCmd.type == COMMAND_PUSHDATA )
1450  {
1451  const int status = cmd->arg[ 0 ];
1452 
1453  cmd->arg[ 0 ] = cmd->arg[ 1 ];
1454  cmd->arg[ 1 ] = 0;
1455  cmd->noArgs--;
1456  return( status );
1457  }
1458  return( cmd->arg[ 0 ] );
1459  }
1460  assert( cryptStatusOK( cmd->arg[ 0 ] ) );
1461  for( i = 1; i < cmd->noArgs; i++ )
1462  cmd->arg[ i - 1 ] = cmd->arg[ i ];
1463  cmd->arg[ i ] = 0;
1464  cmd->noArgs--;
1465 
1466  /* Copy any string arg data back to the caller */
1467  if( cmd->noStrArgs && cmd->strArgLen[ 0 ] )
1468  {
1469  memcpy( sentCmd.strArg[ 0 ], cmd->strArg[ 0 ],
1470  cmd->strArgLen[ 0 ] );
1471  cmd->strArg[ 0 ] = sentCmd.strArg[ 0 ];
1472  if( cmd->type == COMMAND_PUSHDATA )
1473  {
1474  /* A data push returns the actual number of copied bytes
1475  (which may be less than the requested number of bytes) as
1476  arg 0 */
1477  cmd->arg[ 0 ] = cmd->strArgLen[ 0 ];
1478  }
1479  }
1480 
1481  return( CRYPT_OK );
1482  }
1483 
1484  /* Remember where the variable-length payload starts in the buffer and
1485  where it's to be copied to */
1486  payloadStartPtr = buffer + COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE;
1487  payloadPtr = sentCmd.strArg[ 0 ];
1488 
1489  /* It's a long-datasize command, handle fragmentation */
1490  do
1491  {
1492  COMMAND_INFO cmdResult = { 0 };
1493  const int fragmentLength = min( dataLength, MAX_FRAGMENT_SIZE );
1494  int status;
1495 
1496  /* Write the fixed and variable-length message fields to the buffer */
1497  putMessageType( buffer, sentCmd.type, 0, sentCmd.noArgs,
1498  sentCmd.noStrArgs );
1499  if( sentCmd.type == COMMAND_POPDATA )
1500  {
1501  putMessageLength( buffer + COMMAND_WORDSIZE,
1502  ( COMMAND_WORDSIZE * 2 ) );
1503  }
1504  else
1505  {
1506  putMessageLength( buffer + COMMAND_WORDSIZE,
1507  ( COMMAND_WORDSIZE * 2 ) + fragmentLength );
1508  }
1509  putMessageWord( buffer + COMMAND_FIXED_DATA_SIZE,
1510  sentCmd.arg[ 0 ] );
1511  putMessageWord( payloadStartPtr, fragmentLength );
1512  if( sentCmd.type != COMMAND_POPDATA )
1513  {
1514  memcpy( payloadStartPtr + COMMAND_WORDSIZE, payloadPtr,
1515  fragmentLength );
1516  }
1517 
1518  /* Process as much data as we can and read the server's message
1519  header */
1520  serverTransact( buffer );
1521  memcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );
1522 
1523  /* Process the fixed message header and make sure it's valid */
1524  getMessageType( header, cmdResult.type, cmdResult.flags,
1525  cmdResult.noArgs, cmdResult.noStrArgs );
1526  resultLength = getMessageLength( header + COMMAND_WORDSIZE );
1527  if( !checkCommandInfo( &cmdResult, resultLength ) || \
1528  cmdResult.type != COMMAND_RESULT || \
1529  cmdResult.flags != COMMAND_FLAG_NONE )
1530  {
1531  assert( DEBUG_WARN );
1532  return( CRYPT_ERROR );
1533  }
1534  if( cmdResult.noArgs != 1 || cmdResult.noStrArgs )
1535  {
1536  /* Make sure the parameters are valid for a non-error return */
1537  if( sentCmd.type == COMMAND_PUSHDATA )
1538  {
1539  if( cmdResult.noArgs != 2 || cmdResult.noStrArgs )
1540  {
1541  assert( DEBUG_WARN );
1542  return( CRYPT_ERROR );
1543  }
1544  }
1545  else
1546  if( cmdResult.noArgs != 1 || cmdResult.noStrArgs != 1 )
1547  {
1548  assert( DEBUG_WARN );
1549  return( CRYPT_ERROR );
1550  }
1551  }
1552 
1553  /* Process the fixed message header and make sure it's valid */
1554  bufPtr = buffer + COMMAND_FIXED_DATA_SIZE;
1555  status = getMessageWord( bufPtr );
1556  if( cryptStatusError( status ) )
1557  {
1558  /* The push data command is a special case since it returns a
1559  bytes copied value even if an error occurs */
1560  if( sentCmd.type == COMMAND_PUSHDATA )
1561  {
1562  const long bytesCopied = \
1563  getMessageWord( bufPtr + COMMAND_WORDSIZE );
1564 
1565  if( bytesCopied < 0 )
1566  {
1567  assert( DEBUG_WARN );
1568  return( CRYPT_ERROR );
1569  }
1570  cmdResult.arg[ 0 ] = cmd->arg[ 0 ] + bytesCopied;
1571  cmdResult.noArgs = 1;
1572  }
1573  *cmd = cmdResult;
1574  return( status );
1575  }
1576  assert( cryptStatusOK( status ) );
1577 
1578  /* Read the rest of the server's message */
1579  resultLength = getMessageWord( bufPtr + COMMAND_WORDSIZE );
1580  if( isPushPop )
1581  {
1582  /* It's a variable-length transformation, we have to return a
1583  non-negative number of bytes */
1584  if( resultLength <= 0 )
1585  {
1586  if( resultLength == 0 )
1587  {
1588  /* We've run out of data, return to the caller */
1589  break;
1590  }
1591  assert( DEBUG_WARN );
1592  return( CRYPT_ERROR );
1593  }
1594  if( cmd->type == COMMAND_PUSHDATA )
1595  cmd->arg[ 0 ] += resultLength;
1596  else
1597  cmd->strArgLen[ 0 ] += resultLength;
1598  if( sentCmd.type == COMMAND_POPDATA )
1599  {
1600  memcpy( payloadPtr, payloadStartPtr + COMMAND_WORDSIZE,
1601  resultLength );
1602 
1603  /* If we got less than what we asked for, there's nothing
1604  more available, exit */
1605  if( resultLength < fragmentLength )
1606  dataLength = resultLength;
1607  }
1608  }
1609  else
1610  {
1611  /* It's an encrypt/decrypt, the result must be a 1:1
1612  transformation unless it's a hash, in which case nothing is
1613  returned */
1614  if( resultLength )
1615  {
1616  if( resultLength != fragmentLength )
1617  {
1618  assert( DEBUG_WARN );
1619  return( CRYPT_ERROR );
1620  }
1621  memcpy( payloadPtr, payloadStartPtr + COMMAND_WORDSIZE,
1622  resultLength );
1623  }
1624  else
1625  {
1626  /* If no data was returned, it was a hash, set a pseudo-
1627  result length which is the same size as the amount of
1628  data fed in */
1629  resultLength = fragmentLength;
1630  }
1631  }
1632 
1633  /* Move on to the next fragment */
1634  payloadPtr += resultLength;
1635  dataLength -= resultLength;
1636  }
1637  while( dataLength > 0 );
1638 
1639  return( CRYPT_OK );
1640  }
1641 #endif /* USE_RPCAPI */
1642 
1643 /****************************************************************************
1644 * *
1645 * Client-side Translation Handling *
1646 * *
1647 ****************************************************************************/
1648 
1649 /* When the cryptlib client is using a different character set, we need to
1650  map from the internal to the external character set. The following
1651  function checks for attribute values that contain text strings. In
1652  addition the functions cryptGetKey(), cryptGetPrivateKey(),
1653  cryptAddPrivateKey(), and cryptLogin() use text strings that need to be
1654  mapped to the internal character set */
1655 
1656 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
1657 
1658 static BOOLEAN needsTranslation( const CRYPT_ATTRIBUTE_TYPE attribute )
1659  {
1660  if( attribute < CRYPT_CTXINFO_LAST )
1661  {
1662  if( attribute < CRYPT_OPTION_LAST )
1663  {
1664  return( ( attribute == CRYPT_ATTRIBUTE_ERRORMESSAGE || \
1665  attribute == CRYPT_OPTION_INFO_DESCRIPTION || \
1666  attribute == CRYPT_OPTION_INFO_COPYRIGHT || \
1667  attribute == CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS || \
1668  attribute == CRYPT_OPTION_KEYS_LDAP_FILTER || \
1669  attribute == CRYPT_OPTION_KEYS_LDAP_CACERTNAME || \
1670  attribute == CRYPT_OPTION_KEYS_LDAP_CERTNAME || \
1671  attribute == CRYPT_OPTION_KEYS_LDAP_CRLNAME || \
1672  attribute == CRYPT_OPTION_KEYS_LDAP_EMAILNAME ) ? \
1673  TRUE : FALSE );
1674  }
1675  return( ( attribute == CRYPT_CTXINFO_NAME_ALGO || \
1676  attribute == CRYPT_CTXINFO_NAME_MODE || \
1677  attribute == CRYPT_CTXINFO_KEYING_VALUE || \
1678  attribute == CRYPT_CTXINFO_LABEL ) ? \
1679  TRUE : FALSE );
1680  }
1681  if( attribute <= CRYPT_CERTINFO_LAST_NAME )
1682  {
1683  if( attribute < CRYPT_CERTINFO_FIRST_NAME )
1684  {
1685  return( ( attribute == CRYPT_CERTINFO_DN || \
1686  attribute == CRYPT_CERTINFO_PKIUSER_ID || \
1687  attribute == CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD || \
1688  attribute == CRYPT_CERTINFO_PKIUSER_REVPASSWORD ) ? \
1689  TRUE : FALSE );
1690  }
1691  return( ( attribute == CRYPT_CERTINFO_COUNTRYNAME || \
1692  attribute == CRYPT_CERTINFO_STATEORPROVINCENAME || \
1693  attribute == CRYPT_CERTINFO_LOCALITYNAME || \
1694  attribute == CRYPT_CERTINFO_ORGANIZATIONNAME || \
1695  attribute == CRYPT_CERTINFO_ORGANIZATIONALUNITNAME || \
1696  attribute == CRYPT_CERTINFO_COMMONNAME || \
1697  attribute == CRYPT_CERTINFO_OTHERNAME_TYPEID || \
1698  attribute == CRYPT_CERTINFO_RFC822NAME || \
1699  attribute == CRYPT_CERTINFO_DNSNAME || \
1701  attribute == CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME || \
1702  attribute == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER ) ? \
1703  TRUE : FALSE );
1704  }
1705  if( attribute <= CRYPT_CERTINFO_LAST_EXTENSION )
1706  {
1707  return( ( attribute == CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY || \
1709  attribute == CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY || \
1710  attribute == CRYPT_CERTINFO_SIGG_RESTRICTION || \
1711  attribute == CRYPT_CERTINFO_SUBJECTDIR_TYPE || \
1712  attribute == CRYPT_CERTINFO_CERTPOLICYID || \
1713  attribute == CRYPT_CERTINFO_CERTPOLICY_CPSURI || \
1714  attribute == CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION || \
1715  attribute == CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT || \
1716  attribute == CRYPT_CERTINFO_ISSUERDOMAINPOLICY || \
1717  attribute == CRYPT_CERTINFO_SUBJECTDOMAINPOLICY || \
1718  attribute == CRYPT_CERTINFO_SET_MERID || \
1719  attribute == CRYPT_CERTINFO_SET_MERACQUIRERBIN || \
1720  attribute == CRYPT_CERTINFO_SET_MERCHANTLANGUAGE || \
1721  attribute == CRYPT_CERTINFO_SET_MERCHANTNAME || \
1722  attribute == CRYPT_CERTINFO_SET_MERCHANTCITY || \
1724  attribute == CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE || \
1725  attribute == CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME || \
1726  attribute == CRYPT_CERTINFO_SET_MERCOUNTRY || \
1727  attribute == CRYPT_CERTINFO_SET_MERAUTHFLAG ) ? \
1728  TRUE : FALSE );
1729  }
1730  if( attribute <= CRYPT_CERTINFO_LAST_CMS )
1731  {
1732  return( ( attribute == CRYPT_CERTINFO_CMS_SECLABEL_POLICY || \
1733  attribute == CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK || \
1734  attribute == CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE || \
1735  attribute == CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE || \
1737  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_POLICY || \
1738  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK || \
1739  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE || \
1740  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE || \
1741  attribute == CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES || \
1742  attribute == CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME || \
1743  attribute == CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL || \
1744  attribute == CRYPT_CERTINFO_CMS_SPCAGENCYURL ) ? \
1745  TRUE : FALSE );
1746  }
1747  if( attribute < CRYPT_KEYINFO_LAST )
1748  return( ( attribute == CRYPT_KEYINFO_QUERY || \
1749  attribute == CRYPT_KEYINFO_QUERY_REQUESTS ) ? \
1750  TRUE : FALSE );
1751  if( attribute < CRYPT_DEVINFO_LAST )
1752  {
1753  return( ( attribute == CRYPT_DEVINFO_INITIALISE || \
1754  attribute == CRYPT_DEVINFO_AUTHENT_USER || \
1755  attribute == CRYPT_DEVINFO_AUTHENT_SUPERVISOR || \
1756  attribute == CRYPT_DEVINFO_SET_AUTHENT_USER || \
1757  attribute == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR || \
1758  attribute == CRYPT_DEVINFO_ZEROISE || \
1759  attribute == CRYPT_DEVINFO_LABEL ) ? \
1760  TRUE : FALSE );
1761  }
1762  if( attribute < CRYPT_ENVINFO_LAST )
1763  {
1764  return( ( attribute == CRYPT_ENVINFO_PASSWORD || \
1765  attribute == CRYPT_ENVINFO_RECIPIENT || \
1766  attribute == CRYPT_ENVINFO_PRIVATEKEY_LABEL ) ? \
1767  TRUE : FALSE );
1768  }
1769  if( attribute < CRYPT_SESSINFO_LAST )
1770  {
1771  return( ( attribute == CRYPT_SESSINFO_USERNAME || \
1772  attribute == CRYPT_SESSINFO_PASSWORD || \
1773  attribute == CRYPT_SESSINFO_SERVER_NAME || \
1774  attribute == CRYPT_SESSINFO_CLIENT_NAME ) ? \
1775  TRUE : FALSE );
1776  }
1777  return( ( attribute == CRYPT_USERINFO_PASSWORD ) ? TRUE : FALSE );
1778  }
1779 
1780 #ifdef EBCDIC_CHARS
1781  #define nativeStrlen( string ) strlen( string )
1782  #define nativeToCryptlibString( dest, destMaxLen, src, length ) \
1783  ebcdicToAscii( dest, src, length )
1784  #define cryptlibToNativeString( dest, destMaxLen, src, length ) \
1785  asciiToEbcdic( dest, src, length )
1786 #else
1787  #define nativeStrlen( string ) wcslen( string )
1788  #define nativeToCryptlibString( dest, destMaxLen, src, length ) \
1789  unicodeToAscii( dest, destMaxLen, src, length )
1790  #define cryptlibToNativeString( dest, destMaxLen, src, length ) \
1791  asciiToUnicode( dest, destMaxLen, src, length )
1792 #endif /* EBCDIC vs. Unicode translation */
1793 
1794 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
1795 
1796 /****************************************************************************
1797 * *
1798 * Utility Functions *
1799 * *
1800 ****************************************************************************/
1801 
1802 /* Some functions take null-terminated strings as parameters, since these
1803  can be ASCII or Unicode strings depending on the environment we need to
1804  define a situation-specific get-string-length function to handle them */
1805 
1806 #ifdef nativeStrlen
1807  #define strParamLen nativeStrlen
1808 #else
1809  #define strParamLen strlen
1810 #endif /* System-specific string parameter length functions */
1811 
1812 /* Internal parameter errors are reported in terms of the parameter type (eg
1813  invalid object, invalid attribute), but externally they're reported in
1814  terms of parameter numbers. Before we return error values to the caller,
1815  we have to map them from the internal representation to the position they
1816  occur in in the function parameter list. The following function takes a
1817  list of parameter types and maps the returned parameter type error to a
1818  parameter position error */
1819 
1820 typedef enum {
1821  ARG_D, /* Dummy placeholder */
1822  ARG_O, /* Object */
1823  ARG_V, /* Value (attribute) */
1824  ARG_N, /* Numeric arg */
1825  ARG_S, /* String arg */
1827  } ERRORMAP;
1828 
1829 static int mapError( const ERRORMAP *errorMap, const int errorMapSize,
1830  const int status )
1831  {
1832  ERRORMAP type;
1833  int count = 0, i;
1834 
1835  /* If it's not an internal parameter error, let it out */
1836  if( !cryptArgError( status ) )
1837  {
1838  assert( cryptStandardError( status ) );
1839  return( status );
1840  }
1841 
1842  /* Map the parameter error to a position error */
1843  switch( status )
1844  {
1845  case CRYPT_ARGERROR_OBJECT:
1846  type = ARG_O;
1847  break;
1848  case CRYPT_ARGERROR_VALUE:
1849  type = ARG_V;
1850  break;
1851  case CRYPT_ARGERROR_NUM1:
1852  case CRYPT_ARGERROR_NUM2:
1853  type = ARG_N;
1854  count = CRYPT_ARGERROR_NUM1 - status;
1855  break;
1856  case CRYPT_ARGERROR_STR1:
1857  case CRYPT_ARGERROR_STR2:
1858  type = ARG_S;
1859  count = CRYPT_ARGERROR_STR1 - status;
1860  break;
1861  default:
1862  retIntError();
1863  }
1864  for( i = 0; errorMap[ i ] != ARG_LAST && \
1865  i < errorMapSize; i++ )
1866  {
1867  if( errorMap[ i ] == type && !count-- )
1868  return( CRYPT_ERROR_PARAM1 - i );
1869  }
1870  if( i >= errorMapSize )
1871  retIntError();
1872  retIntError();
1873  }
1874 
1875 /****************************************************************************
1876 * *
1877 * Create/Destroy Objects *
1878 * *
1879 ****************************************************************************/
1880 
1881 /* A flag to record whether the external API initialisation function has
1882  been called. This merely reflects the current state of the cryptInit()/
1883  cryptEnd() calls at the external API level rather than the internal state
1884  of the kernel, and is used to try and catch problems with people who
1885  don't call cryptInit() */
1886 
1887 static BOOLEAN initCalled = FALSE;
1888 
1889 /* Initialise and shut down cryptlib. These functions are a type of super-
1890  create/destroy in that they create/destroy an instantiation of cryptlib.
1891  Unlike the other functions in this module, these can't pass control to
1892  the kernel because it hasn't been instantiated yet, so they pass the call
1893  down to the internal init/shutodwn functions */
1894 
1896  {
1897  int status;
1898 
1899  status = initCryptlib();
1900  if( cryptStatusOK( status ) )
1901  initCalled = TRUE;
1902  return( status );
1903  }
1904 
1906  {
1907  initCalled = FALSE;
1908  return( endCryptlib() );
1909  }
1910 
1911 /* Create an encryption context */
1912 
1916  {
1917  static const COMMAND_INFO FAR_BSS cmdTemplate = \
1920  static const ERRORMAP FAR_BSS errorMap[] = \
1921  { ARG_D, ARG_O, ARG_N, ARG_N, ARG_LAST, ARG_LAST };
1922  COMMAND_INFO cmd;
1923  int status;
1924 
1925  /* Perform basic client-side error checking */
1926  if( !isWritePtrConst( cryptContext, sizeof( CRYPT_CONTEXT ) ) )
1927  return( CRYPT_ERROR_PARAM1 );
1928  *cryptContext = CRYPT_ERROR;
1929  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
1930  return( CRYPT_ERROR_PARAM2 );
1931  if( ( cryptAlgo <= CRYPT_ALGO_NONE || \
1932  cryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL ) && \
1933  cryptAlgo != CRYPT_USE_DEFAULT )
1934  return( CRYPT_ERROR_PARAM3 );
1935 
1936  /* Make sure that the user has remembered to initialise cryptlib */
1937  if( !initCalled )
1938  return( CRYPT_ERROR_NOTINITED );
1939 
1940  /* Dispatch the command */
1941  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
1942  if( cryptUser != CRYPT_UNUSED )
1943  cmd.arg[ 0 ] = cryptUser;
1944  cmd.arg[ 2 ] = cryptAlgo;
1945  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
1946  if( cryptStatusOK( status ) )
1947  {
1948  *cryptContext = cmd.arg[ 0 ];
1949  return( CRYPT_OK );
1950  }
1951  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
1952  status ) );
1953  }
1954 
1955 /* Create an encryption context via the device */
1956 
1960  {
1961  static const COMMAND_INFO FAR_BSS cmdTemplate = \
1963  { 0, OBJECT_TYPE_CONTEXT } };
1964  static const ERRORMAP FAR_BSS errorMap[] = \
1965  { ARG_O, ARG_D, ARG_N, ARG_N, ARG_LAST, ARG_LAST };
1966  COMMAND_INFO cmd;
1967  int status;
1968 
1969  /* Perform basic client-side error checking */
1970  if( !isHandleRangeValid( device ) )
1971  return( CRYPT_ERROR_PARAM1 );
1972  if( !isWritePtrConst( cryptContext, sizeof( CRYPT_CONTEXT ) ) )
1973  return( CRYPT_ERROR_PARAM2 );
1974  *cryptContext = CRYPT_ERROR;
1975  if( ( cryptAlgo <= CRYPT_ALGO_NONE || \
1976  cryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL ) && \
1977  cryptAlgo != CRYPT_USE_DEFAULT )
1978  return( CRYPT_ERROR_PARAM3 );
1979 
1980  /* Make sure that the user has remembered to initialise cryptlib */
1981  if( !initCalled )
1982  return( CRYPT_ERROR_NOTINITED );
1983 
1984  /* Dispatch the command */
1985  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
1986  cmd.arg[ 0 ] = device;
1987  cmd.arg[ 2 ] = cryptAlgo;
1988  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
1989  if( cryptStatusOK( status ) )
1990  {
1991  *cryptContext = cmd.arg[ 0 ];
1992  return( CRYPT_OK );
1993  }
1994  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
1995  status ) );
1996  }
1997 
1998 /* Create a certificate */
1999 
2003  {
2004  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2007  static const ERRORMAP FAR_BSS errorMap[] = \
2008  { ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };
2009  COMMAND_INFO cmd;
2010  int status;
2011 
2012  /* Perform basic client-side error checking */
2013  if( !isWritePtrConst( certificate, sizeof( CRYPT_CERTIFICATE ) ) )
2014  return( CRYPT_ERROR_PARAM1 );
2015  *certificate = CRYPT_ERROR;
2016  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2017  return( CRYPT_ERROR_PARAM2 );
2018  if( certType <= CRYPT_CERTTYPE_NONE || \
2019  certType >= CRYPT_CERTTYPE_LAST_EXTERNAL )
2020  return( CRYPT_ERROR_PARAM3 );
2021 
2022  /* Make sure that the user has remembered to initialise cryptlib */
2023  if( !initCalled )
2024  return( CRYPT_ERROR_NOTINITED );
2025 
2026  /* Dispatch the command */
2027  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2028  if( cryptUser != CRYPT_UNUSED )
2029  cmd.arg[ 0 ] = cryptUser;
2030  cmd.arg[ 2 ] = certType;
2031  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2032  if( cryptStatusOK( status ) )
2033  {
2034  *certificate = cmd.arg[ 0 ];
2035  return( CRYPT_OK );
2036  }
2037  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2038  status ) );
2039  }
2040 
2041 /* Open a device */
2042 
2046  C_IN_OPT C_STR name )
2047  {
2048  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2051  static const ERRORMAP FAR_BSS errorMap[] = \
2052  { ARG_D, ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
2053  COMMAND_INFO cmd;
2054 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2055  BYTE nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *namePtr = NULL;
2056 #else
2057  const char *namePtr = name;
2058 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2059  int nameLen = 0, status;
2060 
2061  /* Perform basic error checking */
2062  if( !isReadPtrConst( device, sizeof( CRYPT_DEVICE ) ) )
2063  return( CRYPT_ERROR_PARAM1 );
2064  *device = CRYPT_ERROR;
2065  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2066  return( CRYPT_ERROR_PARAM2 );
2067  if( deviceType <= CRYPT_DEVICE_NONE || deviceType >= CRYPT_DEVICE_LAST )
2068  return( CRYPT_ERROR_PARAM3 );
2069  if( ( deviceType == CRYPT_DEVICE_PKCS11 || \
2070  deviceType == CRYPT_DEVICE_CRYPTOAPI ) && \
2071  ( !isReadPtrConst( name, MIN_NAME_LENGTH ) || \
2072  strParamLen( name ) < MIN_NAME_LENGTH || \
2073  strParamLen( name ) >= MAX_ATTRIBUTE_SIZE ) )
2074  return( CRYPT_ERROR_PARAM4 );
2075 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2076  if( name != NULL )
2077  {
2078  status = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,
2079  name, nativeStrlen( name ) + 1 );
2080  if( cryptStatusError( status ) )
2081  return( CRYPT_ERROR_PARAM4 );
2082  namePtr = nameBuffer;
2083  }
2084 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2085 
2086  /* Check and clean up any string parameters if required */
2087  if( namePtr != NULL )
2088  {
2089  nameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );
2090  if( nameLen <= 0 )
2091  return( CRYPT_ERROR_PARAM4 );
2092  }
2093 
2094  /* Make sure that the user has remembered to initialise cryptlib */
2095  if( !initCalled )
2096  return( CRYPT_ERROR_NOTINITED );
2097 
2098  /* Dispatch the command */
2099  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2100  if( cryptUser != CRYPT_UNUSED )
2101  cmd.arg[ 0 ] = cryptUser;
2102  cmd.arg[ 2 ] = deviceType;
2103  cmd.strArg[ 0 ] = ( void * ) namePtr;
2104  cmd.strArgLen[ 0 ] = nameLen;
2105  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2106  if( cryptStatusOK( status ) )
2107  {
2108  *device = cmd.arg[ 0 ];
2109  return( CRYPT_OK );
2110  }
2111  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2112  status ) );
2113  }
2114 
2115 /* Create an envelope */
2116 
2120  {
2121  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2124  static const ERRORMAP FAR_BSS errorMap[] = \
2125  { ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };
2126  COMMAND_INFO cmd;
2127  int status;
2128 
2129  /* Perform basic error checking */
2130  if( !isWritePtrConst( envelope, sizeof( CRYPT_ENVELOPE ) ) )
2131  return( CRYPT_ERROR_PARAM1 );
2132  *envelope = CRYPT_ERROR;
2133  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2134  return( CRYPT_ERROR_PARAM2 );
2135  if( formatType <= CRYPT_FORMAT_NONE || \
2136  formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
2137  return( CRYPT_ERROR_PARAM3 );
2138 
2139  /* Make sure that the user has remembered to initialise cryptlib */
2140  if( !initCalled )
2141  return( CRYPT_ERROR_NOTINITED );
2142 
2143  /* Dispatch the command */
2144  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2145  if( cryptUser != CRYPT_UNUSED )
2146  cmd.arg[ 0 ] = cryptUser;
2147  cmd.arg[ 2 ] = formatType;
2148  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2149  if( cryptStatusOK( status ) )
2150  {
2151  *envelope = cmd.arg[ 0 ];
2152  return( CRYPT_OK );
2153  }
2154  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2155  status ) );
2156  }
2157 
2158 /* Open/create a keyset */
2159 
2164  {
2165  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2168  static const ERRORMAP FAR_BSS errorMap[] = \
2169  { ARG_D, ARG_O, ARG_N, ARG_S, ARG_N, ARG_LAST, ARG_LAST };
2170  COMMAND_INFO cmd;
2171 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2172  BYTE nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *namePtr = nameBuffer;
2173 #else
2174  const char *namePtr = name;
2175 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2176  int nameLen, status;
2177 
2178  /* Perform basic error checking */
2179  if( !isReadPtrConst( keyset, sizeof( CRYPT_KEYSET ) ) )
2180  return( CRYPT_ERROR_PARAM1 );
2181  *keyset = CRYPT_ERROR;
2182  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2183  return( CRYPT_ERROR_PARAM2 );
2184  if( keysetType <= CRYPT_KEYSET_NONE || keysetType >= CRYPT_KEYSET_LAST )
2185  return( CRYPT_ERROR_PARAM3 );
2186  if( !isReadPtrConst( name, MIN_NAME_LENGTH ) || \
2187  strParamLen( name ) < MIN_NAME_LENGTH || \
2188  strParamLen( name ) >= MAX_ATTRIBUTE_SIZE )
2189  return( CRYPT_ERROR_PARAM4 );
2190  if( options < CRYPT_KEYOPT_NONE || \
2191  options >= CRYPT_KEYOPT_LAST_EXTERNAL )
2192  {
2193  /* CRYPT_KEYOPT_NONE is a valid setting for this parameter */
2194  return( CRYPT_ERROR_PARAM4 );
2195  }
2196 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2197  status = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,
2198  name, nativeStrlen( name ) + 1 );
2199  if( cryptStatusError( status ) )
2200  return( CRYPT_ERROR_PARAM4 );
2201 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2202 
2203  /* Check and clean up any string parameters if required */
2204  nameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );
2205  if( nameLen <= 0 )
2206  return( CRYPT_ERROR_PARAM4 );
2207 
2208  /* Make sure that the user has remembered to initialise cryptlib */
2209  if( !initCalled )
2210  return( CRYPT_ERROR_NOTINITED );
2211 
2212  /* Dispatch the command */
2213  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2214  if( cryptUser != CRYPT_UNUSED )
2215  cmd.arg[ 0 ] = cryptUser;
2216  cmd.arg[ 2 ] = keysetType;
2217  cmd.arg[ 3 ] = options;
2218  cmd.strArg[ 0 ] = ( void * ) namePtr;
2219  cmd.strArgLen[ 0 ] = nameLen;
2220  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2221  if( cryptStatusOK( status ) )
2222  {
2223  *keyset = cmd.arg[ 0 ];
2224  return( CRYPT_OK );
2225  }
2226  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2227  status ) );
2228  }
2229 
2230 /* Create a session */
2231 
2234  C_IN CRYPT_SESSION_TYPE sessionType )
2235  {
2236  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2239  static const ERRORMAP FAR_BSS errorMap[] = \
2240  { ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };
2241  COMMAND_INFO cmd;
2242  int status;
2243 
2244  /* Perform basic error checking */
2245  if( !isWritePtrConst( session, sizeof( CRYPT_SESSION ) ) )
2246  return( CRYPT_ERROR_PARAM1 );
2247  *session = CRYPT_ERROR;
2248  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2249  return( CRYPT_ERROR_PARAM2 );
2250  if( sessionType <= CRYPT_SESSION_NONE || \
2251  sessionType >= CRYPT_SESSION_LAST )
2252  return( CRYPT_ERROR_PARAM3 );
2253 
2254  /* Make sure that the user has remembered to initialise cryptlib */
2255  if( !initCalled )
2256  return( CRYPT_ERROR_NOTINITED );
2257 
2258  /* Dispatch the command */
2259  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2260  if( cryptUser != CRYPT_UNUSED )
2261  cmd.arg[ 0 ] = cryptUser;
2262  cmd.arg[ 2 ] = sessionType;
2263  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2264  if( cryptStatusOK( status ) )
2265  {
2266  *session = cmd.arg[ 0 ];
2267  return( CRYPT_OK );
2268  }
2269  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2270  status ) );
2271  }
2272 
2273 /* Log on/create a user object */
2274 
2277  {
2278  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2281  static const ERRORMAP FAR_BSS errorMap[] = \
2282  { ARG_D, ARG_S, ARG_S, ARG_LAST, ARG_LAST };
2283  COMMAND_INFO cmd;
2284 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2285  BYTE nameBuffer[ CRYPT_MAX_TEXTSIZE + 1 ], *namePtr = nameBuffer;
2286  BYTE passwordBuffer[ CRYPT_MAX_TEXTSIZE + 1 ], *passwordPtr = passwordBuffer;
2287 #else
2288  const char *namePtr = name, *passwordPtr = password;
2289 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2290  int nameLen, passwordLen, status;
2291 
2292  /* Perform basic error checking */
2293  if( !isReadPtrConst( user, sizeof( CRYPT_USER ) ) )
2294  return( CRYPT_ERROR_PARAM1 );
2295  *user = CRYPT_ERROR;
2296  if( !isReadPtrConst( name, MIN_NAME_LENGTH ) || \
2297  strParamLen( name ) < MIN_NAME_LENGTH || \
2298  strParamLen( name ) > CRYPT_MAX_TEXTSIZE )
2299  return( CRYPT_ERROR_PARAM2 );
2300  if( !isReadPtrConst( password, MIN_NAME_LENGTH ) || \
2301  strParamLen( password ) < MIN_NAME_LENGTH || \
2302  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE )
2303  return( CRYPT_ERROR_PARAM3 );
2304 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2305  status = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,
2306  name, nativeStrlen( name ) + 1 );
2307  if( cryptStatusError( status ) )
2308  return( CRYPT_ERROR_PARAM2 );
2309  status = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,
2310  password, nativeStrlen( password ) + 1 );
2311  if( cryptStatusError( status ) )
2312  return( CRYPT_ERROR_PARAM3 );
2313 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2314 
2315  /* Check and clean up any string parameters if required */
2316  nameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );
2317  if( nameLen <= 0 )
2318  return( CRYPT_ERROR_PARAM2 );
2319  passwordLen = strStripWhitespace( &passwordPtr, passwordPtr,
2320  strlen( passwordPtr ) );
2321  if( passwordLen <= 0 )
2322  return( CRYPT_ERROR_PARAM3 );
2323 
2324  /* Make sure that the user has remembered to initialise cryptlib */
2325  if( !initCalled )
2326  return( CRYPT_ERROR_NOTINITED );
2327 
2328  /* Dispatch the command */
2329  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2330  cmd.strArg[ 0 ] = ( void * ) namePtr;
2331  cmd.strArgLen[ 0 ] = nameLen;
2332  cmd.strArg[ 1 ] = ( void * ) passwordPtr;
2333  cmd.strArgLen[ 1 ] = passwordLen;
2334  status = DISPATCH_COMMAND( cmdCreateObject, cmd );
2335  if( cryptStatusOK( status ) )
2336  {
2337  *user = cmd.arg[ 0 ];
2338  return( CRYPT_OK );
2339  }
2340  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2341  status ) );
2342  }
2343 
2344 /* Destroy object functions */
2345 
2347  {
2348  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2350  static const ERRORMAP FAR_BSS errorMap[] = \
2351  { ARG_O, ARG_LAST, ARG_LAST };
2352  COMMAND_INFO cmd;
2353  int status;
2354 
2355  /* Perform basic client-side error checking */
2356  if( !isHandleRangeValid( cryptHandle ) )
2357  return( CRYPT_ERROR_PARAM1 );
2358 
2359  /* Make sure that the user has remembered to initialise cryptlib */
2360  if( !initCalled )
2361  return( CRYPT_ERROR_NOTINITED );
2362 
2363  /* Dispatch the command */
2364  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2365  cmd.arg[ 0 ] = cryptHandle;
2366  status = DISPATCH_COMMAND( cmdDestroyObject, cmd );
2367  if( cryptStatusOK( status ) )
2368  return( CRYPT_OK );
2369  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2370  status ) );
2371  }
2372 
2374  {
2375  return( cryptDestroyObject( certificate ) );
2376  }
2378  {
2379  return( cryptDestroyObject( cryptContext ) );
2380  }
2382  {
2383  return( cryptDestroyObject( cryptEnvelope ) );
2384  }
2386  {
2387  return( cryptDestroyObject( device ) );
2388  }
2390  {
2391  return( cryptDestroyObject( keyset ) );
2392  }
2394  {
2395  return( cryptDestroyObject( session ) );
2396  }
2398  {
2399  return( cryptDestroyObject( user ) );
2400  }
2401 
2402 /****************************************************************************
2403 * *
2404 * Attribute Manipulation Functions *
2405 * *
2406 ****************************************************************************/
2407 
2408 /* Get an attribute */
2409 
2412  C_OUT int C_PTR value )
2413  {
2414  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2417  static const ERRORMAP FAR_BSS errorMap[] = \
2418  { ARG_O, ARG_V, ARG_S, ARG_LAST, ARG_LAST };
2419  COMMAND_INFO cmd;
2420  int status;
2421 
2422  /* Perform basic client-side error checking */
2423  if( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )
2424  return( CRYPT_ERROR_PARAM1 );
2425  if( attributeType <= CRYPT_ATTRIBUTE_NONE || attributeType >= CRYPT_ATTRIBUTE_LAST )
2426  return( CRYPT_ERROR_PARAM2 );
2427  if( !isWritePtrConst( value, sizeof( int ) ) )
2428  return( CRYPT_ERROR_PARAM3 );
2429  *value = CRYPT_ERROR;
2430 
2431  /* Dispatch the command */
2432  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2433  if( cryptHandle != CRYPT_UNUSED )
2434  cmd.arg[ 0 ] = cryptHandle;
2435  cmd.arg[ 1 ] = attributeType;
2436  status = DISPATCH_COMMAND( cmdGetAttribute, cmd );
2437  if( cryptStatusOK( status ) )
2438  {
2439  *value = cmd.arg[ 0 ];
2440  return( CRYPT_OK );
2441  }
2442  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2443  status ) );
2444  }
2445 
2448  C_OUT void C_PTR value,
2449  C_OUT int C_PTR valueLength )
2450  {
2451  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2453  { DEFAULTUSER_OBJECT_HANDLE, 0, TRUE } };
2454  static const ERRORMAP FAR_BSS errorMap[] = \
2455  { ARG_O, ARG_V, ARG_S, ARG_N, ARG_LAST, ARG_LAST };
2456  COMMAND_INFO cmd;
2457  int status;
2458 
2459  /* Perform basic client-side error checking */
2460  if( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )
2461  return( CRYPT_ERROR_PARAM1 );
2462  if( attributeType <= CRYPT_ATTRIBUTE_NONE || \
2463  attributeType >= CRYPT_ATTRIBUTE_LAST )
2464  return( CRYPT_ERROR_PARAM2 );
2465  if( !isWritePtrConst( valueLength, sizeof( int ) ) )
2466  return( CRYPT_ERROR_PARAM4 );
2467  *valueLength = CRYPT_ERROR;
2468  if( value != NULL )
2469  *( ( BYTE * ) value ) = '\0';
2470 
2471  /* Dispatch the command */
2472  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2473  if( value == NULL )
2474  {
2476  cmd.noStrArgs = 0;
2477  }
2478  if( cryptHandle != CRYPT_UNUSED )
2479  cmd.arg[ 0 ] = cryptHandle;
2480  cmd.arg[ 1 ] = attributeType; /* arg[ 2 ] = TRUE from template */
2481  cmd.strArg[ 0 ] = value;
2483  status = DISPATCH_COMMAND( cmdGetAttribute, cmd );
2484  if( cryptStatusOK( status ) )
2485  {
2486  *valueLength = ( value == NULL ) ? cmd.arg[ 0 ] : cmd.strArgLen[ 0 ];
2487 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2488  if( value != NULL && *valueLength > 0 && \
2489  needsTranslation( attributeType ) )
2490  {
2491  BYTE buffer[ MAX_ATTRIBUTE_SIZE ];
2492 
2493  if( *valueLength >= MAX_ATTRIBUTE_SIZE )
2494  return( CRYPT_ERROR_OVERFLOW );
2495  memcpy( buffer, value, *valueLength );
2496  cryptlibToNativeString( value, MAX_ATTRIBUTE_SIZE,
2497  buffer, *valueLength );
2498  #ifdef UNICODE_CHARS
2499  *valueLength *= sizeof( wchar_t );
2500  #endif /* UNICODE_CHARS */
2501  }
2502 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2503  return( CRYPT_OK );
2504  }
2505  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2506  status ) );
2507  }
2508 
2509 /* Set an attribute */
2510 
2513  C_IN int value )
2514  {
2515  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2518  static const ERRORMAP FAR_BSS errorMap[] = \
2519  { ARG_O, ARG_V, ARG_N, ARG_LAST, ARG_LAST };
2520  COMMAND_INFO cmd;
2521  int status;
2522 
2523  /* Perform basic client-side error checking */
2524  if( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )
2525  return( CRYPT_ERROR_PARAM1 );
2526  if( attributeType <= CRYPT_ATTRIBUTE_NONE || \
2527  attributeType >= CRYPT_ATTRIBUTE_LAST )
2528  return( CRYPT_ERROR_PARAM2 );
2529 
2530  /* Dispatch the command */
2531  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2532  if( cryptHandle != CRYPT_UNUSED )
2533  cmd.arg[ 0 ] = cryptHandle;
2534  cmd.arg[ 1 ] = attributeType;
2535  cmd.arg[ 2 ] = value;
2536  status = DISPATCH_COMMAND( cmdSetAttribute, cmd );
2537  if( cryptStatusOK( status ) )
2538  return( CRYPT_OK );
2539  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2540  status ) );
2541  }
2542 
2545  C_IN void C_PTR value, C_IN int valueLength )
2546  {
2547  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2550  static const ERRORMAP FAR_BSS errorMap[] = \
2551  { ARG_O, ARG_V, ARG_S, ARG_N, ARG_LAST, ARG_LAST };
2552  COMMAND_INFO cmd;
2553 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2554  BYTE valueBuffer[ MAX_ATTRIBUTE_SIZE ];
2555 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2556  int length = valueLength, status;
2557 
2558  /* Perform basic client-side error checking */
2559  if( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )
2560  return( CRYPT_ERROR_PARAM1 );
2561  if( attributeType <= CRYPT_ATTRIBUTE_NONE || \
2562  attributeType >= CRYPT_ATTRIBUTE_LAST )
2563  return( CRYPT_ERROR_PARAM2 );
2564  if( !isReadPtrConst( value, 1 ) )
2565  return( CRYPT_ERROR_PARAM3 );
2566  if( attributeType == CRYPT_CTXINFO_KEY_COMPONENTS )
2567  {
2568  /* Public key components constitute a special case since the
2569  composite structures used are quite large */
2570  if( valueLength != sizeof( CRYPT_PKCINFO_RSA ) && \
2571  valueLength != sizeof( CRYPT_PKCINFO_DLP ) && \
2572  valueLength != sizeof( CRYPT_PKCINFO_ECC ) )
2573  return( CRYPT_ERROR_PARAM4 );
2574  }
2575  else
2576  {
2577  if( valueLength < 1 || valueLength >= MAX_ATTRIBUTE_SIZE )
2578  return( CRYPT_ERROR_PARAM4 );
2579  }
2580  if( !isReadPtr( value, valueLength ) )
2581  return( CRYPT_ERROR_PARAM3 );
2582 
2583 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
2584  if( needsTranslation( attributeType ) )
2585  {
2586  status = nativeToCryptlibString( valueBuffer, MAX_ATTRIBUTE_SIZE,
2587  value, valueLength );
2588  if( cryptStatusError( status ) )
2589  return( CRYPT_ERROR_PARAM3 );
2590  value = valueBuffer;
2591  #ifdef UNICODE_CHARS
2592  length = status;
2593  #endif /* UNICODE_CHARS */
2594  }
2595 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
2596 
2597 #if defined( __WINDOWS__ ) && defined( __WIN32__ ) && !defined( __WIN64__ )
2598  /* In Vista/VS 2008 Microsoft switched the Win32 time_t from 32 to 64
2599  bits, a theoretically commendable move but one that makes it
2600  impossible to create a single DLL that works with code compiled with
2601  different versions of Visual Studio or with different languages (it's
2602  not a problem with Win64 since the time_t there is always 64 bits).
2603  To get around the Win32 issue we try and detect a mismatch of time_t
2604  types and transparently convert them. We first check that it's
2605  within the range where it could be a time attribute to avoid having
2606  to iterate through the whole list on every attribute-set operation,
2607  and only then check for an exact match */
2608  if( attributeType >= CRYPT_CERTINFO_VALIDFROM && \
2609  attributeType <= CRYPT_CERTINFO_CMS_MLEXP_TIME )
2610  {
2611  if( ( attributeType == CRYPT_CERTINFO_VALIDFROM || \
2612  attributeType == CRYPT_CERTINFO_VALIDTO || \
2613  attributeType == CRYPT_CERTINFO_THISUPDATE || \
2614  attributeType == CRYPT_CERTINFO_NEXTUPDATE || \
2615  attributeType == CRYPT_CERTINFO_REVOCATIONDATE || \
2616  attributeType == CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF || \
2617  attributeType == CRYPT_CERTINFO_SIGG_DATEOFCERTGEN || \
2618  attributeType == CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE || \
2619  attributeType == CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER || \
2620  attributeType == CRYPT_CERTINFO_INVALIDITYDATE || \
2621  attributeType == CRYPT_CERTINFO_CMS_SIGNINGTIME || \
2622  attributeType == CRYPT_CERTINFO_CMS_MLEXP_TIME ) && \
2623  length != sizeof( time_t ) )
2624  {
2625  void *timeValuePtr;
2626  time_t time64, time32;
2627 
2628  /* It looks like we have a time_t size mismatch, try and correct
2629  it */
2630  if( length != 4 && length != 8 )
2631  {
2632  /* A time_t can only be 32 or 64 bits */
2633  return( CRYPT_ERROR_PARAM4 );
2634  }
2635  if( length == 4 )
2636  {
2637  /* time_t is 64 bits and we've been given 32, convert to a
2638  64-bit value */
2639  time64 = *( ( unsigned int * ) value );
2640  timeValuePtr = &time64;
2641  }
2642  else
2643  {
2644  /* time_t is 32 bits and we've been given 64, convert to a
2645  32-bit value */
2646  const __int64 timeValue = *( ( __int64 * ) value );
2647  if( timeValue < MIN_TIME_VALUE || timeValue >= ULONG_MAX )
2648  return( CRYPT_ERROR_PARAM3 );
2649  time32 = *( ( time_t * ) value );
2650  timeValuePtr = &time32;
2651  }
2652  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2653  cmd.arg[ 0 ] = cryptHandle;
2654  cmd.arg[ 1 ] = attributeType;
2655  cmd.strArg[ 0 ] = ( void * ) timeValuePtr;
2656  cmd.strArgLen[ 0 ] = sizeof( time_t );
2657  status = DISPATCH_COMMAND( cmdSetAttribute, cmd );
2658  if( cryptStatusOK( status ) )
2659  return( CRYPT_OK );
2660  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2661  status ) );
2662  }
2663  }
2664 #endif /* Win32 */
2665 
2666  /* Dispatch the command */
2667  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2668  if( cryptHandle != CRYPT_UNUSED )
2669  cmd.arg[ 0 ] = cryptHandle;
2670  cmd.arg[ 1 ] = attributeType;
2671  cmd.strArg[ 0 ] = ( void * ) value;
2672  cmd.strArgLen[ 0 ] = length;
2673  status = DISPATCH_COMMAND( cmdSetAttribute, cmd );
2674  if( cryptStatusOK( status ) )
2675  return( CRYPT_OK );
2676  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2677  status ) );
2678  }
2679 
2680 /* Delete an attribute */
2681 
2684  {
2685  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2688  static const ERRORMAP FAR_BSS errorMap[] = \
2689  { ARG_O, ARG_V, ARG_LAST, ARG_LAST };
2690  COMMAND_INFO cmd;
2691  int status;
2692 
2693  /* Perform basic client-side error checking */
2694  if( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )
2695  return( CRYPT_ERROR_PARAM1 );
2696  if( attributeType <= CRYPT_ATTRIBUTE_NONE || \
2697  attributeType >= CRYPT_ATTRIBUTE_LAST )
2698  return( CRYPT_ERROR_PARAM2 );
2699 
2700  /* Dispatch the command */
2701  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2702  if( cryptHandle != CRYPT_UNUSED )
2703  cmd.arg[ 0 ] = cryptHandle;
2704  cmd.arg[ 1 ] = attributeType;
2705  status = DISPATCH_COMMAND( cmdDeleteAttribute, cmd );
2706  if( cryptStatusOK( status ) )
2707  return( CRYPT_OK );
2708  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2709  status ) );
2710  }
2711 
2712 /****************************************************************************
2713 * *
2714 * Encryption Functions *
2715 * *
2716 ****************************************************************************/
2717 
2718 /* Generate a key into an encryption context */
2719 
2721  {
2722  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2723  { COMMAND_GENKEY, COMMAND_FLAG_NONE, 1, 0 };
2724  static const ERRORMAP FAR_BSS errorMap[] = \
2725  { ARG_O, ARG_LAST, ARG_LAST };
2726  COMMAND_INFO cmd;
2727  int status;
2728 
2729  /* Perform basic client-side error checking */
2730  if( !isHandleRangeValid( cryptContext ) )
2731  return( CRYPT_ERROR_PARAM1 );
2732 
2733  /* Dispatch the command */
2734  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2735  cmd.arg[ 0 ] = cryptContext;
2736  status = DISPATCH_COMMAND( cmdGenKey, cmd );
2737  if( cryptStatusOK( status ) )
2738  return( CRYPT_OK );
2739  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2740  status ) );
2741  }
2742 
2743 /* Encrypt/decrypt data */
2744 
2746  C_INOUT void C_PTR buffer,
2747  C_IN int length )
2748  {
2749  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2751  static const ERRORMAP FAR_BSS errorMap[] = \
2752  { ARG_O, ARG_S, ARG_N, ARG_LAST, ARG_LAST };
2753  COMMAND_INFO cmd;
2754  int status;
2755 
2756  /* Perform basic client-side error checking. In theory we should also
2757  check for writeability since the encryption does an in-place update,
2758  however when we're hashing data it's valid for the data to be read-
2759  only so we only check for readability. In addition when hashing we
2760  could be doing a hash-wrapup call so we allow a zero length and only
2761  check the buffer if the length is nonzero */
2762  if( !isHandleRangeValid( cryptContext ) )
2763  return( CRYPT_ERROR_PARAM1 );
2764  if( length < 0 || length >= MAX_INTLENGTH )
2765  return( CRYPT_ERROR_PARAM3 );
2766  if( length > 0 && !isReadPtr( buffer, length ) )
2767  return( CRYPT_ERROR_PARAM2 );
2768 
2769  /* Dispatch the command */
2770  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2771  cmd.arg[ 0 ] = cryptContext;
2772  cmd.strArg[ 0 ] = ( length == 0 ) ? "" : buffer;
2773  cmd.strArgLen[ 0 ] = length;
2774  status = DISPATCH_COMMAND( cmdEncrypt, cmd );
2775  if( cryptStatusOK( status ) )
2776  return( CRYPT_OK );
2777  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2778  status ) );
2779  }
2780 
2782  C_INOUT void C_PTR buffer,
2783  C_IN int length )
2784  {
2785  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2787  static const ERRORMAP FAR_BSS errorMap[] = \
2788  { ARG_O, ARG_S, ARG_N, ARG_LAST, ARG_LAST };
2789  COMMAND_INFO cmd;
2790  int status;
2791 
2792  /* Perform basic client-side error checking */
2793  if( !isHandleRangeValid( cryptContext ) )
2794  return( CRYPT_ERROR_PARAM1 );
2795  if( length < 0 || length >= MAX_INTLENGTH )
2796  return( CRYPT_ERROR_PARAM3 );
2797  if( !isWritePtr( buffer, length ) )
2798  return( CRYPT_ERROR_PARAM2 );
2799 
2800  /* Dispatch the command */
2801  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2802  cmd.arg[ 0 ] = cryptContext;
2803  cmd.strArg[ 0 ] = buffer;
2804  cmd.strArgLen[ 0 ] = length;
2805  status = DISPATCH_COMMAND( cmdDecrypt, cmd );
2806  if( cryptStatusOK( status ) )
2807  return( CRYPT_OK );
2808  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2809  status ) );
2810  }
2811 
2812 /****************************************************************************
2813 * *
2814 * Certificate Functions *
2815 * *
2816 ****************************************************************************/
2817 
2818 /* Sign/sig.check a certificate object. The possibilities for signing are as
2819  follows:
2820 
2821  Signer
2822  Type | Cert Chain
2823  ------+--------------------+---------------
2824  Cert | Cert | Cert
2825  | |
2826  Chain | Chain, length = 2 | Chain, length = n+1
2827 
2828  For sig.checking the cert object is checked against an issuing key/
2829  certificate or against a CRL, either as a raw CRL or a keyset contain
2830  revocation information */
2831 
2834  {
2835  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2837  static const ERRORMAP FAR_BSS errorMap[] = \
2838  { ARG_O, ARG_V, ARG_LAST, ARG_LAST };
2839  COMMAND_INFO cmd;
2840  int status;
2841 
2842  /* Perform basic client-side error checking */
2843  if( !isHandleRangeValid( certificate ) )
2844  return( CRYPT_ERROR_PARAM1 );
2845  if( !isHandleRangeValid( signContext ) )
2846  return( CRYPT_ERROR_PARAM2 );
2847 
2848  /* Dispatch the command */
2849  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2850  cmd.arg[ 0 ] = certificate;
2851  cmd.arg[ 1 ] = signContext;
2852  status = DISPATCH_COMMAND( cmdCertSign, cmd );
2853  if( cryptStatusOK( status ) )
2854  return( CRYPT_OK );
2855  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2856  status ) );
2857  }
2858 
2861  {
2862  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2864  static const ERRORMAP FAR_BSS errorMap[] = \
2865  { ARG_O, ARG_V, ARG_LAST, ARG_LAST };
2866  COMMAND_INFO cmd;
2867  int status;
2868 
2869  /* Perform basic client-side error checking */
2870  if( !isHandleRangeValid( certificate ) )
2871  return( CRYPT_ERROR_PARAM1 );
2872  if( !isHandleRangeValid( sigCheckKey ) && \
2873  ( sigCheckKey != CRYPT_UNUSED ) )
2874  return( CRYPT_ERROR_PARAM2 );
2875 
2876  /* Dispatch the command */
2877  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2878  cmd.arg[ 0 ] = certificate;
2879  cmd.arg[ 1 ] = sigCheckKey;
2880  status = DISPATCH_COMMAND( cmdCertCheck, cmd );
2881  if( cryptStatusOK( status ) )
2882  return( CRYPT_OK );
2883  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2884  status ) );
2885  }
2886 
2887 /* Import/export a certificate, CRL, certification request, or cert chain.
2888  In the export case this just copies the internal encoded object to an
2889  external buffer. For cert/cert chain export the possibilities are as
2890  follows:
2891 
2892  Export
2893  Type | Cert Chain
2894  ------+--------------------+---------------
2895  Cert | Cert | Cert as chain
2896  | |
2897  Chain | Currently selected | Chain
2898  | cert in chain | */
2899 
2901  C_IN int certObjectLength,
2904  {
2905  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2908  static const ERRORMAP FAR_BSS errorMap[] = \
2909  { ARG_S, ARG_N, ARG_N, ARG_O, ARG_LAST, ARG_LAST };
2910  COMMAND_INFO cmd;
2911  int status;
2912 
2913  /* Perform basic client-side error checking */
2914  if( certObjectLength < MIN_CERTSIZE || \
2915  certObjectLength >= MAX_INTLENGTH )
2916  return( CRYPT_ERROR_PARAM2 );
2917  if( !isReadPtr( certObject, certObjectLength ) )
2918  return( CRYPT_ERROR_PARAM1 );
2919  if( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )
2920  return( CRYPT_ERROR_PARAM3 );
2921  if( !isWritePtrConst( certificate, sizeof( CRYPT_CERTIFICATE ) ) )
2922  return( CRYPT_ERROR_PARAM4 );
2923  *certificate = CRYPT_ERROR;
2924 
2925  /* Make sure that the user has remembered to initialise cryptlib */
2926  if( !initCalled )
2927  return( CRYPT_ERROR_NOTINITED );
2928 
2929  /* Dispatch the command */
2930  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2931  if( cryptUser != CRYPT_UNUSED )
2932  cmd.arg[ 0 ] = cryptUser;
2933  cmd.strArg[ 0 ] = ( void * ) certObject;
2934  cmd.strArgLen[ 0 ] = certObjectLength;
2935  status = DISPATCH_COMMAND( cmdCreateObjectIndirect, cmd );
2936  if( cryptStatusOK( status ) )
2937  {
2938  *certificate = cmd.arg[ 0 ];
2939  return( CRYPT_OK );
2940  }
2941  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
2942  status ) );
2943  }
2944 
2948  C_IN CRYPT_CERTFORMAT_TYPE certFormatType,
2950  {
2951  static const COMMAND_INFO FAR_BSS cmdTemplate = \
2953  static const ERRORMAP FAR_BSS errorMap[] = \
2954  { ARG_S, ARG_D, ARG_N, ARG_V, ARG_O, ARG_LAST, ARG_LAST };
2955  COMMAND_INFO cmd;
2956  int status;
2957 
2958  /* Perform basic client-side error checking */
2959  if( certObject != NULL )
2960  {
2961  if( certObjectMaxLength < MIN_CERTSIZE || \
2962  certObjectMaxLength >= MAX_INTLENGTH )
2963  return( CRYPT_ERROR_PARAM2 );
2964  if( !isWritePtr( certObject, certObjectMaxLength ) )
2965  return( CRYPT_ERROR_PARAM1 );
2966  memset( certObject, 0, MIN_CERTSIZE );
2967  }
2968  if( !isWritePtrConst( certObjectLength, sizeof( int ) ) )
2969  return( CRYPT_ERROR_PARAM3 );
2970  *certObjectLength = CRYPT_ERROR;
2971  if( certFormatType <= CRYPT_CERTFORMAT_NONE || \
2972  certFormatType >= CRYPT_CERTFORMAT_LAST_EXTERNAL )
2973  return( CRYPT_ERROR_PARAM4 );
2974  if( !isHandleRangeValid( certificate ) )
2975  return( CRYPT_ERROR_PARAM5 );
2976 
2977  /* Dispatch the command */
2978  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
2979  if( certObject == NULL )
2980  {
2982  cmd.noStrArgs = 0;
2983  }
2984  cmd.arg[ 0 ] = certificate;
2985  cmd.arg[ 1 ] = certFormatType;
2986  cmd.strArg[ 0 ] = certObject;
2987  cmd.strArgLen[ 0 ] = certObjectMaxLength;
2988  status = DISPATCH_COMMAND( cmdExportObject, cmd );
2989  if( cryptStatusOK( status ) )
2990  {
2991  *certObjectLength = ( certObject == NULL ) ? \
2992  cmd.arg[ 0 ] : cmd.strArgLen[ 0 ];
2993 #if defined( EBCDIC_CHARS )
2994  if( ( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
2995  certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \
2996  certFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE || \
2997  certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN ) && \
2998  certObject != NULL )
2999  {
3000  /* It's text-encoded cert data, convert it to the native text
3001  format before we return */
3002  cryptlibToNativeString( certObject, certObjectMaxLength,
3003  certObject, *certObjectLength );
3004  }
3005 #endif /* EBCDIC_CHARS */
3006  return( CRYPT_OK );
3007  }
3008  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3009  status ) );
3010  }
3011 
3012 /* CA management functions */
3013 
3016  {
3017  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3018  { COMMAND_SETKEY, COMMAND_FLAG_NONE, 3, 0 };
3019  static const ERRORMAP FAR_BSS errorMap[] = \
3020  { ARG_O, ARG_N, ARG_LAST, ARG_LAST };
3021  COMMAND_INFO cmd;
3022  int status;
3023 
3024  /* Perform basic client-side error checking */
3025  if( !isHandleRangeValid( keyset ) )
3026  return( CRYPT_ERROR_PARAM1 );
3027  if( !isHandleRangeValid( certificate ) )
3028  return( CRYPT_ERROR_PARAM2 );
3029 
3030  /* Dispatch the command */
3031  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3032  cmd.arg[ 0 ] = keyset;
3033  cmd.arg[ 1 ] = certificate;
3034  cmd.arg[ 2 ] = TRUE;
3035  status = DISPATCH_COMMAND( cmdSetKey, cmd );
3036  if( cryptStatusOK( status ) )
3037  return( CRYPT_OK );
3038  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3039  status ) );
3040  }
3041 
3046  C_IN_OPT C_STR keyID )
3047  {
3048  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3049  { COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 1 };
3050  static const ERRORMAP FAR_BSS errorMap[] = \
3051  { ARG_O, ARG_D, ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3052  COMMAND_INFO cmd;
3053 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3054  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = NULL;
3055 #else
3056  const char *keyIDPtr = keyID;
3057 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3058  BOOLEAN isCert = FALSE;
3059  int keyIDlen = 0, status;
3060 
3061  /* Perform basic client-side error checking. Because of keyset queries
3062  we have to accept CRYPT_KEYID_NONE and a null keyID as well as
3063  obviously valid key ID's */
3064  if( !isHandleRangeValid( keyset ) )
3065  return( CRYPT_ERROR_PARAM1 );
3066  if( !isWritePtrConst( certificate, sizeof( CRYPT_HANDLE ) ) )
3067  return( CRYPT_ERROR_PARAM2 );
3068  *certificate = CRYPT_ERROR;
3069  if( certType == CRYPT_CERTTYPE_CERTIFICATE || \
3070  certType == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
3071  certType == CRYPT_CERTTYPE_CERTCHAIN )
3072  isCert = TRUE;
3073  else
3074  {
3075  if( certType != CRYPT_CERTTYPE_CERTREQUEST && \
3076  certType != CRYPT_CERTTYPE_REQUEST_CERT && \
3077  certType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \
3078  certType != CRYPT_CERTTYPE_PKIUSER )
3079  return( CRYPT_ERROR_PARAM3 );
3080  }
3081  if( keyIDtype < CRYPT_KEYID_NONE || \
3082  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3083  return( CRYPT_ERROR_PARAM4 );
3084  if( keyIDtype == CRYPT_KEYID_NONE )
3085  {
3086  if( keyID != NULL )
3087  return( CRYPT_ERROR_PARAM5 );
3088  }
3089  else
3090  {
3091  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3092  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3093  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3094  return( CRYPT_ERROR_PARAM5 );
3095  }
3096 
3097 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3098  if( keyID != NULL )
3099  {
3100  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3101  keyID, nativeStrlen( keyID ) + 1 );
3102  if( cryptStatusError( status ) )
3103  return( CRYPT_ERROR_PARAM4 );
3104  keyIDPtr = keyIDBuffer;
3105  }
3106 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3107 
3108  /* Check and clean up any string parameters if required */
3109  if( keyIDPtr != NULL )
3110  {
3111  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3112  if( keyIDlen <= 0 )
3113  return( CRYPT_ERROR_PARAM5 );
3114  }
3115 
3116  /* Dispatch the command */
3117  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3118  cmd.arg[ 0 ] = keyset;
3119  if( isCert )
3120  {
3121  /* If we're being asked for a standard cert, the caller should really
3122  be using cryptGetPublicKey(), however for orthogonality we convert
3123  the request into a standard public-key read. Note that this leads
3124  to some ambiguity since we can't explicitly specify what we want
3125  returned for a cert read (for example we could get a chain if we
3126  ask for a single cert or a single cert if we ask for a chain,
3127  depending on what's there), but it's less confusing than refusing
3128  any request to read a cert */
3129  cmd.arg[ 1 ] = KEYMGMT_ITEM_PUBLICKEY;
3130  }
3131  else
3132  {
3133  cmd.arg[ 1 ] = ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \
3135  }
3136  cmd.arg[ 2 ] = keyIDtype;
3137  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3138  cmd.strArgLen[ 0 ] = keyIDlen ;
3139  status = DISPATCH_COMMAND( cmdGetKey, cmd );
3140  if( cryptStatusOK( status ) )
3141  {
3142  *certificate = cmd.arg[ 0 ];
3143  return( CRYPT_OK );
3144  }
3145  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3146  status ) );
3147  }
3148 
3152  C_IN C_STR keyID )
3153  {
3154  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3156  static const ERRORMAP FAR_BSS errorMap[] = \
3157  { ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3158  COMMAND_INFO cmd;
3159 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3160  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;
3161 #else
3162  const char *keyIDPtr = keyID;
3163 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3164  int keyIDlen, status;
3165 
3166  /* Perform basic client-side error checking */
3167  if( !isHandleRangeValid( keyset ) )
3168  return( CRYPT_ERROR_PARAM1 );
3169  if( certType != CRYPT_CERTTYPE_CERTIFICATE && \
3170  certType != CRYPT_CERTTYPE_CERTREQUEST && \
3171  certType != CRYPT_CERTTYPE_REQUEST_CERT && \
3172  certType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \
3173  certType != CRYPT_CERTTYPE_PKIUSER )
3174  return( CRYPT_ERROR_PARAM2 );
3175  if( keyIDtype <= CRYPT_KEYID_NONE || \
3176  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3177  return( CRYPT_ERROR_PARAM3 );
3178  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3179  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3180  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3181  return( CRYPT_ERROR_PARAM4 );
3182 
3183 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3184  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3185  keyID, nativeStrlen( keyID ) + 1 );
3186  if( cryptStatusError( status ) )
3187  return( CRYPT_ERROR_PARAM4 );
3188 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3189 
3190  /* Check and clean up any string parameters if required */
3191  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3192  if( keyIDlen <= 0 )
3193  return( CRYPT_ERROR_PARAM4 );
3194 
3195  /* Dispatch the command */
3196  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3197  cmd.arg[ 0 ] = keyset;
3198  cmd.arg[ 1 ] = keyIDtype;
3199  if( certType == CRYPT_CERTTYPE_CERTIFICATE )
3200  {
3201  /* Allow a delete of a cert for the same reason as given above for
3202  cryptCAGetItem() */
3203  cmd.noArgs = 2;
3204  }
3205  else
3206  {
3207  cmd.arg[ 2 ] = ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \
3209  }
3210  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3211  cmd.strArgLen[ 0 ] = keyIDlen;
3212  status = DISPATCH_COMMAND( cmdDeleteKey, cmd );
3213  if( cryptStatusOK( status ) )
3214  return( CRYPT_OK );
3215  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3216  status ) );
3217  }
3218 
3220  C_IN CRYPT_CERTACTION_TYPE action,
3223  C_IN CRYPT_CERTIFICATE certRequest )
3224  {
3225  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3227  static const ERRORMAP FAR_BSS errorMap[] = \
3228  { ARG_D, ARG_V, ARG_O, ARG_N, ARG_N, ARG_LAST, ARG_LAST };
3229  COMMAND_INFO cmd;
3230  int status;
3231 
3232  /* Perform basic client-side error checking */
3233  if( certificate != NULL )
3234  {
3235  if( !isWritePtrConst( certificate, sizeof( CRYPT_HANDLE ) ) )
3236  return( CRYPT_ERROR_PARAM1 );
3237  *certificate = CRYPT_ERROR;
3238  }
3239  if( action < CRYPT_CERTACTION_FIRST_USER || \
3240  action > CRYPT_CERTACTION_LAST_USER )
3241  return( CRYPT_ERROR_PARAM2 );
3242  if( !isHandleRangeValid( keyset ) )
3243  return( CRYPT_ERROR_PARAM3 );
3244  if( !isHandleRangeValid( caKey ) && \
3245  !( ( action == CRYPT_CERTACTION_EXPIRE_CERT || \
3246  action == CRYPT_CERTACTION_CLEANUP ) && caKey == CRYPT_UNUSED ) )
3247  return( CRYPT_ERROR_PARAM4 );
3248  if( !isHandleRangeValid( certRequest ) && \
3249  !( ( action == CRYPT_CERTACTION_ISSUE_CRL || \
3250  action == CRYPT_CERTACTION_EXPIRE_CERT || \
3251  action == CRYPT_CERTACTION_CLEANUP ) && \
3252  certRequest == CRYPT_UNUSED ) )
3253  return( CRYPT_ERROR_PARAM5 );
3254 
3255  /* Dispatch the command */
3256  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3257  if( certificate == NULL )
3259  cmd.arg[ 0 ] = keyset;
3260  cmd.arg[ 1 ] = action;
3261  cmd.arg[ 2 ] = caKey;
3262  cmd.arg[ 3 ] = certRequest;
3263  status = DISPATCH_COMMAND( cmdCertMgmt, cmd );
3264  if( cryptStatusOK( status ) && certificate != NULL )
3265  {
3266  *certificate = cmd.arg[ 0 ];
3267  return( CRYPT_OK );
3268  }
3269  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3270  status ) );
3271  }
3272 
3273 /****************************************************************************
3274 * *
3275 * Envelope Functions *
3276 * *
3277 ****************************************************************************/
3278 
3279 /* Push data into an envelope/session object */
3280 
3282  C_IN int length, C_OUT int C_PTR bytesCopied )
3283  {
3284  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3286  static const ERRORMAP FAR_BSS errorMap[] = \
3287  { ARG_O, ARG_S, ARG_N, ARG_N, ARG_LAST, ARG_LAST };
3288  COMMAND_INFO cmd;
3289  int dummy, status;
3290 
3291  /* Perform basic client-side error checking */
3292  if( !isHandleRangeValid( envelope ) )
3293  return( CRYPT_ERROR_PARAM1 );
3294  if( !isReadPtr( buffer, length ) )
3295  return( CRYPT_ERROR_PARAM2 );
3296  if( length <= 0 || length >= MAX_INTLENGTH )
3297  return( CRYPT_ERROR_PARAM3 );
3298  if( bytesCopied == NULL )
3299  {
3300  /* If the user isn't interested in the bytes copied count, point at a
3301  dummy location */
3302  bytesCopied = &dummy;
3303  }
3304  *bytesCopied = 0;
3305 
3306  /* Dispatch the command */
3307  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3308  cmd.arg[ 0 ] = envelope;
3309  cmd.strArg[ 0 ] = ( void * ) buffer;
3310  cmd.strArgLen[ 0 ] = length;
3311  status = DISPATCH_COMMAND( cmdPushData, cmd );
3312  *bytesCopied = cmd.arg[ 0 ];
3313  if( cryptStatusOK( status ) )
3314  return( CRYPT_OK );
3315  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3316  status ) );
3317  }
3318 
3319 /* Pop data from an envelope/session object */
3320 
3322  C_IN int length, C_OUT int C_PTR bytesCopied )
3323  {
3324  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3326  static const ERRORMAP FAR_BSS errorMap[] = \
3327  { ARG_O, ARG_S, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3328  COMMAND_INFO cmd;
3329  int status;
3330 
3331  /* Perform basic client-side error checking */
3332  if( !isHandleRangeValid( envelope ) )
3333  return( CRYPT_ERROR_PARAM1 );
3334  if( !isWritePtr( buffer, length ) )
3335  return( CRYPT_ERROR_PARAM2 );
3336  if( length <= 0 || length >= MAX_INTLENGTH )
3337  return( CRYPT_ERROR_PARAM3 );
3338  memset( buffer, 0, min( length, 16 ) );
3339  if( !isWritePtrConst( bytesCopied, sizeof( int ) ) )
3340  return( CRYPT_ERROR_PARAM4 );
3341  *bytesCopied = 0;
3342 
3343  /* Dispatch the command */
3344  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3345  cmd.arg[ 0 ] = envelope;
3346  cmd.arg[ 1 ] = length;
3347  cmd.strArg[ 0 ] = ( void * ) buffer;
3348  cmd.strArgLen[ 0 ] = RETURN_VALUE( length );
3349  status = DISPATCH_COMMAND( cmdPopData, cmd );
3350  *bytesCopied = cmd.strArgLen[ 0 ];
3351  if( cryptStatusOK( status ) )
3352  return( CRYPT_OK );
3353  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3354  status ) );
3355  }
3356 
3357 /* Flush data through an envelope/session object */
3358 
3360  {
3361  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3363  static const ERRORMAP FAR_BSS errorMap[] = \
3364  { ARG_O, ARG_LAST, ARG_LAST };
3365  COMMAND_INFO cmd;
3366  int status;
3367 
3368  /* Perform basic client-side error checking */
3369  if( !isHandleRangeValid( envelope ) )
3370  return( CRYPT_ERROR_PARAM1 );
3371 
3372  /* Dispatch the command */
3373  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3374  cmd.arg[ 0 ] = envelope;
3375  status = DISPATCH_COMMAND( cmdFlushData, cmd );
3376  if( cryptStatusOK( status ) )
3377  return( CRYPT_OK );
3378  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3379  status ) );
3380  }
3381 
3382 /****************************************************************************
3383 * *
3384 * Keyset Functions *
3385 * *
3386 ****************************************************************************/
3387 
3388 /* Retrieve a key from a keyset or equivalent object */
3389 
3393  C_IN_OPT C_STR keyID )
3394  {
3395  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3396  { COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 1 };
3397  static const ERRORMAP FAR_BSS errorMap[] = \
3398  { ARG_O, ARG_D, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3399  COMMAND_INFO cmd;
3400 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3401  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = NULL;
3402 #else
3403  const char *keyIDPtr = keyID;
3404 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3405  int keyIDlen = 0, status;
3406 
3407  /* Perform basic client-side error checking. Because of keyset queries
3408  we have to accept CRYPT_KEYID_NONE and a null keyID as well as
3409  obviously valid key ID's */
3410  if( !isHandleRangeValid( keyset ) )
3411  return( CRYPT_ERROR_PARAM1 );
3412  if( !isWritePtrConst( cryptKey, sizeof( CRYPT_HANDLE ) ) )
3413  return( CRYPT_ERROR_PARAM2 );
3414  *cryptKey = CRYPT_ERROR;
3415  if( keyIDtype < CRYPT_KEYID_NONE || \
3416  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3417  return( CRYPT_ERROR_PARAM3 );
3418  if( keyIDtype == CRYPT_KEYID_NONE )
3419  {
3420  if( keyID != NULL )
3421  return( CRYPT_ERROR_PARAM4 );
3422  }
3423  else
3424  {
3425  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3426  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3427  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3428  return( CRYPT_ERROR_PARAM4 );
3429  }
3430 
3431 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3432  if( keyID != NULL )
3433  {
3434  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3435  keyID, nativeStrlen( keyID ) + 1 );
3436  if( cryptStatusError( status ) )
3437  return( CRYPT_ERROR_PARAM4 );
3438  keyIDPtr = keyIDBuffer;
3439  }
3440 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3441 
3442  /* Check and clean up any string parameters if required */
3443  if( keyIDPtr != NULL )
3444  {
3445  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3446  if( keyIDlen <= 0 )
3447  return( CRYPT_ERROR_PARAM4 );
3448  }
3449 
3450  /* Dispatch the command */
3451  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3452  cmd.arg[ 0 ] = keyset;
3453  cmd.arg[ 1 ] = KEYMGMT_ITEM_PUBLICKEY;
3454  cmd.arg[ 2 ] = keyIDtype;
3455  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3456  cmd.strArgLen[ 0 ] = keyIDlen;
3457  status = DISPATCH_COMMAND( cmdGetKey, cmd );
3458  if( cryptStatusOK( status ) )
3459  {
3460  *cryptKey = cmd.arg[ 0 ];
3461  return( CRYPT_OK );
3462  }
3463  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3464  status ) );
3465  }
3466 
3471  {
3472  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3473  { COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 2 };
3474  static const ERRORMAP FAR_BSS errorMap[] = \
3475  { ARG_O, ARG_D, ARG_N, ARG_S, ARG_S, ARG_LAST, ARG_LAST };
3476  COMMAND_INFO cmd;
3477 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3478  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;
3479  BYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;
3480 #else
3481  const char *keyIDPtr = keyID, *passwordPtr = password;
3482 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3483  int keyIDlen, passwordLen = 0, status;
3484 
3485  /* Perform basic client-side error checking */
3486  if( !isHandleRangeValid( keyset ) )
3487  return( CRYPT_ERROR_PARAM1 );
3488  if( !isWritePtrConst( cryptContext, sizeof( CRYPT_CONTEXT ) ) )
3489  return( CRYPT_ERROR_PARAM2 );
3490  *cryptContext = CRYPT_ERROR;
3491  if( keyIDtype <= CRYPT_KEYID_NONE || \
3492  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3493  return( CRYPT_ERROR_PARAM3 );
3494  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3495  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3496  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3497  return( CRYPT_ERROR_PARAM4 );
3498  if( password != NULL && \
3499  ( !isReadPtrConst( password, MIN_NAME_LENGTH ) || \
3500  strParamLen( password ) < MIN_NAME_LENGTH || \
3501  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )
3502  return( CRYPT_ERROR_PARAM5 );
3503 
3504 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3505  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3506  keyID, nativeStrlen( keyID ) + 1 );
3507  if( cryptStatusError( status ) )
3508  return( CRYPT_ERROR_PARAM4 );
3509  if( password != NULL )
3510  {
3511  status = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,
3512  password, nativeStrlen( password ) + 1 );
3513  if( cryptStatusError( status ) )
3514  return( CRYPT_ERROR_PARAM5 );
3515  passwordPtr = passwordBuffer;
3516  }
3517 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3518 
3519  /* Check and clean up any string parameters if required */
3520  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3521  if( keyIDlen <= 0 )
3522  return( CRYPT_ERROR_PARAM4 );
3523  if( passwordPtr != NULL )
3524  {
3525  passwordLen = strStripWhitespace( &passwordPtr, passwordPtr,
3526  strlen( passwordPtr ) );
3527  if( passwordLen <= 0 )
3528  return( CRYPT_ERROR_PARAM5 );
3529  }
3530 
3531  /* Dispatch the command */
3532  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3533  cmd.arg[ 0 ] = keyset;
3534  cmd.arg[ 1 ] = KEYMGMT_ITEM_PRIVATEKEY;
3535  cmd.arg[ 2 ] = keyIDtype;
3536  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3537  cmd.strArgLen[ 0 ] = keyIDlen;
3538  cmd.strArg[ 1 ] = ( void * ) passwordPtr;
3539  cmd.strArgLen[ 1 ] = passwordLen;
3540  status = DISPATCH_COMMAND( cmdGetKey, cmd );
3541 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3542  zeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );
3543 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3544  if( cryptStatusOK( status ) )
3545  {
3546  *cryptContext = cmd.arg[ 0 ];
3547  return( CRYPT_OK );
3548  }
3549  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3550  status ) );
3551  }
3552 
3556  C_IN C_STR password )
3557  {
3558  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3559  { COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 2 };
3560  static const ERRORMAP FAR_BSS errorMap[] = \
3561  { ARG_O, ARG_D, ARG_N, ARG_S, ARG_S, ARG_LAST, ARG_LAST };
3562  COMMAND_INFO cmd;
3563 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3564  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;
3565  BYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;
3566 #else
3567  const char *keyIDPtr = keyID, *passwordPtr = password;
3568 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3569  int keyIDlen, passwordLen = 0, status;
3570 
3571  /* Perform basic client-side error checking */
3572  if( !isHandleRangeValid( keyset ) )
3573  return( CRYPT_ERROR_PARAM1 );
3574  if( !isWritePtrConst( cryptContext, sizeof( CRYPT_CONTEXT ) ) )
3575  return( CRYPT_ERROR_PARAM2 );
3576  *cryptContext = CRYPT_ERROR;
3577  if( keyIDtype <= CRYPT_KEYID_NONE || \
3578  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3579  return( CRYPT_ERROR_PARAM3 );
3580  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3581  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3582  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3583  return( CRYPT_ERROR_PARAM4 );
3584  if( password != NULL && \
3585  ( !isReadPtrConst( password, MIN_NAME_LENGTH ) || \
3586  strParamLen( password ) < MIN_NAME_LENGTH || \
3587  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )
3588  return( CRYPT_ERROR_PARAM5 );
3589 
3590 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3591  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3592  keyID, nativeStrlen( keyID ) + 1 );
3593  if( cryptStatusError( status ) )
3594  return( CRYPT_ERROR_PARAM4 );
3595  if( password != NULL )
3596  {
3597  status = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,
3598  password, nativeStrlen( password ) + 1 );
3599  if( cryptStatusError( status ) )
3600  return( CRYPT_ERROR_PARAM5 );
3601  passwordPtr = passwordBuffer;
3602  }
3603 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3604 
3605  /* Check and clean up any string parameters if required */
3606  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3607  if( keyIDlen <= 0 )
3608  return( CRYPT_ERROR_PARAM4 );
3609  if( passwordPtr != NULL )
3610  {
3611  passwordLen = strStripWhitespace( &passwordPtr, passwordPtr,
3612  strlen( passwordPtr ) );
3613  if( passwordLen <= 0 )
3614  return( CRYPT_ERROR_PARAM5 );
3615  }
3616 
3617  /* Dispatch the command */
3618  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3619  cmd.arg[ 0 ] = keyset;
3620  cmd.arg[ 1 ] = KEYMGMT_ITEM_SECRETKEY;
3621  cmd.arg[ 2 ] = keyIDtype;
3622  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3623  cmd.strArgLen[ 0 ] = keyIDlen;
3624  cmd.strArg[ 1 ] = ( void * ) passwordPtr;
3625  cmd.strArgLen[ 1 ] = passwordLen;
3626  status = DISPATCH_COMMAND( cmdGetKey, cmd );
3627 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3628  zeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );
3629 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3630  if( cryptStatusOK( status ) )
3631  {
3632  *cryptContext = cmd.arg[ 0 ];
3633  return( CRYPT_OK );
3634  }
3635  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3636  status ) );
3637  }
3638 
3639 /* Add a key from a keyset or equivalent object */
3640 
3643  {
3644  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3645  { COMMAND_SETKEY, COMMAND_FLAG_NONE, 2, 0 };
3646  static const ERRORMAP FAR_BSS errorMap[] = \
3647  { ARG_O, ARG_N, ARG_LAST, ARG_LAST };
3648  COMMAND_INFO cmd;
3649  int status;
3650 
3651  /* Perform basic client-side error checking */
3652  if( !isHandleRangeValid( keyset ) )
3653  return( CRYPT_ERROR_PARAM1 );
3654  if( !isHandleRangeValid( certificate ) )
3655  return( CRYPT_ERROR_PARAM2 );
3656 
3657  /* Dispatch the command */
3658  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3659  cmd.arg[ 0 ] = keyset;
3660  cmd.arg[ 1 ] = certificate;
3661  status = DISPATCH_COMMAND( cmdSetKey, cmd );
3662  if( cryptStatusOK( status ) )
3663  return( CRYPT_OK );
3664  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3665  status ) );
3666  }
3667 
3670  C_IN C_STR password )
3671  {
3672  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3673  { COMMAND_SETKEY, COMMAND_FLAG_NONE, 2, 1 };
3674  static const ERRORMAP FAR_BSS errorMap[] = \
3675  { ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3676  COMMAND_INFO cmd;
3677 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3678  BYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;
3679 #else
3680  const char *passwordPtr = password;
3681 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3682  int passwordLen = 0, status;
3683 
3684  /* Perform basic client-side error checking */
3685  if( !isHandleRangeValid( keyset ) )
3686  return( CRYPT_ERROR_PARAM1 );
3687  if( !isHandleRangeValid( cryptKey ) )
3688  return( CRYPT_ERROR_PARAM2 );
3689  if( password != NULL && \
3690  ( !isReadPtrConst( password, MIN_NAME_LENGTH ) || \
3691  isBadPassword( password ) || \
3692  strParamLen( password ) < MIN_NAME_LENGTH || \
3693  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )
3694  return( CRYPT_ERROR_PARAM3 );
3695 
3696 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3697  if( password != NULL )
3698  {
3699  status = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,
3700  password, nativeStrlen( password ) + 1 );
3701  if( cryptStatusError( status ) )
3702  return( CRYPT_ERROR_PARAM3 );
3703  passwordPtr = passwordBuffer;
3704  }
3705 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3706 
3707  /* Check and clean up any string parameters if required */
3708  if( passwordPtr != NULL )
3709  {
3710  passwordLen = strStripWhitespace( &passwordPtr, passwordPtr,
3711  strlen( passwordPtr ) );
3712  if( passwordLen <= 0 )
3713  return( CRYPT_ERROR_PARAM3 );
3714  }
3715 
3716  /* Dispatch the command */
3717  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3718  cmd.arg[ 0 ] = keyset;
3719  cmd.arg[ 1 ] = cryptKey;
3720  cmd.strArg[ 0 ] = ( void * ) passwordPtr;
3721  cmd.strArgLen[ 0 ] = passwordLen;
3722  status = DISPATCH_COMMAND( cmdSetKey, cmd );
3723 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3724  zeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );
3725 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3726  if( cryptStatusOK( status ) )
3727  return( CRYPT_OK );
3728  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3729  status ) );
3730  }
3731 
3732 /* Delete a key from a keyset or equivalent object */
3733 
3736  C_IN C_STR keyID )
3737  {
3738  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3740  static const ERRORMAP FAR_BSS errorMap[] = \
3741  { ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3742  COMMAND_INFO cmd;
3743 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3744  BYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;
3745 #else
3746  const char *keyIDPtr = keyID;
3747 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3748  int keyIDlen, status;
3749 
3750  /* Perform basic client-side error checking */
3751  if( !isHandleRangeValid( keyset ) )
3752  return( CRYPT_ERROR_PARAM1 );
3753  if( keyIDtype <= CRYPT_KEYID_NONE || \
3754  keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )
3755  return( CRYPT_ERROR_PARAM2 );
3756  if( !isReadPtrConst( keyID, MIN_NAME_LENGTH ) || \
3757  strParamLen( keyID ) < MIN_NAME_LENGTH || \
3758  strParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )
3759  return( CRYPT_ERROR_PARAM3 );
3760 
3761 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3762  status = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,
3763  keyID, nativeStrlen( keyID ) + 1 );
3764  if( cryptStatusError( status ) )
3765  return( CRYPT_ERROR_PARAM3 );
3766 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3767 
3768  /* Check and clean up any string parameters if required */
3769  keyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );
3770  if( keyIDlen <= 0 )
3771  return( CRYPT_ERROR_PARAM3 );
3772 
3773  /* Dispatch the command */
3774  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3775  cmd.arg[ 0 ] = keyset;
3776  cmd.arg[ 1 ] = keyIDtype;
3777  cmd.strArg[ 0 ] = ( void * ) keyIDPtr;
3778  cmd.strArgLen[ 0 ] = keyIDlen;
3779  status = DISPATCH_COMMAND( cmdDeleteKey, cmd );
3780  if( cryptStatusOK( status ) )
3781  return( CRYPT_OK );
3782  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3783  status ) );
3784  }
3785 
3786 /****************************************************************************
3787 * *
3788 * User Management Functions *
3789 * *
3790 ****************************************************************************/
3791 
3792 /****************************************************************************
3793 * *
3794 * Misc Functions *
3795 * *
3796 ****************************************************************************/
3797 
3798 /* cryptlib/object query functions */
3799 
3801  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo )
3802  {
3803  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3805  { SYSTEM_OBJECT_HANDLE } };
3806  static const ERRORMAP FAR_BSS errorMap[] = \
3807  { ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3808  COMMAND_INFO cmd;
3809  int status;
3810 
3811  /* Perform basic client-side error checking */
3812  if( cryptAlgo < CRYPT_ALGO_NONE || \
3813  cryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )
3814  return( CRYPT_ERROR_PARAM1 );
3815  if( cryptQueryInfo != NULL )
3816  {
3817  if( !isWritePtrConst( cryptQueryInfo, sizeof( CRYPT_QUERY_INFO ) ) )
3818  return( CRYPT_ERROR_PARAM3 );
3819  memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );
3820  }
3821 
3822  /* Make sure that the user has remembered to initialise cryptlib */
3823  if( !initCalled )
3824  return( CRYPT_ERROR_NOTINITED );
3825 
3826  /* Dispatch the command. We need to map parameter errors down one
3827  because the system object is invisible to the caller */
3828  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3829  if( cryptQueryInfo == NULL )
3830  {
3832  cmd.noStrArgs = 0;
3833  }
3834  cmd.arg[ 1 ] = cryptAlgo;
3835  cmd.strArg[ 0 ] = cryptQueryInfo;
3837  status = DISPATCH_COMMAND( cmdQueryCapability, cmd );
3838  if( cryptStatusOK( status ) )
3839  {
3840 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3841  if( cryptQueryInfo != NULL )
3842  {
3843  BYTE buffer[ MAX_ATTRIBUTE_SIZE ];
3844  const int algoNameLength = \
3845  strlen( ( char * ) cryptQueryInfo->algoName ) + 1;
3846 
3847  memcpy( buffer, cryptQueryInfo->algoName, algoNameLength );
3848  cryptlibToNativeString( cryptQueryInfo->algoName,
3849  CRYPT_MAX_TEXTSIZE, buffer,
3850  algoNameLength );
3851  }
3852 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3853  return( CRYPT_OK );
3854  }
3855  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3856  status ) );
3857  }
3858 
3861  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo )
3862  {
3863  static const COMMAND_INFO FAR_BSS cmdTemplate = \
3865  static const ERRORMAP FAR_BSS errorMap[] = \
3866  { ARG_O, ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };
3867  COMMAND_INFO cmd;
3868  int status;
3869 
3870  /* Perform basic client-side error checking */
3871  if( !isHandleRangeValid( device ) )
3872  return( CRYPT_ERROR_PARAM1 );
3873  if( cryptAlgo < CRYPT_ALGO_NONE || \
3874  cryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )
3875  return( CRYPT_ERROR_PARAM2 );
3876  if( cryptQueryInfo != NULL )
3877  {
3878  if( !isWritePtrConst( cryptQueryInfo, sizeof( CRYPT_QUERY_INFO ) ) )
3879  return( CRYPT_ERROR_PARAM4 );
3880  memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );
3881  }
3882 
3883  /* Dispatch the command */
3884  memcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );
3885  if( cryptQueryInfo == NULL )
3886  {
3888  cmd.noStrArgs = 0;
3889  }
3890  cmd.arg[ 0 ] = device;
3891  cmd.arg[ 1 ] = cryptAlgo;
3892  cmd.strArg[ 0 ] = cryptQueryInfo;
3894  status = DISPATCH_COMMAND( cmdQueryCapability, cmd );
3895  if( cryptStatusOK( status ) )
3896  {
3897 #if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )
3898  if( cryptQueryInfo != NULL )
3899  {
3900  BYTE buffer[ MAX_ATTRIBUTE_SIZE ];
3901  const int algoNameLength = \
3902  strlen( ( char * ) cryptQueryInfo->algoName ) + 1;
3903 
3904  memcpy( buffer, cryptQueryInfo->algoName, algoNameLength );
3905  cryptlibToNativeString( cryptQueryInfo->algoName,
3906  CRYPT_MAX_TEXTSIZE, buffer,
3907  algoNameLength );
3908  }
3909 #endif /* EBCDIC_CHARS || UNICODE_CHARS */
3910  return( CRYPT_OK );
3911  }
3912  return( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ),
3913  status ) );
3914  }
3915 
3916 /* Add random data to the random pool. This should eventually be replaced
3917  by some sort of device control mechanism, the problem with doing this is
3918  that it's handled by the system device which isn't visible to the user */
3919 
3920 C_RET cryptAddRandom( C_IN void C_PTR randomData, C_IN int randomDataLength )
3921  {
3922  /* Perform basic error checking */
3923  if( randomData == NULL )
3924  {
3925  if( randomDataLength != CRYPT_RANDOM_FASTPOLL && \
3926  randomDataLength != CRYPT_RANDOM_SLOWPOLL )
3927  return( CRYPT_ERROR_PARAM1 );
3928  }
3929  else
3930  {
3931  if( randomDataLength <= 0 || randomDataLength >= MAX_INTLENGTH )
3932  return( CRYPT_ERROR_PARAM2 );
3933  if( !isReadPtr( randomData, randomDataLength ) )
3934  return( CRYPT_ERROR_PARAM1 );
3935  }
3936 
3937  /* Make sure that the user has remembered to initialise cryptlib */
3938  if( !initCalled )
3939  return( CRYPT_ERROR_NOTINITED );
3940 
3941  /* If we're adding data to the pool, add it now and exit. Since the data
3942  is of unknown provenance (and empirical evidence indicates that it
3943  won't be very random) we give it a weight of zero for estimation
3944  purposes */
3945  if( randomData != NULL )
3946  {
3948 
3949 #if defined( __WINDOWS__ ) && !defined( NDEBUG ) /* For debugging tests only */
3950 if( randomDataLength == 5 && !memcmp( randomData, "xyzzy", 5 ) )
3951 {
3952 BYTE buffer[ 256 + 8 ];
3953 int kludge = 100;
3954 memset( buffer, '*', 256 );
3955 setMessageData( &msgData, buffer, 256 );
3957  &msgData, CRYPT_IATTRIBUTE_ENTROPY );
3959  &kludge, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
3960 }
3961 #endif /* Windows debug */
3962 
3963  setMessageData( &msgData, ( MESSAGE_CAST ) randomData, \
3964  randomDataLength );
3966  IMESSAGE_SETATTRIBUTE_S, &msgData,
3967  CRYPT_IATTRIBUTE_ENTROPY ) );
3968  }
3969 
3970  /* Perform either a fast or slow poll for random system data */
3972  ( randomDataLength == CRYPT_RANDOM_SLOWPOLL ) ? \
3974  CRYPT_IATTRIBUTE_RANDOM_POLL ) );
3975  }
3976 
3977 /* If the use of certificates is disabled, we have to provide stub
3978  replacements for the legacy blob cert-extension manipulation
3979  functions, which aren't handled by the kernel */
3980 
3981 #ifndef USE_CERTIFICATES
3982 
3984  C_IN char C_PTR oid,
3985  C_OUT int C_PTR criticalFlag,
3986  C_OUT void C_PTR extension,
3989  {
3990  return( CRYPT_ERROR_NOTAVAIL );
3991  }
3992 
3994  C_IN char C_PTR oid, C_IN int criticalFlag,
3995  C_IN void C_PTR extension,
3996  C_IN int extensionLength )
3997  {
3998  return( CRYPT_ERROR_NOTAVAIL );
3999  }
4000 
4002  C_IN char C_PTR oid )
4003  {
4004  return( CRYPT_ERROR_NOTAVAIL );
4005  }
4006 #endif /* !USE_CERTIFICATES */
4007 
4008 /****************************************************************************
4009 * *
4010 * Custom Code Insertion Point *
4011 * *
4012 ****************************************************************************/
4013 
4014 /* This section can be used to insert custom code for application-specific
4015  purposes. It's normally not used, and isn't present in the standard
4016  distribution */
4017 
4018 #if !defined( NDEBUG ) && 0
4019 
4020 #include "docs/cryptapi_ext.c"
4021 
4022 #endif /* Debug-mode only test code */
4023 
4024 #ifdef CONFIG_SUITEB_TESTS
4025 
4026 /* Special kludge function to enable nonstandard behaviour for Suite B
4027  tests. This just passes the call on down to the low-level internal
4028  Suite B configuration code */
4029 
4030 int sslSuiteBTestConfig( const int magicValue );
4031 
4032 C_RET cryptSuiteBTestConfig( C_IN int magicValue )
4033  {
4034  return( sslSuiteBTestConfig( magicValue ) );
4035  }
4036 #endif /* CONFIG_SUITEB_TESTS */