cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cryptses.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Secure Session Routines *
4 * Copyright Peter Gutmann 1998-2005 *
5 * *
6 ****************************************************************************/
7 
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include "crypt.h"
11 #ifdef INC_ALL
12  #include "asn1.h"
13  #include "stream.h"
14  #include "session.h"
15  #include "scorebrd.h"
16 #else
17  #include "enc_dec/asn1.h"
18  #include "io/stream.h"
19  #include "session/session.h"
20  #include "session/scorebrd.h"
21 #endif /* Compiler-specific includes */
22 
23 /* The number of entries in the SSL session cache. Note that when increasing
24  the SESSIONCACHE_SIZE value to more than about 256 you need to also change
25  MAX_ALLOC_SIZE in kernel/sec_mem.c to allow the allocation of such large
26  amounts of secure memory */
27 
28 #if defined( CONFIG_CONSERVE_MEMORY )
29  #define SESSIONCACHE_SIZE 8
30 #else
31  #define SESSIONCACHE_SIZE 64
32 #endif /* CONFIG_CONSERVE_MEMORY */
33 
34 static SCOREBOARD_STATE scoreboardInfo;
35 
36 #ifdef USE_SESSIONS
37 
38 /****************************************************************************
39 * *
40 * Session Message Handler *
41 * *
42 ****************************************************************************/
43 
44 /* Handle a message sent to a session object */
45 
47 static int sessionMessageFunction( INOUT TYPECAST( CONTEXT_INFO * ) \
48  void *objectInfoPtr,
50  void *messageDataPtr,
51  IN_INT_Z const int messageValue )
52  {
53  SESSION_INFO *sessionInfoPtr = ( SESSION_INFO * ) objectInfoPtr;
54  int status;
55 
56  assert( isWritePtr( objectInfoPtr, sizeof( SESSION_INFO ) ) );
57 
58  REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
59  REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH );
60 
61  /* Process destroy object messages */
62  if( message == MESSAGE_DESTROY )
63  {
64  /* Shut down the session if required. Nemo nisi mors */
65  if( sessionInfoPtr->flags & SESSION_ISOPEN )
66  {
67  sessionInfoPtr->flags |= SESSION_ISCLOSINGDOWN;
68  sessionInfoPtr->shutdownFunction( sessionInfoPtr );
69  }
70 
71  /* Clear and free session state information if necessary */
72  if( sessionInfoPtr->sendBuffer != NULL )
73  {
74  zeroise( sessionInfoPtr->sendBuffer,
75  sessionInfoPtr->sendBufSize );
76  clFree( "sessionMessageFunction", sessionInfoPtr->sendBuffer );
77  }
78  if( sessionInfoPtr->receiveBuffer != NULL )
79  {
80  zeroise( sessionInfoPtr->receiveBuffer,
81  sessionInfoPtr->receiveBufSize );
82  clFree( "sessionMessageFunction", sessionInfoPtr->receiveBuffer );
83  }
84 
85  /* Clear session attributes if necessary */
86  if( sessionInfoPtr->attributeList != NULL )
87  deleteSessionInfoAll( &sessionInfoPtr->attributeList,
88  &sessionInfoPtr->attributeListCurrent );
89 
90  /* Clean up any session-related objects if necessary */
91  if( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )
92  krnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,
94  if( sessionInfoPtr->iKeyexAuthContext != CRYPT_ERROR )
95  krnlSendNotifier( sessionInfoPtr->iKeyexAuthContext,
97  if( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )
98  krnlSendNotifier( sessionInfoPtr->iCryptInContext,
100  if( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )
101  krnlSendNotifier( sessionInfoPtr->iCryptOutContext,
103  if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
104  krnlSendNotifier( sessionInfoPtr->iAuthInContext,
106  if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
107  krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
109  if( sessionInfoPtr->iCertRequest != CRYPT_ERROR )
110  krnlSendNotifier( sessionInfoPtr->iCertRequest,
112  if( sessionInfoPtr->iCertResponse != CRYPT_ERROR )
113  krnlSendNotifier( sessionInfoPtr->iCertResponse,
115  if( sessionInfoPtr->privateKey != CRYPT_ERROR )
116  krnlSendNotifier( sessionInfoPtr->privateKey,
118  if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
119  krnlSendNotifier( sessionInfoPtr->cryptKeyset,
121  if( sessionInfoPtr->privKeyset != CRYPT_ERROR )
122  krnlSendNotifier( sessionInfoPtr->privKeyset,
124  if( sessionInfoPtr->transportSession != CRYPT_ERROR )
125  krnlSendNotifier( sessionInfoPtr->transportSession,
127 
128  return( CRYPT_OK );
129  }
130 
131  /* Process attribute get/set/delete messages */
132  if( isAttributeMessage( message ) )
133  {
134  /* If it's a protocol-specific attribute, forward it directly to
135  the low-level code */
136  if( message != MESSAGE_DELETEATTRIBUTE && \
137  ( ( messageValue >= CRYPT_SESSINFO_FIRST_SPECIFIC && \
138  messageValue <= CRYPT_SESSINFO_LAST_SPECIFIC ) || \
139  messageValue == CRYPT_IATTRIBUTE_ENC_TIMESTAMP ) )
140  {
141  if( message == MESSAGE_SETATTRIBUTE || \
142  message == MESSAGE_SETATTRIBUTE_S )
143  {
144  REQUIRES( sessionInfoPtr->setAttributeFunction != NULL );
145 
146  status = sessionInfoPtr->setAttributeFunction( sessionInfoPtr,
147  messageDataPtr, messageValue );
148  if( status == CRYPT_ERROR_INITED )
149  {
150  setErrorInfo( sessionInfoPtr, messageValue,
152  return( CRYPT_ERROR_INITED );
153  }
154  }
155  else
156  {
157  REQUIRES( message == MESSAGE_GETATTRIBUTE || \
158  message == MESSAGE_GETATTRIBUTE_S );
159  REQUIRES( sessionInfoPtr->getAttributeFunction != NULL );
160 
161  status = sessionInfoPtr->getAttributeFunction( sessionInfoPtr,
162  messageDataPtr, messageValue );
163  if( status == CRYPT_ERROR_NOTFOUND )
164  {
165  setErrorInfo( sessionInfoPtr, messageValue,
167  return( CRYPT_ERROR_NOTFOUND );
168  }
169  }
170  return( status );
171  }
172 
173  if( message == MESSAGE_GETATTRIBUTE )
174  return( getSessionAttribute( sessionInfoPtr,
175  ( int * ) messageDataPtr,
176  messageValue ) );
177  if( message == MESSAGE_GETATTRIBUTE_S )
178  return( getSessionAttributeS( sessionInfoPtr,
179  ( MESSAGE_DATA * ) messageDataPtr,
180  messageValue ) );
181  if( message == MESSAGE_SETATTRIBUTE )
182  {
183  /* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
184  with no parameters so we don't pass it down to the attribute-
185  handling code */
186  if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
187  return( CRYPT_OK );
188 
189  return( setSessionAttribute( sessionInfoPtr,
190  *( ( int * ) messageDataPtr ),
191  messageValue ) );
192  }
193  if( message == MESSAGE_SETATTRIBUTE_S )
194  {
195  const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
196 
197  return( setSessionAttributeS( sessionInfoPtr, msgData->data,
198  msgData->length, messageValue ) );
199  }
200  if( message == MESSAGE_DELETEATTRIBUTE )
201  return( deleteSessionAttribute( sessionInfoPtr, messageValue ) );
202 
203  retIntError();
204  }
205 
206  /* Process object-specific messages */
207  if( message == MESSAGE_ENV_PUSHDATA )
208  {
209  MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
210  const int length = msgData->length;
211  int bytesCopied;
212 
213  /* Unless we're told otherwise, we've copied zero bytes */
214  msgData->length = 0;
215 
216  /* If the session isn't open yet, perform an implicit open */
217  if( !( sessionInfoPtr->flags & SESSION_ISOPEN ) )
218  {
219  status = krnlSendMessage( sessionInfoPtr->objectHandle,
222  if( cryptStatusError( status ) )
223  return( status );
224 
225  /* The session is ready to process data, move it into the high
226  state */
227  status = krnlSendMessage( sessionInfoPtr->objectHandle,
230  CRYPT_IATTRIBUTE_INITIALISED );
231  if( cryptStatusError( status ) )
232  return( status );
233  }
234  ENSURES( sessionInfoPtr->flags & SESSION_ISOPEN );
235  ENSURES( sessionInfoPtr->sendBuffer != NULL );
236 
237  /* Make sure that everything is in order */
238  if( sessionInfoPtr->flags & SESSION_SENDCLOSED )
239  {
240  /* If the other side has closed its receive channel (which is
241  our send channel), we can't send any more data, although we
242  can still get data on our receive channel if we haven't closed
243  it as well. The closing of the other side's send channel is
244  detected during a read and isn't a write error but a normal
245  state change in the channel so we don't treat it as an error
246  when it's seen at the read stage until the caller actually
247  tries to write data to the closed channel */
248  sessionInfoPtr->writeErrorState = CRYPT_ERROR_COMPLETE;
249  }
250  if( sessionInfoPtr->writeErrorState != CRYPT_OK )
251  return( sessionInfoPtr->writeErrorState );
252 
253  /* Write the data */
254  clearErrorInfo( sessionInfoPtr );
255  status = putSessionData( sessionInfoPtr, msgData->data, length,
256  &bytesCopied );
257  if( cryptStatusOK( status ) )
258  msgData->length = bytesCopied;
259  ENSURES( ( cryptStatusError( status ) && bytesCopied == 0 ) || \
260  ( cryptStatusOK( status ) && bytesCopied >= 0 ) );
261  return( status );
262  }
263  if( message == MESSAGE_ENV_POPDATA )
264  {
265  MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
266  const int length = msgData->length;
267  int bytesCopied;
268 
269  /* Unless we're told otherwise, we've copied zero bytes */
270  msgData->length = 0;
271 
272  /* If the session isn't open, there's nothing to pop */
273  if( !( sessionInfoPtr->flags & SESSION_ISOPEN ) )
274  return( CRYPT_ERROR_NOTINITED );
275 
276  ENSURES( sessionInfoPtr->flags & SESSION_ISOPEN );
277  ENSURES( sessionInfoPtr->receiveBuffer != NULL );
278 
279  /* Make sure that everything is in order */
280  if( sessionInfoPtr->readErrorState != CRYPT_OK )
281  return( sessionInfoPtr->readErrorState );
282 
283  /* Read the data */
284  clearErrorInfo( sessionInfoPtr );
285  status = getSessionData( sessionInfoPtr, msgData->data, length,
286  &bytesCopied );
287  if( cryptStatusOK( status ) )
288  msgData->length = bytesCopied;
289  ENSURES( ( cryptStatusError( status ) && bytesCopied == 0 ) || \
290  ( cryptStatusOK( status ) && bytesCopied >= 0 ) );
291  return( status );
292  }
293 
294  retIntError();
295  }
296 
297 /* Open a session. This is a low-level function encapsulated by createSession()
298  and used to manage error exits */
299 
300 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
301 static int openSession( OUT_HANDLE_OPT CRYPT_SESSION *iCryptSession,
304  const CRYPT_SESSION_TYPE sessionType,
305  OUT_OPT_PTR SESSION_INFO **sessionInfoPtrPtr )
306  {
307  CRYPT_SESSION_TYPE sessionBaseType;
309  const PROTOCOL_INFO *protocolInfoPtr;
310  static const MAP_TABLE subtypeMapTbl[] = {
327  };
328  static const MAP_TABLE basetypeMapTbl[] = {
345  };
346  OBJECT_SUBTYPE subType;
347  int value, storageSize, status;
348 
349  assert( isWritePtr( iCryptSession, sizeof( CRYPT_SESSION * ) ) );
350  assert( isWritePtr( sessionInfoPtrPtr, sizeof( SESSION_INFO * ) ) );
351 
352  REQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
353  isHandleRangeValid( iCryptOwner ) );
354  REQUIRES( sessionType > CRYPT_SESSION_NONE && \
355  sessionType < CRYPT_SESSION_LAST );
356 
357  /* Clear return values */
358  *iCryptSession = CRYPT_ERROR;
359  *sessionInfoPtrPtr = NULL;
360 
361  /* Map the external session type to a base type and internal object
362  subtype */
363  status = mapValue( sessionType, &value, subtypeMapTbl,
364  FAILSAFE_ARRAYSIZE( subtypeMapTbl, MAP_TABLE ) );
365  ENSURES( cryptStatusOK( status ) );
366  subType = value;
367  status = mapValue( sessionType, &value, basetypeMapTbl,
368  FAILSAFE_ARRAYSIZE( basetypeMapTbl, MAP_TABLE ) );
369  ENSURES( cryptStatusOK( status ) );
370  sessionBaseType = value;
371 
372  /* Set up subtype-specific information */
373  switch( sessionBaseType )
374  {
375  case CRYPT_SESSION_SSH:
376  storageSize = sizeof( SSH_INFO );
377  break;
378 
379  case CRYPT_SESSION_SSL:
380  storageSize = sizeof( SSL_INFO );
381  break;
382 
383  case CRYPT_SESSION_TSP:
384  storageSize = sizeof( TSP_INFO );
385  break;
386 
387  case CRYPT_SESSION_CMP:
388  storageSize = sizeof( CMP_INFO );
389  break;
390 
391  case CRYPT_SESSION_SCEP:
392  storageSize = sizeof( SCEP_INFO );
393  break;
394 
395  case CRYPT_SESSION_RTCS:
396  case CRYPT_SESSION_OCSP:
398  storageSize = 0;
399  break;
400 
401  default:
402  retIntError();
403  }
404 
405  /* Create the session object */
406  status = krnlCreateObject( iCryptSession, ( void ** ) &sessionInfoPtr,
407  sizeof( SESSION_INFO ) + storageSize,
408  OBJECT_TYPE_SESSION, subType,
409  CREATEOBJECT_FLAG_NONE, iCryptOwner,
410  ACTION_PERM_NONE_ALL, sessionMessageFunction );
411  if( cryptStatusError( status ) )
412  return( status );
413  ANALYSER_HINT( sessionInfoPtr != NULL );
414  *sessionInfoPtrPtr = sessionInfoPtr;
415  sessionInfoPtr->objectHandle = *iCryptSession;
416  sessionInfoPtr->ownerHandle = iCryptOwner;
417  sessionInfoPtr->type = sessionBaseType;
418  if( storageSize > 0 )
419  {
420  switch( sessionBaseType )
421  {
422  case CRYPT_SESSION_SSH:
423  sessionInfoPtr->sessionSSH = \
424  ( SSH_INFO * ) sessionInfoPtr->storage;
425  break;
426 
427  case CRYPT_SESSION_SSL:
428  sessionInfoPtr->sessionSSL = \
429  ( SSL_INFO * ) sessionInfoPtr->storage;
430  break;
431 
432  case CRYPT_SESSION_TSP:
433  sessionInfoPtr->sessionTSP = \
434  ( TSP_INFO * ) sessionInfoPtr->storage;
435  break;
436 
437  case CRYPT_SESSION_CMP:
438  sessionInfoPtr->sessionCMP = \
439  ( CMP_INFO * ) sessionInfoPtr->storage;
440  break;
441 
442  case CRYPT_SESSION_SCEP:
443  sessionInfoPtr->sessionSCEP = \
444  ( SCEP_INFO * ) sessionInfoPtr->storage;
445  break;
446 
447  default:
448  retIntError();
449  }
450  }
451  sessionInfoPtr->storageSize = storageSize;
452 
453  /* If it's a server session, mark it as such. An HTTP certstore session
454  is a special case in that it's always a server session */
455  if( ( sessionType != sessionBaseType ) || \
456  ( sessionType == CRYPT_SESSION_CERTSTORE_SERVER ) )
457  sessionInfoPtr->flags = SESSION_ISSERVER;
458 
459  /* Set up any internal objects to contain invalid handles */
460  sessionInfoPtr->iKeyexCryptContext = \
461  sessionInfoPtr->iKeyexAuthContext = CRYPT_ERROR;
462  sessionInfoPtr->iCryptInContext = \
463  sessionInfoPtr->iCryptOutContext = CRYPT_ERROR;
464  sessionInfoPtr->iAuthInContext = \
465  sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
466  sessionInfoPtr->iCertRequest = \
467  sessionInfoPtr->iCertResponse = CRYPT_ERROR;
468  sessionInfoPtr->privateKey = CRYPT_ERROR;
469  sessionInfoPtr->cryptKeyset = CRYPT_ERROR;
470  sessionInfoPtr->privKeyset = CRYPT_ERROR;
471  sessionInfoPtr->transportSession = CRYPT_ERROR;
472  sessionInfoPtr->networkSocket = CRYPT_ERROR;
473  sessionInfoPtr->readTimeout = \
474  sessionInfoPtr->writeTimeout = \
475  sessionInfoPtr->connectTimeout = CRYPT_ERROR;
476 
477  /* Set up any additinal values */
478  sessionInfoPtr->authResponse = CRYPT_UNUSED;
479 
480  /* Set up the access information for the session and initialise it */
481  switch( sessionBaseType )
482  {
484  status = setAccessMethodCertstore( sessionInfoPtr );
485  break;
486 
487  case CRYPT_SESSION_CMP:
488  status = setAccessMethodCMP( sessionInfoPtr );
489  break;
490 
491  case CRYPT_SESSION_RTCS:
492  status = setAccessMethodRTCS( sessionInfoPtr );
493  break;
494 
495  case CRYPT_SESSION_OCSP:
496  status = setAccessMethodOCSP( sessionInfoPtr );
497  break;
498 
499  case CRYPT_SESSION_SCEP:
500  status = setAccessMethodSCEP( sessionInfoPtr );
501  break;
502 
503  case CRYPT_SESSION_SSH:
504  status = setAccessMethodSSH( sessionInfoPtr );
505  break;
506 
507  case CRYPT_SESSION_SSL:
508  status = setAccessMethodSSL( sessionInfoPtr );
509  break;
510 
511  case CRYPT_SESSION_TSP:
512  status = setAccessMethodTSP( sessionInfoPtr );
513  break;
514 
515  default:
516  retIntError();
517  }
518  if( cryptStatusError( status ) )
519  return( status );
520 
521  /* If it's a session type that uses the scoreboard, set up the
522  scoreboard information for the session */
523  if( sessionType == CRYPT_SESSION_SSL || \
524  sessionType == CRYPT_SESSION_SSL_SERVER )
525  sessionInfoPtr->sessionSSL->scoreboardInfoPtr = &scoreboardInfo;
526 
527  /* Check that the protocol info is OK */
528  protocolInfoPtr = sessionInfoPtr->protocolInfo;
529  ENSURES( ( protocolInfoPtr->isReqResp && \
530  protocolInfoPtr->bufSize == 0 && \
531  protocolInfoPtr->sendBufStartOfs == 0 && \
532  protocolInfoPtr->maxPacketSize == 0 ) ||
533  ( !protocolInfoPtr->isReqResp && \
534  protocolInfoPtr->bufSize >= MIN_BUFFER_SIZE && \
535  protocolInfoPtr->bufSize < MAX_INTLENGTH && \
536  protocolInfoPtr->sendBufStartOfs >= 5 &&
537  protocolInfoPtr->sendBufStartOfs < protocolInfoPtr->maxPacketSize && \
538  protocolInfoPtr->maxPacketSize <= protocolInfoPtr->bufSize ) );
539  ENSURES( ( ( protocolInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) && \
540  protocolInfoPtr->port == 80 ) || \
541  ( protocolInfoPtr->port != 80 ) );
542  ENSURES( protocolInfoPtr->port > 21 && protocolInfoPtr->port <= 65534L );
543  ENSURES( protocolInfoPtr->version >= 0 && protocolInfoPtr->version < 5 );
544 
545  /* Copy mutable protocol-specific information into the session info */
546  sessionInfoPtr->flags |= protocolInfoPtr->flags;
547  sessionInfoPtr->clientReqAttrFlags = protocolInfoPtr->clientReqAttrFlags;
548  sessionInfoPtr->serverReqAttrFlags = protocolInfoPtr->serverReqAttrFlags;
549  sessionInfoPtr->version = protocolInfoPtr->version;
550  if( protocolInfoPtr->isReqResp )
551  {
552  sessionInfoPtr->sendBufSize = CRYPT_UNUSED;
553  sessionInfoPtr->receiveBufSize = MIN_BUFFER_SIZE;
554  }
555  else
556  {
557  sessionInfoPtr->sendBufSize = sessionInfoPtr->receiveBufSize = \
558  protocolInfoPtr->bufSize;
559  sessionInfoPtr->sendBufStartOfs = sessionInfoPtr->receiveBufStartOfs = \
560  protocolInfoPtr->sendBufStartOfs;
561  sessionInfoPtr->maxPacketSize = protocolInfoPtr->maxPacketSize;
562  }
563 
564  /* Install default handlers if no session-specific ones are provided */
565  status = initSessionIO( sessionInfoPtr );
566  if( cryptStatusError( status ) )
567  return( status );
568 
569  /* Check that the handlers are all OK */
570  ENSURES( sessionInfoPtr->connectFunction != NULL );
571  ENSURES( sessionInfoPtr->transactFunction != NULL );
572  ENSURES( ( protocolInfoPtr->isReqResp && \
573  sessionInfoPtr->readHeaderFunction == NULL && \
574  sessionInfoPtr->processBodyFunction == NULL && \
575  sessionInfoPtr->preparePacketFunction == NULL ) || \
576  ( !protocolInfoPtr->isReqResp && \
577  sessionInfoPtr->readHeaderFunction != NULL && \
578  sessionInfoPtr->processBodyFunction != NULL && \
579  sessionInfoPtr->preparePacketFunction != NULL ) );
580 
581  return( CRYPT_OK );
582  }
583 
585 int createSession( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
586  STDC_UNUSED const void *auxDataPtr,
587  STDC_UNUSED const int auxValue )
588  {
589  CRYPT_SESSION iCryptSession;
590  SESSION_INFO *sessionInfoPtr = NULL;
591  int initStatus, status;
592 
593  assert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
594 
595  REQUIRES( auxDataPtr == NULL && auxValue == 0 );
596  REQUIRES( createInfo->arg1 > CRYPT_SESSION_NONE && \
597  createInfo->arg1 < CRYPT_SESSION_LAST );
598 
599  /* Pass the call on to the lower-level open function */
600  initStatus = openSession( &iCryptSession, createInfo->cryptOwner,
601  createInfo->arg1, &sessionInfoPtr );
602  if( cryptStatusError( initStatus ) )
603  {
604  /* If the create object failed, return immediately */
605  if( sessionInfoPtr == NULL )
606  return( initStatus );
607 
608  /* The init failed, make sure that the object gets destroyed when we
609  notify the kernel that the setup process is complete */
610  krnlSendNotifier( iCryptSession, IMESSAGE_DESTROY );
611  }
612 
613  /* We've finished setting up the object-type-specific info, tell the
614  kernel that the object is ready for use */
615  status = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,
616  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
617  if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
618  return( cryptStatusError( initStatus ) ? initStatus : status );
619  createInfo->cryptHandle = iCryptSession;
620 
621  return( CRYPT_OK );
622  }
623 
624 /* Generic management function for this class of object */
625 
626 CHECK_RETVAL \
627 int sessionManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
628  const MANAGEMENT_ACTION_TYPE action )
629  {
630  static int initLevel = 0;
631  int status;
632 
633  REQUIRES( action == MANAGEMENT_ACTION_INIT || \
634  action == MANAGEMENT_ACTION_PRE_SHUTDOWN || \
635  action == MANAGEMENT_ACTION_SHUTDOWN );
636 
637  switch( action )
638  {
640  status = netInitTCP();
641  if( cryptStatusOK( status ) )
642  {
643  initLevel++;
644  if( krnlIsExiting() )
645  {
646  /* The kernel is shutting down, exit */
647  return( CRYPT_ERROR_PERMISSION );
648  }
649  status = initScoreboard( &scoreboardInfo,
651  }
652  if( cryptStatusOK( status ) )
653  initLevel++;
654  return( status );
655 
657  /* We have to wait for the driver binding to complete before we
658  can start the shutdown process */
660  {
661  /* The kernel is shutting down, bail out */
662  DEBUG_DIAG(( "Exiting due to kernel shutdown" ));
663  assert( DEBUG_WARN );
664  return( CRYPT_ERROR_PERMISSION );
665  }
666  if( initLevel > 0 )
668  return( CRYPT_OK );
669 
671  if( initLevel > 1 )
672  endScoreboard( &scoreboardInfo );
673  if( initLevel > 0 )
674  netEndTCP();
675  initLevel = 0;
676 
677  return( CRYPT_OK );
678  }
679 
680  retIntError();
681  }
682 #endif /* USE_SESSIONS */