/****************************************************************************
*																			*
*							TLS Definitions Header File						*
*						Copyright Peter Gutmann 1998-2025					*
*																			*
****************************************************************************/

#ifndef _TLS_DEFINED

#define _TLS_DEFINED

#if defined( INC_ALL )
  #include "scorebrd.h"
#else
  #include "session/scorebrd.h"
#endif /* _STREAM_DEFINED */

#ifdef USE_TLS

/****************************************************************************
*																			*
*								TLS Constants								*
*																			*
****************************************************************************/

/* Default TLS port */

#define TLS_PORT					443

/* TLS algorithm-specific constants */

#define MD5MAC_SIZE					16	/* Size of MD5 proto-HMAC/dual hash */
#define SHA1MAC_SIZE				20	/* Size of SHA-1 proto-HMAC/dual hash */
#define SHA2MAC_SIZE				32	/* Size of SHA-2 HMAC hash */
#define GCMICV_SIZE					16	/* Size of GCM (and Poly1305) ICV */
#define GCM_SALT_SIZE				4	/* Size of implicit portion of 
										   TLS 1.2 GCM IV */
#define GCM_IV_SIZE					12	/* Overall size of GCM IV */
#define BERNSTEIN_IV_SIZE			12	/* Overall size of Bernstein suite IV */
#define X25519_PUBKEY_SIZE			32	/* Size of 25519 public key */
#define MLKEM_PUBKEY_SIZE			1184/* From crypt/mlkem_native.h */
#define MLKEM_WRAPPEDKEY_SIZE		1088/* From crypt/mlkem_native.h */

/* TLS constants */

#define ID_SIZE						1	/* ID byte */
#define LENGTH_SIZE					3	/* 24 bits */
#define SEQNO_SIZE					8	/* 64 bits */
#define VERSIONINFO_SIZE			2	/* 0x03, 0x0n */
#define ALERTINFO_SIZE				2	/* level + description */
#define TLS_HEADER_SIZE				5	/* Type, version, length */
#define TLS_NONCE_SIZE				32	/* Size of client/svr nonce */
#define TLS_SECRET_SIZE				48	/* Size of premaster/master secret */
#define TLS_HASHEDMAC_SIZE			12	/* Size of TLS PRF( MD5 + SHA1 ) */
#define SESSIONID_SIZE				16	/* Size of session ID */
#define MIN_SESSIONID_SIZE			4	/* Min.allowed session ID size */
#define MAX_SESSIONID_SIZE			32	/* Max.allowed session ID size */
#define MAX_KEYBLOCK_SIZE			( ( 64 + 32 + 16 ) * 2 )
										/* HMAC-SHA2 + AES-256 key + AES IV */
#ifdef USE_TLS13
  /* TLS 1.3's camouflage double-wrapping means that the minimum packet size 
     can be 3 bytes for an Alert packet, the two-byte payload followed by 
	 the single-byte type, see session/tls_rd.c:recoverPacketDataTLS13() for 
	 how this piece of cleverness works */
  #define MIN_PACKET_SIZE			3	/* Minimum TLS packet size */
#else
  #define MIN_PACKET_SIZE			4	/* Minimum TLS packet size */
#endif /* USE_TLS13 */
  /* TLS 1.3 has the same problem with maximum packet sizes, the maximum 
	 size is still 16384 bytes but now there's an invisible real-packet-type
	 byte appended to the data that's not actually there but is still 
	 present, so with TLS 1.3 MAX_PACKET_SIZE is actually 16385 even if only
	 16384 bytes of data are allowed.  To deal with this the code 
	 dynamically adds an extra byte to the allowed length if TLS 1.3 is in
	 effect */
#define MAX_PACKET_SIZE				16384	/* Maximum TLS packet size */
#define MAX_CIPHERSUITES			200	/* Max.allowed cipher suites */
#define TLS_DH_KEYSIZE				192	/* Size of server DH key */
#if defined( USE_TLS13 ) && defined( USE_MLKEM )
  #define KEYEX_SECRET_STORAGE_SIZE \
		  ( 8 + max( MLKEM_PUBKEY_SIZE, MLKEM_WRAPPEDKEY_SIZE ) + \
		    X25519_PUBKEY_SIZE )		/* Header + MLKEM-768 + 25519 size */
#else
  #define KEYEX_SECRET_STORAGE_SIZE	\
		  ( CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE )
#endif /* USE_TLS13 */

/* TLS packet/buffer size information.  The extra packet size is somewhat 
   large because it can contains the packet header (5 bytes), IV 
   (0/8/16 bytes), MAC/ICV (12/16/20 bytes), and cipher block padding (up to 
   256 bytes) */

#define EXTRA_PACKET_SIZE			512	

/* By default cryptlib uses DH key agreement, it's also possible to use ECDH 
   key agreement but for TLS classic we disable ECDH by default in order to 
   stick to the safer (less attack surface) DH while for TLS 1.3 where it's
   required we enable it in the code.  To use ECDH key agreement in 
   preference to DH for TLS classic, uncomment the following */

/* #define PREFER_ECC */
#if defined( PREFER_ECC ) && \
	!( defined( USE_ECDH ) && defined( USE_ECDSA ) )
  #error PREFER_ECC can only be used with ECDH and ECDSA enabled
#endif /* PREFER_ECC && !( USE_ECDH && USE_ECDSA ) */

/* For TLS 1.3 we've also got 25519 and ML-KEM.  Define the following to 
   prefer the 25519 algorithms over the standard ones and the 25519/ML-KEM 
   hybrid over 25519 and the others */

#if defined( PREFER_X25519 ) && !defined( USE_X25519 )
  #error PREFER_X25519 can only be used with X25519 enabled
#endif /* PREFER_X25519 && !USE_X25519 */
#if defined( PREFER_MLKEM ) && !defined( USE_MLKEM )
  #error PREFER_MLKEM can only be used with ML-KEM enabled
#endif /* PREFER_MLKEM && !USE_MLKEM */
#if defined( USE_MLKEM ) && !defined( USE_X25519 )
  #error Use of ML-KEM requires that X25519 also be enabled
#endif /* USE_MLKEM && !USE_X25519 */

/* TLS protocol-specific flags that augment the general session flags:

	FLAG_ALERTSENT: Whether we've already sent a close-alert.  Keeping track 
		of this is necessary because we're required to send a close alert 
		when shutting down to prevent a truncation attack, however lower-
		level code may have already sent an alert so we have to remember not 
		to send it twice.

	FLAG_BERNSTEIN: Uses the Bernstein protocol suite instead of the usual 
		CBC.  This is an AEAD exactly like GCM, but the IETF managed to make 
		it incompatible with the standard AEAD use so it needs custom 
		handling.

	FLAG_DISABLE_CERTVERIFY: Disable checking of the server certificate 
	FLAG_DISABLE_NAMEVERIFY: and/or host name.  By default we check both of
		these, but because of all of the problems surrounding certificates 
		we allow the checking to be disabled.

	FLAG_CHECKREHANDSHAKE: The header-read got a handshake packet instead of 
		a data packet, when the body-read decrypts the payload it should 
		check for a rehandshake request in the payload.

	FLAG_CLIAUTHSKIPPED: The client saw an auth-request from the server and 
		responded with a no-certificates alert, if we later get a close 
		alert from the server then we provide additional error information 
		indicating that this may be due to the lack of a client certificate.

	FLAG_EMS: Use extended Master Secret to protect handshake messages.

	FLAG_ENCTHENMAC: Use encrypt-then-MAC rather than the standard 
		MAC-then-encrypt.

	FLAG_GCM: The encryption used is GCM and not the usual CBC, which 
		unifies encryption and MACing into a single operation.
	
	FLAG_MANUAL_CERTCHECK: Interrupt the handshake (returning 
		CRYPT_ERROR_RESOURCE) to allow the caller to check the peer's 
		certificate.

	FLAG_RESUMED: TLS session is resumed.

	FLAG_SUITEB_128: Enforce Suite B semantics on top of the standard TLS 
	FLAG_SUITEB_256: 1.2 + ECC + AES-GCM ones.  _128 = P256 + P384, 
		_256 = P384 only.

	FLAG_TLS12LTS: TLS 1.2 LTS session with enhanced crypto protection */

#define TLS_PFLAG_NONE				0x0000	/* No protocol-specific flags */
#define TLS_PFLAG_ALERTSENT			0x0001	/* Close alert sent */
#define TLS_PFLAG_CLIAUTHSKIPPED	0x0002	/* Client auth-req.skipped */
#define TLS_PFLAG_GCM				0x0004	/* Encryption uses GCM, not CBC */
#define TLS_PFLAG_BERNSTEIN			0x0008	/* Encryption uses Bernstein suite */
#define TLS_PFLAG_SUITEB_128		0x0010	/* Enforce Suite B 128-bit semantics */
#define TLS_PFLAG_SUITEB_256		0x0020	/* Enforce Suite B 256-bit semantics */
#define TLS_PFLAG_CHECKREHANDSHAKE	0x0040	/* Check decrypted pkt.for rehandshake */
#define TLS_PFLAG_MANUAL_CERTCHECK	0x0080	/* Interrupt handshake for cert.check */
#define TLS_PFLAG_DISABLE_NAMEVERIFY 0x0100	/* Disable host name verification */
#define TLS_PFLAG_DISABLE_CERTVERIFY 0x0200	/* Disable certificate verification */
#define TLS_PFLAG_ENCTHENMAC		0x0400	/* Use encrypt-then-MAC */
#define TLS_PFLAG_EMS				0x0800	/* Use extended Master Secret */
#define TLS_PFLAG_TLS12LTS			0x1000	/* Use TLS 1.2 LTS profile */
#define TLS_PFLAG_SERVER_SNI		0x2000	/* Apply server key switching for SNI */
#define TLS_PFLAG_RESUMED_SESSION	0x4000	/* Session is resumed */
#define TLS_PFLAG_MAX				0x7FFF	/* Maximum possible flag value */

/* Some of the flags above denote extended TLS facilities that need to be
   preserved across session resumptions.  The following value defines the 
   flags that need to be preserved across resumes */

#define TLS_RESUMEDSESSION_FLAGS	( TLS_PFLAG_EMS | TLS_PFLAG_ENCTHENMAC | \
									  TLS_PFLAG_TLS12LTS )

/* Symbolic defines for static analysis checking */

#define TLS_FLAG_NONE				TLS_PFLAG_NONE
#define TLS_FLAG_MAX				TLS_PFLAG_MAX

/* Suite B consists of two subclasses, the 128-bit security level (AES-128 
   with P256 and SHA2-256) and the 192-bit security level (AES-256 with P384 
   and SHA2-384), in order to identify generic use of Suite B we provide a
   pseudo-value that combines the 128-bit and 192-bit subclasses */

#define TLS_PFLAG_SUITEB			( TLS_PFLAG_SUITEB_128 | \
									  TLS_PFLAG_SUITEB_256 )

