⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	sessionInfoPtr->authBlocksize = cipherSuiteInfo[ currentSuiteIndex ].macBlockSize;
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
							  sessionInfoPtr->cryptAlgo );
	if( cryptStatusError( status ) )
		return( status );
	sessionInfoPtr->cryptBlocksize = queryInfo.blockSize;

	return( CRYPT_OK );
	}

/* Process RFC 3546 TLS extensions:

	uint16		extListLen		| RFC 3546
		uint16	extType
		uint16	extLen
		byte[]	extData */

static int processExtensions( SESSION_INFO *sessionInfoPtr, STREAM *stream,
							  const int length )
	{
	int endPos = stell( stream ) + length, extListLen, iterationCount = 0;

	/* Read the extension header and make sure that it's valid */
	if( length < UINT16_SIZE + UINT16_SIZE + UINT16_SIZE + 1 )
		{
		retExt( CRYPT_ERROR_BADDATA,
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "TLS hello contains %d bytes extraneous data", length ) );
		}
	extListLen = readUint16( stream );
	if( cryptStatusError( extListLen ) || \
		extListLen != length - UINT16_SIZE )
		{
		retExt( CRYPT_ERROR_BADDATA,
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "Invalid TLS extension data length %d, should be %d",
				  extListLen, length - UINT16_SIZE ) );
		}

	/* Process the extensions */
	while( stell( stream ) < endPos && \
		   iterationCount++ < FAILSAFE_ITERATIONS_MED )
		{
		int type, extLen, value;

		/* Get the next extension */
		type = readUint16( stream );
		extLen = readUint16( stream );
		if( cryptStatusError( extLen ) || extLen < 1 )
			{
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Invalid TLS extension list item header" ) );
			}

		/* Process the extension data.  The internal structure of some of
		   these things shows that they were created by ASN.1 people... */
		switch( type )
			{
			case TLS_EXT_SERVER_NAME:
				{
				int listLen;

				/* Response: Send zero-length reply to peer:

					uint16		listLen
						byte	nameType
						uint16	nameLen
						byte[]	name */
				listLen = readUint16( stream );
				if( cryptStatusError( listLen ) || \
					listLen != extLen - UINT16_SIZE || \
					listLen < 1 + UINT16_SIZE || \
					cryptStatusError( sSkip( stream, listLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS host name extension" ) );
					}
				/* Parsing of further SEQUENCE OF SEQUENCE data omitted */
				break;
				}

			case TLS_EXT_MAX_FRAGMENT_LENTH:
				{
/*				static const int fragmentTbl[] = \
						{ 0, 512, 1024, 2048, 4096, 8192, 16384, 16384 }; */

				/* Response: If frag-size == 3...5, send same to peer.
				   Note that we also allow a frag-size value of 5, which
				   isn't specified in the standard but should probably be
				   present since it would otherwise result in a missing
				   value between 4096 and the default of 16384:

					byte		fragmentLength */
				value = sgetc( stream );
				if( cryptStatusError( value ) || \
					extLen != 1 || value < 1 || value > 5 )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS fragment length extension" ) );
					}
/*				sessionInfoPtr->maxPacketSize = fragmentTbl[ value ]; */
				break;
				}

			case TLS_EXT_CLIENT_CERTIFICATE_URL:
				/* Response: Ignore.  This dangerous extension allows a
				   client to direct a server to grope around in arbitrary
				   external (and untrusted) URLs trying to locate certs,
				   provinding a convenient mechanism for bounce attacks
				   and all manner of similar firewall/trusted-host
				   subversion problems:

					byte		chainType
					uint16		urlAndHashList
						uint16	urlLen
						byte[]	url
						byte	hashPresent
						byte[20] hash	- If hashPresent flag set */
				if( extLen < 1 + UINT16_SIZE + \
							 UINT16_SIZE + MIN_URL_SIZE + 1 || \
					cryptStatusError( sSkip( stream, extLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS client certificate URL "
							  "extension" ) );
					}
				break;

			case TLS_EXT_TRUSTED_CA_KEYS:
				/* Response: Ignore.  This allows a client to specify which
				   CA certs it trusts, and by extension which server certs
				   it trusts, supposedly to reduce handshake messages in
				   constrained clients.  Since the server usually has only
				   a single cert signed by a single CA, specifying the CAs
				   the client trusts doesn't serve much purpose:

					uint16		caList
						byte	idType
						... */
				if( extLen < UINT16_SIZE + 1 || \
					cryptStatusError( sSkip( stream, extLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS trusted CA extension" ) );
					}
				break;

			case TLS_EXT_TRUNCATED_HMAC:
				/* Truncate the HMAC to a nonstandard 80 bits (rather than
				   the de facto IPsec cargo-cult standard of 96 bits) */
				if( extLen != 0 )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS truncated HMAC extension" ) );
					}
				break;

			case TLS_EXT_STATUS_REQUEST:
				/* Response: Ignore - another bounce-attack enabler, this
				   time on both the server and an OCSP responder:

					byte	statusType
					... */
				if( extLen < 1 || \
					cryptStatusError( sSkip( stream, extLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS status request extension" ) );
					}
				break;

			case TLS_EXT_USER_MAPPING:
				/* Response: Used with a complex RFC 4680 mechanism, ignore
				   until someone actually asks for it:

					byte	mappingLength
					byte[]	mapping */
				if( extLen < 1 + 1 || \
					cryptStatusError( sSkip( stream, extLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS user-mapping extension" ) );
					}
				break;

			default:
				/* Default: Ignore the extension */
				if( cryptStatusError( sSkip( stream, extLen ) ) )
					{
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid TLS extension data for extension "
							  "type %d", type ) );
					}
			}
		}
	if( iterationCount >= FAILSAFE_ITERATIONS_MED )
		{
		retExt( CRYPT_ERROR_OVERFLOW,
				( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, 
				  "Excessive number (%d) of TLS extensions encountered", 
				  iterationCount ) );
		}

	return( CRYPT_OK );
	}

/* Process a session ID */

static int processSessionID( SESSION_INFO *sessionInfoPtr,
							 SSL_HANDSHAKE_INFO *handshakeInfo,
							 STREAM *stream )
	{
	BYTE sessionID[ SESSIONID_SIZE + 8 ];
	const int sessionIDlength = sgetc( stream );
	int status;

	/* Get the session ID info and if it's not one of ours, skip it */
	if( cryptStatusError( sessionIDlength ) || \
		sessionIDlength > MAX_SESSIONID_SIZE )
		{
		retExt( CRYPT_ERROR_BADDATA, 
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "Invalid session ID length %d, should be 0...%d", 
				  sessionIDlength, MAX_SESSIONID_SIZE ) );
		}
	if( sessionIDlength != SESSIONID_SIZE )
		{
		if( sessionIDlength > 0 )
			{
			status = sSkip( stream, sessionIDlength );
			if( cryptStatusError( status ) )
				retExt( CRYPT_ERROR_BADDATA,
						( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
						  "Invalid session ID" ) );
			}
		return( CRYPT_OK );
		}

	/* There's a session ID present, check to make sure that it matches our
	   expectations.  If we're the server the the size is right for it to
	   (potentially) be one of ours, if we're the client we check to see
	   whether it matches what we sent */
	status = sread( stream, sessionID, SESSIONID_SIZE );
	if( cryptStatusError( status ) )
		{
		retExt( CRYPT_ERROR_BADDATA, 
				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
				  "Invalid session ID" ) );
		}
#if 0	/* Old PSK mechanism */
	if( !isServer( sessionInfoPtr ) )
		{
		const ATTRIBUTE_LIST *userNamePtr;
		BYTE formattedSessionID[ SESSIONID_SIZE + 8 ];

		/* If the returned session ID matches the one that we sent,
		   it's a resumed session */
		if( ( userNamePtr = \
				findSessionInfo( sessionInfoPtr->attributeList,
								 CRYPT_SESSINFO_USERNAME ) ) == NULL )
			{
			/* There's no user name present, it can't be a resumed
			   session */
			return( CRYPT_OK );
			}
		memset( formattedSessionID, 0, SESSIONID_SIZE );
		memcpy( formattedSessionID, userNamePtr->value,
				min( userNamePtr->valueLength, SESSIONID_SIZE ) );
		if( memcmp( formattedSessionID, sessionID, SESSIONID_SIZE ) )
			{
			/* The user name doesn't match the returned ID, it's not a
			   resumed session */
			return( CRYPT_OK );
			}
		}
#endif /* 0 */

	/* It's a potentially resumed session, remember the details and let the 
	   caller know */
	memcpy( handshakeInfo->sessionID, sessionID, SESSIONID_SIZE );
	handshakeInfo->sessionIDlength = SESSIONID_SIZE;
	return( OK_SPECIAL );
	}

/* Process the client/server hello:

	byte		ID = SSL_HAND_CLIENT_HELLO / SSL_HAND_SERVER_HELLO
	uint24		len
	byte[2]		version = { 0x03, 0x0n }
	uint32		time		| Client/server nonce
	byte[28]	nonce		|
	byte		sessIDlen	| May receive nonzero len +
	byte[]		sessID		|	<len> bytes data

		Client						Server
	uint16		suiteLen		-
	uint16[]	suites			uint16		suite
	byte		coprLen = 1		-
	byte		copr = 0		byte		copr = 0 */

int processHelloSSL( SESSION_INFO *sessionInfoPtr,
					 SSL_HANDSHAKE_INFO *handshakeInfo,
					 STREAM *stream, const BOOLEAN isServer )
	{
	BOOLEAN potentiallyResumedSession = FALSE;
	int endPos, length, suiteLength = 1, status;

	/* Check the header and version info */
	if( isServer )
		{
		status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
									  SSL_HAND_CLIENT_HELLO,
									  VERSIONINFO_SIZE + SSL_NONCE_SIZE + \
										1 + ( UINT16_SIZE * 2 ) + 1 + 1 );
		}
	else
		{
		status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
									  SSL_HAND_SERVER_HELLO,
									  VERSIONINFO_SIZE + SSL_NONCE_SIZE + \
										1 + UINT16_SIZE + 1 );
		}
	if( cryptStatusError( status ) )
		return( status );
	endPos = stell( stream ) + length;
	status = processVersionInfo( sessionInfoPtr, stream,
								 isServer ? \
									&handshakeInfo->clientOfferedVersion : \
									NULL );
	if( cryptStatusError( status ) )
		return( status );

	/* Process the nonce and session ID */
	status = sread( stream, isServer ? \
						handshakeInfo->clientNonce : 
						handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	if( cryptStatusOK( status ) )
		status = processSessionID( sessionInfoPtr, handshakeInfo, stream );
	if( status == OK_SPECIAL )
		potentiallyResumedSession = TRUE;
	else
		{
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Process the cipher suite information */
	if( isServer )
		{
		/* If we're reading the client hello, the packet contains a
		   selection of suites preceded by a suite count */
		suiteLength = readUint16( stream );
		if( cryptStatusError( suiteLength ) || \
			suiteLength < UINT16_SIZE || ( suiteLength % UINT16_SIZE ) != 0 )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -