add linux syscall sys_getrandom to lcorernd
[lcore.git] / lcorernd.pas
index d2788523f244b521f2a0fc9a7e7ed14c535a2c19..b7a3bf21dd35a320b04e97fa611e84d9a4a655d6 100644 (file)
@@ -144,7 +144,17 @@ uses
       baseunix,unix,unixutil,sockets,\r
     {$endif}\r
   {$endif}\r
+  {$ifdef linux}\r
+  syscall,\r
+  {$endif}\r
   fastmd5,sysutils;\r
+{$endif}\r
+\r
+const\r
+  wordsizeshift=2;\r
+  wordsize=1 shl wordsizeshift;\r
+\r
+{$ifndef nolcorernd}\r
 \r
 {$ifdef unix}{$include unixstuff.inc}{$endif}\r
 \r
@@ -170,19 +180,17 @@ type
   hashtype=tmd5;\r
 \r
 const\r
-  wordsizeshift=2;\r
-  wordsize=1 shl wordsizeshift;\r
   //wordsize check commented out for d3 compatibility\r
   //{ $if (wordsize <> sizeof(wordtype))}'wordsizeshift must be setcorrectly'{ $ifend}\r
   hashsize=sizeof(hashtype);\r
   halfhashsize=hashsize div 2;\r
   hashdwords=hashsize div wordsize;\r
   pooldwords=3*hashdwords;\r
-  seeddwords=32;\r
+  seeddwords=40;\r
   hashpasssize=48; {this number has to be small enough that hashing this size uses only one block transform}\r
 \r
 var\r
-  {the seed part of this buffer must be at least as big as the OS seed (windows: 120 bytes, unix: 36 bytes)}\r
+  //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)\r
   pool:array[0..(pooldwords+seeddwords-1)] of wordtype;\r
   reseedcountdown:integer;\r
 \r
@@ -277,6 +285,17 @@ begin
 end;\r
 \r
 \r
+{$ifdef linux}\r
+ {$ifdef i386}\r
+  const sys_getrandom = 355;\r
+ {$endif}\r
+\r
+ {$ifdef cpux64}\r
+  const sys_getrandom = 318;\r
+ {$endif}\r
+{$endif}\r
+\r
+\r
 function collect_seeding(var output;const bufsize:integer):integer;\r
 var\r
   f:file;\r
@@ -293,24 +312,30 @@ begin
   if (bufsize < sizeof(l)) then exit;\r
   result := sizeof(l);\r
 \r
-  {/DEV/URANDOM}\r
-  a := 1;\r
-  assignfile(f,'/dev/urandom');\r
-  filemode := 0;\r
-  {$i-}reset(f,1);{$i+}\r
-  a := ioresult;\r
-  if (a <> 0) then begin\r
-    assignfile(f,'/dev/random');\r
+  a := -1;\r
+  {$ifdef linux}\r
+  a := do_syscall(sys_getrandom,tsysparam(@l.devrnd),sizeof(l.devrnd),0);\r
+  {$endif}\r
+\r
+  if (a < sizeof(l.devrnd)) then begin\r
+    {if syscall misses or fails, fall back to /dev/urandom}\r
+    assignfile(f,'/dev/urandom');\r
+    filemode := 0;\r
     {$i-}reset(f,1);{$i+}\r
     a := ioresult;\r
-  end;\r
-  if (a = 0) then begin\r
-    blockread(f,l.devrnd,sizeof(l.devrnd));\r
-    closefile(f);\r
-  end else begin\r
-    {the OS we are on has no /dev/random or /dev/urandom, get a hash from /var/log/wtmp}\r
-    wtmphash;\r
-    move(wtmpcached,l.devrnd,sizeof(l.devrnd));\r
+    if (a <> 0) then begin\r
+      assignfile(f,'/dev/random');\r
+      {$i-}reset(f,1);{$i+}\r
+      a := ioresult;\r
+    end;\r
+    if (a = 0) then begin\r
+      blockread(f,l.devrnd,sizeof(l.devrnd));\r
+      closefile(f);\r
+    end else begin\r
+      {the OS we are on has no /dev/random or /dev/urandom, get a hash from /var/log/wtmp}\r
+      wtmphash;\r
+      move(wtmpcached,l.devrnd,sizeof(l.devrnd));\r
+    end;\r
   end;\r
   {get more randomness in case there's no /dev/random}\r
   rdtsc(@l.rdtscbuf);\r