/* The TLS minimmum version number is encoded as a CRYPT_TLSOPTION_MINVER_xxx
   value, the following mask allows the version to be extracted from the TLS
   option value */

#define TLS_MINVER_MASK				( CRYPT_TLSOPTION_MINVER_SSLV3 | \
									  CRYPT_TLSOPTION_MINVER_TLS10 | \
									  CRYPT_TLSOPTION_MINVER_TLS11 | \
									  CRYPT_TLSOPTION_MINVER_TLS12 | \
									  CRYPT_TLSOPTION_MINVER_TLS13 )
/* TLS message types */

#define TLS_MSG_NONE				0
#define TLS_MSG_CHANGE_CIPHER_SPEC	20
#define TLS_MSG_ALERT				21
#define TLS_MSG_HANDSHAKE			22
#define TLS_MSG_APPLICATION_DATA	23

#define TLS_MSG_FIRST				TLS_MSG_CHANGE_CIPHER_SPEC
#define TLS_MSG_LAST				TLS_MSG_APPLICATION_DATA

/* Special expected packet-type values that are passed to readHSPacketTLS() 
   to handle situations where special-case handling is required for read
   packets:

	TLS_MSG_FIRST_HANDSHAKE: The first handshake packet from the client or 
		server is treated specially in that the version number information 
		is taken from this packet.
		
	TLS_MSG_FIRST_ENCRHANDSHAKE: The attempt to read the first encrypted 
		handshake packet may be met with a TCP close from the peer if it 
		handles errors badly, in which case we provide a special-case error 
		message that indicates more than just "connection closed" 
		
	TLS_MSG_TLS13_FIRST_ENCRHANDSHAKE: TLS 1.3 stuffs encrypted handshake
		messages inside application-data packets so alongside the
		TLS_MSG_FIRST_ENCRHANDSHAKE semantics this also looks for
		application-data rather than handshake packets.
		
	TLS_MSG_TLS13_HELLORETRY: Some TLS 1.3 implementations send a bogus
		Change Cipherspec between the two Client Hellos (see the comment in
		session/tls13_hs.c:processHelloRetry()) so alongside the expected 
		TLS_MSG_HANDSHAKE this also allows an unexpected  
		TLS_MSG_CHANGE_CIPHER_SPEC */

#define TLS_MSG_FIRST_HANDSHAKE		0xFC
#define TLS_MSG_FIRST_ENCRHANDSHAKE	0xFD
#define TLS_MSG_TLS13_FIRST_ENCRHANDSHAKE	0xFE
#define TLS_MSG_TLS13_HELLORETRY	0xFF
#define TLS_MSG_LAST_SPECIAL		TLS_MSG_TLS13_HELLORETRY

/* TLS handshake message subtypes */

#define TLS_HAND_NONE				0
#define TLS_HAND_CLIENT_HELLO		1
#define TLS_HAND_SERVER_HELLO		2
#define TLS_HAND_NEW_SESSION_TICKET	4
#define TLS_HAND_END_OF_EARLY_DATA	5
#define TLS_HAND_ENCRYPTED_EXTENSIONS 8
#define TLS_HAND_CERTIFICATE		11
#define TLS_HAND_SERVER_KEYEXCHANGE	12
#define TLS_HAND_SERVER_CERTREQUEST	13
#define TLS_HAND_SERVER_HELLODONE	14
#define TLS_HAND_CERTVERIFY			15
#define TLS_HAND_CLIENT_KEYEXCHANGE	16
#define TLS_HAND_FINISHED			20
#define TLS_HAND_SUPPLEMENTAL_DATA	23
#define TLS_HAND_KEY_UPDATE			24

#define TLS_HAND_FIRST				TLS_HAND_CLIENT_HELLO
#define TLS_HAND_LAST				TLS_HAND_KEY_UPDATE

/* When wrapping and unwrapping messages, we can be working with either 
   TLS_MSG types or TLS_HAND types, and the functions that deal with them 
   have to accept either.  To deal with this we define two additional values
   that can be used for range-checking.  Note that we can't use
   max( TLS_MSG_LAST, TLS_HAND_LAST ) in the following because the SAST
   annotations they're used with don't allow expressions */

#define TLS_PACKETTYPE_FIRST		1
#define TLS_PACKETTYPE_LAST			TLS_HAND_LAST

/* TLS alert levels and types, from
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6 */

#define TLS_ALERTLEVEL_WARNING				1
#define TLS_ALERTLEVEL_FATAL				2

#define TLS_ALERT_CLOSE_NOTIFY				0
#define TLS_ALERT_UNEXPECTED_MESSAGE		10
#define TLS_ALERT_BAD_RECORD_MAC			20
#define TLS_ALERT_DECRYPTION_FAILED			21
#define TLS_ALERT_RECORD_OVERFLOW			22
#define TLS_ALERT_DECOMPRESSION_FAILURE		30
#define TLS_ALERT_HANDSHAKE_FAILURE			40
#define TLS_ALERT_NO_CERTIFICATE			41
#define TLS_ALERT_BAD_CERTIFICATE			42
#define TLS_ALERT_UNSUPPORTED_CERTIFICATE	43
#define TLS_ALERT_CERTIFICATE_REVOKED		44
#define TLS_ALERT_CERTIFICATE_EXPIRED		45
#define TLS_ALERT_CERTIFICATE_UNKNOWN		46
#define TLS_ALERT_ILLEGAL_PARAMETER			47
#define TLS_ALERT_UNKNOWN_CA				48
#define TLS_ALERT_ACCESS_DENIED				49
#define TLS_ALERT_DECODE_ERROR				50
#define TLS_ALERT_DECRYPT_ERROR				51
#define TLS_ALERT_TOO_MANY_CIDS				52
#define TLS_ALERT_EXPORT_RESTRICTION		60
#define TLS_ALERT_PROTOCOL_VERSION			70
#define TLS_ALERT_INSUFFICIENT_SECURITY		71
#define TLS_ALERT_INTERNAL_ERROR			80
#define TLS_ALERT_INAPPROPRIATE_FALLBACK	86
#define TLS_ALERT_USER_CANCELLED			90
#define TLS_ALERT_NO_RENEGOTIATION			100
#define TLS_ALERT_MISSING_EXTENSION			109
#define TLS_ALERT_UNSUPPORTED_EXTENSION		110
#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE	111
#define TLS_ALERT_UNRECOGNIZED_NAME			112
#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113
#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114
#define TLS_ALERT_UNKNOWN_PSK_IDENTITY		115
#define TLS_ALERT_CERTIFICATE_REQUIRED		116
#define TLS_ALERT_GENERAL_ERROR				117
#define TLS_ALERT_NO_APPLICATION_PROTOCOL	120
#define TLS_ALERT_ECH_REQUIRED				121

#define TLS_ALERT_FIRST						TLS_ALERT_CLOSE_NOTIFY
#define TLS_ALERT_LAST						TLS_ALERT_ECH_REQUIRED

/* TLS supplemental data subtypes */

#define TLS_SUPPDATA_USERMAPPING			0

/* TLS cipher suites, from
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 */

typedef enum {
	/* SSLv3 cipher suites (0-10) */
	SSL_NULL_WITH_NULL, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA,
	SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_WITH_RC4_128_MD5, 
	SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
	SSL_RSA_WITH_IDEA_CBC_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
	SSL_RSA_WITH_DES_CBC_SHA,
		/* First valid suite if RSA + 3DES enabled */
	SSL_RSA_WITH_3DES_EDE_CBC_SHA,

	/* TLS (RFC 2246) DH cipher suites (11-22) */
	TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_DSS_WITH_DES_CBC_SHA,
	TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
	TLS_DH_RSA_WITH_DES_CBC_SHA, TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
	TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_DSS_WITH_DES_CBC_SHA,
	TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
	TLS_DHE_RSA_WITH_DES_CBC_SHA,
		/* First valid suite if RSA disabled, 3DES enabled */
	TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,

	/* TLS (RFC 2246) anon-DH cipher suites (23-27) */
	TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, TLS_DH_anon_WITH_RC4_128_MD5,
	TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_anon_WITH_DES_CBC_SHA,
	TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,

	/* TLS (RFC 2246) reserved cipher suites (28-29, used for Fortezza in
	   SSLv3) */
	TLS_reserved_1, TLS_reserved_2,

	/* TLS with Kerberos (RFC 2712) suites (30-43) */
	TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
	TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_IDEA_CBC_SHA,
	TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
	TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_IDEA_CBC_MD5,
	TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
	TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
	TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_MD5,

	/* Formerly reserved (44-46), later assigned to PSK-with-NULL suites 
	   (RFC 4785) */
	TLS_PSK_WITH_NULL_SHA, TLS_DHE_PSK_WITH_NULL_SHA, 
	TLS_RSA_PSK_WITH_NULL_SHA,

	/* TLS 1.1 (RFC 4346) cipher suites (47-58) */
	TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DH_DSS_WITH_AES_128_CBC_SHA,
	TLS_DH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
		/* First valid suite if RSA + 3DES disabled */
	TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA,
	TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DH_DSS_WITH_AES_256_CBC_SHA,
	TLS_DH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
	TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA,

	/* TLS 1.2 (RFC 5246) cipher suites (59-61) */
	TLS_RSA_WITH_NULL_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256,
	TLS_RSA_WITH_AES_256_CBC_SHA256,

	/* TLS 1.2 (RFC 5246) DH cipher suites (62-64), continued at 103 */
	TLS_DH_DSS_WITH_AES_128_CBC_SHA256, TLS_DH_RSA_WITH_AES_128_CBC_SHA256, 
	TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, 

	/* Camellia (RFC 4132) AES-128 suites (65-70) */
	TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, 
	TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, 
	TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,

	/* Unknown/reserved suites (71-103) */

	/* More TLS 1.2 (RFC 5246) DH cipher suites (103-109) */
	TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 103, TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
	TLS_DH_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
	TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DH_anon_WITH_AES_128_CBC_SHA256,
	TLS_DH_anon_WITH_AES_256_CBC_SHA256,

	/* Unknown suites (110-131) */

	/* Camellia (RFC 4132) AES-256 suites (132-137) */
	TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 132,
	TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
	TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
	TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,

	/* TLS-PSK (RFC 4279) cipher suites (138-149) */
	TLS_PSK_WITH_RC4_128_SHA, TLS_PSK_WITH_3DES_EDE_CBC_SHA, 
	TLS_PSK_WITH_AES_128_CBC_SHA, TLS_PSK_WITH_AES_256_CBC_SHA, 
	TLS_DHE_PSK_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
	TLS_DHE_PSK_WITH_AES_128_CBC_SHA, TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
	TLS_RSA_PSK_WITH_RC4_128_SHA, TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
	TLS_RSA_PSK_WITH_AES_128_CBC_SHA, TLS_RSA_PSK_WITH_AES_256_CBC_SHA,

	/* SEED (RFC 4162) suites (150-155) */
	TLS_RSA_WITH_SEED_CBC_SHA, TLS_DH_DSS_WITH_SEED_CBC_SHA,
	TLS_DH_RSA_WITH_SEED_CBC_SHA, TLS_DHE_DSS_WITH_SEED_CBC_SHA,
	TLS_DHE_RSA_WITH_SEED_CBC_SHA, TLS_DH_anon_WITH_SEED_CBC_SHA,

	/* TLS 1.2 (RFC 5288) GCM cipher suites (156-167) */
	TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384,
    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
    TLS_DH_RSA_WITH_AES_128_GCM_SHA256, TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
    TLS_DH_DSS_WITH_AES_128_GCM_SHA256, TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
    TLS_DH_anon_WITH_AES_128_GCM_SHA256, TLS_DH_anon_WITH_AES_256_GCM_SHA384,

	/* TLS 1.2 (RFC 5487) PSK cipher suites (168-185) */
	TLS_PSK_WITH_AES_128_GCM_SHA256, TLS_PSK_WITH_AES_256_GCM_SHA384,
	TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
	TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
	TLS_PSK_WITH_AES_128_CBC_SHA256, TLS_PSK_WITH_AES_256_CBC_SHA384,
	TLS_PSK_WITH_NULL_SHA256, TLS_PSK_WITH_NULL_SHA384,
	TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
	TLS_DHE_PSK_WITH_NULL_SHA256, TLS_DHE_PSK_WITH_NULL_SHA384,
	TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
	TLS_RSA_PSK_WITH_NULL_SHA256, TLS_RSA_PSK_WITH_NULL_SHA384,

	/* TLS 1.2 (RFC 5932) Camellia cipher suites (186-197) */
	TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
	TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
	TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
	TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
	TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
	TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,

	/* TLS secure-rengotiation signalling cipher suite, RFC 5746 */
	TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 255,

	/* TLS fallback signalling cpiher suite, RFC 7507, stuffed into a gap in 
	   the range starting at 22016/0x5600 */
	TLS_FALLBACK_SCSV = 22016,

	/* TLS 1.3 symmetric-only suites, RFC 8446 (0x1301-0x1305, 4865-4869) */
	TLS_AES_128_GCM_SHA256 = 4865, TLS_AES_256_GCM_SHA384, 
	TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_128_CCM_8_SHA256,

	/* TLS-ECC (RFC 4492) cipher suites.  For some unknown reason these 
	   start above 49152/0xC000, so the range is 49153...49177 */
	TLS_ECDH_ECDSA_WITH_NULL_SHA = 49153, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
	TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
	TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA,
	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
	TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA,
	TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
	TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA,
	TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
	TLS_ECDH_anon_WITH_NULL_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA,
	TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
	TLS_ECDH_anon_WITH_AES_256_CBC_SHA,

	/* TLS-SRP (RFC 5054) cipher suites, following the pattern from 
	   above at 49178/0xC01A...49186 */
	TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
	TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
	TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
	TLS_SRP_SHA_WITH_AES_256_CBC_SHA, TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
	TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,

	/* TLS-ECC (RFC 5289) SHA-2 cipher suites, following the pattern from 
	   above at 49187/0xC023...49194 */
	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
	TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
	TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,

	/* TLS-ECC (RFC 5289) GCM cipher suites, following the pattern from above
	   at 49195/0xC02B...49202 */
	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
	TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
	TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,

	/* TLS-ECC (RFC 5489) PSK cipher suites, following the pattern from above
	   at 49203/0xC033...49211 */
	TLS_ECDHE_PSK_WITH_RC4_128_SHA, TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
	TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
    TLS_ECDHE_PSK_WITH_NULL_SHA, TLS_ECDHE_PSK_WITH_NULL_SHA256,
    TLS_ECDHE_PSK_WITH_NULL_SHA384,

	/* Endless vanity suites, Aria, Camellia, etc */

	/* TLS Bernstein protocol suite (RFC 7905), following the pattern from 
	   above at 52392/0xCCA8...52398/0xCCAE */
	TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392,
	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 
	TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
	TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 
	TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
	TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,

	TLS_LAST_SUITE
	} TLS_CIPHERSUITE_TYPE;

