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.

1266 lines
33 KiB

  1. //
  2. // keymigrt.c
  3. //
  4. // Copyright (c) Microsoft Corp, 2000
  5. //
  6. //
  7. #include <windows.h>
  8. #include <winbase.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <wincrypt.h>
  12. #include <cspdk.h>
  13. #include "dpapiprv.h"
  14. #include "contman.h"
  15. #define BEHAVIOR_FORCE_KEY 0x1
  16. #define BEHAVIOR_VERBOSE 0x2
  17. #define BEHAVIOR_ALLOW_UI 0x4
  18. #define BEHAVIOR_MACHINE 0x8
  19. #define BEHAVIOR_NO_CHANGE 0x10
  20. #define BEHAVIOR_EXPORT 0x20
  21. #define BEHAVIOR_FORCE_ENC 0x40
  22. typedef struct _ALG_TO_STRING
  23. {
  24. DWORD AlgId;
  25. LPCWSTR wszString;
  26. } ALG_TO_STRING;
  27. #define MS_BASE_CRYPTPROTECT_VERSION 0x01
  28. ALG_TO_STRING g_AlgToString[] =
  29. {
  30. { CALG_MD2, L"MD2-%d " },
  31. { CALG_MD4, L"MD4-%d " },
  32. { CALG_MD5, L"MD5-%d " },
  33. { CALG_SHA1, L"SHA1-%d " },
  34. { CALG_DES, L"DES-%d " },
  35. { CALG_3DES_112, L"3DES-%d " },
  36. { CALG_3DES, L"3DES-%d " },
  37. { CALG_DESX, L"DESX-%d " },
  38. { CALG_RC2, L"RC2-%d " },
  39. { CALG_RC4, L"RC4-%d " },
  40. { CALG_SEAL, L"SEAL-%d " },
  41. { CALG_RSA_SIGN, L"RSA Signature-%d " },
  42. { CALG_RSA_KEYX, L"RSA Exchange-%d " },
  43. { CALG_DSS_SIGN, L"DSS-%d " },
  44. { CALG_DH_SF, L"DH-%d " },
  45. { CALG_DH_EPHEM, L"DH Ephemeral-%d " },
  46. { CALG_KEA_KEYX, L"KEA Exchange-%d " },
  47. { CALG_SKIPJACK, L"SKIPJACK-%d " },
  48. { CALG_TEK, L"TEK-%d " },
  49. { CALG_RC5, L"RC5-%d " },
  50. { CALG_HMAC, L"HMAC-%d " }
  51. };
  52. DWORD g_cAlgToString = sizeof(g_AlgToString)/sizeof(g_AlgToString[0]);
  53. ALG_TO_STRING g_ProviderToString[] =
  54. {
  55. {PROV_RSA_FULL, L"RSA Full"},
  56. {PROV_RSA_SIG , L"RSA Signature Only"},
  57. {PROV_DSS, L"DSS"},
  58. {PROV_FORTEZZA, L"Fortezza"},
  59. {PROV_MS_EXCHANGE, L"Microsoft Exchange"},
  60. {PROV_SSL, L"SSL"},
  61. {PROV_RSA_SCHANNEL, L"RSA SCHANNEL"},
  62. {PROV_DSS_DH, L"DSS DH"},
  63. {PROV_DH_SCHANNEL, L"DH SCHANNEL"},
  64. {PROV_SPYRUS_LYNKS, L"Spyrus LYNKS"},
  65. {PROV_INTEL_SEC, L"Intel SEC"}
  66. };
  67. DWORD g_cProviderToString = sizeof(g_ProviderToString)/sizeof(g_ProviderToString[0]);
  68. DWORD g_dwDefaultCryptProvType = PROV_RSA_FULL;
  69. DWORD g_dwAlgID_Encr_Alg = CALG_RC4;
  70. DWORD g_dwAlgID_Encr_Alg_KeySize = 40;
  71. DWORD g_dwAlgID_MAC_Alg = CALG_SHA1;
  72. DWORD g_dwAlgID_MAC_Alg_KeySize = 160;
  73. void Usage();
  74. VOID PrintAlgID(DWORD dwAlgID, DWORD dwStrength);
  75. BOOL FProviderSupportsAlg(
  76. HCRYPTPROV hQueryProv,
  77. DWORD dwAlgId,
  78. DWORD* pdwKeySize);
  79. DWORD UpdateRegistrySettings(DWORD dwBehavior, HCRYPTPROV hProv);
  80. DWORD UpgradeDPAPIBlob(DWORD dwBehavior,
  81. PBYTE *ppbData,
  82. DWORD *pcbData,
  83. BOOL *pfModified);
  84. DWORD UpgradeKeys(DWORD dwBehavior);
  85. extern DWORD
  86. GetLocalSystemToken(HANDLE* phRet);
  87. int __cdecl main(int cArg, char *rgszArg[])
  88. {
  89. DWORD dwBehavior = 0;
  90. DWORD dwError = ERROR_SUCCESS;
  91. HCRYPTPROV hProv = 0;
  92. HANDLE hToken = NULL;
  93. int i;
  94. // Parse command line
  95. for(i=1; i < cArg; i++)
  96. {
  97. LPSTR szCurrentArg = rgszArg[i];
  98. if((*szCurrentArg != '-') &&
  99. (*szCurrentArg != '/'))
  100. {
  101. Usage();
  102. goto error;
  103. }
  104. szCurrentArg++;
  105. while(*szCurrentArg)
  106. {
  107. switch(*szCurrentArg++)
  108. {
  109. case 'f':
  110. case 'F':
  111. dwBehavior |= BEHAVIOR_FORCE_KEY;
  112. break;
  113. case 'e':
  114. case 'E':
  115. dwBehavior |= BEHAVIOR_FORCE_ENC;
  116. break;
  117. case 'v':
  118. case 'V':
  119. dwBehavior |= BEHAVIOR_VERBOSE;
  120. break;
  121. case 'u':
  122. case 'U':
  123. dwBehavior |= BEHAVIOR_ALLOW_UI;
  124. break;
  125. case 'm':
  126. case 'M':
  127. dwBehavior |= BEHAVIOR_MACHINE;
  128. break;
  129. case 's':
  130. case 'S':
  131. dwBehavior |= BEHAVIOR_NO_CHANGE | BEHAVIOR_VERBOSE;
  132. break;
  133. default:
  134. Usage();
  135. goto error;
  136. }
  137. }
  138. }
  139. if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  140. {
  141. if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  142. {
  143. dwError = GetLastError();
  144. printf("Could not acquire a crypt context:%lx\n", dwError);
  145. goto error;
  146. }
  147. dwBehavior |= BEHAVIOR_EXPORT;
  148. }
  149. dwError = UpdateRegistrySettings(dwBehavior, hProv);
  150. if(dwError != ERROR_SUCCESS)
  151. {
  152. goto error;
  153. }
  154. if(dwBehavior & BEHAVIOR_MACHINE)
  155. {
  156. dwError = GetLocalSystemToken(&hToken);
  157. if(ERROR_SUCCESS == dwError)
  158. {
  159. if(!ImpersonateLoggedOnUser(hToken))
  160. {
  161. dwError = GetLastError();
  162. }
  163. }
  164. if(ERROR_ACCESS_DENIED == dwError)
  165. {
  166. printf("You must be an administrator to upgrade machine keys\n");
  167. goto error;
  168. }
  169. if(ERROR_SUCCESS != dwError)
  170. {
  171. printf("Cannot impersonate local machine:%lx\n", dwError);
  172. }
  173. }
  174. dwError = UpgradeKeys(dwBehavior);
  175. if(dwError != ERROR_SUCCESS)
  176. {
  177. goto error;
  178. }
  179. error:
  180. if(hProv)
  181. {
  182. CryptReleaseContext(hProv, 0);
  183. }
  184. if(hToken)
  185. {
  186. RevertToSelf();
  187. CloseHandle(hToken);
  188. }
  189. return (ERROR_SUCCESS == dwError)?0:-1;
  190. }
  191. void Usage()
  192. {
  193. printf("Usage: keymigrt [-f] [-v] [-u] [-m] [-s]\n");
  194. printf("CAPI Key upgrade utility\n");
  195. printf("\t-f - Force key upgrade\n");
  196. printf("\t-e - Force Encryption Settings upgrade\n");
  197. printf("\t-v - Verbose\n");
  198. printf("\t-u - Allow upgrade of UI protected keys\n");
  199. printf("\t-m - Upgrade machine keys\n");
  200. printf("\t-s - Show current state, but make no modifications\n\n");
  201. }
  202. VOID PrintAlgID(DWORD dwAlgID, DWORD dwStrength)
  203. {
  204. DWORD i;
  205. for(i=0; i < g_cAlgToString; i++)
  206. {
  207. if(dwAlgID == g_AlgToString[i].AlgId)
  208. {
  209. wprintf(g_AlgToString[i].wszString, dwStrength);
  210. break;
  211. }
  212. }
  213. if(i == g_cAlgToString)
  214. {
  215. wprintf(L"Unknown 0x%lx - %d", dwAlgID, dwStrength);
  216. }
  217. };
  218. VOID PrintProviderID(DWORD dwProviderID)
  219. {
  220. DWORD i;
  221. for(i=0; i < g_cProviderToString; i++)
  222. {
  223. if(dwProviderID == g_ProviderToString[i].AlgId)
  224. {
  225. wprintf(g_ProviderToString[i].wszString);
  226. break;
  227. }
  228. }
  229. if(i == g_cProviderToString)
  230. {
  231. wprintf(L"Unknown 0x%lx ", dwProviderID);
  232. }
  233. };
  234. DWORD UpdateRegistrySettings(DWORD dwBehavior, HCRYPTPROV hProv)
  235. {
  236. DWORD dwReturn = ERROR_SUCCESS;
  237. HKEY hKey = NULL;
  238. static const WCHAR szProviderKeyName[] = REG_CRYPTPROTECT_LOC L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC L"\\" CRYPTPROTECT_DEFAULT_PROVIDER_GUIDSZ ;
  239. DWORD dwDefaultCryptProvType = 0;
  240. DWORD dwAlgID_Encr_Alg = 0;
  241. DWORD dwAlgID_Encr_Alg_KeySize = -1;
  242. DWORD dwAlgID_MAC_Alg = 0;
  243. DWORD dwAlgID_MAC_Alg_KeySize = -1;
  244. DWORD cbParameter;
  245. DWORD dwValueType;
  246. DWORD dwParameterValue;
  247. DWORD dwDisposition;
  248. BOOL fUpgrade = FALSE;
  249. SC_HANDLE hscManager = NULL;
  250. SC_HANDLE hscProtectedStorage = NULL;
  251. SERVICE_STATUS sStatus;
  252. DWORD dwWaitTime = 0;
  253. dwReturn = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  254. szProviderKeyName,
  255. 0,
  256. KEY_READ,
  257. &hKey);
  258. if((ERROR_SUCCESS != dwReturn) &&
  259. (ERROR_FILE_NOT_FOUND != dwReturn))
  260. {
  261. printf("Could not open registry: %lx\n", dwReturn);
  262. goto error;
  263. }
  264. if(hKey)
  265. {
  266. cbParameter = sizeof(DWORD);
  267. dwReturn = RegQueryValueExW(
  268. hKey,
  269. CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG,
  270. NULL,
  271. &dwValueType,
  272. (PBYTE)&dwParameterValue,
  273. &cbParameter
  274. );
  275. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  276. // if successful, commit
  277. dwAlgID_Encr_Alg = dwParameterValue;
  278. }
  279. cbParameter = sizeof(DWORD);
  280. dwReturn = RegQueryValueExW(
  281. hKey,
  282. CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG_KEYSIZE,
  283. NULL,
  284. &dwValueType,
  285. (PBYTE)&dwParameterValue,
  286. &cbParameter
  287. );
  288. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  289. // if successful, commit
  290. dwAlgID_Encr_Alg_KeySize = dwParameterValue;
  291. }
  292. cbParameter = sizeof(DWORD);
  293. dwReturn = RegQueryValueExW(
  294. hKey,
  295. CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG,
  296. NULL,
  297. &dwValueType,
  298. (PBYTE)&dwParameterValue,
  299. &cbParameter
  300. );
  301. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  302. // if successful, commit
  303. dwAlgID_MAC_Alg = dwParameterValue;
  304. }
  305. cbParameter = sizeof(DWORD);
  306. dwReturn = RegQueryValueExW(
  307. hKey,
  308. CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG_KEYSIZE,
  309. NULL,
  310. &dwValueType,
  311. (PBYTE)&dwParameterValue,
  312. &cbParameter
  313. );
  314. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  315. // if successful, commit
  316. dwAlgID_MAC_Alg_KeySize = dwParameterValue;
  317. }
  318. cbParameter = sizeof(DWORD);
  319. dwReturn = RegQueryValueExW(
  320. hKey,
  321. CRYPTPROTECT_DEFAULT_PROVIDER_CRYPT_PROV_TYPE,
  322. NULL,
  323. &dwValueType,
  324. (PBYTE)&dwParameterValue,
  325. &cbParameter
  326. );
  327. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  328. // if successful, commit
  329. dwDefaultCryptProvType = dwParameterValue;
  330. }
  331. }
  332. if(0 != dwAlgID_Encr_Alg)
  333. {
  334. g_dwAlgID_Encr_Alg = dwAlgID_Encr_Alg;
  335. }
  336. g_dwAlgID_Encr_Alg_KeySize = dwAlgID_Encr_Alg_KeySize;
  337. FProviderSupportsAlg(hProv, g_dwAlgID_Encr_Alg, &g_dwAlgID_Encr_Alg_KeySize);
  338. if(0 != dwAlgID_MAC_Alg)
  339. {
  340. g_dwAlgID_MAC_Alg = dwAlgID_MAC_Alg;
  341. }
  342. g_dwAlgID_MAC_Alg_KeySize = dwAlgID_MAC_Alg_KeySize;
  343. FProviderSupportsAlg(hProv, g_dwAlgID_MAC_Alg, &g_dwAlgID_MAC_Alg_KeySize);
  344. if(0 != dwDefaultCryptProvType)
  345. {
  346. g_dwDefaultCryptProvType = dwDefaultCryptProvType;
  347. }
  348. if(dwBehavior & BEHAVIOR_VERBOSE)
  349. {
  350. printf("System Encryption Settings\n");
  351. printf("Provider Type:\t");
  352. PrintProviderID(g_dwDefaultCryptProvType);
  353. if(0 == dwDefaultCryptProvType)
  354. {
  355. printf(" (default)");
  356. }
  357. printf("\n");
  358. printf("Encryption Alg:\t");
  359. PrintAlgID(g_dwAlgID_Encr_Alg, g_dwAlgID_Encr_Alg_KeySize);
  360. if(-1 == dwAlgID_Encr_Alg_KeySize)
  361. {
  362. printf(" (default)");
  363. }
  364. printf("\n");
  365. printf("MAC Alg:\t");
  366. PrintAlgID(g_dwAlgID_MAC_Alg, g_dwAlgID_MAC_Alg_KeySize);
  367. if(-1 == dwAlgID_MAC_Alg_KeySize)
  368. {
  369. printf(" (default)");
  370. }
  371. printf("\n\n");
  372. }
  373. if(dwBehavior & BEHAVIOR_NO_CHANGE)
  374. {
  375. goto error;
  376. }
  377. //
  378. // Ok, upgrade the settings
  379. //
  380. if(hKey)
  381. {
  382. RegCloseKey(hKey);
  383. hKey = NULL;
  384. }
  385. // upgrade the algorithms (but never downgrade)
  386. if(dwBehavior & BEHAVIOR_EXPORT)
  387. {
  388. DWORD dwDESKeySize = -1;
  389. FProviderSupportsAlg(hProv, CALG_DES, &dwDESKeySize);
  390. // upgrade to export strength
  391. if((BEHAVIOR_FORCE_ENC & dwBehavior) || // upgrade if forced
  392. (0 == dwAlgID_Encr_Alg) || // upgrade if no settings are present
  393. ( dwDESKeySize > g_dwAlgID_Encr_Alg_KeySize)) // upgrade if other is weak
  394. {
  395. dwAlgID_Encr_Alg = CALG_DES;
  396. dwAlgID_Encr_Alg_KeySize = dwDESKeySize;
  397. fUpgrade = TRUE;
  398. }
  399. else
  400. {
  401. dwAlgID_Encr_Alg = g_dwAlgID_Encr_Alg;
  402. dwAlgID_Encr_Alg_KeySize = g_dwAlgID_Encr_Alg_KeySize;
  403. }
  404. }
  405. else
  406. {
  407. DWORD dw3DESKeySize = -1;
  408. FProviderSupportsAlg(hProv, CALG_3DES, &dw3DESKeySize);
  409. // upgrade to domestic strength
  410. if((BEHAVIOR_FORCE_ENC & dwBehavior) || // upgrade if forced
  411. (0 == dwAlgID_Encr_Alg) || // upgrade if no settings
  412. (CALG_DES == dwAlgID_Encr_Alg) || // upgrade if previously DES
  413. ( dw3DESKeySize > g_dwAlgID_Encr_Alg_KeySize) ) // upgrade if weak
  414. {
  415. dwAlgID_Encr_Alg = CALG_3DES;
  416. dwAlgID_Encr_Alg_KeySize = dw3DESKeySize;
  417. fUpgrade = TRUE;
  418. }
  419. else
  420. {
  421. dwAlgID_Encr_Alg = g_dwAlgID_Encr_Alg;
  422. dwAlgID_Encr_Alg_KeySize = g_dwAlgID_Encr_Alg_KeySize;
  423. }
  424. }
  425. FProviderSupportsAlg(hProv, CALG_SHA1, &dwAlgID_MAC_Alg_KeySize);
  426. if((BEHAVIOR_FORCE_ENC & dwBehavior) ||
  427. (g_dwAlgID_MAC_Alg_KeySize < dwAlgID_MAC_Alg_KeySize))
  428. {
  429. dwAlgID_MAC_Alg = CALG_SHA1;
  430. fUpgrade = TRUE;
  431. }
  432. else
  433. {
  434. dwAlgID_MAC_Alg_KeySize = g_dwAlgID_MAC_Alg_KeySize;
  435. dwAlgID_MAC_Alg = g_dwAlgID_MAC_Alg;
  436. }
  437. if(!fUpgrade)
  438. {
  439. // no upgrade necessary
  440. if(dwBehavior & BEHAVIOR_VERBOSE)
  441. {
  442. printf("No system encryption settings upgrade is necessary\n");
  443. }
  444. goto error;
  445. }
  446. dwReturn = RegCreateKeyExW(
  447. HKEY_LOCAL_MACHINE,
  448. szProviderKeyName,
  449. 0,
  450. NULL,
  451. 0,
  452. KEY_ALL_ACCESS,
  453. NULL,
  454. &hKey,
  455. &dwDisposition
  456. );
  457. if(ERROR_ACCESS_DENIED == dwReturn)
  458. {
  459. printf("You must be administrator to upgrade system encryption settings.\n");
  460. dwReturn = ERROR_SUCCESS;
  461. goto error;
  462. }
  463. if(ERROR_SUCCESS != dwReturn)
  464. {
  465. printf("Could not open system's encryption settings for write:%lx\n", dwReturn);
  466. goto error;
  467. }
  468. dwReturn = RegSetValueExW(
  469. hKey,
  470. CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG,
  471. 0,
  472. REG_DWORD,
  473. (PBYTE)&dwAlgID_Encr_Alg,
  474. sizeof(dwAlgID_Encr_Alg)
  475. );
  476. if( dwReturn == ERROR_SUCCESS) {
  477. // if successful, commit
  478. g_dwAlgID_Encr_Alg = dwAlgID_Encr_Alg;
  479. }
  480. else
  481. {
  482. printf("Could not set encryption alg:%lx\n", dwReturn);
  483. goto error;
  484. }
  485. dwReturn = RegSetValueExW(
  486. hKey,
  487. CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG_KEYSIZE,
  488. 0,
  489. REG_DWORD,
  490. (PBYTE)&dwAlgID_Encr_Alg_KeySize,
  491. sizeof(dwAlgID_Encr_Alg_KeySize)
  492. );
  493. if( dwReturn == ERROR_SUCCESS ) {
  494. // if successful, commit
  495. g_dwAlgID_Encr_Alg_KeySize = dwAlgID_Encr_Alg_KeySize;
  496. }
  497. else
  498. {
  499. printf("Could not set encryption Key Size:%lx\n", dwReturn);
  500. goto error;
  501. }
  502. dwReturn = RegSetValueExW(
  503. hKey,
  504. CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG,
  505. 0,
  506. REG_DWORD,
  507. (PBYTE)&dwAlgID_MAC_Alg,
  508. sizeof(dwAlgID_MAC_Alg)
  509. );
  510. if( dwReturn == ERROR_SUCCESS) {
  511. // if successful, commit
  512. g_dwAlgID_MAC_Alg = dwAlgID_MAC_Alg;
  513. }
  514. else
  515. {
  516. printf("Could not set MAC Alg:%lx\n", dwReturn);
  517. goto error;
  518. }
  519. dwReturn = RegSetValueExW(
  520. hKey,
  521. CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG_KEYSIZE,
  522. 0,
  523. REG_DWORD,
  524. (PBYTE)&dwAlgID_MAC_Alg_KeySize,
  525. sizeof(dwAlgID_MAC_Alg_KeySize)
  526. );
  527. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  528. // if successful, commit
  529. g_dwAlgID_MAC_Alg_KeySize = dwAlgID_MAC_Alg_KeySize;
  530. }
  531. else
  532. {
  533. printf("Could not set MAC Key size:%lx\n", dwReturn);
  534. goto error;
  535. }
  536. dwReturn = RegSetValueExW(
  537. hKey,
  538. CRYPTPROTECT_DEFAULT_PROVIDER_CRYPT_PROV_TYPE,
  539. 0,
  540. REG_DWORD,
  541. (PBYTE)&dwDefaultCryptProvType,
  542. sizeof(dwDefaultCryptProvType)
  543. );
  544. if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) {
  545. // if successful, commit
  546. g_dwDefaultCryptProvType = dwDefaultCryptProvType;
  547. }
  548. else
  549. {
  550. printf("Could not set provider type:%lx\n", dwReturn);
  551. goto error;
  552. }
  553. if(dwBehavior & BEHAVIOR_VERBOSE)
  554. {
  555. printf("Upgrading system encryption settings\n");
  556. printf("System Encryption Settings\n");
  557. printf("Provider Type:\t");
  558. PrintProviderID(g_dwDefaultCryptProvType);
  559. if(0 == dwDefaultCryptProvType)
  560. {
  561. printf(" (default)");
  562. }
  563. printf("\n");
  564. printf("Encryption Alg:\t");
  565. PrintAlgID(g_dwAlgID_Encr_Alg, g_dwAlgID_Encr_Alg_KeySize);
  566. if(-1 == dwAlgID_Encr_Alg_KeySize)
  567. {
  568. printf(" (default)");
  569. }
  570. printf("\n");
  571. printf("MAC Alg:\t");
  572. PrintAlgID(g_dwAlgID_MAC_Alg, g_dwAlgID_MAC_Alg_KeySize);
  573. if(-1 == dwAlgID_MAC_Alg_KeySize)
  574. {
  575. printf(" (default)");
  576. }
  577. printf("\n\n");
  578. printf("Restarting ProtectedStorage Service...\n");
  579. }
  580. // Attempt to restart the protected storage service
  581. hscManager = OpenSCManager(NULL, NULL, GENERIC_EXECUTE);
  582. if(NULL == hscManager)
  583. {
  584. dwReturn = GetLastError();
  585. printf("Could not open service controller:%lx\n", dwReturn);
  586. }
  587. hscProtectedStorage = OpenServiceW(hscManager, L"ProtectedStorage", GENERIC_READ | GENERIC_EXECUTE);
  588. if(NULL == hscManager)
  589. {
  590. dwReturn = GetLastError();
  591. printf("Could not open ProtectedStorage service:%lx\n", dwReturn);
  592. }
  593. // Shut down pstore
  594. if(!QueryServiceStatus(hscProtectedStorage, &sStatus))
  595. {
  596. dwReturn = GetLastError();
  597. printf("Could not query ProtectedStorage service status:%lx\n", dwReturn);
  598. goto error;
  599. }
  600. while(SERVICE_STOPPED != sStatus.dwCurrentState)
  601. {
  602. DWORD dwLastStatus = sStatus.dwCurrentState;
  603. DWORD dwCheckpoint = sStatus.dwCheckPoint;
  604. switch(sStatus.dwCurrentState)
  605. {
  606. case SERVICE_RUNNING:
  607. if(!ControlService(hscProtectedStorage, SERVICE_CONTROL_STOP, &sStatus))
  608. {
  609. dwReturn = GetLastError();
  610. printf("Could not stop ProtectedStorage service:%lx\n", dwReturn);
  611. goto error;
  612. }
  613. break;
  614. case SERVICE_PAUSED:
  615. if(!ControlService(hscProtectedStorage, SERVICE_CONTROL_CONTINUE, &sStatus))
  616. {
  617. dwReturn = GetLastError();
  618. printf("Could not continue ProtectedStorage service:%lx\n", dwReturn);
  619. goto error;
  620. }
  621. break;
  622. default:
  623. if(!QueryServiceStatus(hscProtectedStorage, &sStatus))
  624. {
  625. dwReturn = GetLastError();
  626. printf("Could not query ProtectedStorage service status:%lx\n", dwReturn);
  627. goto error;
  628. }
  629. break;
  630. }
  631. Sleep(sStatus.dwWaitHint);
  632. if((sStatus.dwCheckPoint == dwCheckpoint) &&
  633. (sStatus.dwCurrentState == dwLastStatus))
  634. {
  635. dwWaitTime += sStatus.dwWaitHint;
  636. if(dwWaitTime > 120000) // 2 minutes
  637. {
  638. printf("Service is not responding\n");
  639. goto error;
  640. }
  641. }
  642. else
  643. {
  644. dwWaitTime = 0;
  645. }
  646. }
  647. if(!StartService(hscProtectedStorage, 0, NULL))
  648. {
  649. dwReturn = GetLastError();
  650. printf("Could not start ProtectedStorage service:%lx\n", dwReturn);
  651. goto error;
  652. }
  653. error:
  654. if(hKey)
  655. {
  656. RegCloseKey(hKey);
  657. }
  658. return dwReturn;
  659. }
  660. BOOL FProviderSupportsAlg(
  661. HCRYPTPROV hQueryProv,
  662. DWORD dwAlgId,
  663. DWORD* pdwKeySize)
  664. {
  665. PROV_ENUMALGS sSupportedAlgs;
  666. PROV_ENUMALGS_EX sSupportedAlgsEx;
  667. DWORD cbSupportedAlgs = sizeof(sSupportedAlgs);
  668. DWORD cbSupportedAlgsEx = sizeof(sSupportedAlgsEx);
  669. int iAlgs;
  670. // now we have provider; enum the algorithms involved
  671. for(iAlgs=0; ; iAlgs++)
  672. {
  673. //
  674. // Attempt the EX alg enumeration
  675. if (CryptGetProvParam(
  676. hQueryProv,
  677. PP_ENUMALGS_EX,
  678. (PBYTE)&sSupportedAlgsEx,
  679. &cbSupportedAlgsEx,
  680. (iAlgs == 0) ? CRYPT_FIRST : 0 ))
  681. {
  682. if (sSupportedAlgsEx.aiAlgid == dwAlgId)
  683. {
  684. if(*pdwKeySize == -1)
  685. {
  686. *pdwKeySize = sSupportedAlgsEx.dwMaxLen;
  687. }
  688. else
  689. {
  690. if ((sSupportedAlgsEx.dwMinLen > *pdwKeySize) ||
  691. (sSupportedAlgsEx.dwMaxLen < *pdwKeySize))
  692. return FALSE;
  693. }
  694. return TRUE;
  695. }
  696. }
  697. else if (!CryptGetProvParam(
  698. hQueryProv,
  699. PP_ENUMALGS,
  700. (PBYTE)&sSupportedAlgs,
  701. &cbSupportedAlgs,
  702. (iAlgs == 0) ? CRYPT_FIRST : 0 ))
  703. {
  704. // trouble enumerating algs
  705. break;
  706. if (sSupportedAlgs.aiAlgid == dwAlgId)
  707. {
  708. // were we told to ignore size?
  709. if (*pdwKeySize != -1)
  710. {
  711. // else, if defaults don't match
  712. if (sSupportedAlgs.dwBitLen != *pdwKeySize)
  713. {
  714. return FALSE;
  715. }
  716. }
  717. // report back size
  718. *pdwKeySize = sSupportedAlgs.dwBitLen;
  719. return TRUE;
  720. }
  721. }
  722. else
  723. {
  724. // trouble enumerating algs
  725. break;
  726. }
  727. }
  728. return FALSE;
  729. }
  730. DWORD
  731. GetUserStorageArea(
  732. IN DWORD dwProvType,
  733. IN BOOL fMachineKeyset,
  734. IN BOOL fOldWin2KMachineKeyPath,
  735. OUT BOOL *pfIsLocalSystem, // used if fMachineKeyset is FALSE, in this
  736. // case TRUE is returned if running as Local System
  737. IN OUT LPWSTR *ppwszUserStorageArea
  738. );
  739. DWORD UpgradeKeys(DWORD dwBehavior)
  740. {
  741. DWORD aProvTypes[] = {PROV_RSA_FULL, PROV_DSS };
  742. DWORD cProvTypes = sizeof(aProvTypes)/sizeof(aProvTypes[0]);
  743. DWORD iProv;
  744. DWORD dwLastError = ERROR_SUCCESS;
  745. HANDLE hFind = INVALID_HANDLE_VALUE;
  746. CHAR szContainerName[MAX_PATH+1];
  747. DWORD cbContainerName = 0;
  748. BOOL fModified;
  749. for(iProv = 0; iProv < cProvTypes; iProv++)
  750. {
  751. DWORD dwContainerFlags = CRYPT_FIRST;
  752. while(TRUE)
  753. {
  754. KEY_CONTAINER_INFO ContInfo;
  755. cbContainerName = MAX_PATH + 1;
  756. ZeroMemory(&ContInfo, sizeof(ContInfo));
  757. dwLastError = GetNextContainer(aProvTypes[iProv],
  758. dwBehavior & BEHAVIOR_MACHINE,
  759. dwContainerFlags,
  760. szContainerName,
  761. &cbContainerName,
  762. &hFind);
  763. if(ERROR_NO_MORE_ITEMS == dwLastError)
  764. {
  765. hFind = INVALID_HANDLE_VALUE;
  766. }
  767. if(ERROR_SUCCESS != dwLastError)
  768. {
  769. break;
  770. }
  771. dwContainerFlags = 0;
  772. fModified = FALSE;
  773. dwLastError = ReadContainerInfo(
  774. aProvTypes[iProv],
  775. szContainerName,
  776. dwBehavior & BEHAVIOR_MACHINE,
  777. 0,
  778. &ContInfo
  779. );
  780. if(ERROR_SUCCESS != dwLastError)
  781. {
  782. continue;
  783. }
  784. if(dwBehavior & BEHAVIOR_VERBOSE)
  785. {
  786. printf("========================================\n");
  787. printf("Key Container:\t\t%s\n\n",szContainerName);
  788. }
  789. if((ContInfo.ContLens.cbExchEncPriv) &&
  790. (ContInfo.pbExchEncPriv))
  791. {
  792. if(dwBehavior & BEHAVIOR_VERBOSE)
  793. {
  794. printf(" Exchange Key\n");
  795. }
  796. dwLastError = UpgradeDPAPIBlob(dwBehavior,
  797. &ContInfo.pbExchEncPriv,
  798. &ContInfo.ContLens.cbExchEncPriv,
  799. &fModified);
  800. printf("\n");
  801. }
  802. if((ContInfo.ContLens.cbSigEncPriv) &&
  803. (ContInfo.pbSigEncPriv))
  804. {
  805. if(dwBehavior & BEHAVIOR_VERBOSE)
  806. {
  807. printf(" Signature Key\n");
  808. }
  809. dwLastError = UpgradeDPAPIBlob(dwBehavior,
  810. &ContInfo.pbSigEncPriv,
  811. &ContInfo.ContLens.cbSigEncPriv,
  812. &fModified);
  813. printf("\n");
  814. }
  815. if(dwBehavior & BEHAVIOR_VERBOSE)
  816. {
  817. if(((0 == ContInfo.ContLens.cbExchEncPriv) ||
  818. (NULL == ContInfo.pbExchEncPriv)) &&
  819. ((0 == ContInfo.ContLens.cbSigEncPriv) ||
  820. (NULL == ContInfo.pbSigEncPriv)))
  821. {
  822. printf(" There are no keys in this container\n\n");
  823. }
  824. }
  825. if(((dwBehavior & BEHAVIOR_FORCE_ENC) || fModified) &&
  826. (0 == (dwBehavior & BEHAVIOR_NO_CHANGE)));
  827. {
  828. dwLastError = WriteContainerInfo(
  829. aProvTypes[iProv],
  830. ContInfo.rgwszFileName,
  831. dwBehavior & BEHAVIOR_MACHINE,
  832. &ContInfo
  833. );
  834. }
  835. FreeContainerInfo(&ContInfo);
  836. }
  837. }
  838. if(INVALID_HANDLE_VALUE != hFind)
  839. {
  840. CloseHandle(hFind);
  841. }
  842. return dwLastError;
  843. }
  844. typedef struct _DPAPI_BLOB_DATA
  845. {
  846. DWORD dwVersion;
  847. DWORD dwFlags;
  848. LPWSTR wszDataDescription;
  849. DWORD cbDataDescription;
  850. DWORD EncrAlg;
  851. DWORD EncrAlgSize;
  852. DWORD MacAlg;
  853. DWORD MacAlgSize;
  854. } DPAPI_BLOB_DATA, *PDPAPI_BLOB_DATA;
  855. DWORD GetBlobData(PBYTE pbData, DWORD cbData, PDPAPI_BLOB_DATA BlobData)
  856. {
  857. PBYTE pbCurrent = pbData;
  858. DWORD dwKeySize = 0;
  859. if(cbData < sizeof (DWORD) +
  860. sizeof(GUID) +
  861. sizeof(DWORD) +
  862. sizeof(GUID) +
  863. sizeof(DWORD) +
  864. sizeof(DWORD))
  865. {
  866. return ERROR_INVALID_DATA;
  867. }
  868. pbCurrent += sizeof(DWORD) + sizeof(GUID);
  869. BlobData->dwVersion = *(DWORD UNALIGNED *)pbCurrent;
  870. pbCurrent += sizeof(DWORD) + sizeof(GUID);
  871. BlobData->dwFlags = *(DWORD UNALIGNED *)pbCurrent;
  872. pbCurrent += sizeof(DWORD);
  873. BlobData->cbDataDescription = *(DWORD UNALIGNED *)pbCurrent;
  874. pbCurrent += sizeof(DWORD);
  875. if((DWORD)(pbCurrent - pbData) +
  876. BlobData->cbDataDescription +
  877. sizeof(DWORD) +
  878. sizeof(DWORD) +
  879. sizeof(DWORD)> cbData)
  880. {
  881. return ERROR_INVALID_DATA;
  882. }
  883. BlobData->wszDataDescription = (LPWSTR)pbCurrent;
  884. pbCurrent += BlobData->cbDataDescription;
  885. BlobData->EncrAlg = *(DWORD UNALIGNED *)pbCurrent;
  886. pbCurrent += sizeof(DWORD);
  887. BlobData->EncrAlgSize = *(DWORD UNALIGNED *)pbCurrent;
  888. pbCurrent += sizeof(DWORD);
  889. // skip past key
  890. dwKeySize = *(DWORD UNALIGNED *)pbCurrent;
  891. pbCurrent += sizeof(DWORD);
  892. if((DWORD)(pbCurrent - pbData) +
  893. dwKeySize +
  894. sizeof(DWORD) > cbData)
  895. {
  896. return ERROR_INVALID_DATA;
  897. }
  898. pbCurrent += dwKeySize;
  899. // skip past salt
  900. dwKeySize = *(DWORD UNALIGNED *)pbCurrent;
  901. pbCurrent += sizeof(DWORD);
  902. if((DWORD)(pbCurrent - pbData) +
  903. dwKeySize +
  904. sizeof(DWORD) +
  905. sizeof(DWORD)> cbData)
  906. {
  907. return ERROR_INVALID_DATA;
  908. }
  909. pbCurrent += dwKeySize;
  910. BlobData->MacAlg = *(DWORD UNALIGNED *)pbCurrent;
  911. pbCurrent += sizeof(DWORD);
  912. BlobData->MacAlgSize = *(DWORD UNALIGNED *)pbCurrent;
  913. pbCurrent += sizeof(DWORD);
  914. return ERROR_SUCCESS;
  915. }
  916. DWORD PrintBlobData(PDPAPI_BLOB_DATA BlobData)
  917. {
  918. wprintf(L" Description:\t\t%s\n", BlobData->wszDataDescription);
  919. wprintf(L" Encryption Alg:\t");
  920. PrintAlgID(BlobData->EncrAlg, BlobData->EncrAlgSize);
  921. wprintf(L"\n");
  922. wprintf(L" MAC Alg:\t\t");
  923. PrintAlgID(BlobData->MacAlg, BlobData->MacAlgSize);
  924. wprintf(L"\n\n");
  925. return ERROR_SUCCESS;
  926. }
  927. DWORD UpgradeDPAPIBlob(DWORD dwBehavior,
  928. PBYTE *ppbData,
  929. DWORD *pcbData,
  930. BOOL *pfModified)
  931. {
  932. DPAPI_BLOB_DATA BlobData;
  933. DWORD dwError = ERROR_SUCCESS;
  934. DATA_BLOB DataIn;
  935. DATA_BLOB DataOut;
  936. LPWSTR wszDescription = NULL;
  937. CRYPTPROTECT_PROMPTSTRUCT Prompt;
  938. DWORD dwFlags = 0;
  939. DataIn.pbData = NULL;
  940. DataIn.cbData = 0;
  941. DataOut.pbData = NULL;
  942. DataOut.cbData = 0;
  943. dwError = GetBlobData(*ppbData, *pcbData, &BlobData);
  944. if(ERROR_SUCCESS != dwError)
  945. {
  946. printf("Could not open key:%lx\n ", dwError);
  947. goto error;
  948. }
  949. if(MS_BASE_CRYPTPROTECT_VERSION != BlobData.dwVersion)
  950. {
  951. printf("Unknown data version\n");
  952. dwError = ERROR_INVALID_DATA;
  953. goto error;
  954. }
  955. if(dwBehavior & BEHAVIOR_VERBOSE)
  956. {
  957. dwError = PrintBlobData(&BlobData);
  958. }
  959. if(dwBehavior & BEHAVIOR_NO_CHANGE)
  960. {
  961. goto error;
  962. }
  963. // Check to see if upgrade is required
  964. if((BlobData.EncrAlgSize >= g_dwAlgID_Encr_Alg_KeySize) &&
  965. (0 == (dwBehavior & BEHAVIOR_FORCE_KEY)))
  966. {
  967. if(dwBehavior & BEHAVIOR_VERBOSE)
  968. {
  969. printf(" No upgrade necessary\n");
  970. }
  971. goto error;
  972. }
  973. if(((BlobData.dwFlags & CRYPTPROTECT_PROMPT_ON_UNPROTECT) ||
  974. (BlobData.dwFlags & CRYPTPROTECT_PROMPT_ON_PROTECT)) &&
  975. (0 == (dwBehavior & BEHAVIOR_ALLOW_UI)))
  976. {
  977. if(dwBehavior & BEHAVIOR_VERBOSE)
  978. {
  979. printf(" This key requires UI, and will not be upgraded\n");
  980. }
  981. goto error;
  982. }
  983. //
  984. // Upgrade the key
  985. //
  986. DataIn.pbData = *ppbData;
  987. DataIn.cbData = *pcbData;
  988. Prompt.cbSize = sizeof(Prompt);
  989. Prompt.dwPromptFlags = BlobData.dwFlags & (CRYPTPROTECT_PROMPT_ON_UNPROTECT | CRYPTPROTECT_PROMPT_ON_PROTECT);
  990. Prompt.hwndApp = NULL;
  991. Prompt.szPrompt = L"Key Upgrade Utility\n";
  992. if(0 == (dwBehavior & BEHAVIOR_ALLOW_UI))
  993. {
  994. dwFlags |= CRYPTPROTECT_UI_FORBIDDEN;
  995. }
  996. if(0 == (dwBehavior & BEHAVIOR_MACHINE))
  997. {
  998. dwFlags |= CRYPTPROTECT_LOCAL_MACHINE;
  999. }
  1000. if(!CryptUnprotectData(&DataIn,
  1001. &wszDescription,
  1002. NULL,
  1003. NULL,
  1004. &Prompt,
  1005. dwFlags,
  1006. &DataOut))
  1007. {
  1008. dwError = GetLastError();
  1009. printf("Could not unprotect key:%lx\n", dwError);
  1010. goto error;
  1011. }
  1012. DataIn.pbData = NULL;
  1013. DataIn.cbData = 0;
  1014. if(!CryptProtectData(&DataOut,
  1015. wszDescription,
  1016. NULL,
  1017. NULL,
  1018. &Prompt,
  1019. dwFlags,
  1020. &DataIn))
  1021. {
  1022. dwError = GetLastError();
  1023. printf("Could not protect key:%lx\n", dwError);
  1024. goto error;
  1025. }
  1026. dwError = GetBlobData(DataIn.pbData, DataIn.cbData, &BlobData);
  1027. if(ERROR_SUCCESS != dwError)
  1028. {
  1029. printf("Could not open key:%lx\n ", dwError);
  1030. goto error;
  1031. }
  1032. if(MS_BASE_CRYPTPROTECT_VERSION != BlobData.dwVersion)
  1033. {
  1034. printf("Unknown data version\n");
  1035. dwError = ERROR_INVALID_DATA;
  1036. goto error;
  1037. }
  1038. if(dwBehavior & BEHAVIOR_VERBOSE)
  1039. {
  1040. printf(" Upgraded To\n");
  1041. PrintBlobData(&BlobData);
  1042. }
  1043. LocalFree(*ppbData);
  1044. *ppbData = DataIn.pbData;
  1045. *pcbData = DataIn.cbData;
  1046. *pfModified = TRUE;
  1047. error:
  1048. if(DataOut.pbData)
  1049. {
  1050. ZeroMemory(DataOut.pbData, DataOut.cbData);
  1051. }
  1052. return dwError;
  1053. }