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 | * Modified By: |
---|
7 | * |
---|
8 | * This file is part of Eraser. |
---|
9 | * |
---|
10 | * Eraser is free software: you can redistribute it and/or modify it under the |
---|
11 | * terms of the GNU General Public License as published by the Free Software |
---|
12 | * Foundation, either version 3 of the License, or (at your option) any later |
---|
13 | * version. |
---|
14 | * |
---|
15 | * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY |
---|
16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
---|
17 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
---|
18 | * |
---|
19 | * A copy of the GNU General Public License can be found at |
---|
20 | * <http://www.gnu.org/licenses/>. |
---|
21 | */ |
---|
22 | |
---|
23 | using System; |
---|
24 | using System.Collections.Generic; |
---|
25 | using System.Text; |
---|
26 | |
---|
27 | using System.Threading; |
---|
28 | using System.Security.Cryptography; |
---|
29 | using System.Runtime.InteropServices; |
---|
30 | using System.Diagnostics; |
---|
31 | using System.Reflection; |
---|
32 | using System.IO; |
---|
33 | using Microsoft.Win32.SafeHandles; |
---|
34 | using Eraser.Util; |
---|
35 | |
---|
36 | namespace Eraser.Manager |
---|
37 | { |
---|
38 | /// <summary> |
---|
39 | /// An interface class for all pseudorandom number generators used for the |
---|
40 | /// random data erase passes. |
---|
41 | /// </summary> |
---|
42 | public abstract class Prng |
---|
43 | { |
---|
44 | public override string ToString() |
---|
45 | { |
---|
46 | return Name; |
---|
47 | } |
---|
48 | |
---|
49 | /// <summary> |
---|
50 | /// The name of this erase pass, used for display in the UI |
---|
51 | /// </summary> |
---|
52 | public abstract string Name |
---|
53 | { |
---|
54 | get; |
---|
55 | } |
---|
56 | |
---|
57 | /// <summary> |
---|
58 | /// The GUID for this PRNG. |
---|
59 | /// </summary> |
---|
60 | public abstract Guid Guid |
---|
61 | { |
---|
62 | get; |
---|
63 | } |
---|
64 | |
---|
65 | /// <summary> |
---|
66 | /// Reseeds the PRNG. This can be called by inherited classes, but its most |
---|
67 | /// important function is to provide new seeds regularly. The PRNGManager |
---|
68 | /// will call this function once in a whle to maintain the quality of |
---|
69 | /// generated numbers. |
---|
70 | /// </summary> |
---|
71 | /// <param name="seed">An arbitrary length of information that will be |
---|
72 | /// used to reseed the PRNG</param> |
---|
73 | protected internal abstract void Reseed(byte[] seed); |
---|
74 | |
---|
75 | #region Random members |
---|
76 | /// <summary> |
---|
77 | /// Returns a nonnegative random number less than the specified maximum. |
---|
78 | /// </summary> |
---|
79 | /// <param name="maxValue">The exclusive upper bound of the random number |
---|
80 | /// to be generated. maxValue must be greater than or equal to zero.</param> |
---|
81 | /// <returns>A 32-bit signed integer greater than or equal to zero, and |
---|
82 | /// less than maxValue; that is, the range of return values ordinarily |
---|
83 | /// includes zero but not maxValue. However, if maxValue equals zero, |
---|
84 | /// maxValue is returned.</returns> |
---|
85 | public int Next(int maxValue) |
---|
86 | { |
---|
87 | if (maxValue == 0) |
---|
88 | return 0; |
---|
89 | return Next() % maxValue; |
---|
90 | } |
---|
91 | |
---|
92 | /// <summary> |
---|
93 | /// Returns a random number within a specified range. |
---|
94 | /// </summary> |
---|
95 | /// <param name="minValue">The inclusive lower bound of the random number |
---|
96 | /// returned.</param> |
---|
97 | /// <param name="maxValue">The exclusive upper bound of the random number |
---|
98 | /// returned. maxValue must be greater than or equal to minValue.</param> |
---|
99 | /// <returns>A 32-bit signed integer greater than or equal to minValue and |
---|
100 | /// less than maxValue; that is, the range of return values includes minValue |
---|
101 | /// but not maxValue. If minValue equals maxValue, minValue is returned.</returns> |
---|
102 | public int Next(int minValue, int maxValue) |
---|
103 | { |
---|
104 | if (minValue > maxValue) |
---|
105 | throw new ArgumentOutOfRangeException("minValue", minValue, |
---|
106 | S._("minValue is greater than maxValue")); |
---|
107 | else if (minValue == maxValue) |
---|
108 | return minValue; |
---|
109 | return (Next() % (maxValue - minValue)) + minValue; |
---|
110 | } |
---|
111 | |
---|
112 | /// <summary> |
---|
113 | /// Returns a nonnegative random number. |
---|
114 | /// </summary> |
---|
115 | /// <returns>A 32-bit signed integer greater than or equal to zero and less |
---|
116 | /// than System.Int32.MaxValue.</returns> |
---|
117 | public unsafe int Next() |
---|
118 | { |
---|
119 | //Declare a return variable |
---|
120 | int result; |
---|
121 | int* fResult = &result; |
---|
122 | |
---|
123 | //Get the random-valued bytes to fill the int. |
---|
124 | byte[] rand = new byte[sizeof(int)]; |
---|
125 | NextBytes(rand); |
---|
126 | |
---|
127 | //Copy the random buffer into the int. |
---|
128 | fixed (byte* fRand = rand) |
---|
129 | { |
---|
130 | byte* pResult = (byte*)fResult; |
---|
131 | byte* pRand = fRand; |
---|
132 | for (int i = 0; i != sizeof(int); ++i) |
---|
133 | *pResult++ = *pRand++; |
---|
134 | } |
---|
135 | |
---|
136 | return Math.Abs(result); |
---|
137 | } |
---|
138 | |
---|
139 | /// <summary> |
---|
140 | /// Fills the elements of a specified array of bytes with random numbers. |
---|
141 | /// </summary> |
---|
142 | /// <param name="buffer">An array of bytes to contain random numbers.</param> |
---|
143 | public abstract void NextBytes(byte[] buffer); |
---|
144 | #endregion |
---|
145 | } |
---|
146 | |
---|
147 | /// <summary> |
---|
148 | /// Class managing all the PRNG algorithms. |
---|
149 | /// </summary> |
---|
150 | public class PrngManager |
---|
151 | { |
---|
152 | /// <summary> |
---|
153 | /// Constructor. |
---|
154 | /// </summary> |
---|
155 | public PrngManager() |
---|
156 | { |
---|
157 | } |
---|
158 | |
---|
159 | /// <summary> |
---|
160 | /// Retrieves all currently registered erasure methods. |
---|
161 | /// </summary> |
---|
162 | /// <returns>A mutable list, with an instance of each PRNG.</returns> |
---|
163 | public static Dictionary<Guid, Prng> GetAll() |
---|
164 | { |
---|
165 | lock (ManagerLibrary.Instance.PRNGManager.prngs) |
---|
166 | return ManagerLibrary.Instance.PRNGManager.prngs; |
---|
167 | } |
---|
168 | |
---|
169 | /// <summary> |
---|
170 | /// Retrieves the instance of the PRNG with the given GUID. |
---|
171 | /// </summary> |
---|
172 | /// <param name="guid">The GUID of the PRNG.</param> |
---|
173 | /// <returns>The PRNG instance.</returns> |
---|
174 | public static Prng GetInstance(Guid guid) |
---|
175 | { |
---|
176 | try |
---|
177 | { |
---|
178 | lock (ManagerLibrary.Instance.PRNGManager.prngs) |
---|
179 | return ManagerLibrary.Instance.PRNGManager.prngs[guid]; |
---|
180 | } |
---|
181 | catch (KeyNotFoundException) |
---|
182 | { |
---|
183 | throw new FatalException(S._("PRNG not found: {0}", guid.ToString())); |
---|
184 | } |
---|
185 | } |
---|
186 | |
---|
187 | /// <summary> |
---|
188 | /// Allows plug-ins to register PRNGs with the main program. Thread-safe. |
---|
189 | /// </summary> |
---|
190 | /// <param name="method"></param> |
---|
191 | public static void Register(Prng prng) |
---|
192 | { |
---|
193 | lock (ManagerLibrary.Instance.PRNGManager.prngs) |
---|
194 | ManagerLibrary.Instance.PRNGManager.prngs.Add(prng.Guid, prng); |
---|
195 | } |
---|
196 | |
---|
197 | /// <summary> |
---|
198 | /// Allows the EntropyThread to get entropy to the PRNG functions as seeds. |
---|
199 | /// </summary> |
---|
200 | /// <param name="entropy">An array of bytes, being entropy for the PRNG.</param> |
---|
201 | internal void AddEntropy(byte[] entropy) |
---|
202 | { |
---|
203 | lock (ManagerLibrary.Instance.PRNGManager.prngs) |
---|
204 | foreach (Prng prng in prngs.Values) |
---|
205 | prng.Reseed(entropy); |
---|
206 | } |
---|
207 | |
---|
208 | /// <summary> |
---|
209 | /// Gets entropy from the EntropyThread. |
---|
210 | /// </summary> |
---|
211 | /// <returns>A buffer of arbitrary length containing random information.</returns> |
---|
212 | public static byte[] GetEntropy() |
---|
213 | { |
---|
214 | return ManagerLibrary.Instance.EntropySourceManager.Poller.GetPool(); |
---|
215 | } |
---|
216 | |
---|
217 | /// <summary> |
---|
218 | /// The list of currently registered erasure methods. |
---|
219 | /// </summary> |
---|
220 | private Dictionary<Guid, Prng> prngs = new Dictionary<Guid, Prng>(); |
---|
221 | } |
---|
222 | } |
---|