/*++ 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; }