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.

307 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. crypt.hxx
  5. Abstract:
  6. CSecureString: Encrypted string for holding passwords
  7. History:
  8. 12-April-2002 MattRim Created
  9. 6-June-2002 MattRim Adapted for ADMT use
  10. --*/
  11. #include "stdafx.h"
  12. #include <wincrypt.h>
  13. #include <comutil.h>
  14. #include "crypt.hxx"
  15. #define BAIL() goto exit;
  16. CSecureString::CSecureString() :
  17. m_fEncrypted(false),
  18. m_fEmpty(true),
  19. m_pszUnencryptedString(NULL)
  20. {
  21. m_EncryptedData.pbData = NULL;
  22. m_EncryptedData.cbData = 0;
  23. return;
  24. }
  25. CSecureString::~CSecureString()
  26. {
  27. Reset();
  28. return;
  29. }
  30. void
  31. CSecureString::Reset()
  32. {
  33. if (m_pszUnencryptedString) {
  34. SecureZeroMemory(m_pszUnencryptedString, wcslen(m_pszUnencryptedString) * sizeof(WCHAR));
  35. delete [] m_pszUnencryptedString;
  36. m_pszUnencryptedString = NULL;
  37. }
  38. if (m_EncryptedData.pbData) {
  39. SecureZeroMemory(m_EncryptedData.pbData, m_EncryptedData.cbData);
  40. LocalFree(m_EncryptedData.pbData);
  41. m_EncryptedData.pbData = NULL;
  42. m_EncryptedData.cbData = 0;
  43. }
  44. m_fEmpty = true;
  45. return;
  46. }
  47. CSecureString&
  48. CSecureString::operator=(const CSecureString& rhs)
  49. {
  50. bool fSucceeded = false;
  51. //
  52. // Free up our existing contents and reset to an empty state
  53. //
  54. Reset();
  55. //
  56. // Copy the object
  57. //
  58. m_fEncrypted = rhs.m_fEncrypted;
  59. m_fEmpty = rhs.m_fEmpty;
  60. if (rhs.m_pszUnencryptedString) {
  61. m_pszUnencryptedString = new WCHAR[wcslen(rhs.m_pszUnencryptedString)+1];
  62. if (!m_pszUnencryptedString) {
  63. BAIL();
  64. }
  65. wcscpy(m_pszUnencryptedString, rhs.m_pszUnencryptedString);
  66. }
  67. if (rhs.m_EncryptedData.pbData) {
  68. m_EncryptedData.pbData = new BYTE[rhs.m_EncryptedData.cbData];
  69. if (!m_EncryptedData.pbData) {
  70. BAIL();
  71. }
  72. m_EncryptedData.cbData = rhs.m_EncryptedData.cbData;
  73. memcpy(m_EncryptedData.pbData, rhs.m_EncryptedData.pbData, rhs.m_EncryptedData.cbData);
  74. }
  75. fSucceeded = true;
  76. exit:
  77. if (!fSucceeded) {
  78. Reset();
  79. _com_issue_error(E_OUTOFMEMORY);
  80. }
  81. return *this;
  82. }
  83. CSecureString&
  84. CSecureString::operator=(const PWCHAR& rhs)
  85. {
  86. bool fSucceeded = false;
  87. //
  88. // Free up our existing contents and reset to an empty state
  89. //
  90. Reset();
  91. //
  92. // If we're being set to an empty string, nothing much
  93. // to do.
  94. //
  95. if (rhs == NULL || rhs[0] == L'\0') {
  96. // we're done, empty string
  97. return *this;
  98. }
  99. //
  100. // Non-empty string, do the encryption
  101. //
  102. if (GenerateEncryptedData(rhs)) {
  103. fSucceeded = true;
  104. }
  105. if (!fSucceeded) {
  106. Reset();
  107. _com_issue_error(E_OUTOFMEMORY);
  108. }
  109. m_fEncrypted = true;
  110. m_fEmpty = false;
  111. return *this;
  112. }
  113. bool
  114. CSecureString::Decrypt()
  115. {
  116. DATA_BLOB DecryptedData = {0, NULL};
  117. DWORD dwStringLength = 0;
  118. bool fSuccess = false;
  119. //
  120. // Validate
  121. //
  122. // if already decrypted, or nothing to decrypt, nothing to do
  123. if (!m_fEncrypted || m_EncryptedData.pbData == NULL) {
  124. m_fEncrypted = false;
  125. fSuccess = true;
  126. BAIL();
  127. }
  128. //
  129. // Try to decrypt the data
  130. //
  131. if (!CryptUnprotectData(&m_EncryptedData, // encrypted data
  132. NULL, // description
  133. NULL, // entropy
  134. NULL, // reserved
  135. NULL, // prompt structure
  136. CRYPTPROTECT_UI_FORBIDDEN, // no UI
  137. &DecryptedData)) {
  138. BAIL()
  139. }
  140. //
  141. // Copy the decrypted string into m_pszUnencryptedString
  142. //
  143. dwStringLength = DecryptedData.cbData / sizeof(WCHAR);
  144. m_pszUnencryptedString = new WCHAR[dwStringLength];
  145. if (!m_pszUnencryptedString) {
  146. BAIL();
  147. }
  148. memcpy(m_pszUnencryptedString, DecryptedData.pbData, DecryptedData.cbData);
  149. m_fEncrypted = false;
  150. fSuccess = true;
  151. exit:
  152. if (DecryptedData.pbData) {
  153. SecureZeroMemory (DecryptedData.pbData, DecryptedData.cbData);
  154. LocalFree(DecryptedData.pbData);
  155. }
  156. return fSuccess;
  157. }
  158. void
  159. CSecureString::ReleaseString()
  160. {
  161. //
  162. // We always store an encrypted copy of the data, so this is basically a no-op.
  163. // We just need to destroy the unencrypted buffer.
  164. //
  165. if (m_pszUnencryptedString) {
  166. SecureZeroMemory(m_pszUnencryptedString, wcslen(m_pszUnencryptedString) * sizeof(WCHAR));
  167. delete [] m_pszUnencryptedString;
  168. m_pszUnencryptedString = NULL;
  169. }
  170. m_fEncrypted = true;
  171. return;
  172. }
  173. bool
  174. CSecureString::GetString(PWCHAR *ppszString)
  175. {
  176. *ppszString = NULL;
  177. if (m_fEncrypted) {
  178. if (!Decrypt()) {
  179. return false;
  180. }
  181. }
  182. *ppszString = m_pszUnencryptedString;
  183. return true;
  184. }
  185. bool
  186. CSecureString::GenerateEncryptedData(const PWCHAR pszSource)
  187. {
  188. DATA_BLOB RawData = {0, NULL};
  189. bool fSuccess = false;
  190. _ASSERT(pszSource != NULL);
  191. RawData.pbData = reinterpret_cast<PBYTE>(const_cast<PWCHAR>(pszSource));
  192. RawData.cbData = (wcslen(pszSource)+1) * sizeof(WCHAR);
  193. if (!CryptProtectData(&RawData, // unencrypted data
  194. L"", // description -- note: this cannot be NULL before XP
  195. NULL, // entropy
  196. NULL, // reserved
  197. NULL, // prompt structure
  198. CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_LOCAL_MACHINE, // flags
  199. &m_EncryptedData)) {
  200. BAIL()
  201. }
  202. _ASSERT(m_EncryptedData.pbData != NULL);
  203. _ASSERT(m_EncryptedData.cbData != 0);
  204. fSuccess = true;
  205. exit:
  206. return fSuccess;
  207. }