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

📄 ssl.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:

	/* Initialise the handshake info and begin the handshake */
	status = initHandshakeInfo( sessionInfoPtr, &handshakeInfo, isServer );
	if( cryptStatusOK( status ) )
		status = handshakeInfo.beginHandshake( sessionInfoPtr,
											   &handshakeInfo );
	if( status == OK_SPECIAL )
		resumedSession = TRUE;
	else
		{
		if( cryptStatusError( status ) )
			return( abortStartup( sessionInfoPtr, &handshakeInfo, FALSE,
								  status ) );
		}

	/* Exchange keys with the server */
	if( !resumedSession )
		{
		status = handshakeInfo.exchangeKeys( sessionInfoPtr,
											 &handshakeInfo );
		if( cryptStatusError( status ) )
			return( abortStartup( sessionInfoPtr, &handshakeInfo, TRUE,
								  status ) );
		}

	/* Complete the handshake */
	status = completeHandshake( sessionInfoPtr, &handshakeInfo, !isServer,
								resumedSession );
	destroyHandshakeInfo( &handshakeInfo );
	if( cryptStatusError( status ) )
		return( abortStartup( sessionInfoPtr, NULL, TRUE, status ) );

	return( CRYPT_OK );
	}

static int clientStartup( SESSION_INFO *sessionInfoPtr )
	{
	/* Complete the handshake using the common client/server code */
	return( commonStartup( sessionInfoPtr, FALSE ) );
	}

static int serverStartup( SESSION_INFO *sessionInfoPtr )
	{
#if 0	/* Old PSK mechanism */
	/* Clear any user name/password information that may be present from
	   a previous session or from the manual addition of keys to the session
	   cache */
	resetSessionInfo( sessionInfoPtr->attributeList, 
					  CRYPT_SESSINFO_USERNAME );
	resetSessionInfo( sessionInfoPtr->attributeList,
					  CRYPT_SESSINFO_PASSWORD );
#endif /* 0 */

	/* Complete the handshake using the common client/server code */
	return( commonStartup( sessionInfoPtr, TRUE ) );
	}

/****************************************************************************
*																			*
*						Control Information Management Functions			*
*																			*
****************************************************************************/

static int getAttributeFunction( SESSION_INFO *sessionInfoPtr,
								 void *data, const CRYPT_ATTRIBUTE_TYPE type )
	{
	CRYPT_CERTIFICATE *certPtr = ( CRYPT_CERTIFICATE * ) data;
	CRYPT_CERTIFICATE iCryptCert = isServer( sessionInfoPtr ) ? \
		sessionInfoPtr->iKeyexAuthContext : sessionInfoPtr->iKeyexCryptContext;

	assert( type == CRYPT_SESSINFO_RESPONSE );

	/* If we didn't get a client/server cert there's nothing to return */
	if( iCryptCert == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Return the information to the caller */
	krnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );
	*certPtr = iCryptCert;
	return( CRYPT_OK );
	}

#if 0	/* Old PSK mechanism */

