Deprecate Entropy (leaving platform sources alone)
Also introduces unavoidable breaking change in EntropySource interface: poll() returns Option!ubyte instead of Nullable.
This commit is contained in:
		| @@ -15,10 +15,11 @@ | ||||
| module tanya.math.random; | ||||
|  | ||||
| import std.digest.sha; | ||||
| import std.typecons; | ||||
| import tanya.memory; | ||||
| import tanya.typecons; | ||||
|  | ||||
| /// Block size of entropy accumulator (SHA-512). | ||||
| deprecated | ||||
| enum blockSize = 64; | ||||
|  | ||||
| /// Maximum amount gathered from the entropy sources. | ||||
| @@ -39,7 +40,7 @@ class EntropyException : Exception | ||||
|     this(string msg, | ||||
|          string file = __FILE__, | ||||
|          size_t line = __LINE__, | ||||
|          Throwable next = null) pure @safe nothrow const @nogc | ||||
|          Throwable next = null) const @nogc nothrow pure @safe | ||||
|     { | ||||
|         super(msg, file, line, next); | ||||
|     } | ||||
| @@ -56,17 +57,17 @@ abstract class EntropySource | ||||
|     /** | ||||
|      * Returns: Minimum bytes required from the entropy source. | ||||
|      */ | ||||
|     @property ubyte threshold() const pure nothrow @safe @nogc; | ||||
|     @property ubyte threshold() const @nogc nothrow pure @safe; | ||||
|  | ||||
|     /** | ||||
|      * Returns: Whether this entropy source is strong. | ||||
|      */ | ||||
|     @property bool strong() const pure nothrow @safe @nogc; | ||||
|     @property bool strong() const @nogc nothrow pure @safe; | ||||
|  | ||||
|     /** | ||||
|      * Returns: Amount of already generated entropy. | ||||
|      */ | ||||
|     @property ushort size() const pure nothrow @safe @nogc | ||||
|     @property ushort size() const @nogc nothrow pure @safe | ||||
|     { | ||||
|         return size_; | ||||
|     } | ||||
| @@ -76,7 +77,7 @@ abstract class EntropySource | ||||
|      *  size = Amount of already generated entropy. Cannot be smaller than the | ||||
|      *         already set value. | ||||
|      */ | ||||
|     @property void size(ushort size) pure nothrow @safe @nogc | ||||
|     @property void size(ushort size) @nogc nothrow pure @safe | ||||
|     { | ||||
|         size_ = size; | ||||
|     } | ||||
| @@ -89,9 +90,13 @@ abstract class EntropySource | ||||
|      *           to fill the buffer). | ||||
|      * | ||||
|      * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|      *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|      *          or nothing on error. | ||||
|      * | ||||
|      * Postcondition: Returned length is less than or equal to | ||||
|      *                $(D_PARAM output) length. | ||||
|      */ | ||||
|     Nullable!ubyte poll(out ubyte[maxGather] output) @nogc; | ||||
|     Option!ubyte poll(out ubyte[maxGather] output) @nogc | ||||
|     out (length; length.isNothing || length.get <= maxGather); | ||||
| } | ||||
|  | ||||
| version (CRuntime_Bionic) | ||||
| @@ -118,7 +123,7 @@ else version (Solaris) | ||||
| version (linux) | ||||
| { | ||||
|     import core.stdc.config : c_long; | ||||
|     extern (C) c_long syscall(c_long number, ...) nothrow @system @nogc; | ||||
|     private extern(C) c_long syscall(c_long number, ...) @nogc nothrow @system; | ||||
|  | ||||
|     /** | ||||
|      * Uses getrandom system call. | ||||
| @@ -128,7 +133,7 @@ version (linux) | ||||
|         /** | ||||
|          * Returns: Minimum bytes required from the entropy source. | ||||
|          */ | ||||
|         override @property ubyte threshold() const pure nothrow @safe @nogc | ||||
|         override @property ubyte threshold() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return 32; | ||||
|         } | ||||
| @@ -136,7 +141,7 @@ version (linux) | ||||
|         /** | ||||
|          * Returns: Whether this entropy source is strong. | ||||
|          */ | ||||
|         override @property bool strong() const pure nothrow @safe @nogc | ||||
|         override @property bool strong() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
| @@ -149,19 +154,14 @@ version (linux) | ||||
|          *           to fill the buffer). | ||||
|          * | ||||
|          * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|          *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|          *          or nothing on error. | ||||
|          */ | ||||
|         override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow @nogc | ||||
|         out (length) | ||||
|         { | ||||
|             assert(length <= maxGather); | ||||
|         } | ||||
|         do | ||||
|         override Option!ubyte poll(out ubyte[maxGather] output) @nogc nothrow | ||||
|         { | ||||
|             // int getrandom(void *buf, size_t buflen, unsigned int flags); | ||||
|             import mir.linux._asm.unistd : NR_getrandom; | ||||
|             auto length = syscall(NR_getrandom, output.ptr, output.length, 0); | ||||
|             Nullable!ubyte ret; | ||||
|             Option!ubyte ret; | ||||
|  | ||||
|             if (length >= 0) | ||||
|             { | ||||
| @@ -170,19 +170,11 @@ version (linux) | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @nogc @system unittest | ||||
|     { | ||||
|         auto entropy = defaultAllocator.make!Entropy(); | ||||
|         ubyte[blockSize] output; | ||||
|         output = entropy.random; | ||||
|  | ||||
|         defaultAllocator.dispose(entropy); | ||||
|     } | ||||
| } | ||||
| else version (SecureARC4Random) | ||||
| { | ||||
|     private extern (C) void arc4random_buf(scope void* buf, size_t nbytes) nothrow @nogc @system; | ||||
|     private extern(C) void arc4random_buf(scope void* buf, size_t nbytes) | ||||
|     @nogc nothrow @system; | ||||
|  | ||||
|     /** | ||||
|      * Uses arc4random_buf. | ||||
| @@ -192,7 +184,7 @@ else version (SecureARC4Random) | ||||
|         /** | ||||
|          * Returns: Minimum bytes required from the entropy source. | ||||
|          */ | ||||
|         override @property ubyte threshold() const pure nothrow @safe @nogc | ||||
|         override @property ubyte threshold() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return 32; | ||||
|         } | ||||
| @@ -200,7 +192,7 @@ else version (SecureARC4Random) | ||||
|         /** | ||||
|          * Returns: Whether this entropy source is strong. | ||||
|          */ | ||||
|         override @property bool strong() const pure nothrow @safe @nogc | ||||
|         override @property bool strong() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
| @@ -213,23 +205,15 @@ else version (SecureARC4Random) | ||||
|          *           to fill the buffer). | ||||
|          * | ||||
|          * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|          *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|          *          or nothing on error. | ||||
|          */ | ||||
|         override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow @nogc @safe | ||||
|         override Option!ubyte poll(out ubyte[maxGather] output) | ||||
|         @nogc nothrow @safe | ||||
|         { | ||||
|             (() @trusted => arc4random_buf(output.ptr, output.length))(); | ||||
|             return Nullable!ubyte(cast(ubyte) (output.length)); | ||||
|             return Option!ubyte(cast(ubyte) (output.length)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @nogc @system unittest | ||||
|     { | ||||
|         auto entropy = defaultAllocator.make!Entropy(); | ||||
|         ubyte[blockSize] output; | ||||
|         output = entropy.random; | ||||
|  | ||||
|         defaultAllocator.dispose(entropy); | ||||
|     } | ||||
| } | ||||
| else version (Windows) | ||||
| { | ||||
| @@ -248,22 +232,31 @@ else version (Windows) | ||||
|         BOOL CryptReleaseContext(HCRYPTPROV, ULONG_PTR); | ||||
|     } | ||||
|  | ||||
|     private bool initCryptGenRandom(scope ref HCRYPTPROV hProvider) @nogc nothrow @trusted | ||||
|     private bool initCryptGenRandom(scope ref HCRYPTPROV hProvider) | ||||
|     @nogc nothrow @trusted | ||||
|     { | ||||
|         // https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx | ||||
|         // For performance reasons, we recommend that you set the pszContainer | ||||
|         // parameter to NULL and the dwFlags parameter to CRYPT_VERIFYCONTEXT | ||||
|         // in all situations where you do not require a persisted key. | ||||
|         // CRYPT_SILENT is intended for use with applications for which the UI cannot be displayed by the CSP. | ||||
|         if (!CryptAcquireContextW(&hProvider, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) | ||||
|         // CRYPT_SILENT is intended for use with applications for which the UI | ||||
|         // cannot be displayed by the CSP. | ||||
|         if (!CryptAcquireContextW(&hProvider, | ||||
|                                   null, | ||||
|                                   null, | ||||
|                                   PROV_RSA_FULL, | ||||
|                                   CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) | ||||
|         { | ||||
|             if (GetLastError() == NTE_BAD_KEYSET) | ||||
|             if (GetLastError() != NTE_BAD_KEYSET) | ||||
|             { | ||||
|                 // Attempt to create default container | ||||
|                 if (!CryptAcquireContextA(&hProvider, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT)) | ||||
|                     return false; | ||||
|                 return false; | ||||
|             } | ||||
|             else | ||||
|             // Attempt to create default container | ||||
|             if (!CryptAcquireContextA(&hProvider, | ||||
|                                       null, | ||||
|                                       null, | ||||
|                                       PROV_RSA_FULL, | ||||
|                                       CRYPT_NEWKEYSET | CRYPT_SILENT)) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
| @@ -299,7 +292,7 @@ else version (Windows) | ||||
|         /** | ||||
|          * Returns: Minimum bytes required from the entropy source. | ||||
|          */ | ||||
|         override @property ubyte threshold() const pure nothrow @safe @nogc | ||||
|         override @property ubyte threshold() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return 32; | ||||
|         } | ||||
| @@ -307,7 +300,7 @@ else version (Windows) | ||||
|         /** | ||||
|          * Returns: Whether this entropy source is strong. | ||||
|          */ | ||||
|         override @property bool strong() const pure nothrow @safe @nogc | ||||
|         override @property bool strong() const @nogc nothrow pure @safe | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
| @@ -320,16 +313,14 @@ else version (Windows) | ||||
|          *           to fill the buffer). | ||||
|          * | ||||
|          * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|          *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|          *          or nothing on error. | ||||
|          */ | ||||
|         override Nullable!ubyte poll(out ubyte[maxGather] output) @nogc nothrow @safe | ||||
|         in | ||||
|         override Option!ubyte poll(out ubyte[maxGather] output) | ||||
|         @nogc nothrow @safe | ||||
|         { | ||||
|             assert(hProvider > 0, "hProvider not properly initialized."); | ||||
|         } | ||||
|         do | ||||
|         { | ||||
|             Nullable!ubyte ret; | ||||
|             Option!ubyte ret; | ||||
|  | ||||
|             assert(hProvider > 0, "hProvider not properly initialized"); | ||||
|             if ((() @trusted => CryptGenRandom(hProvider, output.length, cast(PBYTE) output.ptr))()) | ||||
|             { | ||||
|                 ret = cast(ubyte) (output.length); | ||||
| @@ -337,15 +328,16 @@ else version (Windows) | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     @nogc @system unittest | ||||
|     { | ||||
|         auto entropy = defaultAllocator.make!Entropy(); | ||||
|         ubyte[blockSize] output; | ||||
|         output = entropy.random; | ||||
| static if (is(PlatformEntropySource)) @nogc @system unittest | ||||
| { | ||||
|     import tanya.memory.smartref : unique; | ||||
|  | ||||
|         defaultAllocator.dispose(entropy); | ||||
|     } | ||||
|     auto source = defaultAllocator.unique!PlatformEntropySource(); | ||||
|  | ||||
|     assert(source.threshold == 32); | ||||
|     assert(source.strong); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -360,6 +352,7 @@ else version (Windows) | ||||
|  * defaultAllocator.dispose(entropy); | ||||
|  * --- | ||||
|  */ | ||||
| deprecated | ||||
| class Entropy | ||||
| { | ||||
|     /// Entropy sources. | ||||
| @@ -396,7 +389,7 @@ class Entropy | ||||
|     /** | ||||
|      * Returns: Amount of the registered entropy sources. | ||||
|      */ | ||||
|     @property ubyte sourceCount() const pure nothrow @safe @nogc | ||||
|     @property ubyte sourceCount() const @nogc nothrow pure @safe | ||||
|     { | ||||
|         return sourceCount_; | ||||
|     } | ||||
| @@ -413,7 +406,7 @@ class Entropy | ||||
|      *  $(D_PSYMBOL EntropySource) | ||||
|      */ | ||||
|     Entropy opOpAssign(string op)(EntropySource source) | ||||
|     pure nothrow @safe @nogc | ||||
|     @nogc nothrow pure @safe | ||||
|     if (op == "~") | ||||
|     in | ||||
|     { | ||||
| @@ -451,7 +444,7 @@ class Entropy | ||||
|             { | ||||
|                 auto outputLength = sources[i].poll(buffer); | ||||
|  | ||||
|                 if (!outputLength.isNull) | ||||
|                 if (!outputLength.isNothing) | ||||
|                 { | ||||
|                     if (outputLength > 0) | ||||
|                     { | ||||
| @@ -502,7 +495,7 @@ class Entropy | ||||
|      */ | ||||
|     protected void update(in ubyte sourceId, | ||||
|                           ref ubyte[maxGather] data, | ||||
|                           ubyte length) pure nothrow @safe @nogc | ||||
|                           ubyte length) @nogc nothrow pure @safe | ||||
|     { | ||||
|         ubyte[2] header; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user