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

📄 ssl.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
				SSL_MINOR_VERSION : TLS_MINOR_VERSION;
	setResourceData( &msgData, 
					 handshakeInfo->premasterSecret + VERSIONINFO_SIZE, 
					 SSL_SECRET_SIZE - VERSIONINFO_SIZE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_IATTRIBUTE_RANDOM );
	if( cryptStatusError( status ) )
		return( status );
	setMechanismWrapInfo( &mechanismInfo, bufPtr, CRYPT_MAX_PKCSIZE, 
						  handshakeInfo->premasterSecret, SSL_SECRET_SIZE, 
						  CRYPT_UNUSED, sessionInfoPtr->iKeyexCryptContext, 
						  CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_EXPORT, &mechanismInfo,
							  MECHANISM_PKCS1_RAW );
	if( cryptStatusError( status ) )
		return( status );
	bufPtr += keySize;
	length += ID_SIZE + LENGTH_SIZE + keySize;
	if( sessionInfoPtr->version == CRYPT_PROTOCOLVERSION_TLS )
		length += UINT16_SIZE;	/* See earlier comment */

	/* If we need a client cert, send the signature generated with the client
	   cert to prove possession of the private key */
	if( needClientCert )
		{
		int verifyInfoLength, status;

		/* Write the packet header and drop in the signature data */
		*bufPtr++ = SSL_HAND_CLIENT_CERTVERIFY;
		status = verifyInfoLength = \
			processCertVerify( sessionInfoPtr, handshakeInfo, 
							   bufPtr + LENGTH_SIZE, 0, TRUE );
		if( cryptStatusError( status ) )
			return( status );
		*bufPtr++ = 0;
		mputBWord( bufPtr, verifyInfoLength );
		length += ID_SIZE + LENGTH_SIZE + verifyInfoLength;
		}

	/* Send the client information to the server */
	wrapHandshakePacket( sessionInfoPtr->sendBuffer, length,
						 sessionInfoPtr->version );
	status = swrite( &sessionInfoPtr->stream, sessionInfoPtr->sendBuffer, 
					 SSL_HEADER_SIZE + length );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream, 
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	dualMacData( handshakeInfo, sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE, 
				 length );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Server-side Connect Functions					*
*																			*
****************************************************************************/

/* Perform the initial part of the handshake with the client */

