source: branches/eraser6/Manager/EntropySource.cs @ 944

Revision 944, 21.3 KB checked in by lowjoel, 6 years ago (diff)

Fixed a few documentation inconsistencies and changed the event handler delegate types such that all event handlers use the EventArgs?<> generic.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By: Kasra Nassiri <cjax@users.sourceforge.net>
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25
26using System.Threading;
27using System.Security.Cryptography;
28using System.Runtime.InteropServices;
29using System.Diagnostics;
30using System.Reflection;
31using System.IO;
32using Microsoft.Win32.SafeHandles;
33using Eraser.Util;
34
35namespace Eraser.Manager
36{
37    /// <summary>
38    /// Provides an abstract interface to allow multiple sources of entropy into
39    /// the EntropyPoller class.
40    /// </summary>
41    public abstract class EntropySource
42    {
43        /// <summary>
44        /// Constructor.
45        /// </summary>
46        protected EntropySource()
47        {
48        }
49
50        /// <summary>
51        /// The name of the entropy source
52        /// </summary>
53        public abstract string Name
54        {
55            get;
56        }
57
58        /// <summary>
59        /// The guid representing this entropy source
60        /// </summary>
61        public abstract Guid Guid
62        {
63            get;
64        }
65
66        /// <summary>
67        /// Gets a primer to add to the pool when this source is first initialised, to
68        /// further add entropy to the pool.
69        /// </summary>
70        /// <returns>A byte array containing the entropy.</returns>
71        public abstract byte[] GetPrimer();
72
73        /// <summary>
74        /// Retrieve entropy from a source which will have slow rate of
75        /// entropy polling.
76        /// </summary>
77        /// <returns></returns>
78        public abstract byte[] GetSlowEntropy();
79
80        /// <summary>
81        /// Retrieve entropy from a soruce which will have a fast rate of
82        /// entropy polling.
83        /// </summary>
84        /// <returns></returns>
85        public abstract byte[] GetFastEntropy();
86
87        /// <summary>
88        /// Gets entropy from the entropy source. This will be called repetitively.
89        /// </summary>
90        /// <returns>A byte array containing the entropy, both slow rate and fast rate.</returns>
91        public abstract byte[] GetEntropy();
92
93        /// <summary>
94        /// Converts value types into a byte array. This is a helper function to allow
95        /// inherited classes to convert value types into byte arrays which can be
96        /// returned to the EntropyPoller class.
97        /// </summary>
98        /// <typeparam name="T">Any value type</typeparam>
99        /// <param name="entropy">A value which will be XORed with pool contents.</param>
100        protected unsafe static byte[] StructToBuffer<T>(T entropy) where T : struct
101        {
102            int sizeofObject = Marshal.SizeOf(entropy);
103            IntPtr memory = Marshal.AllocHGlobal(sizeofObject);
104            try
105            {
106                Marshal.StructureToPtr(entropy, memory, false);
107                byte[] dest = new byte[sizeofObject];
108
109                //Copy the memory
110                Marshal.Copy(memory, dest, 0, sizeofObject);
111                return dest;
112            }
113            finally
114            {
115                Marshal.FreeHGlobal(memory);
116            }
117        }
118    }
119
120    /// <summary>
121    /// A class which manages all of the instances of the EntropySources
122    /// available. Plugins could register their entropy sources via this class.
123    /// </summary>
124    public class EntropySourceManager
125    {
126        /// <summary>
127        /// Constructor.
128        /// </summary>
129        public EntropySourceManager()
130        {
131            entropyThread.AddEntropySource(new KernelEntropySource());
132        }
133
134        /// <summary>
135        /// Retrieves all currently registered erasure methods.
136        /// </summary>
137        /// <returns>A mutable list, with an instance of each EntropySource.</returns>
138        public static Dictionary<Guid, EntropySource> GetAll()
139        {
140            lock (ManagerLibrary.Instance.EntropySourceManager.sources)
141                return ManagerLibrary.Instance.EntropySourceManager.sources;
142        }
143
144        /// <summary>
145        /// Retrieves the instance of the EntropySource with the given GUID.
146        /// </summary>
147        /// <param name="value">The GUID of the EntropySource.</param>
148        /// <returns>The EntropySource instance.</returns>
149        public static EntropySource GetInstance(Guid value)
150        {
151            try
152            {
153                lock (ManagerLibrary.Instance.EntropySourceManager.sources)
154                    return ManagerLibrary.Instance.EntropySourceManager.sources[value];
155            }
156            catch (KeyNotFoundException)
157            {
158                throw new FatalException(S._("EntropySource GUID not found: {0}",
159                    value.ToString()));
160            }
161        }
162
163        /// <summary>
164        /// Allows plugins to register EntropySources with the main program. Thread-safe.
165        /// </summary>
166        /// <param name="source">The source of entropy to add.</param>
167        public static void Register(EntropySource source)
168        {
169            EntropySourceManager manager = ManagerLibrary.Instance.EntropySourceManager;
170            lock (ManagerLibrary.Instance.EntropySourceManager.sources)
171                manager.sources.Add(source.Guid, source);
172            manager.entropyThread.AddEntropySource(source);
173
174            OnEntropySourceRegistered(new EntropySourceRegistrationEventArgs(source.Guid));
175        }
176
177        /// <summary>
178        /// Calls the EntropySourceRegistered event handlers.
179        /// </summary>
180        private static void OnEntropySourceRegistered(EntropySourceRegistrationEventArgs e)
181        {
182            if (EntropySourceRegistered != null)
183                EntropySourceRegistered(ManagerLibrary.Instance.EntropySourceManager, e);
184        }
185
186        /// <summary>
187        /// Gets the entropy poller instance associated with this manager.
188        /// </summary>
189        public EntropyPoller Poller
190        {
191            get
192            {
193                return entropyThread;
194            }
195        }
196
197        /// <summary>
198        /// Global static instance of the EntropySourceRegisteredFunction,
199        /// called whenever the EntropySourceManager.Register is invoked.
200        /// </summary>
201        public static EventHandler<EntropySourceRegistrationEventArgs>
202            EntropySourceRegistered { get; set; }
203       
204        /// <summary>
205        /// The list of currently registered Entropy Sources.
206        /// </summary>
207        private Dictionary<Guid, EntropySource> sources = new Dictionary<Guid, EntropySource>();
208
209        /// <summary>
210        /// The entropy thread gathering entropy for the RNGs.
211        /// </summary>
212        private EntropyPoller entropyThread = new EntropyPoller();
213    };
214
215    public class EntropySourceRegistrationEventArgs : EventArgs
216    {
217        /// <summary>
218        /// Constructor.
219        /// </summary>
220        /// <param name="value">The GUID of the newly registered/unregistered entropy
221        /// source.</param>
222        public EntropySourceRegistrationEventArgs(Guid value)
223        {
224            Guid = value;
225        }
226
227        /// <summary>
228        /// The GUID of the newly registered/unregistered entropy source.
229        /// </summary>
230        public Guid Guid { get; private set; }
231    }
232       
233    /// <summary>
234    /// Provides means of generating random entropy from the system or user space
235    /// randomness.
236    /// This class is hardcoded into the Manager Library as we need at least one
237    /// instance of such behaviour within our system. The other classes could be
238    /// implemented as plugins, managed by EntropySourceManager.
239    /// </summary>
240    public class KernelEntropySource : EntropySource
241    {
242        public override byte[] GetPrimer()
243        {
244            List<byte> result = new List<byte>();
245
246            //Process startup information
247            KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO();
248            startupInfo.cbSize = (uint)Marshal.SizeOf(typeof(KernelAPI.STARTUPINFO));
249            KernelAPI.GetStartupInfo(out startupInfo);
250            result.AddRange(StructToBuffer(startupInfo));
251
252            //System information
253            KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO();
254            KernelAPI.GetSystemInfo(out systemInfo);
255            result.AddRange(StructToBuffer(systemInfo));
256
257            result.AddRange(GetFastEntropy());
258            result.AddRange(GetSlowEntropy());
259            return result.ToArray();
260        }
261
262        public override Guid Guid
263        {
264            get
265            {
266                return new Guid("{11EDCECF-AD81-4e50-A73D-B9CF1F813093}");
267            }
268        }
269
270        public override string Name
271        {
272            get
273            {
274                return "Kernel Entropy Source";
275            }
276        }
277
278        public override byte[] GetEntropy()
279        {
280            List<byte> result = new List<byte>();
281            result.AddRange(GetFastEntropy());
282            result.AddRange(GetSlowEntropy());
283
284            return result.ToArray();
285        }
286
287        /// <summary>
288        /// Retrieves entropy from quick sources.
289        /// </summary>
290        public override byte[] GetFastEntropy()
291        {
292            List<byte> result = new List<byte>();
293
294            //Add the free disk space to the pool
295            result.AddRange(StructToBuffer(new DriveInfo(new DirectoryInfo(Environment.SystemDirectory).
296                Root.FullName).TotalFreeSpace));
297
298            //Miscellaneous window handles
299            result.AddRange(StructToBuffer(UserAPI.GetCapture()));
300            result.AddRange(StructToBuffer(UserAPI.GetClipboardOwner()));
301            result.AddRange(StructToBuffer(UserAPI.GetClipboardViewer()));
302            result.AddRange(StructToBuffer(UserAPI.GetDesktopWindow()));
303            result.AddRange(StructToBuffer(UserAPI.GetForegroundWindow()));
304            result.AddRange(StructToBuffer(UserAPI.GetMessagePos()));
305            result.AddRange(StructToBuffer(UserAPI.GetMessageTime()));
306            result.AddRange(StructToBuffer(UserAPI.GetOpenClipboardWindow()));
307            result.AddRange(StructToBuffer(UserAPI.GetProcessWindowStation()));
308            result.AddRange(StructToBuffer(KernelAPI.GetCurrentProcessId()));
309            result.AddRange(StructToBuffer(KernelAPI.GetCurrentThreadId()));
310            result.AddRange(StructToBuffer(KernelAPI.GetProcessHeap()));
311
312            //The caret and cursor positions
313            UserAPI.POINT point;
314            UserAPI.GetCaretPos(out point);
315            result.AddRange(StructToBuffer(point));
316            UserAPI.GetCursorPos(out point);
317            result.AddRange(StructToBuffer(point));
318
319            //Amount of free memory
320            KernelAPI.MEMORYSTATUSEX memoryStatus = new KernelAPI.MEMORYSTATUSEX();
321            memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus);
322            if (KernelAPI.GlobalMemoryStatusEx(ref memoryStatus))
323            {
324                result.AddRange(StructToBuffer(memoryStatus.ullAvailPhys));
325                result.AddRange(StructToBuffer(memoryStatus.ullAvailVirtual));
326                result.AddRange(StructToBuffer(memoryStatus));
327            }
328
329            //Thread execution times
330            long creationTime, exitTime, kernelTime, userTime;
331            if (KernelAPI.GetThreadTimes(KernelAPI.GetCurrentThread(), out creationTime,
332                out exitTime, out kernelTime, out userTime))
333            {
334                result.AddRange(StructToBuffer(creationTime));
335                result.AddRange(StructToBuffer(kernelTime));
336                result.AddRange(StructToBuffer(userTime));
337            }
338
339            //Process execution times
340            if (KernelAPI.GetProcessTimes(KernelAPI.GetCurrentProcess(), out creationTime,
341                out exitTime, out kernelTime, out userTime))
342            {
343                result.AddRange(StructToBuffer(creationTime));
344                result.AddRange(StructToBuffer(kernelTime));
345                result.AddRange(StructToBuffer(userTime));
346            }
347
348            //Current system time
349            result.AddRange(StructToBuffer(DateTime.Now.Ticks));
350
351            //The high resolution performance counter
352            long perfCount = 0;
353            if (KernelAPI.QueryPerformanceCounter(out perfCount))
354                result.AddRange(StructToBuffer(perfCount));
355
356            //Ticks since start up
357            uint tickCount = KernelAPI.GetTickCount();
358            if (tickCount != 0)
359                result.AddRange(StructToBuffer(tickCount));
360
361            //CryptGenRandom
362            byte[] cryptGenRandom = new byte[160];
363            if (CryptAPI.CryptGenRandom(cryptGenRandom))
364                result.AddRange(cryptGenRandom);
365
366            return result.ToArray();
367        }
368
369        /// <summary>
370        /// Retrieves entropy from sources which are relatively slower than those from
371        /// the FastAddEntropy function.
372        /// </summary>
373        public override byte[] GetSlowEntropy()
374        {
375            List<byte> result = new List<byte>();
376
377            //NetAPI statistics
378            unsafe
379            {
380                IntPtr netAPIStats = IntPtr.Zero;
381                if (NetAPI.NetStatisticsGet(null, NetAPI.SERVICE_WORKSTATION,
382                    0, 0, out netAPIStats) == 0)
383                {
384                    try
385                    {
386                        //Get the size of the buffer
387                        uint size = 0;
388                        NetAPI.NetApiBufferSize(netAPIStats, out size);
389                        byte[] entropy = new byte[size];
390
391                        //Copy the buffer
392                        Marshal.Copy(entropy, 0, netAPIStats, entropy.Length);
393
394                        //And add it to the pool
395                        result.AddRange(entropy);
396                    }
397                    finally
398                    {
399                        //Free the statistics buffer
400                        NetAPI.NetApiBufferFree(netAPIStats);
401                    }
402                }
403            }
404
405#if false
406            //Get disk I/O statistics for all the hard drives
407            for (int drive = 0; ; ++drive)
408            {
409                //Try to open the drive.
410                using (SafeFileHandle hDevice = File.CreateFile(
411                    string.Format("\\\\.\\PhysicalDrive%d", drive), 0,
412                    File.FILE_SHARE_READ | File.FILE_SHARE_WRITE, IntPtr.Zero,
413                    File.OPEN_EXISTING, 0, IntPtr.Zero))
414                {
415                    if (hDevice.IsInvalid)
416                        break;
417
418                    //This only works if the user has turned on the disk performance
419                    //counters with 'diskperf -y'. These counters are off by default
420                    if (File.DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
421                        &diskPerformance, sizeof(DISK_PERFORMANCE), &uSize, NULL))
422                    {
423                        addEntropy(&diskPerformance, uSize);
424                    }
425                }
426            }
427#endif
428
429            /*
430             Query performance data. Because the Win32 version of this API (through
431             registry) may be buggy, use the NT Native API instead.
432             
433             Scan the first 64 possible information types (we don't bother
434             with increasing the buffer size as we do with the Win32
435             version of the performance data read, we may miss a few classes
436             but it's no big deal).  In addition the returned size value for
437             some classes is wrong (eg 23 and 24 return a size of 0) so we
438             miss a few more things, but again it's no big deal.  This scan
439             typically yields around 20 pieces of data, there's nothing in
440             the range 65...128 so chances are there won't be anything above
441             there either.
442            */
443            uint dataWritten = 0;
444            byte[] infoBuffer = new byte[65536];
445            uint totalEntropy = 0;
446            for (uint infoType = 0; infoType < 64; ++infoType)
447            {
448                uint sysInfo = NTAPI.NtQuerySystemInformation(infoType, infoBuffer,
449                    (uint)infoBuffer.Length, out dataWritten);
450
451                if (sysInfo == 0 /*ERROR_SUCCESS*/ && dataWritten > 0)
452                {
453                    byte[] entropy = new byte[dataWritten];
454                    Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten);
455                    result.AddRange(entropy);
456                    totalEntropy += dataWritten;
457                }
458            }
459
460            result.AddRange(StructToBuffer(totalEntropy));
461
462            //Finally, our good friend CryptGenRandom()
463            byte[] cryptGenRandom = new byte[1536];
464            if (CryptAPI.CryptGenRandom(cryptGenRandom))
465                result.AddRange(cryptGenRandom);
466
467            return result.ToArray();
468        }
469    }
470
471    /// <summary>
472    /// A class which uses EntropyPoll class to fetch system data as a source of
473    /// randomness at "regular" but "random" intervals
474    /// </summary>
475    public class EntropyPoller
476    {
477        /// <summary>
478        /// The algorithm used for mixing
479        /// </summary>
480        private enum PRFAlgorithms
481        {
482            MD5,
483            SHA1,
484            RIPEMD160,
485            SHA256,
486            SHA384,
487            SHA512,
488        };
489
490        /// <summary>
491        /// Constructor.
492        /// </summary>
493        public EntropyPoller()
494        {
495            //Create the pool.
496            pool = new byte[sizeof(uint) << 7];
497
498            //Then start the thread which maintains the pool.
499            Thread = new Thread(delegate()
500                {
501                    this.Main();
502                }
503            );
504            Thread.Start();
505        }
506
507        /// <summary>
508        /// The PRNG entropy thread. This thread will run in the background, getting
509        /// random data to be used for entropy. This will maintain the integrity
510        /// of generated data from the PRNGs.
511        /// </summary>
512        private void Main()
513        {
514            //This entropy thread will utilize a polling loop.
515            DateTime lastAddedEntropy = DateTime.Now;
516            TimeSpan managerEntropySpan = new TimeSpan(0, 10, 0);
517            Stopwatch st = new Stopwatch();
518
519            while (Thread.ThreadState != System.Threading.ThreadState.AbortRequested)
520            {
521                st.Start();
522                lock (EntropySources)
523                    foreach (EntropySource src in EntropySources)
524                    {
525                        byte[] entropy = src.GetEntropy();
526                        AddEntropy(entropy);
527                    }
528
529                st.Stop();
530                // 2049 = bin '100000000001' ==> great avalanche
531                Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L));
532                st.Reset();
533
534                // Send entropy to the PRNGs for new seeds.
535                if (DateTime.Now - lastAddedEntropy > managerEntropySpan)
536                    ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool());
537            }
538        }
539
540        /// <summary>
541        /// Stops the execution of the thread.
542        /// </summary>
543        public void Abort()
544        {
545            Thread.Abort();
546        }
547
548        /// <summary>
549        /// Adds a new Entropy Source to the Poller.
550        /// </summary>
551        /// <param name="source">The EntropySource object to add.</param>
552        public void AddEntropySource(EntropySource source)
553        {
554            lock (EntropySources)
555                EntropySources.Add(source);
556
557            AddEntropy(source.GetPrimer());
558            MixPool();
559
560            //Apply whitening effect
561            PRFAlgorithm = PRFAlgorithms.RIPEMD160;
562            MixPool();
563            PRFAlgorithm = PRFAlgorithms.SHA512;
564        }
565
566        /// <summary>
567        /// Retrieves the current contents of the entropy pool.
568        /// </summary>
569        /// <returns>A byte array containing all the randomness currently found.</returns>
570        public byte[] GetPool()
571        {
572            //Mix and invert the pool
573            MixPool();
574            InvertPool();
575
576            //Return a safe copy
577            lock (poolLock)
578            {
579                byte[] result = new byte[pool.Length];
580                pool.CopyTo(result, 0);
581
582                return result;
583            }
584        }
585
586        /// <summary>
587        /// Inverts the contents of the pool
588        /// </summary>
589        private void InvertPool()
590        {
591            lock (poolLock)
592                unsafe
593                {
594                    fixed (byte* fPool = pool)
595                    {
596                        uint* pPool = (uint*)fPool;
597                        uint poolLength = (uint)(pool.Length / sizeof(uint));
598                        while (poolLength-- != 0)
599                            *pPool = (uint)(*pPool++ ^ uint.MaxValue);
600                    }
601                }
602        }
603
604        /// <summary>
605        /// Mixes the contents of the pool.
606        /// </summary>
607        private void MixPool()
608        {
609            lock (poolLock)
610            {
611                //Mix the last 128 bytes first.
612                const int mixBlockSize = 128;
613                int hashSize = PRF.HashSize / 8;
614                PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0);
615
616                //Then mix the following bytes until wraparound is required
617                int i = 0;
618                for (; i < pool.Length - hashSize; i += hashSize)
619                    Buffer.BlockCopy(PRF.ComputeHash(pool, i,
620                        i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize),
621                        0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize);
622
623                //Mix the remaining blocks which require copying from the front
624                byte[] combinedBuffer = new byte[mixBlockSize];
625                for (; i < pool.Length; i += hashSize)
626                {
627                    Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i);
628
629                    Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i,
630                                mixBlockSize - (pool.Length - i));
631
632                    Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0,
633                        pool, i, pool.Length - i > hashSize ? hashSize : pool.Length - i);
634                }
635            }
636        }
637
638        /// <summary>
639        /// Adds data which is random to the pool
640        /// </summary>
641        /// <param name="entropy">An array of data which will be XORed with pool
642        /// contents.</param>
643        public unsafe void AddEntropy(byte[] entropy)
644        {
645            lock (poolLock)
646                fixed (byte* pEntropy = entropy)
647                fixed (byte* pPool = pool)
648                {
649                    int size = entropy.Length;
650                    byte* mpEntropy = pEntropy;
651                    while (size > 0)
652                    {
653                        //Bring the pool position back to the front if we are at our end
654                        if (poolPosition >= pool.Length)
655                            poolPosition = 0;
656
657                        int amountToMix = Math.Min(size, pool.Length - poolPosition);
658                        MemoryXor(pPool + poolPosition, mpEntropy, amountToMix);
659                        mpEntropy = mpEntropy + amountToMix;
660                        size -= amountToMix;
661                    }
662                }
663        }
664
665        /// <summary>
666        /// XOR's memory a DWORD at a time.
667        /// </summary>
668        /// <param name="destination">The destination buffer to be XOR'ed</param>
669        /// <param name="source">The source buffer to XOR with</param>
670        /// <param name="size">The size of the source buffer</param>
671        private static unsafe void MemoryXor(byte* destination, byte* source, int size)
672        {
673            // XXX: Further optomisation
674            // check the memory bus frame
675            // use BYTE / WORD / DWORD as required         
676           
677            int wsize = size / sizeof(uint);
678            size -= wsize * sizeof(uint);
679            uint* d = (uint*)destination;
680            uint* s = (uint*)source;
681
682            while (wsize-- > 0)
683                *d++ ^= *s++;
684
685            if (size > 0)
686            {
687                byte* db = (byte*)d,
688                      ds = (byte*)s;
689                while (size-- > 0)
690                    *db++ ^= *ds++;
691            }
692        }
693
694        /// <summary>
695        /// PRF algorithm handle
696        /// </summary>
697        private HashAlgorithm PRF
698        {
699            get
700            {
701                Type type = null;
702                switch (PRFAlgorithm)
703                {
704                    case PRFAlgorithms.MD5:
705                        type = typeof(MD5CryptoServiceProvider);
706                        break;
707                    case PRFAlgorithms.SHA1:
708                        type = typeof(SHA1Managed);
709                        break;
710                    case PRFAlgorithms.RIPEMD160:
711                        type = typeof(RIPEMD160Managed);
712                        break;
713                    case PRFAlgorithms.SHA256:
714                        type = typeof(SHA256Managed);
715                        break;
716                    case PRFAlgorithms.SHA384:
717                        type = typeof(SHA384Managed);
718                        break;
719                    default:
720                        type = typeof(SHA512Managed);
721                        break;
722                }
723
724                if (type.IsInstanceOfType(prfCache))
725                    return prfCache;
726                ConstructorInfo hashConstructor = type.GetConstructor(Type.EmptyTypes);
727                return prfCache = (HashAlgorithm)hashConstructor.Invoke(null);
728            }
729        }
730
731        /// <summary>
732        /// The last created PRF algorithm handle.
733        /// </summary>
734        private HashAlgorithm prfCache;
735
736        /// <summary>
737        /// PRF algorithm identifier
738        /// </summary>
739        private PRFAlgorithms PRFAlgorithm = PRFAlgorithms.SHA512;
740
741        /// <summary>
742        /// The pool of data which we currently maintain.
743        /// </summary>
744        private byte[] pool;
745
746        /// <summary>
747        /// The next position where entropy will be added to the pool.
748        /// </summary>
749        private int poolPosition;
750
751        /// <summary>
752        /// The lock guarding the pool array and the current entropy addition index.
753        /// </summary>
754        private object poolLock = new object();
755
756        /// <summary>
757        /// The thread object.
758        /// </summary>
759        private Thread Thread;
760
761        /// <summary>
762        /// The list of entropy sources registered with the Poller.
763        /// </summary>
764        private List<EntropySource> EntropySources = new List<EntropySource>();
765    }
766}
Note: See TracBrowser for help on using the repository browser.