/* The first cipher suite that we'll even consider.  If RSA + 3DES is enabled
   (RSA is disabled by default since it's unsafe) it's the one and only SSLv3 
   3DES suite, if only 3DES is enabled it's the last TLS 1.0 suite, and if 
   neither are enabled it's a TLS 1.1 AES suite */

#if defined( USE_RSA_SUITES )
  #define TLS_FIRST_VALID_SUITE		SSL_RSA_WITH_3DES_EDE_CBC_SHA
#elif defined( USE_3DES )
  #define TLS_FIRST_VALID_SUITE		TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
#else
  #define TLS_FIRST_VALID_SUITE		TLS_DHE_RSA_WITH_AES_128_CBC_SHA
#endif /* Configuration-specific first suite define */

/* TLS extension types, from 
   http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */

typedef enum {
	TLS_EXT_SNI,				/* 0: Name of virtual server to contact (SNI) */
	TLS_EXT_MAX_FRAGMENT_LENGTH,/* 1: Max.fragment length if smaller than 2^14 bytes */
	TLS_EXT_CLIENT_CERTIFICATE_URL,	/* 2: Location for server to find client certificate */
	TLS_EXT_TRUSTED_CA_KEYS,	/* 3: Indication of which CAs clients trust */
	TLS_EXT_TRUNCATED_HMAC,		/* 4: Use 80-bit truncated HMAC */
	TLS_EXT_STATUS_REQUEST,		/* 5: OCSP status request from server */
	TLS_EXT_USER_MAPPING,		/* 6: RFC 4681 mapping of user name to account */
	TLS_EXT_CLIENT_AUTHZ,		/* 7: RFC 5878 authorisation exts */
	TLS_EXT_SERVER_AUTHZ,		/* 8: RFC 5878 authorisation exts */
	TLS_EXT_CERTTYPE,			/* 9: RFC 5081/6091 OpenPGP key support */
	TLS_EXT_SUPPORTED_GROUPS,	/* 10: RFC 8446 Supported Groups, formerly
									   RFC 4492 ECC elliptic curve types */
	TLS_EXT_EC_POINT_FORMATS,	/* 11: RFC 4492 ECDH/ECDSA support */
	TLS_EXT_SRP,				/* 12: RFC 5054 SRP support */
	TLS_EXT_SIGNATURE_ALGORITHMS,/* 13: RFC 5246 TLSv1.2 */
	TLS_EXT_USE_SRP,			/* 14: RFC 5764 DTLS for SRTP keying */
	TLS_EXT_HEARTBEAT,			/* 15: RFC 6520 DTLS heartbeat */
	TLS_EXT_ALPN,				/* 16: RFC 7301 Application layer protocol negotiation */
	TLS_EXT_STATUS_REQUEST_V2,	/* 17: RFC 6961 OCSP status request from server */
	TLS_EXT_CERT_TRANSPARENCY,	/* 18: RFC 6962 Certificate transparency timestamp */
	TLS_EXT_RAWKEY_CLIENT,		/* 19: RFC 7250 Raw client public key */
	TLS_EXT_RAWKEY_SERVER,		/* 20: RFC 7250 Raw server public key */
	TLS_EXT_PADDING,			/* 21: RFC 7685 Padding */
	TLS_EXT_ENCTHENMAC,			/* 22: RFC 7366 Encrypt-then-MAC */
	TLS_EXT_EMS,				/* 23: RFC 7627 Extended master secret */
	TLS_EXT_TOKENBIND,			/* 24: Draft, Token binding */
	TLS_EXT_CACHED_INFO,		/* 25: RFC 7924 Cached info */
	TLS_EXT_TLS12LTS,			/* 26: Draft, TLS 1.2 LTS */
	TLS_EXT_COMPRESS_CERT,		/* 27: RFC 8879 Certificate compression */
	TLS_EXT_RECORD_SIZE_LIMIT,	/* 28: RFC 8449 Record size limit */
	TLS_EXT_PWD_PROTECT,		/* 29: RFC 8492 Password, protected username */
	TLS_EXT_PWD_CLEAR,			/* 30: RFC 8492 Password, visible username */
	TLS_EXT_PASSWORD_SALT,		/* 31: RFC 8492 Password salt */
	TLS_EXT_TICKET_PINNING,		/* 32: RFC 8672 Server identity pinning */
	TLS_EXT_CERT_WITH_PSK,		/* 33: RFC 8773 TLS 1.3 Certificate-based auth with PSK */
	TLS_EXT_DELEGATED_CREDENIALS, /* 34: Draft, Delegated credentials */
	TLS_EXT_SESSIONTICKET,		/* 35: RFC 4507 Session ticket */
	TLS_EXT_TLMSP,				/* 36: ETSI TS 103 523-2, Middlebox */
	TLS_EXT_TLMSP_PROXYING,		/* 37: ETSI TS 103 523-2, Security */
	TLS_EXT_TLMSP_DELEGATE,		/* 38: ETSI TS 103 523-2, Protocol */
	TLS_EXT_SUPPORTED_EKT_CIPHERS, /* 39: RFC 8870, Encrypted key transport */
		/* 40 unused */
	TLS_EXT_PRESHARED_KEY = 41,	/* 41: RFC 8446 TLS 1.3 pre-shared key */
	TLS_EXT_EARLY_DATA,			/* 42: RFC 8446 TLS 1.3 early data */
	TLS_EXT_SUPPORTED_VERSIONS,	/* 43: RFC 8446 TLS 1.3 supported versions */
	TLS_EXT_COOKIE,				/* 44: RFC 8446 TLS 1.3 cookie */
	TLS_EXT_PSK_KEYEX_MODES,	/* 45: RFC 8446 TLS 1.3 key exchange modes */
		/* 46 unused */
	TLS_EXT_CAS = 47,			/* 47: RFC 8446 TLS 1.3 certificate authorities */
	TLS_EXT_OID_FILTERS,		/* 48: RFC 8446 TLS 1.3 OID filters */
	TLS_EXT_POST_HS_AUTH,		/* 49: RFC 8446 TLS 1.3 post-handshake auth */
	TLS_EXT_SIG_ALGOS_CERT,		/* 50: RFC 8446 TLS 1.3 certificate signature algos */
	TLS_EXT_KEY_SHARE,			/* 51: RFC 8446 TLS 1.3 key share */
	TLS_EXT_TRANSPARENCY_INFO,	/* 52: Draft, Certificate transparency info */
	TLS_EXT_CONNECTION_ID_OLD,	/* 53: Draft, DTLS connection ID, deprecated */
	TLS_EXT_CONNECTION_ID,		/* 54: Draft, DTLS connection ID */
	TLS_EXT_EXTERNAL_ID_HASH,	/* 55: RFC 8844, DTLS-SRTP external ID hash */
	TLS_EXT_EXTERNAL_SESSION_ID,/* 56: RFC 8844, DTLS-SRTP external session ID */
	TLS_EXT_QUIC_PARAMETERS,	/* 57: RFC 9001, DTLS for QUIC */
	TLS_EXT_TICKET_REQUEST,		/* 58: Draft, TLS 1.3 ticket request */
	TLS_EXT_DNSSEC_CHAIN,		/* 59: Draft, DANE authentication information */
	TLS_EXT_LAST,
		/* 60....65280 unused */

	/* The secure-renegotiation extension, for some unknown reason, is given
	   a value of 65281 / 0xFF01, so we define it outside the usual 
	   extension range in order for the standard range-checking to be a bit
	   more sensible.
	   
	   Once secure-renegotiation started this, others followed, so now we've
	   got several special-snowflake values that we need to accommodate */
	TLS_EXT_ECH_OUTER = 64768,	/* ECH draft */
	TLS_EXT_ECH = 65037,		/* ECH draft */
	TLS_EXT_SECURE_RENEG = 65281/* RFC 5746 secure renegotiation */
	} TLS_EXT_TYPE;

