static SECURITY_STATUS negotiate_mic_exchange(NEGOTIATE_CONTEXT* context, NegToken* input_token,
                                              NegToken* output_token, PSecBuffer output_buffer)
{
	SecBuffer mic_buffers[2] = { 0 };
	SecBufferDesc mic_buffer_desc = { SECBUFFER_VERSION, 2, mic_buffers };
	SECURITY_STATUS status;

	WINPR_ASSERT(context);
	WINPR_ASSERT(input_token);
	WINPR_ASSERT(output_token);
	WINPR_ASSERT(context->mech);
	WINPR_ASSERT(context->mech->pkg);

	const SecurityFunctionTableA* table = context->mech->pkg->table;
	WINPR_ASSERT(table);

	mic_buffers[0] = context->mechTypes;

	/* Verify MIC if we received one */
	if (input_token->mic.cbBuffer > 0)
	{
		mic_buffers[1] = input_token->mic;

		status = table->VerifySignature(&context->sub_context, &mic_buffer_desc, 0, 0);
		if (status != SEC_E_OK)
			return status;

		output_token->negState = ACCEPT_COMPLETED;
	}

	/* If peer expects a MIC then generate it */
	if (input_token->negState != ACCEPT_COMPLETED)
	{
		/* Store the mic token after the mech token in the output buffer */
		output_token->mic.BufferType = SECBUFFER_TOKEN;
		output_token->mic.cbBuffer = output_buffer->cbBuffer - output_token->mechToken.cbBuffer;
		output_token->mic.pvBuffer =
		    (BYTE*)output_buffer->pvBuffer + output_token->mechToken.cbBuffer;

		mic_buffers[1] = output_token->mic;

		status = table->MakeSignature(&context->sub_context, 0, &mic_buffer_desc, 0);
		if (status != SEC_E_OK)
			return status;

		output_token->mic = mic_buffers[1];
	}

	/* When using NTLM cipher states need to be reset after mic exchange */
	if (_tcscmp(sspi_SecureHandleGetUpperPointer(&context->sub_context), NTLM_SSP_NAME) == 0)
		ntlm_reset_cipher_state(&context->sub_context);

	return SEC_E_OK;
}
static SECURITY_STATUS negotiate_mic_exchange(NEGOTIATE_CONTEXT* context, NegToken* input_token,
                                              NegToken* output_token, PSecBuffer output_buffer)
{
	SecBuffer mic_buffers[2] = { 0 };
	SecBufferDesc mic_buffer_desc = { SECBUFFER_VERSION, 2, mic_buffers };
	SECURITY_STATUS status;

	WINPR_ASSERT(context);
	WINPR_ASSERT(input_token);
	WINPR_ASSERT(output_token);
	WINPR_ASSERT(context->mech);
	WINPR_ASSERT(context->mech->pkg);

	const SecurityFunctionTableA* table = context->mech->pkg->table;
	WINPR_ASSERT(table);

	mic_buffers[0] = context->mechTypes;

	 
	if (input_token->mic.cbBuffer > 0)
	{
		mic_buffers[1] = input_token->mic;

		status = table->VerifySignature(&context->sub_context, &mic_buffer_desc, 0, 0);
		if (status != SEC_E_OK)
			return status;

		output_token->negState = ACCEPT_COMPLETED;
	}

	 
	if (input_token->negState != ACCEPT_COMPLETED)
	{
		 
		output_token->mic.BufferType = SECBUFFER_TOKEN;
		output_token->mic.cbBuffer = output_buffer->cbBuffer - output_token->mechToken.cbBuffer;
		output_token->mic.pvBuffer =
		    (BYTE*)output_buffer->pvBuffer + output_token->mechToken.cbBuffer;

		mic_buffers[1] = output_token->mic;

		status = table->MakeSignature(&context->sub_context, 0, &mic_buffer_desc, 0);
		if (status != SEC_E_OK)
			return status;

		output_token->mic = mic_buffers[1];
	}

	 
	if (_tcscmp(sspi_SecureHandleGetUpperPointer(&context->sub_context), NTLM_SSP_NAME) == 0)
		ntlm_reset_cipher_state(&context->sub_context);

	return SEC_E_OK;
}