1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
18 // This program serves as both
19 // - An example BOINC application, illustrating the use of the BOINC API
20 // - A program for testing various features of BOINC
22 // NOTE: this file exists as both
23 // boinc/apps/upper_case.C
25 // boinc_samples/example_app/uc2.C
26 // If you update one, please update the other!
28 // The program converts a mixed-case file to upper case:
29 // read "in", convert to upper case, write to "out"
31 // command line options
32 // -run_slow: sleep 1 second after each character
33 // -cpu_time N: use about N CPU seconds after copying files
34 // -early_exit: exit(10) after 30 chars
35 // -early_crash: crash after 30 chars
39 #include "boinc_win.h"
57 #include "boinc_api.h"
60 #include "ChainWalkContext.h"
61 //typedef unsigned int uint32;
62 //typedef unsigned __int64 uint64;
64 #include "rcuda_ext.h"
70 bool early_exit = false;
71 bool early_crash = false;
72 bool early_sleep = false;
73 double cpu_time = 20, comp_result;
76 int QuickSortPartition(RainbowChainCP* pChain, int nLow, int nHigh)
78 int nRandomIndex = nLow + ((uint32)rand() * ((uint32)RAND_MAX + 1) + (uint32)rand()) % (nHigh - nLow + 1);
79 RainbowChainCP TempChain;
80 TempChain = pChain[nLow];
81 pChain[nLow] = pChain[nRandomIndex];
82 pChain[nRandomIndex] = TempChain;
84 TempChain = pChain[nLow];
85 uint64 nPivotKey = pChain[nLow].nIndexE;
88 while (nLow < nHigh && pChain[nHigh].nIndexE >= nPivotKey)
90 pChain[nLow] = pChain[nHigh];
91 while (nLow < nHigh && pChain[nLow].nIndexE <= nPivotKey)
93 pChain[nHigh] = pChain[nLow];
95 pChain[nLow] = TempChain;
99 void QuickSort(RainbowChainCP* pChain, int nLow, int nHigh)
103 int nPivotLoc = QuickSortPartition(pChain, nLow, nHigh);
104 QuickSort(pChain, nLow, nPivotLoc - 1);
105 QuickSort(pChain, nPivotLoc + 1, nHigh);
109 int main(int argc, char **argv) {
112 char output_path[512], chkpt_path[512];
114 retval = boinc_init();
116 fprintf(stderr, "boinc_init returned %d\n", retval);
120 // extract a --device option
121 std::vector<char*> argVec;
123 for(int ii = 0; ii < argc; ii++) {
124 if(cudaDevice < 0 && strcmp(argv[ii], "--device") == 0 && ii + 1 < argc)
125 cudaDevice = atoi(argv[++ii]);
127 argVec.push_back(argv[ii]);
129 argc = (int)argVec.size();
131 if(!(cudaDevice < 0))
132 // set the cuda device
133 if(rcuda::SetCudaDevice(cudaDevice) != 0)
135 //XXX this call doesn't work on linux
136 // fixed in upstream source 2010-09-16
137 // http://bolt.berkeley.edu/trac/changeset/22382
139 boinc_temporary_exit(60);
145 fprintf(stderr, "Not enough parameters");
148 string sHashRoutineName, sCharsetName, sSalt, sCheckPoints;
149 uint32 nRainbowChainCount, nPlainLenMin, nPlainLenMax, nRainbowTableIndex, nRainbowChainLen;
151 sHashRoutineName = argv[1];
152 sCharsetName = argv[2];
153 nPlainLenMin = atoi(argv[3]);
154 nPlainLenMax = atoi(argv[4]);
155 nRainbowTableIndex = atoi(argv[5]);
156 nRainbowChainLen = atoi(argv[6]);
157 nRainbowChainCount = atoi(argv[7]);
160 nChainStart = _atoi64(argv[8]);
163 nChainStart = atoll(argv[8]);
165 sCheckPoints = argv[9];
166 vector<int> vCPPositions;
167 char *cp = strtok((char *)sCheckPoints.c_str(), ",");
170 vCPPositions.push_back(atoi(cp));
171 cp = strtok(NULL, ",");
177 //std::cout << "Starting ChainGenerator" << std::endl;
178 // Setup CChainWalkContext
179 //std::cout << "ChainGenerator started." << std::endl;
181 if (!CChainWalkContext::SetHashRoutine(sHashRoutineName))
183 fprintf(stderr, "hash routine %s not supported\n", sHashRoutineName.c_str());
186 //std::cout << "Hash routine validated" << std::endl;
188 if (!CChainWalkContext::SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
190 std::cerr << "charset " << sCharsetName << " not supported" << std::endl;
193 //std::cout << "Plain charset validated" << std::endl;
195 if (!CChainWalkContext::SetRainbowTableIndex(nRainbowTableIndex))
197 std::cerr << "invalid rainbow table index " << nRainbowTableIndex << std::endl;
200 //std::cout << "Rainbowtable index validated" << std::endl;
202 if(sHashRoutineName == "mscache")// || sHashRoutineName == "lmchall" || sHashRoutineName == "halflmchall")
204 // Convert username to unicode
205 const char *szSalt = sSalt.c_str();
206 int salt_length = strlen(szSalt);
207 unsigned char cur_salt[256];
208 for (int i=0; i<salt_length; i++)
210 cur_salt[i*2] = szSalt[i];
211 cur_salt[i*2+1] = 0x00;
213 CChainWalkContext::SetSalt(cur_salt, salt_length*2);
215 else if(sHashRoutineName == "halflmchall")
216 { // The salt is hardcoded into the hash routine
217 // CChainWalkContext::SetSalt((unsigned char*)&salt, 8);
219 else if(sHashRoutineName == "oracle")
221 CChainWalkContext::SetSalt((unsigned char *)sSalt.c_str(), sSalt.length());
223 //std::cout << "Opening chain file" << std::endl;
227 boinc_resolve_filename("result", output_path, sizeof(output_path));
228 fclose(boinc_fopen(output_path, "a"));
229 FILE *outfile = boinc_fopen(output_path, "r+b");
233 std::cerr << "failed to create " << output_path << std::endl;
238 // Check existing chains
239 unsigned int nDataLen = (unsigned int)GetFileLen(outfile);
240 unsigned int nFileLen;
243 nDataLen = nDataLen / 10 * 10;
244 if (nDataLen == nRainbowChainCount * 10)
246 std::cerr << "precomputation of this rainbow table already finished" << std::endl;
251 fseek(outfile, nDataLen, SEEK_SET);
252 //XXX size_t isn't 32/64 clean
254 CChainWalkContext cwc;
256 time_t tStart = time(NULL);
258 // std::cout << "Starting to generate chains" << std::endl;
259 int maxCalcBuffSize = rcuda::GetChainsBufferSize(0x2000);
260 uint64 *calcBuff = new uint64[2*maxCalcBuffSize];
263 CudaCWCExtender ex(&cwc);
264 rcuda::RCudaTask cuTask;
265 std::vector<unsigned char> stPlain;
268 for(int nCurrentCalculatedChains = nDataLen / 10, calcSize; nCurrentCalculatedChains < nRainbowChainCount; )
270 fd = (double)nCurrentCalculatedChains / (double)nRainbowChainCount;
271 boinc_fraction_done(fd);
273 cuTask.hash = ex.GetHash();
274 cuTask.startIdx = nChainStart + nCurrentCalculatedChains;
275 cuTask.idxCount = std::min<int>(nRainbowChainCount - nCurrentCalculatedChains, maxCalcBuffSize);
276 cuTask.stPlainSize = ex.IndexToStartPlain(0, stPlain);
277 cuTask.stPlain = &stPlain[0];
278 cuTask.dimVec = ex.GetPlainDimVec();
279 cuTask.dimVecSize = ex.GetPlainDimVecSize()/3;
280 cuTask.charSet = ex.GetCharSet();
281 cuTask.charSetSize = ex.GetCharSetSize();
282 cuTask.cpPositions = &vCPPositions[0];
283 cuTask.cpPosSize = vCPPositions.size();
284 cuTask.reduceOffset = ex.GetReduceOffset();
285 cuTask.plainSpaceTotal = ex.GetPlainSpaceTotal();
286 cuTask.rainbowChainLen = nRainbowChainLen;
287 for(ii = 0; ii < cuTask.idxCount; ii++) {
288 calcBuff[2*ii] = cuTask.startIdx + ii;
289 calcBuff[2*ii+1] = 0;
291 calcSize = rcuda::CalcChainsOnCUDA(&cuTask, calcBuff);
294 nCurrentCalculatedChains += calcSize;
295 for(ii = 0; ii < cuTask.idxCount; ii++) {
296 nIndex[0] = cuTask.startIdx + ii;
297 // nReturn = fwrite(nIndex, 1, 8, outfile);
298 nReturn = fwrite(calcBuff+(2*ii), 1, 8, outfile);
299 nReturn += fwrite(calcBuff+(2*ii+1), 1, 2, outfile);
301 std::cerr << "disk write fail" << std::endl;
307 std::cerr << "Calculations on CUDA failed!" << std::endl;
314 std::cout << "Generation completed" << std::endl;
317 fseek(outfile, 0, SEEK_SET);
318 nFileLen = GetFileLen(outfile);
319 nRainbowChainCount = nFileLen / 18;
321 RainbowChainCP* pChain = (RainbowChainCP*)new unsigned char[sizeof(RainbowChainCP) * nRainbowChainCount];
327 std::cout << "Sorting file" << std::endl;
329 fseek(outfile, 0, SEEK_SET);
330 for(uint32 i = 0; i < nRainbowChainCount; i++)
332 if(fread(&pChain[i], 1, 16, outfile) != 16)
334 printf("disk read fail\n");
337 if(fread(&pChain[i].nCheckPoint, 1, sizeof(pChain[i].nCheckPoint), outfile) != 2)
339 printf("disk read fail\n");
345 QuickSort(pChain, 0, nRainbowChainCount - 1);
348 fseek(outfile, 0, SEEK_SET);
349 for(uint32 i = 0; i < nRainbowChainCount; i++)
351 fwrite(&pChain[i], 1, 16, outfile);
352 fwrite(&pChain[i].nCheckPoint, 2, 1, outfile);
359 // main loop - read characters, convert to UC, write
362 boinc_fraction_done(1);
367 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode) {
372 command_line = GetCommandLine();
373 argc = parse_command_line( command_line, argv );
374 return main(argc, argv);