Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

260 lines
6.8 KiB

/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
wzcsec.c
Abstract:
This module contains code for providing security functions
Revision History:
sachins, Dec 04 2001, Created
--*/
#include "precomp.h"
#pragma hdrstop
UCHAR SHApad1[40] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
UCHAR SHApad2[40] = {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
VOID
GetNewKeyFromSHA (
IN UCHAR *StartKey,
IN UCHAR *SessionKey,
IN DWORD SessionKeyLength,
OUT UCHAR *InterimKey
)
{
A_SHA_CTX Context;
UCHAR Digest[A_SHA_DIGEST_LEN];
ZeroMemory(Digest, A_SHA_DIGEST_LEN);
A_SHAInit(&Context);
A_SHAUpdate(&Context, StartKey, SessionKeyLength);
A_SHAUpdate(&Context, SHApad1, 40);
A_SHAUpdate(&Context, SessionKey, SessionKeyLength);
A_SHAUpdate(&Context, SHApad2, 40);
A_SHAFinal(&Context, Digest);
CopyMemory (InterimKey, Digest, SessionKeyLength);
}
#define MAX_TOTAL_KEY_LENGTH 128
#define MAX_TOTAL_IV_LENGTH 64
DWORD
GenerateMasterSessionKeys (
PBYTE pbSecret,
DWORD cbSecret,
PBYTE pbRandom,
DWORD cbRandom,
PMASTER_SESSION_KEYS pMasterSessionKeys
)
{
BYTE bPRF1[MAX_TOTAL_KEY_LENGTH]={0}, bPRF2[MAX_TOTAL_IV_LENGTH]={0};
BOOL fResult = FALSE;
DWORD dwRetCode = NO_ERROR;
do
{
fResult = PRF (
pbSecret,
cbSecret,
csz_CLIENT_EAP_ENCRYPTION,
strlen (csz_CLIENT_EAP_ENCRYPTION),
pbRandom,
cbRandom,
bPRF1,
MAX_TOTAL_KEY_LENGTH
);
if (!fResult)
{
dwRetCode = ERROR_CAN_NOT_COMPLETE;
break;
}
CopyMemory ((PBYTE)pMasterSessionKeys,
bPRF1,
MAX_TOTAL_KEY_LENGTH);
fResult = PRF (
pbSecret,
cbSecret,
csz_CLIENT_EAP_ENCRYPTION,
strlen(csz_CLIENT_EAP_ENCRYPTION),
pbRandom,
cbRandom,
bPRF2,
MAX_TOTAL_IV_LENGTH
);
if (!fResult)
{
dwRetCode = ERROR_CAN_NOT_COMPLETE;
break;
}
CopyMemory ((PBYTE)pMasterSessionKeys+MAX_TOTAL_KEY_LENGTH,
bPRF2,
MAX_TOTAL_IV_LENGTH);
}
while (FALSE);
return dwRetCode;
}
DWORD
DeriveSessionKeys (
PBYTE pbMasterSendKey,
PBYTE pbMasterReceiveKey,
DWORD dwSessionKeyLength,
PSESSION_KEYS pSessionKeys
)
{
PBYTE pbSendKey = pSessionKeys->bSendKey;
PBYTE pbReceiveKey = pSessionKeys->bReceiveKey;
DWORD dwEffectiveMasterKeyLength = 0;
BOOLEAN fReduceKeysStrength = FALSE;
DWORD dwRetCode = NO_ERROR;
switch (dwSessionKeyLength*8)
{
case 40:
fReduceKeysStrength = TRUE;
case 56:
dwEffectiveMasterKeyLength = 8;
break;
case 104:
fReduceKeysStrength = TRUE;
case 128:
dwEffectiveMasterKeyLength = 16;
break;
case 168:
fReduceKeysStrength = TRUE;
case 192:
dwEffectiveMasterKeyLength = 24;
break;
default:
dwRetCode = ERROR_INVALID_PARAMETER;
break;
}
if (dwRetCode != NO_ERROR)
{
return dwRetCode;
}
do
{
GetNewKeyFromSHA (
pbMasterSendKey,
pbMasterSendKey,
dwEffectiveMasterKeyLength,
pSessionKeys->bSendKey
);
GetNewKeyFromSHA (
pbMasterReceiveKey,
pbMasterReceiveKey,
dwEffectiveMasterKeyLength,
pSessionKeys->bReceiveKey
);
if (fReduceKeysStrength)
{
pbSendKey[0] = pbReceiveKey[0]= 0xD1;
pbSendKey[1] = pbReceiveKey[1]= 0x26;
pbSendKey[2] = pbReceiveKey[2]= 0x9E;
}
}
while (FALSE);
return dwRetCode;
}
#define NUM_IGNORE_BYTES 3
DWORD
GenerateDynamicKeys (
IN PBYTE pbMasterSecret,
IN DWORD dwMasterSecretLength,
IN PBYTE pbRandom,
IN DWORD dwRandomLength,
IN DWORD dwDynamicKeyLength,
OUT SESSION_KEYS *pSessionKeys
)
{
MASTER_SESSION_KEYS MasterKeys = {0};
SESSION_KEYS SessionKeys = {0};
BOOLEAN fIgnoreThreeLeadingBytes = FALSE;
DWORD dwRetCode = NO_ERROR;
do
{
if (IsBadWritePtr(pSessionKeys, sizeof(SESSION_KEYS)))
{
dwRetCode = ERROR_INVALID_PARAMETER;
break;
}
switch (dwDynamicKeyLength*8)
{
case 40:
case 104:
case 168:
fIgnoreThreeLeadingBytes = TRUE;
break;
}
if ((dwRetCode = GenerateMasterSessionKeys (
pbMasterSecret,
dwMasterSecretLength,
pbRandom,
dwRandomLength,
&MasterKeys
)) != NO_ERROR)
{
break;
}
// Use Peer Encryption (P->A) key as the Master Send Key
// Use Authenticator Encryption (A->P) key as the Master Receive Key
if ((dwRetCode = DeriveSessionKeys (
MasterKeys.bPeerEncryptionKey,
MasterKeys.bAuthenticatorEncryptionKey,
dwDynamicKeyLength,
&SessionKeys
)) != NO_ERROR)
{
break;
}
ZeroMemory(pSessionKeys, sizeof(SESSION_KEYS));
pSessionKeys->dwKeyLength = dwDynamicKeyLength;
memcpy(pSessionKeys->bSendKey,
SessionKeys.bSendKey + (fIgnoreThreeLeadingBytes?NUM_IGNORE_BYTES:0),
dwDynamicKeyLength);
memcpy(pSessionKeys->bReceiveKey,
SessionKeys.bReceiveKey + (fIgnoreThreeLeadingBytes?NUM_IGNORE_BYTES:0),
dwDynamicKeyLength);
}
while (FALSE);
return dwRetCode;
}