Compare commits

...

53 Commits
0.7.0 ... 0.8.1

Author SHA1 Message Date
Guillem Jover
229f85794f Release libbsd 0.8.1 2015-12-14 03:39:48 +01:00
Guillem Jover
7a75687541 Add support for GNU/Hurd to getentropy()
Reuse the getentropy code for Linux on the Hurd, which has fallbacks
for when the better interfaces are not present. And remove all the code
that is not supported currently on the Hurd. Ideally the Hurd should
get an equivalent interfaces that does not suffer from the same
problems as /dev/urandom.
2015-12-14 03:38:23 +01:00
Guillem Jover
f84004baf2 test: Add new unit tests for individual headers usage 2015-12-14 03:34:40 +01:00
Guillem Jover
cdf998a056 Turn <bsd/bsd.h> inert when using LIBBSD_OVERLAY
Also print a warning stating this fact.
2015-12-14 00:58:59 +01:00
Guillem Jover
2c77ad593c Add missing include to <md5.h>
The header was not self-contained, it was missing definitions for some
types included in <sys/types.h>.
2015-12-14 00:58:59 +01:00
Guillem Jover
48ac79b188 Use the non-overlayed libbsd headers when we need our own definitions 2015-12-14 00:58:51 +01:00
Guillem Jover
290a1ce8f2 Switch COPYING to Debian copyright machine readable format 1.0 2015-12-07 03:36:33 +01:00
Guillem Jover
6bcb1312f4 Relicense my contribution to BSD-2-clause
This avoids having two licenses on the same file.
2015-12-07 03:24:47 +01:00
Guillem Jover
da137a0921 Add missing copyright and license headers 2015-12-07 01:56:25 +01:00
Guillem Jover
d2f59a23d5 Fix getentropy implementation to use the correct system hooks
Include getentropy_<SYSTEM>.c instead of arc4random_<SYSTEM>.c.
2015-12-02 04:03:16 +01:00
Guillem Jover
01b77f0dcf Add support for GNU/kFreeBSD for closefrom() and getentropy() 2015-12-02 03:32:13 +01:00
Guillem Jover
75729394af Unify most arc4random Unix hooks into a single file
The Unix hook should work for most Unix-like systems, move glibc
specific code there and a FreeBSd specific comment, and remove the rest.
Also change the code to always fallback to use the generic Unix code.

This should cover GNU/Hurd and GNU/kFreeBSD among others.
2015-12-02 03:08:17 +01:00
Guillem Jover
8493c7f27d Use local SHA512 header
Actually use the local private SHA512 header instead of relying on the
OpenSSL one for no good reason. Add definition for expected macro
SHA512_DIGEST_LENGTH.
2015-12-01 03:40:57 +01:00
Guillem Jover
2b030da016 Release libbsd 0.8.0 2015-11-30 23:48:50 +01:00
Guillem Jover
330e211142 Update license and copyright information 2015-11-30 23:48:50 +01:00
Guillem Jover
874a0e51d3 Update arc4random module from OpenBSD and LibreSSL
Rework arc4random_stir() and arc4random_addrandom() code over the new
internal API, and documentation in the man page. Adapt the code to the
local build system.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85827
2015-11-30 23:48:50 +01:00
Guillem Jover
9a9a8b2dba Add private getentropy module from OpenBSD and LibreSSL
Adapt the code to the local build system.
2015-11-30 23:48:50 +01:00
Guillem Jover
5f9265f816 Add private SHA512 module from FreeBSD 2015-11-30 23:48:50 +01:00
Marek Vasut
1f77cdb40a Add NIOS2 support to nlist()
Add support for the NIOS2 soft-core CPU provided by Altera.

Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
Cc: Ley Foon Tan <lftan@altera.com>
Cc: Thomas Chou <thomas@wytron.com.tw>
Cc: Walter Goossens <waltergoossens@home.nl>
2015-11-30 23:48:50 +01:00
Guillem Jover
f3b115540c man: Rename funopen.3 to funopen.3bsd to avoid clash with funtools
The funtools project ships a man page with the same, name. And although
it mith probably make more sense to rename the man page there, as BSD
systems will certainly not do so, this is the easiest and fastest way
to avoid a file conflict.
2015-11-30 23:48:50 +01:00
Guillem Jover
877732ef4d test: Check asprintf() return code 2015-11-30 23:48:50 +01:00
Guillem Jover
02bccb0a01 test: Add unit test for strmode() 2015-11-30 23:02:23 +01:00
Guillem Jover
58bef83f41 test: Add unit test for arc4random() 2015-11-30 23:02:23 +01:00
Guillem Jover
6e074a2bdc build: Make git log invocation immune to local configuration 2015-11-30 23:02:23 +01:00
Guillem Jover
0871daf7b0 build: Move hash/helper.c into new libbsd_la_included_sources
Use this variable in EXTRA_DIST and libbsd_la_DEPENDENCIES.
2015-11-30 04:12:02 +01:00
Guillem Jover
02c33d5022 build: Move proctitle_LDFLAGS inside BUILD_LIBBSD_CTOR conditional 2015-11-30 04:10:23 +01:00
Guillem Jover
45443583df Add explicit_bzero() function from OpenBSD 2015-09-24 05:47:58 +02:00
Guillem Jover
8641d8aed7 Make closefrom_procfs() fail when reallocarray() fails 2015-09-24 05:28:58 +02:00
Guillem Jover
0982dcd98b Lock the file streams in fgetln() and fparseln()
The fparseln() function had the NetBSD uppercase macros stubbed out,
so replace them with the actual stdio ones. The fgetln() function was
missing any locking at all.
2015-09-23 07:59:34 +02:00
Guillem Jover
ee26e59e72 Mark functions handling format strings with __printflike 2015-09-23 07:59:34 +02:00
Guillem Jover
151bc71d64 Add compile and link-time deprecation warnings for fgetln()
Although the current implementation in libbsd is probably one of the
safest ones around, it still poses some problems when used with many
file streams. This function has now a replacement, that is both more
standard and portable. Ask users to switch to getline(3) instead.
2015-09-23 07:59:34 +02:00
Guillem Jover
41ff37bbcc build: Add support for linker warnings 2015-09-23 07:59:34 +02:00
Guillem Jover
53d989a223 Switch fparseln() implementation from fgetln() to getline() 2015-09-23 07:59:34 +02:00
Guillem Jover
f50b197ea5 test: Add fparseln() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
54f153414a test: Refactor stream testing functions into a new module 2015-09-23 07:59:34 +02:00
Brent Cook
9688ab26b9 Avoid left shift overflow in reallocarray
Some 64-bit platforms (e.g. Windows 64) have a 32-bit long. So, shifting
1UL 32-bits to the left causes an overflow. This replaces the constant
1UL with (size_t)1 so that we get the correct constant size for the
platform.

Import from OpenBSD.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2015-09-23 07:59:34 +02:00
Guillem Jover
025b44800e Make mergesort setup() static 2015-09-23 07:59:34 +02:00
Guillem Jover
a6a101effa Use ANSI C prototypes 2015-09-23 07:59:34 +02:00
Guillem Jover
32388fe59f Use reallocarray() instead of malloc() or realloc() 2015-09-23 07:59:34 +02:00
Guillem Jover
30e328cbf1 Do not close file descriptors while scanning the /proc filesystem
Closing file descriptors changes the content of the fd directories in
the /proc filesystem, which means readdir() might get very confused.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85663
2015-09-23 07:59:34 +02:00
Guillem Jover
4cc43915f2 Move procfs based implementation into a new closefrom_procfs() function 2015-09-23 07:59:34 +02:00
Guillem Jover
34df142665 Refactor file descriptor closure into a new closefrom_close() 2015-09-23 07:59:34 +02:00
Guillem Jover
3881c4fc68 Update closefrom() function
Import from sudo. Adapt the build system to detect the required features.
2015-09-23 07:59:34 +02:00
Guillem Jover
3a3d87d730 test: Add closefrom() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
d62f7d8fac test: Add test case for fpurge(NULL) 2015-09-23 07:59:34 +02:00
Guillem Jover
cfb4d462a9 test: Move and activate fpurge() test case from module to a dedicated file 2015-09-23 07:59:34 +02:00
Guillem Jover
205827a2dd build: Centralize testsuite LDADD setting in a single variable 2015-09-23 07:59:34 +02:00
Guillem Jover
c7e01e9884 Sync queue(3) from FreeBSD
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85147
2015-09-23 07:59:34 +02:00
Guillem Jover
3267114483 Add __offsetof, __rangeof and __containerof to sys/cdefs.h
Import and adapt from FreeBSD.
2015-09-23 07:59:27 +02:00
Guillem Jover
0e4e3ab269 Add __DECONST, __DEVOLATILE and __DEQUALIFY macros to sys/cdefs.h
Import from FreeBSD.
2015-09-23 07:59:24 +02:00
Guillem Jover
a6fe103c1b Add new man page for reallocarray(3)
Import man page from OpenBSD.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85622
2015-09-23 07:14:24 +02:00
Guillem Jover
02b55488c5 Use stdint integer types instead of BSD legacy ones 2015-09-23 07:14:21 +02:00
Callum Davies
6378351169 Fix arc4random() and arc4random_stir() prototypes
These two functions accept no arguments.  The prototypes should reflect
this.  This change lets the compiler warn about certain (admittedly
silly) mistakes.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-08-12 12:18:13 +02:00
74 changed files with 5937 additions and 1138 deletions

1047
COPYING

File diff suppressed because it is too large Load Diff

View File

@@ -12,5 +12,5 @@ EXTRA_DIST = \
dist-hook:
echo $(VERSION) >$(distdir)/.dist-version
if [ -d .git ]; then \
git log --stat -C >$(distdir)/ChangeLog; \
XDG_CONFIG_HOME= HOME= git log --stat -C >$(distdir)/ChangeLog; \
fi

View File

