X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/968c333d05db5d5ecf3599f8e304c67e64f21159..fed3bacaa7e5da92ab4cf44995b5a2bc26a81faa:/lcorernd.pas

diff --git a/lcorernd.pas b/lcorernd.pas
index 648c87a..6f1fe48 100644
--- a/lcorernd.pas
+++ b/lcorernd.pas
@@ -4,7 +4,9 @@
   ----------------------------------------------------------------------------- }
 
 unit lcorernd;
-
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
 interface
 
 {$include lcoreconfig.inc}
@@ -15,7 +17,7 @@ written by Bas Steendijk (beware)
 the aim of this unit is to provide randomness in a consistent way, using OS specific methods for seeding
 
 this unit uses MD5 for performance and code size, but it is made so it is easy to use a different hash,
-as long as it is atleat 128 bits, and a multiple of the "word size" (32 bits)
+as long as it is at least 128 bits, and a multiple of the "word size" (32 bits)
 
 goals:
 
@@ -25,20 +27,20 @@ goals:
 
 - for the numbers to be
  - random: pass diehard and similar tests
- - unique: generate UUID's
+ - unique: generate UUIDs
  - secure: difficult for a remote attacker to guess the internal state, even
    when given some output
 
 typical intended uses:
  - anything that needs random numbers without extreme demands on security or
    speed should be able to use this
- - seeding other (faster) RNG's
- - generation of passwords, UUID's, cookies, and session keys
+ - seeding other (faster) RNGs
+ - generation of passwords, UUIDs, cookies, and session keys
  - randomizing protocol fields to protect against spoofing attacks
  - randomness for games
 
 this is not intended to be directly used for:
-- high securirity purposes (generating RSA root keys etc)
+- high security purposes (generating RSA root keys etc)
 - needing random numbers at very high rates (disk wiping, some simulations, etc)
 
 performance:
@@ -130,6 +132,8 @@ var
 
 implementation
 
+{$include pgtypes.inc}
+
 {$ifndef nolcorernd}
 uses
   {$ifdef mswindows}windows,activex,{$endif}
@@ -144,6 +148,23 @@ uses
 
 {$ifdef unix}{$include unixstuff.inc}{$endif}
 
+procedure rdtsc(buf: pointer);
+asm
+  {$ifdef cpux86}
+  mov ecx, buf
+  db $0f; db $31 {rdtsc}
+  mov [ecx], edx
+  mov [ecx+4], eax
+  {$endif}
+
+  {$ifdef cpux64}
+  mov rcx, buf
+  rdtsc
+  mov [rcx], edx
+  mov [rcx+4], eax
+  {$endif}
+end;
+
 type
   {hashtype must be array of bytes}
   hashtype=tmd5;
@@ -157,18 +178,35 @@ const
   halfhashsize=hashsize div 2;
   hashdwords=hashsize div wordsize;
   pooldwords=3*hashdwords;
-  seeddwords=32;
+  seeddwords=40;
   hashpasssize=48; {this number has to be small enough that hashing this size uses only one block transform}
 
 var
-  {the seed part of this buffer must be atleast as big as the OS seed (windows: 104 bytes, unix: 36 bytes)}
+  //the seed part of this buffer must be at least as big as the OS seed (windows: 120 bytes for 32 bits, 160 bytes for 64 bits, unix: 36 bytes)
   pool:array[0..(pooldwords+seeddwords-1)] of wordtype;
   reseedcountdown:integer;
 
 {$ifdef mswindows}
+var
+  systemfunction036:function(var v; c:cardinal): boolean;  stdcall;
+  rtlgenrandominited:boolean;
+
+procedure initrtlgenrandom;
+var
+  h:thandle;
+begin
+  rtlgenrandominited := true;
+  systemfunction036 := nil;  
+  h := loadlibrary('advapi32.dll');
+  if (h <> 0) then begin
+    systemfunction036 := GetProcAddress(h,'SystemFunction036');
+  end;
+end;
+
 function collect_seeding(var output;const bufsize:integer):integer;
 var
   l:packed record
+    rtlgenrandom:array[0..3] of longint;
     guid:array[0..3] of longint;
     qpcbuf:array[0..1] of longint;
     rdtscbuf:array[0..1] of longint;
@@ -178,7 +216,6 @@ var
     cursor:tpoint;
     hs:theapstatus;
   end absolute output;
-  rdtsc_0,rdtsc_1:integer;
 begin
   result := 0;
   if (bufsize < sizeof(l)) then exit;
@@ -194,15 +231,8 @@ begin
   queryperformancecounter(tlargeinteger(l.qpcbuf));
 
   {RDTSC}
-  {$ifdef cpu386}
-  asm
-    db $0F; db $31
-    mov rdtsc_0,eax
-    mov rdtsc_1,edx
-  end;
-  l.rdtscbuf[0] := rdtsc_0;
-  l.rdtscbuf[1] := rdtsc_1;
-  {$endif}
+  rdtsc(@l.rdtscbuf);
+
   {GETSYSTEMTIME}
   getsystemtime(tsystemtime(l.systemtimebuf));
 
@@ -210,6 +240,10 @@ begin
   getcursorpos(l.cursor);
 
   l.hs := getheapstatus;
+
+  {rtlgenrandom}
+  if not rtlgenrandominited then initrtlgenrandom;
+  if assigned(@systemfunction036) then systemfunction036(l.rtlgenrandom,sizeof(l.rtlgenrandom));
 end;
 {$endif}
 
@@ -248,12 +282,11 @@ var
   f:file;
   a:integer;
   l:packed record
-    devrnd:array[0..3] of integer;
+    devrnd:array[0..7] of integer;
     rdtscbuf:array[0..1] of integer;
     tv:ttimeval;
     pid:integer;
   end absolute output;
-  rdtsc_0,rdtsc_1:integer;
 
 begin
   result := 0;
@@ -280,15 +313,7 @@ begin
     move(wtmpcached,l.devrnd,sizeof(l.devrnd));
   end;
   {get more randomness in case there's no /dev/random}
-  {$ifdef cpu386}{$ASMMODE intel}
-  asm
-    db $0F; db $31
-    mov rdtsc_0,eax
-    mov rdtsc_1,edx
-  end;
-  l.rdtscbuf[0] := rdtsc_0;
-  l.rdtscbuf[1] := rdtsc_1;
-  {$endif}
+  rdtsc(@l.rdtscbuf);
 
   gettimeofday(l.tv);
   l.pid := getpid;