Blame winpr/libwinpr/sspi/NTLM/ntlm_compute.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * NTLM Security Package (Compute)
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <assert.h>
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm.h"
Packit 1fb8d4
#include "../sspi.h"
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/sam.h>
Packit 1fb8d4
#include <winpr/ntlm.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
#include <winpr/sysinfo.h>
Packit 1fb8d4
Packit 1fb8d4
#include "ntlm_compute.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("sspi.NTLM")
Packit 1fb8d4
Packit 1fb8d4
const char LM_MAGIC[] = "KGS!@#$%";
Packit 1fb8d4
Packit 1fb8d4
static const char NTLM_CLIENT_SIGN_MAGIC[] =
Packit 1fb8d4
    "session key to client-to-server signing key magic constant";
Packit 1fb8d4
static const char NTLM_SERVER_SIGN_MAGIC[] =
Packit 1fb8d4
    "session key to server-to-client signing key magic constant";
Packit 1fb8d4
static const char NTLM_CLIENT_SEAL_MAGIC[] =
Packit 1fb8d4
    "session key to client-to-server sealing key magic constant";
Packit 1fb8d4
static const char NTLM_SERVER_SEAL_MAGIC[] =
Packit 1fb8d4
    "session key to server-to-client sealing key magic constant";
Packit 1fb8d4
Packit Service 5a9772
static const BYTE NTLM_NULL_BUFFER[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit Service 5a9772
	                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Populate VERSION structure.
Packit 1fb8d4
 * VERSION @msdn{cc236654}
Packit 1fb8d4
 * @param s
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
Packit 1fb8d4
{
Packit 1fb8d4
	OSVERSIONINFOA osVersionInfo;
Packit 1fb8d4
	osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
Packit 1fb8d4
	GetVersionExA(&osVersionInfo);
Packit Service 5a9772
	versionInfo->ProductMajorVersion = (UINT8)osVersionInfo.dwMajorVersion;
Packit Service 5a9772
	versionInfo->ProductMinorVersion = (UINT8)osVersionInfo.dwMinorVersion;
Packit Service 5a9772
	versionInfo->ProductBuild = (UINT16)osVersionInfo.dwBuildNumber;
Packit 1fb8d4
	ZeroMemory(versionInfo->Reserved, sizeof(versionInfo->Reserved));
Packit 1fb8d4
	versionInfo->NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Read VERSION structure.
Packit 1fb8d4
 * VERSION @msdn{cc236654}
Packit 1fb8d4
 * @param s
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
Packit 1fb8d4
{
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
Packit 1fb8d4
	Stream_Read_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Packit Service 5a9772
	Stream_Read_UINT16(s, versionInfo->ProductBuild);       /* ProductBuild (2 bytes) */
Packit 1fb8d4
	Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
Packit 1fb8d4
	Stream_Read_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Write VERSION structure.
Packit 1fb8d4
 * VERSION @msdn{cc236654}
Packit 1fb8d4
 * @param s
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_write_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
Packit 1fb8d4
{
Packit 1fb8d4
	Stream_Write_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
Packit 1fb8d4
	Stream_Write_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Packit Service 5a9772
	Stream_Write_UINT16(s, versionInfo->ProductBuild);       /* ProductBuild (2 bytes) */
Packit 1fb8d4
	Stream_Write(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
Packit 1fb8d4
	Stream_Write_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Print VERSION structure.
Packit 1fb8d4
 * VERSION @msdn{cc236654}
Packit 1fb8d4
 * @param s
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_INFO(TAG, "VERSION ={");
Packit Service 5a9772
	WLog_INFO(TAG, "\tProductMajorVersion: %" PRIu8 "", versionInfo->ProductMajorVersion);
Packit Service 5a9772
	WLog_INFO(TAG, "\tProductMinorVersion: %" PRIu8 "", versionInfo->ProductMinorVersion);
Packit Service 5a9772
	WLog_INFO(TAG, "\tProductBuild: %" PRIu16 "", versionInfo->ProductBuild);
Packit Service 5a9772
	WLog_INFO(TAG, "\tReserved: 0x%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "", versionInfo->Reserved[0],
Packit 1fb8d4
	          versionInfo->Reserved[1], versionInfo->Reserved[2]);
Packit Service 5a9772
	WLog_INFO(TAG, "\tNTLMRevisionCurrent: 0x%02" PRIX8 "", versionInfo->NTLMRevisionCurrent);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t size;
Packit Service 5a9772
	if (Stream_GetRemainingLength(s) < 28)
Packit Service 5a9772
		return -1;
Packit Service 5a9772
Packit 1fb8d4
	Stream_Read_UINT8(s, challenge->RespType);
Packit 1fb8d4
	Stream_Read_UINT8(s, challenge->HiRespType);
Packit 1fb8d4
	Stream_Read_UINT16(s, challenge->Reserved1);
Packit 1fb8d4
	Stream_Read_UINT32(s, challenge->Reserved2);
Packit 1fb8d4
	Stream_Read(s, challenge->Timestamp, 8);
Packit 1fb8d4
	Stream_Read(s, challenge->ClientChallenge, 8);
Packit 1fb8d4
	Stream_Read_UINT32(s, challenge->Reserved3);
Packit 1fb8d4
	size = Stream_Length(s) - Stream_GetPosition(s);
Packit 1fb8d4
Packit 1fb8d4
	if (size > UINT32_MAX)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	challenge->cbAvPairs = size;
Packit Service 5a9772
	challenge->AvPairs = (NTLM_AV_PAIR*)malloc(challenge->cbAvPairs);
Packit 1fb8d4
Packit 1fb8d4
	if (!challenge->AvPairs)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, challenge->AvPairs, size);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG length;
Packit 1fb8d4
	Stream_Write_UINT8(s, challenge->RespType);
Packit 1fb8d4
	Stream_Write_UINT8(s, challenge->HiRespType);
Packit 1fb8d4
	Stream_Write_UINT16(s, challenge->Reserved1);
Packit 1fb8d4
	Stream_Write_UINT32(s, challenge->Reserved2);
Packit 1fb8d4
	Stream_Write(s, challenge->Timestamp, 8);
Packit 1fb8d4
	Stream_Write(s, challenge->ClientChallenge, 8);
Packit 1fb8d4
	Stream_Write_UINT32(s, challenge->Reserved3);
Packit 1fb8d4
	length = ntlm_av_pair_list_length(challenge->AvPairs, challenge->cbAvPairs);
Packit 1fb8d4
	Stream_Write(s, challenge->AvPairs, length);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
Packit 1fb8d4
{
Packit Service 5a9772
	if (Stream_GetRemainingLength(s) < 16)
Packit Service 5a9772
		return -1;
Packit 1fb8d4
	Stream_Read(s, response->Response, 16);
Packit 1fb8d4
	return ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
Packit 1fb8d4
{
Packit 1fb8d4
	Stream_Write(s, response->Response, 16);
Packit 1fb8d4
	return ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Get current time, in tenths of microseconds since midnight of January 1, 1601.
Packit 1fb8d4
 * @param[out] timestamp 64-bit little-endian timestamp
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_current_time(BYTE* timestamp)
Packit 1fb8d4
{
Packit 1fb8d4
	FILETIME filetime;
Packit 1fb8d4
	ULARGE_INTEGER time64;
Packit 1fb8d4
	GetSystemTimeAsFileTime(&filetime);
Packit Service 5a9772
	time64.u.LowPart = filetime.dwLowDateTime;
Packit Service 5a9772
	time64.u.HighPart = filetime.dwHighDateTime;
Packit 1fb8d4
	CopyMemory(timestamp, &(time64.QuadPart), 8);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate timestamp for AUTHENTICATE_MESSAGE.
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_timestamp(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (memcmp(context->ChallengeTimestamp, NTLM_NULL_BUFFER, 8) != 0)
Packit 1fb8d4
		CopyMemory(context->Timestamp, context->ChallengeTimestamp, 8);
Packit 1fb8d4
	else
Packit 1fb8d4
		ntlm_current_time(context->Timestamp);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_SAM* sam;
Packit 1fb8d4
	WINPR_SAM_ENTRY* entry;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials = context->credentials;
Packit 1fb8d4
	sam = SamOpen(context->SamFile, TRUE);
Packit 1fb8d4
Packit 1fb8d4
	if (!sam)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit Service 5a9772
	entry = SamLookupUserW(
Packit Service 5a9772
	    sam, (LPWSTR)credentials->identity.User, credentials->identity.UserLength * 2,
Packit Service 5a9772
	    (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * 2);
Packit 1fb8d4
Packit 1fb8d4
	if (entry)
Packit 1fb8d4
	{
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
		WLog_DBG(TAG, "NTLM Hash:");
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16);
Packit 1fb8d4
#endif
Packit Service 5a9772
		NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User,
Packit Service 5a9772
		                 credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
Packit Service 5a9772
		                 credentials->identity.DomainLength * 2, (BYTE*)hash);
Packit 1fb8d4
		SamFreeEntry(sam, entry);
Packit 1fb8d4
		SamClose(sam);
Packit 1fb8d4
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	entry = SamLookupUserW(sam, (LPWSTR)credentials->identity.User,
Packit 1fb8d4
	                       credentials->identity.UserLength * 2, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (entry)
Packit 1fb8d4
	{
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
		WLog_DBG(TAG, "NTLM Hash:");
Packit 1fb8d4
		winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16);
Packit 1fb8d4
#endif
Packit Service 5a9772
		NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User,
Packit Service 5a9772
		                 credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
Packit Service 5a9772
		                 credentials->identity.DomainLength * 2, (BYTE*)hash);
Packit 1fb8d4
		SamFreeEntry(sam, entry);
Packit 1fb8d4
		SamClose(sam);
Packit 1fb8d4
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		SamClose(sam);
Packit 1fb8d4
		WLog_ERR(TAG, "Error: Could not find user in SAM database");
Packit 1fb8d4
		return 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	SamClose(sam);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	int i, hn, ln;
Packit 1fb8d4
	char* PasswordHash = NULL;
Packit 1fb8d4
	UINT32 PasswordHashLength = 0;
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials = context->credentials;
Packit Service 5a9772
	/* Password contains a password hash of length (PasswordLength -
Packit Service 5a9772
	 * SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) */
Packit 1fb8d4
	PasswordHashLength = credentials->identity.PasswordLength - SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
Packit Service 5a9772
	status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR)credentials->identity.Password,
Packit 1fb8d4
	                            PasswordHashLength, &PasswordHash, 0, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	CharUpperBuffA(PasswordHash, PasswordHashLength);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < 32; i += 2)
Packit 1fb8d4
	{
Packit 1fb8d4
		hn = PasswordHash[i] > '9' ? PasswordHash[i] - 'A' + 10 : PasswordHash[i] - '0';
Packit 1fb8d4
		ln = PasswordHash[i + 1] > '9' ? PasswordHash[i + 1] - 'A' + 10 : PasswordHash[i + 1] - '0';
Packit 1fb8d4
		hash[i / 2] = (hn << 4) | ln;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(PasswordHash);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
Packit 1fb8d4
{
Packit 1fb8d4
	SSPI_CREDENTIALS* credentials = context->credentials;
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
Packit 1fb8d4
	if (credentials)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_DBG(TAG, "Password (length = %" PRIu32 ")", credentials->identity.PasswordLength * 2);
Packit Service 5a9772
		winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*)credentials->identity.Password,
Packit 1fb8d4
		              credentials->identity.PasswordLength * 2);
Packit Service 5a9772
		WLog_DBG(TAG, "Username (length = %" PRIu32 ")", credentials->identity.UserLength * 2);
Packit Service 5a9772
		winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*)credentials->identity.User,
Packit 1fb8d4
		              credentials->identity.UserLength * 2);
Packit Service 5a9772
		WLog_DBG(TAG, "Domain (length = %" PRIu32 ")", credentials->identity.DomainLength * 2);
Packit Service 5a9772
		winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*)credentials->identity.Domain,
Packit 1fb8d4
		              credentials->identity.DomainLength * 2);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
		WLog_DBG(TAG, "Strange, NTLM_CONTEXT is missing valid credentials...");
Packit 1fb8d4
Packit Service 5a9772
	WLog_DBG(TAG, "Workstation (length = %" PRIu16 ")", context->Workstation.Length);
Packit Service 5a9772
	winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*)context->Workstation.Buffer, context->Workstation.Length);