/* TLS certificate types */

typedef enum {
	TLS_CERTTYPE_NONE, TLS_CERTTYPE_RSA, TLS_CERTTYPE_DSA, 
	TLS_CERTTYPE_DUMMY1 /* RSA+DH */, TLS_CERTTYPE_DUMMY2 /* DSA+DH */,
	TLS_CERTTYPE_DUMMY3 /* RSA+EDH */, TLS_CERTTYPE_DUMMY4 /* DSA+EDH */,
	TLS_CERTTYPE_ECDSA = 64, TLS_CERTTYPE_LAST
	} TLS_CERTTYPE_TYPE;

/* TLS ECC curve types */

typedef enum {
	TLS_CURVETYPE_NONE, TLS_CURVETYPE_EXPLICIT_PRIME, 
	TLS_CURVETYPE_EXPLICIT_CHAR2, TLS_CURVETYPE_NAMED, TLS_CURVETYPE_LAST
	} TLS_CURVETYPE_TYPE;


/* TLS signature and hash algorithm identifiers, from
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
   (for signatures) and 
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18
   (for hash values) */

enum {
	TLS_SIGALGO_NONE, TLS_SIGALGO_RSA, TLS_SIGALGO_DSA, TLS_SIGALGO_ECDSA,
	TLS_SIGALGO_LAST 
	};

enum {
	TLS_HASHALGO_NONE, TLS_HASHALGO_MD5, TLS_HASHALGO_SHA1, 
	TLS_HASHALGO_DUMMY1 /* SHA2-224 */, TLS_HASHALGO_SHA2, 
	TLS_HASHALGO_SHA384, TLS_HASHALGO_SHA512, 
	TLS_HASHALGO_LAST 
	};

/* TLS 1.3 combined signature+hash identifiers, from
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme  
   See the comment in session/tls_ext.c for why there are two lots of 
   identifiers for RSA-PSS */

enum {
	TLS_SIGHASHALGO_NONE,
	
	/* TLS classic IDs */
	TLS_SIGHASHALGO_RSAPKCS1_SHA2 = 0x0401, TLS_SIGHASHALGO_DSA_SHA2, 
	TLS_SIGHASHALGO_ECDSA_SHA2,
	TLS_SIGHASHALGO_RSAPKCS1_SHA384 = 0x0501, TLS_SIGHASHALGO_DSA_SHA384, 
	TLS_SIGHASHALGO_ECDSA_SHA384,
	TLS_SIGHASHALGO_RSAPKCS1_SHA512 = 0x0601, TLS_SIGHASHALGO_DSA_SHA512,
	TLS_SIGHASHALGO_ECDSA_SHA512,

	/* TLS 1.3 IDs */
	TLS_SIGHASHALGO_RSAPSSoid1_SHA2 = 0x0804, 
	TLS_SIGHASHALGO_RSAPSSoid1_SHA384,
	TLS_SIGHASHALGO_RSAPSSoid1_SHA512,
	TLS_SIGHASHALGO_ED25519, TLS_SIGHASHALGO_ED448, 
	TLS_SIGHASHALGO_RSAPSSoid2_SHA2, TLS_SIGHASHALGO_RSAPSSoid2_SHA384,
	TLS_SIGHASHALGO_RSAPSSoid2_SHA512,
	TLS_SIGHASHALGO_LAST
	};

/* TLS group type identifiers, from
   https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 */

typedef enum {
	TLS_GROUP_NONE, 
	
	/* ECC groups */
	TLS_GROUP_SECT163K1, TLS_GROUP_SECT163R1, TLS_GROUP_SECT163R2, 
	TLS_GROUP_SECT193R1, TLS_GROUP_SECT193R2, TLS_GROUP_SECT233K1, 
	TLS_GROUP_SECT233R1, TLS_GROUP_SECT239K1, TLS_GROUP_SECT283K1, 
	TLS_GROUP_SECT283R1, TLS_GROUP_SECT409K1, TLS_GROUP_SECT409R1, 
	TLS_GROUP_SECT571K1, TLS_GROUP_SECT571R1, TLS_GROUP_SECP160K1, 
	TLS_GROUP_SECP160R1, TLS_GROUP_SECP160R2, TLS_GROUP_SECP192K1, 
	TLS_GROUP_SECP192R1, TLS_GROUP_SECP224K1, TLS_GROUP_SECP224R1, 
	TLS_GROUP_SECP256K1, 
	TLS_GROUP_SECP256R1 /* P256 */, 
	TLS_GROUP_SECP384R1 /* P384 */, 
	TLS_GROUP_SECP521R1 /* P521 */,
	TLS_GROUP_BRAINPOOLP256R1, TLS_GROUP_BRAINPOOLP384R1, 
	TLS_GROUP_BRAINPOOLP512R1,
	
	/* Bernstein groups */
	TLS_GROUP_X25519, TLS_GROUP_X448,
	
	/* DH groups */
	TLS_GROUP_FFDHE2048 = 256, TLS_GROUP_FFDHE3072,
	TLS_GROUP_FFDHE4096, TLS_GROUP_FFDHE6144, TLS_GROUP_FFDHE8192,
	
	/* PQC groups */
	TLS_GROUP_MLKEM512 = 512, TLS_GROUP_MLKEM768, TLS_GROUP_MLKEM1024,
	TLS_GROUP_P256MLKEM768 = 4587, TLS_GROUP_X25519MLKEM768, 
	TLS_GROUP_P384MLKEM1024, TLS_GROUP_SM2MLKEM768,
	
	TLS_GROUP_LAST
	} TLS_GROUP_TYPE;

#define isECCGroup( group ) \
		( ( group ) >= TLS_GROUP_SECT163K1 && \
		  ( group ) <= TLS_GROUP_X448 )
#define isPQCGroup( group ) \
		( ( group ) >= TLS_GROUP_MLKEM512 && \
		  ( group ) <= TLS_GROUP_SM2MLKEM768 )

/* TLS 1.3 PSK modes */

typedef enum {
	TLS_PSK_STANDARD,	/* Equivalent to TLS < 1.3 session resumption */
	TLS_PSK_DHE,		/* Session resumption with (EC)DH */
	TLS_PSK_LAST
	} TLS_PSK_TYPE;

/* TLS major and minor version numbers */

#define TLS_MAJOR_VERSION		3
#define TLS_MINOR_VERSION_SSL	0
#define TLS_MINOR_VERSION_TLS	1
#define TLS_MINOR_VERSION_TLS11	2
#define TLS_MINOR_VERSION_TLS12	3
#define TLS_MINOR_VERSION_TLS13	4

/* TLS downgrade-protection magic values for the server random */

#define TLS_DOWNGRADEID_PREFIX	"DOWNGRD"
#define TLS_DOWNGRADEID_PREFIX_SIZE	7
#define TLS_DOWNGRADEID_TLS12	TLS_DOWNGRADEID_PREFIX "\x01"
#define TLS_DOWNGRADEID_TLS11	TLS_DOWNGRADEID_PREFIX "\x00"
#define TLS_DOWNGRADEID_SIZE	8
#define TLS_DOWNGRADEID_OFFSET	( TLS_NONCE_SIZE - TLS_DOWNGRADEID_SIZE )

/* TLS 1.3 magic value to denote that a Server Hello is actually a Hello 
   Retry Request */

#define TLS_HELLORETRY_MAGIC	"\xCF\x21\xAD\x74\xE5\x9A\x61\x11" \
								"\xBE\x1D\x8C\x02\x1E\x65\xB8\x91" \
								"\xC2\xA2\x11\x16\x7A\xBB\x8C\x5E" \
								"\x07\x9E\x09\xE2\xC8\xA8\x33\x9C"
#define TLS_HELLORETRY_MAGIC_SIZE 32

/* TLS cipher suite fallback options, see the comment in TLS_HANDSHAKE_INFO
   for details */

typedef enum {
	TLS_FALLBACK_NONE,				/* No fallback type */
	TLS_FALLBACK_ECC,				/* Fallback to ECC suite */
	TLS_FALLBACK_TLS13,				/* Fallback to TLS 1.3 suite */
	TLS_FALLBACK_LAST
	} TLS_FALLBACK_TYPE;

/* Special-case actions that need to be taken in response to a client hello */

typedef enum {
	TLSHELLO_ACTION_NONE,			/* No special action */
	TLSHELLO_ACTION_RESUMEDSESSION,	/* Session is resumed from previous */
#ifdef USE_TLS13
	TLSHELLO_ACTION_RETRY,			/* Send TLS 1.3 HelloRetryRequest */
#endif /* USE_TLS13 */
	TLSHELLO_ACTION_LAST
	} TLSHELLO_ACTION_TYPE;

/* TLS cipher suite flags.  These are:

	CIPHERSUITE_BERNSTEIN: Suite uses the Bernstein algorithm suite.

	CIPHERSUITE_GCM: Encryption uses GCM instead of the usual CBC.

	CIPHERSUITE_PSK: Suite is a TLS-PSK suite and is used only if we're
		using TLS-PSK.

	CIPHERSUITE_TLS12: Suite is a TLS 1.2 suite and is only sent if
		TLS 1.2 is enabled.

	CIPHERSUITE_TLS13: Suite is a TLS 1.3 suite and is only sent if
		TLS 1.3 is enabled.
	
	CIPHERSUITE_TRIGGER: Suite will trigger a bogus warning from a security
		scanner if the server appears to support it */

#define CIPHERSUITE_FLAG_NONE	0x00	/* No suite */
#define CIPHERSUITE_FLAG_PSK	0x01	/* TLS-PSK suite */
#define CIPHERSUITE_FLAG_TLS12	0x02	/* TLS 1.2 suite */
#define CIPHERSUITE_FLAG_TLS13	0x04	/* TLS 1.3 suite */
#define CIPHERSUITE_FLAG_GCM	0x08	/* GCM instead of CBC */
#define CIPHERSUITE_FLAG_BERNSTEIN 0x10	/* Special-snowflake suite */
#define CIPHERSUITE_FLAG_TRIGGER 0x20	/* Scanner-triggering suite */
#define CIPHERSUITE_FLAG_MAX	0x3F	/* Maximum possible flag value */