static int setAttributeFunction( SESSION_INFO *sessionInfoPtr,
								 const void *data,
								 const CRYPT_ATTRIBUTE_TYPE type )
	{
	const ATTRIBUTE_LIST *userNamePtr = \
				findSessionInfo( sessionInfoPtr->attributeList,
								 CRYPT_SESSINFO_USERNAME );
	BYTE premasterSecret[ ( ( UINT16_SIZE + CRYPT_MAX_TEXTSIZE ) * 2 ) + 8 ];
	BYTE sessionID[ SESSIONID_SIZE + 8 ];
	int uniqueID, premasterSecretLength, status;

	assert( type == CRYPT_SESSINFO_USERNAME || \
			type == CRYPT_SESSINFO_PASSWORD );

	/* At the moment only the server maintains a true session cache, so if
	   it's a client session we return without any further checking, there
	   can never be a duplicate entry in this case */
	if( !isServer( sessionInfoPtr ) )
		return( CRYPT_OK );

	/* If we're setting the password, we have to have a session ID present to
	   set it for */
	if( type == CRYPT_SESSINFO_PASSWORD && userNamePtr == NULL )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME,
					  CRYPT_ERRTYPE_ATTR_ABSENT );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Wait for any async network driver binding to complete.  This is
	   required because the session cache is initialised as part of the
	   asynchronous startup (since it's tied to the session object class
	   rather than a particular session object), so we have to wait until
	   this has completed before we can access it */
	krnlWaitSemaphore( SEMAPHORE_DRIVERBIND );

	/* Format the session ID in the appropriate manner and check whether it's
	   present in the cache */
	memset( sessionID, 0, SESSIONID_SIZE );
	memcpy( sessionID, userNamePtr->value,
			min( userNamePtr->valueLength, SESSIONID_SIZE ) );
	uniqueID = findSessionCacheEntryID( sessionID, SESSIONID_SIZE );

	/* If we're adding or deleting a user name, check whether something
	   identified by the name is present in the cache */
	if( type == CRYPT_SESSINFO_USERNAME )
		{
		if( data != NULL )
			{
			/* User name add, presence is an error */
			if( uniqueID )
				{
				setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME,
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				return( CRYPT_ERROR_INITED );
				}
			}
		else
			{
			/* User name delete, absence is an error */
			if( !uniqueID )
				{
				setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME,
							  CRYPT_ERRTYPE_ATTR_ABSENT );
				return( CRYPT_ERROR_NOTINITED );
				}
			deleteSessionCacheEntry( uniqueID );
			}
		return( CRYPT_OK );
		}

	/* Create the premaster secret from the user-supplied password */
	status = createSharedPremasterSecret( premasterSecret,
										  &premasterSecretLength,
										  sessionInfoPtr );
	if( cryptStatusError( status ) )
		retExt( status,
				( status, SESSION_ERRINFO, 
				  "Couldn't create SSL master secret from shared "
				  "secret/password value" ) );

	/* Add the entry to the session cache */
	addSessionCacheEntry( sessionID, SESSIONID_SIZE, premasterSecret,
						  premasterSecretLength, TRUE );
	zeroise( premasterSecret, SSL_SECRET_SIZE );
	return( CRYPT_OK );
	}
#endif /* 0 */

/****************************************************************************
*																			*
*								Get/Put Data Functions						*
*																			*
****************************************************************************/

/* Read/write data over the SSL link */

static int readHeaderFunction( SESSION_INFO *sessionInfoPtr,
							   READSTATE_INFO *readInfo )
	{
	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
	STREAM stream;
	int packetLength, status;

	/* Clear return value */
	*readInfo = READINFO_NONE;

	/* Read the SSL packet header data */
	status = readFixedHeader( sessionInfoPtr, sslInfo->headerBuffer, 
							  sessionInfoPtr->receiveBufStartOfs );
	if( cryptStatusError( status ) )
		{
		/* OK_SPECIAL means that we got a soft timeout before the entire 
		   header was read */
		return( ( status == OK_SPECIAL ) ? 0 : status );
		}

	/* Since data errors are always fatal, we make all errors fatal until
	   we've finished handling the header */
	*readInfo = READINFO_FATAL;

	/* Check for an SSL alert message */
	if( sslInfo->headerBuffer[ 0 ] == SSL_MSG_ALERT )
		return( processAlert( sessionInfoPtr, sslInfo->headerBuffer, 
							  sessionInfoPtr->receiveBufStartOfs ) );

	/* Process the header data */
	sMemConnect( &stream, sslInfo->headerBuffer, 
				 sessionInfoPtr->receiveBufStartOfs );
	status = checkPacketHeaderSSL( sessionInfoPtr, &stream, &packetLength );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* Determine how much data we'll be expecting */
	sessionInfoPtr->pendingPacketLength = \
		sessionInfoPtr->pendingPacketRemaining = packetLength;

	/* Indicate that we got the header */
	*readInfo = READINFO_NOOP;
	return( OK_SPECIAL );
	}

static int processBodyFunction( SESSION_INFO *sessionInfoPtr,
								READSTATE_INFO *readInfo )
	{
	int length, status;

	assert( sessionInfoPtr->pendingPacketLength > 0 );
	assert( sessionInfoPtr->receiveBufPos + \
				sessionInfoPtr->pendingPacketLength <= \
			sessionInfoPtr->receiveBufEnd );
	assert( sessionInfoPtr->receiveBufEnd <= sessionInfoPtr->receiveBufSize );

	/* All errors processing the payload are fatal */
	*readInfo = READINFO_FATAL;

	/* Unwrap the payload */
	status = unwrapPacketSSL( sessionInfoPtr, 
							  sessionInfoPtr->receiveBuffer + \
								sessionInfoPtr->receiveBufPos, 
							  sessionInfoPtr->pendingPacketLength, 
							  &length, SSL_MSG_APPLICATION_DATA );
	if( cryptStatusError( status ) )
		return( status );

	/* Adjust the data size indicators to account for the stripped padding
	   and MAC info */
	sessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos + length;
	sessionInfoPtr->receiveBufPos = sessionInfoPtr->receiveBufEnd;
	sessionInfoPtr->pendingPacketLength = 0;
	assert( sessionInfoPtr->receiveBufEnd <= sessionInfoPtr->receiveBufSize );

	/* If we only got a partial packet, let the caller know that they should
	   try again */
	if( length < 1 )
		{
		*readInfo = READINFO_PARTIAL;
		return( OK_SPECIAL );
		}
	*readInfo = READINFO_NONE;
	return( length );
	}