Packit 1fb8d4
	WLog_DBG(TAG, "NTOWFv2, NTLMv2 Hash");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (memcmp(context->NtlmV2Hash, NTLM_NULL_BUFFER, 16) != 0)
Packit 1fb8d4
		return 1;
Packit 1fb8d4
Packit Service 5a9772
	if (!credentials)
Packit Service 5a9772
		return -1;
Packit Service 5a9772
	else if (memcmp(context->NtlmHash, NTLM_NULL_BUFFER, 16) != 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		NTOWFv2FromHashW(context->NtlmHash, (LPWSTR)credentials->identity.User,
Packit Service 5a9772
		                 credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
Packit Service 5a9772
		                 credentials->identity.DomainLength * 2, (BYTE*)hash);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (credentials->identity.PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Special case for WinPR: password hash */
Packit 1fb8d4
		if (ntlm_convert_password_hash(context, context->NtlmHash) < 0)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit Service 5a9772
		NTOWFv2FromHashW(context->NtlmHash, (LPWSTR)credentials->identity.User,
Packit Service 5a9772
		                 credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
Packit Service 5a9772
		                 credentials->identity.DomainLength * 2, (BYTE*)hash);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (credentials->identity.Password)
Packit 1fb8d4
	{
Packit Service 5a9772
		NTOWFv2W((LPWSTR)credentials->identity.Password, credentials->identity.PasswordLength * 2,
Packit Service 5a9772
		         (LPWSTR)credentials->identity.User, credentials->identity.UserLength * 2,
Packit Service 5a9772
		         (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * 2,
Packit Service 5a9772
		         (BYTE*)hash);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (context->HashCallback)
Packit 1fb8d4
	{
Packit 1fb8d4
		int ret;
Packit 1fb8d4
		SecBuffer proofValue, micValue;
Packit 1fb8d4
Packit 1fb8d4
		if (ntlm_computeProofValue(context, &proofValue) != SEC_E_OK)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		if (ntlm_computeMicValue(context, &micValue) != SEC_E_OK)
Packit 1fb8d4
		{
Packit 1fb8d4
			sspi_SecBufferFree(&proofValue);
Packit 1fb8d4
			return -1;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		ret = context->HashCallback(context->HashCallbackArg, &credentials->identity, &proofValue,
Packit 1fb8d4
		                            context->EncryptedRandomSessionKey,
Packit 1fb8d4
		                            (&context->AUTHENTICATE_MESSAGE)->MessageIntegrityCheck,
Packit 1fb8d4
		                            &micValue, hash);
Packit 1fb8d4
		sspi_SecBufferFree(&proofValue);
Packit 1fb8d4
		sspi_SecBufferFree(&micValue);
Packit 1fb8d4
		return ret ? 1 : -1;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (context->UseSamFileDatabase)
Packit 1fb8d4
	{
Packit 1fb8d4
		return ntlm_fetch_ntlm_v2_hash(context, hash);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* response;
Packit 1fb8d4
	BYTE value[WINPR_MD5_DIGEST_LENGTH];
Packit 1fb8d4
Packit 1fb8d4
	if (context->LmCompatibilityLevel < 2)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
Packit 1fb8d4
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Compute the NTLMv2 hash */
Packit 1fb8d4
Packit 1fb8d4
	if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	/* Concatenate the server and client challenges */
Packit 1fb8d4
	CopyMemory(value, context->ServerChallenge, 8);
Packit 1fb8d4
	CopyMemory(&value[8], context->ClientChallenge, 8);
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit Service 5a9772
	response = (BYTE*)context->LmChallengeResponse.pvBuffer;
Packit 1fb8d4
	/* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */
Packit Service 5a9772
	winpr_HMAC(WINPR_MD_MD5, (void*)context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*)value,
Packit Service 5a9772
	           WINPR_MD5_DIGEST_LENGTH, (BYTE*)response, WINPR_MD5_DIGEST_LENGTH);
Packit Service 5a9772
	/* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response
Packit Service 5a9772
	 * (24 bytes) */
Packit 1fb8d4
	CopyMemory(&response[16], context->ClientChallenge, 8);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Compute NTLMv2 Response.
Packit 1fb8d4
 * NTLMv2_RESPONSE @msdn{cc236653}
Packit 1fb8d4
 * NTLMv2 Authentication @msdn{cc236700}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* blob;
Packit Service 5a9772
	SecBuffer ntlm_v2_temp = { 0 };
Packit Service 5a9772
	SecBuffer ntlm_v2_temp_chal = { 0 };
Packit Service 5a9772
	PSecBuffer TargetInfo = &context->ChallengeTargetInfo;
Packit Service 5a9772
	int ret = -1;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28))
Packit Service 5a9772
		goto exit;
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
Packit Service 5a9772
	blob = (BYTE*)ntlm_v2_temp.pvBuffer;
Packit 1fb8d4
Packit 1fb8d4
	/* Compute the NTLMv2 hash */
Packit Service 5a9772
	if (ntlm_compute_ntlm_v2_hash(context, (BYTE*)context->NtlmV2Hash) < 0)
Packit Service 5a9772
		goto exit;
Packit 1fb8d4
Packit 1fb8d4
	/* Construct temp */
Packit 1fb8d4
	blob[0] = 1; /* RespType (1 byte) */
Packit 1fb8d4
	blob[1] = 1; /* HighRespType (1 byte) */
Packit 1fb8d4
	/* Reserved1 (2 bytes) */
Packit 1fb8d4
	/* Reserved2 (4 bytes) */
Packit Service 5a9772
	CopyMemory(&blob[8], context->Timestamp, 8);        /* Timestamp (8 bytes) */
Packit 1fb8d4
	CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */
Packit 1fb8d4
	/* Reserved3 (4 bytes) */
Packit 1fb8d4
	CopyMemory(&blob[28], TargetInfo->pvBuffer, TargetInfo->cbBuffer);
Packit 1fb8d4
#ifdef WITH_DEBUG_NTLM
Packit 1fb8d4
	WLog_DBG(TAG, "NTLMv2 Response Temp Blob");
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	/* Concatenate server challenge with temp */
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8))
Packit Service 5a9772
		goto exit;
Packit 1fb8d4
Packit Service 5a9772
	blob = (BYTE*)ntlm_v2_temp_chal.pvBuffer;
Packit 1fb8d4
	CopyMemory(blob, context->ServerChallenge, 8);
Packit 1fb8d4
	CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
Packit Service 5a9772
	winpr_HMAC(WINPR_MD_MD5, (BYTE*)context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH,
Packit Service 5a9772
	           (BYTE*)ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer,
Packit Service 5a9772
	           context->NtProofString, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
Packit 1fb8d4
	/* NtChallengeResponse, Concatenate NTProofStr with temp */
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16))
Packit Service 5a9772
		goto exit;
Packit 1fb8d4
Packit Service 5a9772
	blob = (BYTE*)context->NtChallengeResponse.pvBuffer;
Packit Service 5a9772
	CopyMemory(blob, context->NtProofString, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
	CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
Packit 1fb8d4
	/* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */
Packit Service 5a9772
	winpr_HMAC(WINPR_MD_MD5, (BYTE*)context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH,
Packit Service 5a9772
	           context->NtProofString, WINPR_MD5_DIGEST_LENGTH, context->SessionBaseKey,
Packit Service 5a9772
	           WINPR_MD5_DIGEST_LENGTH);
Packit Service 5a9772
	ret = 1;
Packit Service 5a9772
exit:
Packit 1fb8d4
	sspi_SecBufferFree(&ntlm_v2_temp);
Packit 1fb8d4
	sspi_SecBufferFree(&ntlm_v2_temp_chal);
Packit Service 5a9772
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Encrypt the given plain text using RC4 and the given key.
Packit 1fb8d4
 * @param key RC4 key
Packit 1fb8d4
 * @param length text length
Packit 1fb8d4
 * @param plaintext plain text
Packit 1fb8d4
 * @param ciphertext cipher text
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_RC4_CTX* rc4 = winpr_RC4_New(key, 16);
Packit 1fb8d4
Packit 1fb8d4
	if (rc4)
Packit 1fb8d4
	{
Packit 1fb8d4
		winpr_RC4_Update(rc4, length, plaintext, ciphertext);
Packit 1fb8d4
		winpr_RC4_Free(rc4);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate client challenge (8-byte nonce).
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_client_challenge(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	/* ClientChallenge is used in computation of LMv2 and NTLMv2 responses */
Packit 1fb8d4
	if (memcmp(context->ClientChallenge, NTLM_NULL_BUFFER, 8) == 0)
Packit 1fb8d4
		winpr_RAND(context->ClientChallenge, 8);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate server challenge (8-byte nonce).
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_server_challenge(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (memcmp(context->ServerChallenge, NTLM_NULL_BUFFER, 8) == 0)
Packit 1fb8d4
		winpr_RAND(context->ServerChallenge, 8);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate KeyExchangeKey (the 128-bit SessionBaseKey).
Packit 1fb8d4
 * @msdn{cc236710}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_key_exchange_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	/* In NTLMv2, KeyExchangeKey is the 128-bit SessionBaseKey */
Packit 1fb8d4
	CopyMemory(context->KeyExchangeKey, context->SessionBaseKey, 16);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate RandomSessionKey (16-byte nonce).
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_random_session_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	winpr_RAND(context->RandomSessionKey, 16);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate ExportedSessionKey (the RandomSessionKey, exported)
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_exported_session_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	CopyMemory(context->ExportedSessionKey, context->RandomSessionKey, 16);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Encrypt RandomSessionKey (RC4-encrypted RandomSessionKey, using KeyExchangeKey as the key).
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_encrypt_random_session_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit Service 5a9772
	/* In NTLMv2, EncryptedRandomSessionKey is the ExportedSessionKey RC4-encrypted with the
Packit Service 5a9772
	 * KeyExchangeKey */
Packit 1fb8d4
	ntlm_rc4k(context->KeyExchangeKey, 16, context->RandomSessionKey,
Packit 1fb8d4
	          context->EncryptedRandomSessionKey);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Decrypt RandomSessionKey (RC4-encrypted RandomSessionKey, using KeyExchangeKey as the key).
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit Service 5a9772
	/* In NTLMv2, EncryptedRandomSessionKey is the ExportedSessionKey RC4-encrypted with the
Packit Service 5a9772
	 * KeyExchangeKey */
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * 	if (NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
Packit Service 5a9772
	 * 		Set RandomSessionKey to RC4K(KeyExchangeKey,
Packit Service 5a9772
	 * AUTHENTICATE_MESSAGE.EncryptedRandomSessionKey) else Set RandomSessionKey to KeyExchangeKey
Packit 1fb8d4
	 */
Packit 1fb8d4
	if (context->NegotiateKeyExchange)
Packit 1fb8d4
		ntlm_rc4k(context->KeyExchangeKey, 16, context->EncryptedRandomSessionKey,
Packit 1fb8d4
		          context->RandomSessionKey);
Packit 1fb8d4
	else
Packit 1fb8d4
		CopyMemory(context->RandomSessionKey, context->KeyExchangeKey, 16);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate signing key.
Packit 1fb8d4
 * @msdn{cc236711}
Packit 1fb8d4
 * @param exported_session_key ExportedSessionKey
Packit 1fb8d4
 * @param sign_magic Sign magic string
Packit 1fb8d4
 * @param signing_key Destination signing key
Packit 1fb8d4
 */
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic,
Packit Service 5a9772
                                     BYTE* signing_key)
Packit 1fb8d4
{
Packit 1fb8d4
	int length;
Packit 1fb8d4
	BYTE* value;
Packit 1fb8d4
	length = WINPR_MD5_DIGEST_LENGTH + sign_magic->cbBuffer;
Packit Service 5a9772
	value = (BYTE*)malloc(length);
Packit 1fb8d4
Packit 1fb8d4
	if (!value)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	/* Concatenate ExportedSessionKey with sign magic */
Packit 1fb8d4
	CopyMemory(value, exported_session_key, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
	CopyMemory(&value[WINPR_MD5_DIGEST_LENGTH], sign_magic->pvBuffer, sign_magic->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Digest(WINPR_MD_MD5, value, length, signing_key, WINPR_MD5_DIGEST_LENGTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		free(value);
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(value);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate client signing key (ClientSigningKey).
Packit 1fb8d4
 * @msdn{cc236711}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	SecBuffer signMagic;
Packit Service 5a9772
	signMagic.pvBuffer = (void*)NTLM_CLIENT_SIGN_MAGIC;
Packit 1fb8d4
	signMagic.cbBuffer = sizeof(NTLM_CLIENT_SIGN_MAGIC);
Packit 1fb8d4
	ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ClientSigningKey);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate server signing key (ServerSigningKey).
Packit 1fb8d4
 * @msdn{cc236711}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	SecBuffer signMagic;
Packit Service 5a9772
	signMagic.pvBuffer = (void*)NTLM_SERVER_SIGN_MAGIC;
Packit 1fb8d4
	signMagic.cbBuffer = sizeof(NTLM_SERVER_SIGN_MAGIC);
Packit 1fb8d4
	ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ServerSigningKey);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate sealing key.
Packit 1fb8d4
 * @msdn{cc236712}
Packit 1fb8d4
 * @param exported_session_key ExportedSessionKey
Packit 1fb8d4
 * @param seal_magic Seal magic string
Packit 1fb8d4
 * @param sealing_key Destination sealing key
Packit 1fb8d4
 */
Packit 1fb8d4
Packit Service 5a9772
static int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic,
Packit Service 5a9772
                                     BYTE* sealing_key)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* p;
Packit 1fb8d4
	SecBuffer buffer;
Packit 1fb8d4
Packit 1fb8d4
	if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit Service 5a9772
	p = (BYTE*)buffer.pvBuffer;
Packit 1fb8d4
	/* Concatenate ExportedSessionKey with seal magic */
Packit 1fb8d4
	CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
	CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer);
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Digest(WINPR_MD_MD5, buffer.pvBuffer, buffer.cbBuffer, sealing_key,
Packit 1fb8d4
	                  WINPR_MD5_DIGEST_LENGTH))
Packit 1fb8d4
	{
Packit 1fb8d4
		sspi_SecBufferFree(&buffer);
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	sspi_SecBufferFree(&buffer);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate client sealing key (ClientSealingKey).
Packit 1fb8d4
 * @msdn{cc236712}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	SecBuffer sealMagic;
Packit Service 5a9772
	sealMagic.pvBuffer = (void*)NTLM_CLIENT_SEAL_MAGIC;
Packit 1fb8d4
	sealMagic.cbBuffer = sizeof(NTLM_CLIENT_SEAL_MAGIC);
Packit 1fb8d4
	ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ClientSealingKey);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generate server sealing key (ServerSealingKey).
Packit 1fb8d4
 * @msdn{cc236712}
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	SecBuffer sealMagic;
Packit Service 5a9772
	sealMagic.pvBuffer = (void*)NTLM_SERVER_SEAL_MAGIC;
Packit 1fb8d4
	sealMagic.cbBuffer = sizeof(NTLM_SERVER_SEAL_MAGIC);
Packit 1fb8d4
	ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ServerSealingKey);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Initialize RC4 stream cipher states for sealing.
Packit 1fb8d4
 * @param NTLM context
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (context->server)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->SendSigningKey = context->ServerSigningKey;
Packit 1fb8d4
		context->RecvSigningKey = context->ClientSigningKey;
Packit 1fb8d4
		context->SendSealingKey = context->ClientSealingKey;
Packit 1fb8d4
		context->RecvSealingKey = context->ServerSealingKey;
Packit 1fb8d4
		context->SendRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16);
Packit 1fb8d4
		context->RecvRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		context->SendSigningKey = context->ClientSigningKey;
Packit 1fb8d4
		context->RecvSigningKey = context->ServerSigningKey;
Packit 1fb8d4
		context->SendSealingKey = context->ServerSealingKey;
Packit 1fb8d4
		context->RecvSealingKey = context->ClientSealingKey;
Packit 1fb8d4
		context->SendRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16);
Packit 1fb8d4
		context->RecvRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context, BYTE* mic, UINT32 size)
Packit 1fb8d4
{
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE,
Packit 1fb8d4
	 * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey
Packit 1fb8d4
	 */
Packit 1fb8d4
	WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
Packit 1fb8d4
	assert(size >= WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
Packit 1fb8d4
	if (!hmac)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	if (winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->ExportedSessionKey, WINPR_MD5_DIGEST_LENGTH))
Packit 1fb8d4
	{
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (BYTE*)context->NegotiateMessage.pvBuffer,
Packit 1fb8d4
		                  context->NegotiateMessage.cbBuffer);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (BYTE*)context->ChallengeMessage.pvBuffer,
Packit 1fb8d4
		                  context->ChallengeMessage.cbBuffer);
Packit Service 5a9772
		winpr_HMAC_Update(hmac, (BYTE*)context->AuthenticateMessage.pvBuffer,
Packit 1fb8d4
		                  context->AuthenticateMessage.cbBuffer);
Packit 1fb8d4
		winpr_HMAC_Final(hmac, mic, WINPR_MD5_DIGEST_LENGTH);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	winpr_HMAC_Free(hmac);
Packit 1fb8d4
}