// // keymigrt.c // // Copyright (c) Microsoft Corp, 2000 // // #include #include #include #include #include #include #include "dpapiprv.h" #include "contman.h" #define BEHAVIOR_FORCE_KEY 0x1 #define BEHAVIOR_VERBOSE 0x2 #define BEHAVIOR_ALLOW_UI 0x4 #define BEHAVIOR_MACHINE 0x8 #define BEHAVIOR_NO_CHANGE 0x10 #define BEHAVIOR_EXPORT 0x20 #define BEHAVIOR_FORCE_ENC 0x40 typedef struct _ALG_TO_STRING { DWORD AlgId; LPCWSTR wszString; } ALG_TO_STRING; #define MS_BASE_CRYPTPROTECT_VERSION 0x01 ALG_TO_STRING g_AlgToString[] = { { CALG_MD2, L"MD2-%d " }, { CALG_MD4, L"MD4-%d " }, { CALG_MD5, L"MD5-%d " }, { CALG_SHA1, L"SHA1-%d " }, { CALG_DES, L"DES-%d " }, { CALG_3DES_112, L"3DES-%d " }, { CALG_3DES, L"3DES-%d " }, { CALG_DESX, L"DESX-%d " }, { CALG_RC2, L"RC2-%d " }, { CALG_RC4, L"RC4-%d " }, { CALG_SEAL, L"SEAL-%d " }, { CALG_RSA_SIGN, L"RSA Signature-%d " }, { CALG_RSA_KEYX, L"RSA Exchange-%d " }, { CALG_DSS_SIGN, L"DSS-%d " }, { CALG_DH_SF, L"DH-%d " }, { CALG_DH_EPHEM, L"DH Ephemeral-%d " }, { CALG_KEA_KEYX, L"KEA Exchange-%d " }, { CALG_SKIPJACK, L"SKIPJACK-%d " }, { CALG_TEK, L"TEK-%d " }, { CALG_RC5, L"RC5-%d " }, { CALG_HMAC, L"HMAC-%d " } }; DWORD g_cAlgToString = sizeof(g_AlgToString)/sizeof(g_AlgToString[0]); ALG_TO_STRING g_ProviderToString[] = { {PROV_RSA_FULL, L"RSA Full"}, {PROV_RSA_SIG , L"RSA Signature Only"}, {PROV_DSS, L"DSS"}, {PROV_FORTEZZA, L"Fortezza"}, {PROV_MS_EXCHANGE, L"Microsoft Exchange"}, {PROV_SSL, L"SSL"}, {PROV_RSA_SCHANNEL, L"RSA SCHANNEL"}, {PROV_DSS_DH, L"DSS DH"}, {PROV_DH_SCHANNEL, L"DH SCHANNEL"}, {PROV_SPYRUS_LYNKS, L"Spyrus LYNKS"}, {PROV_INTEL_SEC, L"Intel SEC"} }; DWORD g_cProviderToString = sizeof(g_ProviderToString)/sizeof(g_ProviderToString[0]); DWORD g_dwDefaultCryptProvType = PROV_RSA_FULL; DWORD g_dwAlgID_Encr_Alg = CALG_RC4; DWORD g_dwAlgID_Encr_Alg_KeySize = 40; DWORD g_dwAlgID_MAC_Alg = CALG_SHA1; DWORD g_dwAlgID_MAC_Alg_KeySize = 160; void Usage(); VOID PrintAlgID(DWORD dwAlgID, DWORD dwStrength); BOOL FProviderSupportsAlg( HCRYPTPROV hQueryProv, DWORD dwAlgId, DWORD* pdwKeySize); DWORD UpdateRegistrySettings(DWORD dwBehavior, HCRYPTPROV hProv); DWORD UpgradeDPAPIBlob(DWORD dwBehavior, PBYTE *ppbData, DWORD *pcbData, BOOL *pfModified); DWORD UpgradeKeys(DWORD dwBehavior); extern DWORD GetLocalSystemToken(HANDLE* phRet); int __cdecl main(int cArg, char *rgszArg[]) { DWORD dwBehavior = 0; DWORD dwError = ERROR_SUCCESS; HCRYPTPROV hProv = 0; HANDLE hToken = NULL; int i; // Parse command line for(i=1; i < cArg; i++) { LPSTR szCurrentArg = rgszArg[i]; if((*szCurrentArg != '-') && (*szCurrentArg != '/')) { Usage(); goto error; } szCurrentArg++; while(*szCurrentArg) { switch(*szCurrentArg++) { case 'f': case 'F': dwBehavior |= BEHAVIOR_FORCE_KEY; break; case 'e': case 'E': dwBehavior |= BEHAVIOR_FORCE_ENC; break; case 'v': case 'V': dwBehavior |= BEHAVIOR_VERBOSE; break; case 'u': case 'U': dwBehavior |= BEHAVIOR_ALLOW_UI; break; case 'm': case 'M': dwBehavior |= BEHAVIOR_MACHINE; break; case 's': case 'S': dwBehavior |= BEHAVIOR_NO_CHANGE | BEHAVIOR_VERBOSE; break; default: Usage(); goto error; } } } if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { dwError = GetLastError(); printf("Could not acquire a crypt context:%lx\n", dwError); goto error; } dwBehavior |= BEHAVIOR_EXPORT; } dwError = UpdateRegistrySettings(dwBehavior, hProv); if(dwError != ERROR_SUCCESS) { goto error; } if(dwBehavior & BEHAVIOR_MACHINE) { dwError = GetLocalSystemToken(&hToken); if(ERROR_SUCCESS == dwError) { if(!ImpersonateLoggedOnUser(hToken)) { dwError = GetLastError(); } } if(ERROR_ACCESS_DENIED == dwError) { printf("You must be an administrator to upgrade machine keys\n"); goto error; } if(ERROR_SUCCESS != dwError) { printf("Cannot impersonate local machine:%lx\n", dwError); } } dwError = UpgradeKeys(dwBehavior); if(dwError != ERROR_SUCCESS) { goto error; } error: if(hProv) { CryptReleaseContext(hProv, 0); } if(hToken) { RevertToSelf(); CloseHandle(hToken); } return (ERROR_SUCCESS == dwError)?0:-1; } void Usage() { printf("Usage: keymigrt [-f] [-v] [-u] [-m] [-s]\n"); printf("CAPI Key upgrade utility\n"); printf("\t-f - Force key upgrade\n"); printf("\t-e - Force Encryption Settings upgrade\n"); printf("\t-v - Verbose\n"); printf("\t-u - Allow upgrade of UI protected keys\n"); printf("\t-m - Upgrade machine keys\n"); printf("\t-s - Show current state, but make no modifications\n\n"); } VOID PrintAlgID(DWORD dwAlgID, DWORD dwStrength) { DWORD i; for(i=0; i < g_cAlgToString; i++) { if(dwAlgID == g_AlgToString[i].AlgId) { wprintf(g_AlgToString[i].wszString, dwStrength); break; } } if(i == g_cAlgToString) { wprintf(L"Unknown 0x%lx - %d", dwAlgID, dwStrength); } }; VOID PrintProviderID(DWORD dwProviderID) { DWORD i; for(i=0; i < g_cProviderToString; i++) { if(dwProviderID == g_ProviderToString[i].AlgId) { wprintf(g_ProviderToString[i].wszString); break; } } if(i == g_cProviderToString) { wprintf(L"Unknown 0x%lx ", dwProviderID); } }; DWORD UpdateRegistrySettings(DWORD dwBehavior, HCRYPTPROV hProv) { DWORD dwReturn = ERROR_SUCCESS; HKEY hKey = NULL; static const WCHAR szProviderKeyName[] = REG_CRYPTPROTECT_LOC L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC L"\\" CRYPTPROTECT_DEFAULT_PROVIDER_GUIDSZ ; DWORD dwDefaultCryptProvType = 0; DWORD dwAlgID_Encr_Alg = 0; DWORD dwAlgID_Encr_Alg_KeySize = -1; DWORD dwAlgID_MAC_Alg = 0; DWORD dwAlgID_MAC_Alg_KeySize = -1; DWORD cbParameter; DWORD dwValueType; DWORD dwParameterValue; DWORD dwDisposition; BOOL fUpgrade = FALSE; SC_HANDLE hscManager = NULL; SC_HANDLE hscProtectedStorage = NULL; SERVICE_STATUS sStatus; DWORD dwWaitTime = 0; dwReturn = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szProviderKeyName, 0, KEY_READ, &hKey); if((ERROR_SUCCESS != dwReturn) && (ERROR_FILE_NOT_FOUND != dwReturn)) { printf("Could not open registry: %lx\n", dwReturn); goto error; } if(hKey) { cbParameter = sizeof(DWORD); dwReturn = RegQueryValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit dwAlgID_Encr_Alg = dwParameterValue; } cbParameter = sizeof(DWORD); dwReturn = RegQueryValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG_KEYSIZE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit dwAlgID_Encr_Alg_KeySize = dwParameterValue; } cbParameter = sizeof(DWORD); dwReturn = RegQueryValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit dwAlgID_MAC_Alg = dwParameterValue; } cbParameter = sizeof(DWORD); dwReturn = RegQueryValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG_KEYSIZE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit dwAlgID_MAC_Alg_KeySize = dwParameterValue; } cbParameter = sizeof(DWORD); dwReturn = RegQueryValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_CRYPT_PROV_TYPE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit dwDefaultCryptProvType = dwParameterValue; } } if(0 != dwAlgID_Encr_Alg) { g_dwAlgID_Encr_Alg = dwAlgID_Encr_Alg; } g_dwAlgID_Encr_Alg_KeySize = dwAlgID_Encr_Alg_KeySize; FProviderSupportsAlg(hProv, g_dwAlgID_Encr_Alg, &g_dwAlgID_Encr_Alg_KeySize); if(0 != dwAlgID_MAC_Alg) { g_dwAlgID_MAC_Alg = dwAlgID_MAC_Alg; } g_dwAlgID_MAC_Alg_KeySize = dwAlgID_MAC_Alg_KeySize; FProviderSupportsAlg(hProv, g_dwAlgID_MAC_Alg, &g_dwAlgID_MAC_Alg_KeySize); if(0 != dwDefaultCryptProvType) { g_dwDefaultCryptProvType = dwDefaultCryptProvType; } if(dwBehavior & BEHAVIOR_VERBOSE) { printf("System Encryption Settings\n"); printf("Provider Type:\t"); PrintProviderID(g_dwDefaultCryptProvType); if(0 == dwDefaultCryptProvType) { printf(" (default)"); } printf("\n"); printf("Encryption Alg:\t"); PrintAlgID(g_dwAlgID_Encr_Alg, g_dwAlgID_Encr_Alg_KeySize); if(-1 == dwAlgID_Encr_Alg_KeySize) { printf(" (default)"); } printf("\n"); printf("MAC Alg:\t"); PrintAlgID(g_dwAlgID_MAC_Alg, g_dwAlgID_MAC_Alg_KeySize); if(-1 == dwAlgID_MAC_Alg_KeySize) { printf(" (default)"); } printf("\n\n"); } if(dwBehavior & BEHAVIOR_NO_CHANGE) { goto error; } // // Ok, upgrade the settings // if(hKey) { RegCloseKey(hKey); hKey = NULL; } // upgrade the algorithms (but never downgrade) if(dwBehavior & BEHAVIOR_EXPORT) { DWORD dwDESKeySize = -1; FProviderSupportsAlg(hProv, CALG_DES, &dwDESKeySize); // upgrade to export strength if((BEHAVIOR_FORCE_ENC & dwBehavior) || // upgrade if forced (0 == dwAlgID_Encr_Alg) || // upgrade if no settings are present ( dwDESKeySize > g_dwAlgID_Encr_Alg_KeySize)) // upgrade if other is weak { dwAlgID_Encr_Alg = CALG_DES; dwAlgID_Encr_Alg_KeySize = dwDESKeySize; fUpgrade = TRUE; } else { dwAlgID_Encr_Alg = g_dwAlgID_Encr_Alg; dwAlgID_Encr_Alg_KeySize = g_dwAlgID_Encr_Alg_KeySize; } } else { DWORD dw3DESKeySize = -1; FProviderSupportsAlg(hProv, CALG_3DES, &dw3DESKeySize); // upgrade to domestic strength if((BEHAVIOR_FORCE_ENC & dwBehavior) || // upgrade if forced (0 == dwAlgID_Encr_Alg) || // upgrade if no settings (CALG_DES == dwAlgID_Encr_Alg) || // upgrade if previously DES ( dw3DESKeySize > g_dwAlgID_Encr_Alg_KeySize) ) // upgrade if weak { dwAlgID_Encr_Alg = CALG_3DES; dwAlgID_Encr_Alg_KeySize = dw3DESKeySize; fUpgrade = TRUE; } else { dwAlgID_Encr_Alg = g_dwAlgID_Encr_Alg; dwAlgID_Encr_Alg_KeySize = g_dwAlgID_Encr_Alg_KeySize; } } FProviderSupportsAlg(hProv, CALG_SHA1, &dwAlgID_MAC_Alg_KeySize); if((BEHAVIOR_FORCE_ENC & dwBehavior) || (g_dwAlgID_MAC_Alg_KeySize < dwAlgID_MAC_Alg_KeySize)) { dwAlgID_MAC_Alg = CALG_SHA1; fUpgrade = TRUE; } else { dwAlgID_MAC_Alg_KeySize = g_dwAlgID_MAC_Alg_KeySize; dwAlgID_MAC_Alg = g_dwAlgID_MAC_Alg; } if(!fUpgrade) { // no upgrade necessary if(dwBehavior & BEHAVIOR_VERBOSE) { printf("No system encryption settings upgrade is necessary\n"); } goto error; } dwReturn = RegCreateKeyExW( HKEY_LOCAL_MACHINE, szProviderKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); if(ERROR_ACCESS_DENIED == dwReturn) { printf("You must be administrator to upgrade system encryption settings.\n"); dwReturn = ERROR_SUCCESS; goto error; } if(ERROR_SUCCESS != dwReturn) { printf("Could not open system's encryption settings for write:%lx\n", dwReturn); goto error; } dwReturn = RegSetValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG, 0, REG_DWORD, (PBYTE)&dwAlgID_Encr_Alg, sizeof(dwAlgID_Encr_Alg) ); if( dwReturn == ERROR_SUCCESS) { // if successful, commit g_dwAlgID_Encr_Alg = dwAlgID_Encr_Alg; } else { printf("Could not set encryption alg:%lx\n", dwReturn); goto error; } dwReturn = RegSetValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG_KEYSIZE, 0, REG_DWORD, (PBYTE)&dwAlgID_Encr_Alg_KeySize, sizeof(dwAlgID_Encr_Alg_KeySize) ); if( dwReturn == ERROR_SUCCESS ) { // if successful, commit g_dwAlgID_Encr_Alg_KeySize = dwAlgID_Encr_Alg_KeySize; } else { printf("Could not set encryption Key Size:%lx\n", dwReturn); goto error; } dwReturn = RegSetValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG, 0, REG_DWORD, (PBYTE)&dwAlgID_MAC_Alg, sizeof(dwAlgID_MAC_Alg) ); if( dwReturn == ERROR_SUCCESS) { // if successful, commit g_dwAlgID_MAC_Alg = dwAlgID_MAC_Alg; } else { printf("Could not set MAC Alg:%lx\n", dwReturn); goto error; } dwReturn = RegSetValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG_KEYSIZE, 0, REG_DWORD, (PBYTE)&dwAlgID_MAC_Alg_KeySize, sizeof(dwAlgID_MAC_Alg_KeySize) ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwAlgID_MAC_Alg_KeySize = dwAlgID_MAC_Alg_KeySize; } else { printf("Could not set MAC Key size:%lx\n", dwReturn); goto error; } dwReturn = RegSetValueExW( hKey, CRYPTPROTECT_DEFAULT_PROVIDER_CRYPT_PROV_TYPE, 0, REG_DWORD, (PBYTE)&dwDefaultCryptProvType, sizeof(dwDefaultCryptProvType) ); if( dwReturn == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwDefaultCryptProvType = dwDefaultCryptProvType; } else { printf("Could not set provider type:%lx\n", dwReturn); goto error; } if(dwBehavior & BEHAVIOR_VERBOSE) { printf("Upgrading system encryption settings\n"); printf("System Encryption Settings\n"); printf("Provider Type:\t"); PrintProviderID(g_dwDefaultCryptProvType); if(0 == dwDefaultCryptProvType) { printf(" (default)"); } printf("\n"); printf("Encryption Alg:\t"); PrintAlgID(g_dwAlgID_Encr_Alg, g_dwAlgID_Encr_Alg_KeySize); if(-1 == dwAlgID_Encr_Alg_KeySize) { printf(" (default)"); } printf("\n"); printf("MAC Alg:\t"); PrintAlgID(g_dwAlgID_MAC_Alg, g_dwAlgID_MAC_Alg_KeySize); if(-1 == dwAlgID_MAC_Alg_KeySize) { printf(" (default)"); } printf("\n\n"); printf("Restarting ProtectedStorage Service...\n"); } // Attempt to restart the protected storage service hscManager = OpenSCManager(NULL, NULL, GENERIC_EXECUTE); if(NULL == hscManager) { dwReturn = GetLastError(); printf("Could not open service controller:%lx\n", dwReturn); } hscProtectedStorage = OpenServiceW(hscManager, L"ProtectedStorage", GENERIC_READ | GENERIC_EXECUTE); if(NULL == hscManager) { dwReturn = GetLastError(); printf("Could not open ProtectedStorage service:%lx\n", dwReturn); } // Shut down pstore if(!QueryServiceStatus(hscProtectedStorage, &sStatus)) { dwReturn = GetLastError(); printf("Could not query ProtectedStorage service status:%lx\n", dwReturn); goto error; } while(SERVICE_STOPPED != sStatus.dwCurrentState) { DWORD dwLastStatus = sStatus.dwCurrentState; DWORD dwCheckpoint = sStatus.dwCheckPoint; switch(sStatus.dwCurrentState) { case SERVICE_RUNNING: if(!ControlService(hscProtectedStorage, SERVICE_CONTROL_STOP, &sStatus)) { dwReturn = GetLastError(); printf("Could not stop ProtectedStorage service:%lx\n", dwReturn); goto error; } break; case SERVICE_PAUSED: if(!ControlService(hscProtectedStorage, SERVICE_CONTROL_CONTINUE, &sStatus)) { dwReturn = GetLastError(); printf("Could not continue ProtectedStorage service:%lx\n", dwReturn); goto error; } break; default: if(!QueryServiceStatus(hscProtectedStorage, &sStatus)) { dwReturn = GetLastError(); printf("Could not query ProtectedStorage service status:%lx\n", dwReturn); goto error; } break; } Sleep(sStatus.dwWaitHint); if((sStatus.dwCheckPoint == dwCheckpoint) && (sStatus.dwCurrentState == dwLastStatus)) { dwWaitTime += sStatus.dwWaitHint; if(dwWaitTime > 120000) // 2 minutes { printf("Service is not responding\n"); goto error; } } else { dwWaitTime = 0; } } if(!StartService(hscProtectedStorage, 0, NULL)) { dwReturn = GetLastError(); printf("Could not start ProtectedStorage service:%lx\n", dwReturn); goto error; } error: if(hKey) { RegCloseKey(hKey); } return dwReturn; } BOOL FProviderSupportsAlg( HCRYPTPROV hQueryProv, DWORD dwAlgId, DWORD* pdwKeySize) { PROV_ENUMALGS sSupportedAlgs; PROV_ENUMALGS_EX sSupportedAlgsEx; DWORD cbSupportedAlgs = sizeof(sSupportedAlgs); DWORD cbSupportedAlgsEx = sizeof(sSupportedAlgsEx); int iAlgs; // now we have provider; enum the algorithms involved for(iAlgs=0; ; iAlgs++) { // // Attempt the EX alg enumeration if (CryptGetProvParam( hQueryProv, PP_ENUMALGS_EX, (PBYTE)&sSupportedAlgsEx, &cbSupportedAlgsEx, (iAlgs == 0) ? CRYPT_FIRST : 0 )) { if (sSupportedAlgsEx.aiAlgid == dwAlgId) { if(*pdwKeySize == -1) { *pdwKeySize = sSupportedAlgsEx.dwMaxLen; } else { if ((sSupportedAlgsEx.dwMinLen > *pdwKeySize) || (sSupportedAlgsEx.dwMaxLen < *pdwKeySize)) return FALSE; } return TRUE; } } else if (!CryptGetProvParam( hQueryProv, PP_ENUMALGS, (PBYTE)&sSupportedAlgs, &cbSupportedAlgs, (iAlgs == 0) ? CRYPT_FIRST : 0 )) { // trouble enumerating algs break; if (sSupportedAlgs.aiAlgid == dwAlgId) { // were we told to ignore size? if (*pdwKeySize != -1) { // else, if defaults don't match if (sSupportedAlgs.dwBitLen != *pdwKeySize) { return FALSE; } } // report back size *pdwKeySize = sSupportedAlgs.dwBitLen; return TRUE; } } else { // trouble enumerating algs break; } } return FALSE; } DWORD GetUserStorageArea( IN DWORD dwProvType, IN BOOL fMachineKeyset, IN BOOL fOldWin2KMachineKeyPath, OUT BOOL *pfIsLocalSystem, // used if fMachineKeyset is FALSE, in this // case TRUE is returned if running as Local System IN OUT LPWSTR *ppwszUserStorageArea ); DWORD UpgradeKeys(DWORD dwBehavior) { DWORD aProvTypes[] = {PROV_RSA_FULL, PROV_DSS }; DWORD cProvTypes = sizeof(aProvTypes)/sizeof(aProvTypes[0]); DWORD iProv; DWORD dwLastError = ERROR_SUCCESS; HANDLE hFind = INVALID_HANDLE_VALUE; CHAR szContainerName[MAX_PATH+1]; DWORD cbContainerName = 0; BOOL fModified; for(iProv = 0; iProv < cProvTypes; iProv++) { DWORD dwContainerFlags = CRYPT_FIRST; while(TRUE) { KEY_CONTAINER_INFO ContInfo; cbContainerName = MAX_PATH + 1; ZeroMemory(&ContInfo, sizeof(ContInfo)); dwLastError = GetNextContainer(aProvTypes[iProv], dwBehavior & BEHAVIOR_MACHINE, dwContainerFlags, szContainerName, &cbContainerName, &hFind); if(ERROR_NO_MORE_ITEMS == dwLastError) { hFind = INVALID_HANDLE_VALUE; } if(ERROR_SUCCESS != dwLastError) { break; } dwContainerFlags = 0; fModified = FALSE; dwLastError = ReadContainerInfo( aProvTypes[iProv], szContainerName, dwBehavior & BEHAVIOR_MACHINE, 0, &ContInfo ); if(ERROR_SUCCESS != dwLastError) { continue; } if(dwBehavior & BEHAVIOR_VERBOSE) { printf("========================================\n"); printf("Key Container:\t\t%s\n\n",szContainerName); } if((ContInfo.ContLens.cbExchEncPriv) && (ContInfo.pbExchEncPriv)) { if(dwBehavior & BEHAVIOR_VERBOSE) { printf(" Exchange Key\n"); } dwLastError = UpgradeDPAPIBlob(dwBehavior, &ContInfo.pbExchEncPriv, &ContInfo.ContLens.cbExchEncPriv, &fModified); printf("\n"); } if((ContInfo.ContLens.cbSigEncPriv) && (ContInfo.pbSigEncPriv)) { if(dwBehavior & BEHAVIOR_VERBOSE) { printf(" Signature Key\n"); } dwLastError = UpgradeDPAPIBlob(dwBehavior, &ContInfo.pbSigEncPriv, &ContInfo.ContLens.cbSigEncPriv, &fModified); printf("\n"); } if(dwBehavior & BEHAVIOR_VERBOSE) { if(((0 == ContInfo.ContLens.cbExchEncPriv) || (NULL == ContInfo.pbExchEncPriv)) && ((0 == ContInfo.ContLens.cbSigEncPriv) || (NULL == ContInfo.pbSigEncPriv))) { printf(" There are no keys in this container\n\n"); } } if(((dwBehavior & BEHAVIOR_FORCE_ENC) || fModified) && (0 == (dwBehavior & BEHAVIOR_NO_CHANGE))); { dwLastError = WriteContainerInfo( aProvTypes[iProv], ContInfo.rgwszFileName, dwBehavior & BEHAVIOR_MACHINE, &ContInfo ); } FreeContainerInfo(&ContInfo); } } if(INVALID_HANDLE_VALUE != hFind) { CloseHandle(hFind); } return dwLastError; } typedef struct _DPAPI_BLOB_DATA { DWORD dwVersion; DWORD dwFlags; LPWSTR wszDataDescription; DWORD cbDataDescription; DWORD EncrAlg; DWORD EncrAlgSize; DWORD MacAlg; DWORD MacAlgSize; } DPAPI_BLOB_DATA, *PDPAPI_BLOB_DATA; DWORD GetBlobData(PBYTE pbData, DWORD cbData, PDPAPI_BLOB_DATA BlobData) { PBYTE pbCurrent = pbData; DWORD dwKeySize = 0; if(cbData < sizeof (DWORD) + sizeof(GUID) + sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD)) { return ERROR_INVALID_DATA; } pbCurrent += sizeof(DWORD) + sizeof(GUID); BlobData->dwVersion = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD) + sizeof(GUID); BlobData->dwFlags = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); BlobData->cbDataDescription = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); if((DWORD)(pbCurrent - pbData) + BlobData->cbDataDescription + sizeof(DWORD) + sizeof(DWORD) + sizeof(DWORD)> cbData) { return ERROR_INVALID_DATA; } BlobData->wszDataDescription = (LPWSTR)pbCurrent; pbCurrent += BlobData->cbDataDescription; BlobData->EncrAlg = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); BlobData->EncrAlgSize = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); // skip past key dwKeySize = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); if((DWORD)(pbCurrent - pbData) + dwKeySize + sizeof(DWORD) > cbData) { return ERROR_INVALID_DATA; } pbCurrent += dwKeySize; // skip past salt dwKeySize = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); if((DWORD)(pbCurrent - pbData) + dwKeySize + sizeof(DWORD) + sizeof(DWORD)> cbData) { return ERROR_INVALID_DATA; } pbCurrent += dwKeySize; BlobData->MacAlg = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); BlobData->MacAlgSize = *(DWORD UNALIGNED *)pbCurrent; pbCurrent += sizeof(DWORD); return ERROR_SUCCESS; } DWORD PrintBlobData(PDPAPI_BLOB_DATA BlobData) { wprintf(L" Description:\t\t%s\n", BlobData->wszDataDescription); wprintf(L" Encryption Alg:\t"); PrintAlgID(BlobData->EncrAlg, BlobData->EncrAlgSize); wprintf(L"\n"); wprintf(L" MAC Alg:\t\t"); PrintAlgID(BlobData->MacAlg, BlobData->MacAlgSize); wprintf(L"\n\n"); return ERROR_SUCCESS; } DWORD UpgradeDPAPIBlob(DWORD dwBehavior, PBYTE *ppbData, DWORD *pcbData, BOOL *pfModified) { DPAPI_BLOB_DATA BlobData; DWORD dwError = ERROR_SUCCESS; DATA_BLOB DataIn; DATA_BLOB DataOut; LPWSTR wszDescription = NULL; CRYPTPROTECT_PROMPTSTRUCT Prompt; DWORD dwFlags = 0; DataIn.pbData = NULL; DataIn.cbData = 0; DataOut.pbData = NULL; DataOut.cbData = 0; dwError = GetBlobData(*ppbData, *pcbData, &BlobData); if(ERROR_SUCCESS != dwError) { printf("Could not open key:%lx\n ", dwError); goto error; } if(MS_BASE_CRYPTPROTECT_VERSION != BlobData.dwVersion) { printf("Unknown data version\n"); dwError = ERROR_INVALID_DATA; goto error; } if(dwBehavior & BEHAVIOR_VERBOSE) { dwError = PrintBlobData(&BlobData); } if(dwBehavior & BEHAVIOR_NO_CHANGE) { goto error; } // Check to see if upgrade is required if((BlobData.EncrAlgSize >= g_dwAlgID_Encr_Alg_KeySize) && (0 == (dwBehavior & BEHAVIOR_FORCE_KEY))) { if(dwBehavior & BEHAVIOR_VERBOSE) { printf(" No upgrade necessary\n"); } goto error; } if(((BlobData.dwFlags & CRYPTPROTECT_PROMPT_ON_UNPROTECT) || (BlobData.dwFlags & CRYPTPROTECT_PROMPT_ON_PROTECT)) && (0 == (dwBehavior & BEHAVIOR_ALLOW_UI))) { if(dwBehavior & BEHAVIOR_VERBOSE) { printf(" This key requires UI, and will not be upgraded\n"); } goto error; } // // Upgrade the key // DataIn.pbData = *ppbData; DataIn.cbData = *pcbData; Prompt.cbSize = sizeof(Prompt); Prompt.dwPromptFlags = BlobData.dwFlags & (CRYPTPROTECT_PROMPT_ON_UNPROTECT | CRYPTPROTECT_PROMPT_ON_PROTECT); Prompt.hwndApp = NULL; Prompt.szPrompt = L"Key Upgrade Utility\n"; if(0 == (dwBehavior & BEHAVIOR_ALLOW_UI)) { dwFlags |= CRYPTPROTECT_UI_FORBIDDEN; } if(0 == (dwBehavior & BEHAVIOR_MACHINE)) { dwFlags |= CRYPTPROTECT_LOCAL_MACHINE; } if(!CryptUnprotectData(&DataIn, &wszDescription, NULL, NULL, &Prompt, dwFlags, &DataOut)) { dwError = GetLastError(); printf("Could not unprotect key:%lx\n", dwError); goto error; } DataIn.pbData = NULL; DataIn.cbData = 0; if(!CryptProtectData(&DataOut, wszDescription, NULL, NULL, &Prompt, dwFlags, &DataIn)) { dwError = GetLastError(); printf("Could not protect key:%lx\n", dwError); goto error; } dwError = GetBlobData(DataIn.pbData, DataIn.cbData, &BlobData); if(ERROR_SUCCESS != dwError) { printf("Could not open key:%lx\n ", dwError); goto error; } if(MS_BASE_CRYPTPROTECT_VERSION != BlobData.dwVersion) { printf("Unknown data version\n"); dwError = ERROR_INVALID_DATA; goto error; } if(dwBehavior & BEHAVIOR_VERBOSE) { printf(" Upgraded To\n"); PrintBlobData(&BlobData); } LocalFree(*ppbData); *ppbData = DataIn.pbData; *pcbData = DataIn.cbData; *pfModified = TRUE; error: if(DataOut.pbData) { ZeroMemory(DataOut.pbData, DataOut.cbData); } return dwError; }