Leaked source code of windows server 2003
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.

239 lines
7.3 KiB

  1. #include "stdafx.h"
  2. #include "auth.h"
  3. #include "md5.h"
  4. const CHAR g_cszADVAPI32DllName[] = "ADVAPI32.DLL";
  5. const CHAR g_cszCryptAcquireContextA[] = "CryptAcquireContextA";
  6. const CHAR g_cszCryptCreateHash[] = "CryptCreateHash";
  7. const CHAR g_cszCryptHashData[] = "CryptHashData";
  8. const CHAR g_cszCryptGetHashParam[] = "CryptGetHashParam";
  9. const CHAR g_cszCryptDestroyHash[] = "CryptDestroyHash";
  10. const CHAR g_cszCryptReleaseContext[] = "CryptReleaseContext";
  11. const CHAR g_rgchHexNumMap[] =
  12. {
  13. '0', '1', '2', '3', '4', '5', '6', '7',
  14. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  15. };
  16. const int MD5_HASH_LEN = 16;
  17. void
  18. hmac_md5(
  19. unsigned char* text, /* pointer to data stream */
  20. int text_len, /* length of data stream */
  21. unsigned char* key, /* pointer to authentication key */
  22. int key_len, /* length of authentication key */
  23. BYTE digest[16]) /* caller digest to be filled in */
  24. {
  25. MD5_CTX context;
  26. memset(&context, 0, sizeof(context));
  27. unsigned char k_ipad[65]; /* inner padding -
  28. * key XORd with ipad
  29. */
  30. unsigned char k_opad[65]; /* outer padding -
  31. * key XORd with opad
  32. */
  33. int i;
  34. /* if key is longer than 64 bytes reset it to key=MD5(key) */
  35. if (key_len > 64) {
  36. MD5_CTX tctx;
  37. memset(&tctx, 0, sizeof(tctx));
  38. MD5Init(&tctx);
  39. MD5Update(&tctx, key, key_len);
  40. MD5Final(&tctx);
  41. key = tctx.digest;
  42. key_len = 16;
  43. }
  44. /*
  45. * the HMAC_MD5 transform looks like:
  46. *
  47. * MD5(K XOR opad, MD5(K XOR ipad, text))
  48. *
  49. * where K is an n byte key
  50. * ipad is the byte 0x36 repeated 64 times
  51. * opad is the byte 0x5c repeated 64 times
  52. * and text is the data being protected
  53. */
  54. /* start out by storing key in pads */
  55. ZeroMemory( k_ipad, sizeof k_ipad);
  56. ZeroMemory( k_opad, sizeof k_opad);
  57. CopyMemory( k_ipad, key, key_len);
  58. CopyMemory( k_opad, key, key_len);
  59. /* XOR key with ipad and opad values */
  60. for (i=0; i<64; i++) {
  61. k_ipad[i] ^= 0x36;
  62. k_opad[i] ^= 0x5c;
  63. }
  64. /*
  65. * perform inner MD5
  66. */
  67. MD5Init(&context); /* init context for 1st
  68. * pass */
  69. MD5Update(&context, k_ipad, 64); /* start with inner pad */
  70. MD5Update(&context, text, text_len); /* then text of datagram */
  71. MD5Final(&context); /* finish up 1st pass */
  72. CopyMemory(digest, context.digest, 16);
  73. /*
  74. * perform outer MD5
  75. */
  76. MD5Init(&context); /* init context for 2nd
  77. * pass */
  78. MD5Update(&context, k_opad, 64); /* start with outer pad */
  79. MD5Update(&context, digest, 16); /* then results of 1st
  80. * hash */
  81. MD5Final(&context); /* finish up 2nd pass */
  82. CopyMemory(digest, context.digest, 16);
  83. }
  84. //------------------------------------------------------------------------------------
  85. //
  86. // Initialize the static class members.
  87. //
  88. //------------------------------------------------------------------------------------
  89. CAuthentication* CAuthentication::m_spAuthentication = NULL;
  90. PSTR CAuthentication::GetHMACMD5Result(PSTR pszChallengeInfo, PSTR pszPassword)
  91. {
  92. MD5_CTX MD5Buffer;
  93. memset(&MD5Buffer, 0, sizeof(MD5Buffer));
  94. MD5Init(&MD5Buffer);
  95. MD5Update(&MD5Buffer, (const unsigned char*)pszPassword, lstrlenA(pszPassword));
  96. MD5Final(&MD5Buffer);
  97. BYTE pbHash[16];
  98. PBYTE pbHexHash = NULL; // The MD5 result in hex string format
  99. pbHexHash = new BYTE[MD5DIGESTLEN * 2 + 1];
  100. if (pbHexHash)
  101. {
  102. hmac_md5((unsigned char *) pszChallengeInfo, lstrlenA(pszChallengeInfo), MD5Buffer.digest, sizeof(MD5Buffer.digest), pbHash);
  103. PBYTE pCurrent = pbHexHash;
  104. // Convert the hash data to hex string.
  105. for (int i = 0; i < MD5DIGESTLEN; i++)
  106. {
  107. *pCurrent++ = g_rgchHexNumMap[pbHash[i]/16];
  108. *pCurrent++ = g_rgchHexNumMap[pbHash[i]%16];
  109. }
  110. *pCurrent = '\0';
  111. }
  112. return (PSTR) pbHexHash;
  113. }
  114. //------------------------------------------------------------------------------------
  115. //
  116. // Method: CAuthentication::GetMD5Key()
  117. //
  118. // Synopsis: Construct the MD5 hash key based on the ChallengeInfo and password.
  119. //
  120. // Append the password to the ChallengeInfo.
  121. //
  122. //------------------------------------------------------------------------------------
  123. PSTR
  124. CAuthentication::GetMD5Key(PSTR pszChallengeInfo, PSTR pszPassword)
  125. {
  126. int cbChallengeInfo = lstrlenA(pszChallengeInfo);
  127. int cbPassword = lstrlenA(pszPassword);
  128. PBYTE pbData = new BYTE[cbChallengeInfo + cbPassword + 1];
  129. if (!pbData)
  130. {
  131. //WARNING_OUT(("CAuthentication::GetMD5Key> Out of memory"));
  132. return NULL;
  133. }
  134. PBYTE pCurrent = pbData;
  135. ::CopyMemory(pCurrent, pszChallengeInfo, cbChallengeInfo);
  136. pCurrent += cbChallengeInfo;
  137. ::CopyMemory(pCurrent, pszPassword, cbPassword);
  138. pCurrent += cbPassword;
  139. *pCurrent = '\0';
  140. return (PSTR)pbData;
  141. }
  142. //------------------------------------------------------------------------------------
  143. //
  144. // Method: CAuthentication::GetMD5Result()
  145. //
  146. // Synposis: Compute the MD5 hash result based on the clear text.
  147. //
  148. //------------------------------------------------------------------------------------
  149. PSTR
  150. CAuthentication::GetMD5Result(PCSTR pszClearText)
  151. {
  152. PBYTE pbHexHash = NULL;
  153. if (pszClearText)
  154. {
  155. MD5_CTX MD5Buffer;
  156. MD5Init(&MD5Buffer);
  157. MD5Update(&MD5Buffer, (const unsigned char*)pszClearText, lstrlenA(pszClearText));
  158. MD5Final(&MD5Buffer);
  159. PBYTE pbHash = MD5Buffer.digest;
  160. pbHexHash = new BYTE[MD5DIGESTLEN * 2 + 1];
  161. if (pbHexHash)
  162. {
  163. PBYTE pCurrent = pbHexHash;
  164. // Convert the hash data to hex string.
  165. for (int i = 0; i < MD5DIGESTLEN; i++)
  166. {
  167. *pCurrent++ = g_rgchHexNumMap[pbHash[i]/16];
  168. *pCurrent++ = g_rgchHexNumMap[pbHash[i]%16];
  169. }
  170. *pCurrent = '\0';
  171. }
  172. else
  173. {
  174. //WARNING_OUT(("CAuthentication::GetMD5Result> Out of memory"));
  175. }
  176. }
  177. return (PSTR)pbHexHash;
  178. }
  179. //------------------------------------------------------------------------------------
  180. //
  181. // Method: CAuthentication::GetMD5Result()
  182. //
  183. // Synopsis: Compute the MD5 hash result based on the ChallengeInfo and password.
  184. //
  185. //------------------------------------------------------------------------------------
  186. PSTR
  187. CAuthentication::GetMD5Result(PSTR pszChallengeInfo, PSTR pszPassword)
  188. {
  189. PSTR pbHexHash = NULL; // The MD5 result in hex string format
  190. PSTR pMD5Key = GetMD5Key(pszChallengeInfo, pszPassword);
  191. pbHexHash = GetMD5Result(pMD5Key);
  192. delete pMD5Key;
  193. return pbHexHash;
  194. }