Changeset 479


Ignore:
Timestamp:
11/09/08 10:04:48 (6 years ago)
Author:
lowjoel
Message:

Fixed Kaz's implementation, and implemented his proposal of using EntropySources? to allow extensibility in future to hardware entropy sources, etc.

Location:
branches/eraser6
Files:
1 deleted
2 edited

Legend:

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

    r478 r479  
    144144    { 
    145145        /// <summary> 
     146        /// Constructor. 
     147        /// </summary> 
     148        public PRNGManager() 
     149        { 
     150            entropyThread.AddEntropySource(new KernelEntropySource()); 
     151        } 
     152 
     153        /// <summary> 
    146154        /// Retrieves all currently registered erasure methods. 
    147155        /// </summary> 
     
    217225    /// </summary> 
    218226    class EntropyPoller 
    219     { 
    220         public EntropyPoller() 
    221         {    
    222             //Then start the thread which maintains the pool. 
    223             thread = new Thread(delegate() 
    224                 { 
    225                     this.Main(); 
    226                 } 
    227             ); 
    228             thread.Start(); 
    229         } 
    230  
    231         /// <summary> 
    232         /// The PRNG entropy thread. This thread will run in the background, getting 
    233         /// random data to be used for entropy. This will maintain the integrity 
    234         /// of generated data from the PRNGs. 
    235         /// </summary> 
    236         private void Main() 
    237         { 
    238             //This entropy thread will utilize a polling loop. 
    239             DateTime lastAddedEntropy = DateTime.Now; 
    240             TimeSpan managerEntropySpan = new TimeSpan(0, 10, 0); 
    241             Stopwatch st = new Stopwatch(); 
    242  
    243             while (thread.ThreadState != System.Threading.ThreadState.AbortRequested) 
    244             { 
    245                 st.Start(); 
    246                 { 
    247                     FastAddEntropy(); 
    248                     SlowAddEntropy(); 
    249                 } 
    250                  
    251                 st.Stop();  
    252                 Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L)); 
    253                 st.Reset(); 
    254  
    255                 //Send entropy to the PRNGs for new seeds. 
    256                 if (DateTime.Now - lastAddedEntropy > managerEntropySpan) 
    257                     ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool()); 
    258             } 
    259         } 
    260          
    261         /// <summary> 
    262         /// Stops the execution of the thread. 
    263         /// </summary> 
    264         public void Abort() 
    265         { 
    266             thread.Abort(); 
    267         } 
    268  
    269         /// <summary> 
    270         /// The thread object. 
    271         /// </summary> 
    272         Thread thread;       
    273     } 
    274      
    275     /// <summary> 
    276     /// Provides means of generating random entropy from the system, user data 
    277     /// available from the kernel or dedicated harware. 
    278     /// </summary> 
    279     public class EntropySource 
    280227    { 
    281228        /// <summary> 
     
    292239        }; 
    293240 
    294         public EntropySource() 
     241        /// <summary> 
     242        /// Constructor. 
     243        /// </summary> 
     244        public EntropyPoller() 
    295245        { 
    296246            //Create the pool. 
    297247            pool = new byte[sizeof(uint) * 128]; 
    298248 
    299             //Initialize the pool with some default information. 
    300             { 
    301                 //Process startup information 
    302                 KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO(); 
    303                 KernelAPI.GetStartupInfo(out startupInfo); 
    304                 AddEntropy(startupInfo); 
    305  
    306                 //System information 
    307                 KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO(); 
    308                 KernelAPI.GetSystemInfo(out systemInfo); 
    309                 AddEntropy(systemInfo); 
    310  
    311                 FastAddEntropy(); 
    312                 SlowAddEntropy(); 
    313  
    314                 // set the default PRF algorithm 
    315                 PRFAlgorithm = PRFAlgorithms.SHA512; 
    316                 MixPool(); 
    317             } 
    318  
    319             // apply whitening effect 
     249            //Then start the thread which maintains the pool. 
     250            Thread = new Thread(delegate() 
     251                { 
     252                    this.Main(); 
     253                } 
     254            ); 
     255            Thread.Start(); 
     256        } 
     257 
     258        /// <summary> 
     259        /// The PRNG entropy thread. This thread will run in the background, getting 
     260        /// random data to be used for entropy. This will maintain the integrity 
     261        /// of generated data from the PRNGs. 
     262        /// </summary> 
     263        private void Main() 
     264        { 
     265            //This entropy thread will utilize a polling loop. 
     266            DateTime lastAddedEntropy = DateTime.Now; 
     267            TimeSpan managerEntropySpan = new TimeSpan(0, 10, 0); 
     268            Stopwatch st = new Stopwatch(); 
     269 
     270            while (Thread.ThreadState != System.Threading.ThreadState.AbortRequested) 
     271            { 
     272                st.Start(); 
     273                lock (EntropySources) 
     274                    foreach (EntropySource src in EntropySources) 
     275                    { 
     276                        byte[] entropy = src.GetEntropy(); 
     277                        AddEntropy(entropy); 
     278                    } 
     279                 
     280                st.Stop();  
     281                Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L)); 
     282                st.Reset(); 
     283 
     284                //Send entropy to the PRNGs for new seeds. 
     285                if (DateTime.Now - lastAddedEntropy > managerEntropySpan) 
     286                    ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool()); 
     287            } 
     288        } 
     289         
     290        /// <summary> 
     291        /// Stops the execution of the thread. 
     292        /// </summary> 
     293        public void Abort() 
     294        { 
     295            Thread.Abort(); 
     296        } 
     297 
     298        /// <summary> 
     299        /// Adds a new Entropy Source to the Poller. 
     300        /// </summary> 
     301        /// <param name="source">The EntropySource object to add.</param> 
     302        public void AddEntropySource(EntropySource source) 
     303        { 
     304            lock (EntropySources) 
     305                EntropySources.Add(source); 
     306 
     307            AddEntropy(source.GetPrimer()); 
     308            MixPool(); 
     309 
     310            //Apply whitening effect 
    320311            PRFAlgorithm = PRFAlgorithms.RIPEMD160; 
    321312            MixPool(); 
    322  
    323             // set back to default hash algorithm 
    324313            PRFAlgorithm = PRFAlgorithms.SHA512; 
    325314        } 
     
    436425            uint* d = (uint*)destination; 
    437426            uint* s = (uint*)source; 
    438              
     427 
    439428            while (wsize-- > 0) 
    440429                *d++ ^= *s++; 
     
    447436                    *db++ ^= *ds++; 
    448437            } 
    449         } 
    450  
    451         /// <summary> 
    452         /// Adds data which is random to the pool 
    453         /// </summary> 
    454         /// <typeparam name="T">Any value type</typeparam> 
    455         /// <param name="entropy">A value which will be XORed with pool contents.</param> 
    456         public unsafe void AddEntropy<T>(T entropy) where T : struct 
    457         { 
    458             try 
    459             { 
    460                 int sizeofObject = Marshal.SizeOf(entropy); 
    461                 IntPtr memory = Marshal.AllocHGlobal(sizeofObject); 
    462                 try 
    463                 { 
    464                     Marshal.StructureToPtr(entropy, memory, false); 
    465                     byte[] dest = new byte[sizeofObject]; 
    466  
    467                     //Copy the memory 
    468                     Marshal.Copy(memory, dest, 0, sizeofObject); 
    469  
    470                     //Add entropy 
    471                     AddEntropy(dest); 
    472                 } 
    473                 finally 
    474                 { 
    475                     Marshal.FreeHGlobal(memory); 
    476                 } 
    477             } 
    478             catch (OutOfMemoryException ex1) 
    479             { 
    480                 // ignore this entropy source, we don't have enough memory! 
    481                 string ignored = ex1.Message; 
    482             } 
    483         } 
    484  
    485         /// <summary> 
    486         /// Adds entropy to the pool. The sources of the entropy data is queried 
    487         /// quickly. 
    488         /// </summary> 
    489         private void FastAddEntropy() 
    490         { 
    491             //Add the free disk space to the pool 
    492             AddEntropy(new DriveInfo(new DirectoryInfo(Environment.SystemDirectory). 
    493                 Root.FullName).TotalFreeSpace); 
    494  
    495             //Miscellaneous window handles 
    496             AddEntropy(UserAPI.GetCapture()); 
    497             AddEntropy(UserAPI.GetClipboardOwner()); 
    498             AddEntropy(UserAPI.GetClipboardViewer()); 
    499             AddEntropy(UserAPI.GetDesktopWindow()); 
    500             AddEntropy(UserAPI.GetForegroundWindow()); 
    501             AddEntropy(UserAPI.GetMessagePos()); 
    502             AddEntropy(UserAPI.GetMessageTime()); 
    503             AddEntropy(UserAPI.GetOpenClipboardWindow()); 
    504             AddEntropy(UserAPI.GetProcessWindowStation()); 
    505             AddEntropy(KernelAPI.GetCurrentProcessId()); 
    506             AddEntropy(KernelAPI.GetCurrentThreadId()); 
    507             AddEntropy(KernelAPI.GetProcessHeap()); 
    508  
    509             //The caret and cursor positions 
    510             UserAPI.POINT point; 
    511             UserAPI.GetCaretPos(out point); 
    512             AddEntropy(point); 
    513             UserAPI.GetCursorPos(out point); 
    514             AddEntropy(point); 
    515  
    516             //Amount of free memory 
    517             KernelAPI.MEMORYSTATUSEX memoryStatus = new KernelAPI.MEMORYSTATUSEX(); 
    518             memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus); 
    519             if (KernelAPI.GlobalMemoryStatusEx(ref memoryStatus)) 
    520             { 
    521                 AddEntropy(memoryStatus.ullAvailPhys); 
    522                 AddEntropy(memoryStatus.ullAvailVirtual); 
    523                 AddEntropy(memoryStatus); 
    524             } 
    525  
    526             //Thread execution times 
    527             long creationTime, exitTime, kernelTime, userTime; 
    528             if (KernelAPI.GetThreadTimes(KernelAPI.GetCurrentThread(), out creationTime, 
    529                 out exitTime, out kernelTime, out userTime)) 
    530             { 
    531                 AddEntropy(creationTime); 
    532                 AddEntropy(kernelTime); 
    533                 AddEntropy(userTime); 
    534             } 
    535  
    536             //Process execution times 
    537             if (KernelAPI.GetProcessTimes(KernelAPI.GetCurrentProcess(), out creationTime, 
    538                 out exitTime, out kernelTime, out userTime)) 
    539             { 
    540                 AddEntropy(creationTime); 
    541                 AddEntropy(kernelTime); 
    542                 AddEntropy(userTime); 
    543             } 
    544  
    545             //Current system time 
    546             AddEntropy(DateTime.Now.Ticks); 
    547  
    548             //The high resolution performance counter 
    549             long perfCount = 0; 
    550             if (KernelAPI.QueryPerformanceCounter(out perfCount)) 
    551                 AddEntropy(perfCount); 
    552  
    553             //Ticks since start up 
    554             uint tickCount = KernelAPI.GetTickCount(); 
    555             if (tickCount != 0) 
    556                 AddEntropy(tickCount); 
    557  
    558             //CryptGenRandom 
    559             byte[] cryptGenRandom = new byte[160]; 
    560             if (CryptAPI.CryptGenRandom(cryptGenRandom)) 
    561                 AddEntropy(cryptGenRandom); 
    562         } 
    563  
    564         /// <summary> 
    565         /// Adds entropy to the pool. The sources of the entropy data is queried 
    566         /// relatively slowly compared to the FastAddEntropy function. 
    567         /// </summary> 
    568         private void SlowAddEntropy() 
    569         { 
    570             //NetAPI statistics 
    571             unsafe 
    572             { 
    573                 IntPtr netAPIStats = IntPtr.Zero; 
    574                 if (NetAPI.NetStatisticsGet(null, NetAPI.SERVICE_WORKSTATION, 
    575                     0, 0, out netAPIStats) == 0) 
    576                 { 
    577                     try 
    578                     { 
    579                         //Get the size of the buffer 
    580                         uint size = 0; 
    581                         NetAPI.NetApiBufferSize(netAPIStats, out size); 
    582                         byte[] entropy = new byte[size]; 
    583  
    584                         //Copy the buffer 
    585                         Marshal.Copy(entropy, 0, netAPIStats, entropy.Length); 
    586  
    587                         //And add it to the pool 
    588                         AddEntropy(entropy); 
    589                     } 
    590                     finally 
    591                     { 
    592                         //Free the statistics buffer 
    593                         NetAPI.NetApiBufferFree(netAPIStats); 
    594                     } 
    595                 } 
    596             } 
    597  
    598 #if false 
    599             //Get disk I/O statistics for all the hard drives 
    600             for (int drive = 0; ; ++drive) 
    601             { 
    602                 //Try to open the drive. 
    603                 using (SafeFileHandle hDevice = File.CreateFile( 
    604                     string.Format("\\\\.\\PhysicalDrive%d", drive), 0, 
    605                     File.FILE_SHARE_READ | File.FILE_SHARE_WRITE, IntPtr.Zero, 
    606                     File.OPEN_EXISTING, 0, IntPtr.Zero)) 
    607                 { 
    608                     if (hDevice.IsInvalid) 
    609                         break; 
    610  
    611                     //This only works if the user has turned on the disk performance 
    612                     //counters with 'diskperf -y'. These counters are off by default 
    613                     if (File.DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, 
    614                         &diskPerformance, sizeof(DISK_PERFORMANCE), &uSize, NULL)) 
    615                     { 
    616                         addEntropy(&diskPerformance, uSize); 
    617                     } 
    618                 } 
    619             } 
    620 #endif 
    621  
    622             /* 
    623              Query performance data. Because the Win32 version of this API (through 
    624              registry) may be buggy, use the NT Native API instead. 
    625               
    626              Scan the first 64 possible information types (we don't bother 
    627              with increasing the buffer size as we do with the Win32 
    628              version of the performance data read, we may miss a few classes 
    629              but it's no big deal).  In addition the returned size value for 
    630              some classes is wrong (eg 23 and 24 return a size of 0) so we 
    631              miss a few more things, but again it's no big deal.  This scan 
    632              typically yields around 20 pieces of data, there's nothing in 
    633              the range 65...128 so chances are there won't be anything above 
    634              there either. 
    635             */ 
    636             uint dataWritten = 0; 
    637             byte[] infoBuffer = new byte[65536]; 
    638             uint totalEntropy = 0; 
    639             for (uint infoType = 0; infoType < 64; ++infoType) 
    640             { 
    641                 uint result = NTAPI.NtQuerySystemInformation(infoType, infoBuffer, 
    642                     (uint)infoBuffer.Length, out dataWritten); 
    643  
    644                 if (result == 0 /*ERROR_SUCCESS*/ && dataWritten > 0) 
    645                 { 
    646                     byte[] entropy = new byte[dataWritten]; 
    647                     Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten); 
    648                     AddEntropy(entropy); 
    649                     totalEntropy += dataWritten; 
    650                 } 
    651             } 
    652  
    653             AddEntropy(totalEntropy); 
    654  
    655             //Finally, our good friend CryptGenRandom() 
    656             byte[] cryptGenRandom = new byte[1536]; 
    657             if (CryptAPI.CryptGenRandom(cryptGenRandom)) 
    658                 AddEntropy(cryptGenRandom); 
    659438        } 
    660439 
     
    704483        /// PRF algorithm identifier 
    705484        /// </summary> 
    706         private PRFAlgorithms PRFAlgorithm; 
     485        private PRFAlgorithms PRFAlgorithm = PRFAlgorithms.SHA512; 
    707486 
    708487        /// <summary> 
     
    720499        /// </summary> 
    721500        private object poolLock = new object(); 
     501 
     502        /// <summary> 
     503        /// The thread object. 
     504        /// </summary> 
     505        Thread Thread; 
     506 
     507        /// <summary> 
     508        /// The list of entropy sources registered with the Poller. 
     509        /// </summary> 
     510        private List<EntropySource> EntropySources = new List<EntropySource>(); 
     511    } 
     512     
     513    /// <summary> 
     514    /// Provides an abstract interface to allow multiple sources of entropy into 
     515    /// the EntropyPoller class. 
     516    /// </summary> 
     517    public abstract class EntropySource 
     518    { 
     519        /// <summary> 
     520        /// Constructor. 
     521        /// </summary> 
     522        public EntropySource() 
     523        { 
     524        } 
     525 
     526        /// <summary> 
     527        /// Gets a primer to add to the pool when this source is first initialised, to 
     528        /// further add entropy to the pool. 
     529        /// </summary> 
     530        /// <returns>A byte array containing the entropy.</returns> 
     531        public abstract byte[] GetPrimer(); 
     532 
     533        /// <summary> 
     534        /// Gets entropy from the entropy source. This will be called repetitively. 
     535        /// </summary> 
     536        /// <returns>A byte array containing the entropy.</returns> 
     537        public abstract byte[] GetEntropy(); 
     538 
     539        /// <summary> 
     540        /// Converts value types into a byte array. This is a helper function to allow 
     541        /// inherited classes to convert value types into byte arrays which can be 
     542        /// returned to the EntropyPoller class. 
     543        /// </summary> 
     544        /// <typeparam name="T">Any value type</typeparam> 
     545        /// <param name="entropy">A value which will be XORed with pool contents.</param> 
     546        protected unsafe static byte[] StructToBuffer<T>(T entropy) where T: struct 
     547        { 
     548            int sizeofObject = Marshal.SizeOf(entropy); 
     549            IntPtr memory = Marshal.AllocHGlobal(sizeofObject); 
     550            try 
     551            { 
     552                Marshal.StructureToPtr(entropy, memory, false); 
     553                byte[] dest = new byte[sizeofObject]; 
     554 
     555                //Copy the memory 
     556                Marshal.Copy(memory, dest, 0, sizeofObject); 
     557                return dest; 
     558            } 
     559            finally 
     560            { 
     561                Marshal.FreeHGlobal(memory); 
     562            } 
     563        } 
     564    } 
     565 
     566    /// <summary> 
     567    /// Provides means of generating random entropy from the system or user space 
     568    /// randomness. 
     569    /// </summary> 
     570    internal class KernelEntropySource : EntropySource 
     571    { 
     572        public override byte[] GetPrimer() 
     573        { 
     574            List<byte> result = new List<byte>(); 
     575 
     576            //Process startup information 
     577            KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO(); 
     578            KernelAPI.GetStartupInfo(out startupInfo); 
     579            result.AddRange(StructToBuffer(startupInfo)); 
     580 
     581            //System information 
     582            KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO(); 
     583            KernelAPI.GetSystemInfo(out systemInfo); 
     584            result.AddRange(StructToBuffer(systemInfo)); 
     585 
     586            result.AddRange(GetFastEntropy()); 
     587            result.AddRange(GetSlowEntropy()); 
     588            return result.ToArray(); 
     589        } 
     590 
     591        public override byte[] GetEntropy() 
     592        { 
     593            List<byte> result = new List<byte>(); 
     594            result.AddRange(GetFastEntropy()); 
     595            result.AddRange(GetSlowEntropy()); 
     596             
     597            return result.ToArray(); 
     598        } 
     599 
     600        /// <summary> 
     601        /// Retrieves entropy from quick sources. 
     602        /// </summary> 
     603        private byte[] GetFastEntropy() 
     604        { 
     605            List<byte> result = new List<byte>(); 
     606 
     607            //Add the free disk space to the pool 
     608            result.AddRange(StructToBuffer(new DriveInfo(new DirectoryInfo(Environment.SystemDirectory). 
     609                Root.FullName).TotalFreeSpace)); 
     610 
     611            //Miscellaneous window handles 
     612            result.AddRange(StructToBuffer(UserAPI.GetCapture())); 
     613            result.AddRange(StructToBuffer(UserAPI.GetClipboardOwner())); 
     614            result.AddRange(StructToBuffer(UserAPI.GetClipboardViewer())); 
     615            result.AddRange(StructToBuffer(UserAPI.GetDesktopWindow())); 
     616            result.AddRange(StructToBuffer(UserAPI.GetForegroundWindow())); 
     617            result.AddRange(StructToBuffer(UserAPI.GetMessagePos())); 
     618            result.AddRange(StructToBuffer(UserAPI.GetMessageTime())); 
     619            result.AddRange(StructToBuffer(UserAPI.GetOpenClipboardWindow())); 
     620            result.AddRange(StructToBuffer(UserAPI.GetProcessWindowStation())); 
     621            result.AddRange(StructToBuffer(KernelAPI.GetCurrentProcessId())); 
     622            result.AddRange(StructToBuffer(KernelAPI.GetCurrentThreadId())); 
     623            result.AddRange(StructToBuffer(KernelAPI.GetProcessHeap())); 
     624 
     625            //The caret and cursor positions 
     626            UserAPI.POINT point; 
     627            UserAPI.GetCaretPos(out point); 
     628            result.AddRange(StructToBuffer(point)); 
     629            UserAPI.GetCursorPos(out point); 
     630            result.AddRange(StructToBuffer(point)); 
     631 
     632            //Amount of free memory 
     633            KernelAPI.MEMORYSTATUSEX memoryStatus = new KernelAPI.MEMORYSTATUSEX(); 
     634            memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus); 
     635            if (KernelAPI.GlobalMemoryStatusEx(ref memoryStatus)) 
     636            { 
     637                result.AddRange(StructToBuffer(memoryStatus.ullAvailPhys)); 
     638                result.AddRange(StructToBuffer(memoryStatus.ullAvailVirtual)); 
     639                result.AddRange(StructToBuffer(memoryStatus)); 
     640            } 
     641 
     642            //Thread execution times 
     643            long creationTime, exitTime, kernelTime, userTime; 
     644            if (KernelAPI.GetThreadTimes(KernelAPI.GetCurrentThread(), out creationTime, 
     645                out exitTime, out kernelTime, out userTime)) 
     646            { 
     647                result.AddRange(StructToBuffer(creationTime)); 
     648                result.AddRange(StructToBuffer(kernelTime)); 
     649                result.AddRange(StructToBuffer(userTime)); 
     650            } 
     651 
     652            //Process execution times 
     653            if (KernelAPI.GetProcessTimes(KernelAPI.GetCurrentProcess(), out creationTime, 
     654                out exitTime, out kernelTime, out userTime)) 
     655            { 
     656                result.AddRange(StructToBuffer(creationTime)); 
     657                result.AddRange(StructToBuffer(kernelTime)); 
     658                result.AddRange(StructToBuffer(userTime)); 
     659            } 
     660 
     661            //Current system time 
     662            result.AddRange(StructToBuffer(DateTime.Now.Ticks)); 
     663 
     664            //The high resolution performance counter 
     665            long perfCount = 0; 
     666            if (KernelAPI.QueryPerformanceCounter(out perfCount)) 
     667                result.AddRange(StructToBuffer(perfCount)); 
     668 
     669            //Ticks since start up 
     670            uint tickCount = KernelAPI.GetTickCount(); 
     671            if (tickCount != 0) 
     672                result.AddRange(StructToBuffer(tickCount)); 
     673 
     674            //CryptGenRandom 
     675            byte[] cryptGenRandom = new byte[160]; 
     676            if (CryptAPI.CryptGenRandom(cryptGenRandom)) 
     677                result.AddRange(cryptGenRandom); 
     678 
     679            return result.ToArray(); 
     680        } 
     681 
     682        /// <summary> 
     683        /// Retrieves entropy from sources which are relatively slower than those from 
     684        /// the FastAddEntropy function. 
     685        /// </summary> 
     686        private byte[] GetSlowEntropy() 
     687        { 
     688            List<byte> result = new List<byte>(); 
     689 
     690            //NetAPI statistics 
     691            unsafe 
     692            { 
     693                IntPtr netAPIStats = IntPtr.Zero; 
     694                if (NetAPI.NetStatisticsGet(null, NetAPI.SERVICE_WORKSTATION, 
     695                    0, 0, out netAPIStats) == 0) 
     696                { 
     697                    try 
     698                    { 
     699                        //Get the size of the buffer 
     700                        uint size = 0; 
     701                        NetAPI.NetApiBufferSize(netAPIStats, out size); 
     702                        byte[] entropy = new byte[size]; 
     703 
     704                        //Copy the buffer 
     705                        Marshal.Copy(entropy, 0, netAPIStats, entropy.Length); 
     706 
     707                        //And add it to the pool 
     708                        result.AddRange(entropy); 
     709                    } 
     710                    finally 
     711                    { 
     712                        //Free the statistics buffer 
     713                        NetAPI.NetApiBufferFree(netAPIStats); 
     714                    } 
     715                } 
     716            } 
     717 
     718#if false 
     719            //Get disk I/O statistics for all the hard drives 
     720            for (int drive = 0; ; ++drive) 
     721            { 
     722                //Try to open the drive. 
     723                using (SafeFileHandle hDevice = File.CreateFile( 
     724                    string.Format("\\\\.\\PhysicalDrive%d", drive), 0, 
     725                    File.FILE_SHARE_READ | File.FILE_SHARE_WRITE, IntPtr.Zero, 
     726                    File.OPEN_EXISTING, 0, IntPtr.Zero)) 
     727                { 
     728                    if (hDevice.IsInvalid) 
     729                        break; 
     730 
     731                    //This only works if the user has turned on the disk performance 
     732                    //counters with 'diskperf -y'. These counters are off by default 
     733                    if (File.DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, 
     734                        &diskPerformance, sizeof(DISK_PERFORMANCE), &uSize, NULL)) 
     735                    { 
     736                        addEntropy(&diskPerformance, uSize); 
     737                    } 
     738                } 
     739            } 
     740#endif 
     741 
     742            /* 
     743             Query performance data. Because the Win32 version of this API (through 
     744             registry) may be buggy, use the NT Native API instead. 
     745              
     746             Scan the first 64 possible information types (we don't bother 
     747             with increasing the buffer size as we do with the Win32 
     748             version of the performance data read, we may miss a few classes 
     749             but it's no big deal).  In addition the returned size value for 
     750             some classes is wrong (eg 23 and 24 return a size of 0) so we 
     751             miss a few more things, but again it's no big deal.  This scan 
     752             typically yields around 20 pieces of data, there's nothing in 
     753             the range 65...128 so chances are there won't be anything above 
     754             there either. 
     755            */ 
     756            uint dataWritten = 0; 
     757            byte[] infoBuffer = new byte[65536]; 
     758            uint totalEntropy = 0; 
     759            for (uint infoType = 0; infoType < 64; ++infoType) 
     760            { 
     761                uint sysInfo = NTAPI.NtQuerySystemInformation(infoType, infoBuffer, 
     762                    (uint)infoBuffer.Length, out dataWritten); 
     763 
     764                if (sysInfo == 0 /*ERROR_SUCCESS*/ && dataWritten > 0) 
     765                { 
     766                    byte[] entropy = new byte[dataWritten]; 
     767                    Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten); 
     768                    result.AddRange(entropy); 
     769                    totalEntropy += dataWritten; 
     770                } 
     771            } 
     772 
     773            result.AddRange(StructToBuffer(totalEntropy)); 
     774 
     775            //Finally, our good friend CryptGenRandom() 
     776            byte[] cryptGenRandom = new byte[1536]; 
     777            if (CryptAPI.CryptGenRandom(cryptGenRandom)) 
     778                result.AddRange(cryptGenRandom); 
     779 
     780            return result.ToArray(); 
     781        } 
    722782    } 
    723783} 
  • branches/eraser6/Util/Util.csproj

    r468 r479  
    33    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 
    44    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 
    5     <ProductVersion>8.0.50727</ProductVersion> 
     5    <ProductVersion>9.0.30729</ProductVersion> 
    66    <SchemaVersion>2.0</SchemaVersion> 
    77    <ProjectGuid>{D083E1A8-3A4C-4683-9B3F-D5FEDE61B9C9}</ProjectGuid> 
Note: See TracChangeset for help on using the changeset viewer.