* 'libuuid' of https://github.com/ferivoz/util-linux:
  libuuid: check quality of random bytes
This commit is contained in:
Karel Zak 2020-11-09 12:31:17 +01:00
commit df8a8d1373
5 changed files with 27 additions and 27 deletions

View File

@ -11,7 +11,7 @@ extern int rand_get_number(int low_n, int high_n);
/* /dev/urandom based with fallback to rand() */ /* /dev/urandom based with fallback to rand() */
extern int random_get_fd(void); extern int random_get_fd(void);
extern void ul_random_get_bytes(void *buf, size_t nbytes); extern int ul_random_get_bytes(void *buf, size_t nbytes);
extern const char *random_tell_source(void); extern const char *random_tell_source(void);
#endif #endif

View File

@ -102,7 +102,12 @@ int random_get_fd(void)
#define UL_RAND_READ_ATTEMPTS 8 #define UL_RAND_READ_ATTEMPTS 8
#define UL_RAND_READ_DELAY 125000 /* microseconds */ #define UL_RAND_READ_DELAY 125000 /* microseconds */
void ul_random_get_bytes(void *buf, size_t nbytes) /*
* Write @nbytes random bytes into @buf.
*
* Returns 0 for good quality of random bytes or 1 for weak quality.
*/
int ul_random_get_bytes(void *buf, size_t nbytes)
{ {
unsigned char *cp = (unsigned char *)buf; unsigned char *cp = (unsigned char *)buf;
size_t i, n = nbytes; size_t i, n = nbytes;
@ -118,7 +123,7 @@ void ul_random_get_bytes(void *buf, size_t nbytes)
n -= x; n -= x;
cp += x; cp += x;
lose_counter = 0; lose_counter = 0;
errno = 0;
} else if (errno == ENOSYS) { /* kernel without getrandom() */ } else if (errno == ENOSYS) { /* kernel without getrandom() */
break; break;
@ -177,6 +182,8 @@ void ul_random_get_bytes(void *buf, size_t nbytes)
sizeof(ul_jrand_seed)-sizeof(unsigned short)); sizeof(ul_jrand_seed)-sizeof(unsigned short));
} }
#endif #endif
return n != 0;
} }

View File

@ -49,7 +49,10 @@ The
.B uuid_generate .B uuid_generate
function creates a new universally unique identifier (UUID). The uuid will function creates a new universally unique identifier (UUID). The uuid will
be generated based on high-quality randomness from be generated based on high-quality randomness from
.IR getrandom(2) ,
.IR /dev/urandom , .IR /dev/urandom ,
or
.IR /dev/random
if available. If it is not available, then if available. If it is not available, then
.B uuid_generate .B uuid_generate
will use an alternative algorithm which uses the current time, the will use an alternative algorithm which uses the current time, the
@ -59,8 +62,7 @@ using a pseudo-random generator.
The The
.B uuid_generate_random .B uuid_generate_random
function forces the use of the all-random UUID format, even if function forces the use of the all-random UUID format, even if
a high-quality random number generator (i.e., a high-quality random number generator
.IR /dev/urandom )
is not available, in which case a pseudo-random is not available, in which case a pseudo-random
generator will be substituted. Note that the use of a pseudo-random generator will be substituted. Note that the use of a pseudo-random
generator may compromise the uniqueness of UUIDs generator may compromise the uniqueness of UUIDs

View File

@ -499,11 +499,11 @@ int uuid_generate_time_safe(uuid_t out)
} }
void __uuid_generate_random(uuid_t out, int *num) int __uuid_generate_random(uuid_t out, int *num)
{ {
uuid_t buf; uuid_t buf;
struct uuid uu; struct uuid uu;
int i, n; int i, n, r = 0;
if (!num || !*num) if (!num || !*num)
n = 1; n = 1;
@ -511,7 +511,8 @@ void __uuid_generate_random(uuid_t out, int *num)
n = *num; n = *num;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ul_random_get_bytes(buf, sizeof(buf)); if (ul_random_get_bytes(buf, sizeof(buf)))
r = -1;
uuid_unpack(buf, &uu); uuid_unpack(buf, &uu);
uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
@ -520,6 +521,8 @@ void __uuid_generate_random(uuid_t out, int *num)
uuid_pack(&uu, out); uuid_pack(&uu, out);
out += sizeof(uuid_t); out += sizeof(uuid_t);
} }
return r;
} }
void uuid_generate_random(uuid_t out) void uuid_generate_random(uuid_t out)
@ -531,27 +534,15 @@ void uuid_generate_random(uuid_t out)
} }
/* /*
* Check whether good random source (/dev/random or /dev/urandom) * This is the generic front-end to __uuid_generate_random and
* is available. * uuid_generate_time. It uses __uuid_generate_random output
*/ * only if high-quality randomness is available.
static int have_random_source(void)
{
return (access("/dev/random", R_OK) == 0 ||
access("/dev/urandom", R_OK) == 0);
}
/*
* This is the generic front-end to uuid_generate_random and
* uuid_generate_time. It uses uuid_generate_random only if
* /dev/urandom is available, since otherwise we won't have
* high-quality randomness.
*/ */
void uuid_generate(uuid_t out) void uuid_generate(uuid_t out)
{ {
if (have_random_source()) int num = 1;
uuid_generate_random(out);
else if (__uuid_generate_random(out, &num))
uuid_generate_time(out); uuid_generate_time(out);
} }

View File

@ -49,6 +49,6 @@
#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID #define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID
extern int __uuid_generate_time(uuid_t out, int *num); extern int __uuid_generate_time(uuid_t out, int *num);
extern void __uuid_generate_random(uuid_t out, int *num); extern int __uuid_generate_random(uuid_t out, int *num);
#endif /* _UUID_UUID_H */ #endif /* _UUID_UUID_H */