typedef struct {
	/* The TLS cipher suite.  The debugText field isn't used in error 
	   messages but is enabled if their use is defined because of the way 
	   the DESCRIPTION() macro that sets it works */
	const int cipherSuite;
#if defined( USE_ERRMSGS ) || !defined( NDEBUG )
	const char *debugText;
#endif /* USE_ERRMSGS || !NDEBUG */

	/* cryptlib algorithms for the cipher suite */
	const CRYPT_ALGO_TYPE keyexAlgo, authAlgo, cryptAlgo, macAlgo;

	/* Auxiliary information for the suite */
	const int macParam, cryptKeySize, macBlockSize;
	const int flags;
	} CIPHERSUITE_INFO;

/* Handshake flags.  These are:

	HANDSHAKE_HASEXTENSIONS: Hello has TLS extensions.

	HANDSHAKE_ISGOOGLE: Peer is Google Chrome, used to work around Chrome 
						bugs.

	HANDSHAKE_NEEDEMSRESPONSE: Server needs to respond to EMS.

	HANDSHAKE_NEEDETMRESPONSE: Server needs to respond to encThenMAC.

	HANDSHAKE_NEEDRENEGRESPONSE: Server needs to respond to renegotiation 
								 indication.

	HANDSHAKE_NEEDSNIRESPONSE: Server needs to respond to SNI.

	HANDSHAKE_NEEDTLS12LTSRESPONSE: Server needs to respond to TLS-LTS.

	HANDSHAKE_ISSCANNER: Client is a security scanner which will complain of 
						 bogus vulnerabilities, limit the response data to 
						 non-triggering values.

	HANDSHAKE_RETRIEDCLIENTHELLO: Whether client hello retry done */

#define HANDSHAKE_FLAG_NONE				0x000	/* No flag value */
#define HANDSHAKE_FLAG_HASEXTENSIONS	0x001	/* Hello has extensions */
#define HANDSHAKE_FLAG_NEEDSNIRESPONSE	0x002	/* Response to SNI needed */
#define HANDSHAKE_FLAG_NEEDRENEGRESPONSE 0x004	/* Response to reneg.needed */
#define HANDSHAKE_FLAG_NEEDETMRESPONSE	0x008	/* Response to EtM needed */
#define HANDSHAKE_FLAG_NEEDEMSRESPONSE	0x010	/* Response to EMS needed */
#define HANDSHAKE_FLAG_NEEDTLS12LTSRESPONSE 0x020/* Response to TLS-LTS needed */
#define HANDSHAKE_FLAG_ISSCANNER		0x040	/* Client is a security scanner */
#ifdef USE_TLS13
#define HANDSHAKE_FLAG_RETRIEDCLIENTHELLO 0x080	/* Client Hello Retry needed */
#define HANDSHAKE_FLAG_ISGOOGLE			0x100	/* Peer is Google Chrome */
#define HANDSHAKE_FLAG_MAX				0x1FF	/* Maximum possible flag value */
#else
#define HANDSHAKE_FLAG_MAX				0x07F	/* Maximum possible flag value */
#endif /* USE_TLS13 */

/* The maximum size of the list of cipher suites, used to allocate storage 
   and for bounds checking, see session/tls_suites.c for the contents of the 
   suite lists */

#define NO_SUITES_STD		16		/* DH + PSK */
#if defined( USE_ECDH ) 
  #define NO_SUITES_ECDH	8 
#else
  #define NO_SUITES_ECDH	0 
#endif /* USE_ECDH */
#if defined( USE_GCM ) 
  #define NO_SUITES_GCM		8 
#else
  #define NO_SUITES_GCM		0 
#endif /* USE_GCM */
#if defined( USE_CHACHA20 )
  #define NO_SUITES_CHACHA20 8 
#else
  #define NO_SUITES_CHACHA20 0 
#endif /* USE_CHACHA20 */
#ifdef USE_RSA_SUITES
  #define NO_SUITES_RSA		8 
#else
  #define NO_SUITES_RSA		0 
#endif /* USE_RSA_SUITES */

#define MAX_NO_SUITES		( NO_SUITES_STD + NO_SUITES_ECDH + \
							  NO_SUITES_GCM + NO_SUITES_CHACHA20 + \
							  NO_SUITES_RSA )

/* Check for the presence of a TLS signalling suite */

#define isSignallingSuite( suite ) \
		( ( suite ) == TLS_FALLBACK_SCSV || \
		  ( suite ) == TLS_EMPTY_RENEGOTIATION_INFO_SCSV )

/* Check for an RFC 8701 / GREASE garbage value.  This is, by design, an 
   invalid value for whatever it's being used for but one that we have to 
   accept because Google Chrome inserts them wherever it can in the Client
   Hello.  GREASE values always have the high byte match the low byte with 
   the low nibbles of each byte being 0x0A, so 0x0A0A, 0x1A1A, ..., 0xFAFA */

#define checkGREASE( value ) \
		( ( ( value ) >> 8 ) == ( ( value ) & 0xFF ) && \
		  ( ( value ) & 0x0F0F ) == 0x0A0A ) 

/* If we're configured to only use Suite B algorithms, we override the
   algoAvailable() check to report that only Suite B algorithms are
   available */

#ifdef CONFIG_SUITEB

#if defined( _MSC_VER ) || defined( __GNUC__ ) || defined( __clang__ )
  #pragma message( "  Building with Suite B algorithms only." )
#endif /* Notify Suite B use */

#define algoAvailable( algo ) \
		( ( ( algo ) == CRYPT_ALGO_AES || ( algo ) == CRYPT_ALGO_ECDSA || \
			( algo ) == CRYPT_ALGO_ECDH || ( algo ) == CRYPT_ALGO_SHA2 || \
			( algo ) == CRYPT_ALGO_HMAC_SHA2 ) ? TRUE : FALSE )

  /* Special configuration defines to enable nonstandard behaviour for 
     Suite B tests */
  #ifdef CONFIG_SUITEB_TESTS 
	typedef enum {
		SUITEB_TEST_NONE,			/* No special test behaviour */

		/* RFC 5430bis tests */
		SUITEB_TEST_CLIINVALIDCURVE,/* Client sends non-Suite B curve */
		SUITEB_TEST_SVRINVALIDCURVE,/* Server sends non-Suite B curve */
		SUITEB_TEST_BOTHCURVES,		/* Client must send P256 and P384 as supp.curves */
		SUITEB_TEST_BOTHSIGALGOS,	/* Client must send SHA256 and SHA384 as sig.algos */

		SUITEB_TEST_LAST
		} SUITEB_TEST_VALUE;

	extern SUITEB_TEST_VALUE suiteBTestValue;
	extern BOOLEAN suiteBTestClientCert;
  #endif /* CONFIG_SUITEB_TESTS */
#endif /* Suite B algorithms only */

/* The following macro can be used to enable dumping of PDUs to disk.  As a
   safeguard, this only works in the Win32 debug version to prevent it from
   being accidentally enabled in any release version */

#if defined( __WIN32__ ) && defined( USE_ERRMSGS ) && !defined( NDEBUG )
  #define DEBUG_DUMP_TLS( buffer1, buffer1size, buffer2, buffer2size ) \
		  debugDumpTLS( sessionInfoPtr, buffer1, buffer1size, buffer2, buffer2size )

  STDC_NONNULL_ARG( ( 1, 2 ) ) \
  void debugDumpTLS( const SESSION_INFO *sessionInfoPtr,
					 IN_BUFFER( buffer1size ) const void *buffer1, 
					 IN_LENGTH_SHORT const int buffer1size,
					 IN_BUFFER_OPT( buffer2size ) const void *buffer2, 
					 IN_LENGTH_SHORT_Z const int buffer2size );
#else
  #define DEBUG_DUMP_TLS( buffer1, buffer1size, buffer2, buffer2size )
#endif /* Win32 debug */

/****************************************************************************
*																			*
*								TLS Structures								*
*																			*
****************************************************************************/

/* Information on the smorgasbord of keyex groups used in TLS */

typedef struct {
	TLS_GROUP_TYPE tlsGroupID;		/* TLS group */
	CRYPT_ALGO_TYPE algorithm;		/* Algorithm for the group */
	CRYPT_ECCCURVE_TYPE eccCurveID;	/* ECC curve ID if required */
#if defined( USE_ERRMSGS ) || !defined( NDEBUG )
	const char *description;		/* Text description */
#endif /* USE_ERRMSGS || debug mode */
	int keySize;					/* Key size */
	int minTlsVersion;				/* Min.TLS version to use with */
	BOOLEAN clientAdvertise;		/* Advertise in client hello */
	} TLS_GROUP_INFO;

/* TLS handshake state information.  This is passed around various 
   subfunctions that handle individual parts of the handshake */

struct TH;

typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
	int ( *TLS_HANDSHAKE_FUNCTION )( INOUT_PTR SESSION_INFO *sessionInfoPtr,
									 INOUT_PTR struct TH *handshakeInfo );

