📄 crtsis.cpp
字号:
//append hash cipher text to end of the file //if RSA, we need to add the RSA'd SHA-1 signature if (pKey->KeyType() == ERSAPrivateKey) { memcpy(&pFileBuf[TargetLen], ciphertext, KeyLen); } //If DSA, we need to add the DSA'd SHA-1 signature if (pKey->KeyType() == EDSAPrivateKey) { memcpy(&pFileBuf[TargetLen], hash, KeyLen); delete pHash; } //write new SIS file to disk (hash is now appended) HANDLE hOutFile = ::MakeSISOpenFile(pszTargetFile, GENERIC_WRITE, OPEN_EXISTING); if(hOutFile == INVALID_HANDLE_VALUE) throw ErrCannotOpenFile; if(!::WriteFile(hOutFile, (LPVOID)pFileBuf, TargetLen + KeyLen, &dwNumBytes, NULL)) throw ErrCannotWriteFile; ::CloseHandle(hOutFile); delete [] pFileBuf; delete pKey; }#endif }// Load the private key from the fileCPrivateKey* CSISFileGeneratorBase::LoadPrivateKey() { CPrivateKey* result = NULL;#ifdef DIGITAL_SIGNATURES const SIGNATURENODE* pSignature = m_pSISWriter->GetSignatureBase(); if (pSignature) { // convert private key file name into MBCS for Encrypt() method DWORD length=wcslen(pSignature->pszPrivateKey); LPSTR fName=MakeMBCSString(pSignature->pszPrivateKey, CP_ACP, length); // convert password into MBCS for Encrypt() method WCHAR pszCmdPassword[MAX_PATH]; // Command Line Decryption Password LPSTR pszPassword = ""; //test for command line Decryption Password if (m_pSISWriter->GetCmdPassword(pszCmdPassword)) { length=wcslen(pszCmdPassword); pszPassword=MakeMBCSString(pszCmdPassword, CP_ACP, length); /* #ifdef _DEBUG printf("***DEBUG CODE*** Password is %s\n", pszPassword); #endif */ } else { length=wcslen(pSignature->pszPassword); pszPassword=MakeMBCSString(pSignature->pszPassword, CP_ACP, length); } CPrivateKey* pKey = new CPrivateKey; if (!pKey) throw ErrNotEnoughMemory; pKey->LoadKey(fName, pszPassword); delete [] pszPassword; delete [] fName; if (pKey->Loaded() == FALSE) { throw ErrCannotOpenFile; } else { result = pKey; } }#endif return result; }void CSISFileGeneratorBase::Crc(const void *pPtr, DWORD dwLength)// Purpose : Creates the CRC checksum // Inputs : pPtr - Pointer to a block of memory // wLength - The length of the memory block { const unsigned char *pB = (const unsigned char *)pPtr; const unsigned char *pE = pB + dwLength; WORD crc = m_wCheck; while (pB < pE) crc = (WORD)((crc << 8) ^ crcTab[((crc >> 8) ^ *pB++) & 0xff]); m_wCheck = crc; }void CSISFileGeneratorBase::UIDCheck(const void *pPtr)// Purpose : To create a UID checksum // Inputs : pPtr - Pointer to a block of memory { const unsigned char *pB = (const unsigned char *)pPtr; const unsigned char *pE = pB + (KUidInstallNumUid * sizeof(DWORD)); unsigned char buf[(KUidInstallNumUid * sizeof(DWORD))>>1]; unsigned char *pT = (&buf[0]); while (pB < pE) { *pT++ = (*pB); pB += 2; } m_wCheck = 0; Crc(&buf[0], (KUidInstallNumUid * sizeof(DWORD))>>1); }void CSISFileGeneratorBase::EstimateInstallationSizeL() { int nodes, i; const PKGLINENODE *pNode = m_pSISWriter->GetPkgLineBase(); // This method makes an estimate of the amount of space required by an installation. // It sums the uncompressed size of all files that are to be installed on an epoc device. // If statements are a special case. Only the largest file installed by any given branch of // an if statement will be added to the total install size. Consequently the space required will // overestimated for package files with if statements. // Since nodes are added to the front of the list, the last package line appears at the // front of the list. Its easier to compute the maximum amount of space required by an // if statement if we can access the nodes in the order in which they appear in the // .pkg file. Hence, an array is created with pointers to these nodes. for (nodes = 0; pNode != NULL; pNode = pNode->pNext) nodes++; const PKGLINENODE **pNodePointers = new const PKGLINENODE*[nodes]; pNode = m_pSISWriter->GetPkgLineBase(); for (i = nodes-1; i >= 0; i--) { pNodePointers[i] = pNode; pNode = pNode->pNext; } try { m_dwMaximumSpaceNeeded = 0; i = 0; while (i < nodes) { if (pNodePointers[i]->iPackageLineType == EInstPkgLineCondIf) m_dwMaximumSpaceNeeded += CalculateInstallSizeOfIfBlockL(pNodePointers, i); else { m_dwMaximumSpaceNeeded += CalculateInstallSizeOfFileL(pNodePointers[i]); i++; } } } catch (...) { delete[] pNodePointers; throw; } delete[] pNodePointers; }int CSISFileGeneratorBase::CalculateInstallSizeOfIfBlockL(const PKGLINENODE **pNode, int &index) const { int spaceNeeded = 0; int needsOfBlock; bool processingIf = true; index++; while (processingIf) { needsOfBlock = 0; while (pNode[index]->iPackageLineType != EInstPkgLineCondElseIf && pNode[index]->iPackageLineType != EInstPkgLineCondElse && pNode[index]->iPackageLineType != EInstPkgLineCondEndIf) { if (pNode[index]->iPackageLineType == EInstPkgLineCondIf) needsOfBlock += CalculateInstallSizeOfIfBlockL(pNode,index); else { needsOfBlock += CalculateInstallSizeOfFileL(pNode[index]); index++; } } if (needsOfBlock > spaceNeeded) spaceNeeded = needsOfBlock; processingIf = (pNode[index]->iPackageLineType != EInstPkgLineCondEndIf); index++; } return spaceNeeded; }int CSISFileGeneratorBase::CalculateInstallSizeOfFileL(const PKGLINENODE *pNode) const { int spaceNeeded = 0; if ((pNode->iPackageLineType == EInstPkgLineFile || pNode->iPackageLineType == EInstPkgLineLanguageFile) && (pNode->file->type != EInstFileTypeText && pNode->file->type != EInstFileTypeNull && pNode->file->type != EInstFileTypeMime)) { if (pNode->file->type == EInstFileTypeComponent) { HANDLE hFile = ::MakeSISOpenFile(pNode->file->pszSource,GENERIC_READ, OPEN_EXISTING); if (hFile==INVALID_HANDLE_VALUE) throw ErrCannotOpenFile; TInstInstallation header; DWORD dwBytesRead; if (!::ReadFile(hFile,(LPVOID) &header,sizeof(TInstInstallation),&dwBytesRead,NULL)) throw ErrCannotReadFile; ::CloseHandle(hFile); spaceNeeded = header.iMaximumSpaceNeeded; } else if (pNode->file->type != EInstFileTypeText) spaceNeeded = pNode->file->dwSize; } return spaceNeeded; }void CSISFileGeneratorBase::CompressFiles()// Purpose : To compress files embedded within the sis file. { int compressedSize = 0; Verbage(_T("Compressing files")); const PKGLINENODE *pNode = m_pSISWriter->GetPkgLineBase(); while(pNode) { if ((pNode->iPackageLineType == EInstPkgLineFile || pNode->iPackageLineType == EInstPkgLineLanguageFile) && pNode->file->type != EInstFileTypeNull) { pNode->file->dwUncompressedSize = pNode->file->dwSize; if (((m_pSISWriter->GetFlags() & EInstNoCompress) == 0)) { LPWSTR pszCompressedFileName = TempFileName(pNode->file->pszSource); CompressFile(pNode,pszCompressedFileName,compressedSize); // update the source filename and the file size in the PKGLINEFILE node. wcscpy(pNode->file->pszSource, pszCompressedFileName); pNode->file->dwSize = compressedSize; } } pNode = pNode->pNext; } }void CSISFileGeneratorBase::CompressFile(const PKGLINENODE *pNode, LPWSTR pszOutputFname, int &compressedSize)// Purpose: Compresses the file pointed into a temporary file.// Inputs: pNode: a pointer to a PKGLINENODE which contains information about the source file// pszOutputFname: the name of the compressed file to be created.// Outputs: compressedSize: The size of the compressed File. { HANDLE hUncompressedFile, hCompressedFile; DWORD dwUncompressedFileSize; const int bufferSize = 0xffff; int zlibErr; BOOL zlibInit = FALSE; hUncompressedFile = ::MakeSISOpenFile(pNode->file->pszSource, GENERIC_READ, OPEN_EXISTING); if(hUncompressedFile == INVALID_HANDLE_VALUE) throw ErrCannotOpenFile; dwUncompressedFileSize = ::GetFileSize(hUncompressedFile, NULL); hCompressedFile = ::MakeSISOpenFile(pszOutputFname, GENERIC_WRITE|GENERIC_READ, CREATE_NEW); if (hCompressedFile==INVALID_HANDLE_VALUE) throw ErrCannotOpenFile; BYTE *pbInputBuffer = new BYTE [bufferSize]; BYTE *pbOutputBuffer = new BYTE [bufferSize]; z_stream compressionState; try { if (!pbOutputBuffer || !pbInputBuffer) throw ErrNotEnoughMemory; compressionState.zalloc = NULL; compressionState.zfree = NULL; compressionState.opaque = NULL; compressionState.next_out = pbOutputBuffer; compressionState.avail_out = bufferSize; ReadFromUncompressedFile(hUncompressedFile,pbInputBuffer,compressionState,bufferSize); zlibInit = TRUE; zlibErr = deflateInit(&compressionState,Z_DEFAULT_COMPRESSION); if (zlibErr != Z_OK) throw ErrFailedCompression; while ((zlibErr = deflate(&compressionState,Z_NO_FLUSH)) == Z_OK) { if (compressionState.avail_in == 0) ReadFromUncompressedFile(hUncompressedFile,pbInputBuffer,compressionState,bufferSize); if (compressionState.avail_out == 0) WriteToCompressedFile(hCompressedFile, pbOutputBuffer,compressionState, bufferSize); } while ((zlibErr = deflate(&compressionState,Z_FINISH)) == Z_OK) { if (compressionState.avail_in == 0) ReadFromUncompressedFile(hUncompressedFile,pbInputBuffer,compressionState,bufferSize); if (compressionState.avail_out == 0) WriteToCompressedFile(hCompressedFile, pbOutputBuffer,compressionState, bufferSize); } if (zlibErr != Z_STREAM_END) throw ErrFailedCompression; WriteToCompressedFile(hCompressedFile, pbOutputBuffer,compressionState, bufferSize); } catch(...) { delete[] pbInputBuffer; delete[] pbOutputBuffer; ::CloseHandle(hUncompressedFile); ::CloseHandle(hCompressedFile); _wunlink(pszOutputFname); // delete compressed file if (zlibInit) deflateEnd(&compressionState); throw; } delete[] pbInputBuffer; delete[] pbOutputBuffer; ::CloseHandle(hUncompressedFile); ::CloseHandle(hCompressedFile); compressedSize = compressionState.total_out; deflateEnd(&compressionState); }void CSISFileGeneratorBase::ReadFromUncompressedFile(HANDLE hFile,BYTE *pbBuffer,z_stream &compressionState, int bufferSize) { DWORD dwNumBytes; if (::ReadFile(hFile, (LPVOID)pbBuffer, bufferSize, &dwNumBytes, NULL)) { compressionState.next_in = pbBuffer; compressionState.avail_in = dwNumBytes; } else throw ErrCannotReadFile; }void CSISFileGeneratorBase::WriteToCompressedFile(HANDLE hFile,BYTE *pbBuffer,z_stream &compressionState, int bufferSize) { DWORD dwNumBytes; if (::WriteFile(hFile, (LPVOID)pbBuffer, bufferSize - compressionState.avail_out, &dwNumBytes, NULL)) { compressionState.next_out = pbBuffer; compressionState.avail_out = dwNumBytes; } else throw ErrCannotWriteFile; }// ===========================================================================// CSISFileGeneratorT<>// Template class, handles the character size specific SIS file generation// ===========================================================================template<class T>void CSISFileGeneratorT<T>::WriteString(LPCWSTR pStr, HANDLE hFile)// Purpose : Write a string to the file// Inputs : pStr - The string to write (comes from CSISWritre so is always UNICODE!)// hFile - The target file { // Copy the string into the output format... long len = wcslen(pStr); T* buf = new T[len + 1]; if (!buf) throw ErrNotEnoughMemory; for(int i = 0; i < len; ++i) buf[i] = (T)pStr[i]; // And write it to the file DWORD dwNumBytes; if(!::WriteFile(hFile, (LPVOID)buf, len * sizeof(T), &dwNumBytes, NULL)) throw ErrFailedToWriteStringsBlock; // CRC Crc((void *)buf, len * sizeof(T)); delete [] buf; }template<class T>void CSISFileGeneratorT<T>::WriteString8(LPCWSTR pStr, HANDLE hFile)// Purpose : Write an 8bit string to the file// Inputs : pStr - The string to write// hFile - The target file { // Copy the string into the output format... long len = wcslen(pStr); char* buf = new char[len + 1]; if (!buf) throw ErrNotEnoughMemory; for(int i = 0; i < len; ++i) buf[i] = (char)pStr[i]; // And write it to the file DWORD dwNumBytes; if(!::WriteFile(hFile, (LPVOID)buf, len, &dwNumBytes, NULL)) throw ErrFailedToWriteStringsBlock; // CRC Crc((void *)buf, len); delete [] buf; }void CSISFileGeneratorBase::ParseCertificates() { // Test for PKCS7 chain and re-write as concatenated certificates#ifdef DIGITAL_SIGNATURES //get digital sig info const SIGNATURENODE* pSignature = m_pSISWriter->GetSignatureBase(); if (pSignature) { int status; m_bWriteChain = FALSE; //get a temporary filename for re-writing a PCKS chain LPWSTR pszTempCert; pszTempCert = TempFileName(pSignature->pszPublicKey); // convert tempfile name for Convert Signed method DWORD lent=wcslen(pszTempCert); LPSTR fNameTmp=MakeMBCSString(pszTempCert, CP_ACP, lent); // convert temporary Certificate file name for Convert Signed method DWORD lench=wcslen(pSignature->pszChainFile); LPSTR fNameChain=MakeMBCSString(pSignature->pszChainFile, CP_ACP, lench); // convert certificate name for Convert Signed method DWORD lenc=wcslen(pSignature->pszPublicKey); LPSTR fNameCrt=MakeMBCSString(pSignature->pszPublicKey, CP_ACP, lenc); // convert b64 name DWORD lencb64=wcslen(pSignature->pszB64File); LPSTR fNameB64=MakeMBCSString(pSignature->pszB64File, CP_ACP, lencb64); //create our PKCS7 aware object CPKCS7* pPKCS7 = new CPKCS7; if (!pPKCS7) throw ErrNotEnoughMemory; status = pPKCS7->ConvertSigned(fNameCrt, fNameTmp); //status = pPKCS7->ConvertBase64(fNameCrt, fNameTmp); // If not a single cert, specify that the end entity cert comes first. // Identify ee cert by private key CPrivateKey* pKey = LoadPrivateKey(); pPKCS7->SetEndEntityKey(pKey); int keyMatchesCert = 1; if (status == PKCS7FileReWritten) { int extractStatus = pPKCS7->ExtractChain(fNameTmp, fNameChain, &(unsigned short)pSignature->iNumCerts); m_bWriteChain = TRUE; if (extractStatus == ErrEndEntityNotFound) keyMatchesCert = 0; } else if (status != PKCS7FileIsCertificate) { int extractStatus = pPKCS7->ExtractChain(fNameCrt, fNameChain, &(unsigned short)pSignature->iNumCerts); m_bWriteChain = TRUE; if (extractStatus == ErrEndEntityNotFound) keyMatchesCert = 0; } else { // File is a single cert - check it matches the key keyMatchesCert = pKey->MatchesCert(fNameCrt); } if (!keyMatchesCert) throw ErrCertFileKeyFileMismatch; delete pKey; delete pPKCS7; //create a Base64 convertor object CB64Decrypt* pB64 = new CB64Decrypt; if (!pB64) throw ErrNotEnoughMemory; if (m_bWriteChain) { pB64->Do(fNameChain, fNameB64, NULL); } else { pB64->Do(fNameCrt, fNameB64, NULL); } delete pB64; delete [] fNameTmp; delete [] fNameChain; delete [] fNameCrt; }#endif }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -