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.

887 lines
24 KiB

  1. /****************************************************************************
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name: crypt.c
  4. Abstract: Encryption/Decryption routines
  5. Author: radus - 11/05/98
  6. Notes: Used for encrypting/decrypting of the PIN numbers.
  7. It is NOT thread-safe
  8. Rev History:
  9. ****************************************************************************/
  10. #define STRICT
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <tchar.h>
  14. #include <stdlib.h>
  15. #include <wincrypt.h>
  16. #include <shlwapi.h>
  17. #include <shlwapip.h>
  18. #include "tregupr2.h"
  19. #include "debug.h"
  20. // Context
  21. static LONG gdwNrOfClients = 0;
  22. static PTSTR gpszSidText = NULL;
  23. static HCRYPTPROV ghCryptProvider = 0;
  24. static BOOL gbUseOnlyTheOldAlgorithm = TRUE;
  25. static BOOL gbCryptAvailChecked = FALSE;
  26. static BOOL gbCryptAvailable = TRUE;
  27. static const CHAR MAGIC_1 = 'B';
  28. static const CHAR MAGIC_5 = 'L';
  29. static const CHAR MAGIC_2 = 'U';
  30. static const CHAR MAGIC_4 = 'U';
  31. static const CHAR MAGIC_3 = 'B';
  32. #define ENCRYPTED_MARKER L'X'
  33. // prototypes
  34. static BOOL GetUserSidText(LPTSTR *);
  35. static BOOL GetUserTokenUser(TOKEN_USER **);
  36. static BOOL ConvertSidToText(PSID, LPTSTR, LPDWORD);
  37. static BOOL CreateSessionKey(HCRYPTPROV, LPTSTR, DWORD, HCRYPTKEY *);
  38. static void DestroySessionKey(HCRYPTKEY );
  39. static void Unscrambler( DWORD, LPWSTR, LPWSTR );
  40. static void CopyScrambled( LPWSTR, LPWSTR, DWORD);
  41. DWORD TapiCryptInitialize(void)
  42. {
  43. DWORD dwNew;
  44. DWORD dwError;
  45. HCRYPTKEY hKey;
  46. PBYTE bTestData = "Testing";
  47. DWORD dwTestSize = strlen(bTestData);
  48. // Only one initialization
  49. dwNew = InterlockedIncrement(&gdwNrOfClients);
  50. if(dwNew>1)
  51. return ERROR_SUCCESS;
  52. // By default
  53. gbUseOnlyTheOldAlgorithm = TRUE;
  54. dwError = ERROR_SUCCESS;
  55. #ifdef WINNT
  56. // New encryption only for Windows NT
  57. if(gbCryptAvailable || !gbCryptAvailChecked)
  58. {
  59. // Acquire CryptoAPI context
  60. if(CryptAcquireContext( &ghCryptProvider,
  61. NULL,
  62. MS_DEF_PROV,
  63. PROV_RSA_FULL,
  64. CRYPT_VERIFYCONTEXT // No need of private/public keys
  65. ))
  66. {
  67. // Get the user SID
  68. if(GetUserSidText(&gpszSidText))
  69. {
  70. if (gbCryptAvailChecked == FALSE)
  71. {
  72. if(CreateSessionKey(ghCryptProvider, gpszSidText, 0, &hKey))
  73. {
  74. // try to use the test key and check for the NTE_PERM error meaning that we are not
  75. // going to be able to use crypt
  76. if (CryptEncrypt(hKey, 0, TRUE, 0, (BYTE *)bTestData, &dwTestSize, 0) == FALSE)
  77. {
  78. if (GetLastError() == NTE_PERM)
  79. {
  80. DBGOUT((5, "Encryption unavailable"));
  81. gbCryptAvailable = FALSE;
  82. }
  83. }
  84. // FOR TEST
  85. // DBGOUT((5, "Encryption unavailable")); // Test Only
  86. // gbCryptAvailable = FALSE; // Test Only
  87. gbCryptAvailChecked = TRUE;
  88. DestroySessionKey(hKey);
  89. }
  90. else
  91. dwError = GetLastError();
  92. }
  93. gbUseOnlyTheOldAlgorithm = !gbCryptAvailable;
  94. }
  95. else
  96. dwError = GetLastError();
  97. }
  98. else
  99. {
  100. dwError = GetLastError();
  101. DBGOUT((5, "CryptAcquireContext failed"));
  102. }
  103. }
  104. #endif // WINNT
  105. return dwError;
  106. }
  107. void TapiCryptUninitialize(void)
  108. {
  109. DWORD dwNew;
  110. dwNew = InterlockedDecrement(&gdwNrOfClients);
  111. if(dwNew>0)
  112. return;
  113. #ifdef WINNT
  114. if(ghCryptProvider)
  115. {
  116. CryptReleaseContext(ghCryptProvider, 0);
  117. ghCryptProvider = 0;
  118. }
  119. if(gpszSidText)
  120. {
  121. GlobalFree(gpszSidText);
  122. gpszSidText = NULL;
  123. }
  124. #endif
  125. gbUseOnlyTheOldAlgorithm = TRUE;
  126. return;
  127. }
  128. /////////////////////////////////
  129. // TapiEncrypt
  130. //
  131. // Encrypts the text specified in pszSource.
  132. // Uses the old scrambling algorithm or a cryptographic one.
  133. // The result buffer should be a little bit larger than the source - for pads, etc.
  134. //
  135. DWORD TapiEncrypt(PWSTR pszSource, DWORD dwKey, PWSTR pszDest, DWORD *pdwLengthNeeded)
  136. {
  137. DWORD dwError;
  138. DWORD dwDataLength,
  139. dwLength,
  140. dwLengthDwords,
  141. dwLengthAlpha;
  142. // for speed
  143. BYTE bBuffer1[0x20];
  144. PBYTE pBuffer1 = NULL;
  145. HCRYPTKEY hKey = 0;
  146. DWORD *pdwCrt1;
  147. WCHAR *pwcCrt2;
  148. DWORD dwShift;
  149. DWORD dwCount, dwCount2;
  150. #ifdef WINNT
  151. if(!gbUseOnlyTheOldAlgorithm)
  152. {
  153. // A null PIN is not encrypted
  154. if(*pszSource==L'\0')
  155. {
  156. if(pszDest)
  157. *pszDest = L'\0';
  158. if(pdwLengthNeeded)
  159. *pdwLengthNeeded = 1;
  160. return ERROR_SUCCESS;
  161. }
  162. dwDataLength = (wcslen(pszSource) + 1)*sizeof(WCHAR); // in bytes
  163. dwLength = dwDataLength + 16; // space for pads, a marker etc.
  164. dwLengthAlpha = dwLength*3; // due to the binary->alphabetic conversion
  165. if(pszDest==NULL && pdwLengthNeeded != NULL)
  166. {
  167. *pdwLengthNeeded = dwLengthAlpha/sizeof(WCHAR); // length in characters
  168. dwError = ERROR_SUCCESS;
  169. }
  170. else
  171. {
  172. ZeroMemory(bBuffer1, sizeof(bBuffer1));
  173. pBuffer1 = dwLength>sizeof(bBuffer1) ? (PBYTE)GlobalAlloc(GPTR, dwLength) : bBuffer1;
  174. if(pBuffer1!=NULL)
  175. {
  176. // Copy the source
  177. wcscpy((PWSTR)pBuffer1, pszSource);
  178. // create session key
  179. if(CreateSessionKey(ghCryptProvider, gpszSidText, dwKey, &hKey))
  180. {
  181. // Encrypt inplace
  182. if(CryptEncrypt(hKey,
  183. 0,
  184. TRUE,
  185. 0,
  186. pBuffer1,
  187. &dwDataLength,
  188. dwLength))
  189. {
  190. // Convert to UNICODE between 0030 - 006f
  191. // I hope !
  192. assert((dwDataLength % sizeof(DWORD))==0);
  193. assert(sizeof(DWORD)==4);
  194. assert(sizeof(DWORD) == 2*sizeof(WCHAR));
  195. pdwCrt1 = (DWORD *)pBuffer1;
  196. pwcCrt2 = (WCHAR *)pszDest;
  197. // Place a marker
  198. *pwcCrt2++ = ENCRYPTED_MARKER;
  199. // dwDataLength has the length in bytes of the ciphered data
  200. dwLengthAlpha = dwDataLength*3;
  201. dwLengthDwords = dwDataLength / sizeof(DWORD);
  202. for(dwCount=0; dwCount<dwLengthDwords; dwCount++)
  203. {
  204. dwShift = *pdwCrt1++;
  205. for(dwCount2=0; dwCount2<6; dwCount2++)
  206. {
  207. *pwcCrt2++ = (WCHAR)((dwShift & 0x3f) + 0x30);
  208. dwShift >>= 6;
  209. }
  210. }
  211. // Put a NULL terminator
  212. *pwcCrt2++ = L'\0';
  213. if(pdwLengthNeeded)
  214. *pdwLengthNeeded = (dwLengthAlpha/sizeof(WCHAR))+2; // including the NULL and the marker
  215. dwError = ERROR_SUCCESS;
  216. }
  217. else
  218. dwError = GetLastError();
  219. }
  220. else
  221. dwError = GetLastError();
  222. }
  223. else
  224. dwError = GetLastError();
  225. }
  226. if(pBuffer1 && pBuffer1!=bBuffer1)
  227. GlobalFree(pBuffer1);
  228. if(hKey!=0)
  229. DestroySessionKey(hKey);
  230. }
  231. else
  232. {
  233. #endif
  234. if(pdwLengthNeeded != NULL)
  235. {
  236. *pdwLengthNeeded = wcslen(pszSource) + 1; // dim in characters
  237. }
  238. if(pszDest!=NULL)
  239. {
  240. CopyScrambled(pszSource, pszDest, dwKey);
  241. }
  242. dwError = ERROR_SUCCESS;
  243. #ifdef WINNT
  244. }
  245. #endif
  246. return dwError;
  247. }
  248. DWORD TapiDecrypt(PWSTR pszSource, DWORD dwKey, PWSTR pszDest, DWORD *pdwLengthNeeded)
  249. {
  250. DWORD dwError;
  251. DWORD dwLengthCrypted;
  252. DWORD dwDataLength;
  253. DWORD dwLengthDwords;
  254. HCRYPTKEY hKey = 0;
  255. WCHAR *pwcCrt1;
  256. DWORD *pdwCrt2;
  257. DWORD dwCount;
  258. DWORD dwCount2;
  259. DWORD dwShift;
  260. // A null PIN is not encrypted
  261. if(*pszSource==L'\0')
  262. {
  263. if(pszDest)
  264. *pszDest = L'\0';
  265. if(pdwLengthNeeded)
  266. *pdwLengthNeeded = 1;
  267. return ERROR_SUCCESS;
  268. }
  269. dwError = ERROR_SUCCESS;
  270. // If the first char is a 'X', we have encrypted data
  271. if(*pszSource == ENCRYPTED_MARKER)
  272. {
  273. #ifdef WINNT
  274. if(gbCryptAvailable && gdwNrOfClients>0)
  275. {
  276. dwLengthCrypted = wcslen(pszSource) +1 -2; // In characters, without the marker and the NULL
  277. assert(dwLengthCrypted % 6 == 0);
  278. dwLengthDwords = dwLengthCrypted / 6;
  279. if(pszDest==NULL && pdwLengthNeeded)
  280. {
  281. *pdwLengthNeeded = dwLengthDwords*(sizeof(DWORD)/sizeof(WCHAR));
  282. dwError = ERROR_SUCCESS;
  283. }
  284. else
  285. {
  286. // Convert to binary
  287. pwcCrt1 = pszSource + dwLengthCrypted; // end of the string, before the NULL
  288. pdwCrt2 = ((DWORD *)pszDest) + dwLengthDwords -1; // Last DWORD
  289. for(dwCount=0; dwCount<dwLengthDwords; dwCount++)
  290. {
  291. dwShift=0;
  292. for(dwCount2=0; dwCount2<6; dwCount2++)
  293. {
  294. dwShift <<= 6;
  295. dwShift |= ((*pwcCrt1-- - 0x30) & 0x3f);
  296. }
  297. *pdwCrt2-- = dwShift;
  298. }
  299. if(CreateSessionKey(ghCryptProvider, gpszSidText, dwKey, &hKey))
  300. {
  301. dwDataLength = dwLengthDwords * sizeof(DWORD);
  302. // Decrypt in place
  303. if(CryptDecrypt(hKey,
  304. 0,
  305. TRUE,
  306. 0,
  307. (PBYTE)pszDest,
  308. &dwDataLength))
  309. {
  310. dwDataLength /= sizeof(WCHAR);
  311. if(*(pszDest+dwDataLength-1)==L'\0') // The ending NULL was encrypted too
  312. {
  313. if(pdwLengthNeeded)
  314. *pdwLengthNeeded = dwDataLength;
  315. dwError = ERROR_SUCCESS;
  316. }
  317. else
  318. {
  319. *pszDest = L'\0';
  320. dwError = ERROR_INVALID_DATA;
  321. }
  322. }
  323. else
  324. dwError = GetLastError();
  325. DestroySessionKey(hKey);
  326. }
  327. else
  328. dwError = GetLastError();
  329. }
  330. }
  331. else
  332. dwError = ERROR_INVALID_DATA;
  333. #else
  334. dwError = ERROR_INVALID_DATA;
  335. #endif
  336. }
  337. else
  338. {
  339. if(pdwLengthNeeded != NULL)
  340. {
  341. *pdwLengthNeeded = wcslen(pszSource) + 1; // dim in characters
  342. }
  343. if(pszDest!=NULL)
  344. {
  345. Unscrambler(dwKey, pszSource, pszDest);
  346. }
  347. dwError = ERROR_SUCCESS;
  348. }
  349. return dwError;
  350. }
  351. /////////////////////////////////
  352. // TapiIsSafeToDisplaySensitiveData
  353. //
  354. // Detects if the current process is running in the "LocalSystem" security context.
  355. // Returns FALSE if it is, TRUE if it is not.
  356. // Returns also FALSE if an error occurs.
  357. BOOL TapiIsSafeToDisplaySensitiveData(void)
  358. {
  359. #ifdef WINNT
  360. DWORD dwError = ERROR_SUCCESS;
  361. TOKEN_USER *User = NULL;
  362. SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_NT_AUTHORITY;
  363. PSID SystemSid = NULL;
  364. BOOL bIsSafe = FALSE;
  365. // Get the User info
  366. if(GetUserTokenUser(&User))
  367. {
  368. // Create a system SID
  369. if(AllocateAndInitializeSid(&SidAuth,
  370. 1,
  371. SECURITY_LOCAL_SYSTEM_RID,
  372. 0, 0, 0, 0, 0, 0, 0,
  373. &SystemSid
  374. ))
  375. {
  376. // Compare the two sids
  377. bIsSafe = !EqualSid(SystemSid, User->User.Sid);
  378. FreeSid(SystemSid);
  379. }
  380. else
  381. {
  382. dwError = GetLastError();
  383. }
  384. GlobalFree(User);
  385. }
  386. else
  387. {
  388. dwError = GetLastError();
  389. }
  390. DBGOUT((5, "TapiIsSafeToDisplaySensitiveData - dwError=0x%x, Safe=%d", dwError, bIsSafe));
  391. return bIsSafe;
  392. #else // WINNT
  393. return TRUE; // always safe
  394. #endif
  395. }
  396. #ifdef WINNT
  397. /////////////////////////////////
  398. // GetUserSidText
  399. //
  400. // Retrieves the SID from the token of the current process in text format
  401. BOOL GetUserSidText(LPTSTR *ppszResultSid)
  402. {
  403. TOKEN_USER *User = NULL;
  404. DWORD dwLength;
  405. LPTSTR pszSidText = NULL;
  406. // Get the SID
  407. if(!GetUserTokenUser(&User))
  408. {
  409. DBGOUT((5, "GetMagic (0) failed, 0x%x", GetLastError()));
  410. return FALSE;
  411. }
  412. // Query the space needed for the string format of the SID
  413. dwLength=0;
  414. if(!ConvertSidToText(User->User.Sid, NULL, &dwLength)
  415. && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  416. {
  417. DBGOUT((5, "GetMagic (1) failed, 0x%x", GetLastError()));
  418. GlobalFree(User);
  419. return FALSE;
  420. }
  421. // Alloc the space
  422. pszSidText = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwLength);
  423. if(pszSidText==NULL)
  424. {
  425. GlobalFree(User);
  426. return FALSE;
  427. }
  428. // Convert the SID in string format
  429. if(!ConvertSidToText(User->User.Sid, pszSidText, &dwLength))
  430. {
  431. DBGOUT((5, "GetMagic (2) failed, 0x%x", GetLastError()));
  432. GlobalFree(User);
  433. GlobalFree(pszSidText);
  434. return FALSE;
  435. }
  436. GlobalFree(User);
  437. // The caller should free the buffer
  438. *ppszResultSid = pszSidText;
  439. return TRUE;
  440. }
  441. /////////////////////////////////
  442. // GetUserTokenUser
  443. //
  444. // Retrieves the TOKEN_USER structure from the token of the current process
  445. BOOL GetUserTokenUser(TOKEN_USER **ppszResultTokenUser)
  446. {
  447. HANDLE hToken = NULL;
  448. DWORD dwLength;
  449. TOKEN_USER *User = NULL;
  450. // Open the current process token (for read)
  451. if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken))
  452. {
  453. if( GetLastError() == ERROR_NO_TOKEN)
  454. {
  455. // try with the process token
  456. if (! OpenProcessToken ( GetCurrentProcess(), TOKEN_QUERY, &hToken))
  457. {
  458. DBGOUT((5, "OpenProcessToken failed, 0x%x", GetLastError()));
  459. return FALSE;
  460. }
  461. }
  462. else
  463. {
  464. DBGOUT((5, "OpenThreadToken failed, 0x%x", GetLastError()));
  465. return FALSE;
  466. }
  467. }
  468. // Find the space needed for the SID
  469. if(!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength)
  470. && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  471. {
  472. DBGOUT((5, "GetTokenInformation (1) failed, 0x%x", GetLastError()));
  473. CloseHandle(hToken);
  474. return FALSE;
  475. }
  476. // Alloc the space
  477. User = (TOKEN_USER *)GlobalAlloc(GMEM_FIXED, dwLength);
  478. if(User==NULL)
  479. {
  480. CloseHandle(hToken);
  481. return FALSE;
  482. }
  483. // Retrieve the SID
  484. if(!GetTokenInformation(hToken, TokenUser, User, dwLength, &dwLength))
  485. {
  486. DBGOUT((5, "GetTokenInformation (2) failed, 0x%x", GetLastError()));
  487. CloseHandle(hToken);
  488. GlobalFree(User);
  489. return FALSE;
  490. }
  491. CloseHandle(hToken);
  492. // The caller should free the buffer
  493. *ppszResultTokenUser = User;
  494. return TRUE;
  495. }
  496. /////////////////////////////////
  497. // ConvertSidToText
  498. //
  499. // Transforms a binary SID in string format
  500. // Author Jeff Spelman
  501. BOOL ConvertSidToText(
  502. PSID pSid, // binary Sid
  503. LPTSTR TextualSid, // buffer for Textual representation of Sid
  504. LPDWORD lpdwBufferLen // required/provided TextualSid buffersize
  505. )
  506. {
  507. PSID_IDENTIFIER_AUTHORITY psia;
  508. DWORD dwSubAuthorities;
  509. DWORD dwSidRev=SID_REVISION;
  510. DWORD dwCounter;
  511. DWORD dwSidSize;
  512. // Validate the binary SID.
  513. if(!IsValidSid(pSid)) return FALSE;
  514. // Get the identifier authority value from the SID.
  515. psia = GetSidIdentifierAuthority(pSid);
  516. // Get the number of subauthorities in the SID.
  517. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  518. // Compute the buffer length.
  519. // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
  520. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  521. // Check input buffer length.
  522. // If too small, indicate the proper size and set last error.
  523. if (*lpdwBufferLen < dwSidSize)
  524. {
  525. *lpdwBufferLen = dwSidSize;
  526. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  527. return FALSE;
  528. }
  529. // Add 'S' prefix and revision number to the string.
  530. dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
  531. // Add SID identifier authority to the string.
  532. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  533. {
  534. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  535. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  536. (USHORT)psia->Value[0],
  537. (USHORT)psia->Value[1],
  538. (USHORT)psia->Value[2],
  539. (USHORT)psia->Value[3],
  540. (USHORT)psia->Value[4],
  541. (USHORT)psia->Value[5]);
  542. }
  543. else
  544. {
  545. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  546. TEXT("%lu"),
  547. (ULONG)(psia->Value[5] ) +
  548. (ULONG)(psia->Value[4] << 8) +
  549. (ULONG)(psia->Value[3] << 16) +
  550. (ULONG)(psia->Value[2] << 24) );
  551. }
  552. // Add SID subauthorities to the string.
  553. //
  554. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  555. {
  556. dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
  557. *GetSidSubAuthority(pSid, dwCounter) );
  558. }
  559. return TRUE;
  560. }
  561. /////////////////////////////////
  562. // CreateSessionKey
  563. //
  564. // Creates a session key derived from the user SID and a hint (currently the calling card ID)
  565. //
  566. //
  567. BOOL CreateSessionKey(HCRYPTPROV hProv, LPTSTR pszSidText, DWORD dwHint, HCRYPTKEY *phKey)
  568. {
  569. HCRYPTHASH hHash = 0;
  570. CHAR szTmpBuff[0x20];
  571. DWORD dwSize;
  572. LPSTR pszBuf;
  573. // Create a hash object
  574. if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
  575. {
  576. DBGOUT((5, "CryptCreateHash failed, 0x%x, Prov=0x%x", GetLastError(), hProv));
  577. return FALSE;
  578. }
  579. // the Sid is of type TCHAR but, for back compat reasons, we want to encrypt the ANSI
  580. // version of this string. We can either:
  581. // 1.) Convert the creation path for pszSid to ANSI (more correct solution)
  582. // 2.) thunk pszSid to ansi before converting (lazy solution)
  583. // I'm lazy so I'm choosing option #2. It should be safe to thunk to ANSI because the
  584. // Sid should correctly round trip back to unicode.
  585. dwSize = lstrlen(pszSidText)+1;
  586. pszBuf = (LPSTR)GlobalAlloc( GPTR, dwSize*sizeof(CHAR) );
  587. if ( !pszBuf )
  588. {
  589. // out of memory
  590. CryptDestroyHash(hHash);
  591. return FALSE;
  592. }
  593. SHTCharToAnsi( pszSidText, pszBuf, dwSize );
  594. #ifdef DEBUG
  595. #ifdef UNICODE
  596. {
  597. // ensure that the SID round trips. If it doesn't round trip then the validity of this
  598. // encription scheme is questionable on NT. The solution would be to encrypt using Unicode,
  599. // but that would break back compat.
  600. LPTSTR pszDebug;
  601. pszDebug = (LPTSTR)GlobalAlloc( GPTR, dwSize*sizeof(TCHAR) );
  602. if ( pszDebug )
  603. {
  604. SHAnsiToTChar(pszBuf, pszDebug, dwSize);
  605. if ( 0 != StrCmp( pszDebug, pszSidText ) )
  606. {
  607. DBGOUT((1,"CRYPT ERROR! Sid doesn't round trip! FIX THIS!!!"));
  608. }
  609. GlobalFree(pszDebug);
  610. }
  611. }
  612. #endif
  613. #endif
  614. // hash the SID
  615. if(!CryptHashData(hHash, (PBYTE)pszBuf, (dwSize)*sizeof(CHAR), 0))
  616. {
  617. CryptDestroyHash(hHash);
  618. return FALSE;
  619. }
  620. GlobalFree(pszBuf);
  621. // hash a "magic" and the hint
  622. ZeroMemory(szTmpBuff, sizeof(szTmpBuff));
  623. wsprintfA(szTmpBuff, "-%c%c%c%c%c%x", MAGIC_1, MAGIC_2, MAGIC_3, MAGIC_4, MAGIC_5, dwHint);
  624. if(!CryptHashData(hHash, (PBYTE)szTmpBuff, sizeof(szTmpBuff), 0))
  625. {
  626. CryptDestroyHash(hHash);
  627. return FALSE;
  628. }
  629. // Generate the key, use block alg
  630. if(!CryptDeriveKey(hProv, CALG_RC2, hHash, 0, phKey))
  631. {
  632. DBGOUT((5, "CryptDeriveKey failed, 0x%x", GetLastError()));
  633. CryptDestroyHash(hHash);
  634. return FALSE;
  635. }
  636. CryptDestroyHash(hHash);
  637. return TRUE;
  638. }
  639. /////////////////////////////////
  640. // DestroySessionKey
  641. //
  642. // Destroys a session key
  643. //
  644. //
  645. void DestroySessionKey(HCRYPTKEY hKey)
  646. {
  647. CryptDestroyKey(hKey);
  648. }
  649. #endif //WINNT
  650. // Old routines
  651. #define IsWDigit(c) (((WCHAR)(c)) >= (WCHAR)'0' && ((WCHAR)(c)) <= (WCHAR)'9')
  652. void Unscrambler( DWORD dwKey,
  653. LPWSTR lpszSrc,
  654. LPWSTR lpszDst )
  655. {
  656. UINT uIndex;
  657. UINT uSubKey;
  658. UINT uNewKey;
  659. // InternalDebugOut((101, "Entering Unscrambler"));
  660. if ( !lpszSrc || !lpszDst )
  661. {
  662. goto done;
  663. }
  664. uNewKey = (UINT)dwKey & 0x7FFF;
  665. uSubKey = (UINT)dwKey % 10;
  666. for ( uIndex = 1; *lpszSrc ; lpszSrc++, lpszDst++, uIndex++ )
  667. {
  668. if ( IsWDigit( *lpszSrc ))
  669. {
  670. // do the unscramble thang
  671. //------------------------
  672. uSubKey = ((*lpszSrc - (WCHAR)'0') - ((uSubKey + uIndex + uNewKey) % 10) + 10) % 10;
  673. *lpszDst = (WCHAR)(uSubKey + (WCHAR)'0');
  674. }
  675. else
  676. *lpszDst = *lpszSrc; // just save the byte
  677. }
  678. done:
  679. *lpszDst = (WCHAR)'\0';
  680. //InternalDebugOut((101, "Leaving Unscrambler"));
  681. return;
  682. }
  683. void CopyScrambled( LPWSTR lpszSrc,
  684. LPWSTR lpszDst,
  685. DWORD dwKey
  686. )
  687. {
  688. UINT uIndex;
  689. UINT uSubKey;
  690. UINT uNewKey;
  691. //nternalDebugOut((50, "Entering IniScrambler"));
  692. if ( !lpszSrc || !lpszDst )
  693. {
  694. goto done;
  695. } // end if
  696. uNewKey = (UINT)dwKey & 0x7FFF;
  697. uSubKey = (UINT)dwKey % 10;
  698. for ( uIndex = 1; *lpszSrc ; lpszSrc++, lpszDst++, uIndex++ )
  699. {
  700. if ( IsWDigit( *lpszSrc ))
  701. {
  702. // do the scramble thang
  703. //----------------------
  704. *lpszDst = (WCHAR)(((uSubKey + (*lpszSrc - (WCHAR)'0') + uIndex + uNewKey) % 10) + (WCHAR)'0');
  705. uSubKey = (UINT)(*lpszSrc - (WCHAR)'0');
  706. }
  707. else
  708. *lpszDst = *lpszSrc; // just save the byte
  709. } // end for
  710. done:
  711. *lpszDst = (WCHAR)'\0';
  712. // InternalDebugOut((60, "Leaving IniScrambler"));
  713. return;
  714. }