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

📄 ssl_cli.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
		byte		ID = SSL_HAND_CERTIFICATE
		uint24		len
		uint24		certLen			| 1...n certs ordered
		byte[]		cert			|   leaf -> root */
	if( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )
		{
		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
		if( cryptStatusError( status ) )
			return( status );
		status = readSSLCertChain( sessionInfoPtr, handshakeInfo, 
							stream, &sessionInfoPtr->iKeyexCryptContext, 
							FALSE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}

	/* Process the optional server keyex:

		byte		ID = SSL_HAND_SERVER_KEYEXCHANGE
		uint24		len
		uint16		dh_pLen
		byte[]		dh_p
		uint16		dh_gLen
		byte[]		dh_g
		uint16		dh_YsLen
		byte[]		dh_Ys
		uint16		signatureLen
		byte[]		signature */
	if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
		{
		KEYAGREE_PARAMS keyAgreeParams;
		const void *keyData;
		int keyDataOffset, length;

		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
		if( cryptStatusError( status ) )
			return( status );
		length = checkHSPacketHeader( sessionInfoPtr, stream, 
							SSL_HAND_SERVER_KEYEXCHANGE, 
							UINT16_SIZE + bitsToBytes( MIN_PKCSIZE_BITS ) + \
							UINT16_SIZE + 1 + \
							UINT16_SIZE + bitsToBytes( MIN_PKCSIZE_BITS ) + \
							UINT16_SIZE + bitsToBytes( MIN_PKCSIZE_BITS ) );
		if( cryptStatusError( length ) )
			{
			sMemDisconnect( stream );
			return( length );
			}

		/* Read the server DH key and DH public value */
		memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
		keyData = sMemBufPtr( stream );
		keyDataOffset = stell( stream );
		readInteger16U( stream, NULL, NULL, bitsToBytes( MIN_PKCSIZE_BITS ),
						CRYPT_MAX_PKCSIZE );
		status = readInteger16U( stream, NULL, NULL, 1, CRYPT_MAX_PKCSIZE );
		if( cryptStatusOK( status ) )
			status = initDHcontextSSL( &handshakeInfo->dhContext, keyData, 
									   stell( stream ) - keyDataOffset );
		if( cryptStatusOK( status ) )
			status = readInteger16U( stream, keyAgreeParams.publicValue,
									 &keyAgreeParams.publicValueLen,
									 bitsToBytes( MIN_PKCSIZE_BITS ),
									 CRYPT_MAX_PKCSIZE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			retExt( sessionInfoPtr, cryptArgError( status ) ? \
					CRYPT_ERROR_BADDATA : status, 
					"Invalid server key agreement parameters" );
			}

		/* Check the server's signature on the DH parameters */
		status = checkKeyexSignature( sessionInfoPtr, handshakeInfo,
									  stream, keyData, 
									  stell( stream ) - keyDataOffset );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			retExt( sessionInfoPtr, status, 
					"Bad server key agreement parameter signature" );
			}

		/* 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 ) );
		}

	/* Process the optional server cert request:

		byte	ID = SSL_HAND_SERVER_CERTREQUEST
		uint24	len
		byte	certTypeLen
		byte[]	certType
		uint16	caNameListLen
			uint16	caNameLen
			byte[]	caName

	   We don't really care what's in the cert request packet since the 
	   contents are irrelevant, in a number of cases servers have been 
	   known to send out superfluous cert requests without the admins even 
	   knowning that they're doing it.  All we do here is perform a basic 
	   sanity check and remember that we may need to submit a cert later 
	   on.

	   Since we're about to peek ahead into the stream to see if we need to 
	   process a server cert request, we have to refresh the stream at this 
	   point in case the cert request wasn't bundled with the preceding 
	   packets */
	status = refreshHSStream( sessionInfoPtr, handshakeInfo );
	if( cryptStatusError( status ) )
		return( status );
	if( sPeek( stream ) == SSL_HAND_SERVER_CERTREQUEST )
		{
		int length;

		/* Although the spec says that at least one CA name entry must be 
		   present, some implementations send a zero-length list, so we 
		   allow this as well.  The spec was changed in late TLS 1.1 drafts 
		   to reflect this practice */
		status = checkHSPacketHeader( sessionInfoPtr, stream, 
									  SSL_HAND_SERVER_CERTREQUEST, 
									  1 + 1 + UINT16_SIZE );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		length = sgetc( stream );
		if( cryptStatusError( length ) || \
			length < 1 || cryptStatusError( sSkip( stream, length ) ) )
			{
			sMemDisconnect( stream );
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid cert request certificate type" );
			}
		length = readUint16( stream );
		if( cryptStatusError( length ) || \
			length < 0 || \
			( length > 0 && cryptStatusError( sSkip( stream, length ) ) ) )
			{
			sMemDisconnect( stream );
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid cert request CA name list" );
			}
		needClientCert = TRUE;
		}

	/* Process the server hello done:

		byte		ID = SSL_HAND_SERVER_HELLODONE
		uint24		len = 0 */
	status = refreshHSStream( sessionInfoPtr, handshakeInfo );
	if( cryptStatusError( status ) )
		return( status );
	status = checkHSPacketHeader( sessionInfoPtr, stream, 
								  SSL_HAND_SERVER_HELLODONE, 0 );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}

	/* If we need a client cert, build the client cert packet */
	openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT, 
						 SSL_MSG_HANDSHAKE );
	if( needClientCert )
		{
		BOOLEAN sentResponse = FALSE;

		/* If we haven't got a cert available, tell the server.  SSL and TLS
		   differ here, SSL sends a no-certificate alert while TLS sends an
		   empty client cert packet, which is handled further on */
		if( sessionInfoPtr->privateKey == CRYPT_ERROR )
			{
			setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY, 
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
				{
				static const FAR_BSS BYTE noCertAlertSSLTemplate[] = {
					SSL_MSG_ALERT,							/* ID */
					SSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL,/* Version */
					0, 2,									/* Length */
					SSL_ALERTLEVEL_WARNING, SSL_ALERT_NO_CERTIFICATE
					};

				/* This is an alert-protocol message rather than a handshake
				   message, so we don't add it to the handshake packet stream
				   but write it directly to the network stream */
				swrite( &sessionInfoPtr->stream, noCertAlertSSLTemplate, 7 );
				sentResponse = TRUE;
				}

			/* The reaction to the lack of a cert is up to the server (some 
			   just request one anyway even though they can't do anything
			   with it), so from here on we just continue as if nothing had
			   happened */
			needClientCert = FALSE;
			}

		/* If we haven't sent a response yet, send it now */
		if( !sentResponse )
			{
			status = writeSSLCertChain( sessionInfoPtr, stream );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( stream );
				return( status );
				}
			}
		}

	/* Build 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 ) */
	packetOffset = continueHSPacketStream( stream, 
										   SSL_HAND_CLIENT_KEYEXCHANGE );
	if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
		{
		KEYAGREE_PARAMS keyAgreeParams;

		/* Perform phase 1 of the DH key agreement process */
		memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
		status = krnlSendMessage( handshakeInfo->dhContext,
								  IMESSAGE_CTX_ENCRYPT, &keyAgreeParams,
								  sizeof( KEYAGREE_PARAMS ) );
		if( cryptStatusError( status ) )
			{
			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
			sMemDisconnect( stream );
			return( status );
			}
		writeInteger16U( stream, keyAgreeParams.publicValue, 
						 keyAgreeParams.publicValueLen );
		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
		}
	else
		if( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )
			{
			const ATTRIBUTE_LIST *attributeListPtr = \
				findSessionAttribute( sessionInfoPtr->attributeList,
									  CRYPT_SESSINFO_USERNAME );

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

			/* Write the PSK client identity */
			writeUint16( stream, attributeListPtr->valueLength );
			swrite( stream, attributeListPtr->value, 
					attributeListPtr->valueLength );
			}
		else
			{
			BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];
			int wrappedKeyLength;

			status = wrapPremasterSecret( sessionInfoPtr, handshakeInfo,
										  wrappedKey, &wrappedKeyLength );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( stream );
				return( status );
				}
			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 ambiguous) so 
				   the encoding differs slightly between SSL and TLS */
				swrite( stream, wrappedKey, wrappedKeyLength );
			else
				writeInteger16U( stream, wrappedKey, wrappedKeyLength );
			}
	completeHSPacketStream( stream, packetOffset );

	/* If we need to supply a client cert, send the signature generated with 
	   the cert to prove possession of the private key */
	if( needClientCert )
		{
		/* Write the packet header and drop in the signature data */
		packetOffset = continueHSPacketStream( stream, 
											   SSL_HAND_CLIENT_CERTVERIFY );
		status = createCertVerify( sessionInfoPtr, handshakeInfo, stream );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		completeHSPacketStream( stream, packetOffset );
		}

	/* Wrap and MAC the packet.  This is followed by the change cipherspec
	   packet so we don't send it at this point but leave it to be sent by
	   the shared handshake-completion code */
	status = completePacketStreamSSL( stream, 0 );
	dualMacData( handshakeInfo, stream, FALSE );
	return( status );
	}

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

void initSSLclientProcessing( SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	handshakeInfo->beginHandshake = beginClientHandshake;
	handshakeInfo->exchangeKeys = exchangeClientKeys;
	}
#endif /* USE_SSL */

⌨️ 快捷键说明

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