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

📄 ssl.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
	for( premaster_index = 0; premaster_index < 48; )
		{
		int i;

		premaster_secret[ premaster_index++ ] = shared_secret_length;
		for( i = 0; i < shared_secret_length && premaster_index < 48; i++ )
			premaster_secret[ premaster_index++ ] = shared_secret[ i ];
		}
	}

int createSharedMasterSecret( BYTE *masterSecret, 
							  const SESSION_INFO *sessionInfoPtr )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	BYTE premasterSecret[ SSL_SECRET_SIZE ];
	int status;

	/* Expand the shared secret to create the premaster secret */
	if( sessionInfoPtr->flags & SESSION_ISENCODEDPW )
		{
		BYTE decodedValue[ CRYPT_MAX_TEXTSIZE ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded password, decode it into its binary 
		   value */
		decodedValueLength = decodePKIUserValue( decodedValue,
											sessionInfoPtr->password,
											sessionInfoPtr->passwordLength );
		if( cryptStatusError( decodedValueLength ) )
			{
			assert( NOTREACHED );
			return( decodedValueLength );
			}
		expandSharedSecret( premasterSecret, decodedValue, 
							min( decodedValueLength, SSL_SECRET_SIZE ) );
		zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
		}
	else
		expandSharedSecret( premasterSecret, sessionInfoPtr->password, 
							min( sessionInfoPtr->passwordLength, 
								 SSL_SECRET_SIZE ) );

	/* Create the master secret from the expanded user-supplied password.  
	   Note that since the use of shared secrets is specified only for TLS, 
	   we always use the TLS key derivation even if it's with the SSL 
	   protocol */
	setMechanismDeriveInfo( &mechanismInfo,
							masterSecret, SSL_SECRET_SIZE,
							premasterSecret, SSL_SECRET_SIZE,
							CRYPT_USE_DEFAULT, "shared secret", 13, 1 );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_DERIVE, &mechanismInfo, 
							  MECHANISM_TLS );
	zeroise( premasterSecret, SSL_SECRET_SIZE );
	return( status );
	}

/* Encrypt/decrypt a data block */

static int encryptData( const SESSION_INFO *sessionInfoPtr, BYTE *data,
						const int dataLength )
	{
	int length = dataLength, status;

	assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( dataLength > 0 && dataLength <= MAX_PACKET_SIZE + 20 );
	assert( isWritePtr( data, dataLength ) );

	/* If it's a block cipher, we need to add end-of-block padding */
	if( sessionInfoPtr->cryptBlocksize > 1 )
		{
		BYTE *dataPadPtr = data + dataLength;
		const int padSize = ( sessionInfoPtr->cryptBlocksize - 1 ) - \
						    ( dataLength & ( sessionInfoPtr->cryptBlocksize - 1 ) );
		int i;

		/* Add the PKCS #5-style padding (PKCS #5 uses n, TLS uses n-1) */
		for( i = 0; i < padSize + 1; i++ )
			*dataPadPtr++ = padSize;
		length += padSize + 1;
		}

	status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
							  IMESSAGE_CTX_ENCRYPT, data, length );
	return( cryptStatusError( status ) ? status : length );
	}

static int decryptData( SESSION_INFO *sessionInfoPtr, BYTE *data,
						const int dataLength )
	{
	int length = dataLength, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( dataLength > 0 && dataLength <= sessionInfoPtr->receiveBufEnd );
	assert( isWritePtr( data, dataLength ) );

	/* Decrypt the data */
	status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
							  IMESSAGE_CTX_DECRYPT, data, length );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, 
				"Decryption of SSL packet failed" );

	/* If it's a block cipher, we need to remove end-of-block padding.  Up
	   until TLS 1.1 the spec was silent about any requirement to check the 
	   padding (and for SSLv3 it didn't specify the padding format at all) 
	   so it's not really safe to reject an SSL a message if we don't find 
	   the correct padding because many SSL implementations didn't process 
	   the padded space in any way, leaving it containing whatever was there 
	   before.  Almost all TLS implementations get it right (even though in
	   TLS 1.0 there was only a requirement to generate, but not to check, 
	   the PKCS #5-style padding).  Because of this we only check the 
	   padding bytes if we're talking TLS */
	if( sessionInfoPtr->cryptBlocksize > 1 )
		{
		const int padSize = data[ dataLength - 1 ];

		/* Make sure that the padding info looks OK.  TLS allows up to 256 
		   bytes of padding, but there are no known implementations that do 
		   this.  This is convenient because it allows us to quickly detect
		   most invalid decrypts */
		if( padSize < 0 || padSize > sessionInfoPtr->cryptBlocksize - 1 )
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid padding value 0x%02X", padSize );
		length -= padSize + 1;
		if( length < 0 )
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Padding adjustment value 0x%02X is greater than packet "
					"length %d", padSize, dataLength );

		/* Check for PKCS #5-type padding (PKCS #5 uses n, TLS uses n-1) if
		   necessary */
		if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS )
			{
			int i;

			for( i = 0; i < padSize; i++ )
				if( data[ length + i ] != padSize )
					retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
							"Invalid padding byte 0x%02X at position %d", 
							data[ length + i ], length + i );
			}
		}

	return( length );
	}

/* Perform a MAC or dual MAC of a data block.  We have to provide special-
   case handling of zero-length blocks since some versions of OpenSSL send
   these as a kludge to work around chosen-IV attacks */

