mirror of
https://github.com/Stone-Red-Code/RemSox.git
synced 2026-09-04 00:56:19 +02:00
Reorganize project structure
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
using Cosmos.Build.API.Attributes;
|
||||
|
||||
namespace RemSox.Kernel.Plugs;
|
||||
|
||||
[Plug("System.Security.Cryptography.RandomNumberGeneratorImplementation")]
|
||||
/// <summary>
|
||||
/// Cryptographic stream generator based on ChaCha20.
|
||||
/// Initial entropy is limited at boot; depends on hardware events (mouse & keyboard)
|
||||
/// </summary>
|
||||
public static unsafe class RandomNumberGeneratorImplementationImpl
|
||||
{
|
||||
private static readonly uint[] key = new uint[8];
|
||||
private static readonly uint[] counter = new uint[4];
|
||||
private static readonly uint[] state = new uint[16];
|
||||
|
||||
private static ulong e0, e1, e2, e3;
|
||||
private static int entropyCounter;
|
||||
private static bool initialized = false;
|
||||
|
||||
private static readonly uint[] constants = [
|
||||
0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
|
||||
];
|
||||
|
||||
private static uint RotL(uint x, int n)
|
||||
{
|
||||
return (x << n) | (x >> (32 - n));
|
||||
}
|
||||
|
||||
private static void QR(ref uint a, ref uint b, ref uint c, ref uint d)
|
||||
{
|
||||
a += b; d ^= a; d = RotL(d, 16);
|
||||
c += d; b ^= c; b = RotL(b, 12);
|
||||
a += b; d ^= a; d = RotL(d, 8);
|
||||
c += d; b ^= c; b = RotL(b, 7);
|
||||
}
|
||||
|
||||
private static void ChaChaBlock(uint[] output)
|
||||
{
|
||||
uint[] x = new uint[16];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
x[i] = constants[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
x[4 + i] = key[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
x[12 + i] = counter[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
state[i] = x[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
QR(ref x[0], ref x[4], ref x[8], ref x[12]);
|
||||
QR(ref x[1], ref x[5], ref x[9], ref x[13]);
|
||||
QR(ref x[2], ref x[6], ref x[10], ref x[14]);
|
||||
QR(ref x[3], ref x[7], ref x[11], ref x[15]);
|
||||
|
||||
QR(ref x[0], ref x[5], ref x[10], ref x[15]);
|
||||
QR(ref x[1], ref x[6], ref x[11], ref x[12]);
|
||||
QR(ref x[2], ref x[7], ref x[8], ref x[13]);
|
||||
QR(ref x[3], ref x[4], ref x[9], ref x[14]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
output[i] = x[i] + state[i];
|
||||
}
|
||||
|
||||
counter[0]++;
|
||||
if (counter[0] == 0)
|
||||
{
|
||||
counter[1]++;
|
||||
if (counter[1] == 0)
|
||||
{
|
||||
counter[2]++;
|
||||
if (counter[2] == 0)
|
||||
{
|
||||
counter[3]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Mix(ulong v)
|
||||
{
|
||||
e0 ^= v;
|
||||
e0 *= 0x9E3779B97F4A7C15UL;
|
||||
e1 ^= e0 ^ (e0 >> 30);
|
||||
e1 *= 0xBF58476D1CE4E5B9UL;
|
||||
e2 ^= e1 ^ (e1 >> 27);
|
||||
e2 *= 0x94D049BB133111EBUL;
|
||||
e3 ^= e2 ^ (e2 >> 31);
|
||||
}
|
||||
|
||||
private static void Reseed()
|
||||
{
|
||||
key[0] ^= (uint)e0; key[1] ^= (uint)(e0 >> 32);
|
||||
key[2] ^= (uint)e1; key[3] ^= (uint)(e1 >> 32);
|
||||
key[4] ^= (uint)e2; key[5] ^= (uint)(e2 >> 32);
|
||||
key[6] ^= (uint)e3; key[7] ^= (uint)(e3 >> 32);
|
||||
|
||||
counter[0] ^= (uint)(e0 >> 16);
|
||||
counter[1] ^= (uint)(e1 >> 16);
|
||||
counter[2] ^= (uint)(e2 >> 16);
|
||||
counter[3] ^= (uint)(e3 >> 16);
|
||||
|
||||
e0 = 0; e1 = 0; e2 = 0; e3 = 0;
|
||||
|
||||
bufferIndex = 16;
|
||||
}
|
||||
|
||||
private static void MaybeReseed()
|
||||
{
|
||||
if (++entropyCounter % 64 == 0)
|
||||
{
|
||||
Reseed();
|
||||
}
|
||||
}
|
||||
|
||||
private static ulong ReadTSC()
|
||||
{
|
||||
return (ulong)Environment.TickCount;
|
||||
}
|
||||
|
||||
private static void EnsureInitialized()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
||||
const ulong BUILD_NONCE = 0xDEADBEEFCAFEBABEUL;
|
||||
|
||||
ulong heapBits;
|
||||
fixed (byte* p = new byte[1])
|
||||
{
|
||||
heapBits = (ulong)p;
|
||||
}
|
||||
|
||||
Mix(BUILD_NONCE);
|
||||
Mix(ReadTSC());
|
||||
Mix(heapBits);
|
||||
Mix(ReadTSC() ^ (heapBits << 17));
|
||||
|
||||
Reseed();
|
||||
}
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
|
||||
private static readonly uint[] buffer = new uint[16];
|
||||
private static int bufferIndex = 16;
|
||||
|
||||
private static uint NextUInt32()
|
||||
{
|
||||
EnsureInitialized();
|
||||
|
||||
if (bufferIndex >= 16)
|
||||
{
|
||||
ChaChaBlock(buffer);
|
||||
bufferIndex = 0;
|
||||
|
||||
key[0] ^= buffer[0];
|
||||
key[1] ^= buffer[1];
|
||||
key[2] ^= buffer[2];
|
||||
key[3] ^= buffer[3];
|
||||
key[4] ^= buffer[4];
|
||||
key[5] ^= buffer[5];
|
||||
key[6] ^= buffer[6];
|
||||
key[7] ^= buffer[7];
|
||||
|
||||
ChaChaBlock(buffer);
|
||||
}
|
||||
|
||||
return buffer[bufferIndex++];
|
||||
}
|
||||
|
||||
private static int byteShift = 0;
|
||||
private static uint byteWord = 0;
|
||||
|
||||
private static byte NextByte()
|
||||
{
|
||||
if (byteShift == 0)
|
||||
{
|
||||
byteWord = NextUInt32();
|
||||
byteShift = 32;
|
||||
}
|
||||
|
||||
byteShift -= 8;
|
||||
return (byte)(byteWord >> byteShift);
|
||||
}
|
||||
|
||||
public static void AddMouseEntropy(int dx, int dy, int dz, int x, int y)
|
||||
{
|
||||
ulong tsc = ReadTSC();
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
Mix((ulong)dx);
|
||||
Mix((ulong)dy);
|
||||
Mix((ulong)dz);
|
||||
Mix((ulong)x ^ ((ulong)y << 32));
|
||||
Mix(tsc);
|
||||
MaybeReseed();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddKeyboardEntropy(uint scanCode, uint flags, char keyChar)
|
||||
{
|
||||
ulong tsc = ReadTSC();
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
Mix(scanCode);
|
||||
Mix(flags);
|
||||
Mix(keyChar);
|
||||
Mix(tsc);
|
||||
MaybeReseed();
|
||||
}
|
||||
}
|
||||
|
||||
[PlugMember]
|
||||
public static void FillSpan(Span<byte> data)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = NextByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[PlugMember]
|
||||
public static void GetBytes(byte* bufferPtr, int count)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
bufferPtr[i] = NextByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Runtime;
|
||||
|
||||
namespace RemSox.Kernel.Plugs;
|
||||
|
||||
public static partial class RuntimeExports
|
||||
{
|
||||
[RuntimeExport("fmod")]
|
||||
public static double fmod(double x, double y)
|
||||
{
|
||||
if (Math.Abs(y) < double.Epsilon)
|
||||
{
|
||||
return double.NaN;
|
||||
}
|
||||
|
||||
double q = Math.Truncate(x / y);
|
||||
return x - (q * y);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user