1 /****************************************************************************
2 *																			*
3 *						Secure Session Routines Header File					*
4 *						 Copyright Peter Gutmann 1998-2013					*
5 *																			*
6 ****************************************************************************/
7 
8 #ifndef _SES_DEFINED
9 
10 #define _SES_DEFINED
11 
12 #ifndef _STREAM_DEFINED
13   #if defined( INC_ALL )
14 	#include "stream.h"
15   #else
16 	#include "io/stream.h"
17   #endif /* Compiler-specific includes */
18 #endif /* _STREAM_DEFINED */
19 
20 /****************************************************************************
21 *																			*
22 *							Session Types and Constants						*
23 *																			*
24 ****************************************************************************/
25 
26 /* Session information flags.  These are:
27 
28 	SESSION_ISOPEN: The session is active.
29 
30 	SESSION_PARTIALOPEN: The session is partially active pending
31 			confirmation of credentials such as a username and password
32 			or certificate.  This means that the session remains in the
33 			handshake state, with the handshake being completed once the
34 			credentials have been confirmed.
35 
36 	SESSION_SENDCLOSED: The remote system has closed its receive channel,
37 			which means that no more data can be sent to it.  This does not
38 			however mean that no more data can be received on our receive
39 			channel.
40 
41 	SESSION_ISCLOSINGDOWN: The session is in the shutdown stage, if further
42 			requests from the remote system arrive they should be NACK'd or
43 			ignored.
44 
45 	SESSION_NOREPORTERROR: Don't update the extended error information if
46 			an error occurs, since this has already been set.  This is
47 			typically used when performing shutdown actions in response to
48 			a protocol error, when a network error such as the other side
49 			closing the connection would overwrite the details of the
50 			error that caused the shutdown to be performed.
51 
52 	SESSION_ISSERVER: The session is a server session.
53 
54 	SESSION_ISSECURE_READ:  The read/write channel is in the secure state,
55 	SESSION_ISSECURE_WRITE: for secure data transport sessions.  In other
56 			words the session has passed the initial handshake stage and all
57 			data is now being encrypted/MACd/whatever.
58 
59 	SESSION_ISCRYPTLIB: The peer is also running cryptlib, which means that
60 			we can apply cryptlib-specific optimistions and security
61 			enhancements.
62 
63 	SESSION_ISHTTPTRANSPORT: The session is using HTTP transport, for
64 			request/response sessions */
65 
66 #define SESSION_NONE				0x0000	/* No session flags */
67 #define SESSION_ISOPEN				0x0001	/* Session is active */
68 #define SESSION_PARTIALOPEN			0x0002	/* Session is partially active */
69 #define SESSION_SENDCLOSED			0x0004	/* Send channel is closed */
70 #define SESSION_ISCLOSINGDOWN		0x0008	/* Session is in process of shutdown */
71 #define SESSION_NOREPORTERROR		0x0010	/* Don't report network-level errors */
72 #define SESSION_ISSERVER			0x0020	/* Session is server session */
73 #define SESSION_ISSECURE_READ		0x0040	/* Session read ch.in secure state */
74 #define SESSION_ISSECURE_WRITE		0x0080	/* Session write ch.in secure state */
75 #define SESSION_ISCRYPTLIB			0x0100	/* Peer is running cryptlib */
76 #define SESSION_ISHTTPTRANSPORT		0x0200	/* Session using HTTP transport */
77 
78 /* Needed-information flags used by protocol-specific handlers to indicate
79    that the caller must set the given attributes in the session information
80    before the session can be activated.  This allows it to be checked at the
81    general cryptses.c level rather than at the per-protocol level.
82 
83    Some session types have private keys optional but if present they must
84    meet certain requirements, this is indicated by omitting the presence-
85    check SESSION_NEEDS_PRIVATEKEY but specifying one or more of the
86    SESSION_NEEDS_PRIVKEYxxx options */
87 
88 #define SESSION_NEEDS_USERID		0x0001	/* Must have userID */
89 #define SESSION_NEEDS_PASSWORD		0x0002	/* Must have password */
90 #define SESSION_NEEDS_PRIVATEKEY	0x0004	/* Must have private key */
91 #define SESSION_NEEDS_PRIVKEYCRYPT	0x0008	/* Priv.key must have certificate */
92 #define SESSION_NEEDS_PRIVKEYSIGN	0x0010	/* Priv.key must have sig.capabil.*/
93 #define SESSION_NEEDS_PRIVKEYCERT	0x0020	/* Priv.key must have crypt capabil.*/
94 #define SESSION_NEEDS_PRIVKEYCACERT	0x0040	/* Priv key must have CA certificate */
95 #define SESSION_NEEDS_KEYORPASSWORD	( 0x0080 | SESSION_NEEDS_PASSWORD | \
96 									  SESSION_NEEDS_PRIVATEKEY )
97 											/* Password can be used in place of
98 											   private, this is a modifier on top
99 											   of privKey/password */
100 #define SESSION_NEEDS_REQUEST		0x0100	/* Must have request obj.*/
101 #define SESSION_NEEDS_KEYSET		0x0200	/* Must have certificate keyset */
102 #define SESSION_NEEDS_CERTSTORE		0x0400	/* Keyset must be certificate store */
103 
104 /* The minimum- and maximum-length fixed headers that we should see in
105    header-read code */
106 
107 #define FIXED_HEADER_MIN			5		/* SSL header */
108 #define FIXED_HEADER_MAX			21		/* TLS 1.1+ header with explicit
109 											   AES IV */
110 
111 /* When reading packets for a secure session protocol, we need to
112    communicate read state information which is more complex than the usual
113    length or error code.  The following values modify the standard return
114    value (either a positive or zero byte count or a negative error value)
115    with additional context-specific information */
116 
117 typedef enum {
118 	READINFO_NONE,						/* No special handling */
119 	READINFO_HEADERPAYLOAD,				/* Header read got some payload data */
120 	READINFO_NOOP,						/* Packet was no-op, try again */
121 	READINFO_PARTIAL,					/* Partial packet, try again */
122 	READINFO_FATAL,						/* Treat errors as fatal */
123 	READINFO_LAST						/* Last possible read information */
124 	} READSTATE_INFO;
125 
126 /* The control mechanism for authorisation in interactive sessions.
127    Normally when the server gets a user-authorisation request it'll return a
128    CRYPT_ENVELOPE_RESOURCE to tell the caller that they need to decide what
129    to do with the request.  If they set it to AUTHRESPONSE_SUCCESS, we allow
130    the client authorisation, if they set it to AUTHRESPONSE_FAILURE we
131    disallow it and the client gets another go at authorising themselves.
132    The default setting of AUTHRESPONSE_NONE means that we ask the user for
133    instructions */
134 
135 typedef enum {
136 	AUTHRESPONSE_NONE,					/* No authorisation response */
137 	AUTHRESPONSE_SUCCESS,				/* Allow authorisation */
138 	AUTHRESPONSE_FAILURE,				/* Disallow authorisation */
139 	AUTHRESPONSE_LAST					/* Last possible authorisation response */
140 	} AUTHRESPONSE_TYPE;
141 
142 /****************************************************************************
143 *																			*
144 *								Session Structures							*
145 *																			*
146 ****************************************************************************/
147 
148 /* Protocol-specific information for each session */
149 
150 typedef struct {
151 	/* Information required for all sessions: Whether this is a secure
152 	   session or request/response protocol, protocol-specific flags, the
153 	   default port for the protocol, flags for attributes required before
154 	   the session can be activated, the default protocol version and lowest
155 	   and highest allowed versions, and the transport-protocol client and
156 	   server content-types */
157 	const BOOLEAN isReqResp;			/* Whether session is req/resp session */
158 	const int flags;					/* Protocol flags */
159 	const int port;						/* Default port */
160 	const int clientReqAttrFlags, serverReqAttrFlags; /* Required attributes */
161 	const int version, minVersion, maxVersion;/* Protocol version/subtype */
162 
163 	/* Session type-specific information: The send and receive buffer size,
164 	   the alternative transport protocol for request/response sessions if
165 	   HTTP isn't being used, the minimum allowed size for the server's
166 	   private key */
167 	const int bufSize;					/* Send/receive buffer sizes */
168 	const int sendBufStartOfs;			/* Payload data start */
169 	const int maxPacketSize;			/* Maximum packet (payload data) size */
170 	} PROTOCOL_INFO;
171 
172 /* A value to initialise the session type-specific buffer size values to
173    default settings for request/response protocols */
174 
175 #define BUFFER_SIZE_DEFAULT		0, 0, 0
176 
177 /* Attribute flags.  These are:
178 
179 	FLAG_COMPOSITE: Composite attribute containing sub-attribute data in the
180 			{ value, valueLength } buffer.  The attribute cursor can be
181 			moved within the attribute using the internal virtual cursor.
182 
183 	FLAG_CURSORMOVED: The attribute (group) cursor has moved, so the virtual
184 			cursor within the attribute needs to be reset the next time that
185 			it's referenced.  This is used with composite attributes, whose
186 			internal structure is opaque to the general session code.
187 
188 	FLAG_ENCODEDVALUE: The attribute value is stored in cryptlib
189 			XXXXX-XXXXX-... style encoding and needs to be converted to
190 			binary form before use.
191 
192 	FLAG_EPHEMERAL: The attribute is only valid for the current session
193 			activation and is cleared between session re-activations.
194 
195 	FLAG_MULTIVALUED: Multiple instances of the attribute are permitted.
196 			This complements ATTR_FLAG_OVERWRITE in that instead of
197 			overwriting the single existing instance, another instance is
198 			created */
199 
200 #define ATTR_FLAG_NONE			0x00	/* No attribute flag */
201 #define ATTR_FLAG_ENCODEDVALUE	0x01	/* Value uses XXX-XXX encoding */
202 #define ATTR_FLAG_MULTIVALUED	0x02	/* Multiple instances permitted */
203 #define ATTR_FLAG_COMPOSITE		0x04	/* Composite attribute */
204 #define ATTR_FLAG_CURSORMOVED	0x08	/* Attribute virtual cursor reset */
205 #define ATTR_FLAG_EPHEMERAL		0x10	/* Only valid for current sess.act.*/
206 #define ATTR_FLAG_MAX			0x1F	/* Maximum possible flag value */
207 
208 /* The helper function used to access session subtype-specific internal
209    attributes within an attribute list entry */
210 
211 struct AL;	/* Forward declaration for attribute-list access function */
212 
213 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
214 		int ( *ATTRACCESS_FUNCTION )( INOUT struct AL *attributeListPtr,
215 									  IN_ENUM_OPT( ATTR ) \
216 										const ATTR_TYPE attrGetType,
217 									  OUT_INT_Z int *value );
218 
219 /* An attribute list used to store session-related attributes such as
220    user names, passwords, and public keys.  Since some of these can be
221    composite attributes (with information stored in the { value,
222    valueLength } buffer), we implement a virtual cursor that points to the
223    currently-selected sub-attribute within the composite attribute */
224 
225 typedef struct AL {
226 	/* Identification and other information for this attribute */
227 	CRYPT_ATTRIBUTE_TYPE groupID, attributeID;
228 										/* Attribute group and type */
229 	FNPTR_DECLARE( ATTRACCESS_FUNCTION, accessFunction );
230 										/* Internal attribute access fn.*/
231 	int flags;							/* Attribute data flags */
232 
233 	/* The data payload for this attribute.  If it's numeric data such as
234 	   a small integer or context, we store it in the intValue member.  If
235 	   it's a string or composite attribute data, we store it in the
236 	   variable-length buffer */
237 	long intValue;						/* Integer value for simple types */
238 	BUFFER_OPT_FIXED( valueLength ) \
239 	void *value;						/* Attribute value */
240 	int valueLength;					/* Attribute value length */
241 
242 	/* The previous and next list element in the linked list of elements */
243 	struct AL *prev, *next;				/* Prev, next item in the list */
244 
245 	/* Variable-length storage for the attribute data */
246 	DECLARE_VARSTRUCT_VARS;
247 	} ATTRIBUTE_LIST;
248 
249 /* Deferred response information.  When we get a request, we may be in the
250    middle of assembling or sending a data packet, so the response has to be
251    deferred until after the data packet has been completed and sent.  The
252    following structure is used to hold the response data until the send
253    channel is clear */
254 
255 #define SSH_MAX_RESPONSESIZE	16		/* 2 * channelNo + 2 * param */
256 
257 typedef struct {
258 	int type;							/* Response type */
259 	BUFFER( SSH_MAX_RESPONSESIZE, dataLen ) \
260 	BYTE data[ SSH_MAX_RESPONSESIZE + 8 ];	/* Encoded response data */
261 	int dataLen;
262 	} SSH_RESPONSE_INFO;
263 
264 /* The internal fields in a session that hold data for the various session
265    types */
266 
267 typedef struct {
268 	/* Session state information */
269 	int sessionCacheID;					/* Session cache ID for this session */
270 	int minVersion;						/* Minimum acceptable protocol version */
271 	int ivSize;							/* Explicit IV size for TLS 1.1+ */
272 
273 	/* The incoming and outgoing packet sequence number, for detecting
274 	   insertion/deletion attacks */
275 	long readSeqNo, writeSeqNo;
276 
277 	/* The SSL MAC read/write secrets are required because SSL 3.0 uses a
278 	   proto-HMAC that isn't handled by cryptlib.  We leave the data in
279 	   normal memory because it's only usable for an active attack, which
280 	   means that recovering it from swap afterwards isn't a problem */
281 	BUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \
282 	BYTE macReadSecret[ CRYPT_MAX_HASHSIZE + 8 ];
283 	BUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \
284 	BYTE macWriteSecret[ CRYPT_MAX_HASHSIZE + 8 ];
285 
286 	/* TLS 1.2+ with GCM modes breaks the IV down into two parts, an
287 	   explicit portion that's sent with every packet and an implicit
288 	   portion that's derived from the master secret.  To save space
289 	   we store this in the data block for the SSL 3.0 MAC read/write
290 	   secrets */
291 	#define gcmReadSalt		macReadSecret
292 	#define gcmWriteSalt	macWriteSecret
293 	int gcmSaltSize;
294 
295 	/* When TLS 1.1+ explicit IVs are used the IV is stripped on read so
296 	   that the remaining packet data can be copied into the read buffer for
297 	   in-place processing, however when used with encrypt-then-MAC we need
298 	   to store the read IV in order that it can be MAC'd once the packet is
299 	   processed */
300 	BYTE iv[ CRYPT_MAX_IVSIZE + 8 ];
301 
302 	/* When performing manual certificate checking the handshake is
303 	   interrupted halfway through, so we have to store the handshake state
304 	   in order to allow it to be continued later.  The following pointer
305 	   points to this state data, a buffer of size SSL_HANDSHAKE_INFO */
306 	void *savedHandshakeInfo;			/* Saved handshake state */
307 
308 	/* The session scoreboard, used for the SSL session cache */
309 	void *scoreboardInfoPtr;			/* Session scoreboard */
310 
311 	/* A buffer for the SSL packet header, which is read out-of-band */
312 	BUFFER_FIXED( 8 + CRYPT_MAX_IVSIZE ) \
313 	BYTE headerBuffer[ 8 + CRYPT_MAX_IVSIZE + 8 ];
314 	} SSL_INFO;
315 
316 typedef struct {
317 	/* The packet type and padding length, which are extracted from the
318 	   packet header during header processing */
319 	int packetType, padLength;
320 
321 	/* The incoming and outgoing packet sequence number, for detecting
322 	   insertion/deletion attacks */
323 	long readSeqNo, writeSeqNo;
324 
325 	/* Per-channel state information */
326 	int currReadChannel, currWriteChannel; /* Current active R/W channels */
327 	int nextChannelNo;					/* Next SSH channel no.to use */
328 	int channelIndex;					/* Current cryptlib unique channel ID */
329 
330 	/* Deferred response data, used to enqueue responses when unwritten data
331 	   remains in the send buffer */
332 	SSH_RESPONSE_INFO response;
333 
334 	/* Whether an SSH user authentication packet has been read ready for the
335 	   server to act on */
336 	BOOLEAN authRead;
337 
338 	/* A buffer for the SSH packet header, which we receive in encrypted
339 	   form so that it needs to be decrypted, parts discarded, and the
340 	   remainder copied into the main buffer as payload data (ugh) */
341 	BUFFER_FIXED( CRYPT_MAX_IVSIZE ) \
342 	BYTE headerBuffer[ CRYPT_MAX_IVSIZE + 8 ];
343 
344 	/* To keep track of the partially-processed data we need to augment the
345 	   standard pendingPacket indicators with an additional value that
346 	   tracks how much of the pending packet has already been processed as
347 	   part of the header read */
348 	int partialPacketDataLength;		/* Length of data already processed */
349 
350 	/* The SSH spec allows authentication to be performed in lots of little
351 	   bits and pieces, which give an attacker lots of leeway to fiddle with
352 	   the credentials being submitted on different passes of the
353 	   authentication to try and confuse the server.  To avoid this problem
354 	   we require that the userID and authentication method remain constant
355 	   over different iterations of authentication, which unfortunately
356 	   means recording a pile of server-side authentication state */
357 	BUFFER_FIXED( KEYID_SIZE ) \
358 	BYTE authUserNameHash[ KEYID_SIZE + 8 ];	/* Hashed userID */
359 	int authType;						/* Authentication method */
360 	} SSH_INFO;
361 
362 typedef struct {
363 	/* The message imprint (hash) algorithm and hash value */
364 	CRYPT_ALGO_TYPE imprintAlgo;
365 	BUFFER( CRYPT_MAX_HASHSIZE, imprintSize ) \
366 	BYTE imprint[ CRYPT_MAX_HASHSIZE ];
367 	int imprintSize;
368 	} TSP_INFO;
369 
370 typedef struct {
371 	/* CMP request subtype, user information and protocol flags */
372 	int requestType;					/* CMP request subtype */
373 	CRYPT_CERTIFICATE userInfo;			/* PKI user information */
374 	int flags;							/* Protocol flags */
375 
376 	/* The saved MAC context from a previous transaction (if any).  This is
377 	   saved across transactions in case the same user information is used
378 	   for subsequent transactions, see the comment in cmp.h for details */
379 	CRYPT_CONTEXT savedMacContext;		/* MAC context from prev.trans */
380 	} CMP_INFO;
381 
382 typedef struct {
383 	/* SCEP request type and protocol flags */
384 	int requestType;					/* SCEP request subtype */
385 	int flags;							/* Protocol flags */
386 	} SCEP_INFO;
387 
388 /* Defines to make access to the union fields less messy */
389 
390 #define sessionSSH		sessionInfo.sshInfo
391 #define sessionSSL		sessionInfo.sslInfo
392 #define sessionTSP		sessionInfo.tspInfo
393 #define sessionCMP		sessionInfo.cmpInfo
394 #define sessionSCEP		sessionInfo.scepInfo
395 
396 /* The structure that stores the information on a session */
397 
398 struct SI;
399 
400 typedef STDC_NONNULL_ARG( ( 1 ) ) \
401 		void ( *SES_SHUTDOWN_FUNCTION )( INOUT struct SI *sessionInfoPtr );
402 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
403 		int ( *SES_CONNECT_FUNCTION )( INOUT struct SI *sessionInfoPtr );
404 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
405 		int ( *SES_GETATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr,
406 											OUT void *data,
407 											IN_ATTRIBUTE \
408 												const CRYPT_ATTRIBUTE_TYPE type );
409 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
410 		int ( *SES_SETATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr,
411 											IN const void *data,
412 											IN_ATTRIBUTE \
413 												const CRYPT_ATTRIBUTE_TYPE type );
414 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
415 		int ( *SES_CHECKATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr,
416 											  IN const void *data,
417 											  IN_ATTRIBUTE \
418 												const CRYPT_ATTRIBUTE_TYPE type );
419 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
420 		int ( *SES_TRANSACT_FUNCTION )( INOUT struct SI *sessionInfoPtr );
421 typedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \
422 		int ( *SES_READHEADER_FUNCTION )( INOUT struct SI *sessionInfoPtr,
423 										  OUT_ENUM_OPT( READINFO ) \
424 											READSTATE_INFO *readInfo );
425 typedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \
426 		int ( *SES_PROCESSBODY_FUNCTION )( INOUT struct SI *sessionInfoPtr,
427 										   OUT_ENUM_OPT( READINFO ) \
428 											READSTATE_INFO *readInfo );
429 typedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
430 		int ( *SES_PREPAREPACKET_FUNCTION )( INOUT struct SI *sessionInfoPtr );
431 
432 typedef struct SI {
433 	/* Control and status information */
434 	CRYPT_SESSION_TYPE type;			/* Session type */
435 	const PROTOCOL_INFO *protocolInfo;	/* Session subtype information */
436 	int version;						/* Protocol version/subtype */
437 	CRYPT_ALGO_TYPE cryptAlgo;			/* Negotiated encryption algo */
438 	CRYPT_ALGO_TYPE integrityAlgo;		/* Negotiated integrity prot.algo */
439 	int flags, protocolFlags;			/* Session information, protocol-specific flags */
440 	AUTHRESPONSE_TYPE authResponse;		/* Response to user-auth request */
441 
442 	/* Session type-specific information */
443 	union {
444 		SSL_INFO *sslInfo;
445 		SSH_INFO *sshInfo;
446 		TSP_INFO *tspInfo;
447 		CMP_INFO *cmpInfo;
448 		SCEP_INFO *scepInfo;
449 		} sessionInfo;
450 
451 	/* When we add generic attributes to the session, we occasionally need to
452 	   perform protocol-specific checking of the attributes being added.  The
453 	   following values are used to tell the generic cryptses.c code which
454 	   checks need to be performed */
455 	int clientReqAttrFlags, serverReqAttrFlags; /* Required attributes */
456 
457 	/* The overall session status.  If we run into a nonrecoverable error
458 	   (which for the encrypted session types means just about anything,
459 	   once we lose sync we're toast) we remember the status here so that
460 	   any further attempts to work with the session will return this
461 	   status.  Since an error on one side of the channel (e.g. bad data on
462 	   read) doesn't necessarily affect the operation of the other side, we
463 	   keep track of the two sides independantly, and only set the error
464 	   state for both sides for network-related errors.
465 
466 	   In many cases there'll still be data in the internal buffer that the
467 	   user can read/write without triggering an error response so before we
468 	   set the error state we set the pending error state and only move the
469 	   pending state into the current state once all data still present in
470 	   the buffer has been read */
471 	int readErrorState, writeErrorState;/* Current error state */
472 	int pendingReadErrorState, pendingWriteErrorState;
473 										/* Error state when buffer emptied */
474 
475 	/* Data buffer information.  In protocols that consist of single
476 	   messages sent back and forth only the receive buffer is used for
477 	   sending and receiving data, this buffer is somewhat more flexible
478 	   since it's associated with extra variables for handling the current
479 	   position in the buffer (bufPos) vs.the total amount of data present
480 	   (bufEnd) */
481 	BUFFER( sendBufSize, sendBufPos ) \
482 	BYTE *sendBuffer;
483 	BUFFER_OPT( receiveBufSize, receiveBufEnd ) \
484 	BYTE *receiveBuffer;				/* Data buffer */
485 	int sendBufSize, receiveBufSize;	/* Total buffer size */
486 	int sendBufPos, receiveBufPos;		/* Current position in buffer */
487 	int sendBufStartOfs, receiveBufStartOfs; /* Space for header in buffer */
488 	int receiveBufEnd;					/* Total data in buffer */
489 	int maxPacketSize;					/* Maximum packet (payload data) size */
490 
491 	/* When reading encrypted data packets we typically end up with a partial
492 	   packet in the read buffer that we can't process until the remainder
493 	   arrives, the following variables holds the eventual length of the
494 	   pending data packet and the amount of data remaining to be read */
495 	int pendingPacketLength;			/* Lending of pending data packet */
496 	int pendingPacketRemaining;			/* Bytes remaining to be read */
497 
498 	/* Unlike payload data, the packet header can't be read in sections but
499 	   must be read completely since all of the header information needs to
500 	   be processed at once.  The following value is usually zero, if it's
501 	   nonzero it records how much of the header remains to be read */
502 	int partialHeaderRemaining;			/* Header bytes still to read */
503 
504 	/* When sending data we can also end up with partially-processed packets
505 	   in the send buffer, but for sending we prevent further packets from
506 	   being added until the current one is flushed.  To handle this all we
507 	   need is a simple high-water-mark indicator that indicates the start
508 	   position of any yet-to-be-written data */
509 	BOOLEAN partialWrite;				/* Unwritten data remains in buffer */
510 	int sendBufPartialBufPos;			/* Progress point of partial write */
511 
512 	/* The session generally has various ephemeral contexts associated with
513 	   it, some short-term (e.g.public-key contexts used to establish the
514 	   session) and some long-term (e.g.encryption contexts used to perform
515 	   bulk data encryption).  These contexts are ephemeral ones that are
516 	   created as part of the session, long-term ones (e.g.signature keys
517 	   used for authentication) are held elsewhere */
518 	CRYPT_CONTEXT iKeyexCryptContext;	/* Key exchange encryption */
519 	CRYPT_CONTEXT iKeyexAuthContext;	/* Key exchange authentication */
520 	CRYPT_CONTEXT iCryptInContext, iCryptOutContext;
521 										/* In/outgoing data encryption */
522 	CRYPT_CONTEXT iAuthInContext, iAuthOutContext;
523 										/* In/outgoing auth/integrity */
524 	CRYPT_CERTIFICATE iCertRequest, iCertResponse;
525 										/* Certificate request/response */
526 	int cryptBlocksize, authBlocksize;	/* Block size of crypt, auth.algos */
527 
528 	/* The private key, which is required to authenticate the client or
529 	   server in some protocols */
530 	CRYPT_CONTEXT privateKey;			/* Authentication private key */
531 
532 	/* Certificate store for certificate management protocols like OCSP and
533 	   CMP and private-key keyset for PnP PKI protocols */
534 	CRYPT_KEYSET cryptKeyset;			/* Certificate store */
535 	CRYPT_HANDLE privKeyset;			/* Private-key keyset/device */
536 
537 	/* Session-related attributes, a current-position cursor in the
538 	   attribute list */
539 	ATTRIBUTE_LIST *attributeList, *attributeListCurrent;
540 
541 	/* Network connection information.  The reason why the client and server
542 	   information require separate storage is that (on the server) we may
543 	   be binding to a specific interface (requiring a server name) and we
544 	   need to record where the remote system's connection is coming from
545 	   (requiring a client name) */
546 	CRYPT_SESSION transportSession;		/* Transport mechanism */
547 	int networkSocket;					/* User-supplied network socket */
548 	int readTimeout, writeTimeout, connectTimeout;
549 										/* Connect and data xfer.timeouts */
550 	STREAM stream;						/* Network I/O stream */
551 
552 	/* Low-level error information */
553 	ERROR_INFO errorInfo;
554 
555 	/* Pointers to session access methods.  Stateful sessions use the read/
556 	   write functions, stateless ones use the transact function */
557 	FNPTR_DECLARE( SES_SHUTDOWN_FUNCTION, shutdownFunction );
558 	FNPTR_DECLARE( SES_CONNECT_FUNCTION, connectFunction );
559 	FNPTR_DECLARE( SES_GETATTRIBUTE_FUNCTION, getAttributeFunction );
560 	FNPTR_DECLARE( SES_SETATTRIBUTE_FUNCTION, setAttributeFunction );
561 	FNPTR_DECLARE( SES_CHECKATTRIBUTE_FUNCTION, checkAttributeFunction );
562 	FNPTR_DECLARE( SES_TRANSACT_FUNCTION, transactFunction );
563 	FNPTR_DECLARE( SES_READHEADER_FUNCTION, readHeaderFunction );
564 	FNPTR_DECLARE( SES_PROCESSBODY_FUNCTION, processBodyFunction );
565 	FNPTR_DECLARE( SES_PREPAREPACKET_FUNCTION, preparePacketFunction );
566 
567 	/* Error information */
568 	CRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */
569 	CRYPT_ERRTYPE_TYPE errorType;	/* Error type */
570 
571 	/* The object's handle and the handle of the user who owns this object.
572 	   The former is used when sending messages to the object when only the
573 	   xxx_INFO is available, the latter is used to avoid having to fetch the
574 	   same information from the system object table */
575 	CRYPT_HANDLE objectHandle;
576 	CRYPT_USER ownerHandle;
577 
578 	/* Variable-length storage for the type-specific data */
579 	DECLARE_VARSTRUCT_VARS;
580 	} SESSION_INFO;
581 
582 /****************************************************************************
583 *																			*
584 *								Session Functions							*
585 *																			*
586 ****************************************************************************/
587 
588 /* Macros to make handling of error reporting on shutdown a bit more
589    obvious */
590 
591 #define disableErrorReporting( sessionInfoPtr )	\
592 		( sessionInfoPtr )->flags |= SESSION_NOREPORTERROR
593 #define enableErrorReporting( sessionInfoPtr )	\
594 		( sessionInfoPtr )->flags &= ~SESSION_NOREPORTERROR
595 
596 /* The SESSION_ISSERVER flag is checked so often that we define a macro to
597    handle it */
598 
599 #define isServer( sessionInfoPtr ) \
600 		( sessionInfoPtr->flags & SESSION_ISSERVER )
601 
602 /* Session attribute handling functions */
603 
604 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
605 int getSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,
606 						 OUT_INT_Z int *valuePtr,
607 						 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
608 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
609 int getSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,
610 						  INOUT MESSAGE_DATA *msgData,
611 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
612 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
613 int setSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,
614 						 IN const int value,
615 						 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
616 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
617 int setSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,
618 						  IN_BUFFER( dataLength ) const void *data,
619 						  IN_LENGTH const int dataLength,
620 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
621 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
622 int deleteSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,
623 							IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
624 
625 /* Session-specific attribute management functions */
626 
627 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
628 int addSessionInfo( INOUT_PTR ATTRIBUTE_LIST **listHeadPtr,
629 					IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,
630 					IN_INT_Z const int value );
631 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
632 int addSessionInfoS( INOUT_PTR ATTRIBUTE_LIST **listHeadPtr,
633 					IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,
634 					IN_BUFFER( dataLength ) const void *data,
635 					IN_LENGTH_SHORT const int dataLength );
636 
637 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
638 int addSessionInfoEx( INOUT_PTR ATTRIBUTE_LIST **listHeadPtr,
639 					  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,
640 					  IN_BUFFER( dataLength ) const void *data,
641 					  IN_LENGTH_SHORT const int dataLength,
642 					  IN_FLAGS_Z( ATTR ) const int flags );
643 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
644 int addSessionInfoComposite( INOUT_PTR ATTRIBUTE_LIST **listHeadPtr,
645 							 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,
646 							 const ATTRACCESS_FUNCTION accessFunction,
647 							 IN_BUFFER( dataLength ) const void *data,
648 							 IN_LENGTH_SHORT const int dataLength,
649 							 IN_FLAGS( ATTR ) const int flags );
650 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
651 int updateSessionInfo( INOUT_PTR ATTRIBUTE_LIST **listHeadPtr,
652 					   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,
653 					   IN_BUFFER( dataLength ) const void *data,
654 					   IN_LENGTH_SHORT const int dataLength,
655 					   IN_LENGTH_SHORT const int dataMaxLength,
656 					   IN_FLAGS_Z( ATTR ) const int flags );
657 CHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \
658 int getSessionAttributeCursor( IN_OPT ATTRIBUTE_LIST *attributeListHead,
659 							   IN_OPT ATTRIBUTE_LIST *attributeListCursor,
660 							   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,
661 							   OUT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *valuePtr );
662 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
663 int setSessionAttributeCursor( IN_OPT const ATTRIBUTE_LIST *attributeListHead,
664 							   INOUT_PTR ATTRIBUTE_LIST **attributeListCursorPtr,
665 							   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,
666 							   IN_RANGE( CRYPT_CURSOR_LAST, \
667 										 CRYPT_CURSOR_FIRST ) /* Values are -ve */
668 									const int position );
669 CHECK_RETVAL_PTR \
670 const ATTRIBUTE_LIST *findSessionInfo( IN_OPT const ATTRIBUTE_LIST *attributeListPtr,
671 									   IN_ATTRIBUTE \
672 											const CRYPT_ATTRIBUTE_TYPE attributeID );
673 CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 3 ) ) \
674 const ATTRIBUTE_LIST *findSessionInfoEx( IN_OPT const ATTRIBUTE_LIST *attributeListPtr,
675 										 IN_ATTRIBUTE \
676 											const CRYPT_ATTRIBUTE_TYPE attributeID,
677 										 IN_BUFFER( valueLength ) const void *value,
678 										 IN_LENGTH_SHORT const int valueLength );
679 STDC_NONNULL_ARG( ( 1 ) ) \
680 void lockEphemeralAttributes( INOUT ATTRIBUTE_LIST *attributeListHead );
681 STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
682 int deleteSessionInfo( INOUT ATTRIBUTE_LIST **attributeListHead,
683 					   INOUT ATTRIBUTE_LIST **attributeListCurrent,
684 					   INOUT ATTRIBUTE_LIST *attributeListPtr );
685 STDC_NONNULL_ARG( ( 1, 2 ) ) \
686 void deleteSessionInfoAll( INOUT ATTRIBUTE_LIST **attributeListHead,
687 						   INOUT ATTRIBUTE_LIST **attributeListCurrent );
688 CHECK_RETVAL_ENUM( CRYPT_ATTRIBUTE ) \
689 CRYPT_ATTRIBUTE_TYPE checkMissingInfo( IN_OPT const ATTRIBUTE_LIST *attributeListHead,
690 									   const BOOLEAN isServer );
691 
692 /* Prototypes for functions in sess_rw.c */
693 
694 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
695 int readFixedHeaderAtomic( INOUT SESSION_INFO *sessionInfoPtr,
696 						   OUT_BUFFER_FIXED( headerLength ) void *headerBuffer,
697 						   IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \
698 								const int headerLength );
699 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
700 int readFixedHeader( INOUT SESSION_INFO *sessionInfoPtr,
701 					 OUT_BUFFER_FIXED( headerLength ) void *headerBuffer,
702 					 IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \
703 							const int headerLength );
704 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
705 int getSessionData( INOUT SESSION_INFO *sessionInfoPtr,
706 					OUT_BUFFER( dataMaxLength, *bytesCopied ) void *data,
707 					IN_DATALENGTH const int dataMaxLength,
708 					OUT_DATALENGTH_Z int *bytesCopied );
709 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
710 int putSessionData( INOUT SESSION_INFO *sessionInfoPtr,
711 					IN_BUFFER_OPT( dataLength ) const void *data,
712 					IN_DATALENGTH_Z const int dataLength,
713 					OUT_DATALENGTH_Z int *bytesCopied );
714 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
715 int readPkiDatagram( INOUT SESSION_INFO *sessionInfoPtr );
716 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
717 int writePkiDatagram( INOUT SESSION_INFO *sessionInfoPtr,
718 					  IN_BUFFER( contentTypeLen ) const char *contentType,
719 					  IN_LENGTH_TEXT const int contentTypeLen );
720 
721 /* Prototypes for functions in session.c */
722 
723 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
724 int initSessionIO( INOUT SESSION_INFO *sessionInfoPtr );
725 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
726 int initSessionNetConnectInfo( const SESSION_INFO *sessionInfoPtr,
727 							   OUT NET_CONNECT_INFO *connectInfo );
728 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
729 BOOLEAN checkAttributesConsistent( INOUT SESSION_INFO *sessionInfoPtr,
730 								   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );
731 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
732 int checkServerCertValid( const CRYPT_CERTIFICATE iServerKey,
733 						  INOUT ERROR_INFO *errorInfo );
734 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
735 int activateSession( INOUT SESSION_INFO *sessionInfoPtr );
736 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
737 int sendCloseNotification( INOUT SESSION_INFO *sessionInfoPtr,
738 						   IN_BUFFER_OPT( length ) const void *data,
739 						   IN_LENGTH_SHORT_Z const int length );
740 
741 /* Prototypes for session mapping functions */
742 
743 #ifdef USE_CERTSTORE
744   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
745   int setAccessMethodCertstore( INOUT SESSION_INFO *sessionInfoPtr );
746 #else
747   #define setAccessMethodCertstore( x )	CRYPT_ARGERROR_NUM1
748 #endif /* USE_CERTSTORE */
749 #ifdef USE_CMP
750   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
751   int setAccessMethodCMP( INOUT SESSION_INFO *sessionInfoPtr );
752 #else
753   #define setAccessMethodCMP( x )	CRYPT_ARGERROR_NUM1
754 #endif /* USE_CMP */
755 #ifdef USE_RTCS
756   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
757   int setAccessMethodRTCS( INOUT SESSION_INFO *sessionInfoPtr );
758 #else
759   #define setAccessMethodRTCS( x )	CRYPT_ARGERROR_NUM1
760 #endif /* USE_RTCS */
761 #ifdef USE_OCSP
762   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
763   int setAccessMethodOCSP( INOUT SESSION_INFO *sessionInfoPtr );
764 #else
765   #define setAccessMethodOCSP( x )	CRYPT_ARGERROR_NUM1
766 #endif /* USE_OCSP */
767 #ifdef USE_SCEP
768   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
769   int setAccessMethodSCEP( INOUT SESSION_INFO *sessionInfoPtr );
770 #else
771   #define setAccessMethodSCEP( x )	CRYPT_ARGERROR_NUM1
772 #endif /* USE_SCEP */
773 #if defined( USE_SSH ) || defined( USE_SSH1 )
774   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
775   int setAccessMethodSSH( INOUT SESSION_INFO *sessionInfoPtr );
776 #else
777   #define setAccessMethodSSH( x )	CRYPT_ARGERROR_NUM1
778 #endif /* USE_SSH || USE_SSH1 */
779 #ifdef USE_SSL
780   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
781   int setAccessMethodSSL( INOUT SESSION_INFO *sessionInfoPtr );
782 #else
783   #define setAccessMethodSSL( x )	CRYPT_ARGERROR_NUM1
784 #endif /* USE_SSL */
785 #ifdef USE_TSP
786   CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
787   int setAccessMethodTSP( INOUT SESSION_INFO *sessionInfoPtr );
788 #else
789   #define setAccessMethodTSP( x )	CRYPT_ARGERROR_NUM1
790 #endif /* USE_TCP */
791 #endif /* _SES_DEFINED */
792