static int macDataSSL( SESSION_INFO *sessionInfoPtr, const void *data,
					   const int dataLength, const int type,
					   const BOOLEAN isRead )
	{
	RESOURCE_DATA msgData;
	BYTE buffer[ 128 ], *bufPtr;
	BYTE *macPtr = isRead ? buffer : ( BYTE * ) data + dataLength;
	const CRYPT_CONTEXT iHashContext = isRead ? \
			sessionInfoPtr->iAuthInContext : sessionInfoPtr->iAuthOutContext;
	const void *macSecret = isRead ? \
			sessionInfoPtr->sslMacReadSecret : sessionInfoPtr->sslMacWriteSecret;
	const long seqNo = isRead ? \
			sessionInfoPtr->readSeqNo++ : sessionInfoPtr->writeSeqNo++;
	const int padSize = \
			( sessionInfoPtr->integrityAlgo == CRYPT_ALGO_MD5 ) ? 48 : 40;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );
	assert( isReadPtr( data, dataLength ) );

	/* Set up the sequence number and length data */
	memcpy( buffer, PROTOHMAC_PAD1, padSize );
	memset( buffer + padSize, 0, SEQNO_SIZE );
	bufPtr = buffer + padSize + 4;
	mputLong( bufPtr, seqNo );
	*bufPtr++ = type;
	mputWord( bufPtr, dataLength );

	/* Reset the hash context and generate the inner portion of the MAC:

		hash( MAC_secret || pad1 || seq_num || type || length || data ) */
	krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) macSecret, 
					 sessionInfoPtr->authBlocksize );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 
					 padSize + SEQNO_SIZE + ID_SIZE + UINT16_SIZE );
	if( dataLength > 0 )
		krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) data, 
						 dataLength );
	status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusError( status ) )
		return( status );

	/* Extract the inner hash value */
	memcpy( buffer, PROTOHMAC_PAD2, padSize );
	setMessageData( &msgData, buffer + padSize, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusError( status ) )
		return( status );

	/* Generate the outer portion of the handshake message's MAC and get the
	   MAC value, which is either written to the end of the data (for a
	   write) or to a separate buffer (for a read):
		hash( MAC_secret || pad2 || inner_hash ) */
	krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) macSecret, 
					 sessionInfoPtr->authBlocksize );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 
					 padSize + msgData.length );
	status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, macPtr, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a read, compare the calculated MAC to the MAC present at the
	   end of the data */
	if( isRead )
		{
		if( memcmp( macPtr, ( BYTE * ) data + dataLength, msgData.length ) )
			retExt( sessionInfoPtr, CRYPT_ERROR_SIGNATURE,
					"Bad message MAC" );
		return( CRYPT_OK );
		}

	return( dataLength + msgData.length );
	}

static int macDataTLS( SESSION_INFO *sessionInfoPtr, const void *data,
					   const int dataLength, const int type,
					   const BOOLEAN isRead )
	{
	RESOURCE_DATA msgData;
	BYTE buffer[ 128 ], *bufPtr;
	BYTE *macPtr = isRead ? buffer : ( BYTE * ) data + dataLength;
	const CRYPT_CONTEXT iHashContext = isRead ? \
			sessionInfoPtr->iAuthInContext : sessionInfoPtr->iAuthOutContext;
	const long seqNo = isRead ? \
			sessionInfoPtr->readSeqNo++ : sessionInfoPtr->writeSeqNo++;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );
	assert( isReadPtr( data, dataLength ) );

	/* Set up the sequence number, type, version, and length data */
	memset( buffer, 0, SEQNO_SIZE );
	bufPtr = buffer + 4;
	mputLong( bufPtr, seqNo );
	*bufPtr++ = type;
	*bufPtr++ = SSL_MAJOR_VERSION;
	*bufPtr++ = SSL_MINOR_VERSION_TLS;
	mputWord( bufPtr, dataLength );

	/* Reset the hash context and generate the MAC, which is either written
	   to the end of the data (for a write) or to a separate buffer (for a
	   read):

		HMAC( seq_num || type || version || length || data ) */
	krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 
					 SEQNO_SIZE + ID_SIZE + VERSIONINFO_SIZE + UINT16_SIZE );
	if( dataLength > 0 )
		krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) data, 
						 dataLength );
	status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, macPtr, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a read, compare the calculated MAC to the MAC present at the
	   end of the data */
	if( isRead )
		{
		if( memcmp( macPtr, ( BYTE * ) data + dataLength, msgData.length ) )
			retExt( sessionInfoPtr, CRYPT_ERROR_SIGNATURE,
					"Bad message MAC" );
		return( CRYPT_OK );
		}

	return( dataLength + msgData.length );
	}

int dualMacData( const SSL_HANDSHAKE_INFO *handshakeInfo, const void *data,
				 const int dataLength )
	{
	int status;

	status = krnlSendMessage( handshakeInfo->clientMD5context,
							  IMESSAGE_CTX_HASH, ( void * ) data, 
							  dataLength );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( handshakeInfo->clientSHA1context,
								  IMESSAGE_CTX_HASH, ( void * ) data, 
								  dataLength );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( handshakeInfo->serverMD5context,
								  IMESSAGE_CTX_HASH, ( void * ) data, 
								  dataLength );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( handshakeInfo->serverSHA1context,
								  IMESSAGE_CTX_HASH, ( void * ) data, 
								  dataLength );
	return( status );
	}

/* Wrap/unwrap an SSL data packet.  These functions process data as follows:

				------				MAC'd
		   =======================  Encrypted

	[ hdr | IV | data | MAC | pad ]	|
	|		   +------+				| Wrap, adds hdr, IV, MAC, pad,
	|			  |					| returns total length
   buffer		length 

⌨️ 快捷键说明

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