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

📄 ssl_svr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
		writeUint16( stream, 2 );
		swrite( stream, "\x30\x00", 2 );
		status = completeHSPacketStream( stream, packetOffset );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}

	/*	...
		byte		ID = SSL_HAND_SERVER_HELLODONE
		uint24		len = 0 */
	packetOffset = \
		continueHSPacketStream( stream, SSL_HAND_SERVER_HELLODONE );
	status = completeHSPacketStream( stream, packetOffset );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}

	/* Send the combined server packets to the client.  We perform the dual 
	   MAC'ing of the packets in between the network ops where it's 
	   effectively free */
	status = sendPacketSSL( sessionInfoPtr, stream, FALSE );
	if( cryptStatusOK( status ) )
		status = dualMacDataWrite( handshakeInfo, stream );
	sMemDisconnect( stream );
	return( status );
	}

/* Exchange keys with the client */

int exchangeServerKeys( SESSION_INFO *sessionInfoPtr, 
						SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	STREAM *stream = &handshakeInfo->stream;
	int length, status;

	/* Read the response from the client and, if we're expecting a client 
	   cert, make sure that it's present */
	status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
							  SSL_MSG_HANDSHAKE );
	if( cryptStatusError( status ) )
		return( status );
	sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
	if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
		{
		MESSAGE_KEYMGMT_INFO getkeyInfo;
		MESSAGE_DATA msgData;
		BYTE certID[ KEYID_SIZE + 8 ];

		/* Process the client cert chain */
		status = readSSLCertChain( sessionInfoPtr, handshakeInfo,
								   stream, &sessionInfoPtr->iKeyexAuthContext, 
								   TRUE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}

		/* Make sure that the client cert is present in our cert store.  
		   Since we've already got a copy of the cert, we only do a presence 
		   check rather than actually fetching the cert */
		setMessageData( &msgData, certID, KEYID_SIZE );
		status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, 
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_CERTINFO_FINGERPRINT_SHA );
		if( cryptStatusOK( status ) )
			{
			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, certID, 
								   KEYID_SIZE, NULL, 0, 
								   KEYMGMT_FLAG_CHECK_ONLY );
			status = krnlSendMessage( sessionInfoPtr->cryptKeyset, 
									  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
										  KEYMGMT_ITEM_PUBLICKEY );
			}
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			retExt( CRYPT_ERROR_INVALID,
					( CRYPT_ERROR_INVALID, SESSION_ERRINFO, 
					  "Client certificate is not trusted for "
					  "authentication purposes" ) );
			}

		/* Read the next packet(s) if necessary */
		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Process the client key exchange packet:

		byte		ID = SSL_HAND_CLIENT_KEYEXCHANGE
		uint24		len
	   DH:
		uint16		yLen
		byte[]		y
	   PSK:
		uint16		userIDLen
		byte[]		userID 
	   RSA:
	  [ uint16		encKeyLen - TLS only ]
		byte[]		rsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */
	status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
								  SSL_HAND_CLIENT_KEYEXCHANGE, 
								  UINT16_SIZE + 1 );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}
	if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
		{
		KEYAGREE_PARAMS keyAgreeParams;

		memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
		status = readInteger16UChecked( stream, keyAgreeParams.publicValue,
										&keyAgreeParams.publicValueLen,
										MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );

			/* Some misconfigured clients may use very short keys, we 
			   perform a special-case check for these and return a more 
			   specific message than the generic bad-data */
			if( status == CRYPT_ERROR_NOSECURE )
				{
				retExt( CRYPT_ERROR_NOSECURE,
						( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, 
						  "Insecure key used in key exchange" ) );
				}

			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Invalid DH key agreement data" ) );
			}

		/* Perform phase 2 of the DH key agreement */
		status = krnlSendMessage( handshakeInfo->dhContext,
								  IMESSAGE_CTX_DECRYPT, &keyAgreeParams, 
								  sizeof( KEYAGREE_PARAMS ) );
		if( cryptStatusError( status ) )
			{
			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
			sMemDisconnect( stream );
			return( status );
			}
		memcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,
				keyAgreeParams.wrappedKeyLen );
		handshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;
		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
		}
	else
		{
		if( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )
			{
			const ATTRIBUTE_LIST *attributeListPtr;
			BYTE userID[ CRYPT_MAX_TEXTSIZE + 8 ];

			/* Read the client user ID and make sure that it's a valid 
			   user.  Handling non-valid users is somewhat problematic,
			   we can either bail out immediately or invent a fake 
			   password for the (non-)user and continue with that.  The
			   problem with this is that it doesn't really help hide 
			   whether the user is valid or not because we're still 
			   vulnerable to a timing attack because it takes considerably 
			   longer to generate the fake password than it does to read a 
			   fixed password string from memory, so an attacker can tell 
			   from the timing whether the username is valid or not.  
			   Because of this we don't try and fake out the valid/invalid 
			   user name indication but just exit immediately if an invalid
			   name is found */
			length = readUint16( stream );
			if( length < 1 || length > CRYPT_MAX_TEXTSIZE || \
				cryptStatusError( sread( stream, userID, length ) ) )
				{
				sMemDisconnect( stream );
				retExt( CRYPT_ERROR_BADDATA,
						( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
						  "Invalid client user ID" ) );
				}
			attributeListPtr = \
				findSessionInfoEx( sessionInfoPtr->attributeList,
								   CRYPT_SESSINFO_USERNAME, userID, length );
			if( attributeListPtr == NULL )
				{
				sMemDisconnect( stream );
				retExt( CRYPT_ERROR_WRONGKEY,
						( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, 
						  "Unknown user name '%s'", 
						  sanitiseString( userID, CRYPT_MAX_TEXTSIZE, 
										  length ) ) );
				}

			/* Select the attribute with the user ID and move on to the
			   associated password */
			sessionInfoPtr->attributeListCurrent = \
								( ATTRIBUTE_LIST * ) attributeListPtr;
			attributeListPtr = attributeListPtr->next;
			assert( attributeListPtr->attributeID == CRYPT_SESSINFO_PASSWORD );

			/* Create the shared premaster secret from the user password */
			status = createSharedPremasterSecret( \
									handshakeInfo->premasterSecret,
									CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,
									&handshakeInfo->premasterSecretSize, 
									attributeListPtr );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( stream );
				retExt( status, 
						( status, SESSION_ERRINFO, 
						  "Couldn't create SSL master secret from shared "
						  "secret/password value" ) );
				}
			}
		else
			{
			BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];

			if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
				{
				/* The original Netscape SSL implementation didn't provide a 
				   length for the encrypted key and everyone copied that so 
				   it became the de facto standard way to do it (Sic faciunt 
				   omnes.  The spec itself is ambiguous on the topic).  This 
				   was fixed in TLS (although the spec is still ambigous) so 
				   the encoding differs slightly between SSL and TLS */
				if( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE || \
					cryptStatusError( sread( stream, wrappedKey, length ) ) )
					status = CRYPT_ERROR_BADDATA;
				}
			else
				{
				status = readInteger16UChecked( stream, wrappedKey, &length, 
												MIN_PKCSIZE, 
												CRYPT_MAX_PKCSIZE );
				}
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( stream );

				/* Some misconfigured clients may use very short keys, we 
				   perform a special-case check for these and return a more 
				   specific message than the generic bad-data */
				if( status == CRYPT_ERROR_NOSECURE )
					{
					retExt( CRYPT_ERROR_NOSECURE,
							( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, 
							  "Insecure key used in key exchange" ) );
					}

				retExt( CRYPT_ERROR_BADDATA,
						( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
						  "Invalid RSA encrypted key data" ) );
				}

			/* Decrypt the pre-master secret */
			status = unwrapPremasterSecret( sessionInfoPtr, handshakeInfo,
											wrappedKey, length );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( stream );
				return( status );
				}
			}
		}

	/* If we're expecting a client cert, process the client cert verify */
	if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
		{
		/* Read the next packet(s) if necessary */
		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
		if( cryptStatusError( status ) )
			return( status );

		/* Process the client cert verify packet:

			byte		ID = SSL_HAND_CLIENT_CERTVERIFY
			uint24		len
			byte[]		signature */
		status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
									  SSL_HAND_CLIENT_CERTVERIFY, 
									  MIN_PKCSIZE );
		if( cryptStatusOK( status ) )
			status = checkCertVerify( sessionInfoPtr, handshakeInfo, stream, 
									  length );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}
	sMemDisconnect( stream );

	return( CRYPT_OK );
	}

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

void initSSLserverProcessing( SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	handshakeInfo->beginHandshake = beginServerHandshake;
	handshakeInfo->exchangeKeys = exchangeServerKeys;
	}
#endif /* USE_SSL */

⌨️ 快捷键说明

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