//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: mssip32.cpp // // Contents: Microsoft SIP Provider // // History: 14-Feb-1997 pberkman created // //-------------------------------------------------------------------------- #include "global.hxx" #include "sipobj.hxx" #include "sipobjpe.hxx" #include "sipobjjv.hxx" #include "sipobjcb.hxx" #include "sipobjfl.hxx" #include "sipobjct.hxx" #include "sipobjss.hxx" #include "crypthlp.h" #include "sha.h" #include "md5.h" #define MY_NAME L"WINTRUST.DLL" SIPObject_ *mssip_CreateSubjectObject(const GUID *chk); // // the entries in SubjectsGuid MUST be in the same // relative position and coalate with those in the // SubjectsID. // static const GUID SubjectsGuid[] = { CRYPT_SUBJTYPE_PE_IMAGE, CRYPT_SUBJTYPE_JAVACLASS_IMAGE, CRYPT_SUBJTYPE_CABINET_IMAGE, CRYPT_SUBJTYPE_FLAT_IMAGE, CRYPT_SUBJTYPE_CATALOG_IMAGE, CRYPT_SUBJTYPE_CTL_IMAGE }; // CRYPT_SUBJTYPE_SS_IMAGE static const UINT SubjectsID[] = { MSSIP_ID_PE, MSSIP_ID_JAVA, MSSIP_ID_CAB, MSSIP_ID_FLAT, MSSIP_ID_CATALOG, MSSIP_ID_CTL, MSSIP_ID_NONE // MUST be at the end! }; // MSSIP_ID_SS, BOOL WINAPI CryptSIPGetSignedDataMsg( IN SIP_SUBJECTINFO *pSubjectInfo, OUT DWORD *dwEncodingType, IN DWORD dwIndex, IN OUT DWORD *pdwDataLen, OUT BYTE *pbData) { DWORD dwLastError=0; if (!(pSubjectInfo) || !(pdwDataLen) || !(dwEncodingType)) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } SIPObject_ *pSubjectObj; if (!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwEncodingType))) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } pSubjectObj = mssip_CreateSubjectObject(pSubjectInfo->pgSubjectType); if (!(pSubjectObj)) { if (!(pbData)) { *pdwDataLen = 0; } return(FALSE); } pSubjectObj->set_CertVersion(pSubjectInfo->dwIntVersion); BOOL bRet; bRet = pSubjectObj->GetSignedDataMsg(pSubjectInfo, dwIndex,pdwDataLen,pbData,dwEncodingType); dwLastError=GetLastError(); delete pSubjectObj; SetLastError(dwLastError); return(bRet); } BOOL WINAPI CryptSIPPutSignedDataMsg( IN SIP_SUBJECTINFO *pSubjectInfo, IN DWORD dwEncodingType, OUT DWORD *pdwIndex, IN DWORD dwDataLen, IN BYTE *pbData) { if (!(pSubjectInfo) || (dwDataLen < 1) || !(pdwIndex) || !(pbData)) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } SIPObject_ *pSubjectObj; if (!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwEncodingType))) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } pSubjectObj = mssip_CreateSubjectObject(pSubjectInfo->pgSubjectType); if (!(pSubjectObj)) { return(FALSE); } pSubjectObj->set_CertVersion(pSubjectInfo->dwIntVersion); BOOL bRet; bRet = pSubjectObj->PutSignedDataMsg(pSubjectInfo, pdwIndex,dwDataLen,pbData,dwEncodingType); delete pSubjectObj; return(bRet); } BOOL WINAPI CryptSIPRemoveSignedDataMsg( IN SIP_SUBJECTINFO *pSubjectInfo, IN DWORD dwIndex) { if (!(pSubjectInfo)) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } SIPObject_ *pSubjectObj; if (!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwEncodingType))) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } pSubjectObj = mssip_CreateSubjectObject(pSubjectInfo->pgSubjectType); if (!(pSubjectObj)) { return(FALSE); } pSubjectObj->set_CertVersion(pSubjectInfo->dwIntVersion); BOOL bRet; bRet = pSubjectObj->RemoveSignedDataMsg(pSubjectInfo,dwIndex); delete pSubjectObj; return(bRet); } BOOL WINAPI CryptSIPCreateIndirectData( IN SIP_SUBJECTINFO *pSubjectInfo, IN OUT DWORD *pdwDataLen, OUT SIP_INDIRECT_DATA *psData) { if (!(pSubjectInfo) || !(pdwDataLen)) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } SIPObject_ *pSubjectObj; if (!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwEncodingType))) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } pSubjectObj = mssip_CreateSubjectObject(pSubjectInfo->pgSubjectType); if (!(pSubjectObj)) { if (!(psData)) { *pdwDataLen = 0; } return(FALSE); } // // ALWAYS set the latest version when we are creating the // indirect data content! // pSubjectInfo->dwIntVersion = WIN_CERT_REVISION_2_0; pSubjectObj->set_CertVersion(pSubjectInfo->dwIntVersion); BOOL bRet; bRet = pSubjectObj->CreateIndirectData(pSubjectInfo,pdwDataLen,psData); delete pSubjectObj; return(bRet); } BOOL WINAPI CryptSIPVerifyIndirectData( IN SIP_SUBJECTINFO *pSubjectInfo, IN SIP_INDIRECT_DATA *psData) { if (!(pSubjectInfo)) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } SIPObject_ *pSubjectObj; if (!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwEncodingType))) { SetLastError((DWORD)ERROR_INVALID_PARAMETER); return(FALSE); } pSubjectObj = mssip_CreateSubjectObject(pSubjectInfo->pgSubjectType); if (!(pSubjectObj)) { return(FALSE); } // // if we are a catalog member, set the version number to whatever // was set when the catalog file was created... // if ((WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(SIP_SUBJECTINFO, pSubjectInfo->cbSize, dwUnionChoice)) && (pSubjectInfo->dwUnionChoice == MSSIP_ADDINFO_CATMEMBER) && (pSubjectInfo->psCatMember)) { if (pSubjectInfo->psCatMember->cbStruct == sizeof(MS_ADDINFO_CATALOGMEMBER)) { if ((pSubjectInfo->psCatMember->pMember) && (pSubjectInfo->psCatMember->pMember->cbStruct == sizeof(CRYPTCATMEMBER))) { pSubjectInfo->dwIntVersion = pSubjectInfo->psCatMember->pMember->dwCertVersion; } } } pSubjectObj->set_CertVersion(pSubjectInfo->dwIntVersion); if (pSubjectObj->get_CertVersion() < WIN_CERT_REVISION_2_0) { DWORD dwCAPIFlags; CryptSIPGetRegWorkingFlags(&dwCAPIFlags); if (dwCAPIFlags & WTPF_VERIFY_V1_OFF) { delete pSubjectObj; SetLastError((DWORD)CRYPT_E_SECURITY_SETTINGS); return(FALSE); } } BOOL bRet; bRet = pSubjectObj->VerifyIndirectData(pSubjectInfo, psData); delete pSubjectObj; return(bRet); } ////////////////////////////////////////////////////////////////////////////////////// // // internal utility functions //------------------------------------------------------------------------------------ // SIPObject_ *mssip_CreateSubjectObject(const GUID *chk) { UINT idx; SIPObject_ *pSO; pSO = NULL; idx = 0; while (SubjectsID[idx] != MSSIP_ID_NONE) { if (SubjectsGuid[idx] == *chk) { switch (SubjectsID[idx]) { case MSSIP_ID_PE: pSO = (SIPObject_ *)new SIPObjectPE_(SubjectsID[idx]); break; case MSSIP_ID_JAVA: pSO = (SIPObject_ *)new SIPObjectJAVA_(SubjectsID[idx]); break; case MSSIP_ID_CAB: pSO = (SIPObject_ *)new SIPObjectCAB_(SubjectsID[idx]); break; case MSSIP_ID_FLAT: pSO = (SIPObject_ *)new SIPObjectFlat_(SubjectsID[idx]); break; case MSSIP_ID_CTL: // currently, the same logic as catalog files! case MSSIP_ID_CATALOG: pSO = (SIPObject_ *)new SIPObjectCatalog_(SubjectsID[idx]); break; /* case MSSIP_ID_SS: pSO = (SIPObject_ *)new SIPObjectSS_(SubjectsID[idx]); break; */ case MSSIP_V1ID_PE: case MSSIP_V1ID_PE_EX: default: SetLastError((DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN); return(NULL); } if (!(pSO)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(NULL); } break; } idx++; } if (!(pSO)) { SetLastError((DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN); } return(pSO); } BOOL WINAPI DigestFileData( IN HSPCDIGESTDATA hDigestData, IN const BYTE *pbData, IN DWORD cbData) { BOOL fRet; PDIGEST_DATA pDigestData; fRet = TRUE; pDigestData = (PDIGEST_DATA)hDigestData; if (cbData > HASH_CACHE_LEN) { if (pDigestData->cbCache > 0) { fRet = SipHashData(pDigestData, pDigestData->pbCache, pDigestData->cbCache); pDigestData->cbCache = 0; if (!(fRet)) { return(FALSE); } } fRet = SipHashData(pDigestData, (BYTE *)pbData, cbData); } else { while (cbData > 0) { DWORD cbCopy; cbCopy = min(HASH_CACHE_LEN - pDigestData->cbCache, cbData); memcpy(&pDigestData->pbCache[pDigestData->cbCache], pbData, cbCopy); cbData -= cbCopy; pbData += cbCopy; pDigestData->cbCache += cbCopy; if (pDigestData->cbCache == HASH_CACHE_LEN) { pDigestData->cbCache = 0; if (!(fRet = SipHashData(pDigestData, pDigestData->pbCache, HASH_CACHE_LEN))) { break; } } } } return(fRet); } BOOL SipCreateHash(HCRYPTPROV hProv, DIGEST_DATA *psDigestData) { BOOL fRet; fRet = TRUE; switch (psDigestData->dwAlgId) { case CALG_MD5: MD5Init((MD5_CTX *)psDigestData->pvSHA1orMD5Ctx); break; case CALG_SHA1: A_SHAInit((A_SHA_CTX *)psDigestData->pvSHA1orMD5Ctx); break; default: if (!(hProv)) { hProv = I_CryptGetDefaultCryptProv(0); // get the default and DONT RELEASE IT!!!! } fRet = CryptCreateHash(hProv, psDigestData->dwAlgId, NULL, 0, &psDigestData->hHash); break; } return(fRet); } BOOL SipHashData(DIGEST_DATA *psDigestData, BYTE *pbData, DWORD cbData) { switch (psDigestData->dwAlgId) { case CALG_MD5: MD5Update((MD5_CTX *)psDigestData->pvSHA1orMD5Ctx, pbData, cbData); return(TRUE); case CALG_SHA1: A_SHAUpdate((A_SHA_CTX *)psDigestData->pvSHA1orMD5Ctx, pbData, cbData); return(TRUE); } return(CryptHashData(psDigestData->hHash, pbData, cbData, 0)); } BYTE *SipGetHashValue(DIGEST_DATA *psDigestData, DWORD *pcbHash) { BYTE *pbRet; pbRet = NULL; switch (psDigestData->dwAlgId) { case CALG_MD5: *pcbHash = MD5DIGESTLEN; break; case CALG_SHA1: *pcbHash = A_SHA_DIGEST_LEN; break; default: *pcbHash = 0; CryptGetHashParam(psDigestData->hHash, HP_HASHVAL, NULL, pcbHash,0); } if (*pcbHash < 1) { goto HashLengthError; } if (!(pbRet = new BYTE[*pcbHash])) { goto MemoryError; } switch (psDigestData->dwAlgId) { case CALG_MD5: MD5_CTX *pMD5; pMD5 = (MD5_CTX *)psDigestData->pvSHA1orMD5Ctx; MD5Final(pMD5); memcpy(pbRet, pMD5->digest, MD5DIGESTLEN); psDigestData->pvSHA1orMD5Ctx = NULL; break; case CALG_SHA1: A_SHAFinal((A_SHA_CTX *)psDigestData->pvSHA1orMD5Ctx, pbRet); psDigestData->pvSHA1orMD5Ctx = NULL; break; default: if (CryptGetHashParam(psDigestData->hHash, HP_HASHVAL, pbRet, pcbHash, 0)) { goto HashParamError; } break; } CommonReturn: return(pbRet); ErrorReturn: DELETE_OBJECT(pbRet); goto CommonReturn; SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY); SET_ERROR_VAR_EX(DBG_SS, HashLengthError, GetLastError()); SET_ERROR_VAR_EX(DBG_SS, HashParamError, GetLastError()); } void SipDestroyHash(DIGEST_DATA *psDigestData) { switch (psDigestData->dwAlgId) { case CALG_MD5: if (psDigestData->pvSHA1orMD5Ctx) { MD5Final((MD5_CTX *)psDigestData->pvSHA1orMD5Ctx); } break; case CALG_SHA1: if (psDigestData->pvSHA1orMD5Ctx) { BYTE bRet[A_SHA_DIGEST_LEN]; A_SHAFinal((A_SHA_CTX *)psDigestData->pvSHA1orMD5Ctx, &bRet[0]); } break; default: CryptDestroyHash(psDigestData->hHash); break; } } ////////////////////////////////////////////////////////////////////////////////////// // // standard DLL exports ... //------------------------------------------------------------------------------------ // BOOL WINAPI mssip32DllMain(HANDLE hInstDLL,DWORD fdwReason,LPVOID lpvReserved) { return(TRUE); } STDAPI mssip32DllRegisterServer(void) { BOOL fRet; GUID gFlat = CRYPT_SUBJTYPE_FLAT_IMAGE; GUID gPe = CRYPT_SUBJTYPE_PE_IMAGE; GUID gCb = CRYPT_SUBJTYPE_CABINET_IMAGE; GUID gJv = CRYPT_SUBJTYPE_JAVACLASS_IMAGE; GUID gCat = CRYPT_SUBJTYPE_CATALOG_IMAGE; GUID gCTL = CRYPT_SUBJTYPE_CTL_IMAGE; GUID gSS = CRYPT_SUBJTYPE_SS_IMAGE; SIP_ADD_NEWPROVIDER sProv; fRet = TRUE; memset(&sProv, 0x00, sizeof(SIP_ADD_NEWPROVIDER)); sProv.cbStruct = sizeof(SIP_ADD_NEWPROVIDER); sProv.pwszDLLFileName = MY_NAME; sProv.pwszGetFuncName = L"CryptSIPGetSignedDataMsg"; sProv.pwszPutFuncName = L"CryptSIPPutSignedDataMsg"; sProv.pwszCreateFuncName = L"CryptSIPCreateIndirectData"; sProv.pwszVerifyFuncName = L"CryptSIPVerifyIndirectData"; sProv.pwszRemoveFuncName = L"CryptSIPRemoveSignedDataMsg"; sProv.pgSubject = &gFlat; fRet &= CryptSIPAddProvider(&sProv); sProv.pgSubject = &gCb; sProv.pwszMagicNumber = L"MSCF"; fRet &= CryptSIPAddProvider(&sProv); sProv.pgSubject = &gPe; sProv.pwszMagicNumber = L"0x00004550"; fRet &= CryptSIPAddProvider(&sProv); sProv.pgSubject = &gJv; sProv.pwszMagicNumber = L"0xcafebabe"; fRet &= CryptSIPAddProvider(&sProv); sProv.pgSubject = &gCat; fRet &= CryptSIPAddProvider(&sProv); sProv.pgSubject = &gCTL; fRet &= CryptSIPAddProvider(&sProv); // // structured storage is last becuase it // has an "is" function... // /* sProv.pgSubject = &gSS; sProv.pwszIsFunctionNameFmt2 = L"IsStructuredStorageFile"; fRet &= CryptSIPAddProvider(&sProv); */ CryptSIPRemoveProvider(&gSS); return(fRet ? S_OK : S_FALSE); } STDAPI mssip32DllUnregisterServer(void) { GUID gFlat = CRYPT_SUBJTYPE_FLAT_IMAGE; GUID gPe = CRYPT_SUBJTYPE_PE_IMAGE; GUID gCb = CRYPT_SUBJTYPE_CABINET_IMAGE; GUID gJv = CRYPT_SUBJTYPE_JAVACLASS_IMAGE; GUID gCat = CRYPT_SUBJTYPE_CATALOG_IMAGE; GUID gCTL = CRYPT_SUBJTYPE_CTL_IMAGE; GUID gSS = CRYPT_SUBJTYPE_SS_IMAGE; CryptSIPRemoveProvider(&gFlat); CryptSIPRemoveProvider(&gPe); CryptSIPRemoveProvider(&gCb); CryptSIPRemoveProvider(&gJv); CryptSIPRemoveProvider(&gCat); CryptSIPRemoveProvider(&gCTL); CryptSIPRemoveProvider(&gSS); return(S_OK); } void CryptSIPGetRegWorkingFlags(DWORD *pdwState) { WintrustGetRegPolicyFlags(pdwState); } // // support for Auth2 release // typedef struct _SIP_INFORMATION { DWORD cbSize; // sizeof(SIP_INFORMATION) DWORD cgSubjects; // number of guids in array const GUID *pgSubjects; // array of supported guids/subjects } SIP_INFORMATION, *PSIP_INFORMATION; BOOL CryptSIPGetInfo(IN OUT SIP_INFORMATION *pSIPInit) { UINT i; i = 0; pSIPInit->cbSize = sizeof(SIP_INFORMATION); while (SubjectsID[i] != MSSIP_ID_NONE) { i++; } pSIPInit->cgSubjects = i; pSIPInit->pgSubjects = &SubjectsGuid[0]; return(TRUE); }