typedef struct TH {
	/* Client and server dual-hash/hash contexts */
	CRYPT_CONTEXT md5context, sha1context, sha2context;
#ifdef CONFIG_SUITEB
	CRYPT_CONTEXT sha384context;
#endif /* CONFIG_SUITEB */

	/* Client and server nonces, session ID, and hashed SNI (which is used
	   alongside the session ID for scoreboard lookup) */
	BUFFER_FIXED( TLS_NONCE_SIZE ) \
	BYTE clientNonce[ TLS_NONCE_SIZE + 8 ];
	BUFFER_FIXED( TLS_NONCE_SIZE ) \
	BYTE serverNonce[ TLS_NONCE_SIZE + 8 ];
	BUFFER( MAX_SESSIONID_SIZE, sessionIDlength ) \
	BYTE sessionID[ MAX_SESSIONID_SIZE + 8 ];
	int sessionIDlength;
	BYTE hashedSNI[ KEYID_SIZE + 8 ];
	BOOLEAN hashedSNIpresent;

	/* Client/server hello hash, the hash of the Client Hello and Server 
	   Hello, and session hash, the hash of all messages from Client Hello 
	   to Client Keyex (TLS 1.2) or the last message before the current one
	   (TLS 1.3).
	   
	   We use two different strategies for the hashing, for the Client/
	   Server Hello hash, which are just the first two messages and both 
	   available at the same time, we use direct hash access via 
	   getHashParameters()/hashFunction().  For the session hash, which is
	   an ongoing hash of all messages exchanged, we use a hash context and,
	   for the case of TLS 1.3 which keeps peeling off copies of it to 
	   inject into the endless PRF churn that it applies, clone it and copy
	   the hash value from the cloned copy.  This means that the first two
	   messages, namely the Client and Server Hello, are hashed twice, once 
	   via direct access to get the hello hash and once via the context as 
	   part of the ongoing session hash.

	   In addition the sessionHashContext below isn't what's used for the
	   ongoing hash operation because, depending on the TLS classic version 
	   in use we could be using MD5+SHA1 or SHA2, so the way the hashing is 
	   done is to run as many of the different algorithms as required in 
	   parallel and then clone the one being used into sessionHashContext 
	   via session/tls_sign.c:createSessionHash() when it's time to create 
	   the handshake signature in session/tls_sign.c:createCertVerify() and
	   checkCertVerify().

	   For TLS 1.3 which does things differently we don't clone the ongoing 
	   hash state into sessionHashContext but instead use it to hash some 
	   magic values and the current transcript hash to get the hash value
	   that's then signed.

	   In theory we could just use the hash context and clone-and-copy
	   strategy in all cases, but since TLS 1.2 and TLS 1.3 handle things
	   somewhat differently the simpler strategy is to use direct access for
	   the hello hash, the context for the session hash, and then handle TLS
	   1.3's PRF churn separately as a special case of the latter */
	BUFFER( 16, CRYPT_MAX_HASHSIZE ) \
	BYTE helloHash[ CRYPT_MAX_HASHSIZE + 8 ];
	CRYPT_CONTEXT sessionHashContext;
	BUFFER( 16, CRYPT_MAX_HASHSIZE ) \
	BYTE sessionHash[ CRYPT_MAX_HASHSIZE + 8 ];
	int helloHashSize, sessionHashSize;

	/* Premaster/master secret */
	BUFFER( KEYEX_SECRET_STORAGE_SIZE, premasterSecretSize ) \
	BYTE premasterSecret[ KEYEX_SECRET_STORAGE_SIZE + 8 ];
	int premasterSecretSize;

#ifdef USE_TLS13
	/* For TLS 1.3, which does its keyex via values stuffed into extensions 
	   in the client and server hello, we need to store the keyex data for 
	   later when it's actually used.  Since this can get rather large, we 
	   overload the use of the premaster secret storage, which isn't used at
	   this point */
	#define tls13KeyexValue			premasterSecret
	#define tls13KeyexValueLen		premasterSecretSize

	/* TLS 1.3 also creates a huge explosion of secret data that needs to be
	   passed around different functions, for which we again reuse the
	   premaster secret storage.  Note that the values must be defined 
	   without the usual surrounding brackets because they're used as
	   tlsInfo->tls13ClientSecret which would expand to 
	   tlsInfo->( premasterSecret + CRYPT_MAX_HASHSIZE ) */
	#define tls13MasterSecret		premasterSecret
	#define tls13MasterSecretLen	CRYPT_MAX_HASHSIZE
	#define tls13ClientSecret		premasterSecret + CRYPT_MAX_HASHSIZE
	#define tls13ClientSecretLen	CRYPT_MAX_HASHSIZE
	#define tls13ServerSecret		premasterSecret + ( 2 * CRYPT_MAX_HASHSIZE )
	#define tls13ServerSecretLen	CRYPT_MAX_HASHSIZE
	#if 3 * CRYPT_MAX_HASHSIZE > KEYEX_SECRET_STORAGE_SIZE
		#error KEYEX_SECRET_STORAGE_SIZE is too small
	#endif /* KEYEX_SECRET_STORAGE_SIZE check */

	/* There's even more stuff that needs to be stored for TLS 1.3, in this 
	   case a binary-blob certificate context that the server sends in
	   certificate-request packets that the client has to echo back in its
	   certificate response, because reasons */
	BUFFER( CRYPT_MAX_HASHSIZE, tls13CertContextLen ) \
	BYTE tls13CertContext[ CRYPT_MAX_HASHSIZE + 8 ];
	int tls13CertContextLen;

	/* PQC needs even more stuff, this time the ML-KEM secret key that's 
	   generated as part of the key-wrap operation */
  #ifdef USE_MLKEM
	BUFFER( CRYPT_MAX_HASHSIZE, tls13PqcSecretValueLen ) \
	BYTE tls13PqcSecretValue[ CRYPT_MAX_HASHSIZE + 8 ];
	int tls13PqcSecretValueLen;
  #endif /* USE_MLKEM */
  
	/* Since we don't know at the time that we're reading the cipher suites
	   whether we'll be doing TLS 1.3 or not, we have to bookmark the 
	   required TLS 1.3 suite in case we later need to use it */
	const CIPHERSUITE_INFO *tls13SuiteInfoPtr;/* TLS 1.3 suite information */
	
	/* Complicating things even further, we can also see TLS 1.3 keyex data
	   and other paraphernalia before we get an indication that TLS 1.3 is 
	   OK via the supported-versions extension.  To deal with this, we 
	   remember whether we've seen any TLS 1.3 suites in the cipher suites 
	   list and only look at the TLS 1.3-related extensions like keyex if
	   there are cipher suites available to go with them.
	   
	   We can't simply use the presence or absence of data in the 
	   tls13SuiteInfoPtr for this because if the only suite that we've seen 
	   is a TLS 1.3 one then it'll be saved as the primary cipher suite and
	   tls13SuiteInfoPtr won't be set */
	BOOLEAN tls13OK;				/* Whether TLS 1.3 suite seen */

	/* When a TLS 1.3 client guess incorrectly at what the server wants, it 
	   needs to re-send the Client Hello with a different guess.  To deal 
	   with this we need to re-hash the original Client Hello and Server 
	   Hello along with the re-sent second Client Hello and Server Hello to
	   get the hello hash.  To do this we need to record the sizes of the 
	   first Client and Server Hello */
	int originalClientHelloLength, originalServerHelloLength;

	/* The special-snowflake algorithms want to sign the entire message 
	   rather than just a hash of the message, fortunately what TLS 1.3
	   signs is a hash of the transcript hash and a prefix string so all
	   we need to store is the prefix string and transcript hash rather
	   than a copy of every handshake message as we would with TLS classic */
  #ifdef USE_ED25519
	const void *transcriptPrefixString;
	int transcriptPrefixStringLength;
	BUFFER( CRYPT_MAX_HASHSIZE, transcriptHashLength ) \
	BYTE transcriptHash[ CRYPT_MAX_HASHSIZE + 8 ];
	int transcriptHashLength;
  #endif /* USE_ED25519 */
#endif /* USE_TLS13 */

	/* Encryption/security information.  Since for TLS 1.3 we have to guess 
	   which keyex mechanism the other side is using we need two or even
	   three DH/ECDH/25519 contexts on the client, one for each guessed 
	   algorithm.  
	   
	   The encryption algorithm (cryptAlgo) and integrity algorithm 
	   (integrityAlgo) are stored with the session information, although the 
	   optional integrity-algorithm parameters are stored here.  In 
	   particular for TLS classic the cipher suite selects the keyexAlgo
	   (e.g. DH) and authAlgo (e.g. RSA) while for TLS 1.3 it's stuffed 
	   into extensions, it also selects the sessionInfoPtr->cryptAlgo (e.g. 
	   AES) and sessionInfoPtr->integrityAlgo (e.g. HMAC-SHA2) */
	CRYPT_CONTEXT keyexContext;	/* Keyex context for DH/ECDH/25519 */
#ifdef USE_TLS13
	CRYPT_CONTEXT keyexEcdhContext;	/* Alt.ECDH context for TLS 1.3 */
  #ifdef USE_X25519
	CRYPT_CONTEXT keyex25519Context;/* Alt.25519 context for TLS 1.3 */
  #endif /* USE_X25519 */
  #ifdef USE_MLKEM
	CRYPT_CONTEXT keyexAltContext;	/* MLKEM context for 25519MLKEM */
  #endif /* USE_MLKEM */
#endif /* USE_TLS13 */
	int cipherSuite;			/* Selected cipher suite */
	int cipherSuiteFlags;		/* Flags for selected cipher suite */
	CRYPT_ALGO_TYPE keyexAlgo;	/* Cipher suite keyex algo, e.g. DH */
	CRYPT_ALGO_TYPE authAlgo;	/* Cipher suite auth algo, e.g. RSA */
	int integrityAlgoParam;		/* Optional param.for integrity algo in
								   sessionInfo */
	CRYPT_ALGO_TYPE keyexSigHashAlgo;/* Hash algo.for keyex sig. e.g. SHA2 */
	int keyexSigHashAlgoParam;	/* Optional params.for keyex hash */
	int cryptKeysize;			/* Size of key in sessionInfo */

	/* Other information */
	HANDSHAKE_STATE_TYPE completedHSstate;	/* Just-completed handshake state */
	int clientOfferedVersion;	/* Prot.vers.originally offered by client */
	int originalVersion;		/* Original version set by the user before
								   it was modified based on what the peer
								   requested */
	int flags;					/* HANDSHAKE_FLAG_x flags */
	int failAlertType;			/* Alert type to send on failure */

	/* ECC-related information.  Since ECC algorithms have a huge pile of
	   parameters we need to parse any extensions that the client sends in 
	   order to locate any additional information required to handle them.  
	   In the worst case these can retroactively modify the already-
	   negotiated cipher suites, disabling the use of ECC algorithms after 
	   they were agreed on via cipher suites.  
	   
	   To handle this we remember both the preferred mainstream suite, a 
	   pointer to the preferred ECC suite in 'eccSuiteInfoPtr', and pointers 
	   to the ECC suite parameters in 'keyexGroupInfo' and further 
	   parameters for TLS 1.3 in 'keyexTls13GroupInfo' if it later turns out 
	   that we're doing TLS 1.3 and not TLS 1.2 as the handshake version 
	   claims.  If it later turns out (via supported groups) that the use of 
	   ECC is OK we reset the crypto parameters using the saved ECC suite 
	   pointer.
	   
	   We also have to check which of the modifiers to basic ECC via
	   supported groups takes precedence, since if we're using TLS 1.3 we
	   don't want to automatically choose the 1.3 suite if the client has
	   indicated a preference for a TLS classic suite, but we don't know
	   at the time we see it which of TLS 1.3 or TLS classic we'll be 
	   applying.
	   
	   If the use of ECC isn't retroactively disabled then the 
	   sendECCPointExtn flag indicates whether the server needs to respond 
	   with a point-extension indicator */
	BOOLEAN disableECC;			/* Extn.disabled use of ECC suites */
	const void *eccSuiteInfoPtr;/* ECC suite information */
	const TLS_GROUP_INFO *keyexGroupInfo;	/* Further ECC info from supp.groups */
#ifdef USE_TLS13
	const TLS_GROUP_INFO *keyexTls13GroupInfo;
	const TLS_GROUP_INFO *keyexTls13PrefGroupInfo;	
								/* Preferred TLS 1.2 or 1.3 group */
	BOOLEAN keyexTls13Preferred;/* Whether to prefer TLS 1.3 keyex or general keyex */
#endif /* USE_TLS13 */
	BOOLEAN sendECCPointExtn;	/* Whether svr.has to respond with ECC point ext.*/

	/* Another side-effect of the post-modification of suites via 
	   information in extensions is that depending on what the client 
	   advertises we may have to fall back through successive alternatives 
	   while parsing the suites.  Typical behaviour for a standard client
	   hello is to record the main suite and bookmark ECC and TLS 1.3
	   alternatives, however if there's no main suite present that what's
	   recorded is the ECC suite, and if that's not present the TLS 1.3
	   suite.  In order to figure out what's what, we need to record whether
	   the fallback to alternative suites has been triggered */
	TLS_FALLBACK_TYPE fallbackType;

	/* The packet data stream.  Since TLS can encapsulate multiple handshake
	   packets within a single TLS packet, the stream has to be persistent
	   across the different handshake functions to allow the continuation of
	   packets */
	STREAM stream;				/* Packet data stream */

	/* Function pointers to handshaking functions.  These are set up as 
	   required depending on whether the session is client or server */
	FNPTR beginHandshake, exchangeKeys;
	} TLS_HANDSHAKE_INFO;