@@ -12,8 +12,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
LIBBSD_ABI_MAJOR=0
LIBBSD_ABI_MINOR=7
LIBBSD_ABI_PATCH=0
LIBBSD_ABI_MINOR=8
LIBBSD_ABI_PATCH=1
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
AC_SUBST([LIBBSD_ABI])
@@ -38,9 +38,14 @@ if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
fi
# Checks for libraries.
AC_CHECK_LIB([testu01], [unif01_CreateExternGenBits],
[TESTU01_LIBS="-ltestu01"])
AC_SUBST([TESTU01_LIBS])
AM_CONDITIONAL([HAVE_LIBTESTU01],
[test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
# Checks for header files.
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h])
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -123,7 +128,10 @@ AC_LINK_IFELSE(
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge getexecname getline sysconf])
AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
getauxval getentropy getexecname getline \
pstat_getproc sysconf])
AM_CONDITIONAL(HAVE_GETENTROPY, [test "x$ac_cv_func_getentropy" = "xtrue"])
AC_CONFIG_FILES([
Makefile

View File

@@ -27,10 +27,12 @@
#ifndef LIBBSD_H
#define LIBBSD_H
#ifdef LIBBSD_OVERLAY
#warning "This header is meant to be used w/o the libbsd overlay."
#else
/*
* Include all bsd compat headers.
*/
#include <bsd/sys/cdefs.h>
#include <bsd/sys/queue.h>
#include <bsd/sys/tree.h>
@@ -40,5 +42,6 @@
#include <bsd/err.h>
#include <bsd/getopt.h>
#include <bsd/md5.h>
#endif
#endif

View File

@@ -34,15 +34,23 @@
#ifndef LIBBSD_ERR_H
#define LIBBSD_ERR_H
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h>
#else
#include <bsd/sys/cdefs.h>
#endif
#include <stdarg.h>
__BEGIN_DECLS
extern void warnc (int code, const char *format, ...);
extern void vwarnc (int code, const char *format, va_list ap);
extern void errc (int status, int code, const char *format, ...);
extern void verrc (int status, int code, const char *format, va_list ap);
void warnc(int code, const char *format, ...)
__printflike(2, 3);
void vwarnc(int code, const char *format, va_list ap)
__printflike(2, 0);
void errc(int status, int code, const char *format, ...)
__printflike(3, 4);
void verrc(int status, int code, const char *format, va_list ap)
__printflike(3, 0);
__END_DECLS
#endif

View File

@@ -15,26 +15,29 @@
#ifndef _MD5_H_
#define _MD5_H_
#include <stdint.h>
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
typedef struct MD5Context {
u_int32_t state[4]; /* state */
u_int64_t count; /* number of bits, mod 2^64 */
u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
uint32_t state[4]; /* state */
uint64_t count; /* number of bits, mod 2^64 */
uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
} MD5_CTX;
#include <sys/cdefs.h>
#include <sys/types.h>
__BEGIN_DECLS
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, const u_int8_t *, size_t)
void MD5Update(MD5_CTX *, const uint8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
void MD5Pad(MD5_CTX *);
void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));
void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH])
void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
__attribute__((__bounded__(__minbytes__,1,4)))
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
char *MD5End(MD5_CTX *, char *)
@@ -43,7 +46,7 @@ char *MD5File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5Data(const u_int8_t *, size_t, char *)
char *MD5Data(const uint8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
__END_DECLS

View File

@@ -44,7 +44,12 @@
__BEGIN_DECLS
const char *fmtcheck(const char *, const char *);
char *fgetln(FILE *fp, size_t *lenp);
/* XXX: The function requires cooperation from the system libc to store the
* line buffer in the FILE struct itself. */
char *fgetln(FILE *fp, size_t *lenp)
__attribute__((deprecated("This functions cannot be safely ported, "
"use getline(3) instead, as it is supported "
"by GNU and POSIX.1-2008.")));
/*
* Note: We diverge from the FreeBSD, OpenBSD and DragonFlyBSD declarations,

View File

@@ -47,11 +47,11 @@
#include <stdint.h>
__BEGIN_DECLS
u_int32_t arc4random();
void arc4random_stir();
uint32_t arc4random(void);
void arc4random_stir(void);
void arc4random_addrandom(u_char *dat, int datlen);
void arc4random_buf(void *_buf, size_t n);
u_int32_t arc4random_uniform(u_int32_t upper_bound);
uint32_t arc4random_uniform(uint32_t upper_bound);
int dehumanize_number(const char *str, int64_t *size);

View File

@@ -41,6 +41,8 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
char *strnstr(const char *str, const char *find, size_t str_len);
void strmode(mode_t mode, char *str);
void explicit_bzero(void *buf, size_t len);
__END_DECLS
#endif

View File

@@ -114,6 +114,47 @@
# define __bounded__(x, y, z)
#endif
/*
* We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h>
* require it.
*/
#ifndef __offsetof
# if LIBBSD_GCC_VERSION >= 0x0401
# define __offsetof(type, field) __builtin_offsetof(type, field)
# else
# ifndef __cplusplus
# define __offsetof(type, field) \
((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
# else
# define __offsetof(type, field) \
(__offsetof__ (reinterpret_cast <__size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<type *> (0)->field))))
# endif
# endif
#endif
#define __rangeof(type, start, end) \
(__offsetof(type, end) - __offsetof(type, start))
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure. When using GCC, we first
* assign pointer x to a local variable, to check that its type is
* compatible with member m.
*/
#ifndef __containerof
# if LIBBSD_GCC_VERSION >= 0x0301
# define __containerof(x, s, m) ({ \
const volatile __typeof(((s *)0)->m) *__x = (x); \
__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m)); \
})
# else
# define __containerof(x, s, m) \
__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
# endif
#endif
#ifndef __RCSID
# define __RCSID(x)
#endif
@@ -138,4 +179,16 @@
# define __COPYRIGHT(x)
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#endif
#endif

View File

@@ -1,6 +1,9 @@
/*
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
*
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -9,19 +12,18 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef LIBBSD_OVERLAY
@@ -49,32 +51,6 @@
#define _PDP_ENDIAN __PDP_ENDIAN
#endif
/*
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdint.h>
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */

View File

