示例#1
0
/* ========= ClientKeyExchange ========= */
int ssl3_decode_client_key_exchange( DSSL_Session* sess, u_char* data, uint32_t len )
{
	EVP_PKEY *pk = NULL;
	u_char* org_data = data;
	uint32_t org_len = len;
	int pms_len = 0;
	int rc = DSSL_RC_OK;

	if( sess->version < SSL3_VERSION || sess->version > TLS1_2_VERSION )
	{
		return NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION );
	}

	/* 
	TLS is different as it sends the record length, while SSL3 implementaions don't
	(due to a bug in Netscape implementation)
	*/
	if( sess->version > SSL3_VERSION )
	{
		uint16_t recLen = 0;
		if( !IS_ENOUGH_LENGTH( org_data, org_len, data, 2 ) ) 
		{
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		recLen = MAKE_UINT16( data[0], data[1] );
		if( len != (uint32_t)recLen + 2 )
		{
			/*TODO: set an option to tolerate this bug?*/
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		/* advance */
		data += len - recLen;
		len = recLen;
	}

	if( !IS_ENOUGH_LENGTH( org_data, org_len, data, SSL_MAX_MASTER_KEY_LENGTH ) )
	{
		return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
	}

	pk = ssls_get_session_private_key( sess );

	/* if SSL server key is not found, try to find a matching one from the key pool */
	if(pk == NULL) 
	{
		_ASSERT( sess->last_packet);
		pk = ssls_try_ssl_keys( sess, data, len );

		/* if a matching key found, register it with the server IP:port */
		if(pk != NULL)
		{
			if( ssls_register_ssl_key( sess, pk ) == DSSL_RC_OK)
			{
				/* ssls_register_ssl_key clones the key, query the key back */
				pk = ssls_get_session_private_key( sess );
			}
			else
			{
				pk = NULL;
			}
		}
	}

	if(!pk) 
	{
		ssls_register_missing_key_server( sess );
		return NM_ERROR( DSSL_E_SSL_SERVER_KEY_UNKNOWN );
	}

	if(pk->type != EVP_PKEY_RSA) return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT_NON_RSA );

	pms_len = RSA_private_decrypt( len, data, sess->PMS, pk->pkey.rsa, RSA_PKCS1_PADDING );

	if( pms_len != SSL_MAX_MASTER_KEY_LENGTH )
	{
		return NM_ERROR( DSSL_E_SSL_CORRUPTED_PMS );
	}

	if( MAKE_UINT16( sess->PMS[0], sess->PMS[1] ) != sess->client_version )
	{
		return NM_ERROR( DSSL_E_SSL_PMS_VERSION_ROLLBACK );
	}

	rc = ssls_decode_master_secret( sess );
	OPENSSL_cleanse(sess->PMS, sizeof(sess->PMS) );

	if( rc != DSSL_RC_OK ) return rc;

	rc = ssls_generate_keys( sess );
	if( rc == DSSL_RC_OK )
	{
		ssls_store_session( sess );
	}
	return rc;
}
示例#2
0
/* ========== CLIENT-MASTER-KEY ========== */
static int ssl2_decode_client_master_key(  DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed )
{
	int rc = DSSL_RC_OK;
	uint16_t clearKeyLen = 0;
	uint16_t encKeyLen = 0;
	uint16_t keyArgLen = 0;
	u_char* pClearKey = NULL;
	u_char* pEncKey = NULL;
	u_char* pKeyArg = NULL;

	_ASSERT( processed && data && sess );
	if( len < SSL20_CLIENT_MASTER_KEY_MIN_LEN ) { return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); }

	/* CIPHER-KIND - convert to 2 byte DSSL_Session::cipher_suite */
	rc = DSSL_ConvertSSL2CipherSuite( data, &sess->cipher_suite );

	/* CLEAR-KEY-LENGTH, ENCRYPTED-KEY-LENGTH, KEY-ARG-LENGTH */
	if( rc == DSSL_RC_OK )
	{
		clearKeyLen = MAKE_UINT16( data[3], data[4] );
		encKeyLen = MAKE_UINT16( data[5], data[6] );
		keyArgLen = MAKE_UINT16( data[7], data[8] );

		if( len != (uint32_t)clearKeyLen + encKeyLen + keyArgLen + SSL20_CLIENT_MASTER_KEY_MIN_LEN )
		{
			rc = NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		*processed = len;

	}
	
	/* reconstitute the master secret */
	if( rc == DSSL_RC_OK )
	{
		EVP_PKEY *pk = NULL;

		pClearKey = data + SSL20_CLIENT_MASTER_KEY_MIN_LEN;
		pEncKey = pClearKey + clearKeyLen;
		pKeyArg = pEncKey + encKeyLen;

		if( clearKeyLen ) { memcpy( sess->master_secret, pClearKey, clearKeyLen ); }

		pk = ssls_get_session_private_key( sess );
		
		/* if SSL server key is not found, try to find a matching one from the key pool */
		if(pk == NULL) 
		{
			u_char buff[1024];
			_ASSERT( sess->last_packet);

			memcpy(buff, pEncKey, encKeyLen);
			pk = ssls_try_ssl_keys( sess, pEncKey, encKeyLen );

			/* if a matching key found, register it with the server IP:port */
			if(pk != NULL)
			{
				if( ssls_register_ssl_key( sess, pk ) == DSSL_RC_OK)
				{
					/* ssls_register_ssl_key clones the key, query the key back */
					//pk = ssls_get_session_private_key( sess );
				}
				else
				{
					pk = NULL;
				}
			}
		}

		if( pk )
		{
			uint32_t encLen2 = RSA_private_decrypt( encKeyLen, pEncKey, 
					sess->master_secret + clearKeyLen, pk->pkey.rsa, RSA_PKCS1_PADDING );

			if( clearKeyLen + encLen2 >= sizeof( sess->master_secret ) )
			{
				rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );
			}

			sess->master_key_len = clearKeyLen + encLen2;
		}
		else
		{
			rc = NM_ERROR( DSSL_E_SSL_SERVER_KEY_UNKNOWN );
			ssls_register_missing_key_server( sess );
		}
	}

	/* generate session keys */
	if( rc == DSSL_RC_OK )
	{
		rc = ssls2_generate_keys( sess, pKeyArg, keyArgLen );
	}

	/* turn on new ciphers */
	if( rc == DSSL_RC_OK ) 
	{
		rc = dssl_decoder_stack_flip_cipher( &sess->c_dec );
		if (rc == DSSL_RC_OK ) { rc = dssl_decoder_stack_flip_cipher( &sess->s_dec ); }
	}

	return rc;
}