/****************************************************************************
*																			*
*								TLS Functions								*
*																			*
****************************************************************************/

/* Prototypes for functions in tls.c */

#ifndef CONFIG_CONSERVE_MEMORY_EXTRA
CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN sanityCheckSessionTLS( IN_PTR const SESSION_INFO *sessionInfoPtr );
CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN sanityCheckTLSHandshakeInfo( IN_PTR \
										const TLS_HANDSHAKE_INFO *handshakeInfo );
#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */
CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
int readUint24( INOUT_PTR STREAM *stream );
STDC_NONNULL_ARG( ( 1 ) ) \
int writeUint24( INOUT_PTR STREAM *stream, IN_LENGTH_Z const int length );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int readEcdhValue( INOUT_PTR STREAM *stream,
				   OUT_BUFFER( valueMaxLen, *valueLen ) void *value,
				   IN_LENGTH_SHORT_MIN( 64 ) const int valueMaxLen,
				   OUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int readTLSCertChain( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					  INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo, 
					  INOUT_PTR STREAM *stream,
					  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertChain, 
					  IN_BOOL const BOOLEAN isServer );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int writeTLSCertChain( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo, 
					   INOUT_PTR STREAM *stream );

/* Prototypes for functions in tls_cert.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \
int checkHostNameTLS( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
					  INOUT_BUFFER_FIXED( serverNameLength ) void *serverName,
					  IN_LENGTH_DNS const int serverNameLength,
					  OUT_PTR ERROR_INFO *errorInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int checkTLSCertificateInfo( INOUT_PTR SESSION_INFO *sessionInfoPtr );

/* Prototypes for functions in tls_crypt.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int encryptData( const SESSION_INFO *sessionInfoPtr, 
				 INOUT_BUFFER( dataMaxLength, *dataLength ) \
					BYTE *data, 
				 IN_DATALENGTH const int dataMaxLength,
				 OUT_DATALENGTH_Z int *dataLength,
				 IN_DATALENGTH const int payloadLength );
				 /* This one's a bit tricky, the input is 
				    { data, payloadLength } which is padded (if necessary) 
					and the padded length returned in '*dataLength' */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int decryptData( SESSION_INFO *sessionInfoPtr, 
				 INOUT_BUFFER_FIXED( dataLength ) \
					BYTE *data, 
				 IN_DATALENGTH const int dataLength, 
				 OUT_DATALENGTH_Z int *processedDataLength );
				/* This one's also tricky, the entire data block will be 
				   processed but only 'processedDataLength' bytes of result 
				   are valid output */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int createMacTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
				  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data,
				  IN_DATALENGTH const int dataMaxLength, 
				  OUT_DATALENGTH_Z int *dataLength,
				  IN_DATALENGTH const int payloadLength, 
				  IN_RANGE( TLS_PACKETTYPE_FIRST, \
							TLS_PACKETTYPE_LAST ) const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int checkMacTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
				 IN_BUFFER( dataLength ) const void *data, 
				 IN_DATALENGTH const int dataLength, 
				 IN_DATALENGTH_Z const int payloadLength, 
				 IN_RANGE( TLS_PACKETTYPE_FIRST, \
						   TLS_PACKETTYPE_LAST ) \
						const int packetType,
				 IN_BOOL const BOOLEAN noReportError );
#ifdef USE_GCM
CHECK_RETVAL \
int macDataTLSGCM( IN_HANDLE const CRYPT_CONTEXT iCryptContext, 
				   IN_INT_Z const int seqNo, 
				   IN_RANGE( TLS_MINOR_VERSION_TLS, \
							 TLS_MINOR_VERSION_TLS13 ) const int version,
				   IN_LENGTH_Z const int payloadLength, 
				   IN_RANGE( TLS_PACKETTYPE_FIRST, \
							 TLS_PACKETTYPE_LAST ) const int packetType );
#endif /* USE_GCM */
#ifdef USE_CHACHA20
CHECK_RETVAL \
int initCryptBernstein( INOUT_PTR SESSION_INFO *sessionInfoPtr,
						IN_BOOL const BOOLEAN isRead );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int createMacTLSBernstein( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						   INOUT_BUFFER( dataMaxLength, *dataLength ) \
								void *data, 
						   IN_DATALENGTH const int dataMaxLength, 
						   OUT_DATALENGTH_Z int *dataLength,
						   IN_DATALENGTH const int payloadLength, 
						   IN_RANGE( TLS_PACKETTYPE_FIRST, \
									 TLS_PACKETTYPE_LAST ) \
								const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int checkMacTLSBernstein( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						  IN_BUFFER( dataLength ) const void *data, 
						  IN_DATALENGTH const int dataLength, 
						  IN_DATALENGTH_Z const int payloadLength, 
						  IN_RANGE( TLS_PACKETTYPE_FIRST, \
									TLS_PACKETTYPE_LAST ) \
								const int packetType );
#endif /* USE_CHACHA20 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int hashHSPacketRead( IN_PTR const TLS_HANDSHAKE_INFO *handshakeInfo, 
					  INOUT_PTR STREAM *stream );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int hashHSPacketWrite( IN_PTR const TLS_HANDSHAKE_INFO *handshakeInfo, 
					   INOUT_PTR STREAM *stream,
					   IN_DATALENGTH_Z const int offset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \
int completeTLSHashedMAC( IN_HANDLE const CRYPT_CONTEXT md5context,
						  IN_HANDLE const CRYPT_CONTEXT sha1context, 
						  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \
								BYTE *hashValues, 
						  IN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \
								const int hashValuesMaxLen,
						  OUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \
								int *hashValuesLen,
						  IN_BUFFER( labelLength ) const char *label, 
						  IN_RANGE( 1, 64 ) const int labelLength, 
						  IN_BUFFER( masterSecretLen ) const BYTE *masterSecret, 
						  IN_LENGTH_SHORT const int masterSecretLen );
CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5, 7 ) ) \
int completeTLS12HashedMAC( IN_HANDLE const CRYPT_CONTEXT sha2context,
							OUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \
								BYTE *hashValues, 
							IN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \
								const int hashValuesMaxLen,
							OUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \
								int *hashValuesLen,
							IN_BUFFER( labelLength ) const char *label, 
							IN_RANGE( 1, 64 ) const int labelLength, 
							IN_BUFFER( masterSecretLen ) const BYTE *masterSecret, 
							IN_LENGTH_SHORT const int masterSecretLen,
							IN_BOOL const BOOLEAN fullSizeMAC );

/* Prototypes for functions in tls_ext.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int readExtensions( INOUT_PTR STREAM *stream, 
					INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					OUT_ENUM_OPT( TLSHELLO_ACTION ) \
							TLSHELLO_ACTION_TYPE *actionType,
					IN_LENGTH_SHORT const int length );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int writeClientExtensions( INOUT_PTR STREAM *stream,
						   INOUT_PTR SESSION_INFO *sessionInfoPtr,
						   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int writeServerExtensions( INOUT_PTR STREAM *stream,
						   INOUT_PTR SESSION_INFO *sessionInfoPtr,
						   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );

/* Prototypes for functions in tls_hello.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int processHelloTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo, 
					 INOUT_PTR STREAM *stream, 
					 OUT_ENUM_OPT( TLSHELLO_ACTION ) \
							TLSHELLO_ACTION_TYPE *actionType,
					 IN_BOOL const BOOLEAN isServer );

/* Prototypes for functions in tls_hscomplete.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int completeHandshakeTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr,
						  INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						  IN_BOOL const BOOLEAN isClient,
						  IN_BOOL const BOOLEAN isResumedSession );

/* Prototypes for functions in tls_keyex.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createKeyexContextTLS( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, 
						   IN_ALGO const CRYPT_ALGO_TYPE dhAlgo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initKeyexContextTLS( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, 
						 IN_BUFFER_OPT( keyDataLength ) const void *keyData, 
						 IN_LENGTH_SHORT_Z const int keyDataLength,
						 IN_HANDLE_OPT \
							const CRYPT_CONTEXT iServerKeyTemplate,
						 IN_ENUM_OPT( CRYPT_ECCCURVE ) \
							const CRYPT_ECCCURVE_TYPE eccCurve,
						 IN_BOOL const BOOLEAN isTLSLTS );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int readSupportedGroups( INOUT_PTR STREAM *stream, 
						 INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo, 
						 IN_LENGTH_SHORT_Z const int extLength,
						 OUT_BOOL BOOLEAN *extErrorInfoSet );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeSupportedGroups( INOUT_PTR STREAM *stream,
						  const SESSION_INFO *sessionInfoPtr );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int getTLSGroupInfo( OUT_PTR_PTR const TLS_GROUP_INFO **groupInfoPtrPtr,
					 OUT_INT_Z int *noGroupInfoEntries );
CHECK_RETVAL_PTR \
const TLS_GROUP_INFO *getTLSGroupInfoEntry( IN_ENUM( TLS_GROUP ) \
												const TLS_GROUP_TYPE groupType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \
int completeTLSKeyex( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					  INOUT_PTR STREAM *stream, 
					  IN_BOOL const BOOLEAN isServer,
					  IN_BOOL const BOOLEAN isTLSLTS,
					  IN_BOOL const BOOLEAN isTLS13,
					  INOUT_PTR ERROR_INFO *errorInfo );

/* Prototypes for functions in tls_keymgmt.c */

