Add support for KERN_ARND to get random bytes on NetBSD
[openssl.git] / crypto / rand / rand_unix.c
index 9b6971c09570a574885d4f2ae41a90289e1ec056..bde4ac16cb89f5e10f5ef8411d1d70cf3b056289 100644 (file)
@@ -23,7 +23,7 @@
 # include <sys/sysctl.h>
 # include <sys/param.h>
 #endif
-#if defined(__OpenBSD__)
+#if defined(__OpenBSD__) || defined(__NetBSD__)
 # include <sys/param.h>
 #endif
 #ifdef OPENSSL_SYS_UNIX
@@ -124,7 +124,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     extern void s$sleep2(long long *_duration, short int *_code);
 #  endif
 
-    bytes_needed = rand_pool_bytes_needed(pool, 2 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
 
     for (i = 0; i < bytes_needed; i++) {
         /*
@@ -189,7 +189,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 #   error "librandom not (yet) supported"
 #  endif
 
-#  if defined(__FreeBSD__) && defined(KERN_ARND)
+#  if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
 /*
  * sysctl_random(): Use sysctl() to read a random number from the kernel
  * Returns the size on success, 0 on failure.
@@ -201,14 +201,25 @@ static size_t sysctl_random(char *buf, size_t buflen)
     size_t len;
 
     /*
-     * Old implementations returned longs, newer versions support variable
-     * sizes up to 256 byte. The code below would not work properly when
-     * the sysctl returns long and we want to request something not a multiple
-     * of longs, which should never be the case.
+     * On FreeBSD old implementations returned longs, newer versions support
+     * variable sizes up to 256 byte. The code below would not work properly
+     * when the sysctl returns long and we want to request something not a
+     * multiple of longs, which should never be the case.
      */
     if (!ossl_assert(buflen % sizeof(long) == 0))
         return 0;
 
+    /*
+     * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
+     * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
+     * it returns a variable number of bytes with the current version supporting
+     * up to 256 bytes.
+     * Just return an error on older NetBSD versions.
+     */
+#if   defined(__NetBSD__) && __NetBSD_Version__ < 400000000
+    return 0;
+#endif
+
     mib[0] = CTL_KERN;
     mib[1] = KERN_ARND;
 
@@ -239,7 +250,7 @@ int syscall_random(void *buf, size_t buflen)
     return (int)syscall(SYS_getrandom, buf, buflen, 0);
 #  endif
 
-#  if defined(__FreeBSD__) && defined(KERN_ARND)
+#  if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
     return (int)sysctl_random(buf, buflen);
 #  endif
 
@@ -278,7 +289,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     unsigned char *buffer;
 
 #   ifdef OPENSSL_RAND_SEED_GETRANDOM
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     buffer = rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;
@@ -300,7 +311,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 #   endif
 
 #   ifdef OPENSSL_RAND_SEED_DEVRANDOM
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     if (bytes_needed > 0) {
         static const char *paths[] = { DEVRANDOM, NULL };
         FILE *fp;
@@ -323,7 +334,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
             if (entropy_available > 0)
                 return entropy_available;
 
-            bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+            bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
         }
     }
 #   endif
@@ -341,7 +352,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 #   endif
 
 #   ifdef OPENSSL_RAND_SEED_EGD
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     if (bytes_needed > 0) {
         static const char *paths[] = { DEVRANDOM_EGD, NULL };
         int i;