//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: signcode.cpp // // Contents: The signcode console tool // // History: July-1st-1997 Xiaohs Created //---------------------------------------------------------------------------- #include #include #include #include #include #include #include "mssip.h" #include "resource.h" #include "unicode.h" #include "signhlp.h" #include "pvkhlpr.h" #include "toolutl.h" #include "javaAttr.h" #include "cryptui.h" #define ACTION_SIGN 0x01 #define ACTION_STAMP 0x02 #define ACTION_REQUEST 0x04 #define ACTION_RESPONSE 0x08 #define STORE_DEFAULT_NAME_MAX 40 #define SHA1_LENGTH 20 // Global data for parsing the input parameters DWORD dwAction = 0; DWORD dwExpectedError = 0; BOOL fSigning = TRUE; BOOL fTesting = FALSE; BOOL fStoreTechnology=TRUE; BOOL fUndocumented = FALSE; LPWSTR pwszFile = NULL; LPWSTR pwszCapiProvider=NULL; LPWSTR pwszProviderType=NULL; LPWSTR pwszPvkFile = NULL; LPWSTR pwszKeyContainer= NULL; LPWSTR pwszOpusName = NULL; LPWSTR pwszOpusInfo = NULL; LPWSTR pwszAlgorithm = NULL; LPWSTR pwszAuthority = NULL; LPWSTR pwszSpcFile = NULL; LPWSTR pwszCertFile =NULL; LPWSTR pwszCommonName =NULL; LPWSTR pwszStoreName= NULL; LPWSTR pwszStoreLocation=NULL; LPWSTR pwszStorePolicy= NULL; LPWSTR pwszHttpTime = NULL; LPWSTR pwszRequestFile =NULL; LPWSTR pwszResponseFile =NULL; LPWSTR pwszWait=NULL; LPWSTR pwszRepeat=NULL; LPWSTR pwszKeySpec=NULL; LPWSTR pwszSignerIndex=NULL; LPWSTR pwszSha1Hash = NULL; BYTE *g_pbHash=NULL; DWORD g_cbHash=0; DWORD dwCertEncodingType=X509_ASN_ENCODING; DWORD dwStoreEncodingType=X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; DWORD dwWait=0; DWORD dwRepeat=1; DWORD dwProviderType = PROV_RSA_FULL; BOOL fCommercial = FALSE; BOOL fIndividual = FALSE; DWORD dwKeySpec=0; DWORD dwSignerIndex=0; LPWSTR *prgwszDllName=NULL; LPWSTR *prgwszDllParam=NULL; DWORD dwDllIndex=0; DWORD dwParamIndex=0; //default: //Assume the store is on CERT_SYSTEM_STORE_CURRENT_USER DWORD dwStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER; DWORD dwStorePolicy=SIGNER_CERT_POLICY_SPC; WCHAR wszMyStore[STORE_DEFAULT_NAME_MAX]; //Use MD5 as the default hashing algorithm ALG_ID dwAlgorithmOid = CALG_MD5; //Global Data for loading the string #define OPTION_SWITCH_SIZE 5 #define WSTR_LENGTH_MAX 30 WCHAR wszCaption[WSTR_LENGTH_MAX]; WCHAR wszNULL[WSTR_LENGTH_MAX]; WCHAR wszPlus[WSTR_LENGTH_MAX]; HMODULE hModule=NULL; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // function prototypes HRESULT InitDllParameter(PCRYPT_ATTRIBUTES pAuthAttr, PCRYPT_ATTRIBUTES pUnauthAttr, PCRYPT_ATTRIBUTES *ppAuthAttr, PCRYPT_ATTRIBUTES *ppUnauthAttr); void ReleaseDllParameter(PCRYPT_ATTRIBUTES * ppAuthAttr, PCRYPT_ATTRIBUTES * ppUnauthAttr); HRESULT SetUpSubjectInfo(SIGNER_SUBJECT_INFO *pSubjectInfo, SIGNER_FILE_INFO *pFileInfo); HRESULT SetUpParameter(SIGNER_SUBJECT_INFO *pSubjectInfo, SIGNER_FILE_INFO *pFileInfo, SIGNER_SIGNATURE_INFO *pSignatureInfo, SIGNER_ATTR_AUTHCODE *pAttrAuthcode, SIGNER_PROVIDER_INFO *pProviderInfo, SIGNER_CERT_STORE_INFO *pCertStoreInfo, SIGNER_CERT *pSignerCert, CRYPT_ATTRIBUTES *pAuthenticated, CRYPT_ATTRIBUTES *pUnauthenticated, HCERTSTORE *phCertStore); PCCERT_CONTEXT GetSigningCert(HCERTSTORE *phCertStore, BOOL *pfMore); HRESULT GetCertHashFromFile(LPWSTR pwszCertFile, BYTE **pHash, DWORD *pcbHash, BOOL *pfMore); //-------------------------------------------------------------------------- // Get the hModule hanlder and init two DLLMain. // //--------------------------------------------------------------------------- BOOL InitModule() { if(!(hModule=GetModuleHandle(NULL))) return FALSE; return TRUE; } //-------------------------------------------------------------------------------- // // Help command //-------------------------------------------------------------------------------- void Usage() { IDSwprintf(hModule,IDS_SYNTAX); IDSwprintf(hModule,IDS_OPTIONS); IDSwprintf(hModule,IDS_OPTION_SPC_DESC); IDSwprintf(hModule,IDS_OPTION_V_DESC); IDSwprintf(hModule,IDS_OPTION_K_DESC); IDSwprintf(hModule,IDS_OPTION_N_DESC); IDSwprintf(hModule,IDS_OPTION_I_DESC); IDSwprintf(hModule,IDS_OPTION_P_DESC); IDSwprintf(hModule,IDS_OPTION_Y_DESC); IDSwprintf(hModule,IDS_OPTION_KY_DESC); IDS_IDS_IDSwprintf(hModule, IDS_OPTION_KY_VALUES, IDS_OPTION_KY_SIG, IDS_OPTION_KY_EXC); IDSwprintf(hModule,IDS_OPTION_AUTH_DESC); IDS_IDS_IDSwprintf(hModule,IDS_OPTION_AUTH_VALUE, IDS_AUTHORITY_ID, IDS_AUTHORITY_CM); IDS_IDSwprintf(hModule,IDS_OPTION_AUTH_VALUE1, IDS_AUTHORITY_DEFAULT); IDSwprintf(hModule,IDS_OPTION_A_DESC); IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_MORE_VALUE, IDS_A_MD5, IDS_A_SHA, IDS_A_MD5); IDSwprintf(hModule,IDS_OPTION_T_DESC); IDSwprintf(hModule,IDS_OPTION_TR_DESC); IDSwprintf(hModule,IDS_OPTION_TW_DESC); IDSwprintf(hModule,IDS_OPTION_J_DESC); IDSwprintf(hModule,IDS_OPTION_JP_DESC); IDSwprintf(hModule,IDS_OPTION_C_DESC); IDSwprintf(hModule,IDS_OPTION_S_DESC); IDSwprintf(hModule,IDS_OPTION_R_DESC); IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_MORE_VALUE, IDS_R_LM, IDS_R_CU,IDS_R_CU); IDSwprintf(hModule,IDS_OPTION_SP_DESC); IDSwprintf(hModule,IDS_OPTION_SP_DESC1); IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_MORE_VALUE, IDS_OPTION_SP_CHAIN, IDS_OPTION_SP_SPCSTORE, IDS_OPTION_SP_SPCSTORE); IDSwprintf(hModule, IDS_OPTION_CN_DESC); IDSwprintf(hModule, IDS_OPTION_SHA1_DESC); IDSwprintf(hModule,IDS_OPTION_X_DESC); IDSwprintf(hModule,IDS_ENFLN); IDSwprintf(hModule, IDS_MORE_INFO_1); IDSwprintf(hModule, IDS_MORE_INFO_2); IDSwprintf(hModule, IDS_MORE_INFO_3); } void UndocumentedUsage() { IDSwprintf(hModule,IDS_SYNTAX); IDSwprintf(hModule,IDS_OPTIONS); IDSwprintf(hModule, IDS_OPTION_H_DESC); IDSwprintf(hModule, IDS_OPTION_TQ_DESC); IDSwprintf(hModule, IDS_OPTION_TS_DESC); IDSwprintf(hModule, IDS_OPTION_INDEX_DESC); //mark this is undocumented fUndocumented=TRUE; } //-------------------------------------------------------------------------------- // Print out error msg based on the HRESULT //-------------------------------------------------------------------------------- BOOL PrintBasedOnHResult(HRESULT hr) { BOOL fKnownResult=TRUE; switch(hr) { //0x80070002 is the HRESULT_FROM_WIN32(GetLastError()) when CreateFile failed case 0x80070002: IDSwprintf(hModule,IDS_ERR_INPUT_INVALID); break; case HRESULT_FROM_WIN32(ERROR_INVALID_DATA): IDSwprintf(hModule,IDS_ERR_RESPONSE_INVALID); break; case HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION): IDSwprintf(hModule, IDS_ERR_INVALID_ADDRESS); break; case CRYPT_E_NO_MATCH: IDSwprintf(hModule,IDS_ERR_NOMATCH); break; case TYPE_E_TYPEMISMATCH: IDSwprintf(hModule,IDS_ERR_AUTH); break; case CRYPT_E_FILERESIZED: IDSwprintf(hModule,IDS_ERR_RESIZE); break; case TRUST_E_TIME_STAMP: IDSwprintf(hModule, IDS_ERR_TS_CERT_INVALID); break; case CRYPT_E_NO_DECRYPT_CERT: IDSwprintf(hModule, IDS_ERR_NO_CERT, pwszStoreName); break; case CRYPT_E_DELETED_PREV: IDSwprintf(hModule, IDS_ERR_TOO_MANY_CERT, pwszStoreName); break; case CRYPT_E_NO_PROVIDER: IDSwprintf(hModule, IDS_ERR_NO_PROVIDER); break; case CERT_E_CHAINING: IDSwprintf(hModule, IDS_ERR_NO_CHAINING); break; case CERT_E_EXPIRED: IDSwprintf(hModule, IDS_ERR_EXPRIED); break; default: fKnownResult=FALSE; } return fKnownResult; } //-------------------------------------------------------------------------------- // Convert an array of wchars to a BLOB //-------------------------------------------------------------------------------- HRESULT WSZtoBLOB(LPWSTR pwsz, BYTE **ppbByte, DWORD *pcbByte) { HRESULT hr=E_FAIL; DWORD dwIndex=0; ULONG ulHalfByte=0; DWORD dw1st=0; DWORD dw2nd=0; if((!pwsz) || (!ppbByte) || (!pcbByte)) return E_INVALIDARG; *ppbByte=NULL; *pcbByte=0; //make sure the pwsz consists of 20 characters if(wcslen(pwsz)!= 2*SHA1_LENGTH) return E_FAIL; //memory allocation *ppbByte=(BYTE *)ToolUtlAlloc(SHA1_LENGTH); if(NULL==(*ppbByte)) return E_INVALIDARG; memset(*ppbByte, 0, SHA1_LENGTH); //go through two characters (one byte) at a time for(dwIndex=0; dwIndex=0) { ulHalfByte=(ULONG)((ULONG)(pwsz[dw1st])-(ULONG)(L'0')); } else { if(((int)(towupper(pwsz[dw1st]))-(int)(L'A')) >=0 && ((int)(towupper(pwsz[dw1st]))-(int)(L'A')) <=5 ) ulHalfByte=10+(ULONG)((ULONG)(towupper(pwsz[dw1st]))-(ULONG)(L'A')); else { hr=E_INVALIDARG; goto CLEANUP; } } //copy the 1st character (*ppbByte)[dwIndex]=(BYTE)ulHalfByte; //left shift 4 bits (*ppbByte)[dwIndex]= (*ppbByte)[dwIndex] <<4; //2nd character if(((int)(pwsz[dw2nd])-(int)(L'0')) <=9 && ((int)(pwsz[dw2nd])-(int)(L'0')) >=0) { ulHalfByte=(ULONG)((ULONG)(pwsz[dw2nd])-(ULONG)(L'0')); } else { if(((int)(towupper(pwsz[dw2nd]))-(int)(L'A')) >=0 && ((int)(towupper(pwsz[dw2nd]))-(int)(L'A')) <=5 ) ulHalfByte=10+(ULONG)((ULONG)(towupper(pwsz[dw2nd]))-(ULONG)(L'A')); else { hr=E_INVALIDARG; goto CLEANUP; } } //ORed the second character (*ppbByte)[dwIndex]=(*ppbByte)[dwIndex] | ((BYTE)ulHalfByte); } hr=S_OK; CLEANUP: if(hr!=S_OK) { if(*ppbByte) ToolUtlFree(*ppbByte); *ppbByte=NULL; } else *pcbByte=SHA1_LENGTH; return hr; } //-------------------------------------------------------------------------------- //make sure the input parameters make sense for signing //-------------------------------------------------------------------------------- BOOL CheckSignParam() { //make sure pwszPvkFile and pwszKeyContainer name are not set at the same time if(pwszPvkFile && pwszKeyContainer) { IDSwprintf(hModule,IDS_ERR_BOTH_PVK); return FALSE; } //make sure spc/pvk information and store related information can not be set //at the same time if(pwszSpcFile || pwszPvkFile || pwszKeyContainer || pwszProviderType || pwszCapiProvider ||pwszKeySpec) { fStoreTechnology=FALSE; if(pwszStoreName || pwszCertFile || pwszStoreName || pwszStorePolicy || pwszStoreLocation || pwszCommonName || pwszSha1Hash) { IDSwprintf(hModule,IDS_ERR_BOTH_SPC); return FALSE; } //now that we are not using certStore, spc file has to be set if(!pwszSpcFile) { IDSwprintf(hModule, IDS_ERR_NO_SPC); return FALSE; } //either PVKFile or KeyContainer has to be set if(pwszPvkFile == NULL && pwszKeyContainer ==NULL) { IDSwprintf(hModule,IDS_ERR_NO_PVK); return FALSE; } } //pwszCommonName, pwszCertFile and pwszSha1Hash can not be set at the same time if(pwszCertFile) { if(pwszCommonName || pwszSha1Hash) { IDSwprintf(hModule, IDS_ERR_BOTH_CN_SHA1); return FALSE; } } if(pwszCommonName && pwszSha1Hash) { IDSwprintf(hModule, IDS_ERR_BOTH_CN_SHA1); return FALSE; } //if pwszStoreLocation is set, then the storeName as to be set if(pwszStoreLocation && (pwszStoreName==NULL)) { IDSwprintf(hModule, IDS_STORE_LOCATION_NAME); return FALSE; } return TRUE; } //-------------------------------------------------------------------------------- //make sure the user has passed in a valid set of parameters //-------------------------------------------------------------------------------- BOOL CheckParameter() { BOOL fValid=FALSE; //has to set the file name if(!pwszFile) { IDSwprintf(hModule,IDS_ERR_NO_FILE); return FALSE; } if(fSigning==TRUE) { dwAction |= ACTION_SIGN; //make sure the input parameters make sense if(!CheckSignParam()) return FALSE; } if(pwszResponseFile) { dwAction |= ACTION_RESPONSE; } if(pwszHttpTime) { dwAction |= ACTION_STAMP; //make sure that we have http:// in the address if(wcslen(pwszHttpTime)<=7) { IDSwprintf(hModule,IDS_ERR_ADDR_INVALID); return FALSE; } if(IDSwcsnicmp(hModule, pwszHttpTime, IDS_HTTP,7)!=0) { IDSwprintf(hModule,IDS_ERR_HTTP); return FALSE; } } if(pwszRequestFile) { dwAction |= ACTION_REQUEST; } //make sure timestamping and applying response do not go together if((dwAction & ACTION_RESPONSE) && (dwAction & ACTION_STAMP)) { IDSwprintf(hModule,IDS_ERR_TIME_RESPONSE); return FALSE; } //make sure apply response can not be done after a new signature if((dwAction & ACTION_SIGN) && (dwAction & ACTION_RESPONSE)) { IDSwprintf(hModule,IDS_ERR_SIGN_RESPONSE); return FALSE; } //determine the algorithm OID if(pwszAlgorithm) { if(IDSwcsicmp(hModule, pwszAlgorithm, IDS_A_MD5) == 0) dwAlgorithmOid = CALG_MD5; else { if(IDSwcsicmp(hModule,pwszAlgorithm, IDS_A_SHA) == 0) dwAlgorithmOid = CALG_SHA1; else { IDSwprintf(hModule,IDS_ERR_NO_ALGO); return FALSE; } } } //determing the store location if(pwszStoreLocation) { if(IDSwcsicmp(hModule,pwszStoreLocation, IDS_R_CU) == 0) dwStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER; else { if(IDSwcsicmp(hModule,pwszStoreLocation, IDS_R_LM) == 0) dwStoreFlag = CERT_SYSTEM_STORE_LOCAL_MACHINE; else { IDSwprintf(hModule,IDS_ERR_NO_REG); return FALSE; } } } //determing the store policy if(pwszStorePolicy) { if(IDSwcsicmp(hModule,pwszStorePolicy, IDS_OPTION_SP_CHAIN) == 0) dwStorePolicy=SIGNER_CERT_POLICY_CHAIN; else { if(IDSwcsicmp(hModule, pwszStorePolicy, IDS_OPTION_SP_SPCSTORE) == 0) dwStorePolicy=SIGNER_CERT_POLICY_SPC; else { IDSwprintf(hModule,IDS_ERR_NO_POLICY); return FALSE; } } } //determine the signing authority, either individual or commercial if(pwszAuthority) { if(IDSwcsicmp(hModule,pwszAuthority, IDS_AUTHORITY_ID) == 0) fIndividual = TRUE; else { if(IDSwcsicmp(hModule,pwszAuthority, IDS_AUTHORITY_CM) == 0) fCommercial = TRUE; else { IDSwprintf(hModule,IDS_ERR_NO_AUTH); return FALSE; } } } //determine the key specificatioin if(pwszKeySpec) { if(IDSwcsicmp(hModule,pwszKeySpec, IDS_OPTION_KY_SIG) == 0) dwKeySpec = AT_SIGNATURE; else { if(IDSwcsicmp(hModule,pwszKeySpec, IDS_OPTION_KY_EXC) == 0) dwKeySpec = AT_KEYEXCHANGE; else dwKeySpec=_wtol(pwszKeySpec); } } //get the hash if(pwszSha1Hash) { if(S_OK != WSZtoBLOB(pwszSha1Hash, &g_pbHash, &g_cbHash)) { //sha1 hash is invalid IDSwprintf(hModule, IDS_ERR_SHA1_HASH); return FALSE; } } //determine the provider Type if(pwszProviderType) dwProviderType = _wtoi(pwszProviderType); //get the # of timestamp trial and the # of seconds of delay between //each trial if(pwszWait) dwWait = _wtoi(pwszWait); if(pwszRepeat) dwRepeat = _wtoi(pwszRepeat); //determine the default store name if(!pwszStoreName) pwszStoreName=wszMyStore; //determin the signerIndex. Default to 0 if(pwszSignerIndex) dwSignerIndex=_wtol(pwszSignerIndex); return TRUE; } //-------------------------------------------------------------------------------- // Set the parameters. They can only be set once //-------------------------------------------------------------------------------- BOOL SetParam(WCHAR **ppwszParam, WCHAR *pwszValue) { if(*ppwszParam!=NULL) { IDSwprintf(hModule,IDS_ERR_TOO_MANY_PARAM); return FALSE; } *ppwszParam=pwszValue; return TRUE; } //-------------------------------------------------------------------------------- // Parse arguements //-------------------------------------------------------------------------------- BOOL ParseSwitch (int *pArgc, WCHAR **pArgv[]) { WCHAR* param = **pArgv; //move pass '/' or '-' param++; if (IDSwcsicmp(hModule, param, IDS_OPTION_H) == 0) { fTesting = TRUE; if (!(param[1])) { if (!--(*pArgc)) return FALSE; (*pArgv)++; param = **pArgv; dwExpectedError = wcstoul(¶m[0], NULL, 16); } else { dwExpectedError = wcstoul(¶m[1], NULL, 16); } return TRUE; } else if(IDSwcsicmp(hModule, param, IDS_OPTION_SPC)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszSpcFile, **pArgv); } else if(IDSwcsicmp(hModule, param, IDS_OPTION_C)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszCertFile, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_S)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszStoreName, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_R)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszStoreLocation, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_SP)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszStorePolicy, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_CN)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszCommonName, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_SHA1)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszSha1Hash, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_V)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszPvkFile, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_K)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszKeyContainer, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_N)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszOpusName, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_I)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszOpusInfo, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_P)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszCapiProvider, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_Y)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszProviderType, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_KY)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszKeySpec, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_AUTH)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszAuthority, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_A)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszAlgorithm, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_X)==0) { fSigning=FALSE; return TRUE; } else if(IDSwcsicmp(hModule,param, IDS_OPTION_T)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszHttpTime, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_TW)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszWait,**pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_TR)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszRepeat,**pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_J)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; prgwszDllName[dwDllIndex]=**pArgv; //mark its corresponding parameter as NULL dwParamIndex=dwDllIndex; prgwszDllParam[dwParamIndex]=NULL; dwDllIndex++; return TRUE; } else if(IDSwcsicmp(hModule,param, IDS_OPTION_JP)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; //make sure there is only one or less parameter per dll if(dwParamIndex+1!=dwDllIndex) return FALSE; prgwszDllParam[dwParamIndex]=**pArgv; dwParamIndex++; return TRUE; } else if(IDSwcsicmp(hModule,param, IDS_OPTION_TS)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszResponseFile, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_TQ)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszRequestFile, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_INDEX)==0) { if (!--(*pArgc)) return FALSE; (*pArgv)++; return SetParam(&pwszSignerIndex, **pArgv); } else if(IDSwcsicmp(hModule,param, IDS_OPTION_TEST)==0) { UndocumentedUsage(); return FALSE; } return FALSE; } //-------------------------------------------------------------------------------- // // wmain // //-------------------------------------------------------------------------------- extern "C" int __cdecl wmain(int argc, WCHAR ** wargv) { HRESULT hr = E_FAIL; int idsAction=IDS_ACTION_SIGNCODE; BYTE *pbStampResponse=NULL; DWORD cbStampResponse=0; BYTE *pbStampRequest=NULL; DWORD cbStampRequest=0; HANDLE hFile=NULL; DWORD dwWriteBytes=0; WCHAR *pwChar; WCHAR wszSwitch1[OPTION_SWITCH_SIZE]; WCHAR wszSwitch2[OPTION_SWITCH_SIZE]; CRYPT_ATTRIBUTES AuthAttr; CRYPT_ATTRIBUTES UnauthAttr; PCRYPT_ATTRIBUTES *ppAuthAttr=NULL; PCRYPT_ATTRIBUTES *ppUnauthAttr=NULL; DWORD dwIndex=0; DWORD dwMilliSeconds=0; SIGNER_SUBJECT_INFO subjectInfo; SIGNER_FILE_INFO fileInfo; SIGNER_SIGNATURE_INFO signatureInfo; SIGNER_ATTR_AUTHCODE attrAuthcode; SIGNER_PROVIDER_INFO providerInfo; SIGNER_CERT_STORE_INFO certStoreInfo; SIGNER_CERT signerCert; HCERTSTORE hCertStore=NULL; CRYPTUI_WIZ_DIGITAL_SIGN_INFO DigitalSignInfo; //call the UI version of the signcode if(1==argc) { //memset memset(&DigitalSignInfo, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO)); DigitalSignInfo.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO); //call the signing wizard, which provides //the confirmation result. if(CryptUIWizDigitalSign(0, NULL, NULL, &DigitalSignInfo, NULL)) return 0; else return -1; } //get the module handle if(!InitModule()) return -1; //load the strings necessary for parsing the parameters if( !LoadStringU(hModule, IDS_SWITCH1, wszSwitch1, OPTION_SWITCH_SIZE) ||!LoadStringU(hModule, IDS_SWITCH2, wszSwitch2, OPTION_SWITCH_SIZE) ||!LoadStringU(hModule, IDS_CAPITION, wszCaption, WSTR_LENGTH_MAX) ||!LoadStringU(hModule, IDS_PLUS, wszPlus, WSTR_LENGTH_MAX) ||!LoadStringU(hModule, IDS_MY, wszMyStore, STORE_DEFAULT_NAME_MAX) ) return -1; //load wszNULL LoadStringU(hModule, IDS_NULL, wszNULL, WSTR_LENGTH_MAX); if ( argc <= 1 ) { Usage (); return -1; } //allocate memory for prgwszDllName and prgwszDllParam prgwszDllName=(LPWSTR *)ToolUtlAlloc(sizeof(LPWSTR)*argc); prgwszDllParam=(LPWSTR *)ToolUtlAlloc(sizeof(LPWSTR)*argc); dwDllIndex=0; dwParamIndex=0; if(!prgwszDllName || !prgwszDllParam) { hr=E_OUTOFMEMORY; goto CLEANUP; } //memset memset(prgwszDllName, 0, sizeof(LPWSTR)*argc); memset(prgwszDllParam, 0, sizeof(LPWSTR)*argc); memset(&AuthAttr, 0, sizeof(CRYPT_ATTRIBUTES)); memset(&UnauthAttr, 0, sizeof(CRYPT_ATTRIBUTES)); //parse the parameters while (--argc) { pwChar = *++wargv; if (*pwChar == *wszSwitch1 || *pwChar == *wszSwitch2) { //parse the options if(!ParseSwitch (&argc, &wargv)) { if(FALSE==fUndocumented) Usage(); return -1; } } else { //parse the file name if(!SetParam(&pwszFile, pwChar)) { Usage(); hr=E_FAIL; goto CLEANUP; } } } //Determine the parameter sets passed in by the user if(!CheckParameter()) { Usage(); hr=E_INVALIDARG; goto CLEANUP; } //memory allocation for the dlls if(dwDllIndex) { ppAuthAttr=(PCRYPT_ATTRIBUTES *)ToolUtlAlloc(sizeof(PCRYPT_ATTRIBUTES)*dwDllIndex); ppUnauthAttr=(PCRYPT_ATTRIBUTES *)ToolUtlAlloc(sizeof(PCRYPT_ATTRIBUTES)*dwDllIndex); if(!ppAuthAttr || !ppUnauthAttr) { hr=E_OUTOFMEMORY; goto CLEANUP; } memset(ppAuthAttr, 0,sizeof(PCRYPT_ATTRIBUTES)*dwDllIndex); memset(ppUnauthAttr, 0,sizeof(PCRYPT_ATTRIBUTES)*dwDllIndex); } //init the dll parameters, call the GetAttr entry points of the dlls if(dwDllIndex) { if(S_OK!=(hr=InitDllParameter(&AuthAttr, &UnauthAttr, ppAuthAttr, ppUnauthAttr))) goto CLEANUP; } //Perform the requested action one at a time if(dwAction & ACTION_SIGN) { idsAction=IDS_ACTION_SIGN; //set up the parameters for signing if(S_OK != (hr=SetUpParameter(&subjectInfo, &fileInfo, &signatureInfo, &attrAuthcode, &providerInfo, &certStoreInfo, &signerCert,&AuthAttr, &UnauthAttr, &hCertStore))) goto CLEANUP; hr=SignerSign(&subjectInfo, &signerCert, &signatureInfo, fStoreTechnology ? NULL : &providerInfo, NULL, NULL, NULL); if (hr != S_OK) { idsAction=IDS_ACTION_SIGN; goto CLEANUP; } #if (0) //DSIE: Bug 236022 //warn the user that the file is not timeStamped if (!(dwAction & ACTION_STAMP) && !(dwAction & ACTION_RESPONSE) && !(fTesting)) IDSwprintf(hModule,IDS_WARNING); #endif //free the certificate context if(certStoreInfo.pSigningCert) CertFreeCertificateContext(certStoreInfo.pSigningCert); //close the cert store which includes the signing certificate if(hCertStore) CertCloseStore(hCertStore, 0); } if(dwAction & ACTION_STAMP) { //timestamp the code dwMilliSeconds=dwWait*1000; //set up subject information if((dwAction & ACTION_SIGN) ==0) { if(S_OK!=(hr=SetUpSubjectInfo(&subjectInfo, &fileInfo))) goto CLEANUP; } //perform the # of trials for(dwIndex=0; dwIndex 1) { CertFreeCertificateContext(pDupCert); pDupCert=NULL; CertFreeCertificateContext(pSigningCert); pSigningCert=NULL; *pfMore=TRUE; hr=S_FALSE; goto CLEANUP; } pPreCert=pDupCert; pSigningCert=CertDuplicateCertificateContext(pDupCert); } if(pSigningCert==NULL) { hr=CRYPT_E_NO_DECRYPT_CERT; goto CLEANUP; } //get the hash if(!CertGetCertificateContextProperty(pSigningCert, CERT_SHA1_HASH_PROP_ID, NULL, pcbHash)) { hr=SignError(); goto CLEANUP; } *ppHash=(BYTE *)ToolUtlAlloc(*pcbHash); if(!(*ppHash)) { hr=E_OUTOFMEMORY; goto CLEANUP; } if(!CertGetCertificateContextProperty(pSigningCert, CERT_SHA1_HASH_PROP_ID, *ppHash, pcbHash)) { hr=SignError(); goto CLEANUP; } CLEANUP: if(pSigningCert) CertFreeCertificateContext(pSigningCert); if(hCertStore) CertCloseStore(hCertStore, 0); if(hr!=S_OK) { if(*ppHash) { ToolUtlFree(*ppHash); *ppHash=NULL; } } return hr; } //----------------------------------------------------------------------- // // Get the signing certificate // //-------------------------------------------------------------------------- PCCERT_CONTEXT GetSigningCert(HCERTSTORE *phCertStore, BOOL *pfMore) { PCCERT_CONTEXT pSigningCert=NULL; PCCERT_CONTEXT pPreCert=NULL; PCCERT_CONTEXT pDupCert=NULL; BYTE *pHash=NULL; DWORD cbHash; HCERTSTORE hCertStore=NULL; CRYPT_HASH_BLOB HashBlob; DWORD dwCount=0; //init the output if(!phCertStore || !pfMore) return NULL; *phCertStore=NULL; *pfMore=FALSE; //open a cert store hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, dwStoreEncodingType, NULL, dwStoreFlag |CERT_STORE_READONLY_FLAG, pwszStoreName); if(!hCertStore) return NULL; //get the hash of the certificate. Find the cert based on //pwszCertFile if(pwszCertFile) { if(S_OK != GetCertHashFromFile(pwszCertFile, &pHash, &cbHash, pfMore)) goto CLEANUP; HashBlob.cbData=cbHash; HashBlob.pbData=pHash; pSigningCert=CertFindCertificateInStore(hCertStore, dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &HashBlob, NULL); } else { //find the certificate with the common name if(pwszCommonName) { while(pDupCert=CertFindCertificateInStore(hCertStore, dwCertEncodingType, 0, CERT_FIND_SUBJECT_STR_W, pwszCommonName, pPreCert)) { dwCount++; if(dwCount > 1) { CertFreeCertificateContext(pDupCert); pDupCert=NULL; CertFreeCertificateContext(pSigningCert); pSigningCert=NULL; *pfMore=TRUE; goto CLEANUP; } pPreCert=pDupCert; pSigningCert=CertDuplicateCertificateContext(pDupCert); } } else { //find the certificate based on the hash if(g_pbHash) { HashBlob.cbData=g_cbHash; HashBlob.pbData=g_pbHash; pSigningCert=CertFindCertificateInStore(hCertStore, dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &HashBlob, NULL); } else { //no searching criteria, find the only cert in the store while(pDupCert=CertEnumCertificatesInStore(hCertStore, pPreCert)) { dwCount++; if(dwCount > 1) { CertFreeCertificateContext(pDupCert); pDupCert=NULL; CertFreeCertificateContext(pSigningCert); pSigningCert=NULL; *pfMore=TRUE; goto CLEANUP; } pPreCert=pDupCert; pSigningCert=CertDuplicateCertificateContext(pDupCert); } } } } CLEANUP: if(pHash) ToolUtlFree(pHash); if(pSigningCert) { *phCertStore=hCertStore; } else { //free the hCertStore CertCloseStore(hCertStore, 0); } return pSigningCert; } //----------------------------------------------------------------------- // // Set up the subject info // //-------------------------------------------------------------------------- HRESULT SetUpSubjectInfo(SIGNER_SUBJECT_INFO *pSubjectInfo, SIGNER_FILE_INFO *pFileInfo) { if(!pSubjectInfo || !pFileInfo) return E_INVALIDARG; //init memset(pSubjectInfo, 0, sizeof(SIGNER_SUBJECT_INFO)); memset(pFileInfo, 0, sizeof(SIGNER_FILE_INFO)); //init cbSize pSubjectInfo->cbSize=sizeof(SIGNER_SUBJECT_INFO); pFileInfo->cbSize=sizeof(SIGNER_FILE_INFO); //init pSubjectInfo pSubjectInfo->pdwIndex=&dwSignerIndex; pSubjectInfo->dwSubjectChoice=SIGNER_SUBJECT_FILE; pSubjectInfo->pSignerFileInfo=pFileInfo; pFileInfo->pwszFileName=pwszFile; return S_OK; } //----------------------------------------------------------------------- // // Set up the signing parameters // //-------------------------------------------------------------------------- HRESULT SetUpParameter(SIGNER_SUBJECT_INFO *pSubjectInfo, SIGNER_FILE_INFO *pFileInfo, SIGNER_SIGNATURE_INFO *pSignatureInfo, SIGNER_ATTR_AUTHCODE *pAttrAuthcode, SIGNER_PROVIDER_INFO *pProviderInfo, SIGNER_CERT_STORE_INFO *pCertStoreInfo, SIGNER_CERT *pSignerCert, CRYPT_ATTRIBUTES *pAuthenticated, CRYPT_ATTRIBUTES *pUnauthenticated, HCERTSTORE *phCertStore ) { HRESULT hr; PCCERT_CONTEXT pCertContext=NULL; BOOL fMore=FALSE; if(S_OK!=(hr=SetUpSubjectInfo(pSubjectInfo, pFileInfo))) return hr; if(!pSignatureInfo || !pAttrAuthcode || !pProviderInfo || !pCertStoreInfo || !pSignerCert) return E_INVALIDARG; //init memset(pSignatureInfo, 0, sizeof(SIGNER_SIGNATURE_INFO)); memset(pAttrAuthcode, 0, sizeof(SIGNER_ATTR_AUTHCODE)); memset(pProviderInfo, 0, sizeof(SIGNER_PROVIDER_INFO)); memset(pCertStoreInfo, 0, sizeof(SIGNER_CERT_STORE_INFO)); memset(pSignerCert, 0, sizeof(SIGNER_CERT)); //init cbSize pSignatureInfo->cbSize=sizeof(SIGNER_SIGNATURE_INFO); pAttrAuthcode->cbSize=sizeof(SIGNER_ATTR_AUTHCODE); pProviderInfo->cbSize=sizeof(SIGNER_PROVIDER_INFO); pCertStoreInfo->cbSize=sizeof(SIGNER_CERT_STORE_INFO); pSignerCert->cbSize=sizeof(SIGNER_CERT); //init pAttrAuthcode pAttrAuthcode->fCommercial=fCommercial; pAttrAuthcode->fIndividual=fIndividual; pAttrAuthcode->pwszName=pwszOpusName; pAttrAuthcode->pwszInfo=pwszOpusInfo; //init pSignatureInfo pSignatureInfo->algidHash=dwAlgorithmOid; pSignatureInfo->dwAttrChoice=SIGNER_AUTHCODE_ATTR; pSignatureInfo->pAttrAuthcode=pAttrAuthcode; pSignatureInfo->psAuthenticated=pAuthenticated; pSignatureInfo->psUnauthenticated=pUnauthenticated; //init pProviderInfo only if we are using non-cerStore tech if(fStoreTechnology!=TRUE) { pProviderInfo->pwszProviderName=pwszCapiProvider; pProviderInfo->dwProviderType=dwProviderType; pProviderInfo->dwKeySpec=dwKeySpec; if(pwszPvkFile) { pProviderInfo->dwPvkChoice=PVK_TYPE_FILE_NAME; pProviderInfo->pwszPvkFileName=pwszPvkFile; } else { pProviderInfo->dwPvkChoice=PVK_TYPE_KEYCONTAINER; pProviderInfo->pwszKeyContainer=pwszKeyContainer; } } //init pSignerCert if(fStoreTechnology) { //get the signing cert context pCertContext=GetSigningCert(phCertStore,&fMore ); if(!pCertContext) { if(fMore==FALSE) return CRYPT_E_NO_DECRYPT_CERT; else return CRYPT_E_DELETED_PREV; } pSignerCert->dwCertChoice=SIGNER_CERT_STORE; pSignerCert->pCertStoreInfo=pCertStoreInfo; //init pCertStoreInfo pCertStoreInfo->pSigningCert=pCertContext; pCertStoreInfo->dwCertPolicy=dwStorePolicy; } else { pSignerCert->dwCertChoice=SIGNER_CERT_SPC_FILE; pSignerCert->pwszSpcFile=pwszSpcFile; } return S_OK; } //----------------------------------------------------------------------- // //get the attributes from the dlls // //-------------------------------------------------------------------------- HRESULT InitDllParameter(PCRYPT_ATTRIBUTES pAuthAttr, PCRYPT_ATTRIBUTES pUnauthAttr, PCRYPT_ATTRIBUTES *ppAuthAttr, PCRYPT_ATTRIBUTES *ppUnauthAttr) { DWORD dwIndex=0; DWORD dwIndex2=0; DWORD dwAttrIndex=0; HRESULT hr=E_FAIL; HINSTANCE hAuthInst=NULL; LPSTR pszName=NULL; FARPROC pProc=NULL; PCRYPT_ATTRIBUTES pDllAuthAttr=NULL; PCRYPT_ATTRIBUTES pDllUnauthAttr=NULL; DWORD dwAuthAttrSum=0; DWORD dwUnauthAttrSum=0; if(dwDllIndex==0) return S_OK; if(!ppAuthAttr || !ppUnauthAttr ||!pAuthAttr || !pUnauthAttr) return E_INVALIDARG; //process each dll for(dwIndex=0; dwIndexcAttr) dwAuthAttrSum+=pDllAuthAttr->cAttr; ppAuthAttr[dwIndex]=pDllAuthAttr; //add the sume of unauthenticated if(pDllUnauthAttr->cAttr) dwUnauthAttrSum+=pDllUnauthAttr->cAttr; ppUnauthAttr[dwIndex]=pDllUnauthAttr; //exit if(!(pProc=GetProcAddress(hAuthInst, "ExitAttr"))) { hr=SignError(); goto CLEANUP; } if(S_OK!=(hr=((pExitAttr)pProc)())) goto CLEANUP; //free library FreeLibrary(hAuthInst); hAuthInst=NULL; //free memory ToolUtlFree(pszName); pszName=NULL; } //build up authenticated attribute if(dwAuthAttrSum) { pAuthAttr->cAttr=dwAuthAttrSum; pAuthAttr->rgAttr=(PCRYPT_ATTRIBUTE)ToolUtlAlloc(sizeof(CRYPT_ATTRIBUTE)* pAuthAttr->cAttr); if(!(pAuthAttr->rgAttr) ) { hr=E_OUTOFMEMORY; goto CLEANUP; } //build up autheticated attributes dwAttrIndex=0; for(dwIndex=0; dwIndexcAttr; dwIndex2++) { pAuthAttr->rgAttr[dwAttrIndex]= ppAuthAttr[dwIndex]->rgAttr[dwIndex2]; dwAttrIndex++; } } //make sure dwAttrIndex==pAuthAttr->cAttr if(dwAttrIndex!=pAuthAttr->cAttr) { hr=E_UNEXPECTED; goto CLEANUP; } } else { memset(pAuthAttr, 0, sizeof(CRYPT_ATTRIBUTES)); } //build up unauthenticated attribute if(dwUnauthAttrSum) { pUnauthAttr->cAttr=dwUnauthAttrSum; pUnauthAttr->rgAttr=(PCRYPT_ATTRIBUTE)ToolUtlAlloc(sizeof(CRYPT_ATTRIBUTE)* pUnauthAttr->cAttr); if(!(pUnauthAttr->rgAttr)) { hr=E_OUTOFMEMORY; goto CLEANUP; } //build up the unauthenticated attributes dwAttrIndex=0; for(dwIndex=0; dwIndexcAttr; dwIndex2++) { pUnauthAttr->rgAttr[dwAttrIndex]=ppUnauthAttr[dwIndex]->rgAttr[dwIndex2]; dwAttrIndex++; } } if(dwAttrIndex != pUnauthAttr->cAttr) { hr=E_UNEXPECTED; goto CLEANUP; } } else { memset(pUnauthAttr, 0, sizeof(CRYPT_ATTRIBUTES)); } hr=S_OK; CLEANUP: if(hAuthInst) FreeLibrary(hAuthInst); if(pszName) ToolUtlFree(pszName); //free up memory when hr!=S_OK if(hr!=S_OK) { if(pAuthAttr->rgAttr) { ToolUtlFree(pAuthAttr->rgAttr); pAuthAttr->rgAttr=NULL; } if(pUnauthAttr->rgAttr) { ToolUtlFree(pUnauthAttr->rgAttr); pUnauthAttr->rgAttr=NULL; } } return hr; } //----------------------------------------------------------------------- // // Release the attributes by calling the dlls's ReleaseAttr entry point // //-------------------------------------------------------------------------- void ReleaseDllParameter(PCRYPT_ATTRIBUTES * ppAuthAttr, PCRYPT_ATTRIBUTES * ppUnauthAttr) { DWORD dwIndex=0; HRESULT hr=E_FAIL; HINSTANCE hAuthInst=NULL; LPSTR pszName=NULL; FARPROC pProc=NULL; if((dwDllIndex==0) ||(!ppAuthAttr) || (!ppUnauthAttr)) return; //process each dll for(dwIndex=0; dwIndex