static int beginServerHandshake( SESSION_INFO *sessionInfoPtr, 
								 SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	BYTE *bufPtr, *lengthPtr;
	int length, suite, status;

	/* Wait for the hello packet from the client */
	status = readPacket( sessionInfoPtr, handshakeInfo, 
						 SSL_MSG_SPECIAL_HANDSHAKE );
	if( cryptStatusError( status ) )
		return( status );

	/* Process the client hello.  Although this should be a v3 hello, 
	   Netscape always sends a v2 hello (even if SSLv2 is disabled) so we
	   have to process both types.  The v2 type and version have already 
	   been processed in readPacket(), since this information, which is 
	   moved into the header in v3, is part of the body in v2.  What's
	   left for the v2 hello is the remainder of the payload:
			SSLv2						SSLv3/TLS
		uint16		suiteLen		byte		ID = 1
		uint16		sessIDlen = 0	uint24		len
		uint16		nonceLen		byte[2]		version = { 0x03, 0x0n }
		byte[]		suite			uint32		time			| Session ID
		byte[]		sessID			byte[28]	nonce			|
		byte[]		nonce			byte		sessIDlen = 0
									uint16		suiteLen
									byte[]		suites
									byte		coprLen = 1
									byte		copr = 0 */
	bufPtr = sessionInfoPtr->receiveBuffer;
	if( *bufPtr == SSL_HAND_CLIENT_HELLO )
		{
		int ch, suiteLength;

		/* SSLv3/TLS hello */
		bufPtr += 2;		/* Skip type, length MSB */
		length = mgetBWord( bufPtr );
		if( length < VERSIONINFO_SIZE + SSL_NONCE_SIZE + 1 + \
					 ( UINT16_SIZE * 2 ) + 1 + 1 || \
			length > 256 || *bufPtr++ != SSL_MAJOR_VERSION )
			return( CRYPT_ERROR_BADDATA );
		ch = *bufPtr++;
		if( ch == SSL_MINOR_VERSION )
			{
			if( sessionInfoPtr->version == CRYPT_PROTOCOLVERSION_TLS )
				/* If the client can't do TLS, fall back to SSL */
				sessionInfoPtr->version = CRYPT_PROTOCOLVERSION_SSL;
			}
		else
			if( ch != TLS_MINOR_VERSION )
				return( CRYPT_ERROR_BADDATA );
		memcpy( handshakeInfo->clientNonce, bufPtr, SSL_NONCE_SIZE );
		bufPtr += SSL_NONCE_SIZE;
		length = *bufPtr++;	/* Session ID length */
		if( length > 32 )
			return( CRYPT_ERROR_BADDATA );
		bufPtr += length;	/* Skip session ID */
		suiteLength = mgetBWord( bufPtr );
		if( suiteLength == 0 || ( suiteLength % 2 ) != 0 )
			return( CRYPT_ERROR_BADDATA );
		suite = chooseCipherSuite( bufPtr, suiteLength / 2, FALSE );
		if( suite == SSL_NULL_WITH_NULL )
			return( CRYPT_ERROR_NOTAVAIL );
		bufPtr += suiteLength;
		status = initCiphersuiteInfo( sessionInfoPtr, handshakeInfo, suite );
		if( cryptStatusError( status ) )
			return( status );
		if( *bufPtr++ != 1 || *bufPtr++ )
			return( CRYPT_ERROR_BADDATA );
		}
	else
		{
		int suiteLength, sessIDlength, nonceLength;

		/* SSLv2 hello from Netscape */
		suiteLength = mgetBWord( bufPtr );
		sessIDlength = mgetBWord( bufPtr );
		nonceLength = mgetBWord( bufPtr );
		if( suiteLength == 0 || ( suiteLength % 3 ) != 0 || \
			nonceLength < 16 || nonceLength > SSL_NONCE_SIZE || \
			suiteLength + sessIDlength + nonceLength > \
								sessionInfoPtr->receiveBufEnd )
			return( CRYPT_ERROR_BADDATA );
		suite = chooseCipherSuite( bufPtr, suiteLength / 3, TRUE );
		if( suite == SSL_NULL_WITH_NULL )
			return( CRYPT_ERROR_NOTAVAIL );
		bufPtr += suiteLength;
		status = initCiphersuiteInfo( sessionInfoPtr, handshakeInfo, suite );
		if( cryptStatusError( status ) )
			return( status );
		if( sessIDlength )
			bufPtr += sessIDlength;
		memcpy( handshakeInfo->clientNonce + SSL_NONCE_SIZE - nonceLength, 
				bufPtr, nonceLength );
		}

	/* Build the server hello, cert, optional cert request, and done packets
		byte		ID = 2
		uint24		len
		byte[2]		version = { 0x03, 0x0n }
		uint32		time			| Session ID
		byte[28]	nonce			|
		byte		sessIDlen = 0
		uint16		suite
		byte		copr = 0
		... */
	getNonce( handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	bufPtr = sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE;
	*bufPtr++ = SSL_HAND_SERVER_HELLO;
	*bufPtr++ = 0;
	lengthPtr = bufPtr;		/* Low 16 bits of length */
	bufPtr += LENGTH_SIZE - 1;
	*bufPtr++ = SSL_MAJOR_VERSION;
	*bufPtr++ = ( sessionInfoPtr->version == CRYPT_PROTOCOLVERSION_SSL ) ? \
				SSL_MINOR_VERSION : TLS_MINOR_VERSION;
	memcpy( bufPtr, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	bufPtr += SSL_NONCE_SIZE;
	*bufPtr++ = '\0';		/* No session ID */
	mputBWord( bufPtr, suite ); 
	*bufPtr++ = 0;			/* No compression */
	length = bufPtr - ( sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE );
	mputBWord( lengthPtr, length - ( ID_SIZE + LENGTH_SIZE ) );

	/*	...
		(server cert chain)
		... */
	status = writeSSLCertChain( sessionInfoPtr, bufPtr );
	if( cryptStatusError( status ) )
		return( status );
	bufPtr += status;

	/*	...			( optional client cert request)
		byte		ID = 0x0D
		uint24		len = 7
		byte		certTypeLen = 2
		byte[2]		certType = { 0x01, 0x02 }
		uint16		caNameListLen = 4
		uint16		caNameLen = 2
		byte[]		caName = { 0x30, 0x00 }
		... */
	if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
		{
		memcpy( bufPtr, serverCertRequestTemplate, 
				SERVERCERTREQUEST_TEMPLATE_SIZE );
		bufPtr += SERVERCERTREQUEST_TEMPLATE_SIZE;
		}

	/*	...
		byte		ID = 0x0E
		uint24		len = 0 */
	memcpy( bufPtr, serverHelloDoneTemplate, 
			SERVERHELLODONE_TEMPLATE_SIZE );
	bufPtr += SERVERHELLODONE_TEMPLATE_SIZE;

	/* Send the combined server packets to the client and read back and 
	   process the client's data */
	length = bufPtr - ( sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE );
	wrapHandshakePacket( sessionInfoPtr->sendBuffer, length, 
						 sessionInfoPtr->version );
	status = swrite( &sessionInfoPtr->stream, sessionInfoPtr->sendBuffer, 
					 SSL_HEADER_SIZE + length );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream, 
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	dualMacData( handshakeInfo, sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE, 
				 length );

	return( CRYPT_OK );
	}

/* Exchange keys with the client */

static int exchangeServerKeys( SESSION_INFO *sessionInfoPtr, 
							   SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	BYTE *bufPtr;
	int length, status;

	/* Read the response from the client and, if we're expecting a client 
	   cert, make sure it's present */
	status = readPacket( sessionInfoPtr, handshakeInfo, SSL_MSG_HANDSHAKE );
	if( cryptStatusError( status ) )
		{
		/* If we've asked for a client cert and there's none available, tell
		   the client they can't come in.  Although in theory only an SSL
		   client should send a no-certificates alert, it's quite possible
		   that we'll get one from upgraded-to-TLS SSL code, so we handle 
		   both possibilities here */
		if( sessionInfoPtr->errorCode == SSL_ALERT_NO_CERTIFICATE )
			sendHandshakeFailAlert( sessionInfoPtr );
		return( status );
		}
	bufPtr = sessionInfoPtr->receiveBuffer;
	if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;
		MESSAGE_KEYMGMT_INFO getkeyInfo;
		RESOURCE_DATA msgData;
		BYTE certID[ KEYID_SIZE ];

		/* Make sure the client has sent us a cert chain */
		if( *bufPtr++ != SSL_HAND_SERVER_CERT || *bufPtr++ != 0 )
			return( CRYPT_ERROR_BADDATA );
		length = mgetBWord( bufPtr );
		if( length == 0 || length == 3 )
			{
			/* Sending an empty cert packet is another way to indicate that 
			   the client doesn't have a cert.  The spec is ambiguous on what
			   constitutes an empty packet, it could be either a packet with
			   a length of zero or a packet containing a zero-length cert 
			   list so we check for both.  We also fake the error indicators
			   for consistency with the status obtained from a no-cert alert */
			sendHandshakeFailAlert( sessionInfoPtr );
			sessionInfoPtr->errorCode = SSL_ALERT_NO_CERTIFICATE;
			strcpy( sessionInfoPtr->errorMessage, 
					( sessionInfoPtr->version == CRYPT_PROTOCOLVERSION_SSL ) ? \
						"Received SSL alert message: No certificate" : \
						"Received TLS alert message: No certificate" );
			return( CRYPT_ERROR_PERMISSION );
			}
		if( length < 64 || length > BUFFER_SIZE || \
			*bufPtr++ != 0 )
			return( CRYPT_ERROR_BADDATA );
		sessionInfoPtr->receiveBufPos = ID_SIZE + LENGTH_SIZE + length;
		length = mgetBWord( bufPtr );	/* Length of cert chain */

		/* Import the cert chain.  Since this isn't a true cert chain (in 
		   the sense of being degenerate PKCS #7 SignedData) but a special-
		   case SSL-encoded cert chain, we notify the cert management code 
		   of this when it performs the import */
		setMessageCreateObjectIndirectInfo( &createInfo, bufPtr, length );
		createInfo.arg1 = CERTFORMAT_SSLCHAIN;
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		bufPtr += length;
		sessionInfoPtr->iKeyexAuthContext = createInfo.cryptHandle;

		/* Make sure 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 */
		setResourceData( &msgData, certID, KEYID_SIZE );
		status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_CERTID );
		if( cryptStatusOK( status ) )
			{
			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, certID, 
								   KEYID_SIZE, NULL, 0, 
								   KEYMGMT_FLAG_CHECK_ONLY );
			status = krnlSendMessage( sessionInfoPtr->cryptKeyset, 
									  RESOURCE_IMESSAGE_KEY_GETKEY,
									  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
			}
		if( cryptStatusError( status ) )
			{
			sendHandshakeFailAlert( sessionInfoPtr );
			return( CRYPT_ERROR_INVALID );
			}

		/* Read the next packet(s) if necessary */
		if( sessionInfoPtr->receiveBufPos >= sessionInfoPtr->receiveBufEnd )
			{
			status = readPacket( sessionInfoPtr, handshakeInfo,  
								 SSL_MSG_HANDSHAKE );
			if( cryptStatusError( status ) )
				return( status );
			bufPtr = sessionInfoPtr->receiveBuffer;
			}		
		}

	/* Process the client key exchange packet:
		byte		ID = 0x10
		uint24		len
	  [ uint16		encKeyLen - TLS only ]
		byte[]		rsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */
	if( *bufPtr++ != SSL_HAND_CLIENT_KEYEXCHANGE || *bufPtr++ != 0 )
		return( CRYPT_ERROR_BADDATA );
	length = mgetBWord( bufPtr );
	if( length < 64 || length > CRYPT_MAX_P

⌨️ 快捷键说明

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