@@ -65,7 +65,7 @@
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
@@ -85,12 +85,16 @@
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - - - +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
@@ -99,19 +103,22 @@
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
char * lastfile;
int lastline;
char * prevfile;
int prevline;
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
@@ -130,7 +137,9 @@ struct qm_trace {
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
@@ -162,11 +171,21 @@ struct { \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
@@ -189,6 +208,7 @@ struct { \
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
@@ -198,7 +218,7 @@ struct { \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT((elm)->field.sle_next); \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
@@ -210,6 +230,12 @@ struct { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
@@ -247,12 +273,21 @@ struct { \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
@@ -277,14 +312,13 @@ struct { \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : \
((struct type *)(void *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
@@ -294,13 +328,7 @@ struct { \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT((elm)->field.stqe_next); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
@@ -309,6 +337,12 @@ struct { \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
@@ -378,11 +412,21 @@ struct { \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
@@ -414,15 +458,21 @@ struct { \
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT((elm)->field.le_next); \
TRASHIT((elm)->field.le_prev); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
@@ -446,7 +496,7 @@ struct name { \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
@@ -509,21 +559,41 @@ struct { \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
@@ -587,6 +657,8 @@ struct { \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
@@ -597,8 +669,8 @@ struct { \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT((elm)->field.tqe_next); \
TRASHIT((elm)->field.tqe_prev); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)

View File

@@ -34,7 +34,11 @@
#ifndef LIBBSD_UNISTD_H
#define LIBBSD_UNISTD_H
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h>
#else
#include <bsd/sys/cdefs.h>
#endif
#include <sys/stat.h>
#ifndef S_ISTXT
@@ -60,7 +64,8 @@ void closefrom(int lowfd);
#define initsetproctitle(c, a, e) setproctitle_init((c), (a), (e))
void setproctitle_init(int argc, char *argv[], char *envp[]);
void setproctitle(const char *fmt, ...);
void setproctitle(const char *fmt, ...)
__printflike(1, 2);
int getpeereid(int s, uid_t *euid, gid_t *egid);
__END_DECLS

View File

@@ -23,12 +23,13 @@ dist_man_MANS = \
closefrom.3 \
dehumanize_number.3 \
expand_number.3 \
explicit_bzero.3 \
fgetln.3 \
fgetwln.3 \
flopen.3 \
fmtcheck.3 \
fparseln.3 \
funopen.3 \
funopen.3bsd \
getbsize.3 \
getmode.3 \
getpeereid.3 \
@@ -42,6 +43,7 @@ dist_man_MANS = \
queue.3bsd \
radixsort.3 \
readpassphrase.3 \
reallocarray.3 \
reallocf.3 \
setmode.3 \
setproctitle.3 \

View File

@@ -1,4 +1,5 @@
.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $
.\" $OpenBSD: arc4random.3,v 1.34 2014/07/19 16:11:16 naddy Exp $
.\"
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
.\" All rights reserved.
.\"
@@ -28,9 +29,8 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" Manual page, using -mandoc macros
.\" $FreeBSD$
.\"
.Dd April 15, 1997
.Dd $Mdocdate: July 19 2014 $
.Dt ARC4RANDOM 3
.Os
.Sh NAME
@@ -45,56 +45,70 @@
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft u_int32_t
.Ft uint32_t
.Fn arc4random "void"
.Ft void
.Fn arc4random_buf "void *buf" "size_t nbytes"
.Ft u_int32_t
.Fn arc4random_uniform "u_int32_t upper_bound"
.Ft uint32_t
.Fn arc4random_uniform "uint32_t upper_bound"
.Ft void
.Fn arc4random_stir "void"
.Ft void
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
.Sh DESCRIPTION
The
.Fn arc4random
function uses the key stream generator employed by the
arc4 cipher, which uses 8*8 8 bit S-Boxes.
The S-Boxes
can be in about
.if t 2\u\s71700\s10\d
.if n (2**1700)
states.
The
.Fn arc4random
function returns pseudo-random numbers in the range of 0 to
.if t 2\u\s731\s10\d\(mi1,
.if n (2**32)\(mi1,
and therefore has twice the range of
.Xr rand 3
This family of functions provides higher quality data than those
described in
.Xr rand 3 ,
.Xr random 3 ,
and
.Xr random 3 .
.Xr rand48 3 .
.Pp
Use of these functions is encouraged for almost all random number
consumption because the other interfaces are deficient in either
quality, portability, standardization, or availability.
These functions can be called in almost all coding environments,
including
.Xr pthreads 3
and
.Xr chroot 2 .
.Pp
High quality 32-bit pseudo-random numbers are generated very quickly.
On each call, a cryptographic pseudo-random number generator is used
to generate a new result.
One data pool is used for all consumers in a process, so that consumption
under program flow can act as additional stirring.
The subsystem is re-seeded from the kernel random number subsystem using
.Xr getentropy 2
on a regular basis, and also upon
.Xr fork 2 .
.Pp
The
.Fn arc4random
function returns a single 32-bit value.
.Pp
The
.Fn arc4random_buf
function fills the region
.Fa buf
of length
.Fa nbytes
with ARC4-derived random data.
with random data.
.Pp
.Fn arc4random_uniform
will return a uniformly distributed random number less than
will return a single 32-bit value, uniformly distributed but less than
.Fa upper_bound .
.Fn arc4random_uniform
is recommended over constructions like
This is recommended over constructions like
.Dq Li arc4random() % upper_bound
as it avoids "modulo bias" when the upper bound is not a power of two.
In the worst case, this function may consume multiple iterations
to ensure uniformity; see the source code to understand the problem
and solution.
.Pp
The
.Fn arc4random_stir
function reads data from
.Pa /dev/urandom
and uses it to permute the S-Boxes via
.Xr getentropy 2
and uses it to re-seed the subsystem via
.Fn arc4random_addrandom .
.Pp
There is no need to call
@@ -103,26 +117,22 @@ before using
.Fn arc4random
functions family, since
they automatically initialize themselves.
.Sh EXAMPLES
The following produces a drop-in replacement for the traditional
.Fn rand
and
.Fn random
functions using
.Fn arc4random :
.Pp
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
.Sh RETURN VALUES
These functions are always successful, and no return value is
reserved to indicate an error.
.Sh SEE ALSO
.Xr rand 3 ,
.Xr random 3 ,
.Xr srandomdev 3
.Xr rand48 3 ,
.Xr random 3
.Sh HISTORY
.Pa RC4
has been designed by RSA Data Security, Inc.
It was posted anonymously
to the USENET and was confirmed to be equivalent by several sources who
had access to the original cipher.
Since
.Pa RC4
used to be a trade secret, the cipher is now referred to as
.Pa ARC4 .
These functions first appeared in
.Ox 2.1 .
.Pp
The original version of this random number generator used the
RC4 (also known as ARC4) algorithm.
In
.Ox 5.5
it was replaced with the ChaCha20 cipher, and it may be replaced
again in the future as cryptographic techniques advance.
A good mnemonic is
.Dq A Replacement Call for Random .

72
man/explicit_bzero.3 Normal file
View File

@@ -0,0 +1,72 @@
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $OpenBSD: bzero.3,v 1.10 2014/01/22 21:06:45 tedu Exp $
.\"
.Dd $Mdocdate: January 22 2014 $
.Dt BZERO 3
.Os
.Sh NAME
.Nm explicit_bzero
.Nd write zeroes to a byte string
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/string.h
.Ft void
.Fn explicit_bzero "void *buf" "size_t len"
.Sh DESCRIPTION
The
.Fn explicit_bzero
function writes
.Fa len
zero bytes to the string
.Fa buf .
If
.Fa len
is zero,
.Fn explicit_bzero
does nothing.
.Pp
The
.Fn explicit_bzero
variant behaves the same as the
.Fn bzero
function, but will not be removed by a compiler's dead store optimization
pass, making it useful for clearing sensitive memory such as a password.
.Sh SEE ALSO
.Xr bzero 3 ,
.Xr memset 3 ,
.Xr swab 3
.Sh HISTORY
The
.Fn explicit_bzero
function first appeared in
.Ox 5.5 .

View File

@@ -126,9 +126,9 @@ is returned.
The
.Fn fparseln
function uses internally
.Xr fgetln 3 ,
.Xr getline 3 ,
so all error conditions that apply to
.Xr fgetln 3 ,
.Xr getline 3 ,
apply to
.Fn fparseln .
In addition
@@ -141,7 +141,7 @@ and return
.Dv NULL
if it runs out of memory.
.Sh SEE ALSO
.Xr fgetln 3
.Xr getline 3
.Sh HISTORY
The
.Fn fparseln

View File

@@ -32,13 +32,13 @@
.Ft void
.Fn MDXInit "MDX_CTX *context"
.Ft void
.Fn MDXUpdate "MDX_CTX *context" "const u_int8_t *data" "size_t len"
.Fn MDXUpdate "MDX_CTX *context" "const uint8_t *data" "size_t len"
.Ft void
.Fn MDXPad "MDX_CTX *context"
.Ft void
.Fn MDXFinal "u_int8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context"
.Fn MDXFinal "uint8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context"
.Ft void
.Fn MDXTransform "u_int32_t state[4]" "u_int8_t block[MDX_BLOCK_LENGTH]"
.Fn MDXTransform "uint32_t state[4]" "uint8_t block[MDX_BLOCK_LENGTH]"
.Ft "char *"
.Fn MDXEnd "MDX_CTX *context" "char *buf"
.Ft "char *"
@@ -46,7 +46,7 @@
.Ft "char *"
.Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn MDXData "const u_int8_t *data" "size_t len" "char *buf"
.Fn MDXData "const uint8_t *data" "size_t len" "char *buf"
.Sh DESCRIPTION
The MDX functions calculate a 128-bit cryptographic checksum (digest)
for any number of input bytes.

View File

@@ -9,7 +9,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 4. Neither the name of the University nor the names of its contributors
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
@@ -28,15 +28,17 @@
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
.\" $FreeBSD$
.\"
.Dd May 13, 2011
.Dt QUEUE 3bsd
.Dd June 17, 2013
.Dt QUEUE 3
.Os
.Sh NAME
.Nm SLIST_EMPTY ,
.Nm SLIST_ENTRY ,
.Nm SLIST_FIRST ,
.Nm SLIST_FOREACH ,
.Nm SLIST_FOREACH_FROM ,
.Nm SLIST_FOREACH_SAFE ,
.Nm SLIST_FOREACH_FROM_SAFE ,
.Nm SLIST_HEAD ,
.Nm SLIST_HEAD_INITIALIZER ,
.Nm SLIST_INIT ,
@@ -52,7 +54,9 @@
.Nm STAILQ_ENTRY ,
.Nm STAILQ_FIRST ,
.Nm STAILQ_FOREACH ,
.Nm STAILQ_FOREACH_FROM ,
.Nm STAILQ_FOREACH_SAFE ,
.Nm STAILQ_FOREACH_FROM_SAFE ,
.Nm STAILQ_HEAD ,
.Nm STAILQ_HEAD_INITIALIZER ,
.Nm STAILQ_INIT ,
@@ -69,7 +73,9 @@
.Nm LIST_ENTRY ,
.Nm LIST_FIRST ,
.Nm LIST_FOREACH ,
.Nm LIST_FOREACH_FROM ,
.Nm LIST_FOREACH_SAFE ,
.Nm LIST_FOREACH_FROM_SAFE ,
.Nm LIST_HEAD ,
.Nm LIST_HEAD_INITIALIZER ,
.Nm LIST_INIT ,
@@ -77,6 +83,7 @@
.Nm LIST_INSERT_BEFORE ,
.Nm LIST_INSERT_HEAD ,
.Nm LIST_NEXT ,
.Nm LIST_PREV ,
.Nm LIST_REMOVE ,
.Nm LIST_SWAP ,
.Nm TAILQ_CONCAT ,
@@ -84,9 +91,13 @@
.Nm TAILQ_ENTRY ,
.Nm TAILQ_FIRST ,
.Nm TAILQ_FOREACH ,
.Nm TAILQ_FOREACH_FROM ,
.Nm TAILQ_FOREACH_SAFE ,
.Nm TAILQ_FOREACH_FROM_SAFE ,
.Nm TAILQ_FOREACH_REVERSE ,
.Nm TAILQ_FOREACH_REVERSE_FROM ,
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
.Nm TAILQ_HEAD ,
.Nm TAILQ_HEAD_INITIALIZER ,
.Nm TAILQ_INIT ,
@@ -108,7 +119,9 @@ lists and tail queues
.Fn SLIST_ENTRY "TYPE"
.Fn SLIST_FIRST "SLIST_HEAD *head"
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_HEAD "HEADNAME" "TYPE"
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
.Fn SLIST_INIT "SLIST_HEAD *head"
@@ -125,7 +138,9 @@ lists and tail queues
.Fn STAILQ_ENTRY "TYPE"
.Fn STAILQ_FIRST "STAILQ_HEAD *head"
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_HEAD "HEADNAME" "TYPE"
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
.Fn STAILQ_INIT "STAILQ_HEAD *head"
@@ -143,7 +158,9 @@ lists and tail queues
.Fn LIST_ENTRY "TYPE"
.Fn LIST_FIRST "LIST_HEAD *head"
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_HEAD "HEADNAME" "TYPE"
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
.Fn LIST_INIT "LIST_HEAD *head"
@@ -151,6 +168,7 @@ lists and tail queues
.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_PREV "TYPE *elm" "LIST_HEAD *head" "TYPE" "LIST_ENTRY NAME"
.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
.\"
@@ -159,9 +177,13 @@ lists and tail queues
.Fn TAILQ_ENTRY "TYPE"
.Fn TAILQ_FIRST "TAILQ_HEAD *head"
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_HEAD "HEADNAME" "TYPE"
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
.Fn TAILQ_INIT "TAILQ_HEAD *head"
@@ -244,8 +266,18 @@ Code size and execution time of operations (except for removal) is about
twice that of the singly-linked data-structures.
.El
.Pp
Linked lists are the simplest of the doubly linked data structures and support
only the above functionality over singly-linked lists.
Linked lists are the simplest of the doubly linked data structures.
They add the following functionality over the above:
.Bl -enum -compact -offset indent
.It
They may be traversed backwards.
.El
However:
.Bl -enum -compact -offset indent
.It
To traverse backwards, an entry to begin the traversal and the list in
which it is contained must be specified.
.El
.Pp
Tail queues add the following functionality:
.Bl -enum -compact -offset indent
@@ -349,6 +381,19 @@ turn to
.Fa var .
.Pp
The macro
.Nm SLIST_FOREACH_FROM
behaves identically to
.Nm SLIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_FOREACH_SAFE
traverses the list referenced by
.Fa head
@@ -363,6 +408,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm SLIST_FOREACH_FROM_SAFE
behaves identically to
.Nm SLIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_INIT
initializes the list referenced by
.Fa head .
@@ -388,7 +446,8 @@ The macro
.Nm SLIST_REMOVE_AFTER
removes the element after
.Fa elm
from the list. Unlike
from the list.
Unlike
.Fa SLIST_REMOVE ,
this macro does not traverse the entire list.
.Pp
@@ -528,6 +587,19 @@ in turn to
.Fa var .
.Pp
The macro
.Nm STAILQ_FOREACH_FROM
behaves identically to
.Nm STAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_FOREACH_SAFE
traverses the tail queue referenced by
.Fa head
@@ -542,6 +614,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm STAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm STAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_INIT
initializes the tail queue referenced by
.Fa head .
@@ -579,7 +664,8 @@ The macro
.Nm STAILQ_REMOVE_AFTER
removes the element after
.Fa elm
from the tail queue. Unlike
from the tail queue.
Unlike
.Fa STAILQ_REMOVE ,
this macro does not traverse the entire tail queue.
.Pp
@@ -717,6 +803,19 @@ in the forward direction, assigning each element in turn to
.Fa var .
.Pp
The macro
.Nm LIST_FOREACH_FROM
behaves identically to
.Nm LIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_FOREACH_SAFE
traverses the list referenced by
.Fa head
@@ -730,6 +829,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm LIST_FOREACH_FROM_SAFE
behaves identically to
.Nm LIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_INIT
initializes the list referenced by
.Fa head .
@@ -759,6 +871,14 @@ The macro
returns the next element in the list, or NULL if this is the last.
.Pp
The macro
.Nm LIST_PREV
returns the previous element in the list, or NULL if this is the first.
List
.Fa head
must contain element
.Fa elm .
.Pp
The macro
.Nm LIST_REMOVE
removes the element
.Fa elm
@@ -894,12 +1014,38 @@ is set to
if the loop completes normally, or if there were no elements.
.Pp
The macro
.Nm TAILQ_FOREACH_FROM
behaves identically to
.Nm TAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE
traverses the tail queue referenced by
.Fa head
in the reverse direction, assigning each element in turn to
.Fa var .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM
behaves identically to
.Nm TAILQ_FOREACH_REVERSE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macros
.Nm TAILQ_FOREACH_SAFE
and
@@ -919,6 +1065,32 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm TAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_REVERSE_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_INIT
initializes the tail queue referenced by
.Fa head .

102
man/reallocarray.3 Normal file
View File

@@ -0,0 +1,102 @@
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the American National Standards Committee X3, on Information
.\" Processing Systems.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $OpenBSD: malloc.3,v 1.78 2014/05/01 18:41:59 jmc Exp $
.\"
.Dd $Mdocdate: May 1 2014 $
.Dt MALLOC 3
.Os
.Sh NAME
.Nm reallocarray
.Nd memory allocation and deallocation
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft void *
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
.Sh DESCRIPTION
.Pp
When using
.Fn malloc
be careful to avoid the following idiom:
.Bd -literal -offset indent
if ((p = malloc(num * size)) == NULL)
err(1, "malloc");
.Ed
.Pp
The multiplication may lead to an integer overflow, which can
be avoided using the extension
.Fn reallocarray ,
as follows:
.Bd -literal -offset indent
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, "malloc");
.Ed
.Pp
Alternatively
.Fn calloc
is a more portable solution which comes with the cost of clearing memory.
.Pp
If
.Fn malloc
must be used, be sure to test for overflow:
.Bd -literal -offset indent
if (size && num > SIZE_MAX / size) {
errno = ENOMEM;
err(1, "overflow");
}
.Ed
.Pp
The use of
.Fn reallocarray
or
.Fn calloc
is strongly encouraged when allocating multiple sized objects
in order to avoid possible integer overflows.
.Sh RETURN VALUES
The
.Fn reallocarray
function returns a pointer to the allocated space if successful; otherwise,
a null pointer is returned and
.Va errno
is set to
.Er ENOMEM .
.Sh SEE ALSO
.Xr malloc 3 ,
.Xr calloc 3 ,
.Xr alloca 3
.Sh HISTORY
.Fn reallocarray
appeared in
.Ox 5.6 .

View File

@@ -7,12 +7,23 @@ AM_CPPFLAGS = \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT
libbsd_la_included_sources = \
hash/helper.c \
getentropy_aix.c \
getentropy_bsd.c \
getentropy_hpux.c \
getentropy_hurd.c \
getentropy_linux.c \
getentropy_osx.c \
getentropy_solaris.c \
$(nil)
EXTRA_DIST = \
libbsd.map \
libbsd.pc.in \
libbsd-ctor.pc.in \
libbsd-overlay.pc.in \
hash/helper.c \
$(libbsd_la_included_sources) \
$(nil)
CLEANFILES = \
@@ -39,17 +50,24 @@ hash/md5hl.c: $(srcdir)/hash/helper.c
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \
libbsd.map
libbsd_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libbsd.map \
-version-number $(LIBBSD_ABI)
libbsd_la_SOURCES = \
arc4random.c \
arc4random.h \
arc4random_unix.h \
arc4random_openbsd.h \
arc4random_uniform.c \
bsd_getopt.c \
chacha_private.h \
closefrom.c \
dehumanize_number.c \
err.c \
expand_number.c \
explicit_bzero.c \
fgetln.c \
fgetwln.c \
flopen.c \
@@ -61,10 +79,13 @@ libbsd_la_SOURCES = \
getpeereid.c \
hash/md5.c \
hash/md5hl.c \
hash/sha512.h \
hash/sha512c.c \
heapsort.c \
humanize_number.c \
inet_net_pton.c \
local-elf.h \
local-link.h \
merge.c \
nlist.c \
pidfile.c \
@@ -88,6 +109,12 @@ libbsd_la_SOURCES = \
wcslcpy.c \
$(nil)
if !HAVE_GETENTROPY
libbsd_la_SOURCES += \
getentropy.c \
$(nil)
endif
libbsd_ctor_a_SOURCES = \
setproctitle_ctor.c \
$(nil)

View File

@@ -1,6 +1,11 @@
/* $OpenBSD: arc4random.c,v 1.53 2015/09/10 18:53:50 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2015, Guillem Jover <guillem@hadrons.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,281 +21,192 @@
*/
/*
* Arc4 random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* Here the stream cipher has been modified always to include the time
* when initializing the state. That makes it impossible to
* regenerate the same random sequence twice, so this can't be used
* for encryption, but will generate good random numbers.
*
* RC4 is a registered trademark of RSA Laboratories.
* ChaCha based random number generator for OpenBSD.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
struct arc4_stream {
u_int8_t i;
u_int8_t j;
u_int8_t s[256];
};
#define KEYSTREAM_ONLY
#include "chacha_private.h"
#define RANDOMDEV "/dev/urandom"
#define KEYSIZE 128
#define minimum(a, b) ((a) < (b) ? (a) : (b))
#ifdef __REENTRANT
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define THREAD_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define THREAD_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#else
#define THREAD_LOCK()
#define THREAD_UNLOCK()
#if defined(__GNUC__) || defined(_MSC_VER)
#define inline __inline
#else /* __GNUC__ || _MSC_VER */
#define inline
#endif /* !__GNUC__ && !_MSC_VER */
#define KEYSZ 32
#define IVSZ 8
#define BLOCKSZ 64
#define RSBUFSZ (16*BLOCKSZ)
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
static struct _rs {
size_t rs_have; /* valid bytes at end of rs_buf */
size_t rs_count; /* bytes till reseed */
} *rs;
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
static struct _rsx {
chacha_ctx rs_chacha; /* chacha context for random keystream */
u_char rs_buf[RSBUFSZ]; /* keystream blocks */
} *rsx;
static inline int _rs_allocate(struct _rs **, struct _rsx **);
static inline void _rs_forkdetect(void);
#include "arc4random.h"
static inline void
_rs_init(u_char *buf, size_t n)
{
if (n < KEYSZ + IVSZ)
return;
if (rs == NULL) {
if (_rs_allocate(&rs, &rsx) == -1)
abort();
}
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
}
static inline void
_rs_rekey(u_char *dat, size_t datlen)
{
#ifndef KEYSTREAM_ONLY
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
#endif
/* fill rs_buf with the keystream */
chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
rsx->rs_buf, sizeof(rsx->rs_buf));
/* mix in optional user provided data */
if (dat) {
size_t i, m;
static struct arc4_stream rs;
static int rs_initialized;
static int rs_stired;
static int arc4_count;
static inline u_int8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
arc4_init(void)
{
int n;
for (n = 0; n < 256; n++)
rs.s[n] = n;
rs.i = 0;
rs.j = 0;
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si + dat[n % datlen]);
rs.s[rs.i] = rs.s[rs.j];
rs.s[rs.j] = si;
m = minimum(datlen, KEYSZ + IVSZ);
for (i = 0; i < m; i++)
rsx->rs_buf[i] ^= dat[i];
}
rs.j = rs.i;
/* immediately reinit for backtracking resistance */
_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
}
static void
arc4_stir(void)
_rs_stir(void)
{
int done, fd, n;
struct {
struct timeval tv;
pid_t pid;
u_int8_t rnd[KEYSIZE];
} rdat;
u_char rnd[KEYSZ + IVSZ];
fd = open(RANDOMDEV, O_RDONLY, 0);
done = 0;
if (fd >= 0) {
if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
(void)close(fd);
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
/* We'll just take whatever was on the stack too... */
}
if (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
arc4_addrandom((u_char *)&rdat, KEYSIZE);
if (!rs)
_rs_init(rnd, sizeof(rnd));
else
_rs_rekey(rnd, sizeof(rnd));
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/*
* Throw away the first N bytes of output, as suggested in the
* paper "Weaknesses in the Key Scheduling Algorithm of RC4"
* by Fluher, Mantin, and Shamir. N=1024 is based on
* suggestions in the paper "(Not So) Random Shuffles of RC4"
* by Ilya Mironov.
*/
for (n = 0; n < 1024; n++)
(void) arc4_getbyte();
arc4_count = 1600000;
/* invalidate rs_buf */
rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
rs->rs_count = 1600000;
}
static inline u_int8_t
arc4_getbyte(void)
static inline void
_rs_stir_if_needed(size_t len)
{
u_int8_t si, sj;
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si);
sj = rs.s[rs.j];
rs.s[rs.i] = sj;
rs.s[rs.j] = si;
return (rs.s[(si + sj) & 0xff]);
_rs_forkdetect();
if (!rs || rs->rs_count <= len)
_rs_stir();
if (rs->rs_count <= len)
rs->rs_count = 0;
else
rs->rs_count -= len;
}
static inline u_int32_t
arc4_getword(void)
static inline void
_rs_random_buf(void *_buf, size_t n)
{
u_int32_t val;
u_char *buf = (u_char *)_buf;
u_char *keystream;
size_t m;
val = arc4_getbyte() << 24;
val |= arc4_getbyte() << 16;
val |= arc4_getbyte() << 8;
val |= arc4_getbyte();
return (val);
}
static void
arc4_check_init(void)
{
if (!rs_initialized) {
arc4_init();
rs_initialized = 1;
_rs_stir_if_needed(n);
while (n > 0) {
if (rs->rs_have > 0) {
m = minimum(n, rs->rs_have);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
- rs->rs_have;
memcpy(buf, keystream, m);
memset(keystream, 0, m);
buf += m;
n -= m;
rs->rs_have -= m;
}
if (rs->rs_have == 0)
_rs_rekey(NULL, 0);
}
}
static inline void
arc4_check_stir(void)
_rs_random_u32(uint32_t *val)
{
if (!rs_stired || arc4_count <= 0) {
arc4_stir();
rs_stired = 1;
}
u_char *keystream;
_rs_stir_if_needed(sizeof(*val));
if (rs->rs_have < sizeof(*val))
_rs_rekey(NULL, 0);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
memcpy(val, keystream, sizeof(*val));
memset(keystream, 0, sizeof(*val));
rs->rs_have -= sizeof(*val);
}
void
arc4random_stir(void)
{
THREAD_LOCK();
arc4_check_init();
arc4_stir();
rs_stired = 1;
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_stir();
_ARC4_UNLOCK();
}
void
arc4random_addrandom(u_char *dat, int datlen)
{
THREAD_LOCK();
arc4_check_init();
arc4_check_stir();
arc4_addrandom(dat, datlen);
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_stir_if_needed(datlen);
_rs_rekey(dat, datlen);
_ARC4_UNLOCK();
}
u_int32_t
uint32_t
arc4random(void)
{
u_int32_t rnd;
uint32_t val;
THREAD_LOCK();
arc4_check_init();
arc4_check_stir();
rnd = arc4_getword();
arc4_count -= 4;
THREAD_UNLOCK();
return (rnd);
_ARC4_LOCK();
_rs_random_u32(&val);
_ARC4_UNLOCK();
return val;
}
void
arc4random_buf(void *_buf, size_t n)
arc4random_buf(void *buf, size_t n)
{
u_char *buf = (u_char *)_buf;
THREAD_LOCK();
arc4_check_init();
while (n--) {
arc4_check_stir();
buf[n] = arc4_getbyte();
arc4_count--;
}
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_random_buf(buf, n);
_ARC4_UNLOCK();
}
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
u_int32_t
arc4random_uniform(u_int32_t upper_bound)
{
u_int32_t r, min;
if (upper_bound < 2)
return (0);
#if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound;
#else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if (upper_bound > 0x80000000)
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
}
#endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return (r % upper_bound);
}
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
#include <machine/pctr.h>
int
main(int argc, char **argv)
{
const int iter = 1000000;
int i;
pctrval v;
v = rdtsc();
for (i = 0; i < iter; i++)
arc4random();
v = rdtsc() - v;
v /= iter;
printf("%qd cycles\n", v);
}
#endif

41
src/arc4random.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSD_ARC4RANDOM_H
#define LIBBSD_ARC4RANDOM_H
#include <sys/param.h>
int
getentropy(void *buf, size_t len);
#if defined(__OpenBSD__)
#include "arc4random_openbsd.h"
#else
#include "arc4random_unix.h"
#endif
#endif

61
src/arc4random_openbsd.h Normal file
View File

@@ -0,0 +1,61 @@
/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <signal.h>
#include "thread_private.h"
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
struct {
struct _rs rs;
struct _rsx rsx;
} *p;
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) {
munmap(p, sizeof(*p));
return (-1);
}
*rsp = &p->rs;
*rsxp = &p->rsx;
return (0);
}
static inline void
_rs_forkdetect(void)
{
}

57
src/arc4random_uniform.c Normal file
View File

@@ -0,0 +1,57 @@
/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */
/*
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
uint32_t
arc4random_uniform(uint32_t upper_bound)
{
uint32_t r, min;
if (upper_bound < 2)
return 0;
/* 2**32 % x == (2**32 - x) % x */
min = -upper_bound % upper_bound;
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return r % upper_bound;
}
//DEF_WEAK(arc4random_uniform);

92
src/arc4random_unix.h Normal file
View File

@@ -0,0 +1,92 @@
/* $OpenBSD: arc4random_linux.h,v 1.8 2014/08/13 06:04:10 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#ifdef __GLIBC__
extern void *__dso_handle;
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
#else
/*
* Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
* a program does not link to -lthr. Callbacks registered with pthread_atfork()
* appear to fail silently. So, it is not always possible to detect a PID
* wraparound.
*/
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
#endif
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static volatile sig_atomic_t _rs_forked;
static inline void
_rs_forkhandler(void)
{
_rs_forked = 1;
}
static inline void
_rs_forkdetect(void)
{
static pid_t _rs_pid = 0;
pid_t pid = getpid();
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
_rs_pid = pid;
_rs_forked = 0;
if (rs)
memset(rs, 0, sizeof(*rs));
}
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsp, sizeof(**rsp));
return (-1);
}
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

222
src/chacha_private.h Normal file
View File

@@ -0,0 +1,222 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
/* $OpenBSD$ */
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct
{
u32 input[16]; /* could be compressed */
} chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((u8)(v) & U8C(0xFF))
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((u32)((p)[0]) ) | \
((u32)((p)[1]) << 8) | \
((u32)((p)[2]) << 16) | \
((u32)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
static void
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
{
x->input[12] = 0;
x->input[13] = 0;
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
static void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
u8 *ctarget = NULL;
u8 tmp[64];
u_int i;
if (!bytes) return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20;i > 0;i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
QUARTERROUND( x3, x7,x11,x15)
QUARTERROUND( x0, x5,x10,x15)
QUARTERROUND( x1, x6,x11,x12)
QUARTERROUND( x2, x7, x8,x13)
QUARTERROUND( x3, x4, x9,x14)
}
x0 = PLUS(x0,j0);
x1 = PLUS(x1,j1);
x2 = PLUS(x2,j2);
x3 = PLUS(x3,j3);
x4 = PLUS(x4,j4);
x5 = PLUS(x5,j5);
x6 = PLUS(x6,j6);
x7 = PLUS(x7,j7);
x8 = PLUS(x8,j8);
x9 = PLUS(x9,j9);
x10 = PLUS(x10,j10);
x11 = PLUS(x11,j11);
x12 = PLUS(x12,j12);
x13 = PLUS(x13,j13);
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
#ifndef KEYSTREAM_ONLY
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
x3 = XOR(x3,U8TO32_LITTLE(m + 12));
x4 = XOR(x4,U8TO32_LITTLE(m + 16));
x5 = XOR(x5,U8TO32_LITTLE(m + 20));
x6 = XOR(x6,U8TO32_LITTLE(m + 24));
x7 = XOR(x7,U8TO32_LITTLE(m + 28));
x8 = XOR(x8,U8TO32_LITTLE(m + 32));
x9 = XOR(x9,U8TO32_LITTLE(m + 36));
x10 = XOR(x10,U8TO32_LITTLE(m + 40));
x11 = XOR(x11,U8TO32_LITTLE(m + 44));
x12 = XOR(x12,U8TO32_LITTLE(m + 48));
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
#endif
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0,x0);
U32TO8_LITTLE(c + 4,x1);
U32TO8_LITTLE(c + 8,x2);
U32TO8_LITTLE(c + 12,x3);
U32TO8_LITTLE(c + 16,x4);
U32TO8_LITTLE(c + 20,x5);
U32TO8_LITTLE(c + 24,x6);
U32TO8_LITTLE(c + 28,x7);
U32TO8_LITTLE(c + 32,x8);
U32TO8_LITTLE(c + 36,x9);
U32TO8_LITTLE(c + 40,x10);
U32TO8_LITTLE(c + 44,x11);
U32TO8_LITTLE(c + 48,x12);
U32TO8_LITTLE(c + 52,x13);
U32TO8_LITTLE(c + 56,x14);
U32TO8_LITTLE(c + 60,x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
#ifndef KEYSTREAM_ONLY
m += 64;
#endif
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005, 2007, 2010
* Copyright (c) 2004-2005, 2007, 2010, 2012-2014
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -18,7 +18,6 @@
#include <config.h>
#include <sys/types.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#ifdef STDC_HEADERS
@@ -30,20 +29,26 @@
# endif
#endif /* STDC_HEADERS */
#include <fcntl.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#include <limits.h>
#ifdef HAVE_PSTAT_GETPROC
# include <sys/param.h>
# include <sys/pstat.h>
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
# endif
#endif
@@ -51,15 +56,24 @@
# define OPEN_MAX 256
#endif
#ifndef HAVE_FCNTL_CLOSEM
# ifndef HAVE_DIRFD
# define closefrom_fallback closefrom
# endif
#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
# define closefrom closefrom_fallback
#endif
static inline void
closefrom_close(int fd)
{
#ifdef __APPLE__
/* Avoid potential libdispatch crash when we close its fds. */
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#else
(void)close(fd);
#endif
}
/*
* Close all file descriptors greater than or equal to lowfd.
* This is the expensive (ballback) method.
* This is the expensive (fallback) method.
*/
void
closefrom_fallback(int lowfd)
@@ -80,43 +94,99 @@ closefrom_fallback(int lowfd)
maxfd = OPEN_MAX;
for (fd = lowfd; fd < maxfd; fd++)
(void)close((int)fd);
closefrom_close(fd);
}
/*
* Close all file descriptors greater than or equal to lowfd.
* We try the fast way first, falling back on the slow method.
*/
#ifdef HAVE_FCNTL_CLOSEM
#if defined(HAVE_FCNTL_CLOSEM)
void
closefrom(int lowfd)
{
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
closefrom_fallback(lowfd);
}
#else
# ifdef HAVE_DIRFD
#elif defined(HAVE_PSTAT_GETPROC)
void
closefrom(int lowfd)
{
struct dirent *dent;
DIR *dirp;
char *endp;
long fd;
struct pst_status pstat;
int fd;
/* Use /proc/self/fd directory if it exists. */
dirp = opendir("/proc/self/fd");
if (dirp != NULL) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd &&
fd != dirfd(dirp))
(void)close((int)fd);
}
(void)closedir(dirp);
} else
if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {
for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
(void)close(fd);
} else {
closefrom_fallback(lowfd);
}
}
#elif defined(HAVE_DIRFD)
static int
closefrom_procfs(int lowfd)
{
const char *path;
DIR *dirp;
struct dirent *dent;
int *fd_array = NULL;
int fd_array_used = 0;
int fd_array_size = 0;
int ret = 0;
int i;
/* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
path = "/dev/fd";
# else
path = "/proc/self/fd";
# endif
dirp = opendir(path);
if (dirp == NULL)
return -1;
while ((dent = readdir(dirp)) != NULL) {
const char *errstr;
int fd;
fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr != NULL || fd == dirfd(dirp))
continue;
if (fd_array_used >= fd_array_size) {
int *ptr;
if (fd_array_size > 0)
fd_array_size *= 2;
else
fd_array_size = 32;
ptr = reallocarray(fd_array, fd_array_size, sizeof(int));
if (ptr == NULL) {
ret = -1;
break;
}
fd_array = ptr;
}
fd_array[fd_array_used++] = fd;
}
for (i = 0; i < fd_array_used; i++)
closefrom_close(fd_array[i]);
free(fd_array);
(void)closedir(dirp);
return ret;
}
void
closefrom(int lowfd)
{
if (closefrom_procfs(lowfd) == 0)
return;
closefrom_fallback(lowfd);
}
#endif /* HAVE_DIRFD */
#endif /* HAVE_FCNTL_CLOSEM */

19
src/explicit_bzero.c Normal file
View File

@@ -0,0 +1,19 @@
/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
/*
* Public domain.
* Written by Matthew Dempsky.
*/
#include <string.h>
__attribute__((weak)) void
__explicit_bzero_hook(void *buf, size_t len)
{
}
void
explicit_bzero(void *buf, size_t len)
{
memset(buf, 0, len);
__explicit_bzero_hook(buf, len);
}

View File

@@ -30,6 +30,8 @@
#include <sys/types.h>
#include <string.h>
#include "local-link.h"
#ifdef HAVE_GETLINE
struct filebuf {
FILE *fp;
@@ -48,6 +50,8 @@ fgetln(FILE *stream, size_t *len)
struct filebuf *fb;
ssize_t nread;
flockfile(stream);
/* Try to diminish the possibility of several fgetln() calls being
* used on different streams, by using a pool of buffers per file. */
fb = &fb_pool[fb_pool_cur];
@@ -59,6 +63,9 @@ fgetln(FILE *stream, size_t *len)
fb->fp = stream;
nread = getline(&fb->buf, &fb->len, stream);
funlockfile(stream);
/* Note: the getdelim/getline API ensures nread != 0. */
if (nread == -1) {
*len = 0;
@@ -68,6 +75,9 @@ fgetln(FILE *stream, size_t *len)
return fb->buf;
}
}
libbsd_link_warning(fgetln,
"This functions cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.")
#else
#error "Function fgetln() needs to be ported."
#endif

View File

@@ -68,7 +68,7 @@ fgetwln(FILE *stream, size_t *lenp)
else
fb->len = FILEWBUF_INIT_LEN;
wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t));
wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
if (wp == NULL) {
wused = 0;
break;

View File

@@ -35,8 +35,6 @@ __RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
#include <string.h>
#include <stdlib.h>
#define FLOCKFILE(fp)
#define FUNLOCKFILE(fp)
#define _DIAGASSERT(t)
static int isescaped(const char *, const char *, int);
@@ -77,7 +75,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
{
static const char dstr[3] = { '\\', '\\', '#' };
size_t s, len;
ssize_t s;
size_t len, ptrlen;
char *buf;
char *ptr, *cp;
int cnt;
@@ -87,6 +86,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
len = 0;
buf = NULL;
ptrlen = 0;
ptr = NULL;
cnt = 1;
if (str == NULL)
@@ -97,11 +98,11 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
com = str[2];
/*
* XXX: it would be cool to be able to specify the newline character,
* but unfortunately, fgetln does not let us
* getdelim(3) does let us, but supporting it would diverge from BSDs.
*/
nl = '\n';
FLOCKFILE(fp);
flockfile(fp);
while (cnt) {
cnt = 0;
@@ -109,7 +110,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
if (lineno)
(*lineno)++;
if ((ptr = fgetln(fp, &s)) == NULL)
s = getline(&ptr, &ptrlen, fp);
if (s < 0)
break;
if (s && com) { /* Check and eliminate comments */
@@ -147,8 +149,9 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
}
if ((cp = realloc(buf, len + s + 1)) == NULL) {
FUNLOCKFILE(fp);
funlockfile(fp);
free(buf);
free(ptr);
return NULL;
}
buf = cp;
@@ -158,7 +161,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
buf[len] = '\0';
}
FUNLOCKFILE(fp);
funlockfile(fp);
free(ptr);
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
strchr(buf, esc) != NULL) {
@@ -195,36 +199,3 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
*size = len;
return buf;
}
#ifdef TEST
int main(int, char **);
int
main(int argc, char **argv)
{
char *ptr;
size_t size, line;
line = 0;
while ((ptr = fparseln(stdin, &size, &line, NULL,
FPARSELN_UNESCALL)) != NULL)
printf("line %d (%d) |%s|\n", line, size, ptr);
return 0;
}
/*
# This is a test
line 1
line 2 \
line 3 # Comment
line 4 \# Not comment \\\\
# And a comment \
line 5 \\\
line 6
*/
#endif /* TEST */

View File

@@ -44,23 +44,3 @@ fpurge(FILE *fp)
#else
#error "Function fpurge() needs to be ported."
#endif
#ifdef TEST
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}
#endif

45
src/getentropy.c Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__linux__)
#include "getentropy_linux.c"
#elif defined(__GNU__)
#include "getentropy_hurd.c"
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "getentropy_bsd.c"
#elif defined(__NetBSD__)
#include "getentropy_bsd.c"
#elif defined(__sun)
#include "getentropy_solaris.c"
#elif defined(__APPLE__)
#include "getentropy_osx.c"
#elif defined(_AIX)
#include "getentropy_aix.c"
#elif defined(__hpux)
#include "getentropy_hpux.c"
#else
#error "No getentropy hooks defined for this platform."
#endif

425
src/getentropy_aix.c Normal file
View File

@@ -0,0 +1,425 @@
/* $OpenBSD: getentropy_aix.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2015 Michael Felt <aixtools@gmail.com>
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
/*
* -lperfstat is needed for the psuedo entropy data
*/
#include <sys/mman.h>
#include <sys/procfs.h>
#include <sys/protosw.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/timers.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include "hash/sha512.h"
#include <libperfstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on AIX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that AIX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that AIX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
perfstat_cpu_total_t cpustats;
#ifdef _AIX61
perfstat_cpu_total_wpar_t cpustats_wpar;
#endif
perfstat_partition_total_t lparstats;
perfstat_disk_total_t diskinfo;
perfstat_netinterface_total_t netinfo;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(perfstat_cpu_total(NULL, &cpustats,
sizeof(cpustats), 1) == -1, cpustats);
#ifdef _AIX61
HX(perfstat_cpu_total_wpar(NULL, &cpustats_wpar,
sizeof(cpustats_wpar), 1) == -1, cpustats_wpar);
#endif
HX(perfstat_partition_total(NULL, &lparstats,
sizeof(lparstats), 1) == -1, lparstats);
HX(perfstat_disk_total(NULL, &diskinfo,
sizeof(diskinfo), 1) == -1, diskinfo);
HX(perfstat_netinterface_total(NULL, &netinfo,
sizeof(netinfo), 1) == -1, netinfo);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

62
src/getentropy_bsd.c Normal file
View File

@@ -0,0 +1,62 @@
/* $OpenBSD: getentropy_freebsd.c,v 1.1 2014/11/03 06:23:30 bcook Exp $ */
/*
* Copyright (c) 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2014 Brent Cook <bcook@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <stddef.h>
/*
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
*/
static size_t
getentropy_sysctl(u_char *buf, size_t size)
{
int mib[2];
size_t len, done;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
done = 0;
do {
len = size;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return (done);
done += len;
buf += len;
size -= len;
} while (size > 0);
return (done);
}
int
getentropy(void *buf, size_t len)
{
if (len <= 256 && getentropy_sysctl(buf, len) == len)
return (0);
errno = EIO;
return (-1);
}

420
src/getentropy_hpux.c Normal file
View File

@@ -0,0 +1,420 @@
/* $OpenBSD: getentropy_hpux.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#include <sys/vfs.h>
#include <sys/pstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on hpux that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that hpux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that hpux should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct pst_vminfo pvi;
struct pst_vm_status pvs;
struct pst_dynamic pdy;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
HD(errno);
} else {
HD(pdy.psd_avg_1_min);
HD(pdy.psd_avg_5_min);
HD(pdy.psd_avg_15_min);
}
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

446
src/getentropy_hurd.c Normal file
View File

@@ -0,0 +1,446 @@
/* $OpenBSD: getentropy_linux.c,v 1.40 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len);
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy. See the large
* comment block above.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Hurd
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Hurd should either get a
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
if (p)
HD(p);
#endif
#endif
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

548
src/getentropy_linux.c Normal file
View File

@@ -0,0 +1,548 @@
/* $OpenBSD: getentropy_linux.c,v 1.40 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#ifdef SYS__sysctl
#include <linux/sysctl.h>
#endif
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#include <linux/types.h>
#include <linux/random.h>
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
#ifdef SYS_getrandom
static int getentropy_getrandom(void *buf, size_t len);
#endif
static int getentropy_urandom(void *buf, size_t len);
#ifdef SYS__sysctl
static int getentropy_sysctl(void *buf, size_t len);
#endif
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
#ifdef SYS_getrandom
/*
* Try descriptor-less getrandom()
*/
ret = getentropy_getrandom(buf, len);
if (ret != -1)
return (ret);
if (errno != ENOSYS)
return (-1);
#endif
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
#ifdef SYS__sysctl
/*
* Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
* sysctl is a failsafe API, so it guarantees a result. This
* should work inside a chroot, or when file descriptors are
* exhuasted.
*
* However this can fail if the Linux kernel removes support
* for sysctl. Starting in 2007, there have been efforts to
* deprecate the sysctl API/ABI, and push callers towards use
* of the chroot-unavailable fd-using /proc mechanism --
* essentially the same problems as /dev/urandom.
*
* Numerous setbacks have been encountered in their deprecation
* schedule, so as of June 2014 the kernel ABI still exists on
* most Linux architectures. The sysctl() stub in libc is missing
* on some systems. There are also reports that some kernels
* spew messages to the console.
*/
ret = getentropy_sysctl(buf, len);
if (ret != -1)
return (ret);
#endif /* SYS__sysctl */
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy. See the large
* comment block above.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Linux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Linux should either retain their
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
#ifdef SYS_getrandom
static int
getentropy_getrandom(void *buf, size_t len)
{
int pre_errno = errno;
int ret;
if (len > 256)
return (-1);
do {
ret = syscall(SYS_getrandom, buf, len, 0);
} while (ret == -1 && errno == EINTR);
if (ret != (int)len)
return (-1);
errno = pre_errno;
return (0);
}
#endif
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, cnt, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
#ifdef SYS__sysctl
static int
getentropy_sysctl(void *buf, size_t len)
{
static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
size_t i;
int save_errno = errno;
for (i = 0; i < len; ) {
size_t chunk = min(len - i, 16);
/* SYS__sysctl because some systems already removed sysctl() */
struct __sysctl_args args = {
.name = mib,
.nlen = 3,
.oldval = (char *)buf + i,
.oldlenp = &chunk,
};
if (syscall(SYS__sysctl, &args) != 0)
goto sysctlfailed;
i += chunk;
}
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
sysctlfailed:
errno = EIO;
return (-1);
}
#endif /* SYS__sysctl */
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
if (p)
HD(p);
#endif
#endif
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

429
src/getentropy_osx.c Normal file
View File

@@ -0,0 +1,429 @@
/* $OpenBSD: getentropy_osx.c,v 1.8 2014/07/21 20:19:47 guenther Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <mach/mach_time.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <sys/socketvar.h>
#include <sys/vmmeter.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
#include <netinet/udp_var.h>
#include <CommonCrypto/CommonDigest.h>
#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
#define SHA512_CTX CC_SHA512_CTX
#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on OSX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that OSX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that OSX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
static int kmib[] = { CTL_KERN, KERN_USRSTACK };
static int hwmib[] = { CTL_HW, HW_USERMEM };
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
struct tcpstat tcpstat;
struct udpstat udpstat;
struct ipstat ipstat;
uint64_t mach_time;
unsigned int idata;
void *addr;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
mach_time = mach_absolute_time();
HD(mach_time);
ii = sizeof(addr);
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
&addr, &ii, NULL, 0) == -1, addr);
ii = sizeof(idata);
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
&idata, &ii, NULL, 0) == -1, idata);
ii = sizeof(tcpstat);
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
&tcpstat, &ii, NULL, 0) == -1, tcpstat);
ii = sizeof(udpstat);
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
&udpstat, &ii, NULL, 0) == -1, udpstat);
ii = sizeof(ipstat);
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
&ipstat, &ii, NULL, 0) == -1, ipstat);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
mach_time = mach_absolute_time();
HD(mach_time);
cnt += (int)mach_time;
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

445
src/getentropy_solaris.c Normal file
View File

@@ -0,0 +1,445 @@
/* $OpenBSD: getentropy_solaris.c,v 1.10 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/sha2.h>
#define SHA512_Init SHA512Init
#define SHA512_Update SHA512Update
#define SHA512_Final SHA512Final
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <sys/loadavg.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* Solaris provides /dev/urandom as a symbolic link to
* /devices/pseudo/random@0:urandom which is provided by
* a devfs filesystem. Best practice is to use O_NOFOLLOW,
* so we must try the unpublished name directly.
*
* This can fail if the process is inside a chroot which lacks
* the devfs mount, or if file descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len,
"/devices/pseudo/random@0:urandom", 1);
if (ret != -1)
return (ret);
/*
* Unfortunately, chroot spaces on Solaris are sometimes setup
* with direct device node of the well-known /dev/urandom name
* (perhaps to avoid dragging all of devfs into the space).
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on Solaris that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Solaris
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Solaris should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
(devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
double loadavg[3];
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
HX((getloadavg(loadavg, 3) == -1), loadavg);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

View File

@@ -27,7 +27,7 @@ char *
HASHEnd(HASH_CTX *ctx, char *buf)
{
int i;
u_int8_t digest[HASH_DIGEST_LENGTH];
uint8_t digest[HASH_DIGEST_LENGTH];
#ifdef HASH_DIGEST_UPPERCASE
static const char hex[] = "0123456789ABCDEF";
#else

View File

@@ -37,7 +37,7 @@
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -71,7 +71,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
need = MD5_BLOCK_LENGTH - have;
/* Update bitcount */
ctx->count += (u_int64_t)len << 3;
ctx->count += (uint64_t)len << 3;
if (len >= need) {
if (have != 0) {
@@ -102,7 +102,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
void
MD5Pad(MD5_CTX *ctx)
{
u_int8_t count[8];
uint8_t count[8];
size_t padlen;
/* Convert count to 8 bytes in little endian order. */
@@ -152,19 +152,19 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
#if BYTE_ORDER == LITTLE_ENDIAN
memcpy(in, block, sizeof(in));
#else
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
in[a] = (u_int32_t)(
(u_int32_t)(block[a * 4 + 0]) |
(u_int32_t)(block[a * 4 + 1]) << 8 |
(u_int32_t)(block[a * 4 + 2]) << 16 |
(u_int32_t)(block[a * 4 + 3]) << 24);
in[a] = (uint32_t)(
(uint32_t)(block[a * 4 + 0]) |
(uint32_t)(block[a * 4 + 1]) << 8 |
(uint32_t)(block[a * 4 + 2]) << 16 |
(uint32_t)(block[a * 4 + 3]) << 24);
}
#endif

53
src/hash/sha512.h Normal file
View File

@@ -0,0 +1,53 @@
/*-
* Copyright 2005 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SHA512_H_
#define _SHA512_H_
#include <sys/types.h>
#define SHA512_DIGEST_LENGTH 64
typedef struct SHA512Context {
uint64_t state[8];
uint64_t count[2];
unsigned char buf[128];
} SHA512_CTX;
__BEGIN_DECLS
void SHA512_Init(SHA512_CTX *);
void SHA512_Update(SHA512_CTX *, const void *, size_t);
void SHA512_Final(unsigned char [64], SHA512_CTX *);
char *SHA512_End(SHA512_CTX *, char *);
char *SHA512_File(const char *, char *);
char *SHA512_FileChunk(const char *, char *, off_t, off_t);
char *SHA512_Data(const void *, unsigned int, char *);
__END_DECLS
#endif /* !_SHA512_H_ */

320
src/hash/sha512c.c Normal file
View File

@@ -0,0 +1,320 @@
/*-
* Copyright 2005 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/types.h>
#include <string.h>
#include "sha512.h"
#if BYTE_ORDER == BIG_ENDIAN
/* Copy a vector of big-endian uint64_t into a vector of bytes */
#define be64enc_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
/* Copy a vector of bytes into a vector of big-endian uint64_t */
#define be64dec_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
#else /* BYTE_ORDER != BIG_ENDIAN */
/*
* Encode a length len/4 vector of (uint64_t) into a length len vector of
* (unsigned char) in big-endian form. Assumes len is a multiple of 8.
*/
static void
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
be64enc(dst + i * 8, src[i]);
}
/*
* Decode a big-endian length len vector of (unsigned char) into a length
* len/4 vector of (uint64_t). Assumes len is a multiple of 8.
*/
static void
be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
dst[i] = be64dec(src + i * 8);
}
#endif /* BYTE_ORDER != BIG_ENDIAN */
/* Elementary functions used by SHA512 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
/* SHA512 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(80 - i) % 8], S[(81 - i) % 8], \
S[(82 - i) % 8], S[(83 - i) % 8], \
S[(84 - i) % 8], S[(85 - i) % 8], \
S[(86 - i) % 8], S[(87 - i) % 8], \
W[i] + k)
/*
* SHA512 block compression function. The 512-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA512_Transform(uint64_t * state, const unsigned char block[128])
{
uint64_t W[80];
uint64_t S[8];
uint64_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be64dec_vect(W, block, 128);
for (i = 16; i < 80; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 64);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
RNDr(S, W, 1, 0x7137449123ef65cdULL);
RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
RNDr(S, W, 4, 0x3956c25bf348b538ULL);
RNDr(S, W, 5, 0x59f111f1b605d019ULL);
RNDr(S, W, 6, 0x923f82a4af194f9bULL);
RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
RNDr(S, W, 8, 0xd807aa98a3030242ULL);
RNDr(S, W, 9, 0x12835b0145706fbeULL);
RNDr(S, W, 10, 0x243185be4ee4b28cULL);
RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
RNDr(S, W, 12, 0x72be5d74f27b896fULL);
RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
RNDr(S, W, 15, 0xc19bf174cf692694ULL);
RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
RNDr(S, W, 23, 0x76f988da831153b5ULL);
RNDr(S, W, 24, 0x983e5152ee66dfabULL);
RNDr(S, W, 25, 0xa831c66d2db43210ULL);
RNDr(S, W, 26, 0xb00327c898fb213fULL);
RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
RNDr(S, W, 29, 0xd5a79147930aa725ULL);
RNDr(S, W, 30, 0x06ca6351e003826fULL);
RNDr(S, W, 31, 0x142929670a0e6e70ULL);
RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
RNDr(S, W, 35, 0x53380d139d95b3dfULL);
RNDr(S, W, 36, 0x650a73548baf63deULL);
RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
RNDr(S, W, 39, 0x92722c851482353bULL);
RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
RNDr(S, W, 41, 0xa81a664bbc423001ULL);
RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
RNDr(S, W, 43, 0xc76c51a30654be30ULL);
RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
RNDr(S, W, 45, 0xd69906245565a910ULL);
RNDr(S, W, 46, 0xf40e35855771202aULL);
RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
RNDr(S, W, 49, 0x1e376c085141ab53ULL);
RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
RNDr(S, W, 57, 0x78a5636f43172f60ULL);
RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
RNDr(S, W, 59, 0x8cc702081a6439ecULL);
RNDr(S, W, 60, 0x90befffa23631e28ULL);
RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
RNDr(S, W, 63, 0xc67178f2e372532bULL);
RNDr(S, W, 64, 0xca273eceea26619cULL);
RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
RNDr(S, W, 68, 0x06f067aa72176fbaULL);
RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
RNDr(S, W, 70, 0x113f9804bef90daeULL);
RNDr(S, W, 71, 0x1b710b35131c471bULL);
RNDr(S, W, 72, 0x28db77f523047d84ULL);
RNDr(S, W, 73, 0x32caab7b40c72493ULL);
RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
RNDr(S, W, 75, 0x431d67c49c100d4cULL);
RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
RNDr(S, W, 77, 0x597f299cfc657e2aULL);
RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
RNDr(S, W, 79, 0x6c44198c4a475817ULL);
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
static unsigned char PAD[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA512_Pad(SHA512_CTX * ctx)
{
unsigned char len[16];
uint64_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc_vect(len, ctx->count, 16);
/* Add 1--128 bytes so that the resulting length is 112 mod 128 */
r = (ctx->count[1] >> 3) & 0x7f;
plen = (r < 112) ? (112 - r) : (240 - r);
SHA512_Update(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count */
SHA512_Update(ctx, len, 16);
}
/* SHA-512 initialization. Begins a SHA-512 operation. */
void
SHA512_Init(SHA512_CTX * ctx)
{
/* Zero bits processed so far */
ctx->count[0] = ctx->count[1] = 0;
/* Magic initialization constants */
ctx->state[0] = 0x6a09e667f3bcc908ULL;
ctx->state[1] = 0xbb67ae8584caa73bULL;
ctx->state[2] = 0x3c6ef372fe94f82bULL;
ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
ctx->state[4] = 0x510e527fade682d1ULL;
ctx->state[5] = 0x9b05688c2b3e6c1fULL;
ctx->state[6] = 0x1f83d9abfb41bd6bULL;
ctx->state[7] = 0x5be0cd19137e2179ULL;
}
/* Add bytes into the hash */
void
SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
{
uint64_t bitlen[2];
uint64_t r;
const unsigned char *src = in;
/* Number of bytes left in the buffer from previous updates */
r = (ctx->count[1] >> 3) & 0x7f;
/* Convert the length into a number of bits */
bitlen[1] = ((uint64_t)len) << 3;
bitlen[0] = ((uint64_t)len) >> 61;
/* Update number of bits */
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
ctx->count[0]++;
ctx->count[0] += bitlen[0];
/* Handle the case where we don't need to perform any transforms */
if (len < 128 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block */
memcpy(&ctx->buf[r], src, 128 - r);
SHA512_Transform(ctx->state, ctx->buf);
src += 128 - r;
len -= 128 - r;
/* Perform complete blocks */
while (len >= 128) {
SHA512_Transform(ctx->state, src);
src += 128;
len -= 128;
}
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
}
/*
* SHA-512 finalization. Pads the input data, exports the hash value,
* and clears the context state.
*/
void
SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
{
/* Add padding */
SHA512_Pad(ctx);
/* Write the hash */
be64enc_vect(digest, ctx->state, 64);
/* Clear the context state */
memset((void *)ctx, 0, sizeof(*ctx));
}

View File

@@ -130,10 +130,8 @@
* only advantage over quicksort is that it requires little additional memory.
*/
int
heapsort(vbase, nmemb, size, compar)
void *vbase;
size_t nmemb, size;
int (*compar)(const void *, const void *);
heapsort(void *vbase, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
size_t cnt, i, j, l;
char tmp, *tmp1, *tmp2;

View File

@@ -55,11 +55,7 @@ static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size);
* Paul Vixie (ISC), June 1996
*/
int
inet_net_pton(af, src, dst, size)
int af;
const char *src;
void *dst;
size_t size;
inet_net_pton(int af, const char *src, void *dst, size_t size)
{
switch (af) {
case AF_INET:
@@ -87,10 +83,7 @@ inet_net_pton(af, src, dst, size)
* Paul Vixie (ISC), June 1996
*/
static int
inet_net_pton_ipv4(src, dst, size)
const char *src;
u_char *dst;
size_t size;
inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
{
static const char
xdigits[] = "0123456789abcdef",

View File

@@ -132,3 +132,7 @@ LIBBSD_0.7 {
_time_to_int;
_int_to_time;
} LIBBSD_0.6;
LIBBSD_0.8 {
explicit_bzero;
} LIBBSD_0.7;

View File

@@ -134,6 +134,12 @@
#define ELF_TARG_DATA ELFDATA2LSB
#endif
#elif defined(__nios2__)
#define ELF_TARG_MACH EM_ALTERA_NIOS2
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__powerpc__)
#define ELF_TARG_MACH EM_PPC

33
src/local-link.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSD_LOCAL_LINK_H
#define LIBBSD_LOCAL_LINK_H
#define libbsd_link_warning(symbol, msg) \
static const char libbsd_emit_link_warning_##symbol[] \
__attribute__((used,section(".gnu.warning." #symbol))) = msg;
#endif

View File

@@ -95,11 +95,8 @@ static void insertionsort(u_char *, size_t, size_t,
* Arguments are as for qsort.
*/
int
mergesort(base, nmemb, size, cmp)
void *base;
size_t nmemb;
size_t size;
int (*cmp)(const void *, const void *);
mergesort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *))
{
size_t i;
int sense;
@@ -258,11 +255,9 @@ COPY: b = t;
* when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
* is defined. Otherwise simple pairwise merging is used.)
*/
void
setup(list1, list2, n, size, cmp)
size_t n, size;
int (*cmp)(const void *, const void *);
u_char *list1, *list2;
static void
setup(u_char *list1, u_char *list2, size_t n, size_t size,
int (*cmp)(const void *, const void *))
{
int i, length, size2, tmp, sense;
u_char *f1, *f2, *s, *l2, *last, *p2;
@@ -333,10 +328,8 @@ setup(list1, list2, n, size, cmp)
* last 4 elements.
*/
static void
insertionsort(a, n, size, cmp)
u_char *a;
size_t n, size;
int (*cmp)(const void *, const void *);
insertionsort(u_char *a, size_t n, size_t size,
int (*cmp)(const void *, const void *))
{
u_char *ai, *s, *t, *u, tmp;
int i;

View File

@@ -70,9 +70,7 @@ static int __elf_fdnlist(int, struct nlist *);
int __fdnlist(int, struct nlist *);
int
nlist(name, list)
const char *name;
struct nlist *list;
nlist(const char *name, struct nlist *list)
{
int fd, n;
@@ -96,9 +94,7 @@ static struct nlist_handlers {
};
int
__fdnlist(fd, list)
int fd;
struct nlist *list;
__fdnlist(int fd, struct nlist *list)
{
size_t i;
int n = -1;
@@ -115,9 +111,7 @@ __fdnlist(fd, list)
#ifdef _NLIST_DO_AOUT
static int
__aout_fdnlist(fd, list)
int fd;
struct nlist *list;
__aout_fdnlist(int fd, struct nlist *list)
{
struct nlist *p, *symtab;
caddr_t strtab, a_out_mmap;
@@ -220,8 +214,7 @@ static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int);
* as such its use should be restricted.
*/
static int
__elf_is_okay__(ehdr)
Elf_Ehdr *ehdr;
__elf_is_okay__(Elf_Ehdr *ehdr)
{
int retval = 0;
/*
@@ -244,9 +237,7 @@ __elf_is_okay__(ehdr)
}
static int
__elf_fdnlist(fd, list)
int fd;
struct nlist *list;
__elf_fdnlist(int fd, struct nlist *list)
{
struct nlist *p;
Elf_Off symoff = 0, symstroff = 0;
@@ -386,11 +377,7 @@ __elf_fdnlist(fd, list)
* n_value and n_type members.
*/
static void
elf_sym_to_nlist(nl, s, shdr, shnum)
struct nlist *nl;
Elf_Sym *s;
Elf_Shdr *shdr;
int shnum;
elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
{
nl->n_value = s->st_value;

View File

@@ -118,7 +118,8 @@ sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
if (n < THRESHOLD)
simplesort(a, n, 0, tr, endch);
else {
if ((ta = malloc(n * sizeof(a))) == NULL)
ta = reallocarray(NULL, n, sizeof(a));
if (ta == NULL)
return (-1);
r_sort_b(a, ta, n, 0, tr, endch);
free(ta);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
@@ -24,7 +24,7 @@
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)

View File

@@ -154,7 +154,7 @@ common: if (set->cmd2 & CMD2_CLR) {
if (set >= endset) { \
BITCMD *newset; \
setlen += SET_LEN_INCR; \
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
newset = reallocarray(saveset, setlen, sizeof(BITCMD)); \
if (newset == NULL) \
goto out; \
set = newset + (set - saveset); \
@@ -197,7 +197,8 @@ setmode(const char *p)
setlen = SET_LEN + 2;
if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
set = reallocarray(NULL, setlen, sizeof(BITCMD));
if (set == NULL)
return (NULL);
saveset = set;
endset = set + (setlen - 2);

View File

@@ -67,7 +67,7 @@ sl_init(void)
sl->sl_cur = 0;
sl->sl_max = _SL_CHUNKSIZE;
sl->sl_str = malloc(sl->sl_max * sizeof(char *));
sl->sl_str = reallocarray(NULL, sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL) {
free(sl);
sl = NULL;
@@ -88,8 +88,8 @@ sl_add(StringList *sl, char *name)
if (sl->sl_cur == sl->sl_max - 1) {
char **new;
new = realloc(sl->sl_str,
(sl->sl_max + _SL_CHUNKSIZE) * sizeof(char *));
new = reallocarray(sl->sl_str,
(sl->sl_max + _SL_CHUNKSIZE), sizeof(char *));
if (new == NULL)
return -1;
sl->sl_max += _SL_CHUNKSIZE;

View File

@@ -37,9 +37,7 @@ static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
#include <string.h>
void
strmode(mode, p)
mode_t mode;
char *p;
strmode(mode_t mode, char *p)
{
/* print type */
switch (mode & S_IFMT) {

8
test/.gitignore vendored
View File

@@ -1,8 +1,14 @@
arc4random
bzero
closefrom
endian
fgetln
funopen
headers
fparseln
fpurge
headers-gen.c
humanize
overlay
proctitle-init
proctitle
strmode

View File

@@ -1,36 +1,69 @@
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = \
HEADERS_CPPFLAGS = \
-I$(top_builddir) \
-isystem $(top_srcdir)/include/bsd/ \
-include $(top_builddir)/config.h \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
-DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT
AM_CPPFLAGS = \
-isystem $(top_srcdir)/include/bsd/ \
$(HEADERS_CPPFLAGS) \
-DLIBBSD_OVERLAY
AM_TESTS_ENVIRONMENT = \
export CC="$(CC)"; \
export CPPFLAGS="$(HEADERS_CPPFLAGS)"; \
export top_srcdir="$(top_srcdir)"; \
$(nil)
LDADD = $(top_builddir)/src/libbsd.la
EXTRA_DIST = \
headers-overlay.sh \
headers-system.sh \
$(nil)
check_SCRIPTS = \
headers-overlay.sh \
headers-system.sh \
$(nil)
check_PROGRAMS = \
headers \
overlay \
bzero \
closefrom \
endian \
humanize \
fgetln \
funopen \
fparseln \
fpurge \
proctitle-init \
strmode \
$(nil)
if BUILD_LIBBSD_CTOR
check_PROGRAMS += proctitle
if HAVE_LIBTESTU01
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
check_PROGRAMS += arc4random
endif
humanize_LDFLAGS = $(top_builddir)/src/libbsd.la
fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
funopen_LDFLAGS = $(top_builddir)/src/libbsd.la
proctitle_init_SOURCES = proctitle.c
proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
proctitle_init_LDFLAGS = $(top_builddir)/src/libbsd.la
if BUILD_LIBBSD_CTOR
proctitle_LDFLAGS = \
-Wl,-u,libbsd_init_func \
$(top_builddir)/src/libbsd-ctor.a \
$(top_builddir)/src/libbsd.la \
$(nil)
TESTS = $(check_PROGRAMS)
check_PROGRAMS += proctitle
endif
fgetln_SOURCES = test-stream.c test-stream.h fgetln.c
fgetln_CFLAGS = -Wno-deprecated-declarations
fparseln_SOURCES = test-stream.c test-stream.h fparseln.c
proctitle_init_SOURCES = proctitle.c
proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)

105
test/arc4random.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <testu01/gdef.h>
#include <testu01/unif01.h>
#include <testu01/swrite.h>
#include <testu01/bbattery.h>
#define TEST_OK 0
#define TEST_SKIP 77
#define TEST_DIE 99
#define test_print(msg, ...) \
printf("TEST: " msg "\n", __VA_ARGS__)
#define test_res(idx, name, pval, action) \
test_print("[%4d] (%s) pVal[%d] = %f -> %s", \
idx, name[idx], i, pval[idx], action)
static int test_failed = 0;
static void
test_battery_result(void)
{
char **testNames = bbattery_TestNames;
double *pVal = bbattery_pVal;
double pSuspect = 0.001;
test_print("bbattery_NTests = %d", bbattery_NTests);
for (int i = 0; i < bbattery_NTests; i++) {
/* That test was not done: pVal = -1. */
if (pVal[i] < 0.0) {
test_res(i, testNames, pVal, "SKIP");
continue;
}
/* That test passed or failed. */
if ((pVal[i] >= pSuspect) &&
(pVal[i] <= 1.0 - pSuspect)) {
test_res(i, testNames, pVal, "PASS");
} else {
test_res(i, testNames, pVal, "FAIL");
test_failed++;
}
}
}
int
main(int argc, char **argv)
{
unif01_Gen *gen;
int rc;
gen = unif01_CreateExternGenBits("arc4random", arc4random);
/* XXX: The following battery does not set pVal, so we cannot check
* the results. */
bbattery_FIPS_140_2(gen);
/* XXX: The following battery fails one test. */
bbattery_pseudoDIEHARD(gen);
test_battery_result();
bbattery_Rabbit(gen, 33554432);
test_battery_result();
bbattery_SmallCrush(gen);
test_battery_result();
unif01_DeleteExternGenBits(gen);
if (test_failed) {
test_print("failed tests = %d", test_failed);
/* XXX: We should probably FAIL the test, but we currently
* have one test always failing. */
rc = TEST_SKIP;
}
return rc;
}

47
test/bzero.c Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <string.h>
int
main()
{
unsigned char array[40];
size_t i;
memset(array, 0x3e, sizeof(array));
explicit_bzero(array, 0);
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0x3e);
explicit_bzero(array, sizeof(array));
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0);
return 0;
}

53
test/closefrom.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int
main()
{
int i;
int fd;
fd = open("/dev/null", O_RDONLY);
for (i = 4; i < 1024; i *= 2)
assert(dup2(fd, i) == i);
if (fd < 4)
close(fd);
closefrom(4);
for (i = 4; i < 1024; i++)
assert(fcntl(i, F_GETFL) == -1 && errno == EBADF);
assert(fcntl(fd, F_GETFL) == -1 && errno == EBADF);
return 0;
}

View File

@@ -24,15 +24,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include "test-stream.h"
#define skip(msg) \
do { \
printf("skip: %s\n", (msg)); \
@@ -67,58 +67,6 @@ struct file {
int got_len;
};
static FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
static void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}
static void
test_fgetln_single(void)
{
@@ -149,7 +97,7 @@ test_fgetln_multi(void)
str = strdup("A\n");
str[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str;
files[i].lines[1] = str;
files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
@@ -211,7 +159,7 @@ test_fgetwln_multi(void)
wstr = wcsdup(L"A\n");
wstr[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr;
files[i].lines[1] = wstr;
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);

92
test/fparseln.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test-stream.h"
#define TEST_LINES 9
static const char *data_test[] = {
"# This is a test\n",
"line 1\n",
"line 2 \\\n",
"line 3 # Comment\n",
"line 4 \\# Not comment \\\\\\\\\n",
"\n",
"# And a comment \\\n",
"line 5 \\\\\\\n",
"line 6 w/ escape sequences \\b, \\t, \\\\t",
};
#define EXPECT_LINES 5
static size_t lineno_expect[] = { 2, 4, 5, 6, 9 };
static const char *data_parse[] = {
"line 1",
"line 2 line 3 ",
"line 4 \\# Not comment \\\\\\\\",
"",
"line 5 \\\\line 6 w/ escape sequences \\b, \\t, \\\\t",
};
static const char *data_escape[] = {
"line 1",
"line 2 line 3 ",
"line 4 # Not comment \\\\",
"",
"line 5 \\line 6 w/ escape sequences b, t, \\t",
};
static void
test_fparseln(const char **data_expect, int flags)
{
FILE *fp;
size_t i, len, lineno = 0;
fp = pipe_feed("%s", (const void **)data_test, TEST_LINES);
for (i = 0; i < EXPECT_LINES; i++) {
char *str = fparseln(fp, &len, &lineno, NULL, flags);
assert(str);
assert(lineno == lineno_expect[i]);
assert(strcmp(str, data_expect[i]) == 0);
free(str);
}
assert(fparseln(fp, &len, NULL, NULL, 0) == NULL);
pipe_close(fp);
}
int
main(int argc, char **argv)
{
test_fparseln(data_parse, 0);
test_fparseln(data_escape, FPARSELN_UNESCALL);
return 0;
}

48
test/fpurge.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(NULL) == 0)
return 1;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}

25
test/headers-overlay.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -e
run()
{
echo "$@"
"$@"
}
incdir="${top_srcdir}/include/bsd"
CPPFLAGS="$CPPFLAGS -DLIBBSD_OVERLAY"
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
cat >headers-gen.c <<SOURCE
#include <$inc>
int main() { return 0; }
SOURCE
echo "testing header $inc"
run $CC -isystem "$incdir" $CPPFLAGS headers-gen.c -o /dev/null
echo
rm -f headers-gen*
done

24
test/headers-system.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -e
run()
{
echo "$@"
"$@"
}
incdir="${top_srcdir}/include"
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
cat >headers-gen.c <<SOURCE
#include <$inc>
int main() { return 0; }
SOURCE
echo "testing header $inc"
run $CC -isystem "$incdir" $CPPFLAGS headers-gen.c -o /dev/null
echo
rm -f headers-gen.*
done

View File

@@ -1,25 +0,0 @@
/* Check that all libbsd overlayed headers preprocess. */
#include <sys/cdefs.h>
#include <sys/endian.h>
#include <sys/bitstring.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/poll.h>
#include <err.h>
#include <getopt.h>
#include <libutil.h>
#include <md5.h>
#include <nlist.h>
#include <readpassphrase.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vis.h>
int
main()
{
return 0;
}

View File

@@ -1,3 +1,29 @@
/*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Include system headers that are “known” to pull bits selectively from
* other headers through magic macros, to check that the overlay is working
* properly. */

View File

@@ -36,6 +36,7 @@ main(int argc, char **argv, char **envp)
const char newtitle_base[] = "test arg1 arg2";
char *newtitle_full;
char *envvar;
int rc;
#ifdef TEST_USE_SETPROCTITLE_INIT
setproctitle_init(argc, argv, envp);
@@ -44,7 +45,8 @@ main(int argc, char **argv, char **envp)
setproctitle("-test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_base) == 0);
asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
rc = asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
assert(rc > 0);
setproctitle("test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_full) == 0);
free(newtitle_full);

69
test/strmode.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <string.h>
int
main(int argc, char **argv)
{
char mode_str[12];
strmode(0, mode_str);
assert(strcmp(mode_str, "?--------- ") == 0);
strmode(0777, mode_str);
assert(strcmp(mode_str, "?rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG, mode_str);
assert(strcmp(mode_str, "-rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwsrwsrwt ") == 0);
strmode(0666 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwSrwSrwT ") == 0);
strmode(0777 | S_IFLNK, mode_str);
assert(strcmp(mode_str, "lrwxrwxrwx ") == 0);
strmode(0777 | S_IFCHR, mode_str);
assert(strcmp(mode_str, "crwxrwxrwx ") == 0);
strmode(0777 | S_IFBLK, mode_str);
assert(strcmp(mode_str, "brwxrwxrwx ") == 0);
strmode(0777 | S_IFDIR, mode_str);
assert(strcmp(mode_str, "drwxrwxrwx ") == 0);
strmode(0777 | S_IFIFO, mode_str);
assert(strcmp(mode_str, "prwxrwxrwx ") == 0);
strmode(0777 | S_IFSOCK, mode_str);
assert(strcmp(mode_str, "srwxrwxrwx ") == 0);
return 0;
}

84
test/test-stream.c Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include "test-stream.h"
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}

37
test/test-stream.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSD_TEST_STREAM
#define LIBBSD_TEST_STREAM
#include <stdio.h>
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb);
void
pipe_close(FILE *fp);
#endif