static int preparePacketFunction( SESSION_INFO *sessionInfoPtr )
	{
	STREAM stream;
	int status;

	assert( sessionInfoPtr->sendBufPos - \
			sessionInfoPtr->sendBufStartOfs > 0 && \
			sessionInfoPtr->sendBufPos - \
			sessionInfoPtr->sendBufStartOfs <= MAX_PACKET_SIZE );
	assert( !( sessionInfoPtr->flags & SESSION_SENDCLOSED ) );
	assert( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_ALERTSENT ) );

	/* Wrap up the payload ready for sending.  Since this is wrapping in-
	   place data we first open a write stream to add the header, then open
	   a read stream covering the full buffer in preparation for wrapping
	   the packet.  Note that we connect the stream to the full send buffer
	   (bufSize) even though we only advance the current stream position to
	   the end of the stream contents (bufPos), since the packet-wrapping
	   process adds further data to the stream that exceeds the current
	   stream position */
	status = openPacketStreamSSL( &stream, sessionInfoPtr, 0,
								  SSL_MSG_APPLICATION_DATA );
	if( cryptStatusError( status ) )
		return( status );
	sMemDisconnect( &stream );
	sMemConnect( &stream, sessionInfoPtr->sendBuffer,
				 sessionInfoPtr->sendBufSize );
	sSkip( &stream, sessionInfoPtr->sendBufPos );
	status = wrapPacketSSL( sessionInfoPtr, &stream, 0 );
	if( cryptStatusOK( status ) )
		status = stell( &stream );
	sMemDisconnect( &stream );

	return( status );
	}

/****************************************************************************
*																			*
*							Session Access Routines							*
*																			*
****************************************************************************/

int setAccessMethodSSL( SESSION_INFO *sessionInfoPtr )
	{
	static const ALTPROTOCOL_INFO altProtocolInfo = {
		/* SSL tunnelled via an HTTP proxy.  This is a special case in that
		   the initial connection is made using HTTP, but subsequent
		   communications are via a direct TCP/IP connection that goes
		   through the proxy */
		STREAM_PROTOCOL_TCPIP,		/* Alt.protocol type */
		"https://", 8,				/* Alt.protocol URI type */
		80,							/* Alt.protocol port */
		0,							/* Protocol flags to replace */
		SESSION_USEHTTPTUNNEL		/* Alt.protocol flags */
		};
	static const PROTOCOL_INFO protocolInfo = {
		/* General session information */
		FALSE,						/* Request-response protocol */
		SESSION_NONE,				/* Flags */
		SSL_PORT,					/* SSL port */
		SESSION_NEEDS_PRIVKEYSIGN,	/* Client attributes */
			/* The client private key is optional but if present, it has to
			   be signature-capable */
		SESSION_NEEDS_PRIVATEKEY |	/* Server attributes */
			SESSION_NEEDS_PRIVKEYCRYPT | \
			SESSION_NEEDS_PRIVKEYCERT | \
			SESSION_NEEDS_KEYORPASSWORD,
			/* In theory we need neither a private key nor a password 
			   because the caller can provide the password during the
			   handshake in response to a CRYPT_ENVELOPE_RESOURCE
			   notification, however this facility is likely to be 
			   barely-used in comparison to users forgetting to add server
			   certs and the like, so we require some sort of server-side
			   key set in advance */
		SSL_MINOR_VERSION_TLS,		/* TLS 1.0 */
			SSL_MINOR_VERSION_SSL, SSL_MINOR_VERSION_TLS12,
			/* We default to TLS 1.0 rather than TLS 1.1 or 1.2 because it's 
			   likely that support for the latter will be hit-and-miss for 
			   some time */

		/* Protocol-specific information */
		EXTRA_PACKET_SIZE + \
			MAX_PACKET_SIZE,		/* Send/receive buffer size */
		SSL_HEADER_SIZE,			/* Payload data start */
			/* This may be adjusted during the handshake if we're talking
			   TLS 1.1, which prepends extra data in the form of an IV to
			   the payload */
		MAX_PACKET_SIZE,			/* (Default) maximum packet size */
		&altProtocolInfo			/* Alt.transport protocol */
		};

	/* Set the access method pointer

⌨️ 快捷键说明

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