Changeset 443


Ignore:
Timestamp:
10/17/2008 10:04:30 AM (6 years ago)
Author:
cjax
Message:

More source of entropy, and some optimizations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/Manager/PRNG.cs

    r348 r443  
    33 * Copyright 2008 The Eraser Project 
    44 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 
    5  * Modified By: 
     5 * Modified By: Kasra Nasiri <cjax@users.sourceforge.net> @10/7/2008 
    66 *  
    77 * This file is part of Eraser. 
     
    215215    { 
    216216        public EntropyThread() 
    217         { 
     217        {            
    218218            //Create the pool. 
    219             pool = new byte[512]; 
     219            pool = new byte[poolSize]; // {512,1024} bytes 
    220220 
    221221            //Initialize the pool with some default information. 
     
    233233                FastAddEntropy(); 
    234234                SlowAddEntropy(); 
     235 
     236                // set the default PRF algorithm 
     237                PRFAlgorithm = PRFAlgorithms.SHA512; 
    235238                MixPool(); 
    236239            } 
     240 
     241            // apply whitening effect 
     242            PRFAlgorithm = PRFAlgorithms.RIPEMD160; 
     243            MixPool(); 
     244 
     245            // set back to default hash algorithm 
     246            PRFAlgorithm = PRFAlgorithms.SHA512; 
    237247 
    238248            //Then start the thread which maintains the pool. 
     
    243253            ); 
    244254            thread.Start(); 
     255        } 
     256         
     257        /// <summary> 
     258        /// The algorithm used for mixing 
     259        /// </summary> 
     260        public enum PRFAlgorithms : int 
     261        { 
     262            MD5, 
     263            SHA1, 
     264            RIPEMD160, 
     265            SHA256, 
     266            SHA384, 
     267            SHA512, 
     268        }; 
     269 
     270        /// <summary> 
     271        /// Property sheet for PRF algorithm 
     272        /// </summary> 
     273        public PRFAlgorithms PRFAlgorithm 
     274        { 
     275            get 
     276            { 
     277                return prfAlgorithm; 
     278            } 
     279            set 
     280            { 
     281                prfAlgorithm = value; 
     282            } 
    245283        } 
    246284 
     
    262300            //This entropy thread will utilize a polling loop. 
    263301            DateTime lastAddedEntropy = DateTime.Now; 
     302            TimeSpan ManagerEntropySpan = new TimeSpan(0, 10, 0); 
     303            System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); 
    264304            while (thread.ThreadState != ThreadState.AbortRequested) 
    265305            { 
    266                 FastAddEntropy(); 
    267                 SlowAddEntropy(); 
    268                 Thread.Sleep(3000); 
     306                st.Start(); 
     307                { 
     308                    FastAddEntropy(); 
     309                    SlowAddEntropy(); 
     310                } 
     311                 
     312                st.Stop();  
     313                Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L)); 
     314                st.Reset(); 
    269315 
    270316                //Send entropy to the PRNGs for new seeds. 
    271                 if (DateTime.Now - lastAddedEntropy > new TimeSpan(0, 10, 0)) 
     317                if (DateTime.Now - lastAddedEntropy > ManagerEntropySpan) 
    272318                    ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool()); 
    273319            } 
     
    300346        { 
    301347            lock (poolLock) 
    302             unsafe 
    303             { 
    304                 fixed (byte* fPool = pool) 
    305                 { 
    306                     int* pPool = (int*)fPool; 
    307                     int poolLength = pool.Length / sizeof(int); 
    308                     while (poolLength-- != 0) 
    309                         *pPool = (int)(*pPool++ ^ unchecked((uint)-1)); 
    310                 } 
     348                unsafe 
     349                { 
     350                    fixed (byte* fPool = pool) 
     351                    { 
     352                        uint* pPool = (uint*)fPool; 
     353                        uint poolLength = (uint)(pool.Length / sizeof(uint)); 
     354                        while (poolLength-- != 0) 
     355                            *pPool = (uint)(*pPool++ ^ unchecked((uint)-1)); 
     356                    } 
     357                } 
     358        } 
     359 
     360        /// <summary> 
     361        /// Creates an instance of the requested PRF 
     362        /// </summary> 
     363        private void CheckPRF() 
     364        { 
     365            switch (prfAlgorithm) 
     366            { 
     367                case PRFAlgorithms.MD5:         PRF = new MD5CryptoServiceProvider(); break; 
     368                case PRFAlgorithms.SHA1:        PRF = new SHA1Managed(); break; 
     369                case PRFAlgorithms.RIPEMD160:   PRF = new RIPEMD160Managed();  break; 
     370                case PRFAlgorithms.SHA256:      PRF = new SHA256Managed();  break; 
     371                case PRFAlgorithms.SHA384:      PRF = new SHA384Managed(); break; 
     372                default: /*SHA512: */           PRF = new SHA512Managed(); break; 
    311373            } 
    312374        } 
     
    317379        private void MixPool() 
    318380        { 
     381            CheckPRF(); 
     382 
    319383            lock (poolLock) 
    320             using (SHA512 hash = SHA512.Create()) 
    321384            { 
    322385                //Mix the last 128 bytes first. 
    323386                const int mixBlockSize = 128; 
    324                 int hashSize = hash.HashSize / 8; 
    325                 hash.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0); 
     387                int hashSize = PRF.HashSize / 8; 
     388                PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0); 
    326389 
    327390                //Then mix the following bytes until wraparound is required 
    328391                int i = 0; 
    329392                for (; i < pool.Length - hashSize; i += hashSize) 
    330                     hash.ComputeHash(pool, i, mixBlockSize).CopyTo(pool, i); 
    331  
     393                    Buffer.BlockCopy(PRF.ComputeHash(pool, i,  
     394                        i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize), 
     395                        0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize); 
     396                 
    332397                //Mix the remaining blocks which require copying from the front 
    333398                byte[] combinedBuffer = new byte[mixBlockSize]; 
    334399                for (; i < pool.Length; i += hashSize) 
    335400                { 
    336                     for (int j = i; j < pool.Length; ++j) 
    337                         combinedBuffer[j - i] = pool[j]; 
    338                     for (int j = 0, k = mixBlockSize - (pool.Length - i); j < k; ++j) 
    339                         combinedBuffer[j + pool.Length - i] = pool[j]; 
    340                     hash.ComputeHash(combinedBuffer, 0, mixBlockSize).CopyTo(pool, i); 
     401                    Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i); 
     402 
     403                    Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i, 
     404                                mixBlockSize - (pool.Length - i)); 
     405 
     406                    Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 
     407                        pool, i, pool.Length-i > hashSize ? hashSize : pool.Length-i); 
    341408                } 
    342409            } 
     
    351418        { 
    352419            lock (poolLock) 
    353             fixed (byte* pEntropy = entropy) 
    354             { 
    355                 //Add entropy to the pool by XORing every value with the given entropy. 
    356                 byte* bytes = (byte*)pEntropy; 
    357                 for (int i = 0; i < entropy.Length; ++i) 
    358                 { 
    359                     if (poolPosition == pool.Length) 
    360                         poolPosition = 0; 
    361                     pool[poolPosition++] ^= bytes[i]; 
    362                 } 
     420                fixed (byte* pEntropy = entropy) 
     421                fixed (byte* pPool = pool) 
     422                { 
     423                    //Add entropy to the pool by XORing every value with the given entropy. 
     424                    poolPosition = CircularMemoryXor(new IntPtr(pPool), new IntPtr(pEntropy), 
     425                                        poolPosition, poolSize, entropy.Length); 
     426                } 
     427        } 
     428 
     429        /// <summary> 
     430        /// Optomised unmanaged circular memory xor 
     431        /// </summary> 
     432        /// <param name="dest">Destination Pointer</param> 
     433        /// <param name="source">Source Pointer</param> 
     434        /// <param name="size">Size in bytes</param> 
     435        private unsafe static int CircularMemoryXor(IntPtr destination, IntPtr source, 
     436            int destOffset, int destLength, int size) 
     437        { 
     438            uint* dest = (uint*)destination.ToPointer(); 
     439            uint* src = (uint*)source.ToPointer(); 
     440            while (size > 0) 
     441            { 
     442                if (size + destOffset < destLength) 
     443                { 
     444                    IntPtr _gc = new IntPtr(destination.ToInt32() + destOffset); 
     445                    MemoryXor(_gc, source, size); 
     446                    destOffset += size; 
     447                    size = 0; 
     448                } 
     449                else // (size + destOffset >= destLength) 
     450                { 
     451                    IntPtr _gc = new IntPtr(destination.ToInt32() + destOffset); 
     452                    MemoryXor(_gc, source, destLength - destOffset); 
     453                    source = new IntPtr(source.ToInt32() + destLength - destOffset); 
     454                    size -= destLength - destOffset; 
     455                    destOffset = 0;                      
     456                } 
     457            } 
     458 
     459            return destOffset; 
     460        } 
     461 
     462        private static unsafe void MemoryXor(IntPtr destination, IntPtr source, int size) 
     463        { 
     464            int wsize = size / sizeof(int); size -= wsize * sizeof(int); 
     465            uint* d = (uint*)destination.ToPointer(); 
     466            uint* s = (uint*)source.ToPointer(); 
     467             
     468            while (wsize-- > 0) *d++ ^= *s++; 
     469 
     470            if (size > 0) 
     471            { 
     472                byte* db = (byte*)d, ds = (byte*)s; 
     473                while (size-- > 0)  *db++ ^= *ds++; 
    363474            } 
    364475        } 
     
    371482        public unsafe void AddEntropy<T>(T entropy) where T : struct 
    372483        { 
    373             int sizeofObject = Marshal.SizeOf(entropy); 
    374             IntPtr memory = Marshal.AllocHGlobal(sizeofObject); 
    375484            try 
    376485            { 
    377                 Marshal.StructureToPtr(entropy, memory, false); 
    378                 byte* pMemory = (byte*)memory.ToPointer(); 
    379                 byte[] dest = new byte[sizeofObject]; 
    380  
    381                 //Copy the memory 
    382                 for (int i = 0; i != dest.Length; ++i) 
    383                     dest[i] = *pMemory++; 
    384  
    385                 //Add entropy 
    386                 AddEntropy(dest); 
    387             } 
    388             finally 
    389             { 
    390                 Marshal.FreeHGlobal(memory); 
    391             } 
    392         } 
     486                int sizeofObject = Marshal.SizeOf(entropy); 
     487                IntPtr memory = Marshal.AllocHGlobal(sizeofObject); 
     488                try 
     489                { 
     490                    Marshal.StructureToPtr(entropy, memory, false); 
     491                    byte[] dest = new byte[sizeofObject]; 
     492 
     493                    //Copy the memory 
     494                    Marshal.Copy(memory, dest, 0, sizeofObject); 
     495 
     496                    //Add entropy 
     497                    AddEntropy(dest); 
     498                } 
     499                finally 
     500                { 
     501                    Marshal.FreeHGlobal(memory); 
     502                } 
     503            } 
     504            catch (OutOfMemoryException ex1) 
     505            { 
     506                // ignore this entropy source, we don't have enough memory! 
     507                string ignored = ex1.Message; 
     508            } 
     509        } 
     510#if false 
     511         
     512        /// <summary> 
     513        /// Optomosed constant memory xor 
     514        /// </summary> 
     515        /// <param name="dest">Destination buffer</param> 
     516        /// <param name="value">value the destination should be xored against</param> 
     517        /// <param name="size">size of destination in bytes</param> 
     518        private static unsafe void MemoryXor(IntPtr dest, byte value, int size) 
     519        { 
     520            int wsize = size / sizeof(int); size -= wsize * sizeof(int); 
     521            uint* d = (uint*)dest.ToPointer(); 
     522            uint wvalue = 0; // a word containing values in  correct endian 
     523            for (int i = 0; i < sizeof(uint); i++, wvalue <<= 8)    wvalue |= value;             
     524 
     525            while (wsize-- > 0)     *d++ ^= wvalue; 
     526 
     527            if (size > 0) // size%4 == 0 ? 
     528            { 
     529                byte* db = (byte*)d; 
     530                while (size-- > 0) 
     531                    *db++ ^= value; 
     532            } 
     533        } 
     534#endif 
    393535 
    394536        /// <summary> 
     
    430572                AddEntropy(memoryStatus.ullAvailPhys); 
    431573                AddEntropy(memoryStatus.ullAvailVirtual); 
     574                AddEntropy(memoryStatus); 
    432575            } 
    433576 
     
    483626                    0, 0, out netAPIStats) == 0) 
    484627                { 
    485                     //Get the size of the buffer 
    486                     uint size = 0; 
    487                     NetAPI.NetApiBufferSize(netAPIStats, out size); 
    488                     byte[] entropy = new byte[size]; 
    489  
    490                     //Copy the buffer 
    491                     fixed (byte* fEntropy = entropy) 
     628                    try 
    492629                    { 
    493                         byte* pSrc = (byte*)netAPIStats.ToPointer(); 
    494                         byte* pEntropy = fEntropy; 
    495                         while (size-- != 0) 
    496                             *pEntropy++ = *pSrc++; 
     630                        //Get the size of the buffer 
     631                        uint size = 0; 
     632                        NetAPI.NetApiBufferSize(netAPIStats, out size); 
     633                        byte[] entropy = new byte[size]; 
     634 
     635                        //Copy the buffer 
     636                        Marshal.Copy(entropy, 0, netAPIStats, entropy.Length); 
     637 
     638                        //And add it to the pool 
     639                        AddEntropy(entropy); 
    497640                    } 
    498  
    499                     //And add it to the pool 
    500                     AddEntropy(entropy); 
    501  
    502                     //Free the statistics buffer 
    503                     NetAPI.NetApiBufferFree(netAPIStats); 
     641                    finally 
     642                    { 
     643                        //Free the statistics buffer 
     644                        NetAPI.NetApiBufferFree(netAPIStats); 
     645                    } 
    504646                } 
    505647            } 
     
    554696                { 
    555697                    byte[] entropy = new byte[dataWritten]; 
    556                     for (int i = 0; i < dataWritten; ++i) 
    557                         entropy[i] = infoBuffer[i]; 
     698                    Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten); 
    558699                    AddEntropy(entropy); 
    559700                    totalEntropy += dataWritten; 
    560701                } 
    561702            } 
     703 
     704            AddEntropy(totalEntropy); 
    562705 
    563706            //Finally, our good friend CryptGenRandom() 
     
    568711 
    569712        /// <summary> 
     713        /// PRF algorithm handle 
     714        /// </summary> 
     715        private HashAlgorithm PRF; 
     716 
     717        /// <summary> 
     718        /// PRF algorithm identifier 
     719        /// </summary> 
     720        private PRFAlgorithms prfAlgorithm;      
     721 
     722        /// <summary> 
    570723        /// The thread object. 
    571724        /// </summary> 
    572725        Thread thread; 
     726 
     727        /// <summary> 
     728        /// size of the netropy pool, should allways be exponent of 2. 
     729        /// </summary> 
     730        const int poolSize = sizeof(uint) * 128; 
     731 
     732        /// <summary> 
     733        /// Modulus of pool size 
     734        /// </summary> 
     735        const int poolMod = poolSize - 1; 
    573736 
    574737        /// <summary> 
Note: See TracChangeset for help on using the changeset viewer.