From patchwork Fri Aug 31 20:42:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 29153 Received: (qmail 54226 invoked by alias); 31 Aug 2018 20:42:53 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 54107 invoked by uid 89); 31 Aug 2018 20:42:52 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SEM_URI, SEM_URIRED, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qt0-f193.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references; bh=yZyyjfojeCu0/fTxm4tkjc7oXIDo6lf0EW8Sb8YJY18=; b=DDmzFIdt1/eqmH4PgBAsT7jcCixVQ9IdaxV6XZKF8cJk3pgngHbB6BVripTACCwNfY a8Eq94F0816z5FXROj1KkwytE/nv0w8bxwRpAFkv4vQzedOOZ4P1FB13bXTz8NFHyiVl S7+iL+ReJM6uow3Jj5Sn8EKmiv9xIVJN4PiCI= Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 2/7] support: Add pseudo-random number generator interface Date: Fri, 31 Aug 2018 17:42:33 -0300 Message-Id: <20180831204238.10626-3-adhemerval.zanella@linaro.org> In-Reply-To: <20180831204238.10626-1-adhemerval.zanella@linaro.org> References: <20180831204238.10626-1-adhemerval.zanella@linaro.org> This is based on POSIX mrand48 and the interfaces provided is just wrapping around common usages (buffer fill and uniform distribution). Although better PNRGs exists, the already in place POSIXs one is used for simplicity and a better de factor one is being discussed for inclusion (arc4random based on AES-CTR). Ideally it would replace the mrand48 usage for this interface. Checked on x86_64-linux-gnu. * support/Makefile (libsupport-routines): Add support_random. (tests): Add tst-support_random. * support/support_random.c: New file. * support/support_random.h: Likewise. --- support/Makefile | 3 +- support/support_random.c | 90 ++++++++++++++++++++++++++++++++++++++++ support/support_random.h | 59 ++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 support/support_random.c create mode 100644 support/support_random.h diff --git a/support/Makefile b/support/Makefile index 9063046c23..db46be606e 100644 --- a/support/Makefile +++ b/support/Makefile @@ -56,6 +56,7 @@ libsupport-routines = \ support_openpty \ support_quote_blob \ support_record_failure \ + support_random \ support_run_diff \ support_shared_allocate \ support_test_compare_blob \ @@ -161,7 +162,7 @@ tests = \ tst-support_record_failure \ tst-test_compare \ tst-test_compare_blob \ - tst-xreadlink \ + tst-xreadlink ifeq ($(run-built-tests),yes) tests-special = \ diff --git a/support/support_random.c b/support/support_random.c new file mode 100644 index 0000000000..5feee1a213 --- /dev/null +++ b/support/support_random.c @@ -0,0 +1,90 @@ +/* Function for pseudo-random number generation. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +void +support_random_seed (support_random_state *state, uint32_t seed) +{ + unsigned short int seed16v[3] = { 0 }; + memcpy (seed16v, &seed, sizeof (seed)); + seed48_r (seed16v, state); +} + +void +support_random_rseed (support_random_state *state) +{ + unsigned short int buf[3]; + size_t len = sizeof buf; + + ssize_t ret = getrandom (buf, len, 0); + if (ret != len) + { + int fd = xopen ("/dev/urandom", O_RDONLY, 0); + uintptr_t pbuf = (uintptr_t) buf; + uintptr_t pend = pbuf + len; + while (pbuf < pend) + { + ret = read (fd, buf, pend - pbuf); + if (ret <= 0) + FAIL_EXIT1 ("read %zu bytes from /dev/urandom failed: %m", + pend - pbuf); + pbuf += ret; + } + close (fd); + } + + seed48_r (buf, state); +} + +uint32_t +support_random_u32 (support_random_state *state) +{ + long int rl; + mrand48_r (state, &rl); + return rl; +} + +void +support_random_buf (support_random_state *state, void *buf, size_t nbytes) +{ + size_t nw = nbytes / sizeof (uint32_t); + for (size_t i = 0; i < nw; i++) + { + uint32_t r = support_random_u32 (state); + memcpy (buf, &r, sizeof (uint32_t)); + buf = (void*)((uintptr_t)buf + sizeof (uint32_t)); + } + + size_t nb = nbytes % sizeof (uint32_t); + if (nb != 0) + { + uint32_t r = support_random_u32 (state); + memcpy (buf, &r, nb); + } +} diff --git a/support/support_random.h b/support/support_random.h new file mode 100644 index 0000000000..8224c2b774 --- /dev/null +++ b/support/support_random.h @@ -0,0 +1,59 @@ +/* Function for pseudo-random number generation. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SUPPORT_MT_RAND_H +#define SUPPORT_MT_RAND_H + +#include +#include + +typedef struct drand48_data support_random_state; + +void support_random_seed (support_random_state *state, uint32_t seed); +void support_random_rseed (support_random_state *state); + +uint32_t support_random_u32 (support_random_state *state); +void support_random_buf (support_random_state *state, void *buf, + size_t nbytes); + +/* Scales the number NUMBER to the uniformly distributed closed internal + [min, max]. */ +static inline uint32_t +support_random_uniform_distribution (support_random_state *state, + uint32_t min, uint32_t max) +{ + uint32_t ret; + uint32_t range = max - min; + /* It assumes the input random number RANDOM range is as larger or equal + than the RANGE, so the result will either returned or downscaled. */ + if (range != UINT32_MAX) + { + uint32_t urange = range + 1; /* range can be 0. */ + uint32_t scaling = UINT32_MAX / urange; + uint32_t past = urange * scaling; + do + ret = support_random_u32 (state); + while (ret >= past); + ret /= scaling; + } + else + ret = support_random_u32 (state); + return ret + min; +} + +#endif