STDC_NONNULL_ARG( ( 1 ) ) \
void destroySecurityContextsTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int initHandshakeCryptInfo( INOUT_PTR SESSION_INFO *sessionInfoPtr,
							INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
STDC_NONNULL_ARG( ( 1 ) ) \
void destroyHandshakeCryptInfo( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initSecurityContextsTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr );
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int cloneHashContext( IN_HANDLE const CRYPT_CONTEXT hashContext,
					  OUT_HANDLE_OPT CRYPT_CONTEXT *clonedHashContext );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int createSharedPremasterSecret( OUT_BUFFER( premasterSecretMaxLength, \
											 *premasterSecretLength ) \
									void *premasterSecret, 
								 IN_LENGTH_SHORT_MIN( 16 ) \
									const int premasterSecretMaxLength, 
								 OUT_LENGTH_BOUNDED_Z( premasterSecretMaxLength ) \
									int *premasterSecretLength,
								 IN_BUFFER( sharedSecretLength ) \
									const void *sharedSecret, 
								 IN_LENGTH_TEXT const int sharedSecretLength,
								 IN_BUFFER_OPT( otherSecretLength ) \
									const void *otherSecret, 
								 IN_LENGTH_PKC_Z const int otherSecretLength,
								 IN_BOOL const BOOLEAN isEncodedValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int wrapPremasterSecret( INOUT_PTR SESSION_INFO *sessionInfoPtr,
						 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						 OUT_BUFFER( dataMaxLength, *dataLength ) void *data, 
						 IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength, 
						 OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \
							int *dataLength );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int unwrapPremasterSecret( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						   IN_BUFFER( dataLength ) const void *data, 
						   IN_LENGTH_SHORT_MIN( 16 ) const int dataLength );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int initCryptoTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr,
				   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
				   OUT_BUFFER_FIXED( masterSecretSize ) void *masterSecret,
				   IN_LENGTH_SHORT_MIN( 16 ) const int masterSecretSize,
				   IN_BOOL const BOOLEAN isClient,
				   IN_BOOL const BOOLEAN isResumedSession );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int loadExplicitIV( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					INOUT_PTR STREAM *stream, 
					OUT_INT_SHORT_Z int *ivLength );
#ifdef USE_EAP
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int addDerivedKeydata( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					   IN_BUFFER( masterSecretSize ) const void *masterSecret,
					   IN_LENGTH_SHORT_MIN( 16 ) const int masterSecretSize,
					   IN_ENUM( CRYPT_SUBPROTOCOL ) \
							const CRYPT_SUBPROTOCOL_TYPE type );
#endif /* USE_EAP */

/* Prototypes for functions in tls_rd.c */

#ifdef USE_ERRMSGS
CHECK_RETVAL_PTR_NONNULL \
const char *getTLSPacketName( IN_BYTE const int packetType );
CHECK_RETVAL_PTR_NONNULL \
const char *getTLSHSPacketName( IN_BYTE const int packetType );
#else
  #define getTLSPacketName( x )		"<Unknown>"
  #define getTLSHSPacketName( x )	"<Unknown>"
#endif /* USE_ERRMSGS */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int processVersionInfo( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						INOUT_PTR STREAM *stream, 
						OUT_OPT int *clientVersion,
						IN_BOOL const BOOLEAN generalCheckOnly );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int checkPacketHeaderTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						  INOUT_PTR STREAM *stream, 
						  OUT_DATALENGTH_Z int *packetLength );
CHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int checkHSPacketHeader( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						 INOUT_PTR STREAM *stream, 
						 OUT_DATALENGTH_Z int *packetLength, 
						 IN_RANGE( TLS_HAND_FIRST, \
								   TLS_HAND_LAST ) const int packetType, 
						 IN_LENGTH_SHORT_Z const int minSize );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int unwrapPacketTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					 INOUT_BUFFER( dataMaxLength, \
								   *dataLength ) void *data, 
					 IN_DATALENGTH const int dataMaxLength, 
					 OUT_DATALENGTH_Z int *dataLength,
					 IN_RANGE( TLS_PACKETTYPE_FIRST, \
							   TLS_PACKETTYPE_LAST ) const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int readHSPacketTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					 INOUT_PTR_OPT TLS_HANDSHAKE_INFO *handshakeInfo, 
					 OUT_DATALENGTH_Z int *packetLength, 
					 IN_RANGE( TLS_MSG_FIRST, \
							   TLS_MSG_LAST_SPECIAL ) const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int refreshHSStream( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );

/* Prototypes for functions in tls_sign.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int checkCertWhitelist( INOUT_PTR SESSION_INFO *sessionInfoPtr,
						IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
						OUT_BOOL BOOLEAN *isInWhitelist,
						IN_BOOL const BOOLEAN isServer );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int createSessionHash( IN_PTR const SESSION_INFO *sessionInfoPtr,
					   INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
STDC_NONNULL_ARG( ( 1 ) ) \
void destroySessionHash( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int createCertVerify( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					  INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					  INOUT_PTR STREAM *stream );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int checkCertVerify( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					 INOUT_PTR STREAM *stream, 
					 IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
						const int sigLength );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int createKeyexSignature( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						  INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						  INOUT_PTR STREAM *stream, 
						  IN_BUFFER( keyDataLength ) const void *keyData, 
						  IN_LENGTH_SHORT const int keyDataLength );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 7 ) ) \
int checkKeyexSignature( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
						 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						 INOUT_PTR STREAM *stream, 
						 IN_BUFFER( keyDataLength ) const void *keyData, 
						 IN_LENGTH_SHORT const int keyDataLength,
						 IN_BOOL const BOOLEAN isECC,
						 INOUT_PTR ERROR_INFO *errorInfo );

/* Prototypes for functions in tls_suites.c */

#ifndef CONFIG_SUITEB

CHECK_RETVAL \
int getCipherSuiteInfo( OUT_PTR_PTR \
							const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,
						OUT_INT_Z int *noSuiteEntries );
#else

#define getCipherSuiteInfo( infoPtr, noEntries, isServer ) \
		getSuiteBCipherSuiteInfo( infoPtr, noEntries, isServer, suiteBinfo )

CHECK_RETVAL \
int getSuiteBCipherSuiteInfo( OUT_PTR_PTR \
								const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,
							  OUT_INT_Z int *noSuiteEntries,
							  IN_BOOL const BOOLEAN isServer,
							  IN_FLAGS_Z( TLS ) const int suiteBinfo );

#endif /* CONFIG_SUITEB */

/* Prototypes for functions in tls_svr.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int convertSNISessionID( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						 OUT_BUFFER_FIXED( idBufferLength ) BYTE *idBuffer,
						 IN_LENGTH_FIXED( SESSIONID_SIZE ) \
							const int idBufferLength );

/* Prototypes for functions in tls_wr.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int wrapPacketTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
				   INOUT_PTR STREAM *stream, 
				   IN_LENGTH_Z const int offset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int sendPacketTLS( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
				   INOUT_PTR STREAM *stream, 
				   IN_BOOL const BOOLEAN sendOnly );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int openPacketStreamTLS( OUT_PTR STREAM *stream, 
						 IN_PTR const SESSION_INFO *sessionInfoPtr, 
						 IN_DATALENGTH_OPT const int bufferSize, 
						 IN_RANGE( TLS_MSG_FIRST, \
								   TLS_MSG_LAST ) const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int continuePacketStreamTLS( INOUT_PTR STREAM *stream, 
							 IN_PTR const SESSION_INFO *sessionInfoPtr, 
							 IN_RANGE( TLS_MSG_FIRST, \
									   TLS_MSG_LAST ) const int packetType,
							 OUT_LENGTH_SHORT_Z int *packetOffset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int completePacketStreamTLS( INOUT_PTR STREAM *stream, 
							 IN_LENGTH_Z const int offset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int continueHSPacketStream( INOUT_PTR STREAM *stream, 
							IN_RANGE( TLS_HAND_FIRST, \
									  TLS_HAND_LAST ) const int packetType,
							OUT_LENGTH_SHORT_Z int *packetOffset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int completeHSPacketStream( INOUT_PTR STREAM *stream, 
							IN_LENGTH const int offset );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int processAlert( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
				  IN_BUFFER( headerLength ) const void *header, 
				  IN_DATALENGTH const int headerLength,
				  OUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo );
STDC_NONNULL_ARG( ( 1 ) ) \
void sendCloseAlert( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					 IN_BOOL const BOOLEAN alertReceived );
STDC_NONNULL_ARG( ( 1 ) ) \
void sendHandshakeFailAlert( INOUT_PTR SESSION_INFO *sessionInfoPtr,
							 IN_RANGE( TLS_ALERT_FIRST, \
									   TLS_ALERT_LAST ) const int alertType );
#ifdef USE_TLS13

/* Prototypes for functions in tls13_crypt.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initCryptGCMTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					   IN_BOOL const BOOLEAN isRead );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createSessionHashTLS13( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						    IN_HANDLE const CRYPT_CONTEXT iHashContext,
							IN_BOOL const BOOLEAN isServerVerify );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int createFinishedTLS13( OUT_BUFFER( finishedValueMaxLen, \
									 *finishedValueLen ) \
							void *finishedValue,
						 IN_LENGTH_SHORT_MIN( 20 ) \
							const int finishedValueMaxLen,
						 OUT_LENGTH_BOUNDED_SHORT_Z( finishedValueMaxLen ) \
							 int *finishedValueLen,
						 IN_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
						 IN_HANDLE const CRYPT_CONTEXT iHashContext,
						 IN_BOOL const BOOLEAN isServerFinished );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int loadHSKeysTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr,
					 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int loadAppdataKeysTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr,
						  INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );

/* Prototypes for functions in tls13_hs.c */

STDC_NONNULL_ARG( ( 1 ) ) \
void initProcessingTLS13( TLS_HANDSHAKE_INFO *handshakeInfo,
						  IN_BOOL const BOOLEAN isServer );

/* Prototypes for functions in tls13_keyex.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createKeyexContextsTLS13( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int readKeyexTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					INOUT_PTR STREAM *stream, 
					IN_LENGTH_SHORT_Z const int extLength,
					OUT_BOOL BOOLEAN *extErrorInfoSet );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeKeyexTLS13( INOUT_PTR STREAM *stream,
					 INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo,
					 IN_BOOL const BOOLEAN isServer );

/* Prototypes for functions in tls_rd.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
int unwrapPacketTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					   INOUT_BUFFER( dataMaxLength, \
									 *dataLength ) void *data, 
					   IN_DATALENGTH const int dataMaxLength, 
					   OUT_DATALENGTH_Z int *dataLength,
					   OUT_RANGE( TLS_MSG_NONE, TLS_MSG_LAST ) \
							int *actualPacketType,
					   IN_RANGE( TLS_PACKETTYPE_FIRST, \
								 TLS_PACKETTYPE_LAST ) \
							const int packetType );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int processAlertTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					   IN_BUFFER( dataLength ) const void *data, 
					   IN_DATALENGTH const int dataLength,
					   OUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo );

/* Prototypes for functions in tls_wr.c */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int wrapPacketTLS13( INOUT_PTR SESSION_INFO *sessionInfoPtr, 
					 INOUT_PTR STREAM *stream, 
					 IN_LENGTH_Z const int offset,
					 IN_RANGE( TLS_HAND_FIRST, TLS_HAND_LAST ) \
						const int packetType );
#endif /* USE_TLS13 */

/* Prototypes for session mapping functions */

STDC_NONNULL_ARG( ( 1 ) ) \
void initTLSclientProcessing( INOUT_PTR TLS_HANDSHAKE_INFO *handshakeInfo );
STDC_NONNULL_ARG( ( 1 ) ) \
void initTLSserverProcessing( TLS_HANDSHAKE_INFO *handshakeInfo );

#endif /* USE_TLS */

#endif /* _TLS_DEFINED */
