windows-nt/Source/XPSP1/NT/net/layer2svc/eapol/service/elkey.c
2020-09-26 16:20:57 +08:00

390 lines
10 KiB
C

/*++
Copyright (c) 1999, Microsoft Corporation
Module Name:
elkey.c
Abstract:
This module deals with the key management for EAPOL
Revision History:
Dec 26 2001, Created
--*/
#include "pcheapol.h"
#pragma hdrstop
DWORD
ElQueryMasterKeys (
IN EAPOL_PCB *pPCB,
IN OUT SESSION_KEYS *pSessionKeys
)
{
SESSION_KEYS WZCSessionKeys = {0};
SESSION_KEYS EAPOLSessionKeys = {0};
BOOLEAN fGotWZCKeys = FALSE, fGotEAPOLKeys = FALSE;
DWORD dwRetCode = NO_ERROR;
do
{
if ((dwRetCode = ElQueryWZCMasterKeys (
pPCB,
&WZCSessionKeys
)) != NO_ERROR)
{
TRACE1 (ANY, "ElQueryMasterKeys: ElQueryWZCMasterKeys failed with error %ld",
dwRetCode);
dwRetCode = NO_ERROR;
}
else
{
fGotWZCKeys = TRUE;
}
if (WZCSessionKeys.dwKeyLength == 0)
{
fGotWZCKeys = FALSE;
}
if ((dwRetCode = ElQueryEAPOLMasterKeys (
pPCB,
&EAPOLSessionKeys
)) != NO_ERROR)
{
TRACE1 (ANY, "ElQueryMasterKeys: ElQueryEAPOLMasterKeys failed with error %ld",
dwRetCode);
dwRetCode = NO_ERROR;
}
else
{
fGotEAPOLKeys = TRUE;
}
if (EAPOLSessionKeys.dwKeyLength == 0)
{
fGotEAPOLKeys = FALSE;
}
if (fGotEAPOLKeys)
{
TRACE0 (ANY, "ElQueryMasterKeys: Using EAPOL Keys as Master Keys for Re-keying");
memcpy ((PBYTE)pSessionKeys, (PBYTE)&EAPOLSessionKeys,
sizeof(SESSION_KEYS));
pPCB->fLastUsedEAPOLKeys = TRUE;
}
else
{
if (fGotWZCKeys)
{
TRACE0 (ANY, "ElQueryMasterKeys: Using WZC Keys as Master Keys for Re-keying");
memcpy ((PBYTE)pSessionKeys, (PBYTE)&WZCSessionKeys,
sizeof(SESSION_KEYS));
pPCB->fLastUsedEAPOLKeys = FALSE;
}
else
{
DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_NOT_CONFIGURED_KEYS);
TRACE0 (ANY, "ElQueryMasterKeys: Did not get any keys. Error !!");
dwRetCode = ERROR_INVALID_DATA;
}
}
}
while (FALSE);
return dwRetCode;
}
DWORD
ElSetMasterKeys (
IN EAPOL_PCB *pPCB,
IN SESSION_KEYS *pSessionKeys
)
{
DWORD dwRetCode = NO_ERROR;
do
{
if (pPCB->fLastUsedEAPOLKeys)
{
TRACE0 (ANY, "ElSetMasterKeys: Updating EAPOL Keys after Re-keying");
if ((dwRetCode = ElSetEAPOLMasterKeys (
pPCB,
pSessionKeys
)) != NO_ERROR)
{
TRACE1 (ANY, "ElSetMasterKeys: ElSetMasterKeys failed with error %ld",
dwRetCode);
dwRetCode = NO_ERROR;
}
}
else
{
TRACE0 (ANY, "ElSetMasterKeys: Updating WZC Keys after Re-keying");
if ((dwRetCode = ElSetWZCMasterKeys (
pPCB,
pSessionKeys
)) != NO_ERROR)
{
TRACE1 (ANY, "ElSetMasterKeys: ElSetWZCMasterKeys failed with error %ld",
dwRetCode);
dwRetCode = NO_ERROR;
}
}
// Reset the flag for next run
pPCB->fLastUsedEAPOLKeys = FALSE;
}
while (FALSE);
return dwRetCode;
}
DWORD
ElQueryEAPOLMasterKeys (
IN EAPOL_PCB *pPCB,
IN OUT SESSION_KEYS *pSessionKeys
)
{
SESSION_KEYS EAPOLSessionKeys = {0};
PBYTE pbMasterSecretSend = NULL, pbMasterSecretRecv = NULL;
DWORD dwMasterSecretSendLength = 0, dwMasterSecretRecvLength = 0;
DWORD dwRetCode = NO_ERROR;
do
{
// Access the Master Send and Recv key stored locally
if ((dwRetCode = ElSecureDecodePw (
&(pPCB->MasterSecretSend),
&(pbMasterSecretSend),
&dwMasterSecretSendLength
)) != NO_ERROR)
{
TRACE1 (ANY, "ElQueryEAPOLMasterKeys: ElSecureDecodePw failed for MasterSecretSend with error %ld",
dwRetCode);
break;
}
if ((dwRetCode = ElSecureDecodePw (
&(pPCB->MasterSecretRecv),
&(pbMasterSecretRecv),
&dwMasterSecretRecvLength
)) != NO_ERROR)
{
TRACE1 (ANY, "ElKeyReceivePerSTA: ElSecureDecodePw failed for MasterSecretRecv with error %ld",
dwRetCode);
break;
}
if (dwMasterSecretSendLength != dwMasterSecretRecvLength)
{
dwRetCode = ERROR_INVALID_PARAMETER;
TRACE2 (ANY, "ElQueryEAPOLMasterKeys: Send Secret Length (%ld) != Recv Secret Lenght (%ld): Invalid values",
dwMasterSecretSendLength, dwMasterSecretRecvLength);
break;
}
memcpy (pSessionKeys->bSendKey, pbMasterSecretSend,
dwMasterSecretSendLength);
memcpy (pSessionKeys->bReceiveKey, pbMasterSecretRecv,
dwMasterSecretRecvLength);
pSessionKeys->dwKeyLength = dwMasterSecretSendLength;
}
while (FALSE);
if (pbMasterSecretSend != NULL)
{
FREE (pbMasterSecretSend);
}
if (pbMasterSecretRecv != NULL)
{
FREE (pbMasterSecretRecv);
}
return dwRetCode;
}
DWORD
ElSetEAPOLMasterKeys (
IN EAPOL_PCB *pPCB,
IN SESSION_KEYS *pSessionKeys
)
{
DWORD dwRetCode = NO_ERROR;
do
{
if (pPCB->MasterSecretSend.cbData != 0)
{
FREE (pPCB->MasterSecretSend.pbData);
pPCB->MasterSecretSend.cbData = 0;
pPCB->MasterSecretSend.pbData = NULL;
}
if ((dwRetCode = ElSecureEncodePw (
pSessionKeys->bSendKey,
pSessionKeys->dwKeyLength,
&(pPCB->MasterSecretSend)
)) != NO_ERROR)
{
TRACE1 (ANY, "ElSetEAPOLMasterKeys: ElSecureEncodePw for MasterSecretSend failed with error %ld",
dwRetCode);
break;
}
if (pPCB->MasterSecretRecv.cbData != 0)
{
FREE (pPCB->MasterSecretRecv.pbData);
pPCB->MasterSecretRecv.cbData = 0;
pPCB->MasterSecretRecv.pbData = NULL;
}
if ((dwRetCode = ElSecureEncodePw (
pSessionKeys->bReceiveKey,
pSessionKeys->dwKeyLength,
&(pPCB->MasterSecretRecv)
)) != NO_ERROR)
{
TRACE1 (ANY, "ElSetEAPOLMasterKeys: ElSecureEncodePw for MasterSecretRecv failed with error %ld",
dwRetCode);
break;
}
}
while (FALSE);
return dwRetCode;
}
DWORD
ElQueryWZCMasterKeys (
IN EAPOL_PCB *pPCB,
IN OUT SESSION_KEYS *pSessionKeys
)
{
RAW_DATA rdUserData = {0};
DWORD dwRetCode = NO_ERROR;
do
{
rdUserData.dwDataLen = sizeof (SESSION_KEYS);
rdUserData.pData = (PBYTE)pSessionKeys;
if ((dwRetCode = RpcCmdInterface (
pPCB->dwZeroConfigId,
WZCCMD_SKEY_QUERY,
pPCB->pwszDeviceGUID,
&rdUserData
)) != NO_ERROR)
{
TRACE1 (ANY, "ElQueryWZCMasterKeys: RpcCmdInterface failed with error %ld",
dwRetCode);
}
}
while (FALSE);
return dwRetCode;
}
DWORD
ElSetWZCMasterKeys (
IN EAPOL_PCB *pPCB,
IN SESSION_KEYS *pSessionKeys
)
{
RAW_DATA rdUserData = {0};
DWORD dwRetCode = NO_ERROR;
do
{
rdUserData.dwDataLen = sizeof (SESSION_KEYS);
rdUserData.pData = (PBYTE)pSessionKeys;
if ((dwRetCode = RpcCmdInterface (
pPCB->dwZeroConfigId,
WZCCMD_SKEY_SET,
pPCB->pwszDeviceGUID,
&rdUserData
)) != NO_ERROR)
{
TRACE1 (ANY, "ElSetWZCMasterKeys: RpcCmdInterface failed with error %ld",
dwRetCode);
}
}
while (FALSE);
return dwRetCode;
}
DWORD
ElReloadMasterSecrets (
IN EAPOL_PCB *pPCB
)
{
PBYTE pbSendKey = NULL;
PBYTE pbRecvKey = NULL;
DWORD dwRetCode = NO_ERROR;
do
{
if (pPCB->MPPESendKey.cbData != 0)
{
if ((pbSendKey = MALLOC(pPCB->MPPESendKey.cbData)) == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
memcpy (pbSendKey, pPCB->MPPESendKey.pbData,
pPCB->MPPESendKey.cbData);
}
if (pPCB->MPPERecvKey.cbData != 0)
{
if ((pbRecvKey = MALLOC(pPCB->MPPERecvKey.cbData)) == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
memcpy (pbRecvKey, pPCB->MPPERecvKey.pbData,
pPCB->MPPERecvKey.cbData);
}
if (pPCB->MasterSecretSend.cbData != 0)
{
FREE (pPCB->MasterSecretSend.pbData);
pPCB->MasterSecretSend.cbData = 0;
pPCB->MasterSecretSend.pbData = NULL;
}
pPCB->MasterSecretSend.pbData = pbSendKey;
pPCB->MasterSecretSend.cbData = pPCB->MPPESendKey.cbData;
if (pPCB->MasterSecretRecv.cbData != 0)
{
FREE (pPCB->MasterSecretRecv.pbData);
pPCB->MasterSecretRecv.cbData = 0;
pPCB->MasterSecretRecv.pbData = NULL;
}
pPCB->MasterSecretRecv.pbData = pbRecvKey;
pPCB->MasterSecretRecv.cbData = pPCB->MPPERecvKey.cbData;
}
while (FALSE);
if (dwRetCode != NO_ERROR)
{
if (pbSendKey != NULL)
{
FREE (pbSendKey);
}
if (pbRecvKey != NULL)
{
FREE (pbRecvKey);
}
}
return dwRetCode;
}