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.
 
 
 
 
 
 

1267 lines
33 KiB

//
// keymigrt.c
//
// Copyright (c) Microsoft Corp, 2000
//
//
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include <stdlib.h>
#include <wincrypt.h>
#include <cspdk.h>
#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;
}