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

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. wzcsec.c
  5. Abstract:
  6. This module contains code for providing security functions
  7. Revision History:
  8. sachins, Dec 04 2001, Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. UCHAR SHApad1[40] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  13. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  14. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  15. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  16. UCHAR SHApad2[40] = {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
  17. 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
  18. 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
  19. 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
  20. VOID
  21. GetNewKeyFromSHA (
  22. IN UCHAR *StartKey,
  23. IN UCHAR *SessionKey,
  24. IN DWORD SessionKeyLength,
  25. OUT UCHAR *InterimKey
  26. )
  27. {
  28. A_SHA_CTX Context;
  29. UCHAR Digest[A_SHA_DIGEST_LEN];
  30. ZeroMemory(Digest, A_SHA_DIGEST_LEN);
  31. A_SHAInit(&Context);
  32. A_SHAUpdate(&Context, StartKey, SessionKeyLength);
  33. A_SHAUpdate(&Context, SHApad1, 40);
  34. A_SHAUpdate(&Context, SessionKey, SessionKeyLength);
  35. A_SHAUpdate(&Context, SHApad2, 40);
  36. A_SHAFinal(&Context, Digest);
  37. CopyMemory (InterimKey, Digest, SessionKeyLength);
  38. }
  39. #define MAX_TOTAL_KEY_LENGTH 128
  40. #define MAX_TOTAL_IV_LENGTH 64
  41. DWORD
  42. GenerateMasterSessionKeys (
  43. PBYTE pbSecret,
  44. DWORD cbSecret,
  45. PBYTE pbRandom,
  46. DWORD cbRandom,
  47. PMASTER_SESSION_KEYS pMasterSessionKeys
  48. )
  49. {
  50. BYTE bPRF1[MAX_TOTAL_KEY_LENGTH]={0}, bPRF2[MAX_TOTAL_IV_LENGTH]={0};
  51. BOOL fResult = FALSE;
  52. DWORD dwRetCode = NO_ERROR;
  53. do
  54. {
  55. fResult = PRF (
  56. pbSecret,
  57. cbSecret,
  58. csz_CLIENT_EAP_ENCRYPTION,
  59. strlen (csz_CLIENT_EAP_ENCRYPTION),
  60. pbRandom,
  61. cbRandom,
  62. bPRF1,
  63. MAX_TOTAL_KEY_LENGTH
  64. );
  65. if (!fResult)
  66. {
  67. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  68. break;
  69. }
  70. CopyMemory ((PBYTE)pMasterSessionKeys,
  71. bPRF1,
  72. MAX_TOTAL_KEY_LENGTH);
  73. fResult = PRF (
  74. pbSecret,
  75. cbSecret,
  76. csz_CLIENT_EAP_ENCRYPTION,
  77. strlen(csz_CLIENT_EAP_ENCRYPTION),
  78. pbRandom,
  79. cbRandom,
  80. bPRF2,
  81. MAX_TOTAL_IV_LENGTH
  82. );
  83. if (!fResult)
  84. {
  85. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  86. break;
  87. }
  88. CopyMemory ((PBYTE)pMasterSessionKeys+MAX_TOTAL_KEY_LENGTH,
  89. bPRF2,
  90. MAX_TOTAL_IV_LENGTH);
  91. }
  92. while (FALSE);
  93. return dwRetCode;
  94. }
  95. DWORD
  96. DeriveSessionKeys (
  97. PBYTE pbMasterSendKey,
  98. PBYTE pbMasterReceiveKey,
  99. DWORD dwSessionKeyLength,
  100. PSESSION_KEYS pSessionKeys
  101. )
  102. {
  103. PBYTE pbSendKey = pSessionKeys->bSendKey;
  104. PBYTE pbReceiveKey = pSessionKeys->bReceiveKey;
  105. DWORD dwEffectiveMasterKeyLength = 0;
  106. BOOLEAN fReduceKeysStrength = FALSE;
  107. DWORD dwRetCode = NO_ERROR;
  108. switch (dwSessionKeyLength*8)
  109. {
  110. case 40:
  111. fReduceKeysStrength = TRUE;
  112. case 56:
  113. dwEffectiveMasterKeyLength = 8;
  114. break;
  115. case 104:
  116. fReduceKeysStrength = TRUE;
  117. case 128:
  118. dwEffectiveMasterKeyLength = 16;
  119. break;
  120. case 168:
  121. fReduceKeysStrength = TRUE;
  122. case 192:
  123. dwEffectiveMasterKeyLength = 24;
  124. break;
  125. default:
  126. dwRetCode = ERROR_INVALID_PARAMETER;
  127. break;
  128. }
  129. if (dwRetCode != NO_ERROR)
  130. {
  131. return dwRetCode;
  132. }
  133. do
  134. {
  135. GetNewKeyFromSHA (
  136. pbMasterSendKey,
  137. pbMasterSendKey,
  138. dwEffectiveMasterKeyLength,
  139. pSessionKeys->bSendKey
  140. );
  141. GetNewKeyFromSHA (
  142. pbMasterReceiveKey,
  143. pbMasterReceiveKey,
  144. dwEffectiveMasterKeyLength,
  145. pSessionKeys->bReceiveKey
  146. );
  147. if (fReduceKeysStrength)
  148. {
  149. pbSendKey[0] = pbReceiveKey[0]= 0xD1;
  150. pbSendKey[1] = pbReceiveKey[1]= 0x26;
  151. pbSendKey[2] = pbReceiveKey[2]= 0x9E;
  152. }
  153. }
  154. while (FALSE);
  155. return dwRetCode;
  156. }
  157. #define NUM_IGNORE_BYTES 3
  158. DWORD
  159. GenerateDynamicKeys (
  160. IN PBYTE pbMasterSecret,
  161. IN DWORD dwMasterSecretLength,
  162. IN PBYTE pbRandom,
  163. IN DWORD dwRandomLength,
  164. IN DWORD dwDynamicKeyLength,
  165. OUT SESSION_KEYS *pSessionKeys
  166. )
  167. {
  168. MASTER_SESSION_KEYS MasterKeys = {0};
  169. SESSION_KEYS SessionKeys = {0};
  170. BOOLEAN fIgnoreThreeLeadingBytes = FALSE;
  171. DWORD dwRetCode = NO_ERROR;
  172. do
  173. {
  174. if (IsBadWritePtr(pSessionKeys, sizeof(SESSION_KEYS)))
  175. {
  176. dwRetCode = ERROR_INVALID_PARAMETER;
  177. break;
  178. }
  179. switch (dwDynamicKeyLength*8)
  180. {
  181. case 40:
  182. case 104:
  183. case 168:
  184. fIgnoreThreeLeadingBytes = TRUE;
  185. break;
  186. }
  187. if ((dwRetCode = GenerateMasterSessionKeys (
  188. pbMasterSecret,
  189. dwMasterSecretLength,
  190. pbRandom,
  191. dwRandomLength,
  192. &MasterKeys
  193. )) != NO_ERROR)
  194. {
  195. break;
  196. }
  197. // Use Peer Encryption (P->A) key as the Master Send Key
  198. // Use Authenticator Encryption (A->P) key as the Master Receive Key
  199. if ((dwRetCode = DeriveSessionKeys (
  200. MasterKeys.bPeerEncryptionKey,
  201. MasterKeys.bAuthenticatorEncryptionKey,
  202. dwDynamicKeyLength,
  203. &SessionKeys
  204. )) != NO_ERROR)
  205. {
  206. break;
  207. }
  208. ZeroMemory(pSessionKeys, sizeof(SESSION_KEYS));
  209. pSessionKeys->dwKeyLength = dwDynamicKeyLength;
  210. memcpy(pSessionKeys->bSendKey,
  211. SessionKeys.bSendKey + (fIgnoreThreeLeadingBytes?NUM_IGNORE_BYTES:0),
  212. dwDynamicKeyLength);
  213. memcpy(pSessionKeys->bReceiveKey,
  214. SessionKeys.bReceiveKey + (fIgnoreThreeLeadingBytes?NUM_IGNORE_BYTES:0),
  215. dwDynamicKeyLength);
  216. }
  217. while (FALSE);
  218. return dwRetCode;
  219. }