*** empty log message ***
authorClaus Gittinger <cg@exept.de>
Thu, 10 May 2018 01:09:22 +0200
changeset 4667 35e1ebb8020e
parent 4666 fbe9af9a6158
child 4668 46a47d71f826
*** empty log message ***
RandomRDRand.st
--- a/RandomRDRand.st	Wed May 09 19:42:29 2018 +0200
+++ b/RandomRDRand.st	Thu May 10 01:09:22 2018 +0200
@@ -2,7 +2,7 @@
 
 "
  COPYRIGHT (c) 2014 Claus Gittinger
-              All Rights Reserved
+	      All Rights Reserved
 
  This software is furnished under a license and may be used
  only in accordance with the terms of that license and with the
@@ -27,7 +27,7 @@
 copyright
 "
  COPYRIGHT (c) 2014 Claus Gittinger
-              All Rights Reserved
+	      All Rights Reserved
 
  This software is furnished under a license and may be used
  only in accordance with the terms of that license and with the
@@ -43,29 +43,29 @@
     This generator uses the rdgen random generator which is built into modern intel chips.
     Before using, you should check via the isSupported query.
 
-    Warning: 
-        there have been discussions about the security of the intel rdgen instruction
-        and whether there are NSA backdoors built into it.
-        Linus Torwalds refuses to use it for /dev/urandom in the linux kernel, for that very reason.
-        Be sure you know what you are doing, if you use this generator for sensitive cryptographic stuff.
-        We recommend using one of the libcrypt-based generators and use this only to get additional
-        entropy for the seed.
+    Warning:
+	there have been discussions about the security of the intel rdgen instruction
+	and whether there are NSA backdoors built into it.
+	Linus Torwalds refuses to use it for /dev/urandom in the linux kernel, for that very reason.
+	Be sure you know what you are doing, if you use this generator for sensitive cryptographic stuff.
+	We recommend using one of the libcrypt-based generators and use this only to get additional
+	entropy for the seed.
 
     NO WARRANTY
 
     RandomRDGen new nextInteger
 
     [see also:]
-        RandomGenerator - the default; uses the machine's /dev/random if available
-        Random  - fast, but generates less quality random numbers
-        RandomTT800 - another random generator
-        RandomParkMiller - another random generator
-        RandomMT19937 - another random generator
-        RandomKISS - another random generator
-        exept:libcrypt - a library containing more stuff based on hashes and cyphers
+	RandomGenerator - the default; uses the machine's /dev/random if available
+	Random  - fast, but generates less quality random numbers
+	RandomTT800 - another random generator
+	RandomParkMiller - another random generator
+	RandomMT19937 - another random generator
+	RandomKISS - another random generator
+	exept:libcrypt - a library containing more stuff based on hashes and cyphers
 
     [author:]
-        Claus Gittinger.
+	Claus Gittinger.
 "
 ! !
 
@@ -93,8 +93,8 @@
     "true if this architecture supports hardware random numbers"
 
     ^ OperatingSystem getCPUType = 'x86_64'
-        and:[ (OperatingSystem getSystemInfo at:#extendedInstructions ifAbsent:#())
-              includes:#aes ]
+	and:[ (OperatingSystem getSystemInfo at:#extendedInstructions ifAbsent:#())
+	      includes:#aes ]
 
     "
      self isSupported
@@ -123,34 +123,51 @@
      Notice, it may raise an illegal instruction exception on some cpu chips,
      even though the cpuid instruction says that it is available"
 
+    |cfStillSet|
+
 %{
     unsigned INT r = 0;
     int cf;
+    int count = 50;
 
     do {
 #ifdef USE_DRAND64
-        cf = _rdrand64_step(&r);
+	cf = _rdrand64_step(&r);
 #else
 # ifdef USE_DRAND32
-        cf = _rdrand32_step(&r);
+	cf = _rdrand32_step(&r);
 # else
 #  if defined(__x86__) && defined(__GNUC__) && (__GNUC__ >= 2)
-        // Encoding of rdrand %eax
-        asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" 
-            : "=a" (r), "=r" (cf) 
-            : "0" (r), "1" (cf) 
-            : "cc");
+	// Encoding of rdrand %eax
+	asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1"
+	    : "=a" (r), "=r" (cf)
+	    : "0" (r), "1" (cf)
+	    : "cc");
 
 #  else
-        goto unsupported;
+#   if defined(__x86_64__) && defined(__GNUC__) && (__GNUC__ >= 2)
+	// Encoding of rdrand %rax
+	asm(".byte 0x48, 0x0F, 0xC7, 0xF0; adcl $0,%1"
+	    : "=a" (r), "=r" (cf)
+	    : "0" (r), "1" (cf)
+	    : "cc");
+
+#   else
+	goto unsupported;
+#   endif
 #  endif
 # endif
 #endif
-    } while (cf != 0);
-    RETURN (__MKUINT(r));
-
+    } while ((cf != 0) && (--count > 0));
+    if (cf == 0) {
+	RETURN (__MKUINT(r));
+    }
+    cfStillSet = true;
 unsupported: ;
 %}.
+    cfStillSet ifTrue:[
+	self primitiveFailed:'carry flag not clear after 50 tries'
+    ].
     self primitiveFailed:'unsupported on this architecture'
 
     "
@@ -167,4 +184,3 @@
 version_CVS
     ^ '$Header$'
 ! !
-