Ignore:
Timestamp:
Nov 14, 2010, 5:32:51 PM (11 years ago)
Author:
Sven Rech
Message:

KeySearcher OpenCL implementation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypPlugins/KeySearcher/KeySearcher.cs

    r2061 r2086  
    1717using System;
    1818using System.Diagnostics;
     19using System.IO;
    1920using System.Linq;
    2021using System.Text;
     
    238239            {
    239240                oclManager = new OpenCLManager();
     241                oclManager.AttemptUseBinaries = false;
     242                oclManager.AttemptUseSource = true;
     243                oclManager.RequireImageSupport = false;
     244                oclManager.BuildOptions = "";
    240245                oclManager.CreateDefaultContext(0, DeviceType.ALL);
    241246            }
     
    361366            int bytesToUse = (int)parameters[6];
    362367            Stack threadStack = (Stack)parameters[7];
    363 
    364             KeyPattern.KeyPattern pattern = patterns[threadid];
    365            
     368            bool useOpenCL = (bool)parameters[8];
     369
     370            KeySearcherOpenCLCode keySearcherOpenCLCode = null;
     371            if (useOpenCL)
     372                keySearcherOpenCLCode = new KeySearcherOpenCLCode(encryptedData, sender, CostMaster, 256 * 64);
     373
    366374            try
    367375            {
    368                 while (pattern != null)
    369                 {
    370                     BigInteger size = pattern.size();
     376                while (patterns[threadid] != null)
     377                {
     378                    BigInteger size = patterns[threadid].size();
    371379                    keysLeft[threadid] = size;
    372 
     380                   
    373381                    IKeyTranslator keyTranslator = ControlMaster.getKeyTranslator();
    374                     keyTranslator.SetKeys(pattern);
     382                    keyTranslator.SetKeys(patterns[threadid]);
    375383
    376384                    bool finish = false;
     
    379387                    {
    380388                        //if we are the thread with most keys left, we have to share them:
    381                         if (maxThread == threadid && threadStack.Count != 0)
     389                        keyTranslator = ShareKeys(patterns, threadid, keysLeft, keyTranslator, threadStack);
     390
     391                        if (!useOpenCL)         //CPU
     392                        {
     393                            finish = BruteforceCPU(keyTranslator, sender, bytesToUse);
     394                        }
     395                        else                    //OpenCL
    382396                        {
    383397                            try
    384398                            {
    385                                 maxThreadMutex.WaitOne();
    386                                 if (maxThread == threadid && threadStack.Count != 0)
    387                                 {
    388                                     KeyPattern.KeyPattern[] split = pattern.split();
    389                                     if (split != null)
    390                                     {
    391                                         patterns[threadid] = split[0];
    392                                         pattern = split[0];
    393                                         keyTranslator = ControlMaster.getKeyTranslator();
    394                                         keyTranslator.SetKeys(pattern);
    395 
    396                                         ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
    397                                         patterns[elem.threadid] = split[1];
    398                                         elem.ev.Set();    //wake the other thread up                                   
    399                                         size = pattern.size();
    400                                         keysLeft[threadid] = size;
    401                                     }
    402                                     maxThread = -1;
    403                                 }
     399                                finish = BruteforceOpenCL(keySearcherOpenCLCode, keyTranslator, sender, bytesToUse);
    404400                            }
    405                             finally
     401                            catch (Exception)
    406402                            {
    407                                 maxThreadMutex.ReleaseMutex();
     403                                useOpenCL = false;
     404                                continue;
    408405                            }
    409406                        }
    410 
    411                         for (int count = 0; count < 256 * 256; count++)
    412                         {
    413                             byte[] keya = keyTranslator.GetKey();
    414 
    415                             if (!decryptAndCalculate(sender, bytesToUse, keya, keyTranslator))
    416                                 return;
    417 
    418                             finish = !keyTranslator.NextKey();
    419                             if (finish)
    420                                 break;
    421                         }
     407                       
    422408                        int progress = keyTranslator.GetProgress();
    423409
     
    432418
    433419                    //Let's wait until another thread is willing to share with us:
    434                     pattern = null;
    435                     ThreadStackElement el = new ThreadStackElement();
    436                     el.ev = new AutoResetEvent(false);
    437                     el.threadid = threadid;
    438                     patterns[threadid] = null;
    439                     threadStack.Push(el);
    440                     GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
    441                     el.ev.WaitOne();
    442                     if (!stop)
     420                    WaitForNewPattern(patterns, threadid, threadStack);
     421                }
     422            }
     423            finally
     424            {
     425                sender.Dispose();
     426            }
     427        }
     428
     429        private unsafe bool BruteforceOpenCL(KeySearcherOpenCLCode keySearcherOpenCLCode, IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse)
     430        {
     431            float[] costArray = new float[keySearcherOpenCLCode.GetBruteforceBlock()];
     432            try
     433            {
     434                Kernel bruteforceKernel = keySearcherOpenCLCode.GetBruteforceKernel(oclManager, keyTranslator);
     435                int deviceIndex = settings.OpenCLDevice;
     436               
     437                Mem costs = oclManager.Context.CreateBuffer(MemFlags.READ_ONLY, costArray.Length * 4);
     438                IntPtr[] globalWorkSize = { (IntPtr)keySearcherOpenCLCode.GetBruteforceBlock() };
     439
     440                Mem userKey;
     441                var key = keyTranslator.GetKey();
     442                fixed (byte* ukp = key)
     443                    userKey = oclManager.Context.CreateBuffer(MemFlags.USE_HOST_PTR, key.Length, new IntPtr((void*)ukp));
     444
     445                bruteforceKernel.SetArg(0, userKey);
     446                bruteforceKernel.SetArg(1, costs);
     447
     448                oclManager.CQ[deviceIndex].EnqueueNDRangeKernel(bruteforceKernel, 1, null, globalWorkSize, null);
     449                oclManager.CQ[deviceIndex].EnqueueBarrier();
     450
     451                Event e;
     452                fixed (float* costa = costArray)
     453                    oclManager.CQ[deviceIndex].EnqueueReadBuffer(costs, true, 0, costArray.Length * 4, new IntPtr((void*)costa), 0, null, out e);
     454
     455                e.Wait();
     456                costs.Dispose();
     457            }
     458            catch (Exception ex)
     459            {
     460                GuiLogMessage(ex.Message, NotificationLevel.Error);
     461                GuiLogMessage("Bruteforcing with OpenCL failed! Using CPU instead.", NotificationLevel.Error);
     462                throw new Exception("Bruteforcing with OpenCL failed!");
     463            }
     464
     465            //Check results:
     466            var op = this.costMaster.getRelationOperator();
     467            for (int i = 0; i < costArray.Length; i++)
     468            {
     469                float cost = costArray[i];
     470                if (((op == RelationOperator.LargerThen) && (cost > value_threshold))
     471                    || (op == RelationOperator.LessThen) && (cost < value_threshold))
     472                {
     473                    ValueKey valueKey = new ValueKey {value = cost, key = keyTranslator.GetKeyRepresentation(i)};
     474                    valueKey.keya = keyTranslator.GetKeyFromRepresentation(valueKey.key);
     475                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
     476                    valuequeue.Enqueue(valueKey);
     477                }
     478            }
     479
     480            return !keyTranslator.NextOpenCLBatch();
     481        }
     482
     483        private bool BruteforceCPU(IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse)
     484        {
     485            bool finish = false;
     486            for (int count = 0; count < 256 * 256; count++)
     487            {
     488                byte[] keya = keyTranslator.GetKey();
     489
     490                if (!decryptAndCalculate(sender, bytesToUse, keya, keyTranslator))
     491                    throw new Exception("Bruteforcing not possible!");
     492
     493                finish = !keyTranslator.NextKey();
     494                if (finish)
     495                    break;
     496            }
     497            return finish;
     498        }
     499
     500        private IKeyTranslator ShareKeys(KeyPattern.KeyPattern[] patterns, int threadid, BigInteger[] keysLeft, IKeyTranslator keyTranslator, Stack threadStack)
     501        {
     502            BigInteger size;
     503            if (maxThread == threadid && threadStack.Count != 0)
     504            {
     505                try
     506                {
     507                    maxThreadMutex.WaitOne();
     508                    if (maxThread == threadid && threadStack.Count != 0)
    443509                    {
    444                         GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
    445                         pattern = patterns[threadid];
     510                        KeyPattern.KeyPattern[] split = patterns[threadid].split();
     511                        if (split != null)
     512                        {
     513                            patterns[threadid] = split[0];
     514                            keyTranslator = ControlMaster.getKeyTranslator();
     515                            keyTranslator.SetKeys(patterns[threadid]);
     516
     517                            ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
     518                            patterns[elem.threadid] = split[1];
     519                            elem.ev.Set();    //wake the other thread up                                   
     520                            size = patterns[threadid].size();
     521                            keysLeft[threadid] = size;
     522                        }
     523                        maxThread = -1;
    446524                    }
    447525                }
    448             }
    449             finally
    450             {
    451                 sender.Dispose();
     526                finally
     527                {
     528                    maxThreadMutex.ReleaseMutex();
     529                }
     530            }
     531            return keyTranslator;
     532        }
     533
     534        private void WaitForNewPattern(KeyPattern.KeyPattern[] patterns, int threadid, Stack threadStack)
     535        {
     536            ThreadStackElement el = new ThreadStackElement();
     537            el.ev = new AutoResetEvent(false);
     538            el.threadid = threadid;
     539            patterns[threadid] = null;
     540            threadStack.Push(el);
     541            GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
     542            el.ev.WaitOne();
     543            if (!stop)
     544            {
     545                GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
    452546            }
    453547        }
     
    600694            BigInteger size = pattern.size();
    601695            KeyPattern.KeyPattern[] patterns = splitPatternForThreads(pattern);
     696            if (patterns == null || patterns.Length == 0)
     697            {
     698                GuiLogMessage("No ressources to BruteForce available. Check the KeySearcher settings!", NotificationLevel.Error);
     699                throw new Exception("No ressources to BruteForce available. Check the KeySearcher settings!");
     700            }
    602701
    603702            BigInteger[] doneKeysA = new BigInteger[patterns.Length];
     
    605704            BigInteger[] keysleft = new BigInteger[patterns.Length];
    606705            Stack threadStack = Stack.Synchronized(new Stack());
    607             startThreads(sender, bytesToUse, patterns, doneKeysA, keycounters, keysleft, threadStack);
     706            StartThreads(sender, bytesToUse, patterns, doneKeysA, keycounters, keysleft, threadStack);
    608707
    609708            DateTime lastTime = DateTime.Now;
     
    711810        }
    712811
    713         private string CreateOpenCLBruteForceCode(KeyPattern.KeyPattern keyPattern)
    714         {
    715             try
    716             {
    717                 string code = sender.GetOpenCLCode(CostMaster.getBytesToUse());
    718                 if (code == null)
    719                     throw new Exception("OpenCL not supported in this configuration!");
    720 
    721                 //put cost function stuff into code:
    722                 code = costMaster.ModifyOpenCLCode(code);
    723 
    724                 //put input to be bruteforced into code:
    725                 string inputarray = string.Format("__constant unsigned char inn[{0}] = {{ \n", CostMaster.getBytesToUse());
    726                 for (int i = 0; i < CostMaster.getBytesToUse(); i++)
    727                 {
    728                     inputarray += String.Format("0x{0:X2}, ", this.encryptedData[i]);
    729                 }
    730                 inputarray = inputarray.Substring(0, inputarray.Length - 2);
    731                 inputarray += "}; \n";
    732                 code = code.Replace("$$INPUTARRAY$$", inputarray);
    733 
    734                 //put key movement of pattern into code:
    735                 IKeyTranslator keyTranslator = ControlMaster.getKeyTranslator();
    736                 keyTranslator.SetKeys(pattern);
    737                 code = keyTranslator.ModifyOpenCLCode(code, 256*256);
    738 
    739                 return code;
    740             }
    741             catch (Exception ex)
    742             {
    743                 GuiLogMessage("Error trying to generate OpenCL code: " + ex.Message, NotificationLevel.Error);
    744                 return null;
    745             }
    746         }
     812
    747813
    748814        private void SetStartDate()
     
    9451011        #endregion
    9461012
    947         private void startThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
     1013        private void StartThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
    9481014        {
    9491015            for (int i = 0; i < patterns.Length; i++)
     
    9521018                doneKeysA[i] = new BigInteger();
    9531019                keycounters[i] = new BigInteger();
    954                 //ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender.clone(), bytesToUse, threadStack });
    955                 ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack });
     1020                bool useOpenCL = false;
     1021
     1022                if (settings.UseOpenCL && (i == patterns.Length - 1))     //Last thread is the OpenCL thread
     1023                    useOpenCL = true;
     1024
     1025                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, useOpenCL });
    9561026            }
    9571027        }
     
    9591029        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
    9601030        {
    961             KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[settings.CoresUsed + 1];
    962             if (settings.CoresUsed > 0)
     1031            int threads = settings.CoresUsed;
     1032            if (settings.UseOpenCL)
     1033                threads++;
     1034
     1035            if (threads < 1)
     1036                return null;
     1037
     1038            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[threads];
     1039            if (threads > 1)
    9631040            {
    9641041                KeyPattern.KeyPattern[] patterns2 = pattern.split();
     
    9721049                patterns[1] = patterns2[1];
    9731050                int p = 1;
    974                 int threads = settings.CoresUsed - 1;
     1051                threads -= 2;
     1052
    9751053                while (threads > 0)
    9761054                {
Note: See TracChangeset for help on using the changeset viewer.