diff -Nru spiped-1.6.1/BUILDING spiped-1.6.2/BUILDING --- spiped-1.6.1/BUILDING 2017-01-27 22:38:34.000000000 +0000 +++ spiped-1.6.2/BUILDING 2020-09-02 04:32:10.000000000 +0000 @@ -43,6 +43,14 @@ or LDADD_EXTRA="-L/usr/sfw/lib -lsocket -lnsl" (linker option) to the make command line. +- On Solaris, the command-line utilities in /usr/bin are not + necessarily POSIX-compatible. According to standards(7), in order to use + POSIX.1-2008 standard-conforming utilities, you must set your PATH so that + certain directories (such as /usr/xpg4/bin/) take precedence over /usr/bin. + Please check the documentation in your version of Solaris by: + $ man standards + and carefully read the "Utilities" section. + - On some platforms (OpenBSD prior to 5.4, and possibly others) you will need to add #include at the start of lib/dnsthread/dnsthread.c diff -Nru spiped-1.6.1/CHANGELOG spiped-1.6.2/CHANGELOG --- spiped-1.6.1/CHANGELOG 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/CHANGELOG 2021-12-24 19:28:07.000000000 +0000 @@ -1,3 +1,9 @@ +spiped-1.6.2 +* Warn if the maximum number of connections is reached in spiped. +* Add --syslog (spiped) to send warnings to syslog when daemonized. +* Significantly improve performance of AES-CTR and SHA256 on amd64 and aarch64. +* Add ability to suppress POSIX runtime checks during compilation to simplify + cross-compiling. spiped-1.6.1 * New option -u username:groupname (spiped): change the user and/or group ownership of the process. diff -Nru spiped-1.6.1/COPYRIGHT spiped-1.6.2/COPYRIGHT --- spiped-1.6.1/COPYRIGHT 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/COPYRIGHT 2021-12-10 06:06:24.000000000 +0000 @@ -1,8 +1,8 @@ The included code and documentation ("spiped") is distributed under the following terms: -Copyright 2005-2016 Colin Percival. All rights reserved. -Copyright 2005-2016 Tarsnap Backup Inc. All rights reserved. +Copyright 2005-2021 Colin Percival. All rights reserved. +Copyright 2011-2021 Tarsnap Backup Inc. All rights reserved. Copyright 2014 Sean Kelly. All rights reserved. Redistribution and use in source and binary forms, with or without diff -Nru spiped-1.6.1/debian/changelog spiped-1.6.2/debian/changelog --- spiped-1.6.1/debian/changelog 2021-11-24 10:24:45.000000000 +0000 +++ spiped-1.6.2/debian/changelog 2021-12-26 03:35:50.000000000 +0000 @@ -1,8 +1,41 @@ -spiped (1.6.1-2build1) jammy; urgency=medium +spiped (1.6.2-1) unstable; urgency=medium - * No-change rebuild against openssl3 + * New upstream release. + * Upload to unstable. - -- Simon Chopin Wed, 24 Nov 2021 11:24:45 +0100 + -- Peter Pentchev Sun, 26 Dec 2021 05:35:50 +0200 + +spiped (1.6.1.99.1-1) experimental; urgency=medium + + * New upstream release: + - drop the arm-non-aarch64 and clean-tests patches, both implemented + in a better way upstream + + -- Peter Pentchev Sun, 19 Dec 2021 03:57:26 +0200 + +spiped (1.6.1.99-2) experimental; urgency=medium + + * Add the arm-non-aarch64 patch to fix the armhf build. + * Pass -q0 to netcat in the autopkgtest to make sure it exits. + * Add the clean-tests patch to clean another directory up. + + -- Peter Pentchev Fri, 10 Dec 2021 23:51:17 +0200 + +spiped (1.6.1.99-1) experimental; urgency=medium + + * Declare compliance with Debian Policy 4.6.0 with no changes. + * Add the year 2021 to my debian/* copyright notice. + * Override Lintian "line too long" complaints for source files + listed in several Makefiles. + * Explicitly specify dh-sequence-single-binary as a virtual build + dependency. + * New upstream prerelease: + - update the upstream copyright years + - refresh the line numbers in the debian-build patch + * Fix the debian/tests/simple autopkgtest's options handling. + * Run the debian/tests/simple autopkgtest during the build, too. + + -- Peter Pentchev Fri, 10 Dec 2021 16:14:52 +0200 spiped (1.6.1-2) unstable; urgency=medium diff -Nru spiped-1.6.1/debian/control spiped-1.6.2/debian/control --- spiped-1.6.1/debian/control 2020-09-13 20:51:41.000000000 +0000 +++ spiped-1.6.2/debian/control 2021-12-26 03:35:50.000000000 +0000 @@ -2,8 +2,14 @@ Section: utils Priority: optional Maintainer: Peter Pentchev -Build-Depends: debhelper-compat (= 13), libssl-dev, procps -Standards-Version: 4.5.0 +Build-Depends: + debhelper-compat (= 13), + dh-sequence-single-binary, + libssl-dev, + procps, + netcat-openbsd , + perl , +Standards-Version: 4.6.0 Homepage: https://www.tarsnap.com/spiped.html Vcs-Git: https://gitlab.com/spiped/spiped.git -b debian/master Vcs-Browser: https://gitlab.com/spiped/spiped/tree/debian/master diff -Nru spiped-1.6.1/debian/copyright spiped-1.6.2/debian/copyright --- spiped-1.6.1/debian/copyright 2020-09-13 20:51:41.000000000 +0000 +++ spiped-1.6.2/debian/copyright 2021-12-26 03:35:50.000000000 +0000 @@ -6,8 +6,8 @@ Files: * Copyright: - Copyright 2005-2016 Colin Percival. All rights reserved. - Copyright 2005-2016 Tarsnap Backup Inc. All rights reserved. + Copyright 2005-2021 Colin Percival. All rights reserved. + Copyright 2005-2021 Tarsnap Backup Inc. All rights reserved. Copyright 2014 Sean Kelly. All rights reserved. License: BSD-2-clause @@ -18,7 +18,7 @@ License: BSD-2-clause Files: debian/* -Copyright: 2012-2014, 2016-2020 Peter Pentchev +Copyright: 2012-2014, 2016-2021 Peter Pentchev License: BSD-2-clause License: BSD-2-clause diff -Nru spiped-1.6.1/debian/patches/debian-build.patch spiped-1.6.2/debian/patches/debian-build.patch --- spiped-1.6.1/debian/patches/debian-build.patch 2020-09-13 20:51:41.000000000 +0000 +++ spiped-1.6.2/debian/patches/debian-build.patch 2021-12-26 03:35:50.000000000 +0000 @@ -7,7 +7,7 @@ --- a/spipe/Makefile +++ b/spipe/Makefile -@@ -19,16 +19,11 @@ +@@ -20,16 +20,11 @@ install:${PROG} mkdir -p ${BINDIR} @@ -28,7 +28,7 @@ --- a/spiped/Makefile +++ b/spiped/Makefile -@@ -19,16 +19,11 @@ +@@ -20,16 +20,11 @@ install:${PROG} mkdir -p ${BINDIR} diff -Nru spiped-1.6.1/debian/rules spiped-1.6.2/debian/rules --- spiped-1.6.1/debian/rules 2020-09-13 20:51:41.000000000 +0000 +++ spiped-1.6.2/debian/rules 2021-12-26 03:35:50.000000000 +0000 @@ -17,6 +17,9 @@ %: dh $@ +execute_after_dh_auto_test: + '${CURDIR}/debian/tests/simple' -c '${CURDIR}/spipe/spipe' -s '${CURDIR}/spiped/spiped' + override_dh_auto_install: dh_auto_install -- \ 'BINDIR=${CURDIR}/debian/spiped/usr/bin' \ diff -Nru spiped-1.6.1/debian/source/lintian-overrides spiped-1.6.2/debian/source/lintian-overrides --- spiped-1.6.1/debian/source/lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/debian/source/lintian-overrides 2021-12-26 03:35:50.000000000 +0000 @@ -0,0 +1,5 @@ +# The upstream Makefiles contain long lists of files that are +# not split across lines. +# +spiped source: very-long-line-length-in-source-file liball/Makefile * +spiped source: very-long-line-length-in-source-file perftests/standalone-enc/Makefile * diff -Nru spiped-1.6.1/debian/tests/simple spiped-1.6.2/debian/tests/simple --- spiped-1.6.1/debian/tests/simple 2020-09-13 20:51:41.000000000 +0000 +++ spiped-1.6.2/debian/tests/simple 2021-12-26 03:35:50.000000000 +0000 @@ -44,9 +44,9 @@ MAIN: { my %opts; - getopts 'c:s:C:S:t:', \%opts or usage; + getopts 'c:d:e:s:t:', \%opts or usage; my $spipecmd = $opts{c} // 'spipe'; - my $spipedcmd = $opts{d} // 'spiped'; + my $spipedcmd = $opts{s} // 'spiped'; my $decport = $opts{d} // 8086; my $encport = $opts{e} // 6502; my $token = $opts{t} // 'mellon'; @@ -75,7 +75,7 @@ say "Starting nc..."; my %pid; - $pid{nc} = open my $nc, '|-', 'nc', '-l', '-p', $decport or + $pid{nc} = open my $nc, '|-', 'nc', '-q', '0', '-l', '-p', $decport or die "Could not execute 'nc': $!\n"; if (!defined $pid{nc}) { die "Could not start nc: $!\n"; diff -Nru spiped-1.6.1/lib/dnsthread/dnsthread.c spiped-1.6.2/lib/dnsthread/dnsthread.c --- spiped-1.6.1/lib/dnsthread/dnsthread.c 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/lib/dnsthread/dnsthread.c 2020-12-05 21:26:44.000000000 +0000 @@ -156,7 +156,7 @@ /** * dnsthread_spawn(void): * Spawn a thread for performing address resolution. Return a token which can - * be passed to dnsthread_resolveone and dnsthread_kill. + * be passed to dnsthread_resolveone() and dnsthread_kill(). */ DNSTHREAD dnsthread_spawn(void) @@ -226,9 +226,9 @@ /** * dnsthread_resolveone(T, addr, callback, cookie): - * Using the thread for which ${T} was returned by dnsthread_spawn, resolve - * the address ${addr}, which must be in one of the forms accepted by the - * sock_resolve function. If ${T} is already resolving an address, do not + * Using the thread for which ${T} was returned by dnsthread_spawn(), resolve + * the address ${addr}, which must be in one of the forms accepted by + * sock_resolve(). If ${T} is already resolving an address, do not * resolve this address and instead return with errno == EALREADY. Upon * completion, invoke ${callback}(${cookie}, sas), where ${sas} is a * NULL-terminated array of pointers to sock_addr structures or NULL on diff -Nru spiped-1.6.1/lib/dnsthread/dnsthread.h spiped-1.6.2/lib/dnsthread/dnsthread.h --- spiped-1.6.1/lib/dnsthread/dnsthread.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/lib/dnsthread/dnsthread.h 2020-12-05 21:26:44.000000000 +0000 @@ -10,15 +10,15 @@ /** * dnsthread_spawn(void): * Spawn a thread for performing address resolution. Return a token which can - * be passed to dnsthread_resolveone and dnsthread_kill. + * be passed to dnsthread_resolveone() and dnsthread_kill(). */ DNSTHREAD dnsthread_spawn(void); /** * dnsthread_resolveone(T, addr, callback, cookie): - * Using the thread for which ${T} was returned by dnsthread_spawn, resolve - * the address ${addr}, which must be in one of the forms accepted by the - * sock_resolve function. If ${T} is already resolving an address, do not + * Using the thread for which ${T} was returned by dnsthread_spawn(), resolve + * the address ${addr}, which must be in one of the forms accepted by + * sock_resolve(). If ${T} is already resolving an address, do not * resolve this address and instead return with errno == EALREADY. Upon * completion, invoke ${callback}(${cookie}, sas), where ${sas} is a * NULL-terminated array of pointers to sock_addr structures or NULL on diff -Nru spiped-1.6.1/lib/proto/proto_conn.c spiped-1.6.2/lib/proto/proto_conn.c --- spiped-1.6.1/lib/proto/proto_conn.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_conn.c 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,402 @@ +#include + +#include +#include + +#include +#include +#include + +#include "events.h" +#include "network.h" +#include "sock.h" + +#include "proto_crypt.h" +#include "proto_handshake.h" +#include "proto_pipe.h" + +#include "proto_conn.h" + +struct conn_state { + int (* callback_dead)(void *, int); + void * cookie; + struct sock_addr ** sas; + int decr; + int nopfs; + int requirepfs; + int nokeepalive; + const struct proto_secret * K; + double timeo; + int s; + int t; + void * connect_cookie; + void * connect_timeout_cookie; + void * handshake_cookie; + void * handshake_timeout_cookie; + struct proto_keys * k_f; + struct proto_keys * k_r; + void * pipe_f; + void * pipe_r; + int stat_f; + int stat_r; +}; + +static int callback_connect_done(void *, int); +static int callback_connect_timeout(void *); +static int callback_handshake_done(void *, struct proto_keys *, + struct proto_keys *); +static int callback_handshake_timeout(void *); +static int callback_pipestatus(void *); + +/* Start a handshake. */ +static int +starthandshake(struct conn_state * C, int s, int decr) +{ + + /* Start the handshake timer. */ + if ((C->handshake_timeout_cookie = events_timer_register_double( + callback_handshake_timeout, C, C->timeo)) == NULL) + goto err0; + + /* Start the handshake. */ + if ((C->handshake_cookie = proto_handshake(s, decr, C->nopfs, + C->requirepfs, C->K, callback_handshake_done, C)) == NULL) + goto err1; + + /* Success! */ + return (0); + +err1: + events_timer_cancel(C->handshake_timeout_cookie); + C->handshake_timeout_cookie = NULL; +err0: + /* Failure! */ + return (-1); +} + +/* Launch the two pipes. */ +static int +launchpipes(struct conn_state * C) +{ + int on = C->nokeepalive ? 0 : 1; + int one = 1; + + /* + * Attempt to turn keepalives on or off as requested. We ignore + * failures here since the sockets might not be of a type for which + * SO_KEEPALIVE is valid -- it is a socket level option, but protocol + * specific. In particular, it has no sensible meaning for UNIX + * sockets. + */ + (void)setsockopt(C->s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + (void)setsockopt(C->t, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + + /** + * Attempt to turn off nagling on both sockets. If the TCP stack has + * enough window space that it is always able to send packets, then on + * the encrypted end this will result in every 1060-byte spiped packet + * getting its own TCP segment, including 40 bytes of TCP/IP headers; + * this is fine. On the unencrypted end, we might send a single byte + * of data with 40 bytes of TCP/IP headers; this is not so good. + * + * However, a write over the unencrypted connection will only happen + * after an spiped packet has been read from the encrypted connection, + * so the worst case is 80 bytes of TCP/IP headers per 1061 bytes of + * TCP/IP payload (this may still be only a single byte of spiped + * payload, but that is not relevant to the question of overhead from + * small TCP/IP segments); and while the two sockets might not be on + * the same network, if they are on different networks it is almost + * guaranteed that the network over which the encrypted connection is + * passing would be a wider-area network which is both less secure and + * more expensive. Consequently, the maximum TCP/IP overhead ratio of + * 80/1061 is almost certain to hold even with weighted byte costs. + * + * We ignore errors since (as with keep-alives) we may be dealing with + * a non-TCP socket; and also because while POSIX requires TCP_NODELAY + * to be defined, it is not required to be implemented as a socket + * option. + */ + (void)setsockopt(C->s, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); + (void)setsockopt(C->t, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); + + /* Create two pipes. */ + if ((C->pipe_f = proto_pipe(C->s, C->t, C->decr, C->k_f, + &C->stat_f, callback_pipestatus, C)) == NULL) + goto err0; + if ((C->pipe_r = proto_pipe(C->t, C->s, !C->decr, C->k_r, + &C->stat_r, callback_pipestatus, C)) == NULL) + goto err0; + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/** + * proto_conn_drop(conn_cookie, reason): + * Drop connection and free memory associated with ${conn_cookie}, due to + * ${reason}. Return success or failure. + */ +int +proto_conn_drop(void * conn_cookie, int reason) +{ + struct conn_state * C = conn_cookie; + int rc; + + /* Close the incoming connection. */ + close(C->s); + + /* Close the outgoing connection if it is open. */ + if (C->t != -1) + close(C->t); + + /* Stop connecting if a connection is in progress. */ + if (C->connect_cookie != NULL) + network_connect_cancel(C->connect_cookie); + + /* Free the target addresses if we haven't already done so. */ + sock_addr_freelist(C->sas); + + /* Stop handshaking if a handshake is in progress. */ + if (C->handshake_cookie != NULL) + proto_handshake_cancel(C->handshake_cookie); + + /* Kill timeouts if they are pending. */ + if (C->connect_timeout_cookie != NULL) + events_timer_cancel(C->connect_timeout_cookie); + if (C->handshake_timeout_cookie != NULL) + events_timer_cancel(C->handshake_timeout_cookie); + + /* Free protocol keys. */ + proto_crypt_free(C->k_f); + proto_crypt_free(C->k_r); + + /* Shut down pipes. */ + if (C->pipe_f != NULL) + proto_pipe_cancel(C->pipe_f); + if (C->pipe_r != NULL) + proto_pipe_cancel(C->pipe_r); + + /* Notify the upstream that we've dropped a connection. */ + rc = (C->callback_dead)(C->cookie, reason); + + /* Free the connection cookie. */ + free(C); + + /* Return success/fail status. */ + return (rc); +} + +/** + * proto_conn_create(s, sas, decr, nopfs, requirepfs, nokeepalive, K, timeo, + * callback_dead, cookie): + * Create a connection with one end at ${s} and the other end connecting to + * the target addresses ${sas}. If ${decr} is 0, encrypt the outgoing data; + * if ${decr} is nonzero, decrypt the incoming data. If ${nopfs} is non-zero, + * don't use perfect forward secrecy. If ${requirepfs} is non-zero, drop + * the connection if the other end tries to disable perfect forward secrecy. + * Enable transport layer keep-alives (if applicable) on both sockets if and + * only if ${nokeepalive} is zero. Drop the connection if the handshake or + * connecting to the target takes more than ${timeo} seconds. When the + * connection is dropped, invoke ${callback_dead}(${cookie}). Free ${sas} + * once it is no longer needed. Return a cookie which can be passed to + * proto_conn_drop(). If there is a connection error after this + * function returns, close ${s}. + */ +void * +proto_conn_create(int s, struct sock_addr ** sas, int decr, int nopfs, + int requirepfs, int nokeepalive, const struct proto_secret * K, + double timeo, int (* callback_dead)(void *, int), void * cookie) +{ + struct conn_state * C; + + /* Bake a cookie for this connection. */ + if ((C = malloc(sizeof(struct conn_state))) == NULL) + goto err0; + C->callback_dead = callback_dead; + C->cookie = cookie; + C->sas = sas; + C->decr = decr; + C->nopfs = nopfs; + C->requirepfs = requirepfs; + C->nokeepalive = nokeepalive; + C->K = K; + C->timeo = timeo; + C->s = s; + C->t = -1; + C->connect_cookie = NULL; + C->connect_timeout_cookie = NULL; + C->handshake_cookie = NULL; + C->handshake_timeout_cookie = NULL; + C->k_f = C->k_r = NULL; + C->pipe_f = C->pipe_r = NULL; + C->stat_f = C->stat_r = 1; + + /* Start the connect timer. */ + if ((C->connect_timeout_cookie = events_timer_register_double( + callback_connect_timeout, C, C->timeo)) == NULL) + goto err1; + + /* Connect to target. */ + if ((C->connect_cookie = + network_connect(C->sas, callback_connect_done, C)) == NULL) + goto err2; + + /* If we're decrypting, start the handshake. */ + if (C->decr) { + if (starthandshake(C, C->s, C->decr)) + goto err3; + } + + /* Success! */ + return (C); + +err3: + network_connect_cancel(C->connect_cookie); +err2: + events_timer_cancel(C->connect_timeout_cookie); +err1: + free(C); +err0: + /* Failure! */ + return (NULL); +} + +/* We have connected to the target. */ +static int +callback_connect_done(void * cookie, int t) +{ + struct conn_state * C = cookie; + + /* This connection attempt is no longer pending. */ + C->connect_cookie = NULL; + + /* Don't need the target address any more. */ + sock_addr_freelist(C->sas); + C->sas = NULL; + + /* We beat the clock. */ + events_timer_cancel(C->connect_timeout_cookie); + C->connect_timeout_cookie = NULL; + + /* Did we manage to connect? */ + if ((C->t = t) == -1) + return (proto_conn_drop(C, PROTO_CONN_CONNECT_FAILED)); + + /* If we're encrypting, start the handshake. */ + if (!C->decr) { + if (starthandshake(C, C->t, C->decr)) + goto err1; + } + + /* If the handshake already finished, start shuttling data. */ + if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { + if (launchpipes(C)) + goto err1; + } + + /* Success! */ + return (0); + +err1: + proto_conn_drop(C, PROTO_CONN_ERROR); + + /* Failure! */ + return (-1); +} + +/* Connecting to the target took too long. */ +static int +callback_connect_timeout(void * cookie) +{ + struct conn_state * C = cookie; + + /* This timeout is no longer pending. */ + C->connect_timeout_cookie = NULL; + + /* + * We could free C->sas here, but from a semantic point of view it + * could still be in use by the not-yet-cancelled connect operation. + * Instead, we free it in proto_conn_drop, after cancelling the + * connect. + */ + + /* Drop the connection. */ + return (proto_conn_drop(C, PROTO_CONN_ERROR)); +} + +/* We have performed the protocol handshake. */ +static int +callback_handshake_done(void * cookie, struct proto_keys * f, + struct proto_keys * r) +{ + struct conn_state * C = cookie; + + /* The handshake is no longer in progress. */ + C->handshake_cookie = NULL; + + /* We beat the clock. */ + events_timer_cancel(C->handshake_timeout_cookie); + C->handshake_timeout_cookie = NULL; + + /* If the protocol handshake failed, drop the connection. */ + if ((f == NULL) && (r == NULL)) + return (proto_conn_drop(C, PROTO_CONN_HANDSHAKE_FAILED)); + + /* We should have two keys. */ + assert(f != NULL); + assert(r != NULL); + + /* Record the keys so we can free them later. */ + C->k_f = f; + C->k_r = r; + + /* If we already connected to the target, start shuttling data. */ + if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { + if (launchpipes(C)) + goto err1; + } + + /* Success! */ + return (0); + +err1: + proto_conn_drop(C, PROTO_CONN_ERROR); + + /* Failure! */ + return (-1); +} + +/* The protocol handshake took too long. */ +static int +callback_handshake_timeout(void * cookie) +{ + struct conn_state * C = cookie; + + /* This timeout is no longer pending. */ + C->handshake_timeout_cookie = NULL; + + /* Drop the connection. */ + return (proto_conn_drop(C, PROTO_CONN_ERROR)); +} + +/* The status of one of the directions has changed. */ +static int +callback_pipestatus(void * cookie) +{ + struct conn_state * C = cookie; + + /* If we have an error in either direction, kill the connection. */ + if ((C->stat_f == -1) || (C->stat_r == -1)) + return (proto_conn_drop(C, PROTO_CONN_ERROR)); + + /* If both directions have been shut down, kill the connection. */ + if ((C->stat_f == 0) && (C->stat_r == 0)) + return (proto_conn_drop(C, PROTO_CONN_CLOSED)); + + /* Nothing to do. */ + return (0); +} diff -Nru spiped-1.6.1/lib/proto/proto_conn.h spiped-1.6.2/lib/proto/proto_conn.h --- spiped-1.6.1/lib/proto/proto_conn.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_conn.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,43 @@ +#ifndef _PROTO_CONN_H_ +#define _PROTO_CONN_H_ + +/* Opaque structures. */ +struct proto_secret; +struct sock_addr; + +/* Reason why the connection was dropped. */ +enum { + PROTO_CONN_CLOSED = 0, /* Normal exit */ + PROTO_CONN_CANCELLED, /* Exit triggered by client code */ + PROTO_CONN_CONNECT_FAILED, /* Could not connect */ + PROTO_CONN_HANDSHAKE_FAILED, /* Handshake failed */ + PROTO_CONN_ERROR, /* Unspecified reason */ +}; + +/** + * proto_conn_create(s, sas, decr, nopfs, requirepfs, nokeepalive, K, timeo, + * callback_dead, cookie): + * Create a connection with one end at ${s} and the other end connecting to + * the target addresses ${sas}. If ${decr} is 0, encrypt the outgoing data; + * if ${decr} is nonzero, decrypt the incoming data. If ${nopfs} is non-zero, + * don't use perfect forward secrecy. If ${requirepfs} is non-zero, drop + * the connection if the other end tries to disable perfect forward secrecy. + * Enable transport layer keep-alives (if applicable) on both sockets if and + * only if ${nokeepalive} is zero. Drop the connection if the handshake or + * connecting to the target takes more than ${timeo} seconds. When the + * connection is dropped, invoke ${callback_dead}(${cookie}). Free ${sas} + * once it is no longer needed. Return a cookie which can be passed to + * proto_conn_drop(). If there is a connection error after this + * function returns, close ${s}. + */ +void * proto_conn_create(int, struct sock_addr **, int, int, int, int, + const struct proto_secret *, double, int (*)(void *, int), void *); + +/** + * proto_conn_drop(conn_cookie, reason): + * Drop connection and free memory associated with ${conn_cookie}, due to + * ${reason}. Return success or failure. + */ +int proto_conn_drop(void *, int); + +#endif /* !_PROTO_CONN_H_ */ diff -Nru spiped-1.6.1/lib/proto/proto_crypt.c spiped-1.6.2/lib/proto/proto_crypt.c --- spiped-1.6.1/lib/proto/proto_crypt.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_crypt.c 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,440 @@ +#include +#include +#include +#include +#include +#include + +#include "crypto_aes.h" +#include "crypto_aesctr.h" +#include "crypto_verify_bytes.h" +#include "insecure_memzero.h" +#include "sha256.h" +#include "sysendian.h" +#include "warnp.h" + +#include "proto_crypt.h" + +struct proto_secret { + uint8_t K[32]; +}; + +struct proto_keys { + struct crypto_aes_key * k_aes; + HMAC_SHA256_CTX ctx_init; + uint64_t pnum; +}; + +/** + * mkkeypair(kbuf): + * Convert the 64 bytes of ${kbuf} into a protocol key structure. + */ +#ifdef STANDALONE_ENC_TESTING +struct proto_keys * +mkkeypair(uint8_t kbuf[64]) +#else +static struct proto_keys * +mkkeypair(uint8_t kbuf[64]) +#endif +{ + struct proto_keys * k; + + /* Allocate a structure. */ + if ((k = malloc(sizeof(struct proto_keys))) == NULL) + goto err0; + + /* Expand the AES key. */ + if ((k->k_aes = crypto_aes_key_expand(&kbuf[0], 32)) == NULL) + goto err1; + + /* Initialize the HMAC_SHA256 context. */ + HMAC_SHA256_Init(&k->ctx_init, &kbuf[32], 32); + + /* The first packet will be packet number zero. */ + k->pnum = 0; + + /* Success! */ + return (k); + +err1: + free(k); +err0: + /* Failure! */ + return (NULL); +} + +/** + * proto_crypt_secret(filename): + * Read the key file ${filename} and return a protocol secret structure. + */ +struct proto_secret * +proto_crypt_secret(const char * filename) +{ + SHA256_CTX ctx; + FILE * f; + struct proto_secret * K; + uint8_t buf[BUFSIZ]; + size_t lenread; + + /* Allocate a protocol secret structure. */ + if ((K = malloc(sizeof(struct proto_secret))) == NULL) + goto err0; + + /* Open the file, or use stdin if requested. */ + if (strcmp(filename, STDIN_FILENAME) == 0) { + f = stdin; + } else if ((f = fopen(filename, "r")) == NULL) { + warnp("Cannot open file: %s", filename); + goto err1; + } + + /* Initialize the SHA256 hash context. */ + SHA256_Init(&ctx); + + /* Read the file until we hit EOF. */ + while ((lenread = fread(buf, 1, BUFSIZ, f)) > 0) + SHA256_Update(&ctx, buf, lenread); + + /* Did we hit EOF? */ + if (!feof(f)) { + if (f == stdin) { + warnp("Error reading from stdin"); + } else { + warnp("Error reading file: %s", filename); + } + + goto err2; + } + + /* Close the file if it isn't stdin. */ + if (f != stdin) + fclose(f); + + /* Compute the final hash and wipe context state. */ + SHA256_Final(K->K, &ctx); + + /* Success! */ + return (K); + +err2: + /* Close the file if it isn't stdin. */ + if (f != stdin) + fclose(f); + + /* Wipe context state. */ + SHA256_Final(K->K, &ctx); +err1: + proto_crypt_secret_free(K); +err0: + /* Failure! */ + return (NULL); +} + +/** + * proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr): + * Using the protocol secret ${K}, and the local and remote nonces ${nonce_l} + * and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC + * keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S" + * and "remote" == "C"; otherwise the assignments are opposite. + */ +void +proto_crypt_dhmac(const struct proto_secret * K, + const uint8_t nonce_l[PCRYPT_NONCE_LEN], + const uint8_t nonce_r[PCRYPT_NONCE_LEN], + uint8_t dhmac_l[PCRYPT_DHMAC_LEN], uint8_t dhmac_r[PCRYPT_DHMAC_LEN], + int decr) +{ + uint8_t nonce_CS[PCRYPT_NONCE_LEN * 2]; + uint8_t dk_1[PCRYPT_DHMAC_LEN * 2]; + const uint8_t * nonce_c, * nonce_s; + uint8_t * dhmac_c, * dhmac_s; + + /* Figure out how {c, s} maps to {l, r}. */ + nonce_c = decr ? nonce_r : nonce_l; + dhmac_c = decr ? dhmac_r : dhmac_l; + nonce_s = decr ? nonce_l : nonce_r; + dhmac_s = decr ? dhmac_l : dhmac_r; + + /* Copy in nonces (in the right order). */ + memcpy(&nonce_CS[0], nonce_c, PCRYPT_NONCE_LEN); + memcpy(&nonce_CS[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN); + + /* Compute dk_1. */ + PBKDF2_SHA256(K->K, 32, nonce_CS, PCRYPT_NONCE_LEN * 2, 1, + dk_1, PCRYPT_DHMAC_LEN * 2); + + /* Copy out diffie-hellman parameter MAC keys (in the right order). */ + memcpy(dhmac_c, &dk_1[0], PCRYPT_DHMAC_LEN); + memcpy(dhmac_s, &dk_1[PCRYPT_DHMAC_LEN], PCRYPT_DHMAC_LEN); +} + +/** + * is_not_one(x, len): + * Return non-zero if the big-endian value stored at (${x}, ${len}) is not + * equal to 1. + */ +static int +is_not_one(const uint8_t * x, size_t len) +{ + size_t i; + char y; + + for (i = 0, y = 0; i < len - 1; i++) { + y |= x[i]; + } + + return (y | (x[len - 1] - 1)); +} + +/** + * proto_crypt_dh_validate(yh_r, dhmac_r, requirepfs): + * Return non-zero if the value ${yh_r} received from the remote party is not + * correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or + * if the included y value is >= the diffie-hellman group modulus, or if + * ${requirepfs} is non-zero and the included y value is 1. + */ +int +proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN], + const uint8_t dhmac_r[PCRYPT_DHMAC_LEN], int requirepfs) +{ + uint8_t hbuf[32]; + + /* Compute HMAC. */ + HMAC_SHA256_Buf(dhmac_r, PCRYPT_DHMAC_LEN, yh_r, CRYPTO_DH_PUBLEN, + hbuf); + + /* Check that the MAC matches. */ + if (crypto_verify_bytes(&yh_r[CRYPTO_DH_PUBLEN], hbuf, 32)) + return (1); + + /* Sanity-check the diffie-hellman value. */ + if (crypto_dh_sanitycheck(&yh_r[0])) + return (1); + + /* If necessary, enforce that the diffie-hellman value is != 1. */ + if (requirepfs) { + if (! is_not_one(&yh_r[0], CRYPTO_DH_PUBLEN)) + return (1); + } + + /* Everything is good. */ + return (0); +} + +/** + * proto_crypt_dh_generate(yh_l, x, dhmac_l, nopfs): + * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake + * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If + * ${nopfs} is non-zero, skip diffie-hellman generation and use y = 1. + */ +int +proto_crypt_dh_generate(uint8_t yh_l[PCRYPT_YH_LEN], uint8_t x[PCRYPT_X_LEN], + const uint8_t dhmac_l[PCRYPT_DHMAC_LEN], int nopfs) +{ + + /* Are we skipping the diffie-hellman generation? */ + if (nopfs) { + /* Set y_l to a big-endian 1. */ + memset(yh_l, 0, CRYPTO_DH_PUBLEN - 1); + yh_l[CRYPTO_DH_PUBLEN - 1] = 1; + } else { + /* Generate diffie-hellman parameters x and y. */ + if (crypto_dh_generate(yh_l, x)) + goto err0; + } + + /* Append an HMAC. */ + HMAC_SHA256_Buf(dhmac_l, PCRYPT_DHMAC_LEN, yh_l, CRYPTO_DH_PUBLEN, + &yh_l[CRYPTO_DH_PUBLEN]); + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/** + * proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nopfs, decr, eh_c, eh_s): + * Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and + * ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r}, + * and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and + * ${eh_s}. If ${nopfs} is non-zero, we are performing weak handshaking and + * y_SC is set to 1 rather than being computed. If ${decr} is non-zero, + * "local" == "S" and "remote" == "C"; otherwise the assignments are opposite. + */ +int +proto_crypt_mkkeys(const struct proto_secret * K, + const uint8_t nonce_l[PCRYPT_NONCE_LEN], + const uint8_t nonce_r[PCRYPT_NONCE_LEN], + const uint8_t yh_r[PCRYPT_YH_LEN], const uint8_t x[PCRYPT_X_LEN], + int nopfs, int decr, + struct proto_keys ** eh_c, struct proto_keys ** eh_s) +{ + uint8_t nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN]; + uint8_t dk_2[128]; + const uint8_t * nonce_c, * nonce_s; + + /* Copy in nonces (in the right order). */ + nonce_c = decr ? nonce_r : nonce_l; + nonce_s = decr ? nonce_l : nonce_r; + memcpy(&nonce_y[0], nonce_c, PCRYPT_NONCE_LEN); + memcpy(&nonce_y[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN); + + /* Are we bypassing the diffie-hellman computation? */ + if (nopfs) { + /* We sent y_l = 1, so y_SC is also 1. */ + memset(&nonce_y[PCRYPT_NONCE_LEN * 2], 0, + CRYPTO_DH_KEYLEN - 1); + nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN - 1] = 1; + } else { + /* Perform the diffie-hellman computation. */ + if (crypto_dh_compute(yh_r, x, + &nonce_y[PCRYPT_NONCE_LEN * 2])) + goto err0; + } + + /* Compute dk_2. */ + PBKDF2_SHA256(K->K, 32, nonce_y, + PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN, 1, dk_2, 128); + + /* Create key structures. */ + if ((*eh_c = mkkeypair(&dk_2[0])) == NULL) + goto err0; + if ((*eh_s = mkkeypair(&dk_2[64])) == NULL) + goto err1; + + /* Success! */ + return (0); + +err1: + proto_crypt_free(*eh_c); +err0: + /* Failure! */ + return (-1); +} + +/** + * proto_crypt_enc(ibuf, len, obuf, k): + * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in + * ${k}, and write the result into ${obuf}. + */ +void +proto_crypt_enc(uint8_t * ibuf, size_t len, uint8_t obuf[PCRYPT_ESZ], + struct proto_keys * k) +{ + HMAC_SHA256_CTX ctx; + uint8_t pnum_exp[8]; + + /* Sanity-check the length. */ + assert(len <= PCRYPT_MAXDSZ); + + /* Copy the decrypted data into the encrypted buffer. */ + memcpy(obuf, ibuf, len); + + /* Pad up to PCRYPT_MAXDSZ with zeroes. */ + memset(&obuf[len], 0, PCRYPT_MAXDSZ - len); + + /* Add the length. */ + be32enc(&obuf[PCRYPT_MAXDSZ], (uint32_t)len); + + /* Encrypt the buffer in-place. */ + crypto_aesctr_buf(k->k_aes, k->pnum, obuf, obuf, PCRYPT_MAXDSZ + 4); + + /* Copy the original (initialized) context. */ + memcpy(&ctx, &k->ctx_init, sizeof(HMAC_SHA256_CTX)); + + /* Append an HMAC. */ + be64enc(pnum_exp, k->pnum); + HMAC_SHA256_Update(&ctx, obuf, PCRYPT_MAXDSZ + 4); + HMAC_SHA256_Update(&ctx, pnum_exp, 8); + HMAC_SHA256_Final(&obuf[PCRYPT_MAXDSZ + 4], &ctx); + + /* Increment packet number. */ + k->pnum += 1; +} + +/** + * proto_crypt_dec(ibuf, obuf, k): + * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data + * is valid, write it into ${obuf} and return the length; otherwise, return + * -1. + */ +ssize_t +proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf, + struct proto_keys * k) +{ + HMAC_SHA256_CTX ctx; + uint8_t hbuf[32]; + uint8_t pnum_exp[8]; + size_t len; + + /* Copy the original (initialized) context. */ + memcpy(&ctx, &k->ctx_init, sizeof(HMAC_SHA256_CTX)); + + /* Verify HMAC. */ + be64enc(pnum_exp, k->pnum); + HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4); + HMAC_SHA256_Update(&ctx, pnum_exp, 8); + HMAC_SHA256_Final(hbuf, &ctx); + if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32)) + return (-1); + + /* Decrypt the buffer in-place. */ + crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4); + + /* Increment packet number. */ + k->pnum += 1; + + /* Parse length. */ + len = be32dec(&ibuf[PCRYPT_MAXDSZ]); + + /* Make sure nobody is being evil here... */ + if ((len == 0) || (len > PCRYPT_MAXDSZ)) + return (-1); + + /* Copy the bytes into the output buffer. */ + memcpy(obuf, ibuf, len); + + /* Return the decrypted length. */ + return ((ssize_t)len); +} + +/** + * proto_crypt_secret_free(K): + * Free the protocol secret structure ${K}. + */ +void +proto_crypt_secret_free(struct proto_secret * K) +{ + + /* Be compatible with free(NULL). */ + if (K == NULL) + return; + + /* Clear secret from the memory. */ + insecure_memzero(K, sizeof(struct proto_secret)); + + /* Free the key structure. */ + free(K); +} + +/** + * proto_crypt_free(k): + * Free the protocol key structure ${k}. + */ +void +proto_crypt_free(struct proto_keys * k) +{ + + /* Be compatible with free(NULL). */ + if (k == NULL) + return; + + /* Free the AES key. */ + crypto_aes_key_free(k->k_aes); + + /* Free the key structure. */ + free(k); +} diff -Nru spiped-1.6.1/lib/proto/proto_crypt.h spiped-1.6.2/lib/proto/proto_crypt.h --- spiped-1.6.1/lib/proto/proto_crypt.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_crypt.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,120 @@ +#ifndef _PROTO_CRYPT_H_ +#define _PROTO_CRYPT_H_ + +#include +#include + +#include "crypto_dh.h" + +/* Opaque structures. */ +struct proto_keys; +struct proto_secret; + +/* Size of nonce. */ +#define PCRYPT_NONCE_LEN 32 + +/* Size of temporary MAC keys used for Diffie-Hellman parameters. */ +#define PCRYPT_DHMAC_LEN 32 + +/* Size of private Diffie-Hellman value. */ +#define PCRYPT_X_LEN CRYPTO_DH_PRIVLEN + +/* Size of MACed Diffie-Hellman parameter. */ +#define PCRYPT_YH_LEN (CRYPTO_DH_PUBLEN + 32) + +/* Filename for stdin. */ +#define STDIN_FILENAME "-" + +/** + * proto_crypt_secret(filename): + * Read the key file ${filename} and return a protocol secret structure. + */ +struct proto_secret * proto_crypt_secret(const char *); + +/** + * proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr): + * Using the protocol secret ${K}, and the local and remote nonces ${nonce_l} + * and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC + * keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S" + * and "remote" == "C"; otherwise the assignments are opposite. + */ +void proto_crypt_dhmac(const struct proto_secret *, + const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN], + uint8_t[PCRYPT_DHMAC_LEN], uint8_t[PCRYPT_DHMAC_LEN], int); + +/** + * proto_crypt_dh_validate(yh_r, dhmac_r, requirepfs): + * Return non-zero if the value ${yh_r} received from the remote party is not + * correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or + * if the included y value is >= the diffie-hellman group modulus, or if + * ${requirepfs} is non-zero and the included y value is 1. + */ +int proto_crypt_dh_validate(const uint8_t[PCRYPT_YH_LEN], + const uint8_t[PCRYPT_DHMAC_LEN], int); + +/** + * proto_crypt_dh_generate(yh_l, x, dhmac_l, nopfs): + * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake + * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If + * ${nopfs} is non-zero, skip diffie-hellman generation and use y = 1. + */ +int proto_crypt_dh_generate(uint8_t[PCRYPT_YH_LEN], uint8_t[PCRYPT_X_LEN], + const uint8_t[PCRYPT_DHMAC_LEN], int); + +/** + * proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nopfs, decr, eh_c, eh_s): + * Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and + * ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r}, + * and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and + * ${eh_s}. If ${nopfs} is non-zero, we are performing weak handshaking and + * y_SC is set to 1 rather than being computed. If ${decr} is non-zero, + * "local" == "S" and "remote" == "C"; otherwise the assignments are opposite. + */ +int proto_crypt_mkkeys(const struct proto_secret *, + const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN], + const uint8_t[PCRYPT_YH_LEN], const uint8_t[PCRYPT_X_LEN], int, int, + struct proto_keys **, struct proto_keys **); + +/* Maximum size of an unencrypted packet. */ +#define PCRYPT_MAXDSZ 1024 + +/* Size of an encrypted packet. */ +#define PCRYPT_ESZ (PCRYPT_MAXDSZ + 4 /* len */ + 32 /* hmac */) + +/** + * proto_crypt_enc(ibuf, len, obuf, k): + * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in + * ${k}, and write the result into ${obuf}. + */ +void proto_crypt_enc(uint8_t *, size_t, uint8_t[PCRYPT_ESZ], + struct proto_keys *); + +/** + * proto_crypt_dec(ibuf, obuf, k): + * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data + * is valid, write it into ${obuf} and return the length; otherwise, return + * -1. + */ +ssize_t proto_crypt_dec(uint8_t[PCRYPT_ESZ], uint8_t *, struct proto_keys *); + +/** + * proto_crypt_secret_free(K): + * Free the protocol secret structure ${K}. + */ +void proto_crypt_secret_free(struct proto_secret *); + +/** + * proto_crypt_free(k): + * Free the protocol key structure ${k}. + */ +void proto_crypt_free(struct proto_keys *); + +#ifdef STANDALONE_ENC_TESTING +/** + * mkkeypair(kbuf): + * Convert the 64 bytes of ${kbuf} into a protocol key structure. + */ +struct proto_keys * mkkeypair(uint8_t kbuf[64]); +#endif + +#endif /* !_PROTO_CRYPT_H_ */ diff -Nru spiped-1.6.1/lib/proto/proto_handshake.c spiped-1.6.2/lib/proto/proto_handshake.c --- spiped-1.6.1/lib/proto/proto_handshake.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_handshake.c 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +#include "crypto_entropy.h" +#include "network.h" + +#include "proto_crypt.h" + +#include "proto_handshake.h" + +struct handshake_cookie { + int (* callback)(void *, struct proto_keys *, struct proto_keys *); + void * cookie; + int s; + int decr; + int nopfs; + int requirepfs; + const struct proto_secret * K; + uint8_t nonce_local[PCRYPT_NONCE_LEN]; + uint8_t nonce_remote[PCRYPT_NONCE_LEN]; + uint8_t dhmac_local[PCRYPT_DHMAC_LEN]; + uint8_t dhmac_remote[PCRYPT_DHMAC_LEN]; + uint8_t x[PCRYPT_X_LEN]; + uint8_t yh_local[PCRYPT_YH_LEN]; + uint8_t yh_remote[PCRYPT_YH_LEN]; + void * read_cookie; + void * write_cookie; +}; + +static int callback_nonce_write(void *, ssize_t); +static int callback_nonce_read(void *, ssize_t); +static int gotnonces(struct handshake_cookie *); +static int dhread(struct handshake_cookie *); +static int callback_dh_read(void *, ssize_t); +static int dhwrite(struct handshake_cookie *); +static int callback_dh_write(void *, ssize_t); +static int handshakedone(struct handshake_cookie *); + +/* The handshake failed. Call back and clean up. */ +static int +handshakefail(struct handshake_cookie * H) +{ + int rc; + + /* Cancel any pending network read or write. */ + if (H->read_cookie != NULL) + network_read_cancel(H->read_cookie); + if (H->write_cookie != NULL) + network_write_cancel(H->write_cookie); + + /* Perform the callback. */ + rc = (H->callback)(H->cookie, NULL, NULL); + + /* Free the cookie. */ + free(H); + + /* Return status from callback. */ + return (rc); +} + +/** + * proto_handshake(s, decr, nopfs, requirepfs, K, callback, cookie): + * Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are + * at the receiving end of the connection; otherwise at the sending end. If + * ${nopfs} is non-zero, perform a "weak" handshake without perfect forward + * secrecy. If ${requirepfs} is non-zero, drop the connection if the other + * end attempts to perform a "weak" handshake. The shared protocol secret is + * ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f + * contains the keys needed for the forward direction and r contains the keys + * needed for the reverse direction; or f = r = NULL if the handshake failed. + * Return a cookie which can be passed to proto_handshake_cancel() to cancel the + * handshake. + */ +void * +proto_handshake(int s, int decr, int nopfs, int requirepfs, + const struct proto_secret * K, + int (* callback)(void *, struct proto_keys *, struct proto_keys *), + void * cookie) +{ + struct handshake_cookie * H; + + /* Bake a cookie. */ + if ((H = malloc(sizeof(struct handshake_cookie))) == NULL) + goto err0; + H->callback = callback; + H->cookie = cookie; + H->s = s; + H->decr = decr; + H->nopfs = nopfs; + H->requirepfs = requirepfs; + H->K = K; + + /* Generate a 32-byte connection nonce. */ + if (crypto_entropy_read(H->nonce_local, 32)) + goto err1; + + /* Send our nonce. */ + if ((H->write_cookie = network_write(s, H->nonce_local, 32, 32, + callback_nonce_write, H)) == NULL) + goto err1; + + /* Read the other party's nonce. */ + if ((H->read_cookie = network_read(s, H->nonce_remote, 32, 32, + callback_nonce_read, H)) == NULL) + goto err2; + + /* Success! */ + return (H); + +err2: + network_write_cancel(H->write_cookie); +err1: + free(H); +err0: + /* Failure! */ + return (NULL); +} + +/* We've written our nonce. */ +static int +callback_nonce_write(void * cookie, ssize_t len) +{ + struct handshake_cookie * H = cookie; + + /* This write is no longer pending. */ + H->write_cookie = NULL; + + /* Did we successfully write? */ + if (len < 32) + return (handshakefail(H)); + + /* If the nonce read is also done, move on to the next step. */ + if (H->read_cookie == NULL) + return (gotnonces(H)); + + /* Nothing to do. */ + return (0); +} + +/* We've read a nonce. */ +static int +callback_nonce_read(void * cookie, ssize_t len) +{ + struct handshake_cookie * H = cookie; + + /* This read is no longer pending. */ + H->read_cookie = NULL; + + /* Did we successfully read? */ + if (len < 32) + return (handshakefail(H)); + + /* If the nonce write is also done, move on to the next step. */ + if (H->write_cookie == NULL) + return (gotnonces(H)); + + /* Nothing to do. */ + return (0); +} + +/* We have two nonces. Start the DH exchange. */ +static int +gotnonces(struct handshake_cookie * H) +{ + + /* Compute the diffie-hellman parameter MAC keys. */ + proto_crypt_dhmac(H->K, H->nonce_local, H->nonce_remote, + H->dhmac_local, H->dhmac_remote, H->decr); + + /* + * If we're the server, we need to read the client's diffie-hellman + * parameter. If we're the client, we need to generate and send our + * diffie-hellman parameter. + */ + if (H->decr) + return (dhread(H)); + else + return (dhwrite(H)); + + /* NOTREACHED */ +} + +/* Read a diffie-hellman parameter. */ +static int +dhread(struct handshake_cookie * H) +{ + + /* Read the remote signed diffie-hellman parameter. */ + if ((H->read_cookie = network_read(H->s, H->yh_remote, PCRYPT_YH_LEN, + PCRYPT_YH_LEN, callback_dh_read, H)) == NULL) + goto err0; + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/* We have read a diffie-hellman parameter. */ +static int +callback_dh_read(void * cookie, ssize_t len) +{ + struct handshake_cookie * H = cookie; + + /* This read is no longer pending. */ + H->read_cookie = NULL; + + /* Did we successfully read? */ + if (len < PCRYPT_YH_LEN) + return (handshakefail(H)); + + /* Is the value we read valid? */ + if (proto_crypt_dh_validate(H->yh_remote, H->dhmac_remote, + H->requirepfs)) + return (handshakefail(H)); + + /* + * If we're the server, we need to send our diffie-hellman parameter + * next. If we're the client, move on to the final computation. + */ + if (H->decr) + return (dhwrite(H)); + else + return (handshakedone(H)); + + /* NOTREACHED */ +} + +/* Generate and write a diffie-hellman parameter. */ +static int +dhwrite(struct handshake_cookie * H) +{ + + /* Generate a signed diffie-hellman parameter. */ + if (proto_crypt_dh_generate(H->yh_local, H->x, H->dhmac_local, + H->nopfs)) + goto err0; + + /* Write our signed diffie-hellman parameter. */ + if ((H->write_cookie = network_write(H->s, H->yh_local, PCRYPT_YH_LEN, + PCRYPT_YH_LEN, callback_dh_write, H)) == NULL) + goto err0; + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/* We have written our diffie-hellman parameter. */ +static int +callback_dh_write(void * cookie, ssize_t len) +{ + struct handshake_cookie * H = cookie; + + /* This write is no longer pending. */ + H->write_cookie = NULL; + + /* Did we successfully write? */ + if (len < PCRYPT_YH_LEN) + return (handshakefail(H)); + + /* + * If we're the server, move on to the final computation. If we're + * the client, we need to read the server's parameter next. + */ + if (H->decr) + return (handshakedone(H)); + else + return (dhread(H)); + + /* NOTREACHED */ +} + +/* We've got all the bits; do the final computation and callback. */ +static int +handshakedone(struct handshake_cookie * H) +{ + struct proto_keys * c; + struct proto_keys * s; + int rc; + + /* Sanity-check: There should be no callbacks in progress. */ + assert(H->read_cookie == NULL); + assert(H->write_cookie == NULL); + + /* Perform the final computation. */ + if (proto_crypt_mkkeys(H->K, H->nonce_local, H->nonce_remote, + H->yh_remote, H->x, H->nopfs, H->decr, &c, &s)) + goto err0; + + /* Perform the callback. */ + rc = (H->callback)(H->cookie, c, s); + + /* Free the cookie. */ + free(H); + + /* Return status code from callback. */ + return (rc); + +err0: + /* Failure! */ + return (-1); +} + +/** + * proto_handshake_cancel(cookie): + * Cancel the handshake for which proto_handshake() returned ${cookie}. + */ +void +proto_handshake_cancel(void * cookie) +{ + struct handshake_cookie * H = cookie; + + /* Cancel any in-progress network operations. */ + if (H->read_cookie != NULL) + network_read_cancel(H->read_cookie); + if (H->write_cookie != NULL) + network_write_cancel(H->write_cookie); + + /* Free the cookie. */ + free(H); +} diff -Nru spiped-1.6.1/lib/proto/proto_handshake.h spiped-1.6.2/lib/proto/proto_handshake.h --- spiped-1.6.1/lib/proto/proto_handshake.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_handshake.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,30 @@ +#ifndef _PROTO_HANDSHAKE_H_ +#define _PROTO_HANDSHAKE_H_ + +/* Opaque structures. */ +struct proto_keys; +struct proto_secret; + +/** + * proto_handshake(s, decr, nopfs, requirepfs, K, callback, cookie): + * Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are + * at the receiving end of the connection; otherwise at the sending end. If + * ${nopfs} is non-zero, perform a "weak" handshake without perfect forward + * secrecy. If ${requirepfs} is non-zero, drop the connection if the other + * end attempts to perform a "weak" handshake. The shared protocol secret is + * ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f + * contains the keys needed for the forward direction and r contains the keys + * needed for the reverse direction; or f = r = NULL if the handshake failed. + * Return a cookie which can be passed to proto_handshake_cancel() to cancel the + * handshake. + */ +void * proto_handshake(int, int, int, int, const struct proto_secret *, + int (*)(void *, struct proto_keys *, struct proto_keys *), void *); + +/** + * proto_handshake_cancel(cookie): + * Cancel the handshake for which proto_handshake() returned ${cookie}. + */ +void proto_handshake_cancel(void *); + +#endif /* !_PROTO_HANDSHAKE_H_ */ diff -Nru spiped-1.6.1/lib/proto/proto_pipe.c spiped-1.6.2/lib/proto/proto_pipe.c --- spiped-1.6.1/lib/proto/proto_pipe.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_pipe.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,229 @@ +#include +#include + +#include +#include + +#include "netbuf.h" +#include "network.h" + +#include "proto_crypt.h" + +#include "proto_pipe.h" + +/* Maximum size of data to output in a single callback_pipe_read() call. */ +#define OUTBUFSIZE (8 * PCRYPT_ESZ) + +struct pipe_cookie { + int (* callback)(void *); + void * cookie; + int * status; + int s_in; + int s_out; + int decr; + struct proto_keys * k; + uint8_t outbuf[OUTBUFSIZE]; + struct netbuf_read * R; + void * write_cookie; + ssize_t wlen; + size_t minread; + size_t full_buflen; +}; + +static int callback_pipe_read(void *, int); +static int callback_pipe_write(void *, ssize_t); + +/** + * proto_pipe(s_in, s_out, decr, k, status, callback, cookie): + * Read bytes from ${s_in} and write them to ${s_out}. If ${decr} is non-zero + * then use ${k} to decrypt the bytes; otherwise use ${k} to encrypt them. + * If EOF is read, set ${status} to 0, and if an error is encountered set + * ${status} to -1; in either case, invoke ${callback}(${cookie}). Return a + * cookie which can be passed to proto_pipe_cancel(). + */ +void * +proto_pipe(int s_in, int s_out, int decr, struct proto_keys * k, + int * status, int (* callback)(void *), void * cookie) +{ + struct pipe_cookie * P; + + /* Bake a cookie. */ + if ((P = malloc(sizeof(struct pipe_cookie))) == NULL) + goto err0; + P->callback = callback; + P->cookie = cookie; + P->status = status; + P->s_in = s_in; + P->s_out = s_out; + P->decr = decr; + P->k = k; + P->write_cookie = NULL; + + /* Initialize reader. */ + if ((P->R = netbuf_read_init(P->s_in)) == NULL) + goto err1; + + /* Set the minimum number of bytes to read. */ + P->minread = P->decr ? PCRYPT_ESZ : 1; + + /* Set the number of bytes in a full buffer. */ + P->full_buflen = P->decr ? PCRYPT_ESZ : PCRYPT_MAXDSZ; + + /* Start reading. */ + if (netbuf_read_wait(P->R, P->minread, callback_pipe_read, P)) + goto err2; + + /* Success! */ + return (P); + +err2: + netbuf_read_free(P->R); +err1: + free(P); +err0: + /* Failure! */ + return (NULL); +} + +/* Some data has been read. */ +static int +callback_pipe_read(void * cookie, int status) +{ + struct pipe_cookie * P = cookie; + uint8_t * inbuf; + size_t inlen; + size_t inpos = 0; + size_t outpos = 0; + size_t loop_inlen; + ssize_t loop_outlen; + + /* Did we read EOF? */ + if (status == 1) + goto eof; + + /* Did the read fail? */ + if (status == -1) + goto fail; + + /* Get data. */ + netbuf_read_peek(P->R, &inbuf, &inlen); + + /* Process as many packets as possible. */ + while (inlen > 0) { + /* Stop processing if we don't have space for more output. */ + if (outpos + P->full_buflen > OUTBUFSIZE) + break; + + /* How many bytes should we process this time? */ + loop_inlen = (inlen > P->full_buflen) ? P->full_buflen : inlen; + + /* + * If we don't have enough data to decrypt, leave it until the + * next time callback_pipe_read() is called. + */ + if ((P->decr) && (loop_inlen < PCRYPT_ESZ)) + break; + + /* Encrypt or decrypt the data. */ + if (P->decr) { + if ((loop_outlen = proto_crypt_dec(&inbuf[inpos], + &P->outbuf[outpos], P->k)) == -1) + goto fail; + } else { + proto_crypt_enc(&inbuf[inpos], loop_inlen, + &P->outbuf[outpos], P->k); + loop_outlen = PCRYPT_ESZ; + } + + /* We've processed this data. */ + inlen -= loop_inlen; + inpos += loop_inlen; + outpos += (size_t)loop_outlen; + } + + /* Let netbuf layer know what we've used. */ + netbuf_read_consume(P->R, inpos); + + /* Write the encrypted or decrypted data. */ + P->wlen = (ssize_t)outpos; + if ((P->write_cookie = network_write(P->s_out, P->outbuf, + (size_t)P->wlen, (size_t)P->wlen, callback_pipe_write, + P)) == NULL) + goto err0; + + /* Success! */ + return (0); + +fail: + /* Record that this connection is broken. */ + *(P->status) = -1; + + /* Inform the upstream that our status has changed. */ + return ((P->callback)(P->cookie)); + +eof: + /* We aren't going to write any more. */ + shutdown(P->s_out, SHUT_WR); + + /* Record that we have reached EOF. */ + *(P->status) = 0; + + /* Inform the upstream that our status has changed. */ + return ((P->callback)(P->cookie)); + +err0: + /* Failure! */ + return (-1); +} + +static int +callback_pipe_write(void * cookie, ssize_t len) +{ + struct pipe_cookie * P = cookie; + + /* This write is no longer in progress. */ + P->write_cookie = NULL; + + /* Did we fail to write everything? */ + if (len < P->wlen) + goto fail; + + /* Launch another read. */ + if (netbuf_read_wait(P->R, P->minread, callback_pipe_read, P)) + goto err0; + + /* Success! */ + return (0); + +fail: + /* Record that this connection is broken. */ + *(P->status) = -1; + + /* Inform the upstream that our status has changed. */ + return ((P->callback)(P->cookie)); + +err0: + /* Failure! */ + return (-1); +} + +/** + * proto_pipe_cancel(cookie): + * Shut down the pipe created by proto_pipe() for which ${cookie} was returned. + */ +void +proto_pipe_cancel(void * cookie) +{ + struct pipe_cookie * P = cookie; + + /* If a read or write is in progress, cancel it. */ + netbuf_read_wait_cancel(P->R); + if (P->write_cookie) + network_write_cancel(P->write_cookie); + + /* Clean up the buffered reader. */ + netbuf_read_free(P->R); + + /* Free the cookie. */ + free(P); +} diff -Nru spiped-1.6.1/lib/proto/proto_pipe.h spiped-1.6.2/lib/proto/proto_pipe.h --- spiped-1.6.1/lib/proto/proto_pipe.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/proto/proto_pipe.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,24 @@ +#ifndef _PROTO_PIPE_H_ +#define _PROTO_PIPE_H_ + +/* Opaque structure. */ +struct proto_keys; + +/** + * proto_pipe(s_in, s_out, decr, k, status, callback, cookie): + * Read bytes from ${s_in} and write them to ${s_out}. If ${decr} is non-zero + * then use ${k} to decrypt the bytes; otherwise use ${k} to encrypt them. + * If EOF is read, set ${status} to 0, and if an error is encountered set + * ${status} to -1; in either case, invoke ${callback}(${cookie}). Return a + * cookie which can be passed to proto_pipe_cancel(). + */ +void * proto_pipe(int, int, int, struct proto_keys *, int *, + int (*)(void *), void *); + +/** + * proto_pipe_cancel(cookie): + * Shut down the pipe created by proto_pipe() for which ${cookie} was returned. + */ +void proto_pipe_cancel(void *); + +#endif /* !_PROTO_PIPE_H_ */ diff -Nru spiped-1.6.1/lib/util/graceful_shutdown.c spiped-1.6.2/lib/util/graceful_shutdown.c --- spiped-1.6.1/lib/util/graceful_shutdown.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/lib/util/graceful_shutdown.c 2020-12-05 21:26:44.000000000 +0000 @@ -1,3 +1,4 @@ +#include #include #include #include @@ -73,9 +74,9 @@ /** * graceful_shutdown_initialize(callback, caller_cookie): - * Initializes a signal handler for SIGTERM, and starts a continuous 1-second - * timer which checks if SIGTERM was given; if detected, calls ${callback} and - * gives it the ${caller_cookie}. + * Initialize a signal handler for SIGTERM, and start a continuous 1-second + * timer which checks if SIGTERM was given; if detected, call ${callback} and + * give it the ${caller_cookie}. */ int graceful_shutdown_initialize(int (* begin_shutdown_parent)(void *), @@ -111,3 +112,26 @@ /* Failure! */ return (-1); } + +/** + * graceful_shutdown_manual(void): + * Shutdown immediately, without needing a SIGTERM. + */ +void +graceful_shutdown_manual(void) +{ + + /* Sanity check: we must be initialized. */ + assert(begin_shutdown != NULL); + assert(caller_cookie != NULL); + + /* Stop the timer. */ + if (timer_cookie != NULL) { + events_timer_cancel(timer_cookie); + timer_cookie = NULL; + } + + /* Shut down. */ + should_shutdown = 1; + graceful_shutdown(NULL); +} diff -Nru spiped-1.6.1/lib/util/graceful_shutdown.h spiped-1.6.2/lib/util/graceful_shutdown.h --- spiped-1.6.1/lib/util/graceful_shutdown.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/lib/util/graceful_shutdown.h 2020-12-05 21:26:44.000000000 +0000 @@ -3,10 +3,16 @@ /** * graceful_shutdown_initialize(callback, caller_cookie): - * Initializes a signal handler for SIGTERM, and starts a continuous 1-second - * timer which checks if SIGTERM was given; if detected, calls ${callback} and - * gives it the ${caller_cookie}. + * Initialize a signal handler for SIGTERM, and start a continuous 1-second + * timer which checks if SIGTERM was given; if detected, call ${callback} and + * give it the ${caller_cookie}. */ int graceful_shutdown_initialize(int (*)(void *), void *); +/** + * graceful_shutdown_manual(void): + * Shutdown immediately, without needing a SIGTERM. + */ +void graceful_shutdown_manual(void); + #endif /* !_GRACEFUL_SHUTDOWN_H_ */ diff -Nru spiped-1.6.1/lib/util/pthread_create_blocking_np.c spiped-1.6.2/lib/util/pthread_create_blocking_np.c --- spiped-1.6.1/lib/util/pthread_create_blocking_np.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/util/pthread_create_blocking_np.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,162 @@ +#include +#include +#include + +#include "pthread_create_blocking_np.h" + +struct wrapped_cookie { + /* User-supplied. */ + void * (*start_routine)(void *); + void * arg; + + /* Synchronization. */ + pthread_mutex_t mutex; + pthread_cond_t cond; + int running; /* 1 if the thread has started. */ + + /* In case the synchronization fails. */ + int rc_sync; /* non-zero if synchronization failed. */ +}; + +/* Routine which is executed by pthread_create(). */ +static void * +wrapped_thread(void * cookie) +{ + struct wrapped_cookie * U = cookie; + void * (*start_routine)(void *); + void * arg; + int rc; + + /* + * Copy the user-supplied parameters, because U will not be valid + * after we signal the parent thread that we have started running. + */ + start_routine = U->start_routine; + arg = U->arg; + + /* Lock mutex. */ + if ((rc = pthread_mutex_lock(&U->mutex))) + goto err1; + + /* Set the "running" flag and signal the condition variable. */ + U->running = 1; + if ((rc = pthread_cond_signal(&U->cond))) + goto err2; + + /* Unlock mutex. This allows the parent thread to free U. */ + if ((rc = pthread_mutex_unlock(&U->mutex))) + goto err1; + + /* Run the desired routine. */ + return (start_routine(arg)); + +err2: + /* + * Don't record any errors in this clean-up; the existing value of rc + * is more important. + */ + pthread_mutex_unlock(&U->mutex); +err1: + /* If there was an error, then we can still write to U. */ + U->rc_sync = rc; + + /* Failure! */ + return (NULL); +} + +/** + * pthread_create_blocking_np(thread, attr, start_routine, arg): + * Run pthread_create() and block until the the ${thread} has started. The + * thread will execute ${start_routine} with ${arg} as its sole argument. + * When ${start_routine} finishes, make its returned value available via + * pthread_join(). If successful, return 0; otherwise return the error number. + */ +int +pthread_create_blocking_np(pthread_t * restrict thread, + const pthread_attr_t * restrict attr, + void * (*start_routine)(void *), void * restrict arg) +{ + struct wrapped_cookie * U; + int rc; + + /* + * Allocate our cookie and store parameters. The C standard does not + * require that variables with automatic storage duration are + * accessible by other threads; POSIX (and thus pthreads) does provide + * that guarantee, but out of an abundance of caution we take the + * option of using malloc in case this code ends up running on a + * non-POSIX system. + */ + if ((U = malloc(sizeof(struct wrapped_cookie))) == NULL) { + rc = errno; + goto err0; + } + U->start_routine = start_routine; + U->arg = arg; + + /* Initialize synchronization-related variables. */ + if ((rc = pthread_mutex_init(&U->mutex, NULL)) != 0) + goto err1; + if ((rc = pthread_cond_init(&U->cond, NULL)) != 0) + goto err2; + U->running = 0; + U->rc_sync = 0; + + /* Lock mutex. */ + if ((rc = pthread_mutex_lock(&U->mutex)) != 0) + goto err3; + + /* Create the thread. */ + if ((rc = pthread_create(thread, attr, wrapped_thread, U)) != 0) { + /* + * Don't record any pthread_mutex_unlock() error here; the + * error from pthread_create() is more important. + */ + pthread_mutex_unlock(&U->mutex); + goto err3; + } + + /* Wait for the thread to have started, then unlock the mutex. */ + while (!U->running) { + /* Wait until signalled. */ + if ((rc = pthread_cond_wait(&U->cond, &U->mutex)) != 0) + goto err5; + + /* Quit if there was an error in the synchronization. */ + if ((rc = U->rc_sync) != 0) + goto err5; + } + if ((rc = pthread_mutex_unlock(&U->mutex)) != 0) + goto err4; + + /* Clean up synchronization-related variables. */ + if ((rc = pthread_cond_destroy(&U->cond)) != 0) + goto err2; + if ((rc = pthread_mutex_destroy(&U->mutex)) != 0) + goto err1; + + /* Clean up. */ + free(U); + + /* Success! */ + return (0); + +err5: + /* + * Don't record any errors in this clean-up; the existing value of rc + * is more important. + */ + pthread_mutex_unlock(&U->mutex); +err4: + pthread_cancel(*thread); + pthread_join(*thread, NULL); +err3: + pthread_cond_destroy(&U->cond); +err2: + pthread_mutex_destroy(&U->mutex); +err1: + free(U); +err0: + /* Failure! */ + return (rc); +} diff -Nru spiped-1.6.1/lib/util/pthread_create_blocking_np.h spiped-1.6.2/lib/util/pthread_create_blocking_np.h --- spiped-1.6.1/lib/util/pthread_create_blocking_np.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/lib/util/pthread_create_blocking_np.h 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef _PTHREAD_CREATE_BLOCKING_NP_H_ +#define _PTHREAD_CREATE_BLOCKING_NP_H_ + +#include + +/** + * pthread_create_blocking_np(thread, attr, start_routine, arg): + * Run pthread_create() and block until the the ${thread} has started. The + * thread will execute ${start_routine} with ${arg} as its sole argument. + * When ${start_routine} finishes, make its returned value available via + * pthread_join(). If successful, return 0; otherwise return the error number. + */ +int pthread_create_blocking_np(pthread_t * restrict, + const pthread_attr_t * restrict, void *(*)(void *), void *); + +#endif /* !_PTHREAD_CREATE_BLOCKING_NP_H_ */ diff -Nru spiped-1.6.1/liball/Makefile spiped-1.6.2/liball/Makefile --- spiped-1.6.1/liball/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/liball/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -0,0 +1,133 @@ +.POSIX: +# AUTOGENERATED FILE, DO NOT EDIT +LIB=liball.a +SRCS=sha256.c sha256_arm.c sha256_shani.c sha256_sse2.c cpusupport_arm_aes.c cpusupport_arm_sha256.c cpusupport_x86_aesni.c cpusupport_x86_rdrand.c cpusupport_x86_shani.c cpusupport_x86_sse2.c cpusupport_x86_ssse3.c crypto_aes.c crypto_aes_aesni.c crypto_aes_arm.c crypto_aesctr.c crypto_aesctr_aesni.c crypto_aesctr_arm.c crypto_dh.c crypto_dh_group14.c crypto_entropy.c crypto_entropy_rdrand.c crypto_verify_bytes.c elasticarray.c ptrheap.c timerqueue.c events.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c netbuf_read.c network_accept.c network_connect.c network_read.c network_write.c asprintf.c daemonize.c entropy.c getopt.c insecure_memzero.c monoclock.c noeintr.c perftest.c setgroups_none.c setuidgid.c sock.c sock_util.c warnp.c dnsthread.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c graceful_shutdown.c pthread_create_blocking_np.c +IDIRS=-I../libcperciva/alg -I../libcperciva/cpusupport -I../libcperciva/crypto -I../libcperciva/datastruct -I../libcperciva/events -I../libcperciva/netbuf -I../libcperciva/network -I../libcperciva/util -I../lib/dnsthread -I../lib/proto -I../lib/util +SUBDIR_DEPTH=.. +RELATIVE_DIR=liball + +all: + if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ + cd ${SUBDIR_DEPTH}; \ + ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ + BUILD_TARGET=${PROG} buildsubdir; \ + else \ + ${MAKE} ${LIB}; \ + fi + +clean: + rm -f ${LIB} ${SRCS:.c=.o} + +${LIB}:${SRCS:.c=.o} + ${AR} ${ARFLAGS} ${LIB} ${SRCS:.c=.o} + +sha256.o: ../libcperciva/alg/sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256_arm.h ../libcperciva/alg/sha256_shani.h ../libcperciva/alg/sha256_sse2.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../libcperciva/alg/sha256.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256.c -o sha256.o +sha256_arm.o: ../libcperciva/alg/sha256_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_arm.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_ARM_SHA256} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256_arm.c -o sha256_arm.o +sha256_shani.o: ../libcperciva/alg/sha256_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_shani.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_SHANI} ${CFLAGS_X86_SSSE3} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256_shani.c -o sha256_shani.o +sha256_sse2.o: ../libcperciva/alg/sha256_sse2.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_sse2.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_SSE2} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256_sse2.c -o sha256_sse2.o +cpusupport_arm_aes.o: ../libcperciva/cpusupport/cpusupport_arm_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_arm_aes.c -o cpusupport_arm_aes.o +cpusupport_arm_sha256.o: ../libcperciva/cpusupport/cpusupport_arm_sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_arm_sha256.c -o cpusupport_arm_sha256.o +cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o +cpusupport_x86_rdrand.o: ../libcperciva/cpusupport/cpusupport_x86_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_rdrand.c -o cpusupport_x86_rdrand.o +cpusupport_x86_shani.o: ../libcperciva/cpusupport/cpusupport_x86_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_shani.c -o cpusupport_x86_shani.o +cpusupport_x86_sse2.o: ../libcperciva/cpusupport/cpusupport_x86_sse2.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_sse2.c -o cpusupport_x86_sse2.o +cpusupport_x86_ssse3.o: ../libcperciva/cpusupport/cpusupport_x86_ssse3.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_ssse3.c -o cpusupport_x86_ssse3.o +crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/crypto/crypto_aes_arm.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o +crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/align_ptr.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/crypto/crypto_aes_aesni_m128i.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o +crypto_aes_arm.o: ../libcperciva/crypto/crypto_aes_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/align_ptr.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes_arm.h ../libcperciva/crypto/crypto_aes_arm_u8.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_ARM_AES} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes_arm.c -o crypto_aes_arm.o +crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr_aesni.h ../libcperciva/crypto/crypto_aesctr_arm.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_aesctr_shared.c + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o +crypto_aesctr_aesni.o: ../libcperciva/crypto/crypto_aesctr_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aes_aesni_m128i.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr_aesni.h ../libcperciva/crypto/crypto_aesctr_shared.c + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr_aesni.c -o crypto_aesctr_aesni.o +crypto_aesctr_arm.o: ../libcperciva/crypto/crypto_aesctr_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aes_arm_u8.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr_arm.h ../libcperciva/crypto/crypto_aesctr_shared.c + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_ARM_AES} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr_arm.c -o crypto_aesctr_arm.o +crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_dh_group14.h ../libcperciva/crypto/crypto_entropy.h ../libcperciva/crypto/crypto_dh.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o +crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ../libcperciva/crypto/crypto_dh_group14.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o +crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h ../libcperciva/util/entropy.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/crypto/crypto_entropy.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o +crypto_entropy_rdrand.o: ../libcperciva/crypto/crypto_entropy_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_RDRAND} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy_rdrand.c -o crypto_entropy_rdrand.o +crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ../libcperciva/crypto/crypto_verify_bytes.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o +elasticarray.o: ../libcperciva/datastruct/elasticarray.c ../libcperciva/datastruct/elasticarray.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o +ptrheap.o: ../libcperciva/datastruct/ptrheap.c ../libcperciva/datastruct/elasticarray.h ../libcperciva/datastruct/ptrheap.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o +timerqueue.o: ../libcperciva/datastruct/timerqueue.c ../libcperciva/datastruct/ptrheap.h ../libcperciva/datastruct/timerqueue.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o +events.o: ../libcperciva/events/events.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events.c -o events.o +events_immediate.o: ../libcperciva/events/events_immediate.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o +events_network.o: ../libcperciva/events/events_network.c ../libcperciva/util/ctassert.h ../libcperciva/datastruct/elasticarray.h ../libcperciva/util/warnp.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network.c -o events_network.o +events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ../libcperciva/util/monoclock.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o +events_timer.o: ../libcperciva/events/events_timer.c ../libcperciva/util/monoclock.h ../libcperciva/datastruct/timerqueue.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_timer.c -o events_timer.o +netbuf_read.o: ../libcperciva/netbuf/netbuf_read.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/netbuf/netbuf.h ../libcperciva/netbuf/netbuf_ssl_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/netbuf/netbuf_read.c -o netbuf_read.o +network_accept.o: ../libcperciva/network/network_accept.c ../libcperciva/events/events.h ../libcperciva/network/network.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_accept.c -o network_accept.o +network_connect.o: ../libcperciva/network/network_connect.c ../libcperciva/events/events.h ../libcperciva/util/sock.h ../libcperciva/network/network.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_connect.c -o network_connect.o +network_read.o: ../libcperciva/network/network_read.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/network/network.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_read.c -o network_read.o +network_write.o: ../libcperciva/network/network_write.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/util/warnp.h ../libcperciva/network/network.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_write.c -o network_write.o +asprintf.o: ../libcperciva/util/asprintf.c ../libcperciva/util/asprintf.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/asprintf.c -o asprintf.o +daemonize.o: ../libcperciva/util/daemonize.c ../libcperciva/util/noeintr.h ../libcperciva/util/warnp.h ../libcperciva/util/daemonize.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/daemonize.c -o daemonize.o +entropy.o: ../libcperciva/util/entropy.c ../libcperciva/util/warnp.h ../libcperciva/util/entropy.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/entropy.c -o entropy.o +getopt.o: ../libcperciva/util/getopt.c ../libcperciva/util/getopt.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/getopt.c -o getopt.o +insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ../libcperciva/util/insecure_memzero.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o +monoclock.o: ../libcperciva/util/monoclock.c ../libcperciva/util/warnp.h ../libcperciva/util/monoclock.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/monoclock.c -o monoclock.o +noeintr.o: ../libcperciva/util/noeintr.c ../libcperciva/util/noeintr.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/noeintr.c -o noeintr.o +perftest.o: ../libcperciva/util/perftest.c ../libcperciva/util/monoclock.h ../libcperciva/util/warnp.h ../libcperciva/util/perftest.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/perftest.c -o perftest.o +setgroups_none.o: ../libcperciva/util/setgroups_none.c ../libcperciva/util/setgroups_none.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/setgroups_none.c -o setgroups_none.o +setuidgid.o: ../libcperciva/util/setuidgid.c ../libcperciva/util/parsenum.h ../libcperciva/util/setgroups_none.h ../libcperciva/util/warnp.h ../libcperciva/util/setuidgid.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/setuidgid.c -o setuidgid.o +sock.o: ../libcperciva/util/sock.c ../libcperciva/util/imalloc.h ../libcperciva/util/parsenum.h ../libcperciva/util/warnp.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock.c -o sock.o +sock_util.o: ../libcperciva/util/sock_util.c ../libcperciva/util/asprintf.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h ../libcperciva/util/sock_util.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock_util.c -o sock_util.o +warnp.o: ../libcperciva/util/warnp.c ../libcperciva/util/warnp.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/warnp.c -o warnp.o +dnsthread.o: ../lib/dnsthread/dnsthread.c ../libcperciva/events/events.h ../libcperciva/util/noeintr.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../lib/dnsthread/dnsthread.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/dnsthread/dnsthread.c -o dnsthread.o +proto_conn.o: ../lib/proto/proto_conn.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_handshake.h ../lib/proto/proto_pipe.h ../lib/proto/proto_conn.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_conn.c -o proto_conn.o +proto_crypt.o: ../lib/proto/proto_crypt.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_verify_bytes.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_crypt.c -o proto_crypt.o +proto_handshake.o: ../lib/proto/proto_handshake.c ../libcperciva/crypto/crypto_entropy.h ../libcperciva/network/network.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_handshake.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_handshake.c -o proto_handshake.o +proto_pipe.o: ../lib/proto/proto_pipe.c ../libcperciva/netbuf/netbuf.h ../libcperciva/network/network.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_pipe.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_pipe.c -o proto_pipe.o +graceful_shutdown.o: ../lib/util/graceful_shutdown.c ../libcperciva/events/events.h ../libcperciva/util/warnp.h ../lib/util/graceful_shutdown.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/graceful_shutdown.c -o graceful_shutdown.o +pthread_create_blocking_np.o: ../lib/util/pthread_create_blocking_np.c ../lib/util/pthread_create_blocking_np.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/pthread_create_blocking_np.c -o pthread_create_blocking_np.o diff -Nru spiped-1.6.1/libcperciva/alg/sha256_arm.c spiped-1.6.2/libcperciva/alg/sha256_arm.c --- spiped-1.6.1/libcperciva/alg/sha256_arm.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_arm.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,102 @@ +#include "cpusupport.h" +#ifdef CPUSUPPORT_ARM_SHA256 +/** + * CPUSUPPORT CFLAGS: ARM_SHA256 + */ + +#include +#include +#include + +#ifdef __ARM_NEON +#include +#endif + +#include "sha256_arm.h" + +/* SHA256 round constants. */ +static const uint32_t Krnd[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* Round computation. */ +#define RND4(S, M, Kp) do { \ + uint32x4_t S0_step; \ + uint32x4_t Wk; \ + S0_step = S[0]; \ + Wk = vaddq_u32(M, vld1q_u32(Kp)); \ + S[0] = vsha256hq_u32(S[0], S[1], Wk); \ + S[1] = vsha256h2q_u32(S[1], S0_step, Wk); \ + } while (0) + +/* Message schedule computation */ +#define MSG4(X0, X1, X2, X3) \ + X0 = vsha256su1q_u32(vsha256su0q_u32(X0, X1), X2, X3) + +/** + * SHA256_Transform_arm(state, block, W, S): + * Compute the SHA256 block compression function, transforming ${state} using + * the data in ${block}. This implementation uses ARM SHA256 instructions, + * and should only be used if _SHA256 is defined and cpusupport_arm_sha256() + * returns nonzero. The arrays W and S may be filled with sensitive data, and + * should be cleared by the callee. + */ +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +void +SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64]) +#else +void +SHA256_Transform_arm(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64]) +#endif +{ + uint32x4_t Y[4]; + uint32x4_t S[2]; + uint32x4_t _state[2]; + int i; + + /* 1. Prepare the first part of the message schedule W. */ + Y[0] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[0]))); + Y[1] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[16]))); + Y[2] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[32]))); + Y[3] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[48]))); + + /* 2. Initialize working variables. */ + S[0] = _state[0] = vld1q_u32(&state[0]); + S[1] = _state[1] = vld1q_u32(&state[4]); + + /* 3. Mix. */ + for (i = 0; i < 64; i += 16) { + RND4(S, Y[0], &Krnd[i + 0]); + RND4(S, Y[1], &Krnd[i + 4]); + RND4(S, Y[2], &Krnd[i + 8]); + RND4(S, Y[3], &Krnd[i + 12]); + + if (i == 48) + break; + MSG4(Y[0], Y[1], Y[2], Y[3]); + MSG4(Y[1], Y[2], Y[3], Y[0]); + MSG4(Y[2], Y[3], Y[0], Y[1]); + MSG4(Y[3], Y[0], Y[1], Y[2]); + } + + /* 4. Mix local working variables into global state. */ + vst1q_u32(&state[0], vaddq_u32(_state[0], S[0])); + vst1q_u32(&state[4], vaddq_u32(_state[1], S[1])); +} +#endif /* CPUSUPPORT_ARM_SHA256 */ diff -Nru spiped-1.6.1/libcperciva/alg/sha256_arm.h spiped-1.6.2/libcperciva/alg/sha256_arm.h --- spiped-1.6.1/libcperciva/alg/sha256_arm.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_arm.h 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,21 @@ +#ifndef _SHA256_ARM_H_ +#define _SHA256_ARM_H_ + +#include + +/** + * SHA256_Transform_arm(state, block, W, S): + * Compute the SHA256 block compression function, transforming ${state} using + * the data in ${block}. This implementation uses ARM SHA256 instructions, + * and should only be used if _SHA256 is defined and cpusupport_arm_sha256() + * returns nonzero. The arrays W and S may be filled with sensitive data, and + * should be cleared by the callee. + */ +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +void SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64]); +#else +void SHA256_Transform_arm(uint32_t[static restrict 8], + const uint8_t[static restrict 64]); +#endif + +#endif /* !_SHA256_ARM_H_ */ diff -Nru spiped-1.6.1/libcperciva/alg/sha256.c spiped-1.6.2/libcperciva/alg/sha256.c --- spiped-1.6.1/libcperciva/alg/sha256.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256.c 2021-12-09 22:15:31.000000000 +0000 @@ -4,15 +4,43 @@ #include "cpusupport.h" #include "insecure_memzero.h" +#include "sha256_arm.h" #include "sha256_shani.h" +#include "sha256_sse2.h" #include "sysendian.h" #include "warnp.h" #include "sha256.h" +#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) || \ + defined(CPUSUPPORT_X86_SSE2) || \ + defined(CPUSUPPORT_ARM_SHA256) +#define HWACCEL + +static enum { + HW_SOFTWARE = 0, +#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) + HW_X86_SHANI, +#endif +#if defined(CPUSUPPORT_X86_SSE2) + HW_X86_SSE2, +#endif +#if defined(CPUSUPPORT_ARM_SHA256) + HW_ARM_SHA256, +#endif + HW_UNSET +} hwaccel = HW_UNSET; +#endif + +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +static void SHA256_Transform(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8]); +#else static void SHA256_Transform(uint32_t[static restrict 8], const uint8_t[static restrict 64], uint32_t[static restrict 64], uint32_t[static restrict 8]); +#endif /* * Encode a length len/4 vector of (uint32_t) into a length len vector of @@ -74,69 +102,99 @@ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 }; +#ifdef HWACCEL #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) +/* Shim so that we can test SHA256_Transform_shani() in the standard manner. */ +static void +SHA256_Transform_shani_with_W_S(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8]) +{ + + (void)W; /* UNUSED */ + (void)S; /* UNUSED */ + + SHA256_Transform_shani(state, block); +} +#endif +#if defined(CPUSUPPORT_ARM_SHA256) +/* Shim so that we can test SHA256_Transform_arm() in the standard manner. */ +static void +SHA256_Transform_arm_with_W_S(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8]) +{ + + (void)W; /* UNUSED */ + (void)S; /* UNUSED */ + + SHA256_Transform_arm(state, block); +} +#endif + /* - * Test whether software and SHANI transform code produce the same results. - * Must be called with usesha() returning 0 (software). + * Test whether software and hardware extensions transform code produce the + * same results. Must be called with (hwaccel == HW_SOFTWARE). */ static int -shanitest(const uint32_t state[static restrict 8], +hwtest(const uint32_t state[static restrict 8], const uint8_t block[static restrict 64], - uint32_t W[static restrict 64], uint32_t S[static restrict 8]) + uint32_t W[static restrict 64], uint32_t S[static restrict 8], + void(* func)(uint32_t [static restrict 8], + const uint8_t [static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8])) { uint32_t state_sw[8]; - uint32_t state_shani[8]; + uint32_t state_hw[8]; /* Software transform. */ memcpy(state_sw, state, sizeof(state_sw)); SHA256_Transform(state_sw, block, W, S); - /* SHANI transform. */ - memcpy(state_shani, state, sizeof(state_shani)); - SHA256_Transform_shani(state_shani, block); + /* Hardware transform. */ + memcpy(state_hw, state, sizeof(state_hw)); + func(state_hw, block, W, S); /* Do the results match? */ - return (memcmp(state_sw, state_shani, sizeof(state_sw))); + return (memcmp(state_sw, state_hw, sizeof(state_sw))); } -/* Should we use SHANI? */ -static int -useshani(void) +/* Which type of hardware acceleration should we use, if any? */ +static void +hwaccel_init(void) { - static int shanigood = -1; uint32_t W[64]; uint32_t S[8]; uint8_t block[64]; uint8_t i; - /* If we haven't decided which code to use yet, decide now. */ - while (shanigood == -1) { - /* Default to software. */ - shanigood = 0; - - /* If the CPU doesn't claim to support AESNI, stop here. */ - if (!cpusupport_x86_shani()) - break; - - /* If the CPU doesn't claim to support SSSE3, stop here. */ - if (!cpusupport_x86_ssse3()) - break; + /* If we've already set hwaccel, we're finished. */ + if (hwaccel != HW_UNSET) + return; - /* Test case: Hash 0x00 0x01 0x02 ... 0x3f. */ - for (i = 0; i < 64; i++) - block[i] = i; - if (shanitest(initial_state, block, W, S)) { - warn0("Disabling SHANI due to failed self-test"); - break; - } + /* Default to software. */ + hwaccel = HW_SOFTWARE; - /* SHANI works; use it. */ - shanigood = 1; - } + /* Test case: Hash 0x00 0x01 0x02 ... 0x3f. */ + for (i = 0; i < 64; i++) + block[i] = i; - return (shanigood); +#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) + CPUSUPPORT_VALIDATE(hwaccel, HW_X86_SHANI, + cpusupport_x86_shani() && cpusupport_x86_ssse3(), + hwtest(initial_state, block, W, S, + SHA256_Transform_shani_with_W_S)); +#endif +#if defined(CPUSUPPORT_X86_SSE2) + CPUSUPPORT_VALIDATE(hwaccel, HW_X86_SSE2, cpusupport_x86_sse2(), + hwtest(initial_state, block, W, S, SHA256_Transform_sse2)); +#endif +#if defined(CPUSUPPORT_ARM_SHA256) + CPUSUPPORT_VALIDATE(hwaccel, HW_ARM_SHA256, cpusupport_arm_sha256(), + hwtest(initial_state, block, W, S, SHA256_Transform_arm_with_W_S)); +#endif } -#endif /* CPUSUPPORT_X86_SHANI && CPUSUPPORT_X86_SSSE3 */ +#endif /* HWACCEL */ /* Elementary functions used by SHA256 */ #define Ch(x, y, z) ((x & (y ^ z)) ^ z) @@ -168,7 +226,8 @@ /* * SHA256 block compression function. The 256-bit state is transformed via - * the 512-bit input block to produce a new state. + * the 512-bit input block to produce a new state. The arrays W and S may be + * filled with sensitive data, and should be sanitized by the callee. */ static void SHA256_Transform(uint32_t state[static restrict 8], @@ -177,13 +236,39 @@ { int i; +#ifdef HWACCEL + +#if defined(__GNUC__) && defined(__aarch64__) + /* + * We require that SHA256_Init() is called before SHA256_Transform(), + * but the compiler has no way of knowing that. This assert adds a + * significant speed boost for gcc on 64-bit ARM, and a minor penalty + * on other systems & compilers. + */ + assert(hwaccel != HW_UNSET); +#endif + + switch(hwaccel) { #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) - /* Use SHANI if we can. */ - if (useshani()) { + case HW_X86_SHANI: SHA256_Transform_shani(state, block); return; - } #endif +#if defined(CPUSUPPORT_X86_SSE2) + case HW_X86_SSE2: + SHA256_Transform_sse2(state, block, W, S); + return; +#endif +#if defined(CPUSUPPORT_ARM_SHA256) + case HW_ARM_SHA256: + SHA256_Transform_arm(state, block); + return; +#endif + case HW_SOFTWARE: + case HW_UNSET: + break; + } +#endif /* HWACCEL */ /* 1. Prepare the first part of the message schedule W. */ be32dec_vect(W, block, 64); @@ -284,6 +369,11 @@ /* Initialize state. */ memcpy(ctx->state, initial_state, sizeof(initial_state)); + +#ifdef HWACCEL + /* Ensure that we've chosen the type of hardware acceleration. */ + hwaccel_init(); +#endif } /** @@ -340,13 +430,13 @@ _SHA256_Update(ctx, in, len, tmp32); /* Clean the stack. */ - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); } /** * SHA256_Final(digest, ctx): * Output the SHA256 hash of the data input to the context ${ctx} into the - * buffer ${digest}. + * buffer ${digest}, and clear the context state. */ static void _SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx, @@ -373,7 +463,7 @@ insecure_memzero(ctx, sizeof(SHA256_CTX)); /* Clean the stack. */ - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); } /** @@ -392,7 +482,7 @@ /* Clean the stack. */ insecure_memzero(&ctx, sizeof(SHA256_CTX)); - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); } /** @@ -444,7 +534,7 @@ _HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash); /* Clean the stack. */ - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); insecure_memzero(khash, 32); insecure_memzero(pad, 64); } @@ -472,13 +562,13 @@ _HMAC_SHA256_Update(ctx, in, len, tmp32); /* Clean the stack. */ - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); } /** * HMAC_SHA256_Final(digest, ctx): * Output the HMAC-SHA256 of the data input to the context ${ctx} into the - * buffer ${digest}. + * buffer ${digest}, and clear the context state. */ static void _HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx, @@ -509,7 +599,7 @@ insecure_memzero(ctx, sizeof(HMAC_SHA256_CTX)); /* Clean the stack. */ - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); insecure_memzero(ihash, 32); } @@ -532,7 +622,7 @@ /* Clean the stack. */ insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX)); - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); insecure_memzero(tmp8, 96); } @@ -556,8 +646,10 @@ int k; size_t clen; +#if SIZE_MAX >= (32 * UINT32_MAX) /* Sanity-check. */ assert(dkLen <= 32 * (size_t)(UINT32_MAX)); +#endif /* Compute HMAC state after processing P. */ _HMAC_SHA256_Init(&Phctx, passwd, passwdlen, @@ -602,7 +694,7 @@ insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX)); insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX)); insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX)); - insecure_memzero(tmp32, 288); + insecure_memzero(tmp32, sizeof(uint32_t) * 72); insecure_memzero(tmp8, 96); insecure_memzero(U, 32); insecure_memzero(T, 32); diff -Nru spiped-1.6.1/libcperciva/alg/sha256.h spiped-1.6.2/libcperciva/alg/sha256.h --- spiped-1.6.1/libcperciva/alg/sha256.h 2017-01-27 22:38:34.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256.h 2021-01-11 23:41:03.000000000 +0000 @@ -41,7 +41,7 @@ /** * SHA256_Final(digest, ctx): * Output the SHA256 hash of the data input to the context ${ctx} into the - * buffer ${digest}. + * buffer ${digest}, and clear the context state. */ void SHA256_Final(uint8_t[32], SHA256_CTX *); @@ -73,7 +73,7 @@ /** * HMAC_SHA256_Final(digest, ctx): * Output the HMAC-SHA256 of the data input to the context ${ctx} into the - * buffer ${digest}. + * buffer ${digest}, and clear the context state. */ void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *); diff -Nru spiped-1.6.1/libcperciva/alg/sha256_shani.c spiped-1.6.2/libcperciva/alg/sha256_shani.c --- spiped-1.6.1/libcperciva/alg/sha256_shani.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_shani.c 2021-12-09 22:15:31.000000000 +0000 @@ -1,5 +1,8 @@ #include "cpusupport.h" #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) +/** + * CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3 + */ #include #include @@ -53,7 +56,7 @@ /* Shift the two words of M down and perform the next two rounds. */ \ M = _mm_srli_si128(M, 8); \ S[0] = _mm_sha256rnds2_epu32(S[0], S[1], M); \ -} while (0); +} while (0) /* Compute the ith set of four words of message schedule. */ #define MSG4(W, i) do { \ diff -Nru spiped-1.6.1/libcperciva/alg/sha256_shani.h spiped-1.6.2/libcperciva/alg/sha256_shani.h --- spiped-1.6.1/libcperciva/alg/sha256_shani.h 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_shani.h 2020-09-02 04:32:10.000000000 +0000 @@ -10,8 +10,12 @@ * instructions, and should only be used if CPUSUPPORT_X86_SHANI and _SSSE3 * are defined and cpusupport_x86_shani() and _ssse3() return nonzero. */ -void -SHA256_Transform_shani(uint32_t[static restrict 8], +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +void SHA256_Transform_shani(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64]); +#else +void SHA256_Transform_shani(uint32_t[static restrict 8], const uint8_t[static restrict 64]); +#endif #endif /* !_SHA256_SHANI_H_ */ diff -Nru spiped-1.6.1/libcperciva/alg/sha256_sse2.c spiped-1.6.2/libcperciva/alg/sha256_sse2.c --- spiped-1.6.1/libcperciva/alg/sha256_sse2.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_sse2.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,239 @@ +#include "cpusupport.h" +#ifdef CPUSUPPORT_X86_SSE2 +/** + * CPUSUPPORT CFLAGS: X86_SSE2 + */ + +#include +#include +#include + +#include + +#include "sha256_sse2.h" + +/** + * _mm_bswap_epi32(a): + * Byte-swap each 32-bit word. + */ +static inline __m128i +_mm_bswap_epi32(__m128i a) +{ + + /* Swap bytes in each 16-bit word. */ + a = _mm_or_si128(_mm_slli_epi16(a, 8), _mm_srli_epi16(a, 8)); + + /* Swap all 16-bit words. */ + a = _mm_shufflelo_epi16(a, _MM_SHUFFLE(2, 3, 0, 1)); + a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(2, 3, 0, 1)); + + return (a); +} + +/* SHA256 round constants. */ +static const uint32_t Krnd[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* Elementary functions used by SHA256 */ +#define Ch(x, y, z) ((x & (y ^ z)) ^ z) +#define Maj(x, y, z) ((x & (y | z)) | (y & z)) +#define ROTR(x, n) ((x >> n) | (x << (32 - n))) +#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) + +/* SHA256 round function */ +#define RND(a, b, c, d, e, f, g, h, k) \ + h += S1(e) + Ch(e, f, g) + k; \ + d += h; \ + h += S0(a) + Maj(a, b, c) + +/* Adjusted round function for rotating state */ +#define RNDr(S, W, i, ii) \ + RND(S[(64 - i) % 8], S[(65 - i) % 8], \ + S[(66 - i) % 8], S[(67 - i) % 8], \ + S[(68 - i) % 8], S[(69 - i) % 8], \ + S[(70 - i) % 8], S[(71 - i) % 8], \ + W[i + ii] + Krnd[i + ii]) + +/* Message schedule computation */ +#define SHR32(x, n) (_mm_srli_epi32(x, n)) +#define ROTR32(x, n) (_mm_or_si128(SHR32(x, n), _mm_slli_epi32(x, (32-n)))) +#define s0_128(x) _mm_xor_si128(_mm_xor_si128( \ + ROTR32(x, 7), ROTR32(x, 18)), SHR32(x, 3)) + +static inline __m128i +s1_128_high(__m128i a) +{ + __m128i b; + __m128i c; + + /* ROTR, loading data as {B, B, A, A}; lanes 1 & 3 will be junk. */ + b = _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 1, 0, 0)); + c = _mm_xor_si128(_mm_srli_epi64(b, 17), _mm_srli_epi64(b, 19)); + + /* Shift and XOR with rotated data; lanes 1 & 3 will be junk. */ + c = _mm_xor_si128(c, _mm_srli_epi32(b, 10)); + + /* Shuffle good data back and zero unwanted lanes. */ + c = _mm_shuffle_epi32(c, _MM_SHUFFLE(2, 0, 2, 0)); + c = _mm_slli_si128(c, 8); + + return (c); +} + +static inline __m128i +s1_128_low(__m128i a) +{ + __m128i b; + __m128i c; + + /* ROTR, loading data as {B, B, A, A}; lanes 1 & 3 will be junk. */ + b = _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 3, 2, 2)); + c = _mm_xor_si128(_mm_srli_epi64(b, 17), _mm_srli_epi64(b, 19)); + + /* Shift and XOR with rotated data; lanes 1 & 3 will be junk. */ + c = _mm_xor_si128(c, _mm_srli_epi32(b, 10)); + + /* Shuffle good data back and zero unwanted lanes. */ + c = _mm_shuffle_epi32(c, _MM_SHUFFLE(2, 0, 2, 0)); + c = _mm_srli_si128(c, 8); + + return (c); +} + +/** + * SPAN_ONE_THREE(a, b): + * Combine the upper three words of ${a} with the lowest word of ${b}. This + * could also be thought of returning bits [159:32] of the 256-bit value + * consisting of (b[127:0] a[127:0]). In other words, set: + * dst[31:0] := a[63:32] + * dst[63:32] := a[95:64] + * dst[95:64] := a[127:96] + * dst[127:96] := b[31:0] + */ +#define SPAN_ONE_THREE(a, b) (_mm_shuffle_epi32(_mm_castps_si128( \ + _mm_move_ss(_mm_castsi128_ps(a), _mm_castsi128_ps(b))), \ + _MM_SHUFFLE(0, 3, 2, 1))) + +/** + * MSG4(X0, X1, X2, X3): + * Calculate the next four values of the message schedule. If we define + * ${W[j]} as the first unknown value in the message schedule, then the input + * arguments are: + * X0 = W[j - 16] : W[j - 13] + * X1 = W[j - 12] : W[j - 9] + * X2 = W[j - 8] : W[j - 5] + * X3 = W[j - 4] : W[j - 1] + * This function therefore calculates: + * X4 = W[j + 0] : W[j + 3] + */ +static inline __m128i +MSG4(__m128i X0, __m128i X1, __m128i X2, __m128i X3) +{ + __m128i X4; + __m128i Xj_minus_seven, Xj_minus_fifteen; + + /* Set up variables which span X values. */ + Xj_minus_seven = SPAN_ONE_THREE(X2, X3); + Xj_minus_fifteen = SPAN_ONE_THREE(X0, X1); + + /* Begin computing X4. */ + X4 = _mm_add_epi32(X0, Xj_minus_seven); + X4 = _mm_add_epi32(X4, s0_128(Xj_minus_fifteen)); + + /* First half of s1. */ + X4 = _mm_add_epi32(X4, s1_128_low(X3)); + + /* Second half of s1; this depends on the above value of X4. */ + X4 = _mm_add_epi32(X4, s1_128_high(X4)); + + return (X4); +} + +/** + * SHA256_Transform_sse2(state, block): + * Compute the SHA256 block compression function, transforming ${state} using + * the data in ${block}. This implementation uses x86 SSE2 instructions, and + * should only be used if _SSE2 is defined and cpusupport_x86_sse2() returns + * nonzero. The arrays W and S may be filled with sensitive data, and should + * be cleared by the callee. + */ +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +void +SHA256_Transform_sse2(uint32_t state[8], const uint8_t block[64], + uint32_t W[64], uint32_t S[8]) +#else +void +SHA256_Transform_sse2(uint32_t state[static restrict 8], + const uint8_t block[static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8]) +#endif +{ + __m128i Y[4]; + int i; + + /* 1. Prepare the first part of the message schedule W. */ + Y[0] = _mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[0])); + _mm_storeu_si128((__m128i *)&W[0], Y[0]); + Y[1] = _mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[16])); + _mm_storeu_si128((__m128i *)&W[4], Y[1]); + Y[2] = _mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[32])); + _mm_storeu_si128((__m128i *)&W[8], Y[2]); + Y[3] = _mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[48])); + _mm_storeu_si128((__m128i *)&W[12], Y[3]); + + /* 2. Initialize working variables. */ + memcpy(S, state, 32); + + /* 3. Mix. */ + for (i = 0; i < 64; i += 16) { + RNDr(S, W, 0, i); + RNDr(S, W, 1, i); + RNDr(S, W, 2, i); + RNDr(S, W, 3, i); + RNDr(S, W, 4, i); + RNDr(S, W, 5, i); + RNDr(S, W, 6, i); + RNDr(S, W, 7, i); + RNDr(S, W, 8, i); + RNDr(S, W, 9, i); + RNDr(S, W, 10, i); + RNDr(S, W, 11, i); + RNDr(S, W, 12, i); + RNDr(S, W, 13, i); + RNDr(S, W, 14, i); + RNDr(S, W, 15, i); + + if (i == 48) + break; + Y[0] = MSG4(Y[0], Y[1], Y[2], Y[3]); + _mm_storeu_si128((__m128i *)&W[16 + i + 0], Y[0]); + Y[1] = MSG4(Y[1], Y[2], Y[3], Y[0]); + _mm_storeu_si128((__m128i *)&W[16 + i + 4], Y[1]); + Y[2] = MSG4(Y[2], Y[3], Y[0], Y[1]); + _mm_storeu_si128((__m128i *)&W[16 + i + 8], Y[2]); + Y[3] = MSG4(Y[3], Y[0], Y[1], Y[2]); + _mm_storeu_si128((__m128i *)&W[16 + i + 12], Y[3]); + } + + /* 4. Mix local working variables into global state. */ + for (i = 0; i < 8; i++) + state[i] += S[i]; +} +#endif /* CPUSUPPORT_X86_SSE2 */ diff -Nru spiped-1.6.1/libcperciva/alg/sha256_sse2.h spiped-1.6.2/libcperciva/alg/sha256_sse2.h --- spiped-1.6.1/libcperciva/alg/sha256_sse2.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/alg/sha256_sse2.h 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,23 @@ +#ifndef _SHA256_SSE2_H_ +#define _SHA256_SSE2_H_ + +#include + +/** + * SHA256_Transform_sse2(state, block): + * Compute the SHA256 block compression function, transforming ${state} using + * the data in ${block}. This implementation uses x86 SSE2 instructions, and + * should only be used if _SSE2 is defined and cpusupport_x86_sse2() returns + * nonzero. The arrays W and S may be filled with sensitive data, and should + * be cleared by the callee. + */ +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +void SHA256_Transform_sse2(uint32_t state[8], + const uint8_t block[64], uint32_t W[64], uint32_t S[8]); +#else +void SHA256_Transform_sse2(uint32_t[static restrict 8], + const uint8_t[static restrict 64], uint32_t W[static restrict 64], + uint32_t S[static restrict 8]); +#endif + +#endif /* !_SHA256_SSE2_H_ */ diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-ARM-AES.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-ARM-AES.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-ARM-AES.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-ARM-AES.c 2021-12-17 17:16:26.000000000 +0000 @@ -0,0 +1,21 @@ +#ifdef __ARM_NEON +#include +#endif + +int +main(void) +{ + uint8x16_t data; + uint8x16_t key = {0}; + uint8x16_t output; + uint32x4_t lanes = {0}; + uint8_t arr[16] = {0}; + + data = vld1q_u8(arr); + output = vaeseq_u8(data, key); + (void)output; /* UNUSED */ + + lanes = vdupq_laneq_u32(lanes, 0); + + return (0); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,16 @@ +#ifdef __ARM_NEON +#include +#endif + +int +main(void) +{ + uint32x4_t w0 = {0}; + uint32x4_t w4 = {0}; + uint32x4_t output; + + output = vsha256su0q_u32(w0, w4); + (void)output; /* UNUSED */ + + return (0); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c 2021-08-01 23:41:28.000000000 +0000 @@ -0,0 +1,13 @@ +#include + +int +main(void) +{ + int res; + unsigned long val; + + res = elf_aux_info(AT_HWCAP, &val, sizeof(unsigned long)); + (void)res; + + return (val != 0); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,11 @@ +#include + +int +main(void) +{ + unsigned long val; + + val = getauxval(AT_HWCAP); + + return (val != 0); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport.sh spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport.sh --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport.sh 2019-11-06 00:04:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport.sh 2021-08-01 23:41:28.000000000 +0000 @@ -7,7 +7,7 @@ # Standard output should be written to cpusupport-config.h, which is both a # C header file defining CPUSUPPORT_ARCH_FEATURE macros and sourceable sh # code which sets CFLAGS_ARCH_FEATURE environment variables. -SRCDIR=`command -p dirname "$0"` +SRCDIR=$(command -p dirname "$0") feature() { ARCH=$1 @@ -43,7 +43,17 @@ esac } +if [ "$2" = "--all" ]; then + feature() { + ARCH=$1 + FEATURE=$2 + echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" + } +fi + # Detect CPU-detection features +feature HWCAP ELF_AUX_INFO "" +feature HWCAP GETAUXVAL "" feature X86 CPUID "" feature X86 CPUID_COUNT "" @@ -51,15 +61,34 @@ feature X86 AESNI "" "-maes" \ "-maes -Wno-cast-align" \ "-maes -Wno-missing-prototypes -Wno-cast-qual" \ - "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align" -feature X86 CRC32_64 "" "-msse4.2" \ - "-msse4.2 -Wno-cast-align" \ - "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ - "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" + "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align" \ + "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align \ + -DBROKEN_MM_LOADU_SI64" feature X86 RDRAND "" "-mrdrnd" feature X86 SHANI "" "-msse2 -msha" \ "-msse2 -msha -Wno-cast-align" -feature X86 SSE2 "" "-msse2" \ +feature X86 SSE2 "" \ + "-Wno-cast-align" \ + "-msse2" \ "-msse2 -Wno-cast-align" +feature X86 SSE42 "" "-msse4.2" \ + "-msse4.2 -Wno-cast-align" \ + "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ + "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" +feature X86 SSE42_64 "" "-msse4.2" \ + "-msse4.2 -Wno-cast-align" \ + "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ + "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" feature X86 SSSE3 "" "-mssse3" \ "-mssse3 -Wno-cast-align" + +# Detect specific ARM features +feature ARM AES "-march=armv8.1-a+crypto" \ + "-march=armv8.1-a+crypto -D__ARM_ACLE=200" +feature ARM CRC32_64 "-march=armv8.1-a" \ + "-march=armv8.1-a+crc" \ + "-march=armv8.1-a+crc -Wno-cast-align" \ + "-march=armv8.1-a -D__ARM_ACLE=200" +feature ARM SHA256 "-march=armv8.1-a+crypto" \ + "-march=armv8.1-a+crypto -Wno-cast-align" \ + "-march=armv8.1-a+crypto -D__ARM_ACLE=200" diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c 2021-03-22 17:57:56.000000000 +0000 @@ -2,15 +2,33 @@ #include -static uint8_t a[16]; +/* + * Use a separate function for this, because that means that the alignment of + * the _mm_loadu_si128() will move to function level, which may require + * -Wno-cast-align. + */ +static __m128i +load_128(const uint8_t * src) +{ + __m128i x; + + x = _mm_loadu_si128((const __m128i *)src); + return (x); +} int main(void) { __m128i x, y; + uint8_t a[16]; - x = _mm_loadu_si128((const __m128i *)&a[0]); - y = _mm_aesenc_si128(x, x); + x = load_128(a); +#ifdef BROKEN_MM_LOADU_SI64 + y = _mm_loadu_si128(a); +#else + y = _mm_loadu_si64(a); +#endif + y = _mm_aesenc_si128(x, y); _mm_storeu_si128((__m128i *)&a[0], y); return (a[0]); } diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c 2020-12-05 21:26:44.000000000 +0000 @@ -0,0 +1,10 @@ +#include + +int +main(void) +{ + unsigned int a, b, c, d; + + __cpuid_count(7, 0, a, b, c, d); + return ((int)a); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c 2021-12-09 22:15:31.000000000 +0000 @@ -5,5 +5,5 @@ { unsigned int x; - return(!_rdrand32_step(&x)); + return (!_rdrand32_step(&x)); } diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c 2020-12-05 21:26:44.000000000 +0000 @@ -1,14 +1,27 @@ #include #include -static char a[16]; +/* + * Use a separate function for this, because that means that the alignment of + * the _mm_loadu_si128() will move to function level, which may require + * -Wno-cast-align. + */ +static __m128i +load_128(const uint8_t * src) +{ + __m128i x; + + x = _mm_loadu_si128((const __m128i *)src); + return (x); +} int main(void) { __m128i x; + uint8_t a[16]; - x = _mm_loadu_si128((const __m128i *)&a[0]); + x = load_128(a); x = _mm_sha256msg1_epu32(x, x); _mm_storeu_si128((__m128i *)a, x); return (a[0]); diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,27 @@ +#include + +static char a[16]; + +/* + * Use a separate function for this, because that means that the alignment of + * the _mm_loadu_si128() will move to function level, which may require + * -Wno-cast-align. + */ +static __m128i +load_128(const char * src) +{ + __m128i x; + + x = _mm_loadu_si128((const __m128i *)src); + return (x); +} + +int +main(void) +{ + __m128i x; + + x = load_128(a); + _mm_storeu_si128((__m128i *)a, x); + return (a[0]); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c --- spiped-1.6.1/libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c 2021-01-11 23:41:03.000000000 +0000 @@ -3,12 +3,26 @@ static char a[16]; +/* + * Use a separate function for this, because that means that the alignment of + * the _mm_loadu_si128() will move to function level, which may require + * -Wno-cast-align. + */ +static __m128i +load_128(const char * src) +{ + __m128i x; + + x = _mm_loadu_si128((const __m128i *)src); + return (x); +} + int main(void) { __m128i x; - x = _mm_loadu_si128((__m128i *)a); + x = load_128(a); x = _mm_alignr_epi8(x, x, 8); _mm_storeu_si128((__m128i *)a, x); return (a[0]); diff -Nru spiped-1.6.1/libcperciva/cpusupport/cpusupport_arm_aes.c spiped-1.6.2/libcperciva/cpusupport/cpusupport_arm_aes.c --- spiped-1.6.1/libcperciva/cpusupport/cpusupport_arm_aes.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/cpusupport_arm_aes.c 2021-08-01 23:41:28.000000000 +0000 @@ -0,0 +1,56 @@ +#include "cpusupport.h" + +#ifdef CPUSUPPORT_HWCAP_GETAUXVAL +#include + +#if defined(__arm__) +/** + * Workaround for a glibc bug: contains a comment saying: + * The following must match the kernel's . + * However, it does not contain any of the HWCAP2_* entries from . + */ +#ifndef HWCAP2_AES +#include +#endif +#endif /* __arm__ */ +#endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ + +#if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) +#include +#endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ + +CPUSUPPORT_FEATURE_DECL(arm, aes) +{ + int supported = 0; + +#if defined(CPUSUPPORT_ARM_AES) +#if defined(CPUSUPPORT_HWCAP_GETAUXVAL) + unsigned long capabilities; + +#if defined(__aarch64__) + capabilities = getauxval(AT_HWCAP); + supported = (capabilities & HWCAP_AES) ? 1 : 0; +#elif defined(__arm__) + capabilities = getauxval(AT_HWCAP2); + supported = (capabilities & HWCAP2_AES) ? 1 : 0; +#endif +#endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ + +#if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) + unsigned long capabilities; + +#if defined(__aarch64__) + if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) + return (0); + supported = (capabilities & HWCAP_AES) ? 1 : 0; +#else + if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) + return (0); + supported = (capabilities & HWCAP2_AES) ? 1 : 0; +#endif +#endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ +#endif /* CPUSUPPORT_ARM_AES */ + + /* Return the supported status. */ + return (supported); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/cpusupport_arm_sha256.c spiped-1.6.2/libcperciva/cpusupport/cpusupport_arm_sha256.c --- spiped-1.6.1/libcperciva/cpusupport/cpusupport_arm_sha256.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/cpusupport_arm_sha256.c 2021-08-01 23:41:28.000000000 +0000 @@ -0,0 +1,56 @@ +#include "cpusupport.h" + +#ifdef CPUSUPPORT_HWCAP_GETAUXVAL +#include + +#if defined(__arm__) +/** + * Workaround for a glibc bug: contains a comment saying: + * The following must match the kernel's . + * However, it does not contain any of the HWCAP2_* entries from . + */ +#ifndef HWCAP2_CRC32 +#include +#endif +#endif /* __arm__ */ +#endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ + +#if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) +#include +#endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ + +CPUSUPPORT_FEATURE_DECL(arm, sha256) +{ + int supported = 0; + +#if defined(CPUSUPPORT_ARM_SHA256) +#if defined(CPUSUPPORT_HWCAP_GETAUXVAL) + unsigned long capabilities; + +#if defined(__aarch64__) + capabilities = getauxval(AT_HWCAP); + supported = (capabilities & HWCAP_SHA2) ? 1 : 0; +#elif defined(__arm__) + capabilities = getauxval(AT_HWCAP2); + supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; +#endif +#endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ + +#if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) + unsigned long capabilities; + +#if defined(__aarch64__) + if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) + return (0); + supported = (capabilities & HWCAP_SHA2) ? 1 : 0; +#else + if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) + return (0); + supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; +#endif +#endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ +#endif /* CPUSUPPORT_ARM_SHA256 */ + + /* Return the supported status. */ + return (supported); +} diff -Nru spiped-1.6.1/libcperciva/cpusupport/cpusupport.h spiped-1.6.2/libcperciva/cpusupport/cpusupport.h --- spiped-1.6.1/libcperciva/cpusupport/cpusupport.h 2019-11-06 00:04:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/cpusupport.h 2021-07-04 18:08:39.000000000 +0000 @@ -77,7 +77,7 @@ #define CPUSUPPORT_FEATURE(arch, feature, enabler) \ CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler) -/* +/** * CPUSUPPORT_FEATURE_DECL(arch, feature): * Macro which defines variables and provides a function declaration for * detecting the presence of "feature" on the "arch" architecture. The @@ -94,6 +94,26 @@ int \ cpusupport_ ## arch ## _ ## feature ## _detect_1(void) +/** + * CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, check): + * Check if we can enable ${success_value}, given the ${cpusupport_checks} and + * ${check}; if so, write to ${hwvar}. If the ${cpusupport_checks} pass but + * the ${check} is non-zero, produce a warning which includes a stringified + * ${success_value}, then fallthrough. + */ +#define CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, \ + check) do { \ + if ((cpusupport_checks)) { \ + if ((check) == 0) { \ + (hwvar) = (success_value); \ + return; \ + } else { \ + warn0("Disabling " #success_value \ + " due to failed self-test"); \ + } \ + } \ +} while (0) + /* * List of features. If a feature here is not enabled by the appropriate * CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the @@ -103,10 +123,13 @@ * compiled and linked in. */ CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI); -CPUSUPPORT_FEATURE(x86, crc32_64, X86_CRC32_64); CPUSUPPORT_FEATURE(x86, rdrand, X86_RDRAND); CPUSUPPORT_FEATURE(x86, shani, X86_SHANI); CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2); +CPUSUPPORT_FEATURE(x86, sse42, X86_SSE42); CPUSUPPORT_FEATURE(x86, ssse3, X86_SSSE3); +CPUSUPPORT_FEATURE(arm, aes, ARM_AES); +CPUSUPPORT_FEATURE(arm, crc32_64, ARM_CRC32_64); +CPUSUPPORT_FEATURE(arm, sha256, ARM_SHA256); #endif /* !_CPUSUPPORT_H_ */ diff -Nru spiped-1.6.1/libcperciva/cpusupport/cpusupport_x86_sse2.c spiped-1.6.2/libcperciva/cpusupport/cpusupport_x86_sse2.c --- spiped-1.6.1/libcperciva/cpusupport/cpusupport_x86_sse2.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/cpusupport/cpusupport_x86_sse2.c 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,30 @@ +#include "cpusupport.h" + +#ifdef CPUSUPPORT_X86_CPUID +#include + +#define CPUID_SSE2_BIT (1 << 26) +#endif + +CPUSUPPORT_FEATURE_DECL(x86, sse2) +{ +#ifdef CPUSUPPORT_X86_CPUID + unsigned int eax, ebx, ecx, edx; + + /* Check if CPUID supports the level we need. */ + if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) + goto unsupported; + if (eax < 1) + goto unsupported; + + /* Ask about CPU features. */ + if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) + goto unsupported; + + /* Return the relevant feature bit. */ + return ((edx & CPUID_SSE2_BIT) ? 1 : 0); + +unsupported: +#endif + return (0); +} diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni.c spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni.c --- spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni.c 2017-01-27 22:38:21.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni.c 2021-02-22 04:15:07.000000000 +0000 @@ -1,19 +1,23 @@ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_AESNI +/** + * CPUSUPPORT CFLAGS: X86_AESNI + */ #include #include #include +#include "align_ptr.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes_aesni.h" +#include "crypto_aes_aesni_m128i.h" /* Expanded-key structure. */ struct crypto_aes_key_aesni { - uint8_t rkeys_buf[15 * sizeof(__m128i) + (sizeof(__m128i) - 1)]; - __m128i * rkeys; + ALIGN_PTR_DECL(__m128i, rkeys, 15, sizeof(__m128i)); size_t nr; }; @@ -39,7 +43,7 @@ { /* The first round key is just the key. */ - /** + /*- * XXX Compiler breakage: * The intrinsic defined by Intel for _mm_loadu_si128 defines it as * taking a (const __m128i *) parameter. This forces us to write a @@ -93,7 +97,7 @@ { /* The first two round keys are just the key. */ - /** + /*- * XXX Compiler breakage: * The intrinsic defined by Intel for _mm_loadu_si128 defines it as * taking a (const __m128i *) parameter. This forces us to write a @@ -135,7 +139,7 @@ /** * crypto_aes_key_expand_aesni(key, len): * Expand the ${len}-byte AES key ${key} into a structure which can be passed - * to crypto_aes_encrypt_block_aesni. The length must be 16 or 32. This + * to crypto_aes_encrypt_block_aesni(). The length must be 16 or 32. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ @@ -143,16 +147,13 @@ crypto_aes_key_expand_aesni(const uint8_t * key, size_t len) { struct crypto_aes_key_aesni * kexp; - size_t rkey_offset; /* Allocate structure. */ if ((kexp = malloc(sizeof(struct crypto_aes_key_aesni))) == NULL) goto err0; /* Figure out where to put the round keys. */ - rkey_offset = (uintptr_t)(&kexp->rkeys_buf[0]) % sizeof(__m128i); - rkey_offset = (sizeof(__m128i) - rkey_offset) % sizeof(__m128i); - kexp->rkeys = (void *)&kexp->rkeys_buf[rkey_offset]; + ALIGN_PTR_INIT(kexp->rkeys, sizeof(__m128i)); /* Compute round keys. */ if (len == 16) { @@ -177,22 +178,20 @@ } /** - * crypto_aes_encrypt_block_aesni(in, out, key): - * Using the expanded AES key ${key}, encrypt the block ${in} and write the - * resulting ciphertext to ${out}. This implementation uses x86 AESNI - * instructions, and should only be used if CPUSUPPORT_X86_AESNI is defined - * and cpusupport_x86_aesni() returns nonzero. + * crypto_aes_encrypt_block_aesni_m128i(in, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and return the + * resulting ciphertext. This implementation uses x86 AESNI instructions, + * and should only be used if CPUSUPPORT_X86_AESNI is defined and + * cpusupport_x86_aesni() returns nonzero. */ -void -crypto_aes_encrypt_block_aesni(const uint8_t * in, uint8_t * out, - const void * key) +__m128i +crypto_aes_encrypt_block_aesni_m128i(__m128i in, const void * key) { const struct crypto_aes_key_aesni * _key = key; const __m128i * aes_key = _key->rkeys; - __m128i aes_state; + __m128i aes_state = in; size_t nr = _key->nr; - aes_state = _mm_loadu_si128((const __m128i *)in); aes_state = _mm_xor_si128(aes_state, aes_key[0]); aes_state = _mm_aesenc_si128(aes_state, aes_key[1]); aes_state = _mm_aesenc_si128(aes_state, aes_key[2]); @@ -206,14 +205,29 @@ if (nr > 10) { aes_state = _mm_aesenc_si128(aes_state, aes_key[10]); aes_state = _mm_aesenc_si128(aes_state, aes_key[11]); - - if (nr > 12) { - aes_state = _mm_aesenc_si128(aes_state, aes_key[12]); - aes_state = _mm_aesenc_si128(aes_state, aes_key[13]); - } + aes_state = _mm_aesenc_si128(aes_state, aes_key[12]); + aes_state = _mm_aesenc_si128(aes_state, aes_key[13]); } aes_state = _mm_aesenclast_si128(aes_state, aes_key[nr]); + return (aes_state); +} + +/** + * crypto_aes_encrypt_block_aesni(in, out, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and write the + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This + * implementation uses x86 AESNI instructions, and should only be used if + * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. + */ +void +crypto_aes_encrypt_block_aesni(const uint8_t in[16], uint8_t out[16], + const void * key) +{ + __m128i aes_state; + + aes_state = _mm_loadu_si128((const __m128i *)in); + aes_state = crypto_aes_encrypt_block_aesni_m128i(aes_state, key); _mm_storeu_si128((__m128i *)out, aes_state); } diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni.h spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni.h --- spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni.h 2020-09-02 04:32:10.000000000 +0000 @@ -7,7 +7,7 @@ /** * crypto_aes_key_expand_aesni(key, len): * Expand the ${len}-byte AES key ${key} into a structure which can be passed - * to crypto_aes_encrypt_block_aesni. The length must be 16 or 32. This + * to crypto_aes_encrypt_block_aesni(). The length must be 16 or 32. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ @@ -16,11 +16,12 @@ /** * crypto_aes_encrypt_block_aesni(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the - * resulting ciphertext to ${out}. This implementation uses x86 AESNI - * instructions, and should only be used if CPUSUPPORT_X86_AESNI is defined - * and cpusupport_x86_aesni() returns nonzero. + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This + * implementation uses x86 AESNI instructions, and should only be used if + * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ -void crypto_aes_encrypt_block_aesni(const uint8_t *, uint8_t *, const void *); +void crypto_aes_encrypt_block_aesni(const uint8_t[16], uint8_t[16], + const void *); /** * crypto_aes_key_free_aesni(key): diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni_m128i.h spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni_m128i.h --- spiped-1.6.1/libcperciva/crypto/crypto_aes_aesni_m128i.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_aesni_m128i.h 2021-01-11 23:41:03.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef _CRYPTO_AES_AESNI_M128I_H_ +#define _CRYPTO_AES_AESNI_M128I_H_ + +#include + +/** + * crypto_aes_encrypt_block_aesni_m128i(in, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and return the + * resulting ciphertext. This implementation uses x86 AESNI instructions, + * and should only be used if CPUSUPPORT_X86_AESNI is defined and + * cpusupport_x86_aesni() returns nonzero. + */ +__m128i crypto_aes_encrypt_block_aesni_m128i(__m128i, const void *); + +#endif /* !_CRYPTO_AES_AESNI_M128I_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_arm.c spiped-1.6.2/libcperciva/crypto/crypto_aes_arm.c --- spiped-1.6.1/libcperciva/crypto/crypto_aes_arm.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_arm.c 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,306 @@ +#include "cpusupport.h" +#ifdef CPUSUPPORT_ARM_AES +/** + * CPUSUPPORT CFLAGS: ARM_AES + */ + +#include +#include + +#ifdef __ARM_NEON +#include +#endif + +#include "align_ptr.h" +#include "insecure_memzero.h" +#include "warnp.h" + +#include "crypto_aes_arm.h" +#include "crypto_aes_arm_u8.h" + +/* Expanded-key structure. */ +struct crypto_aes_key_arm { + ALIGN_PTR_DECL(uint8x16_t, rkeys, 15, sizeof(uint8x16_t)); + size_t nr; +}; + +/** + * vdupq_laneq_u32_u8(a, lane): + * Set all 32-bit vector lanes to the same value. Exactly the same as + * vdupq_laneq_u32(), except that accepts (and returns) uint8x16_t. + */ +#define vdupq_laneq_u32_u8(a, lane) \ + vreinterpretq_u8_u32(vdupq_laneq_u32(vreinterpretq_u32_u8(a), lane)) + +/** + * vshlq_n_u128(a, n): + * Shift left (immediate), applied to the whole vector at once. + * + * Implementation note: this concatenates ${a} with a vector containing zeros, + * then extracts a new vector from the pair (similar to a sliding window). + * For example, vshlq_n_u128(a, 3) would do: + * 0xaaaaaaaaaaaaaaaa0000000000000000 + * return: ~~~~~~~~~~~~~~~~ + * This is the recommended method of shifting an entire vector with Neon + * intrinsics; all of the built-in shift instructions operate on multiple + * values (such as a pair of 64-bit values). + */ +#define vshlq_n_u128(a, n) vextq_u8(vdupq_n_u8(0), a, 16 - n) + +/** + * SubWord_duplicate(a): + * Perform the AES SubWord operation on the final 32-bit word (bits 96..127) + * of ${a}, and return a vector consisting of that value copied to all lanes. + */ +static inline uint8x16_t +SubWord_duplicate(uint8x16_t a) +{ + + /* + * Duplicate the final 32-bit word in all other lanes. By having four + * copies of the same uint32_t, we cause the ShiftRows in the upcoming + * AESE to have no effect. + */ + a = vdupq_laneq_u32_u8(a, 3); + + /* AESE does AddRoundKey (nop), ShiftRows (nop), and SubBytes. */ + a = vaeseq_u8(a, vdupq_n_u8(0)); + + return (a); +} + +/** + * SubWord_RotWord_XOR_duplicate(a, rcon): + * Perform the AES key schedule operations of SubWord, RotWord, and XOR with + * ${rcon}, acting on the final 32-bit word (bits 96..127) of ${a}, and return + * a vector consisting of that value copied to all lanes. + */ +static inline uint8x16_t +SubWord_RotWord_XOR_duplicate(uint8x16_t a, const uint32_t rcon) +{ + uint32_t x3; + + /* Perform SubWord on the final 32-bit word and copy it to all lanes. */ + a = SubWord_duplicate(a); + + /* We'll use non-neon for the rest. */ + x3 = vgetq_lane_u32(vreinterpretq_u32_u8(a), 0); + + /*- + * x3 gets RotWord. Note that + * RotWord(SubWord(a)) == SubWord(RotWord(a)) + */ + x3 = (x3 >> 8) | (x3 << (32 - 8)); + + /* x3 gets XOR'd with rcon. */ + x3 = x3 ^ rcon; + + /* Copy x3 to all 128 bits, and convert it to a uint8x16_t. */ + return (vreinterpretq_u8_u32(vdupq_n_u32(x3))); +} + +/* Compute an AES-128 round key. */ +#define MKRKEY128(rkeys, i, rcon) do { \ + uint8x16_t _s = rkeys[i - 1]; \ + uint8x16_t _t = rkeys[i - 1]; \ + _s = veorq_u8(_s, vshlq_n_u128(_s, 4)); \ + _s = veorq_u8(_s, vshlq_n_u128(_s, 8)); \ + _t = SubWord_RotWord_XOR_duplicate(_t, rcon); \ + rkeys[i] = veorq_u8(_s, _t); \ +} while (0) + +/** + * crypto_aes_key_expand_128_arm(key, rkeys): + * Expand the 128-bit AES key ${key} into the 11 round keys ${rkeys}. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +static void +crypto_aes_key_expand_128_arm(const uint8_t key[16], uint8x16_t rkeys[11]) +{ + + /* The first round key is just the key. */ + rkeys[0] = vld1q_u8(&key[0]); + + /* + * Each of the remaining round keys are computed from the preceding + * round key: rotword+subword+rcon (provided as aeskeygenassist) to + * compute the 'temp' value, then xor with 1, 2, 3, or all 4 of the + * 32-bit words from the preceding round key. + */ + MKRKEY128(rkeys, 1, 0x01); + MKRKEY128(rkeys, 2, 0x02); + MKRKEY128(rkeys, 3, 0x04); + MKRKEY128(rkeys, 4, 0x08); + MKRKEY128(rkeys, 5, 0x10); + MKRKEY128(rkeys, 6, 0x20); + MKRKEY128(rkeys, 7, 0x40); + MKRKEY128(rkeys, 8, 0x80); + MKRKEY128(rkeys, 9, 0x1b); + MKRKEY128(rkeys, 10, 0x36); +} + +/* Compute an AES-256 round key. */ +#define MKRKEY256(rkeys, i, rcon) do { \ + uint8x16_t _s = rkeys[i - 2]; \ + uint8x16_t _t = rkeys[i - 1]; \ + _s = veorq_u8(_s, vshlq_n_u128(_s, 4)); \ + _s = veorq_u8(_s, vshlq_n_u128(_s, 8)); \ + _t = (i % 2 == 1) ? \ + SubWord_duplicate(_t) : \ + SubWord_RotWord_XOR_duplicate(_t, rcon); \ + rkeys[i] = veorq_u8(_s, _t); \ +} while (0) + +/** + * crypto_aes_key_expand_256_arm(key, rkeys): + * Expand the 256-bit AES key ${key} into the 15 round keys ${rkeys}. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +static void +crypto_aes_key_expand_256_arm(const uint8_t key[32], uint8x16_t rkeys[15]) +{ + + /* The first two round keys are just the key. */ + rkeys[0] = vld1q_u8(&key[0]); + rkeys[1] = vld1q_u8(&key[16]); + + /* + * Each of the remaining round keys are computed from the preceding + * pair of keys. Even rounds use rotword+subword+rcon, while odd + * rounds just use subword. The rcon value used is irrelevant for odd + * rounds since we ignore the value which it feeds into. + */ + MKRKEY256(rkeys, 2, 0x01); + MKRKEY256(rkeys, 3, 0x00); + MKRKEY256(rkeys, 4, 0x02); + MKRKEY256(rkeys, 5, 0x00); + MKRKEY256(rkeys, 6, 0x04); + MKRKEY256(rkeys, 7, 0x00); + MKRKEY256(rkeys, 8, 0x08); + MKRKEY256(rkeys, 9, 0x00); + MKRKEY256(rkeys, 10, 0x10); + MKRKEY256(rkeys, 11, 0x00); + MKRKEY256(rkeys, 12, 0x20); + MKRKEY256(rkeys, 13, 0x00); + MKRKEY256(rkeys, 14, 0x40); +} + +/** + * crypto_aes_key_expand_arm(key, len): + * Expand the ${len}-byte AES key ${key} into a structure which can be passed + * to crypto_aes_encrypt_block_arm(). The length must be 16 or 32. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +void * +crypto_aes_key_expand_arm(const uint8_t * key, size_t len) +{ + struct crypto_aes_key_arm * kexp; + + /* Allocate structure. */ + if ((kexp = malloc(sizeof(struct crypto_aes_key_arm))) == NULL) + goto err0; + + /* Figure out where to put the round keys. */ + ALIGN_PTR_INIT(kexp->rkeys, sizeof(uint8x16_t)); + + /* Compute round keys. */ + if (len == 16) { + kexp->nr = 10; + crypto_aes_key_expand_128_arm(key, kexp->rkeys); + } else if (len == 32) { + kexp->nr = 14; + crypto_aes_key_expand_256_arm(key, kexp->rkeys); + } else { + warn0("Unsupported AES key length: %zu bytes", len); + goto err1; + } + + /* Success! */ + return (kexp); + +err1: + free(kexp); +err0: + /* Failure! */ + return (NULL); +} + +/** + * crypto_aes_encrypt_block_arm_u8(in, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and return the + * resulting ciphertext. This implementation uses ARM AES instructions, + * and should only be used if CPUSUPPORT_ARM_AES is defined and + * cpusupport_arm_aes() returns nonzero. + */ +uint8x16_t +crypto_aes_encrypt_block_arm_u8(uint8x16_t in, const void * key) +{ + const struct crypto_aes_key_arm * _key = key; + const uint8x16_t * aes_key = _key->rkeys; + uint8x16_t aes_state = in; + size_t nr = _key->nr; + + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[0])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[1])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[2])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[3])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[4])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[5])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[6])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[7])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[8])); + if (nr > 10) { + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[9])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[10])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[11])); + aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[12])); + } + + /* Last round. */ + aes_state = vaeseq_u8(aes_state, aes_key[nr - 1]); + aes_state = veorq_u8(aes_state, aes_key[nr]); + + return (aes_state); +} + +/** + * crypto_aes_encrypt_block_arm(in, out, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and write the + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +void +crypto_aes_encrypt_block_arm(const uint8_t in[16], uint8_t out[16], + const void * key) +{ + uint8x16_t aes_state; + + aes_state = vld1q_u8(in); + aes_state = crypto_aes_encrypt_block_arm_u8(aes_state, key); + vst1q_u8(out, aes_state); +} + +/** + * crypto_aes_key_free_arm(key): + * Free the expanded AES key ${key}. + */ +void +crypto_aes_key_free_arm(void * key) +{ + + /* Behave consistently with free(NULL). */ + if (key == NULL) + return; + + /* Attempt to zero the expanded key. */ + insecure_memzero(key, sizeof(struct crypto_aes_key_arm)); + + /* Free the key. */ + free(key); +} + +#endif /* CPUSUPPORT_ARM_AES */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_arm.h spiped-1.6.2/libcperciva/crypto/crypto_aes_arm.h --- spiped-1.6.1/libcperciva/crypto/crypto_aes_arm.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_arm.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef _CRYPTO_AES_ARM_H_ +#define _CRYPTO_AES_ARM_H_ + +#include +#include + +/** + * crypto_aes_key_expand_arm(key, len): + * Expand the ${len}-byte AES key ${key} into a structure which can be passed + * to crypto_aes_encrypt_block_arm(). The length must be 16 or 32. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +void * crypto_aes_key_expand_arm(const uint8_t *, size_t); + +/** + * crypto_aes_encrypt_block_arm(in, out, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and write the + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This + * implementation uses ARM AES instructions, and should only be used if + * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. + */ +void crypto_aes_encrypt_block_arm(const uint8_t[16], uint8_t[16], + const void *); + +/** + * crypto_aes_key_free_arm(key): + * Free the expanded AES key ${key}. + */ +void crypto_aes_key_free_arm(void *); + +#endif /* !_CRYPTO_AES_ARM_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes_arm_u8.h spiped-1.6.2/libcperciva/crypto/crypto_aes_arm_u8.h --- spiped-1.6.1/libcperciva/crypto/crypto_aes_arm_u8.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes_arm_u8.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef _CRYPTO_AES_ARM_U8_H_ +#define _CRYPTO_AES_ARM_U8_H_ + +#ifdef __ARM_NEON +#include +#endif + +/** + * crypto_aes_encrypt_block_arm_u8(in, key): + * Using the expanded AES key ${key}, encrypt the block ${in} and return the + * resulting ciphertext. This implementation uses ARM AES instructions, + * and should only be used if CPUSUPPORT_ARM_AES is defined and + * cpusupport_arm_aes() returns nonzero. + */ +uint8x16_t crypto_aes_encrypt_block_arm_u8(uint8x16_t, const void *); + +#endif /* !_CRYPTO_AES_ARM_U8_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes.c spiped-1.6.2/libcperciva/crypto/crypto_aes.c --- spiped-1.6.1/libcperciva/crypto/crypto_aes.c 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes.c 2021-07-04 18:08:39.000000000 +0000 @@ -7,11 +7,27 @@ #include "cpusupport.h" #include "crypto_aes_aesni.h" +#include "crypto_aes_arm.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes.h" +#if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES) +#define HWACCEL + +static enum { + HW_SOFTWARE = 0, +#if defined(CPUSUPPORT_X86_AESNI) + HW_X86_AESNI, +#endif +#if defined(CPUSUPPORT_ARM_AES) + HW_ARM_AES, +#endif + HW_UNSET +} hwaccel = HW_UNSET; +#endif + /** * This represents either an AES_KEY or a struct crypto_aes_key_aesni; we * know which it is based on whether we're using AESNI code or not. As such, @@ -20,81 +36,188 @@ */ struct crypto_aes_key; -#ifdef CPUSUPPORT_X86_AESNI -/* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */ +#ifdef HWACCEL +static struct aes_test { + const uint8_t key[32]; + const size_t len; + const uint8_t ptext[16]; + const uint8_t ctext[16]; +} testcases[] = { { + /* NIST FIPS 179, Appendix C - Example Vectors, AES-128, p. 35. */ + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, + .len = 16, + .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .ctext = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + /* NIST FIPS 179, Appendix C - Example Vectors, AES-256, p. 42. */ + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, }, + .len = 32, + .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .ctext = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } +}; + +/* Test a function against test vectors. */ static int -aesnitest(uint8_t ptext[16], uint8_t * key, size_t len) +functest(int(* func)(const uint8_t *, size_t, const uint8_t[16], uint8_t[16])) { - AES_KEY kexp_openssl; - void * kexp_aesni; - uint8_t ctext_openssl[16]; - uint8_t ctext_aesni[16]; + struct aes_test * knowngood; + uint8_t ctext[16]; + size_t i; - /* Sanity-check. */ - assert((len == 16) || (len == 32)); + for (i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++) { + knowngood = &testcases[i]; - /* Expand the key. */ - AES_set_encrypt_key(key, (int)(len * 8), &kexp_openssl); - if ((kexp_aesni = crypto_aes_key_expand_aesni(key, len)) == NULL) + /* Sanity-check. */ + assert((knowngood->len == 16) || (knowngood->len == 32)); + + /* Expand the key and encrypt with the provided function. */ + if (func(knowngood->key, knowngood->len, knowngood->ptext, + ctext)) + goto err0; + + /* Does the output match the known good value? */ + if (memcmp(knowngood->ctext, ctext, 16)) + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +#if defined(CPUSUPPORT_X86_AESNI) +static int +x86_aesni_oneshot(const uint8_t * key, size_t len, const uint8_t ptext[16], + uint8_t ctext[16]) +{ + void * kexp_hw; + + /* Expand the key and encrypt with hardware intrinsics. */ + if ((kexp_hw = crypto_aes_key_expand_aesni(key, len)) == NULL) goto err0; + crypto_aes_encrypt_block_aesni(ptext, ctext, kexp_hw); + crypto_aes_key_free_aesni(kexp_hw); - /* Encrypt the block. */ - AES_encrypt(ptext, ctext_openssl, &kexp_openssl); - crypto_aes_encrypt_block_aesni(ptext, ctext_aesni, kexp_aesni); + /* Success! */ + return (0); - /* Free the AESNI expanded key. */ - crypto_aes_key_free_aesni(kexp_aesni); +err0: + /* Failure! */ + return (-1); +} +#endif - /* Do the outputs match? */ - return (memcmp(ctext_openssl, ctext_aesni, 16)); +#if defined(CPUSUPPORT_ARM_AES) +static int +arm_aes_oneshot(const uint8_t * key, size_t len, const uint8_t ptext[16], + uint8_t * ctext) +{ + void * kexp_hw; + + if ((kexp_hw = crypto_aes_key_expand_arm(key, len)) == NULL) + goto err0; + crypto_aes_encrypt_block_arm(ptext, ctext, kexp_hw); + crypto_aes_key_free_arm(kexp_hw); + + /* Success! */ + return (0); err0: /* Failure! */ return (-1); } +#endif -/* Should we use AESNI? */ static int -useaesni(void) +openssl_oneshot(const uint8_t * key, size_t len, const uint8_t ptext[16], + uint8_t * ctext) { - static int aesnigood = -1; - uint8_t key[32]; - uint8_t ptext[16]; - size_t i; + AES_KEY kexp; + + /* Expand the key, encrypt, and clean up. */ + AES_set_encrypt_key(key, (int)(len * 8), &kexp); + AES_encrypt(ptext, ctext, &kexp); + insecure_memzero(&kexp, sizeof(AES_KEY)); + + return (0); +} + +/* Which type of hardware acceleration should we use, if any? */ +static void +hwaccel_init(void) +{ + + /* If we've already set hwaccel, we're finished. */ + if (hwaccel != HW_UNSET) + return; + + /* Default to software. */ + hwaccel = HW_SOFTWARE; - /* If we haven't decided which code to use yet, decide now. */ - while (aesnigood == -1) { - /* Default to OpenSSL. */ - aesnigood = 0; - - /* If the CPU doesn't claim to support AESNI, stop here. */ - if (!cpusupport_x86_aesni()) - break; - - /* Test cases: key is 0x00010203..., ptext is 0x00112233... */ - for (i = 0; i < 16; i++) - ptext[i] = (0x11 * i) & 0xff; - for (i = 0; i < 32; i++) - key[i] = i & 0xff; - - /* Test that AESNI and OpenSSL produce the same results. */ - if (aesnitest(ptext, key, 16) || aesnitest(ptext, key, 32)) { - warn0("Disabling AESNI due to failed self-test"); - break; - } +#if defined(CPUSUPPORT_X86_AESNI) + CPUSUPPORT_VALIDATE(hwaccel, HW_X86_AESNI, cpusupport_x86_aesni(), + functest(x86_aesni_oneshot)); +#endif +#if defined(CPUSUPPORT_ARM_AES) + CPUSUPPORT_VALIDATE(hwaccel, HW_ARM_AES, cpusupport_arm_aes(), + functest(arm_aes_oneshot)); +#endif - /* AESNI works; use it. */ - aesnigood = 1; + /* + * If we're here, we're not using any intrinsics. Test OpenSSL; if + * there's an error, print a warning and abort. + */ + if (functest(openssl_oneshot)) { + warn0("OpenSSL gives incorrect AES values."); + abort(); } +} +#endif /* HWACCEL */ + +/** + * crypto_aes_can_use_intrinsics(void): + * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI + * operations are available, 2 if ARM-AES operations are available, or 0 if + * none are available. + */ +int +crypto_aes_can_use_intrinsics(void) +{ + +#ifdef HWACCEL + /* Ensure that we've chosen the type of hardware acceleration. */ + hwaccel_init(); + +#if defined(CPUSUPPORT_X86_AESNI) + if (hwaccel == HW_X86_AESNI) + return (1); +#endif +#if defined(CPUSUPPORT_ARM_AES) + if (hwaccel == HW_ARM_AES) + return (2); +#endif +#endif /* HWACCEL */ - return (aesnigood); + /* Software only. */ + return (0); } -#endif /* CPUSUPPORT_X86_AESNI */ /** * crypto_aes_key_expand(key, len): * Expand the ${len}-byte AES key ${key} into a structure which can be passed - * to crypto_aes_encrypt_block. The length must be 16 or 32. + * to crypto_aes_encrypt_block(). The length must be 16 or 32. */ struct crypto_aes_key * crypto_aes_key_expand(const uint8_t * key, size_t len) @@ -104,11 +227,19 @@ /* Sanity-check. */ assert((len == 16) || (len == 32)); +#ifdef HWACCEL + /* Ensure that we've chosen the type of hardware acceleration. */ + hwaccel_init(); + #ifdef CPUSUPPORT_X86_AESNI - /* Use AESNI if we can. */ - if (useaesni()) + if (hwaccel == HW_X86_AESNI) return (crypto_aes_key_expand_aesni(key, len)); #endif +#ifdef CPUSUPPORT_ARM_AES + if (hwaccel == HW_ARM_AES) + return (crypto_aes_key_expand_arm(key, len)); +#endif +#endif /* HWACCEL */ /* Allocate structure. */ if ((kexp = malloc(sizeof(AES_KEY))) == NULL) @@ -128,19 +259,27 @@ /** * crypto_aes_encrypt_block(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the - * resulting ciphertext to ${out}. + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. */ void -crypto_aes_encrypt_block(const uint8_t * in, uint8_t * out, +crypto_aes_encrypt_block(const uint8_t in[16], uint8_t out[16], const struct crypto_aes_key * key) { +#ifdef HWACCEL #ifdef CPUSUPPORT_X86_AESNI - if (useaesni()) { + if (hwaccel == HW_X86_AESNI) { crypto_aes_encrypt_block_aesni(in, out, (const void *)key); return; } #endif +#ifdef CPUSUPPORT_ARM_AES + if (hwaccel == HW_ARM_AES) { + crypto_aes_encrypt_block_arm(in, out, (const void *)key); + return; + } +#endif +#endif /* HWACCEL */ /* Get AES to do the work. */ AES_encrypt(in, out, (const void *)key); @@ -154,12 +293,20 @@ crypto_aes_key_free(struct crypto_aes_key * key) { +#ifdef HWACCEL #ifdef CPUSUPPORT_X86_AESNI - if (useaesni()) { + if (hwaccel == HW_X86_AESNI) { crypto_aes_key_free_aesni((void *)key); return; } #endif +#ifdef CPUSUPPORT_ARM_AES + if (hwaccel == HW_ARM_AES) { + crypto_aes_key_free_arm((void *)key); + return; + } +#endif +#endif /* HWACCEL */ /* Behave consistently with free(NULL). */ if (key == NULL) diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr_aesni.c spiped-1.6.2/libcperciva/crypto/crypto_aesctr_aesni.c --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr_aesni.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr_aesni.c 2021-03-22 17:57:56.000000000 +0000 @@ -0,0 +1,136 @@ +#include "cpusupport.h" +#ifdef CPUSUPPORT_X86_AESNI +/** + * CPUSUPPORT CFLAGS: X86_AESNI + */ + +#include +#include +#include + +#include + +#include "crypto_aes.h" +#include "crypto_aes_aesni_m128i.h" +#include "sysendian.h" + +#include "crypto_aesctr_aesni.h" + +/** + * In order to optimize AES-CTR, it is desirable to separate out the handling + * of individual bytes of data vs. the handling of complete (16 byte) blocks. + * The handling of blocks in turn can be optimized further using CPU + * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code + * remains the same across platforms it should be inlined into the same (CPU + * feature specific) routines for performance reasons. + * + * In order to allow those generic functions to be inlined into multiple + * functions in separate translation units, we place them into a "shared" C + * file which is included in each of the platform-specific variants. + */ +#include "crypto_aesctr_shared.c" + +#ifdef BROKEN_MM_LOADU_SI64 +#warning Working around compiler bug: _mm_loadu_si64 is missing +#warning Updating to a newer compiler may improve performance +#endif + +/** + * load_si64(mem): + * Load an unaligned 64-bit integer from memory into the lowest 64 bits of the + * returned value. The contents of the upper 64 bits is not defined. + */ +static inline __m128i +load_si64(const void * mem) +{ + +#ifdef BROKEN_MM_LOADU_SI64 + return (_mm_castpd_si128(_mm_load_sd(mem))); +#else + return (_mm_loadu_si64(mem)); +#endif +} + +/* Process multiple whole blocks by generating & using a cipherblock. */ +static void +crypto_aesctr_aesni_stream_wholeblocks(struct crypto_aesctr * stream, + const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) +{ + __m128i bufsse; + __m128i inbufsse; + __m128i nonce_be; + uint8_t block_counter_be_arr[8]; + uint64_t block_counter; + size_t num_blocks; + size_t i; + + /* Load local variables from stream. */ + nonce_be = load_si64(stream->pblk); + block_counter = stream->bytectr / 16; + + /* How many blocks should we process? */ + num_blocks = (*buflen) / 16; + + /* + * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the + * compiler knows that we will execute the loop at least once. + */ + i = num_blocks; + do { + /* Prepare counter. */ + be64enc(block_counter_be_arr, block_counter); + + /* Encrypt the cipherblock. */ + bufsse = load_si64(block_counter_be_arr); + bufsse = _mm_unpacklo_epi64(nonce_be, bufsse); + bufsse = crypto_aes_encrypt_block_aesni_m128i(bufsse, + stream->key); + + /* Encrypt the byte(s). */ + inbufsse = _mm_loadu_si128((const __m128i *)(*inbuf)); + bufsse = _mm_xor_si128(inbufsse, bufsse); + _mm_storeu_si128((__m128i *)(*outbuf), bufsse); + + /* Update the positions. */ + block_counter++; + *inbuf += 16; + *outbuf += 16; + + /* Update the counter. */ + i--; + } while (i > 0); + + /* Update the overall buffer length. */ + *buflen -= 16 * num_blocks; + + /* Update variables in stream. */ + memcpy(stream->pblk + 8, block_counter_be_arr, 8); + stream->bytectr += 16 * num_blocks; +} + +/** + * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): + * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor + * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the + * buffers ${inbuf} and ${outbuf} overlap, they must be identical. + */ +void +crypto_aesctr_aesni_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, + uint8_t * outbuf, size_t buflen) +{ + + /* Process any bytes before we can process a whole block. */ + if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, + &buflen)) + return; + + /* Process whole blocks of 16 bytes. */ + if (buflen >= 16) + crypto_aesctr_aesni_stream_wholeblocks(stream, &inbuf, + &outbuf, &buflen); + + /* Process any final bytes after finishing all whole blocks. */ + crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); +} + +#endif /* CPUSUPPORT_X86_AESNI */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr_aesni.h spiped-1.6.2/libcperciva/crypto/crypto_aesctr_aesni.h --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr_aesni.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr_aesni.h 2021-02-22 04:15:07.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef _CRYPTO_AESCTR_AESNI_H_ +#define _CRYPTO_AESCTR_AESNI_H_ + +#include +#include + +/* Opaque type. */ +struct crypto_aesctr; + +/** + * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): + * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor + * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the + * buffers ${inbuf} and ${outbuf} overlap, they must be identical. + */ +void crypto_aesctr_aesni_stream(struct crypto_aesctr *, const uint8_t *, + uint8_t *, size_t); + +#endif /* !_CRYPTO_AESCTR_AESNI_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr_arm.c spiped-1.6.2/libcperciva/crypto/crypto_aesctr_arm.c --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr_arm.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr_arm.c 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,117 @@ +#include "cpusupport.h" +#ifdef CPUSUPPORT_ARM_AES +/** + * CPUSUPPORT CFLAGS: ARM_AES + */ + +#include +#include +#include + +#ifdef __ARM_NEON +#include +#endif + +#include "crypto_aes.h" +#include "crypto_aes_arm_u8.h" +#include "sysendian.h" + +#include "crypto_aesctr_arm.h" + +/** + * In order to optimize AES-CTR, it is desirable to separate out the handling + * of individual bytes of data vs. the handling of complete (16 byte) blocks. + * The handling of blocks in turn can be optimized further using CPU + * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code + * remains the same across platforms it should be inlined into the same (CPU + * feature specific) routines for performance reasons. + * + * In order to allow those generic functions to be inlined into multiple + * functions in separate translation units, we place them into a "shared" C + * file which is included in each of the platform-specific variants. + */ +#include "crypto_aesctr_shared.c" + +/* Process multiple whole blocks by generating & using a cipherblock. */ +static void +crypto_aesctr_arm_stream_wholeblocks(struct crypto_aesctr * stream, + const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) +{ + uint8x16_t bufarm; + uint8x16_t inbufarm; + uint8x8_t nonce_be; + uint8x8_t block_counter_be; + uint8_t block_counter_be_arr[8]; + uint64_t block_counter; + size_t num_blocks; + size_t i; + + /* Load local variables from stream. */ + nonce_be = vld1_u8(stream->pblk); + block_counter = stream->bytectr / 16; + + /* How many blocks should we process? */ + num_blocks = (*buflen) / 16; + + /* + * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the + * compiler knows that we will execute the loop at least once. + */ + i = num_blocks; + do { + /* Prepare counter. */ + be64enc(block_counter_be_arr, block_counter); + + /* Encrypt the cipherblock. */ + block_counter_be = vld1_u8(block_counter_be_arr); + bufarm = vcombine_u8(nonce_be, block_counter_be); + bufarm = crypto_aes_encrypt_block_arm_u8(bufarm, stream->key); + + /* Encrypt the byte(s). */ + inbufarm = vld1q_u8(*inbuf); + bufarm = veorq_u8(inbufarm, bufarm); + vst1q_u8(*outbuf, bufarm); + + /* Update the positions. */ + block_counter++; + *inbuf += 16; + *outbuf += 16; + + /* Update the counter. */ + i--; + } while (i > 0); + + /* Update the overall buffer length. */ + *buflen -= 16 * num_blocks; + + /* Update variables in stream. */ + memcpy(stream->pblk + 8, block_counter_be_arr, 8); + stream->bytectr += 16 * num_blocks; +} + +/** + * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): + * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor + * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the + * buffers ${inbuf} and ${outbuf} overlap, they must be identical. + */ +void +crypto_aesctr_arm_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, + uint8_t * outbuf, size_t buflen) +{ + + /* Process any bytes before we can process a whole block. */ + if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, + &buflen)) + return; + + /* Process whole blocks of 16 bytes. */ + if (buflen >= 16) + crypto_aesctr_arm_stream_wholeblocks(stream, &inbuf, &outbuf, + &buflen); + + /* Process any final bytes after finishing all whole blocks. */ + crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); +} + +#endif /* CPUSUPPORT_ARM_AES */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr_arm.h spiped-1.6.2/libcperciva/crypto/crypto_aesctr_arm.h --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr_arm.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr_arm.h 2021-07-04 18:08:39.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef _CRYPTO_AESCTR_ARM_H_ +#define _CRYPTO_AESCTR_ARM_H_ + +#include +#include + +/* Opaque type. */ +struct crypto_aesctr; + +/** + * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): + * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor + * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the + * buffers ${inbuf} and ${outbuf} overlap, they must be identical. + */ +void crypto_aesctr_arm_stream(struct crypto_aesctr *, const uint8_t *, + uint8_t *, size_t); + +#endif /* !_CRYPTO_AESCTR_ARM_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr.c spiped-1.6.2/libcperciva/crypto/crypto_aesctr.c --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr.c 2021-07-04 18:08:39.000000000 +0000 @@ -1,38 +1,154 @@ +#include #include #include +#include "cpusupport.h" #include "crypto_aes.h" +#include "crypto_aesctr_aesni.h" +#include "crypto_aesctr_arm.h" #include "insecure_memzero.h" #include "sysendian.h" #include "crypto_aesctr.h" -struct crypto_aesctr { - const struct crypto_aes_key * key; - uint64_t nonce; - uint64_t bytectr; - uint8_t buf[16]; -}; +/** + * In order to optimize AES-CTR, it is desirable to separate out the handling + * of individual bytes of data vs. the handling of complete (16 byte) blocks. + * The handling of blocks in turn can be optimized further using CPU + * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code + * remains the same across platforms it should be inlined into the same (CPU + * feature specific) routines for performance reasons. + * + * In order to allow those generic functions to be inlined into multiple + * functions in separate translation units, we place them into a "shared" C + * file which is included in each of the platform-specific variants. + */ +#include "crypto_aesctr_shared.c" + +#if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES) +#define HWACCEL + +static enum { + HW_SOFTWARE = 0, +#if defined(CPUSUPPORT_X86_AESNI) + HW_X86_AESNI, +#endif +#if defined(CPUSUPPORT_ARM_AES) + HW_ARM_AES, +#endif + HW_UNSET +} hwaccel = HW_UNSET; +#endif + +#ifdef HWACCEL +/* Which type of hardware acceleration should we use, if any? */ +static void +hwaccel_init(void) +{ + + /* If we've already set hwaccel, we're finished. */ + if (hwaccel != HW_UNSET) + return; + + /* Default to software. */ + hwaccel = HW_SOFTWARE; + + /* Can we use AESNI? */ + switch (crypto_aes_can_use_intrinsics()) { +#ifdef CPUSUPPORT_X86_AESNI + case 1: + hwaccel = HW_X86_AESNI; + break; +#endif +#ifdef CPUSUPPORT_ARM_AES + case 2: + hwaccel = HW_ARM_AES; + break; +#endif + case 0: + break; + default: + /* Should never happen. */ + assert(0); + } +} +#endif /* HWACCEL */ + +/** + * crypto_aesctr_alloc(void): + * Allocate an object for performing AES in CTR code. This must be followed + * by calling _init2(). + */ +struct crypto_aesctr * +crypto_aesctr_alloc(void) +{ + struct crypto_aesctr * stream; + + /* Allocate memory. */ + if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) + goto err0; + + /* Success! */ + return (stream); + +err0: + /* Failure! */ + return (NULL); +} + +/** + * crypto_aesctr_init2(stream, key, nonce): + * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} + * is NULL, retain the previous AES key. + */ +void +crypto_aesctr_init2(struct crypto_aesctr * stream, + const struct crypto_aes_key * key, uint64_t nonce) +{ + + /* If the key is NULL, retain the previous AES key. */ + if (key != NULL) + stream->key = key; + + /* Set nonce as provided and reset bytectr. */ + be64enc(stream->pblk, nonce); + stream->bytectr = 0; + + /* + * Set the counter such that the least significant byte will wrap once + * incremented. + */ + stream->pblk[15] = 0xff; + +#ifdef HWACCEL + hwaccel_init(); +#endif + + /* Sanity check. */ + assert(stream->key != NULL); +} /** * crypto_aesctr_init(key, nonce): * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided - * expanded key and nonce. The key provided must remain valid for the - * lifetime of the stream. + * expanded ${key} and ${nonce}. The key provided must remain valid for the + * lifetime of the stream. This is the same as calling _alloc() followed by + * _init2(). */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce) { struct crypto_aesctr * stream; + /* Sanity check. */ + assert(key != NULL); + /* Allocate memory. */ - if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) + if ((stream = crypto_aesctr_alloc()) == NULL) goto err0; /* Initialize values. */ - stream->key = key; - stream->nonce = nonce; - stream->bytectr = 0; + crypto_aesctr_init2(stream, key, nonce); /* Success! */ return (stream); @@ -52,28 +168,39 @@ crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { - uint8_t pblk[16]; - size_t pos; - int bytemod; - - for (pos = 0; pos < buflen; pos++) { - /* How far through the buffer are we? */ - bytemod = stream->bytectr % 16; - - /* Generate a block of cipherstream if needed. */ - if (bytemod == 0) { - be64enc(pblk, stream->nonce); - be64enc(pblk + 8, stream->bytectr / 16); - crypto_aes_encrypt_block(pblk, stream->buf, - stream->key); - } - /* Encrypt a byte. */ - outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod]; +#if defined(HWACCEL) +#if defined(CPUSUPPORT_X86_AESNI) + if ((buflen >= 16) && (hwaccel == HW_X86_AESNI)) { + crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen); + return; + } +#endif +#if defined(CPUSUPPORT_ARM_AES) + if ((buflen >= 16) && (hwaccel == HW_ARM_AES)) { + crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen); + return; + } +#endif +#endif /* HWACCEL */ + + /* Process any bytes before we can process a whole block. */ + if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, + &buflen)) + return; - /* Move to the next byte of cipherstream. */ - stream->bytectr += 1; + /* Process whole blocks of 16 bytes. */ + while (buflen >= 16) { + /* Generate a block of cipherstream. */ + crypto_aesctr_stream_cipherblock_generate(stream); + + /* Encrypt the bytes and update the positions. */ + crypto_aesctr_stream_cipherblock_use(stream, &inbuf, &outbuf, + &buflen, 16, 0); } + + /* Process any final bytes after finishing all whole blocks. */ + crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); } /** @@ -106,10 +233,11 @@ struct crypto_aesctr stream_rec; struct crypto_aesctr * stream = &stream_rec; + /* Sanity check. */ + assert(key != NULL); + /* Initialize values. */ - stream->key = key; - stream->nonce = nonce; - stream->bytectr = 0; + crypto_aesctr_init2(stream, key, nonce); /* Perform the encryption. */ crypto_aesctr_stream(stream, inbuf, outbuf, buflen); diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr.h spiped-1.6.2/libcperciva/crypto/crypto_aesctr.h --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr.h 2021-01-11 23:41:03.000000000 +0000 @@ -11,13 +11,29 @@ /** * crypto_aesctr_init(key, nonce): * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided - * expanded key and nonce. The key provided must remain valid for the - * lifetime of the stream. + * expanded ${key} and ${nonce}. The key provided must remain valid for the + * lifetime of the stream. This is the same as calling _alloc() followed by + * _init2(). */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key *, uint64_t); /** + * crypto_aesctr_alloc(void): + * Allocate an object for performing AES in CTR code. This must be followed + * by calling _init2(). + */ +struct crypto_aesctr * crypto_aesctr_alloc(void); + +/** + * crypto_aesctr_init2(stream, key, nonce): + * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} + * is NULL, retain the previous AES key. + */ +void crypto_aesctr_init2(struct crypto_aesctr *, const struct crypto_aes_key *, + uint64_t); + +/** * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aesctr_shared.c spiped-1.6.2/libcperciva/crypto/crypto_aesctr_shared.c --- spiped-1.6.1/libcperciva/crypto/crypto_aesctr_shared.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aesctr_shared.c 2021-01-11 23:41:03.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * This code is shared between crypto_aesctr*.c files, and should not be + * compiled as a separate translation unit. For details, see the comments in + * those files. + */ + +/* AES-CTR state. */ +struct crypto_aesctr { + const struct crypto_aes_key * key; + uint64_t bytectr; + uint8_t buf[16]; + uint8_t pblk[16]; +}; + +/* Generate a block of cipherstream. */ +static inline void +crypto_aesctr_stream_cipherblock_generate(struct crypto_aesctr * stream) +{ + + /* Sanity check. */ + assert(stream->bytectr % 16 == 0); + + /* Prepare counter. */ + stream->pblk[15]++; + if (stream->pblk[15] == 0) { + /* + * If incrementing the least significant byte resulted in it + * wrapping, re-encode the complete 64-bit value. + */ + be64enc(stream->pblk + 8, stream->bytectr / 16); + } + + /* Encrypt the cipherblock. */ + crypto_aes_encrypt_block(stream->pblk, stream->buf, stream->key); +} + +/* Encrypt ${nbytes} bytes, then update ${inbuf}, ${outbuf}, and ${buflen}. */ +static inline void +crypto_aesctr_stream_cipherblock_use(struct crypto_aesctr * stream, + const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen, size_t nbytes, + size_t bytemod) +{ + size_t i; + + /* Encrypt the byte(s). */ + for (i = 0; i < nbytes; i++) + (*outbuf)[i] = (*inbuf)[i] ^ stream->buf[bytemod + i]; + + /* Move to the next byte(s) of cipherstream. */ + stream->bytectr += nbytes; + + /* Update the positions. */ + *inbuf += nbytes; + *outbuf += nbytes; + *buflen -= nbytes; +} + +/* + * Process any bytes before we can process a whole block. Return 1 if there + * are no bytes left to process after calling this function. + */ +static inline int +crypto_aesctr_stream_pre_wholeblock(struct crypto_aesctr * stream, + const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) +{ + size_t bytemod; + + /* Do we have any bytes left in the current cipherblock? */ + bytemod = stream->bytectr % 16; + if (bytemod != 0) { + /* Do we have enough to complete the request? */ + if (bytemod + *buflen_p <= 16) { + /* Process only buflen bytes, then return. */ + crypto_aesctr_stream_cipherblock_use(stream, inbuf, + outbuf, buflen_p, *buflen_p, bytemod); + return (1); + } + + /* Encrypt the byte(s) and update the positions. */ + crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, + buflen_p, 16 - bytemod, bytemod); + } + + return (0); +} + +/* Process any final bytes after finishing all whole blocks. */ +static inline void +crypto_aesctr_stream_post_wholeblock(struct crypto_aesctr * stream, + const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) +{ + + /* Process any final bytes; we need a new cipherblock. */ + if (*buflen_p > 0) { + /* Generate a block of cipherstream. */ + crypto_aesctr_stream_cipherblock_generate(stream); + + /* Encrypt the byte(s) and update the positions. */ + crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, + buflen_p, *buflen_p, 0); + } +} diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_aes.h spiped-1.6.2/libcperciva/crypto/crypto_aes.h --- spiped-1.6.1/libcperciva/crypto/crypto_aes.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_aes.h 2021-07-04 18:08:39.000000000 +0000 @@ -8,18 +8,26 @@ struct crypto_aes_key; /** + * crypto_aes_can_use_intrinsics(void): + * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI + * operations are available, 2 if ARM-AES operations are available, or 0 if + * none are available. + */ +int crypto_aes_can_use_intrinsics(void); + +/** * crypto_aes_key_expand(key, len): * Expand the ${len}-byte AES key ${key} into a structure which can be passed - * to crypto_aes_encrypt_block. The length must be 16 or 32. + * to crypto_aes_encrypt_block(). The length must be 16 or 32. */ struct crypto_aes_key * crypto_aes_key_expand(const uint8_t *, size_t); /** * crypto_aes_encrypt_block(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the - * resulting ciphertext to ${out}. + * resulting ciphertext to ${out}. ${in} and ${out} can overlap. */ -void crypto_aes_encrypt_block(const uint8_t *, uint8_t *, +void crypto_aes_encrypt_block(const uint8_t[16], uint8_t[16], const struct crypto_aes_key *); /** diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_dh.c spiped-1.6.2/libcperciva/crypto/crypto_dh.c --- spiped-1.6.1/libcperciva/crypto/crypto_dh.c 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_dh.c 2021-12-09 22:15:31.000000000 +0000 @@ -15,7 +15,7 @@ const uint8_t priv[CRYPTO_DH_PRIVLEN]); /* Big-endian representation of 2^256. */ -static uint8_t two_exp_256[] = { +static const uint8_t two_exp_256[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -248,7 +248,7 @@ * crypto_dh_compute(pub, priv, key): * In the Diffie-Hellman group #14, compute ${pub}^(2^258 + ${priv}) and * write the result into ${key}. All values are big-endian. Note that the - * value ${pub} is the public key produced by the call to crypto_dh_generate + * value ${pub} is the public key produced by the call to crypto_dh_generate() * made by the *other* participant in the key exchange. */ int diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_dh_group14.c spiped-1.6.2/libcperciva/crypto/crypto_dh_group14.c --- spiped-1.6.1/libcperciva/crypto/crypto_dh_group14.c 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_dh_group14.c 2021-12-09 22:15:31.000000000 +0000 @@ -10,7 +10,7 @@ * in the group of quadratic residues modulo p, and the integer 2 is a * generator of this group. */ -uint8_t crypto_dh_group14[256] = { +const uint8_t crypto_dh_group14[256] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_dh_group14.h spiped-1.6.2/libcperciva/crypto/crypto_dh_group14.h --- spiped-1.6.1/libcperciva/crypto/crypto_dh_group14.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_dh_group14.h 2021-12-09 22:15:31.000000000 +0000 @@ -4,6 +4,6 @@ #include /* Diffie-Hellman group #14, from RFC 3526. */ -extern uint8_t crypto_dh_group14[]; +extern const uint8_t crypto_dh_group14[]; #endif /* !_CRYPTO_DH_GROUP14_H_ */ diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_dh.h spiped-1.6.2/libcperciva/crypto/crypto_dh.h --- spiped-1.6.1/libcperciva/crypto/crypto_dh.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_dh.h 2020-09-02 04:32:10.000000000 +0000 @@ -27,7 +27,7 @@ * crypto_dh_compute(pub, priv, key): * In the Diffie-Hellman group #14, compute ${pub}^(2^258 + ${priv}) and * write the result into ${key}. All values are big-endian. Note that the - * value ${pub} is the public key produced by the call to crypto_dh_generate + * value ${pub} is the public key produced by the call to crypto_dh_generate() * made by the *other* participant in the key exchange. */ int crypto_dh_compute(const uint8_t[CRYPTO_DH_PUBLEN], diff -Nru spiped-1.6.1/libcperciva/crypto/crypto_entropy_rdrand.c spiped-1.6.2/libcperciva/crypto/crypto_entropy_rdrand.c --- spiped-1.6.1/libcperciva/crypto/crypto_entropy_rdrand.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/crypto/crypto_entropy_rdrand.c 2021-02-22 04:15:07.000000000 +0000 @@ -1,5 +1,8 @@ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_RDRAND +/** + * CPUSUPPORT CFLAGS: X86_RDRAND + */ #include #include diff -Nru spiped-1.6.1/libcperciva/datastruct/elasticarray.c spiped-1.6.2/libcperciva/datastruct/elasticarray.c --- spiped-1.6.1/libcperciva/datastruct/elasticarray.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/elasticarray.c 2020-09-02 04:32:10.000000000 +0000 @@ -196,7 +196,7 @@ * present will be deleted. The value ${reclen} must be positive. * * As an exception to the normal rule, an elastic array may occupy more than - * 4 times the optimal storage immediately following an elasticarray_shrink + * 4 times the optimal storage immediately following an elasticarray_shrink() * call; but only if realloc(3) failed to shrink a memory allocation. */ void diff -Nru spiped-1.6.1/libcperciva/datastruct/elasticarray.h spiped-1.6.2/libcperciva/datastruct/elasticarray.h --- spiped-1.6.1/libcperciva/datastruct/elasticarray.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/elasticarray.h 2020-09-02 04:32:10.000000000 +0000 @@ -60,7 +60,7 @@ * present will be deleted. The value ${reclen} must be positive. * * As an exception to the normal rule, an elastic array may occupy more than - * 4 times the optimal storage immediately following an elasticarray_shrink + * 4 times the optimal storage immediately following an elasticarray_shrink() * call; but only if realloc(3) failed to shrink a memory allocation. */ void elasticarray_shrink(struct elasticarray *, size_t, size_t); diff -Nru spiped-1.6.1/libcperciva/datastruct/ptrheap.c spiped-1.6.2/libcperciva/datastruct/ptrheap.c --- spiped-1.6.1/libcperciva/datastruct/ptrheap.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/ptrheap.c 2020-09-02 04:32:10.000000000 +0000 @@ -133,7 +133,7 @@ /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): - * Create and return a heap, as in ptrheap_init, but with the ${N} pointers + * Create and return a heap, as in ptrheap_init(), but with the ${N} pointers * in ${ptrs} as heap elements. This is faster than creating an empty heap * and adding the elements individually. */ diff -Nru spiped-1.6.1/libcperciva/datastruct/ptrheap.h spiped-1.6.2/libcperciva/datastruct/ptrheap.h --- spiped-1.6.1/libcperciva/datastruct/ptrheap.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/ptrheap.h 2020-09-02 04:32:10.000000000 +0000 @@ -32,7 +32,7 @@ /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): - * Create and return a heap, as in ptrheap_init, but with the ${N} pointers + * Create and return a heap, as in ptrheap_init(), but with the ${N} pointers * in ${ptrs} as heap elements. This is faster than creating an empty heap * and adding the elements individually. */ diff -Nru spiped-1.6.1/libcperciva/datastruct/timerqueue.c spiped-1.6.2/libcperciva/datastruct/timerqueue.c --- spiped-1.6.1/libcperciva/datastruct/timerqueue.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/timerqueue.c 2020-09-02 04:32:10.000000000 +0000 @@ -91,7 +91,7 @@ /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Return a cookie - * which can be passed to timerqueue_delete or timerqueue_increase. + * which can be passed to timerqueue_delete() or timerqueue_increase(). */ void * timerqueue_add(struct timerqueue * Q, const struct timeval * tv, void * ptr) diff -Nru spiped-1.6.1/libcperciva/datastruct/timerqueue.h spiped-1.6.2/libcperciva/datastruct/timerqueue.h --- spiped-1.6.1/libcperciva/datastruct/timerqueue.h 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/datastruct/timerqueue.h 2020-09-02 04:32:10.000000000 +0000 @@ -17,7 +17,7 @@ /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Return a cookie - * which can be passed to timerqueue_delete or timerqueue_increase. + * which can be passed to timerqueue_delete() or timerqueue_increase(). */ void * timerqueue_add(struct timerqueue *, const struct timeval *, void *); diff -Nru spiped-1.6.1/libcperciva/events/events.c spiped-1.6.2/libcperciva/events/events.c --- spiped-1.6.1/libcperciva/events/events.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/events/events.c 2020-09-02 04:32:10.000000000 +0000 @@ -77,16 +77,16 @@ /** * events_run(void): - * Run events. Events registered via events_immediate_register will be run + * Run events. Events registered via events_immediate_register() will be run * first, in order of increasing ${prio} values; then events associated with - * ready sockets registered via events_network_register; finally, events - * associated with expired timers registered via events_timer_register will - * be run. If any event function returns a non-zero result, no further - * events will be run and said non-zero result will be returned; on error, - * -1 will be returned. May be interrupted by events_interrupt, in which case - * 0 will be returned. If there are runnable events, events_run is guaranteed - * to run at least one; but it may return while there are still more runnable - * events. + * ready sockets registered via events_network_register(); finally, events + * associated with expired timers registered via events_timer_register() will + * be run. If any event function returns a non-zero result, no further events + * will be run and said non-zero result will be returned; on error, + * -1 will be returned. May be interrupted by events_interrupt(), in which + * case 0 will be returned. If there are runnable events, events_run() is + * guaranteed to run at least one; but it may return while there are still + * more runnable events. */ static int _events_run(void) @@ -201,10 +201,10 @@ /** * events_spin(done): - * Call events_run until ${done} is non-zero (and return 0), an error occurs (and - * return -1), or a callback returns a non-zero status (and return the status - * code from the callback). May be interrupted by events_interrupt (and return - * 0). + * Call events_run() until ${done} is non-zero (and return 0), an error occurs + * (and return -1), or a callback returns a non-zero status (and return the + * status code from the callback). May be interrupted by events_interrupt() + * (and return 0). */ int events_spin(int * done) diff -Nru spiped-1.6.1/libcperciva/events/events.h spiped-1.6.2/libcperciva/events/events.h --- spiped-1.6.1/libcperciva/events/events.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/events/events.h 2020-09-02 04:32:10.000000000 +0000 @@ -5,21 +5,21 @@ /** * events_immediate_register(func, cookie, prio): - * Register ${func}(${cookie}) to be run the next time events_run is invoked, - * after immediate events with smaller ${prio} values and before events with - * larger ${prio} values. The value ${prio} must be in the range [0, 31]. - * Return a cookie which can be passed to events_immediate_cancel. + * Register ${func}(${cookie}) to be run the next time events_run() is + * invoked, after immediate events with smaller ${prio} values and before + * events with larger ${prio} values. The value ${prio} must be in the range + * [0, 31]. Return a cookie which can be passed to events_immediate_cancel(). */ void * events_immediate_register(int (*)(void *), void *, int); /** * events_immediate_cancel(cookie): * Cancel the immediate event for which the cookie ${cookie} was returned by - * events_immediate_register. + * events_immediate_register(). */ void events_immediate_cancel(void *); -/* "op" parameter to events_network_register. */ +/* "op" parameter to events_network_register(). */ #define EVENTS_NETWORK_OP_READ 0 #define EVENTS_NETWORK_OP_WRITE 1 @@ -51,52 +51,52 @@ /** * events_timer_register(func, cookie, timeo): * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a - * cookie which can be passed to events_timer_cancel or events_timer_reset. + * cookie which can be passed to events_timer_cancel() or events_timer_reset(). */ void * events_timer_register(int (*)(void *), void *, const struct timeval *); /** * events_timer_register_double(func, cookie, timeo): - * As events_timer_register, but ${timeo} is a double-precision floating point - * value specifying a number of seconds. + * As events_timer_register(), but ${timeo} is a double-precision + * floating-point value specifying a number of seconds. */ void * events_timer_register_double(int (*)(void *), void *, double); /** * events_timer_cancel(cookie): * Cancel the timer for which the cookie ${cookie} was returned by - * events_timer_register. + * events_timer_register(). */ void events_timer_cancel(void *); /** * events_timer_reset(cookie): * Reset the timer for which the cookie ${cookie} was returned by - * events_timer_register to its initial value. + * events_timer_register() to its initial value. */ int events_timer_reset(void *); /** * events_run(void): - * Run events. Events registered via events_immediate_register will be run + * Run events. Events registered via events_immediate_register() will be run * first, in order of increasing ${prio} values; then events associated with - * ready sockets registered via events_network_register; finally, events - * associated with expired timers registered via events_timer_register will - * be run. If any event function returns a non-zero result, no further - * events will be run and said non-zero result will be returned; on error, - * -1 will be returned. May be interrupted by events_interrupt, in which case - * 0 will be returned. If there are runnable events, events_run is guaranteed - * to run at least one; but it may return while there are still more runnable - * events. + * ready sockets registered via events_network_register(); finally, events + * associated with expired timers registered via events_timer_register() will + * be run. If any event function returns a non-zero result, no further events + * will be run and said non-zero result will be returned; on error, + * -1 will be returned. May be interrupted by events_interrupt(), in which + * case 0 will be returned. If there are runnable events, events_run() is + * guaranteed to run at least one; but it may return while there are still + * more runnable events. */ int events_run(void); /** * events_spin(done): - * Call events_run until ${done} is non-zero (and return 0), an error occurs (and - * return -1), or a callback returns a non-zero status (and return the status - * code from the callback). May be interrupted by events_interrupt (and return - * 0). + * Call events_run() until ${done} is non-zero (and return 0), an error occurs + * (and return -1), or a callback returns a non-zero status (and return the + * status code from the callback). May be interrupted by events_interrupt() + * (and return 0). */ int events_spin(int *); diff -Nru spiped-1.6.1/libcperciva/events/events_immediate.c spiped-1.6.2/libcperciva/events/events_immediate.c --- spiped-1.6.1/libcperciva/events/events_immediate.c 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/events/events_immediate.c 2020-09-02 04:32:10.000000000 +0000 @@ -31,10 +31,10 @@ /** * events_immediate_register(func, cookie, prio): - * Register ${func}(${cookie}) to be run the next time events_run is invoked, - * after immediate events with smaller ${prio} values and before events with - * larger ${prio} values. The value ${prio} must be in the range [0, 31]. - * Return a cookie which can be passed to events_immediate_cancel. + * Register ${func}(${cookie}) to be run the next time events_run() is + * invoked, after immediate events with smaller ${prio} values and before + * events with larger ${prio} values. The value ${prio} must be in the range + * [0, 31]. Return a cookie which can be passed to events_immediate_cancel(). */ void * events_immediate_register(int (*func)(void *), void * cookie, int prio) @@ -81,7 +81,7 @@ /** * events_immediate_cancel(cookie): * Cancel the immediate event for which the cookie ${cookie} was returned by - * events_immediate_register. + * events_immediate_register(). */ void events_immediate_cancel(void * cookie) diff -Nru spiped-1.6.1/libcperciva/events/events_network_selectstats.c spiped-1.6.2/libcperciva/events/events_network_selectstats.c --- spiped-1.6.1/libcperciva/events/events_network_selectstats.c 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/events/events_network_selectstats.c 2020-09-02 04:32:10.000000000 +0000 @@ -67,7 +67,7 @@ goto done; /* Compute inter-select duration in seconds. */ - t = (tnow.tv_sec - st.tv_sec) + (tnow.tv_usec - st.tv_usec) * 0.000001; + t = timeval_diff(st, tnow); /* Adjust statistics. We track running mean, variance * N, and max. */ N += 1.0; diff -Nru spiped-1.6.1/libcperciva/events/events_timer.c spiped-1.6.2/libcperciva/events/events_timer.c --- spiped-1.6.1/libcperciva/events/events_timer.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/events/events_timer.c 2020-09-02 04:32:10.000000000 +0000 @@ -44,7 +44,7 @@ /** * events_timer_register(func, cookie, timeo): * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a - * cookie which can be passed to events_timer_cancel or events_timer_reset. + * cookie which can be passed to events_timer_cancel() or events_timer_reset(). */ void * events_timer_register(int (*func)(void *), void * cookie, @@ -96,8 +96,8 @@ /** * events_timer_register_double(func, cookie, timeo): - * As events_timer_register, but ${timeo} is a double-precision floating point - * value specifying a number of seconds. + * As events_timer_register(), but ${timeo} is a double-precision + * floating-point value specifying a number of seconds. */ void * events_timer_register_double(int (*func)(void *), void * cookie, @@ -107,7 +107,7 @@ /* Convert timeo to a struct timeval. */ tv.tv_sec = (time_t)timeo; - tv.tv_usec = (suseconds_t)((timeo - tv.tv_sec) * 1000000.0); + tv.tv_usec = (suseconds_t)((timeo - (double)tv.tv_sec) * 1000000.0); /* Schedule the timeout. */ return (events_timer_register(func, cookie, &tv)); @@ -116,7 +116,7 @@ /** * events_timer_cancel(cookie): * Cancel the timer for which the cookie ${cookie} was returned by - * events_timer_register. + * events_timer_register(). */ void events_timer_cancel(void * cookie) @@ -134,7 +134,7 @@ /** * events_timer_reset(cookie): * Reset the timer for which the cookie ${cookie} was returned by - * events_timer_register to its initial value. + * events_timer_register() to its initial value. */ int events_timer_reset(void * cookie) diff -Nru spiped-1.6.1/libcperciva/netbuf/netbuf.h spiped-1.6.2/libcperciva/netbuf/netbuf.h --- spiped-1.6.1/libcperciva/netbuf/netbuf.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/netbuf/netbuf.h 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,108 @@ +#ifndef _NETBUF_H_ +#define _NETBUF_H_ + +#include +#include + +/* Opaque types. */ +struct network_ssl_ctx; +struct netbuf_read; +struct netbuf_write; + +/** + * netbuf_read_init(s): + * Create and return a buffered reader attached to socket ${s}. The caller + * is responsible for ensuring that no attempts are made to read from said + * socket except via the returned reader. + */ +struct netbuf_read * netbuf_read_init(int); + +/** + * netbuf_read_peek(R, data, datalen): + * Set ${data} to point to the currently buffered data in the reader ${R}; set + * ${datalen} to the number of bytes buffered. + */ +void netbuf_read_peek(struct netbuf_read *, uint8_t **, size_t *); + +/** + * netbuf_read_wait(R, len, callback, cookie): + * Wait until ${R} has ${len} or more bytes of data buffered or an error + * occurs; then invoke ${callback}(${cookie}, status) with status set to 0 + * if the data is available, -1 on error, or 1 on EOF. + */ +int netbuf_read_wait(struct netbuf_read *, size_t, + int (*)(void *, int), void *); + +/** + * netbuf_read_wait_cancel(R): + * Cancel any in-progress wait on the reader ${R}. Do not invoke the callback + * associated with the wait. + */ +void netbuf_read_wait_cancel(struct netbuf_read *); + +/** + * netbuf_read_consume(R, len): + * Advance the reader pointer for the reader ${R} by ${len} bytes. + */ +void netbuf_read_consume(struct netbuf_read *, size_t); + +/** + * netbuf_read_free(R): + * Free the reader ${R}. Note that an indeterminate amount of data may have + * been buffered and will be lost. + */ +void netbuf_read_free(struct netbuf_read *); + +/** + * netbuf_write_init(s, fail_callback, fail_cookie): + * Create and return a buffered writer attached to socket ${s}. The caller + * is responsible for ensuring that no attempts are made to write to said + * socket except via the returned writer until netbuf_write_free() is called. + * If a write fails, ${fail_callback} will be invoked with the parameter + * ${fail_cookie}. + */ +struct netbuf_write * netbuf_write_init(int, int (*)(void *), void *); + +/** + * netbuf_write_reserve(W, len): + * Reserve ${len} bytes of space in the buffered writer ${W} and return a + * pointer to the buffer. This operation must be followed by a call to + * netbuf_write_consume() before the next call to _reserve() or _write() and + * before a callback could be made into netbuf_write() (i.e., before control + * returns to the event loop). + */ +uint8_t * netbuf_write_reserve(struct netbuf_write *, size_t); + +/** + * netbuf_write_consume(W, len): + * Consume a reservation previously made by netbuf_write_reserve(); the value + * ${len} must be <= the value passed to netbuf_write_reserve(). + */ +int netbuf_write_consume(struct netbuf_write *, size_t); + +/** + * netbuf_write_write(W, buf, buflen): + * Write ${buflen} bytes from the buffer ${buf} via the buffered writer ${W}. + */ +int netbuf_write_write(struct netbuf_write *, const uint8_t *, size_t); + +/** + * netbuf_write_free(W): + * Free the writer ${W}. + */ +void netbuf_write_free(struct netbuf_write *); + +/** + * netbuf_ssl_read_init(ssl): + * Behave as netbuf_read_init() but take an SSL context instead. + */ +struct netbuf_read * netbuf_ssl_read_init(struct network_ssl_ctx *); + +/** + * netbuf_ssl_write_init(ssl, fail_callback, fail_cookie): + * Behave as netbuf_write_init() but take an SSL context instead. + */ +struct netbuf_write * netbuf_ssl_write_init(struct network_ssl_ctx *, + int (*)(void *), void *); + +#endif /* !_NETBUF_H_ */ diff -Nru spiped-1.6.1/libcperciva/netbuf/netbuf_read.c spiped-1.6.2/libcperciva/netbuf/netbuf_read.c --- spiped-1.6.1/libcperciva/netbuf/netbuf_read.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/netbuf/netbuf_read.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,293 @@ +#include + +#include +#include +#include +#include + +#include "events.h" +#include "network.h" + +#include "netbuf.h" +#include "netbuf_ssl_internal.h" + +/* + * Set to NULL here; initialized by netbuf_ssl if SSL is being used. This + * allows us to avoid needing to link libssl into binaries which aren't + * going to be using SSL. + */ +void * (* netbuf_read_ssl_func)(struct network_ssl_ctx *, uint8_t *, size_t, + size_t, int (*)(void *, ssize_t), void *) = NULL; +void (* netbuf_read_ssl_cancel_func)(void *) = NULL; + +/* Buffered reader structure. */ +struct netbuf_read { + /* Reader state. */ + int s; /* Source socket for reads... */ + struct network_ssl_ctx * ssl; /* ... unless we're using this. */ + int (* callback)(void *, int); /* Callback for _wait. */ + void * cookie; /* Cookie for _wait. */ + void * read_cookie; /* From network_read. */ + void * immediate_cookie; /* From events_immediate_register. */ + + /* Buffer state. */ + uint8_t * buf; /* Current read buffer. */ + size_t buflen; /* Length of buf. */ + size_t bufpos; /* Position of read pointer in buf. */ + size_t datalen; /* Position of write pointer in buf. */ +}; + +static int callback_success(void *); +static int callback_read(void *, ssize_t); + +/** + * netbuf_read_init(s): + * Create and return a buffered reader attached to socket ${s}. The caller + * is responsible for ensuring that no attempts are made to read from said + * socket except via the returned reader. + */ +struct netbuf_read * +netbuf_read_init(int s) +{ + + return (netbuf_read_init2(s, NULL)); +} + +/** + * netbuf_read_init2(s, ssl): + * Behave like netbuf_read_init if ${ssl} is NULL. If the SSL context ${ssl} + * is not NULL, use it and ignore ${s}. + */ +struct netbuf_read * +netbuf_read_init2(int s, struct network_ssl_ctx * ssl) +{ + struct netbuf_read * R; + + /* Bake a cookie. */ + if ((R = malloc(sizeof(struct netbuf_read))) == NULL) + goto err0; + R->s = s; + R->ssl = ssl; + R->read_cookie = NULL; + R->immediate_cookie = NULL; + + /* Allocate buffer. */ + R->buflen = 4096; + if ((R->buf = malloc(R->buflen)) == NULL) + goto err1; + R->bufpos = 0; + R->datalen = 0; + + /* Success! */ + return (R); + +err1: + free(R); +err0: + /* Failure! */ + return (NULL); +} + +/** + * netbuf_read_peek(R, data, datalen): + * Set ${data} to point to the currently buffered data in the reader ${R}; set + * ${datalen} to the number of bytes buffered. + */ +void +netbuf_read_peek(struct netbuf_read * R, uint8_t ** data, size_t * datalen) +{ + + /* Point at current buffered data. */ + *data = &R->buf[R->bufpos]; + *datalen = R->datalen - R->bufpos; +} + +/** + * netbuf_read_wait(R, len, callback, cookie): + * Wait until ${R} has ${len} or more bytes of data buffered or an error + * occurs; then invoke ${callback}(${cookie}, status) with status set to 0 + * if the data is available, -1 on error, or 1 on EOF. + */ +int +netbuf_read_wait(struct netbuf_read * R, size_t len, + int (* callback)(void *, int), void * cookie) +{ + uint8_t * nbuf; + size_t nbuflen; + + /* Sanity-check: We shouldn't be reading already. */ + assert(R->read_cookie == NULL); + assert(R->immediate_cookie == NULL); + + /* Record parameters for future reference. */ + R->callback = callback; + R->cookie = cookie; + + /* If we have enough data already, schedule a callback. */ + if (R->datalen - R->bufpos >= len) { + if ((R->immediate_cookie = + events_immediate_register(callback_success, R, 0)) == NULL) + goto err0; + else + goto done; + } + + /* Resize the buffer if needed. */ + if (R->buflen < len) { + /* Compute new buffer size. */ + nbuflen = R->buflen * 2; + if (nbuflen < len) + nbuflen = len; + + /* Allocate new buffer. */ + if ((nbuf = malloc(nbuflen)) == NULL) + goto err0; + + /* Copy data into new buffer. */ + memcpy(nbuf, &R->buf[R->bufpos], R->datalen - R->bufpos); + + /* Free old buffer and use new buffer. */ + free(R->buf); + R->buf = nbuf; + R->buflen = nbuflen; + R->datalen -= R->bufpos; + R->bufpos = 0; + } + + /* Move data to start of buffer if needed. */ + if (R->buflen - R->bufpos < len) { + memmove(R->buf, &R->buf[R->bufpos], R->datalen - R->bufpos); + R->datalen -= R->bufpos; + R->bufpos = 0; + } + + /* Read data into the buffer. */ + if (R->ssl) { + if ((R->read_cookie = (netbuf_read_ssl_func)(R->ssl, + &R->buf[R->datalen], R->buflen - R->datalen, + R->bufpos + len - R->datalen, callback_read, R)) == NULL) + goto err0; + } else { + if ((R->read_cookie = network_read(R->s, &R->buf[R->datalen], + R->buflen - R->datalen, R->bufpos + len - R->datalen, + callback_read, R)) == NULL) + goto err0; + } + +done: + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/* Perform immediate callback for netbuf_read_wait. */ +static int +callback_success(void * cookie) +{ + struct netbuf_read * R = cookie; + + /* Sanity-check: We should be expecting this callback. */ + assert(R->immediate_cookie != NULL); + + /* This callback is no longer pending. */ + R->immediate_cookie = NULL; + + /* Perform callback. */ + return ((R->callback)(R->cookie, 0)); +} + +/* Callback for a completed network read. */ +static int +callback_read(void * cookie, ssize_t lenread) +{ + struct netbuf_read * R = cookie; + + /* Sanity-check: We should be reading. */ + assert(R->read_cookie != NULL); + + /* This callback is no longer pending. */ + R->read_cookie = NULL; + + /* Did the read fail? */ + if (lenread < 0) + goto failed; + + /* Did we hit EOF? */ + if (lenread == 0) + goto eof; + + /* We've got more data. */ + R->datalen += (size_t)lenread; + + /* Perform callback. */ + return ((R->callback)(R->cookie, 0)); + +eof: + /* Perform EOF callback. */ + return ((R->callback)(R->cookie, 1)); + +failed: + /* Perform failure callback. */ + return ((R->callback)(R->cookie, -1)); +} + +/** + * netbuf_read_wait_cancel(R): + * Cancel any in-progress wait on the reader ${R}. Do not invoke the callback + * associated with the wait. + */ +void +netbuf_read_wait_cancel(struct netbuf_read * R) +{ + + /* If we have an in-progress read, cancel it. */ + if (R->read_cookie != NULL) { + if (R->ssl) + (netbuf_read_ssl_cancel_func)(R->read_cookie); + else + network_read_cancel(R->read_cookie); + R->read_cookie = NULL; + } + + /* If we have an immediate callback pending, cancel it. */ + if (R->immediate_cookie != NULL) { + events_immediate_cancel(R->immediate_cookie); + R->immediate_cookie = NULL; + } +} + +/** + * netbuf_read_consume(R, len): + * Advance the reader pointer for the reader ${R} by ${len} bytes. + */ +void +netbuf_read_consume(struct netbuf_read * R, size_t len) +{ + + /* Sanity-check: We can't consume data we don't have. */ + assert(R->datalen - R->bufpos >= len); + + /* Advance the buffer pointer. */ + R->bufpos += len; +} + +/** + * netbuf_read_free(R): + * Free the reader ${R}. Note that an indeterminate amount of data may have + * been buffered and will be lost. + */ +void +netbuf_read_free(struct netbuf_read * R) +{ + + /* Can't free a reader which is busy. */ + assert(R->read_cookie == NULL); + assert(R->immediate_cookie == NULL); + + /* Free the buffer and the reader. */ + free(R->buf); + free(R); +} diff -Nru spiped-1.6.1/libcperciva/netbuf/netbuf_ssl_internal.h spiped-1.6.2/libcperciva/netbuf/netbuf_ssl_internal.h --- spiped-1.6.1/libcperciva/netbuf/netbuf_ssl_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/netbuf/netbuf_ssl_internal.h 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,30 @@ +#ifndef _NETBUF_SSL_H_ +#define _NETBUF_SSL_H_ + +/* + * Function pointers defined in netbuf_read and netbuf_write; we set them + * from our _init functions in order to avoid unnecessary linkage. + */ +extern void * (* netbuf_read_ssl_func)(struct network_ssl_ctx *, uint8_t *, + size_t, size_t, int (*)(void *, ssize_t), void *); +extern void (* netbuf_read_ssl_cancel_func)(void *); +extern void * (* netbuf_write_ssl_func)(struct network_ssl_ctx *, + const uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); +extern void (* netbuf_write_ssl_cancel_func)(void *); + +/** + * netbuf_read_init2(s, ssl): + * Behave like netbuf_read_init if ${ssl} is NULL. If the SSL context ${ssl} + * is not NULL, use it and ignore ${s}. + */ +struct netbuf_read * netbuf_read_init2(int, struct network_ssl_ctx *); + +/** + * netbuf_write_init2(s, ssl, fail_callback, fail_cookie): + * Behave like netbuf_write_init if ${ssl} is NULL. If the SSL context ${ssl} + * is not NULL, use it and ignore ${s}. + */ +struct netbuf_write * netbuf_write_init2(int, struct network_ssl_ctx *, + int (*)(void *), void *); + +#endif /* !_NETBUF_SSL_H_ */ diff -Nru spiped-1.6.1/libcperciva/network/network_accept.c spiped-1.6.2/libcperciva/network/network_accept.c --- spiped-1.6.1/libcperciva/network/network_accept.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/network/network_accept.c 2020-12-05 21:26:44.000000000 +0000 @@ -25,7 +25,9 @@ if ((s = accept(C->fd, NULL, NULL)) == -1) { /* If a connection isn't available, reset the callback. */ if ((errno == EAGAIN) || +#if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || +#endif (errno == ECONNABORTED) || (errno == EINTR)) goto tryagain; @@ -52,7 +54,7 @@ * already marked as listening and non-blocking. When a connection has been * accepted or an error occurs, invoke ${callback}(${cookie}, s) where s is * the accepted connection or -1 on error. Return a cookie which can be - * passed to network_accept_cancel in order to cancel the accept. + * passed to network_accept_cancel() in order to cancel the accept. */ void * network_accept(int fd, int (* callback)(void *, int), void * cookie) @@ -87,7 +89,7 @@ /** * network_accept_cancel(cookie): * Cancel the connection accept for which the cookie ${cookie} was returned - * by network_accept. Do not invoke the callback associated with the accept. + * by network_accept(). Do not invoke the callback associated with the accept. */ void network_accept_cancel(void * cookie) diff -Nru spiped-1.6.1/libcperciva/network/network_connect.c spiped-1.6.2/libcperciva/network/network_connect.c --- spiped-1.6.1/libcperciva/network/network_connect.c 2017-01-27 22:38:21.000000000 +0000 +++ spiped-1.6.2/libcperciva/network/network_connect.c 2020-09-02 04:32:10.000000000 +0000 @@ -170,7 +170,7 @@ * a non-blocking socket. Once connected, invoke ${callback}(${cookie}, s) * where s is the connected socket; upon fatal error or if there are no * addresses remaining to attempt, invoke ${callback}(${cookie}, -1). Return - * a cookie which can be passed to network_connect_cancel in order to cancel + * a cookie which can be passed to network_connect_cancel() in order to cancel * the connection attempt. */ void * @@ -184,7 +184,7 @@ /** * network_connect_timeo(sas, timeo, callback, cookie): - * Behave as network_connect, but wait a duration of at most ${timeo} for + * Behave as network_connect(), but wait a duration of at most ${timeo} for * each address which is being attempted. */ void * @@ -227,7 +227,7 @@ /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by - * network_connect. Do not invoke the associated callback. + * network_connect(). Do not invoke the associated callback. */ void network_connect_cancel(void * cookie) diff -Nru spiped-1.6.1/libcperciva/network/network.h spiped-1.6.2/libcperciva/network/network.h --- spiped-1.6.1/libcperciva/network/network.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/network/network.h 2020-09-02 04:32:10.000000000 +0000 @@ -16,14 +16,14 @@ * already marked as listening and non-blocking. When a connection has been * accepted or an error occurs, invoke ${callback}(${cookie}, s) where s is * the accepted connection or -1 on error. Return a cookie which can be - * passed to network_accept_cancel in order to cancel the accept. + * passed to network_accept_cancel() in order to cancel the accept. */ void * network_accept(int, int (*)(void *, int), void *); /** * network_accept_cancel(cookie): * Cancel the connection accept for which the cookie ${cookie} was returned - * by network_accept. Do not invoke the callback associated with the accept. + * by network_accept(). Do not invoke the callback associated with the accept. */ void network_accept_cancel(void *); @@ -33,7 +33,7 @@ * a non-blocking socket. Once connected, invoke ${callback}(${cookie}, s) * where s is the connected socket; upon fatal error or if there are no * addresses remaining to attempt, invoke ${callback}(${cookie}, -1). Return - * a cookie which can be passed to network_connect_cancel in order to cancel + * a cookie which can be passed to network_connect_cancel() in order to cancel * the connection attempt. */ void * network_connect(struct sock_addr * const *, @@ -41,7 +41,7 @@ /** * network_connect_timeo(sas, timeo, callback, cookie): - * Behave as network_connect, but wait a duration of at most ${timeo} for + * Behave as network_connect(), but wait a duration of at most ${timeo} for * each address which is being attempted. */ void * network_connect_timeo(struct sock_addr * const *, const struct timeval *, @@ -50,7 +50,7 @@ /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by - * network_connect. Do not invoke the associated callback. + * network_connect(). Do not invoke the associated callback. */ void network_connect_cancel(void *); @@ -60,7 +60,7 @@ * When at least ${minread} bytes have been read or on error, invoke * ${callback}(${cookie}, lenread), where lenread is 0 on EOF or -1 on error, * and the number of bytes read (between ${minread} and ${buflen} inclusive) - * otherwise. Return a cookie which can be passed to network_read_cancel in + * otherwise. Return a cookie which can be passed to network_read_cancel() in * order to cancel the read. */ void * network_read(int, uint8_t *, size_t, size_t, @@ -69,7 +69,7 @@ /** * network_read_cancel(cookie): * Cancel the buffer read for which the cookie ${cookie} was returned by - * network_read. Do not invoke the callback associated with the read. + * network_read(). Do not invoke the callback associated with the read. */ void network_read_cancel(void *); @@ -79,7 +79,7 @@ * When at least ${minwrite} bytes have been written or on error, invoke * ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the * number of bytes written (between ${minwrite} and ${buflen} inclusive) - * otherwise. Return a cookie which can be passed to network_write_cancel in + * otherwise. Return a cookie which can be passed to network_write_cancel() in * order to cancel the write. */ void * network_write(int, const uint8_t *, size_t, size_t, @@ -88,7 +88,7 @@ /** * network_write_cancel(cookie): * Cancel the buffer write for which the cookie ${cookie} was returned by - * network_write. Do not invoke the callback associated with the write. + * network_write(). Do not invoke the callback associated with the write. */ void network_write_cancel(void *); diff -Nru spiped-1.6.1/libcperciva/network/network_read.c spiped-1.6.2/libcperciva/network/network_read.c --- spiped-1.6.1/libcperciva/network/network_read.c 2018-10-14 23:25:59.000000000 +0000 +++ spiped-1.6.2/libcperciva/network/network_read.c 2020-12-05 21:26:44.000000000 +0000 @@ -56,7 +56,9 @@ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || +#if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || +#endif (errno == EINTR)) goto tryagain; @@ -104,7 +106,7 @@ * When at least ${minread} bytes have been read or on error, invoke * ${callback}(${cookie}, lenread), where lenread is 0 on EOF or -1 on error, * and the number of bytes read (between ${minread} and ${buflen} inclusive) - * otherwise. Return a cookie which can be passed to network_read_cancel in + * otherwise. Return a cookie which can be passed to network_read_cancel() in * order to cancel the read. */ void * @@ -148,7 +150,7 @@ /** * network_read_cancel(cookie): * Cancel the buffer read for which the cookie ${cookie} was returned by - * network_read. Do not invoke the callback associated with the read. + * network_read(). Do not invoke the callback associated with the read. */ void network_read_cancel(void * cookie) diff -Nru spiped-1.6.1/libcperciva/network/network_write.c spiped-1.6.2/libcperciva/network/network_write.c --- spiped-1.6.1/libcperciva/network/network_write.c 2018-10-14 23:25:59.000000000 +0000 +++ spiped-1.6.2/libcperciva/network/network_write.c 2021-12-09 22:15:31.000000000 +0000 @@ -68,9 +68,10 @@ ssize_t len; #ifdef POSIXFAIL_MSG_NOSIGNAL void (*oldsig)(int); + int saved_errno; #endif - /* If we don't have MSG_NOSIGNAL, catch SIGPIPE. */ + /* If we don't have MSG_NOSIGNAL, ignore SIGPIPE. */ #ifdef POSIXFAIL_MSG_NOSIGNAL if ((oldsig = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) { warnp("signal(SIGPIPE)"); @@ -85,19 +86,27 @@ /* We should never see a send length of zero. */ assert(len != 0); - /* If we set a SIGPIPE handler, restore the old one. */ + /* If we ignored SIGPIPE, restore the old handler. */ #ifdef POSIXFAIL_MSG_NOSIGNAL + /* Save errno in case it gets clobbered by signal(). */ + saved_errno = errno; + if (signal(SIGPIPE, oldsig) == SIG_ERR) { warnp("signal(SIGPIPE)"); goto failed; } + + /* Restore saved errno. */ + errno = saved_errno; #endif /* Failure? */ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || +#if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || +#endif (errno == EINTR)) goto tryagain; @@ -138,7 +147,7 @@ * When at least ${minwrite} bytes have been written or on error, invoke * ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the * number of bytes written (between ${minwrite} and ${buflen} inclusive) - * otherwise. Return a cookie which can be passed to network_write_cancel in + * otherwise. Return a cookie which can be passed to network_write_cancel() in * order to cancel the write. */ void * @@ -182,7 +191,7 @@ /** * network_write_cancel(cookie): * Cancel the buffer write for which the cookie ${cookie} was returned by - * network_write. Do not invoke the callback associated with the write. + * network_write(). Do not invoke the callback associated with the write. */ void network_write_cancel(void * cookie) diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-abstract-declarator.c spiped-1.6.2/libcperciva/POSIX/posix-abstract-declarator.c --- spiped-1.6.1/libcperciva/POSIX/posix-abstract-declarator.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-abstract-declarator.c 2020-09-02 04:32:10.000000000 +0000 @@ -0,0 +1,21 @@ +#ifdef POSIXFAIL_ABSTRACT_DECLARATOR +static int func(int ARGNAME[static restrict 1]); +#else +static int func(int [static restrict 1]); +#endif + +int +func(int arr[static restrict 1]) +{ + + (void)arr; /* UNUSED */ + return (0); +} + +int +main(void) +{ + + (void)func; /* UNUSED */ + return (0); +} diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-cflags-filter.sh spiped-1.6.2/libcperciva/POSIX/posix-cflags-filter.sh --- spiped-1.6.1/libcperciva/POSIX/posix-cflags-filter.sh 2019-12-22 02:38:52.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-cflags-filter.sh 2021-01-11 23:41:03.000000000 +0000 @@ -1,5 +1,7 @@ -# Should be sourced by `command -p sh posix-cflags-filter.sh "$PATH"` from within a Makefile -# Produces a file to be sourced which edits CFLAGS +# Should be sourced by +# command -p sh posix-cflags-filter.sh "$PATH" +# from within a Makefile. +# Produces a file to be sourced which edits CFLAGS. # Sanity check environment variables if [ -z "${CC}" ]; then @@ -12,7 +14,7 @@ fi # Find directory of this script and the source files -D=`dirname $0` +D=$(dirname $0) if ! ${CC} -O2 $D/posix-cflags-filter.c 2>/dev/null; then if ${CC} $D/posix-cflags-filter.c 2>/dev/null; then diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-cflags.sh spiped-1.6.2/libcperciva/POSIX/posix-cflags.sh --- spiped-1.6.1/libcperciva/POSIX/posix-cflags.sh 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-cflags.sh 2021-12-09 22:15:31.000000000 +0000 @@ -1,4 +1,6 @@ -# Should be sourced by `command -p sh posix-cflags.sh "$PATH"` from within a Makefile +# Should be sourced by +# command -p sh posix-cflags.sh "$PATH" +# from within a Makefile. # Sanity check environment variables if [ -z "${CC}" ]; then @@ -11,23 +13,51 @@ fi # Find directory of this script and the source files -D=`dirname $0` +D=$(dirname $0) + +# Check if we can compile & run a binary. +if ! ${CC} ${CFLAGS} $D/posix-trivial.c 2>/dev/null; then + echo "WARNING: failed to compile posix-trivial.c" 1>&2 +else + # If the user hasn't disabled runtime checks... + if [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -eq "0" ]; then + # ... test if we can run the trivial binary. + if ! ./a.out ; then + echo "WARNING: failed to run a trivial binary; " 1>&2 + echo "disabling runtime POSIX compatibility checks" 1>&2 + DISABLE_POSIX_RUNTIME_CHECKS=1 + fi + fi +fi FIRST=YES -if ! ${CC} -D_POSIX_C_SOURCE=200809L $D/posix-msg_nosignal.c 2>/dev/null; then +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L $D/posix-msg_nosignal.c 2>/dev/null; then [ ${FIRST} = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_MSG_NOSIGNAL" echo "WARNING: POSIX violation: not defining MSG_NOSIGNAL" 1>&2 fi -if ! ${CC} -D_POSIX_C_SOURCE=200809L $D/posix-clock_realtime.c 2>/dev/null; then +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L $D/posix-clock_realtime.c 2>/dev/null; then [ ${FIRST} = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_CLOCK_REALTIME" echo "WARNING: POSIX violation: not defining CLOCK_REALTIME" 1>&2 fi -if ! ${CC} -D_POSIX_C_SOURCE=200809L $D/posix-clock_gettime.c 2>/dev/null; then +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 $D/posix-inet-addrstrlen.c 2>/dev/null; then + [ ${FIRST} = "NO" ] && printf " "; FIRST=NO + printf %s "-DPOSIXFAIL_INET_ADDRSTRLEN" + echo "WARNING: POSIX violation: not defining INET_ADDRSTRLEN" 1>&2 +fi +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 $D/posix-inet6-addrstrlen.c 2>/dev/null; then + [ ${FIRST} = "NO" ] && printf " "; FIRST=NO + printf %s "-DPOSIXFAIL_INET6_ADDRSTRLEN" + echo "WARNING: POSIX violation: not defining INET6_ADDRSTRLEN" 1>&2 +fi +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L $D/posix-clock_gettime.c 2>/dev/null; then [ ${FIRST} = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_CLOCK_GETTIME" echo "WARNING: POSIX violation: not declaring clock_gettime()" 1>&2 +elif [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -ne "0" ]; then + # Do nothing + true else # Even if the compilation succeeds, we still need to run the binary # because OS X 10.11 with XCode 8 _will_ contain clock_gettime() in the @@ -43,11 +73,26 @@ echo "WARNING: POSIX violation: clock_gettime() is not linkable" 1>&2 fi fi -if ! ${CC} -D_POSIX_C_SOURCE=200809L $D/posix-restrict.c 2>/dev/null; then +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 $D/posix-stat-st_mtim.c 2>/dev/null; then + [ ${FIRST} = "NO" ] && printf " "; FIRST=NO + printf %s "-DPOSIXFAIL_STAT_ST_MTIM" + echo "WARNING: POSIX violation: struct stat does not contain st_mtim" 1>&2 +fi +NEED_STD_C99="" +if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L $D/posix-restrict.c 2>/dev/null; then echo "WARNING: POSIX violation: ${CC} does not accept the 'restrict' keyword" 1>&2 - if ${CC} -D_POSIX_C_SOURCE=200809L -std=c99 $D/posix-restrict.c 2>/dev/null; then + if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -std=c99 $D/posix-restrict.c 2>/dev/null; then [ ${FIRST} = "NO" ] && printf " "; FIRST=NO printf %s "-std=c99" + NEED_STD_C99="-std=c99" + fi +fi +if ! ${CC} ${CFLAGS} ${NEED_STD_C99} -D_POSIX_C_SOURCE=200809L -DARGNAME="" $D/posix-abstract-declarator.c 2>/dev/null; then + echo "WARNING: POSIX violation: ${CC} does not accept qualifiers in an abstract declarator" 1>&2 + # Test compile with -DPOSIXFAIL_ABSTRACT_DECLARATOR + if ${CC} ${CFLAGS} ${NEED_STD_C99} -D_POSIX_C_SOURCE=200809L -DPOSIXFAIL_ABSTRACT_DECLARATOR $D/posix-abstract-declarator.c 2>/dev/null; then + [ ${FIRST} = "NO" ] && printf " "; FIRST=NO + printf %s "-DPOSIXFAIL_ABSTRACT_DECLARATOR" fi fi rm -f a.out diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-inet6-addrstrlen.c spiped-1.6.2/libcperciva/POSIX/posix-inet6-addrstrlen.c --- spiped-1.6.1/libcperciva/POSIX/posix-inet6-addrstrlen.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-inet6-addrstrlen.c 2020-09-02 04:32:10.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +int +main(void) +{ + + return (INET6_ADDRSTRLEN); +} diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-inet-addrstrlen.c spiped-1.6.2/libcperciva/POSIX/posix-inet-addrstrlen.c --- spiped-1.6.1/libcperciva/POSIX/posix-inet-addrstrlen.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-inet-addrstrlen.c 2020-09-02 04:32:10.000000000 +0000 @@ -0,0 +1,8 @@ +#include + +int +main(void) +{ + + return (INET_ADDRSTRLEN); +} diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-l.c spiped-1.6.2/libcperciva/POSIX/posix-l.c --- spiped-1.6.1/libcperciva/POSIX/posix-l.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-l.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -int -main(void) -{ - - return (0); -} diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-l.sh spiped-1.6.2/libcperciva/POSIX/posix-l.sh --- spiped-1.6.1/libcperciva/POSIX/posix-l.sh 2019-12-22 02:38:52.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-l.sh 2021-12-09 22:15:31.000000000 +0000 @@ -1,4 +1,6 @@ -# Should be sourced by `command -p sh posix-l.sh "$PATH"` from within a Makefile. +# Should be sourced by +# command -p sh posix-l.sh "$PATH" +# from within a Makefile. # Sanity check environment variables if [ -z "${CC}" ]; then @@ -10,9 +12,12 @@ PATH=$1 fi +# Find directory of this script and the source files +D=$(dirname $0) + FIRST=YES for LIB in rt xnet; do - if ${CC} -l${LIB} posix-l.c 2>/dev/null; then + if ${CC} ${CFLAGS} -l${LIB} $D/posix-trivial.c 2>/dev/null; then if [ ${FIRST} = "NO" ]; then printf " "; fi diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-stat-st_mtim.c spiped-1.6.2/libcperciva/POSIX/posix-stat-st_mtim.c --- spiped-1.6.1/libcperciva/POSIX/posix-stat-st_mtim.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-stat-st_mtim.c 2020-12-05 21:26:44.000000000 +0000 @@ -0,0 +1,12 @@ +#include + +int +main(void) +{ + struct stat sb; + + /* Can we reference st_mtim? */ + (void)sb.st_mtim.tv_sec; + + return (0); +} diff -Nru spiped-1.6.1/libcperciva/POSIX/posix-trivial.c spiped-1.6.2/libcperciva/POSIX/posix-trivial.c --- spiped-1.6.1/libcperciva/POSIX/posix-trivial.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/posix-trivial.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,6 @@ +int +main(void) +{ + + return (0); +} diff -Nru spiped-1.6.1/libcperciva/POSIX/README spiped-1.6.2/libcperciva/POSIX/README --- spiped-1.6.1/libcperciva/POSIX/README 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/POSIX/README 2021-12-09 22:15:31.000000000 +0000 @@ -7,6 +7,10 @@ thus we should see behaviour consistent with a standard-compliant C99 compiler. +One POSIX compatibility check requires a runtime test. This will be +automatically disabled if the build system detects that you are +cross-compiling for another platform, or it can be manually disabled by +setting DISABLE_POSIX_RUNTIME_CHECKS to a non-zero value. - posix-cflags.sh: Detects if ${CC} supports certain POSIX features, and outputs a POSIXFAIL_ define if it is not supported so that we can work around @@ -16,11 +20,23 @@ - DPOSIXFAIL_MSG_NOSIGNAL: not defining MSG_NOSIGNAL. - DPOSIXFAIL_CLOCK_REALTIME: not defining CLOCK_REALTIME. - DPOSIXFAIL_CLOCK_GETTIME: not declaring clock_gettime(), or - clock_gettime() is not linkable. + clock_gettime() is not linkable. The latter test requires a runtime check. + - DPOSIXFAIL_INET_ADDRSTRLEN: not defining + INET_ADDRSTRLEN. + - DPOSIXFAIL_INET6_ADDRSTRLEN: not defining + INET6_ADDRSTRLEN. + - DPOSIXFAIL_ABSTRACT_DECLARATOR: ${CC} does not accept + qualifiers in an abstract declarator. + - DPOSIXFAIL_STAT_ST_MTIM: struct stat does not contain st_mtim. - std=c99: ${CC} does not accept the `restrict` keyword by default, but accepts it when given this flag. -posix-l.sh: Detects whether the linker supports certain POSIX features. +- posix-cflags-filter.sh: Detects if ${CC} supports expected ${CFLAG} value(s). + + The potential ${CFLAGS} flags it checks are: + - O2: some compilers only accept -O. + +- posix-l.sh: Detects whether the linker supports certain POSIX features. The potential command-line flags are: - lrt lxnet: c99 is required to understand these options, and ignore them if diff -Nru spiped-1.6.1/libcperciva/util/align_ptr.h spiped-1.6.2/libcperciva/util/align_ptr.h --- spiped-1.6.1/libcperciva/util/align_ptr.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/align_ptr.h 2021-01-11 23:41:03.000000000 +0000 @@ -0,0 +1,50 @@ +#ifndef _ALIGN_PTR_H_ +#define _ALIGN_PTR_H_ + +#include +#include + +/** + * ALIGN_PTR_DECL(type, name, num, alignsize): + * Declare a pointer called ${name}, which points to an array large enough to + * contain ${num} values of ${type} and is aligned to ${alignsize} bytes. The + * pointer must not be used until ALIGN_PTR_INIT(${name}, ${alignsize}) has + * been called. This macro may also create an additional variable called + * "${name}_buf". + */ +#define ALIGN_PTR_DECL(type, name, num, alignsize) \ + uint8_t name##_buf[num * sizeof(type) + (alignsize - 1)]; \ + type * name + +/** + * ALIGN_PTR_INIT(name, alignsize): + * Initialize the variable called ${name} to point to an array which is + * aligned to ${alignsize} bytes. They must have previously been declared + * with ALIGN_PTR_DECL(${name}, ${alignsize}). This macro assumes that + * casting a pointer to uintptr_t behaves naturally, i.e. yields a byte offset + * relative to aligned memory. + */ +#define ALIGN_PTR_INIT(name, alignsize) \ + name = align_ptr(name##_buf, alignsize) + +/** + * align_ptr(arr, alignment): + * Return a pointer to the first memory location within ${arr} which is + * aligned to ${alignsize} bytes. (It is expected that this function will + * only be called via the ALIGN_PTR_INIT macro). + */ +static inline void * +align_ptr(uint8_t * arr, size_t alignment) +{ + size_t offset; + + /* + * This assumes that casting a pointer to uintptr_t behaves naturally, + * i.e. yields a byte offset relative to aligned memory. + */ + offset = (uintptr_t)(&arr[0]) % alignment; + offset = (alignment - offset) % alignment; + return ((void *)&arr[offset]); +} + +#endif /* !_ALIGN_PTR_H_ */ diff -Nru spiped-1.6.1/libcperciva/util/ctassert.h spiped-1.6.2/libcperciva/util/ctassert.h --- spiped-1.6.1/libcperciva/util/ctassert.h 2017-04-21 06:04:42.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/ctassert.h 2020-09-02 04:32:10.000000000 +0000 @@ -14,6 +14,7 @@ /* Define using libcperciva namespace to avoid collisions. */ #define CTASSERT(x) libcperciva_CTASSERT(x, __LINE__) #define libcperciva_CTASSERT(x, y) libcperciva__CTASSERT(x, y) -#define libcperciva__CTASSERT(x, y) extern char libcperciva__assert ## y[(x) ? 1 : -1] +#define libcperciva__CTASSERT(x, y) \ + extern char libcperciva__assert ## y[(x) ? 1 : -1] #endif /* !_CTASSERT_H_ */ diff -Nru spiped-1.6.1/libcperciva/util/entropy.c spiped-1.6.2/libcperciva/util/entropy.c --- spiped-1.6.1/libcperciva/util/entropy.c 2017-01-27 22:38:21.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/entropy.c 2020-12-05 21:26:44.000000000 +0000 @@ -1,7 +1,9 @@ +#include #include #include #include #include +#include #include #include "warnp.h" @@ -17,40 +19,72 @@ */ /** - * entropy_read(buf, buflen): - * Fill the given buffer with random bytes provided by the operating system. + * Entropy reader state. At present it holds a file descriptor for + * /dev/urandom, but in the future this structure may gain other OS-dependent + * state, e.g. a Windows Handle. */ -int -entropy_read(uint8_t * buf, size_t buflen) -{ +struct entropy_read_cookie { int fd; - ssize_t lenread; +}; - /* Sanity-check the buffer size. */ - if (buflen > SSIZE_MAX) { - warn0("Programmer error: " - "Trying to read insane amount of random data: %zu", - buflen); +/** + * entropy_read_init(void): + * Initialize the ability to produce random bytes from the operating system, + * and return a cookie. + */ +struct entropy_read_cookie * +entropy_read_init(void) +{ + struct entropy_read_cookie * er; + + /* Allocate cookie. */ + if ((er = malloc(sizeof(struct entropy_read_cookie))) == NULL) { + warnp("malloc"); goto err0; } /* Open /dev/urandom. */ - if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { + if ((er->fd = open("/dev/urandom", O_RDONLY)) == -1) { warnp("open(/dev/urandom)"); - goto err0; + goto err1; } + /* Success! */ + return (er); + +err1: + free(er); +err0: + /* Failure! */ + return (NULL); +} + +/** + * entropy_read_fill(er, buf, buflen): + * Fill the given buffer with random bytes provided by the operating system + * using the resources in ${er}. + */ +int +entropy_read_fill(struct entropy_read_cookie * er, uint8_t * buf, + size_t buflen) +{ + ssize_t lenread; + + /* Sanity checks. */ + assert(er != NULL); + assert(buflen <= SSIZE_MAX); + /* Read bytes until we have filled the buffer. */ while (buflen > 0) { - if ((lenread = read(fd, buf, buflen)) == -1) { + if ((lenread = read(er->fd, buf, buflen)) == -1) { warnp("read(/dev/urandom)"); - goto err1; + goto err0; } /* The random device should never EOF. */ if (lenread == 0) { warn0("EOF on /dev/urandom?"); - goto err1; + goto err0; } /* We've filled a portion of the buffer. */ @@ -58,19 +92,81 @@ buflen -= (size_t)lenread; } + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/** + * entropy_read_done(er): + * Release any resources used by {er}. + */ +int +entropy_read_done(struct entropy_read_cookie * er) +{ + + /* Sanity check. */ + assert(er != NULL); + /* Close the device. */ - while (close(fd) == -1) { + while (close(er->fd) == -1) { if (errno != EINTR) { warnp("close(/dev/urandom)"); - goto err0; + goto err1; } } + /* Clean up. */ + free(er); + + /* Success! */ + return (0); + +err1: + free(er); + + /* Failure! */ + return (-1); +} + +/** + * entropy_read(buf, buflen): + * Fill the given buffer with random bytes provided by the operating system. + */ +int +entropy_read(uint8_t * buf, size_t buflen) +{ + struct entropy_read_cookie * er; + + /* Sanity-check the buffer size. */ + assert(buflen <= SSIZE_MAX); + + /* Open /dev/urandom. */ + if ((er = entropy_read_init()) == NULL) { + warn0("entropy_read_init"); + goto err0; + } + + /* Read bytes until we have filled the buffer. */ + if (entropy_read_fill(er, buf, buflen)) { + warn0("entropy_read_fill"); + goto err1; + } + + /* Close the device. */ + if (entropy_read_done(er)) { + warn0("entropy_read_done"); + goto err0; + } + /* Success! */ return (0); err1: - close(fd); + entropy_read_done(er); err0: /* Failure! */ return (-1); diff -Nru spiped-1.6.1/libcperciva/util/entropy.h spiped-1.6.2/libcperciva/util/entropy.h --- spiped-1.6.1/libcperciva/util/entropy.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/entropy.h 2020-12-05 21:26:44.000000000 +0000 @@ -4,6 +4,29 @@ #include #include +/* Opaque type. */ +struct entropy_read_cookie; + +/** + * entropy_read_init(void): + * Initialize the ability to produce random bytes from the operating system, + * and return a cookie. + */ +struct entropy_read_cookie * entropy_read_init(void); + +/** + * entropy_read_fill(er, buf, buflen): + * Fill the given buffer with random bytes provided by the operating system + * using the resources in ${er}. + */ +int entropy_read_fill(struct entropy_read_cookie *, uint8_t *, size_t); + +/** + * entropy_read_done(er): + * Release any resources used by {er}. + */ +int entropy_read_done(struct entropy_read_cookie * er); + /** * entropy_read(buf, buflen): * Fill the given buffer with random bytes provided by the operating system. diff -Nru spiped-1.6.1/libcperciva/util/getopt.c spiped-1.6.2/libcperciva/util/getopt.c --- spiped-1.6.1/libcperciva/util/getopt.c 2018-10-14 23:26:03.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/getopt.c 2020-09-02 04:32:10.000000000 +0000 @@ -28,8 +28,8 @@ const char * os; size_t olen; int hasarg; -} * opts = NULL; -static size_t nopts; +} * opts = NULL; /* Probably a sparse array: some values, some NULLs. */ +static size_t nopts; /* Maximum number of options. */ static size_t opt_missing; static size_t opt_default; static size_t opt_found; @@ -336,8 +336,9 @@ opt_missing = ln; } +/* Prepare for the number of potential options. */ void -getopt_setrange(size_t ln) +getopt_setrange(size_t maxopts) { size_t i; @@ -348,18 +349,18 @@ /* We should only be called during initialization. */ assert(!getopt_initialized); - /* Allocate space for options. */ - opts = malloc(ln * sizeof(struct opt)); - if ((ln > 0) && (opts == NULL)) + /* Allocate space for (potential) options. */ + opts = malloc(maxopts * sizeof(struct opt)); + if ((maxopts > 0) && (opts == NULL)) DIE("Failed to allocate memory in getopt"); /* Initialize options. */ - for (i = 0; i < ln; i++) + for (i = 0; i < maxopts; i++) opts[i].os = NULL; /* Record the number of (potential) options. */ - nopts = ln; + nopts = maxopts; /* Record default missing-argument and no-such-option values. */ - opt_missing = opt_default = ln + 1; + opt_missing = opt_default = maxopts + 1; } diff -Nru spiped-1.6.1/libcperciva/util/getopt.h spiped-1.6.2/libcperciva/util/getopt.h --- spiped-1.6.1/libcperciva/util/getopt.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/getopt.h 2020-09-02 04:32:10.000000000 +0000 @@ -33,6 +33,18 @@ #ifdef __clang__ #warning Working around bug in LLVM optimizer #warning For more details see https://bugs.llvm.org/show_bug.cgi?id=27190 +#define GETOPT_USE_COMPUTED_GOTO +#endif + +/* Work around broken header on Solaris. */ +#if defined(__GNUC__) && (defined(sun) || defined(__sun)) +#warning Working around broken header on Solaris +#define GETOPT_USE_COMPUTED_GOTO +#endif + +/* Select the method of performing local jumps. */ +#ifdef GETOPT_USE_COMPUTED_GOTO +/* Workaround with computed goto. */ #define DO_SETJMP _DO_SETJMP(__LINE__) #define _DO_SETJMP(x) __DO_SETJMP(x) #define __DO_SETJMP(x) \ @@ -41,6 +53,7 @@ #define DO_LONGJMP \ goto *getopt_initloop #else +/* Intended code, for fully C99-compliant systems. */ #define DO_SETJMP \ sigjmp_buf getopt_initloop; \ if (!getopt_initialized) \ @@ -82,9 +95,9 @@ */ #define GETOPT_SWITCH(ch) \ volatile size_t getopt_ln_min = __LINE__; \ - volatile size_t getopt_ln = getopt_ln_min - 1; \ + volatile size_t getopt_ln = getopt_ln_min - 1; \ volatile int getopt_default_missing = 0; \ - DO_SETJMP; \ + DO_SETJMP; \ switch (getopt_initialized ? getopt_lookup(ch) + getopt_ln_min : getopt_ln++) /** diff -Nru spiped-1.6.1/libcperciva/util/monoclock.c spiped-1.6.2/libcperciva/util/monoclock.c --- spiped-1.6.1/libcperciva/util/monoclock.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/monoclock.c 2020-09-02 04:32:10.000000000 +0000 @@ -113,7 +113,7 @@ #ifdef USE_MONOTONIC if (clock_getres(CLOCK_MONOTONIC, &res) == 0) { /* Convert clock resolution to a double. */ - *resd = res.tv_sec + res.tv_nsec * 0.000000001; + *resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001; } else if ((errno != ENOSYS) && (errno != EINVAL)) { warnp("clock_getres(CLOCK_MONOTONIC)"); goto err0; @@ -122,7 +122,7 @@ #ifdef USE_REALTIME if (clock_getres(CLOCK_REALTIME, &res) == 0) { /* Convert clock resolution to a double. */ - *resd = res.tv_sec + res.tv_nsec * 0.000000001; + *resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001; } else { warnp("clock_getres(CLOCK_REALTIME)"); goto err0; diff -Nru spiped-1.6.1/libcperciva/util/monoclock.h spiped-1.6.2/libcperciva/util/monoclock.h --- spiped-1.6.1/libcperciva/util/monoclock.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/monoclock.h 2020-09-02 04:32:10.000000000 +0000 @@ -4,8 +4,8 @@ #include /* Macro to simplify benchmarks. */ -#define timeval_diff(x, y) ((y.tv_sec - x.tv_sec) + \ - (y.tv_usec - x.tv_usec) * 0.000001) +#define timeval_diff(x, y) ((double)(y.tv_sec - x.tv_sec) + \ + (double)(y.tv_usec - x.tv_usec) * 0.000001) /** * monoclock_get(tv): diff -Nru spiped-1.6.1/libcperciva/util/noeintr.c spiped-1.6.2/libcperciva/util/noeintr.c --- spiped-1.6.1/libcperciva/util/noeintr.c 2017-01-27 22:38:21.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/noeintr.c 2020-09-02 04:32:10.000000000 +0000 @@ -13,14 +13,14 @@ * a signal. Return ${nbytes} on success or -1 on error. */ ssize_t -noeintr_write(int d, const void * buf, size_t nbyte) +noeintr_write(int d, const void * buf, size_t nbytes) { const uint8_t * p = buf; - size_t len = nbyte; + size_t len = nbytes; ssize_t lenwrit; /* Implementation-defined: Don't allow oversized writes. */ - assert(nbyte <= SSIZE_MAX); + assert(nbytes <= SSIZE_MAX); /* Loop until we have no data left to write. */ while (len > 0) { @@ -46,7 +46,7 @@ } /* Success! */ - return (ssize_t)(nbyte); + return (ssize_t)(nbytes); err0: /* Failure! */ diff -Nru spiped-1.6.1/libcperciva/util/parsenum.h spiped-1.6.2/libcperciva/util/parsenum.h --- spiped-1.6.1/libcperciva/util/parsenum.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/parsenum.h 2020-09-02 04:32:10.000000000 +0000 @@ -114,24 +114,28 @@ " float with base != 0"), 1)) : \ (((*(x)) = -1) <= 0) ? \ ((*(x)) = parsenum_signed((s), \ - (*(x) <= 0) ? (min) : 0, \ - (*(x) <= 0) ? (max) : 0, (base), \ + ((*(x)) <= 0) ? (min) : 0, \ + ((*(x)) <= 0) ? (max) : 0, (base), \ (trailing))) : \ (((*(x)) = parsenum_unsigned((s), \ - (min) <= 0 ? 0 : (min), \ - (uintmax_t)(max), *(x), (base), \ + ((min) <= 0) ? 0 : (min), \ + (uintmax_t)(max), (*(x)), (base), \ (trailing))), \ - ((((max) < 0) && (errno == 0)) ? \ - (errno = ERANGE) : 0)), \ + (((max) <= INTMAX_MAX) ? \ + (((intmax_t)(max) < 0) && (errno == 0)) ? \ + (errno = ERANGE) : \ + 0 : 0)), \ errno != 0 \ PARSENUM_EPILOGUE \ ) /* Magic to select which version of PARSENUM_EX to use. */ -#define PARSENUM_EX(...) PARSENUM_EX_(PARSENUM_EX_COUNT(__VA_ARGS__))(__VA_ARGS__, "PARSENUM_EX") +#define PARSENUM_EX(...) \ + PARSENUM_EX_(PARSENUM_EX_COUNT(__VA_ARGS__))(__VA_ARGS__, "PARSENUM_EX") #define PARSENUM_EX_(N) PARSENUM_EX__(N) #define PARSENUM_EX__(N) PARSENUM_EX ## N -#define PARSENUM_EX_COUNT(...) PARSENUM_EX_COUNT_(__VA_ARGS__, 6, 5, 4, 3, 2, 1) +#define PARSENUM_EX_COUNT(...) \ + PARSENUM_EX_COUNT_(__VA_ARGS__, 6, 5, 4, 3, 2, 1) #define PARSENUM_EX_COUNT_(_1, _2, _3, _4, _5, _6, N, ...) N /* Functions for performing the parsing and parameter checking. */ @@ -141,6 +145,9 @@ char * eptr; double val; + /* Sanity check. */ + assert(s != NULL); + val = strtod(s, &eptr); if (eptr == s || (!trailing && (*eptr != '\0'))) errno = EINVAL; @@ -156,6 +163,9 @@ char * eptr; intmax_t val; + /* Sanity check. */ + assert(s != NULL); + val = strtoimax(s, &eptr, base); if (eptr == s || (!trailing && (*eptr != '\0'))) errno = EINVAL; @@ -173,6 +183,9 @@ char * eptr; uintmax_t val; + /* Sanity check. */ + assert(s != NULL); + val = strtoumax(s, &eptr, base); if (eptr == s || (!trailing && (*eptr != '\0'))) errno = EINVAL; diff -Nru spiped-1.6.1/libcperciva/util/perftest.c spiped-1.6.2/libcperciva/util/perftest.c --- spiped-1.6.1/libcperciva/util/perftest.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/perftest.c 2021-08-01 23:41:28.000000000 +0000 @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include + +#include "monoclock.h" +#include "warnp.h" + +#include "perftest.h" + +/** + * perftest_buffers(nbytes, sizes, nsizes, nbytes_warmup, cputime, + * init_func, func, clean_func, cookie): + * Time using ${func} to process ${nbytes} bytes in blocks of ${sizes}. + * Before timing any block sizes, process ${nbytes_warmup} bytes with the + * maximum size in ${sizes}. If ${cputime} is non-zero, attempt to use + * cpu time rather than wall-clock time. Invoke callback functions as: + * init_func(cookie, buffer, buflen) + * func(cookie, buffer, buflen, nbuffers) + * clean_func(cookie) + * where ${buffer} is large enough to hold the maximum buffer size. Print + * the time and speed of processing each buffer size. ${init_func} and + * ${clean_func} may be NULL. If ${init_func} has completed successfully, + * then ${clean_func} will be called if there is a subsequent error. + */ +int +perftest_buffers(size_t nbytes, const size_t * sizes, size_t nsizes, + size_t nbytes_warmup, int cputime, + int init_func(void * cookie, uint8_t * buf, size_t buflen), + int func(void * cookie, uint8_t * buf, size_t buflen, size_t num_buffers), + int clean_func(void * cookie), void * cookie) +{ + uint8_t * buf; + struct timeval begin, end; + double * delta_s; + double speed; + size_t i; + size_t buflen; + size_t num_buffers; + size_t nbuffers_warmup; + size_t nbytes_in_buffer; + size_t max_buflen = 0; + + /* Find the maximum buffer size. */ + for (i = 0; i < nsizes; i++) { + if (max_buflen < sizes[i]) + max_buflen = sizes[i]; + } + assert(max_buflen > 0); + + /* Allocate buffers. */ + if ((buf = malloc(max_buflen)) == NULL) { + warnp("malloc"); + goto err0; + } + if ((delta_s = malloc(nsizes * sizeof(double))) == NULL) { + warnp("malloc"); + goto err1; + } + + /* Warm up. */ + nbuffers_warmup = nbytes_warmup / max_buflen; + if (init_func && init_func(cookie, buf, max_buflen)) + goto err2; + if (func(cookie, buf, max_buflen, nbuffers_warmup)) + goto err3; + if (clean_func && clean_func(cookie)) + goto err2; + + /* Run operations. */ + for (i = 0; i < nsizes; i++) { + /* Configure and sanity checks. */ + buflen = sizes[i]; + assert(buflen > 0); + num_buffers = nbytes / buflen; + + /* Set up. */ + if (init_func && init_func(cookie, buf, buflen)) + goto err2; + + /* Get beginning time. */ + if (cputime) { + if (monoclock_get_cputime(&begin)) { + warnp("monoclock_get_cputime()"); + goto err3; + } + } else { + if (monoclock_get(&begin)) { + warnp("monoclock_get()"); + goto err3; + } + } + + /* Time actual code. */ + if (func(cookie, buf, buflen, num_buffers)) + goto err3; + + /* Get ending time. */ + if (cputime) { + if (monoclock_get_cputime(&end)) { + warnp("monoclock_get_cputime()"); + goto err3; + } + } else { + if (monoclock_get(&end)) { + warnp("monoclock_get()"); + goto err3; + } + } + + /* Store time. */ + delta_s[i] = timeval_diff(begin, end); + + /* Clean up. */ + if (clean_func && clean_func(cookie)) + goto err2; + } + + /* Print output. */ + for (i = 0; i < nsizes; i++) { + buflen = sizes[i]; + num_buffers = nbytes / buflen; + + /* We might not be processing an integer number of buffers. */ + nbytes_in_buffer = buflen * num_buffers; + speed = (double)nbytes_in_buffer / 1e6 / delta_s[i]; + + /* Print output. */ + printf("%zu blocks of size %zu\t%.06f s\t%.06f MB/s\n", + num_buffers, buflen, delta_s[i], speed); + } + + /* Clean up. */ + free(delta_s); + free(buf); + + /* Success! */ + return (0); + +err3: + if (clean_func) + clean_func(cookie); +err2: + free(delta_s); +err1: + free(buf); +err0: + /* Failure! */ + return (-1); +} diff -Nru spiped-1.6.1/libcperciva/util/perftest.h spiped-1.6.2/libcperciva/util/perftest.h --- spiped-1.6.1/libcperciva/util/perftest.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/perftest.h 2021-08-01 23:41:28.000000000 +0000 @@ -0,0 +1,27 @@ +#ifndef _PERFTESTS_H_ +#define _PERFTESTS_H_ + +#include +#include + +/** + * perftest_buffers(nbytes, sizes, nsizes, nbytes_warmup, cputime, + * init_func, func, clean_func, cookie): + * Time using ${func} to process ${nbytes} bytes in blocks of ${sizes}. + * Before timing any block sizes, process ${nbytes_warmup} bytes with the + * maximum size in ${sizes}. If ${cputime} is non-zero, attempt to use + * cpu time rather than wall-clock time. Invoke callback functions as: + * init_func(cookie, buffer, buflen) + * func(cookie, buffer, buflen, nbuffers) + * clean_func(cookie) + * where ${buffer} is large enough to hold the maximum buffer size. Print + * the time and speed of processing each buffer size. ${init_func} and + * ${clean_func} may be NULL. If ${init_func} has completed successfully, + * then ${clean_func} will be called if there is a subsequent error. + */ +int perftest_buffers(size_t, const size_t *, size_t, size_t, int, + int (*)(void *, uint8_t *, size_t), + int (*)(void *, uint8_t *, size_t, size_t), + int (*)(void *), void *); + +#endif /* !_PERFTESTS_H_ */ diff -Nru spiped-1.6.1/libcperciva/util/setgroups_none.c spiped-1.6.2/libcperciva/util/setgroups_none.c --- spiped-1.6.1/libcperciva/util/setgroups_none.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/setgroups_none.c 2020-12-05 21:26:44.000000000 +0000 @@ -0,0 +1,60 @@ +/* We use non-POSIX functionality in this file. */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +/* + * There is no setgroups() in the POSIX standard, so if we want to drop + * supplementary groups, we need to use platform-specific code. This must + * happen before the regular includes, as in some cases we need to define other + * symbols before including the relevant header. + */ +#if defined(__linux__) +/* setgroups() includes for Linux. */ +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 + +#include + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) +/* setgroups() includes for FreeBSD, NetBSD, MacOS X. */ +#include +#include + +#elif defined(__OpenBSD__) || defined(__osf__) +/* setgroups() includes for OpenBSD. */ +#include +#include + +#elif defined(__sun) || defined(__hpux) +/* setgroups() includes for Solaris. */ +#include + +#elif defined(_AIX) +/* setgroups() includes for AIX. */ +#include + +#else +/* Unknown OS; we don't know how to get setgroups(). */ +#define NO_SETGROUPS + +#endif /* end includes for setgroups() */ + +#include + +#include "setgroups_none.h" + +/** + * setgroups_none(void): + * Attempt to leave all supplementary groups. If we do not know how to do this + * on the platform, return 0 anyway. + */ +int +setgroups_none(void) +{ + +#ifdef NO_SETGROUPS + return (0); +#else + return (setgroups(0, NULL)); +#endif +} diff -Nru spiped-1.6.1/libcperciva/util/setgroups_none.h spiped-1.6.2/libcperciva/util/setgroups_none.h --- spiped-1.6.1/libcperciva/util/setgroups_none.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/setgroups_none.h 2020-12-05 21:26:44.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef _SETGROUPS_NONE_H_ +#define _SETGROUPS_NONE_H_ + +/** + * setgroups_none(void): + * Attempt to leave all supplementary groups. If we do not know how to do this + * on the platform, return 0 anyway. + */ +int setgroups_none(void); + +#endif /* !_SETGROUPS_NONE_H_ */ diff -Nru spiped-1.6.1/libcperciva/util/setuidgid.c spiped-1.6.2/libcperciva/util/setuidgid.c --- spiped-1.6.1/libcperciva/util/setuidgid.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/setuidgid.c 2021-07-04 18:08:39.000000000 +0000 @@ -1,44 +1,3 @@ -/* We use non-POSIX functionality in this file. */ -#undef _POSIX_C_SOURCE -#undef _XOPEN_SOURCE - -/* - * There is no setgroups() in the POSIX standard, so if we want to drop - * supplementary groups, we need to use platform-specific code. This must - * happen before the regular includes, as in some cases we need to define other - * symbols before including the relevant header. - */ -#if defined(__linux__) -/* setgroups() includes for Linux. */ -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 - -#include - -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) -/* setgroups() includes for FreeBSD, NetBSD, MacOS X. */ -#include -#include - -#elif defined(__OpenBSD__) || defined(__osf__) -/* setgroups() includes for OpenBSD. */ -#include -#include - -#elif defined(__sun) || defined(__hpux) -/* setgroups() includes for Solaris. */ -#include - -#elif defined(_AIX) -/* setgroups() includes for AIX. */ -#include - -#else -/* Unknown OS; we don't know how to get setgroups(). */ -#define NO_SETGROUPS - -#endif /* end includes for setgroups() */ - #include #include #include @@ -49,12 +8,12 @@ #include #include "parsenum.h" +#include "setgroups_none.h" #include "warnp.h" #include "setuidgid.h" /* Function prototypes related to supplementary groups. */ -static int setgroups_none(void); static int check_supplementary_groups_none(void); /* Function prototypes related to uid and gid. */ @@ -62,32 +21,6 @@ static int set_user(const char *); static int string_extract_user_group(const char *, char **, char **); -/** - * setgroups_none(void): - * Attempt to leave all supplementary groups. If we do not know how to do this - * on the platform, return 0 anyway. - */ -static int -setgroups_none(void) -{ - -#ifndef NO_SETGROUPS - if (setgroups(0, NULL)) { - /* We handle EPERM separately; keep it in errno. */ - if (errno != EPERM) - warnp("setgroups()"); - goto err0; - } -#endif - - /* Success! */ - return (0); - -err0: - /* Failure! */ - return (-1); -} - /* Check if we're in any supplementary groups. */ static int check_supplementary_groups_none(void) @@ -144,7 +77,7 @@ if ((group_info = getgrnam(groupname)) != NULL) { gid = group_info->gr_gid; } else if (errno) { - warnp("getgrnam(\"%s\")", groupname); + warnp("getgrnam(%s)", groupname); goto err0; } else if (PARSENUM(&gid, groupname)) { warn0("No such group: %s", groupname); @@ -179,7 +112,7 @@ if ((user_info = getpwnam(username)) != NULL) { uid = user_info->pw_uid; } else if (errno) { - warnp("getpwnam(\"%s\")", username); + warnp("getpwnam(%s)", username); goto err0; } else if (PARSENUM(&uid, username)) { warn0("No such user: %s", username); @@ -207,58 +140,62 @@ string_extract_user_group(const char * combined, char ** username_p, char ** groupname_p) { - size_t pos; - size_t len; + const char * s; + size_t username_len; /* Sanity check. */ assert(combined != NULL); - /* Search for ":" and get string length. */ - pos = strcspn(combined, ":"); - len = strlen(combined); - - /* Reject silly strings. */ - if (pos == len - 1) { - warn0("Empty group name: %s", combined); - goto err0; - } - - /* String ok, proceed. */ - if (pos == 0) { - /* Groupname only; duplicate string. */ - if ((*groupname_p = strdup(&combined[1])) == NULL) { - warnp("strdup()"); + /* If there's a ':', what follows is the group name. */ + if ((s = strchr(combined, ':')) != NULL) { + /* Duplicate the group name. */ + if ((*groupname_p = strdup(&s[1])) == NULL) { + warnp("strdup"); goto err0; } - *username_p = NULL; - } else if (pos != len) { - /* Extract username. */ - if ((*username_p = malloc(pos + 1)) == NULL) { - warnp("Failed to allocate memory"); - goto err0; - } - memcpy(*username_p, combined, pos); - (*username_p)[pos] = '\0'; + } else { + /* No group name. */ + *groupname_p = NULL; + + /* User name includes everything prior to terminating NUL. */ + s = &combined[strlen(combined)]; + } - /* Extract groupname. */ - if ((*groupname_p = strdup(&combined[pos + 1])) == NULL) { - warnp("strdup()"); + /* Anything prior to the ':' or terminating NUL is the user name. */ + if (s > combined) { + username_len = (size_t)(s - combined); + + /* Duplicate the user name. */ + if ((*username_p = malloc(username_len + 1)) == NULL) { + warnp("malloc"); goto err1; } + memcpy(*username_p, combined, username_len); + (*username_p)[username_len] = '\0'; } else { - /* Duplicate string. */ - if ((*username_p = strdup(combined)) == NULL) { - warnp("strdup()"); - goto err0; - } - *groupname_p = NULL; + /* No user name. */ + *username_p = NULL; + } + + /* Reject empty group names. */ + if ((*groupname_p != NULL) && (strlen(*groupname_p) == 0)) { + warn0("Empty group name: \"%s\"", combined); + goto err2; + } + + /* Reject strings with neither user nor group. */ + if ((*groupname_p == NULL) && (*username_p == NULL)) { + warn0("Need to specify user and/or group: \"%s\"", combined); + goto err2; } /* Success! */ return (0); -err1: +err2: free(*username_p); +err1: + free(*groupname_p); err0: /* Failure! */ return (-1); @@ -296,6 +233,12 @@ if (leave_suppgrp != SETUIDGID_SGROUP_IGNORE) { /* Attempt to leave all supplementary groups. */ if (setgroups_none()) { + if (errno != EPERM) { + warnp("setgroups()"); + goto err1; + } + + /* We handle EPERM separately; keep it in errno. */ if (leave_suppgrp == SETUIDGID_SGROUP_LEAVE_ERROR) goto err1; } @@ -305,10 +248,10 @@ if (leave_suppgrp == SETUIDGID_SGROUP_LEAVE_ERROR) { warn0("Failed to leave supplementary groups"); goto err1; - } else { - warn0("Warning: Failed to leave supplementary " - "groups"); } + + /* Print warning, but don't indicate an error. */ + warn0("Warning: Failed to leave supplementary groups"); } } diff -Nru spiped-1.6.1/libcperciva/util/sock.c spiped-1.6.2/libcperciva/util/sock.c --- spiped-1.6.1/libcperciva/util/sock.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/sock.c 2021-12-17 17:16:26.000000000 +0000 @@ -295,8 +295,8 @@ /** * sock_listener(sa): - * Create a socket, set SO_REUSEADDR, bind it to the socket address ${sa}, - * mark it for listening, and mark it as non-blocking. + * Create a socket, attempt to set SO_REUSEADDR, bind it to the socket address + * ${sa}, mark it for listening, and mark it as non-blocking. */ int sock_listener(const struct sock_addr * sa) @@ -310,10 +310,13 @@ goto err0; } - /* Set SO_REUSEADDR. */ + /* Attempt to set SO_REUSEADDR. */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { - warnp("setsockopt(SO_REUSEADDR)"); - goto err1; + /* ENOPROTOOPT is ok. */ + if (errno != ENOPROTOOPT) { + warnp("setsockopt(SO_REUSEADDR)"); + goto err1; + } } /* Bind the socket. */ diff -Nru spiped-1.6.1/libcperciva/util/sock.h spiped-1.6.2/libcperciva/util/sock.h --- spiped-1.6.1/libcperciva/util/sock.h 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/sock.h 2021-12-17 17:16:26.000000000 +0000 @@ -20,8 +20,8 @@ /** * sock_listener(sa): - * Create a socket, set SO_REUSEADDR, bind it to the socket address ${sa}, - * mark it for listening, and mark it as non-blocking. + * Create a socket, attempt to set SO_REUSEADDR, bind it to the socket address + * ${sa}, mark it for listening, and mark it as non-blocking. */ int sock_listener(const struct sock_addr *); diff -Nru spiped-1.6.1/libcperciva/util/sock_util.c spiped-1.6.2/libcperciva/util/sock_util.c --- spiped-1.6.1/libcperciva/util/sock_util.c 2015-10-26 23:29:47.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/sock_util.c 2020-09-02 04:32:10.000000000 +0000 @@ -14,6 +14,13 @@ #include "sock_internal.h" #include "sock_util.h" +#ifdef POSIXFAIL_INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif +#ifdef POSIXFAIL_INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + /** * sock_addr_cmp(sa1, sa2): * Return non-zero iff the socket addresses ${sa1} and ${sa2} are different. diff -Nru spiped-1.6.1/libcperciva/util/sysendian.h spiped-1.6.2/libcperciva/util/sysendian.h --- spiped-1.6.1/libcperciva/util/sysendian.h 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/sysendian.h 2021-02-22 04:15:07.000000000 +0000 @@ -22,7 +22,7 @@ { const uint8_t * p = (uint8_t const *)pp; - return (uint16_t)((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8)); + return (uint16_t)((uint16_t)(p[1]) | ((uint16_t)(p[0]) << 8)); } static inline void @@ -39,8 +39,8 @@ { const uint8_t * p = (uint8_t const *)pp; - return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + - ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); + return ((uint32_t)(p[3]) | ((uint32_t)(p[2]) << 8) | + ((uint32_t)(p[1]) << 16) | ((uint32_t)(p[0]) << 24)); } static inline void @@ -59,10 +59,10 @@ { const uint8_t * p = (uint8_t const *)pp; - return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + - ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + - ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + - ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); + return ((uint64_t)(p[7]) | ((uint64_t)(p[6]) << 8) | + ((uint64_t)(p[5]) << 16) | ((uint64_t)(p[4]) << 24) | + ((uint64_t)(p[3]) << 32) | ((uint64_t)(p[2]) << 40) | + ((uint64_t)(p[1]) << 48) | ((uint64_t)(p[0]) << 56)); } static inline void @@ -85,7 +85,7 @@ { const uint8_t * p = (uint8_t const *)pp; - return (uint16_t)((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8)); + return (uint16_t)((uint16_t)(p[0]) | ((uint16_t)(p[1]) << 8)); } static inline void @@ -102,8 +102,8 @@ { const uint8_t * p = (uint8_t const *)pp; - return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + - ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); + return ((uint32_t)(p[0]) | ((uint32_t)(p[1]) << 8) | + ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24)); } static inline void @@ -122,10 +122,10 @@ { const uint8_t * p = (uint8_t const *)pp; - return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + - ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + - ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + - ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); + return ((uint64_t)(p[0]) | ((uint64_t)(p[1]) << 8) | + ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | + ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | + ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56)); } static inline void diff -Nru spiped-1.6.1/libcperciva/util/warnp.c spiped-1.6.2/libcperciva/util/warnp.c --- spiped-1.6.1/libcperciva/util/warnp.c 2015-05-25 07:07:28.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/warnp.c 2020-09-02 04:32:10.000000000 +0000 @@ -3,17 +3,24 @@ #include #include #include +#include #include "warnp.h" static int initialized = 0; static char * name = NULL; +static int use_syslog = 0; +static int syslog_priority = LOG_WARNING; -/* Free the name string. */ +/* Free the name string and clean up writing to the syslog (if applicable). */ static void done(void) { + /* Clean up writing to the syslog (if applicable). */ + if (use_syslog) + closelog(); + free(name); name = NULL; } @@ -49,14 +56,33 @@ warn(const char * fmt, ...) { va_list ap; + char msgbuf[WARNP_SYSLOG_MAX_LINE + 1]; va_start(ap, fmt); - fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); - if (fmt != NULL) { - fprintf(stderr, ": "); - vfprintf(stderr, fmt, ap); + if (use_syslog == 0) { + /* Stop other threads writing to stderr. */ + flockfile(stderr); + + /* Print to stderr. */ + fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); + if (fmt != NULL) { + fprintf(stderr, ": "); + vfprintf(stderr, fmt, ap); + } + fprintf(stderr, ": %s\n", strerror(errno)); + + /* Allow other threads to write to stderr. */ + funlockfile(stderr); + } else { + /* Print to syslog. */ + if (fmt != NULL) { + /* No need to print "${name}: "; syslog does it. */ + vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap); + syslog(syslog_priority, "%s: %s\n", msgbuf, + strerror(errno)); + } else + syslog(syslog_priority, "%s\n", strerror(errno)); } - fprintf(stderr, ": %s\n", strerror(errno)); va_end(ap); } @@ -64,13 +90,59 @@ warnx(const char * fmt, ...) { va_list ap; + char msgbuf[WARNP_SYSLOG_MAX_LINE + 1]; va_start(ap, fmt); - fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); - if (fmt != NULL) { - fprintf(stderr, ": "); - vfprintf(stderr, fmt, ap); + if (use_syslog == 0) { + /* Stop other threads writing to stderr. */ + flockfile(stderr); + + /* Print to stderr. */ + fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); + if (fmt != NULL) { + fprintf(stderr, ": "); + vfprintf(stderr, fmt, ap); + } + fprintf(stderr, "\n"); + + /* Allow other threads to write to stderr. */ + funlockfile(stderr); + } else { + /* Print to syslog. */ + if (fmt != NULL) { + /* No need to print "${name}: "; syslog does it. */ + vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap); + syslog(syslog_priority, "%s\n", msgbuf); + } else + syslog(syslog_priority, "\n"); } - fprintf(stderr, "\n"); va_end(ap); } + +/** + * warnp_syslog(enable): + * Send future messages to syslog if ${enable} is non-zero. Messages to + * syslog will be truncated at WARNP_SYSLOG_MAX_LINE characters. + */ +void +warnp_syslog(int enable) +{ + + /* Clean up writing to the syslog (if applicable). */ + if (use_syslog && !enable) + closelog(); + + use_syslog = enable; +} + +/** + * warnp_syslog_priority(priority): + * Tag future syslog messages with priority ${priority}. Do not enable + * syslog messages; for that, use warnp_syslog(). + */ +void +warnp_syslog_priority(int priority) +{ + + syslog_priority = priority; +} diff -Nru spiped-1.6.1/libcperciva/util/warnp.h spiped-1.6.2/libcperciva/util/warnp.h --- spiped-1.6.1/libcperciva/util/warnp.h 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/libcperciva/util/warnp.h 2020-09-02 04:32:10.000000000 +0000 @@ -8,6 +8,12 @@ #define warn libcperciva_warn #define warnx libcperciva_warnx +/* + * Maximum length of messages sent to syslog; longer warnings will + * be truncated. + */ +#define WARNP_SYSLOG_MAX_LINE 4095 + /** * warnp_setprogname(progname): * Set the program name to be used by warn() and warnx() to ${progname}. @@ -18,6 +24,20 @@ warnp_setprogname(argv[0]); \ } while (0) +/** + * warnp_syslog(enable): + * Send future messages to syslog if ${enable} is non-zero. Messages to + * syslog will be truncated at WARNP_SYSLOG_MAX_LINE characters. + */ +void warnp_syslog(int); + +/** + * warnp_syslog_priority(priority): + * Tag future syslog messages with priority ${priority}. Do not enable + * syslog messages; for that, use warnp_syslog(). + */ +void warnp_syslog_priority(int); + /* As in BSD . */ void warn(const char *, ...); void warnx(const char *, ...); @@ -47,7 +67,7 @@ } while (0) /* - * Call warnx(3) and set errno == 0. Unlike warnp, this should be used + * Call warnx(3) and set errno == 0. Unlike warnp(), this should be used * in cases where we're reporting a problem which we discover ourselves * rather than one which is reported to us from a library or the kernel. */ diff -Nru spiped-1.6.1/Makefile spiped-1.6.2/Makefile --- spiped-1.6.1/Makefile 2019-12-22 02:38:52.000000000 +0000 +++ spiped-1.6.2/Makefile 2021-12-17 17:16:26.000000000 +0000 @@ -1,9 +1,16 @@ .POSIX: -PROGS= spiped spipe -TESTS= tests/dnsthread-resolve tests/nc-client tests/nc-server \ - tests/pushbits tests/valgrind \ - perftests/recv-zeros perftests/send-zeros +PROGS= spipe \ + spiped +TESTS= perftests/recv-zeros \ + perftests/send-zeros \ + perftests/standalone-enc \ + tests/dnsthread-resolve \ + tests/nc-client \ + tests/nc-server \ + tests/pthread_create_blocking_np \ + tests/pushbits \ + tests/valgrind BINDIR_DEFAULT= /usr/local/bin CFLAGS_DEFAULT= -O2 LIBCPERCIVA_DIR= libcperciva @@ -11,7 +18,7 @@ ### Shared code between Tarsnap projects. -all: cflags-filter.sh cpusupport-config.h posix-flags.sh +all: toplevel export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \ . ./posix-flags.sh; \ . ./cpusupport-config.h; \ @@ -21,14 +28,27 @@ ( cd $${D} && ${MAKE} all ) || exit 2; \ done +.PHONY: toplevel +toplevel: cflags-filter.sh cpusupport-config.h \ + liball posix-flags.sh + # For "loop-back" building of a subdirectory -buildsubdir: cflags-filter.sh cpusupport-config.h posix-flags.sh +buildsubdir: toplevel . ./posix-flags.sh; \ . ./cpusupport-config.h; \ . ./cflags-filter.sh; \ export HAVE_BUILD_FLAGS=1; \ cd ${BUILD_SUBDIR} && ${MAKE} ${BUILD_TARGET} +# For "loop-back" building of the library +.PHONY: liball +liball: cflags-filter.sh cpusupport-config.h posix-flags.sh + . ./posix-flags.sh; \ + . ./cpusupport-config.h; \ + . ./cflags-filter.sh; \ + export HAVE_BUILD_FLAGS=1; \ + ( cd liball && make all ) || exit 2; + posix-flags.sh: if [ -d ${LIBCPERCIVA_DIR}/POSIX/ ]; then \ export CC="${CC}"; \ @@ -72,9 +92,9 @@ ( cd $${D} && ${MAKE} install ) || exit 2; \ done -clean: +clean: test-clean rm -f cflags-filter.sh cpusupport-config.h posix-flags.sh - for D in ${PROGS} ${TESTS}; do \ + for D in liball ${PROGS} ${TESTS}; do \ ( cd $${D} && ${MAKE} clean ) || exit 2; \ done diff -Nru spiped-1.6.1/perftests/recv-zeros/main.c spiped-1.6.2/perftests/recv-zeros/main.c --- spiped-1.6.1/perftests/recv-zeros/main.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/perftests/recv-zeros/main.c 2020-12-05 21:26:44.000000000 +0000 @@ -62,7 +62,7 @@ goto err3; } - /* Accept connections. */ + /* Accept a connection. */ if ((socket_recv = accept(socket, NULL, NULL)) == -1) { warnp("accept"); goto err3; @@ -77,11 +77,13 @@ goto err4; } - /* Clean up. */ + /* Close the connection. */ if (close(socket_recv)) { warnp("close"); goto err3; } + + /* Clean up. */ if (close(socket)) { warnp("close"); goto err2; diff -Nru spiped-1.6.1/perftests/recv-zeros/Makefile spiped-1.6.2/perftests/recv-zeros/Makefile --- spiped-1.6.1/perftests/recv-zeros/Makefile 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/perftests/recv-zeros/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -1,10 +1,11 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=recv-zeros -SRCS=main.c monoclock.c sock.c warnp.c +SRCS=main.c IDIRS=-I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=perftests/recv-zeros +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -18,14 +19,8 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ../../libcperciva/util/parsenum.h ../../libcperciva/util/sock.h ../../libcperciva/util/warnp.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -monoclock.o: ../../libcperciva/util/monoclock.c ../../libcperciva/util/warnp.h ../../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/monoclock.c -o monoclock.o -sock.o: ../../libcperciva/util/sock.c ../../libcperciva/util/imalloc.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock.c -o sock.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o diff -Nru spiped-1.6.1/perftests/send-zeros/main.c spiped-1.6.2/perftests/send-zeros/main.c --- spiped-1.6.1/perftests/send-zeros/main.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/perftests/send-zeros/main.c 2020-09-02 04:32:10.000000000 +0000 @@ -125,7 +125,7 @@ /* Print duration and speed. */ duration_s = timeval_diff(begin, end); printf("%zu\t%zu\t%.4f\t%.2f\n", buflen, count, duration_s, - buflen * count / duration_s / 1e6); + (double)(buflen * count) / duration_s / 1e6); /* Clean up. */ if (close(socket)) { diff -Nru spiped-1.6.1/perftests/send-zeros/Makefile spiped-1.6.2/perftests/send-zeros/Makefile --- spiped-1.6.1/perftests/send-zeros/Makefile 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/perftests/send-zeros/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -1,10 +1,11 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=send-zeros -SRCS=main.c monoclock.c sock.c warnp.c +SRCS=main.c IDIRS=-I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=perftests/send-zeros +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -18,14 +19,8 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ../../libcperciva/util/monoclock.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/sock.h ../../libcperciva/util/warnp.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -monoclock.o: ../../libcperciva/util/monoclock.c ../../libcperciva/util/warnp.h ../../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/monoclock.c -o monoclock.o -sock.o: ../../libcperciva/util/sock.c ../../libcperciva/util/imalloc.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock.c -o sock.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o diff -Nru spiped-1.6.1/perftests/standalone-enc/main.c spiped-1.6.2/perftests/standalone-enc/main.c --- spiped-1.6.1/perftests/standalone-enc/main.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/perftests/standalone-enc/main.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,627 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "cpusupport.h" +#include "crypto_aes.h" +#include "crypto_aesctr.h" +#include "events.h" +#include "noeintr.h" +#include "parsenum.h" +#include "perftest.h" +#include "proto_crypt.h" +#include "proto_pipe.h" +#include "pthread_create_blocking_np.h" +#include "sha256.h" +#include "sysendian.h" +#include "warnp.h" + +/* The smallest this can be is PCRYPT_ESZ (which is 1060). */ +#define MAXOUTSIZE 16384 + +/* Smaller buffers are padded, so no point testing smaller values. */ +static const size_t perfsizes[] = {1024}; +static const size_t num_perf = sizeof(perfsizes) / sizeof(perfsizes[0]); +static const size_t nbytes_perftest = 100000000; /* 100 MB */ +static const size_t nbytes_warmup = 10000000; /* 10 MB */ + +/* Print a string, then whether or not we're using hardware instructions. */ +static void +print_hardware(const char * str) +{ + + /* Inform the user of the general topic... */ + printf("%s", str); + + /* ... and whether we're using hardware acceleration or not. */ +#if defined(CPUSUPPORT_CONFIG_FILE) +#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) + if (cpusupport_x86_shani() && cpusupport_x86_ssse3()) + printf(" using hardware SHANI"); + else +#endif +#if defined(CPUSUPPORT_X86_SSE2) + if (cpusupport_x86_sse2()) + printf(" using hardware SSE2"); + else +#endif +#if defined(CPUSUPPORT_ARM_SHA256) + if (cpusupport_arm_sha256()) + printf(" using hardware SHA256"); + else +#endif + printf(" using software SHA"); + +#if defined(CPUSUPPORT_X86_AESNI) + if (cpusupport_x86_aesni()) + printf(" and hardware AESNI.\n"); + else +#endif + printf(" and software AES.\n"); +#else + printf(" with unknown hardware acceleration status.\n"); +#endif /* CPUSUPPORT_CONFIG_FILE */ +} + +static int +hmac_init(void * cookie, uint8_t * buf, size_t buflen) +{ + HMAC_SHA256_CTX * ctx = cookie; + uint8_t kbuf[32]; + size_t i; + + /* (Re-)Initialize the context. */ + memset(kbuf, 0, 32); + HMAC_SHA256_Init(ctx, kbuf, 32); + + /* Set the input. */ + for (i = 0; i < buflen; i++) + buf[i] = (uint8_t)(i & 0xff); + + /* Success! */ + return (0); +} + +static int +hmac_func(void * cookie, uint8_t * buf, size_t buflen, size_t nreps) +{ + HMAC_SHA256_CTX * ctx = cookie; + uint8_t hbuf[32]; + uint8_t pnum_exp[8]; + size_t i; + + /* Do the hashing. */ + for (i = 0; i < nreps; i++) { + HMAC_SHA256_Update(ctx, buf, buflen); + + /* Hash the iteration number as well. */ + be64enc(pnum_exp, i); + HMAC_SHA256_Update(ctx, pnum_exp, 8); + } + HMAC_SHA256_Final(hbuf, ctx); + + /* Success! */ + return (0); +} + +static int +hmac_perftest(void) +{ + HMAC_SHA256_CTX ctx; + + /* Report what we're doing. */ + printf("Testing HMAC_SHA256 with iteration numbers\n"); + + /* Time the function. */ + if (perftest_buffers(nbytes_perftest, perfsizes, num_perf, + nbytes_warmup, 0, hmac_init, hmac_func, NULL, &ctx)) { + warn0("perftest_buffers"); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +} + +static int +aesctr_init(void * cookie, uint8_t * buf, size_t buflen) +{ + size_t i; + + (void)cookie; /* UNUSED */ + + /* Set the input. */ + for (i = 0; i < buflen; i++) + buf[i] = (uint8_t)(i & 0xff); + + /* Success! */ + return (0); +} + +static int +aesctr_func(void * cookie, uint8_t * buf, size_t buflen, size_t nreps) +{ + struct crypto_aes_key * k_aes = cookie; + size_t i; + + /* Do the hashing. */ + for (i = 0; i < nreps; i++) { + /* + * In proto_crypt_enc(), we would append the length to buf, + * then encrypt the buffer + 4 bytes of length. For + * simplicity, this test does not imitate that details. + */ + crypto_aesctr_buf(k_aes, i, buf, buf, buflen); + } + + /* Success! */ + return (0); +} + +static int +aesctr_perftest(void) +{ + struct crypto_aes_key * k_aes; + uint8_t kbuf[32]; + + /* Report what we're doing. */ + printf("Testing AES-CTR\n"); + + /* Initialize. */ + memset(kbuf, 0, 32); + if ((k_aes = crypto_aes_key_expand(kbuf, 32)) == NULL) + goto err0; + + /* Time the function. */ + if (perftest_buffers(nbytes_perftest, perfsizes, num_perf, + nbytes_warmup, 0, aesctr_init, aesctr_func, NULL, k_aes)) { + warn0("perftest_buffers"); + goto err0; + } + + /* Clean up. */ + crypto_aes_key_free(k_aes); + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +} + +/* Cookie for HMAC_SHA256 with crypto_aesctr. */ +struct aesctr_hmac_cookie { + HMAC_SHA256_CTX * ctx; + struct crypto_aes_key * k_aes; +}; + +static int +aesctr_hmac_init(void * cookie, uint8_t * buf, size_t buflen) +{ + struct aesctr_hmac_cookie * ahc = cookie; + uint8_t kbuf[32]; + size_t i; + + /* (Re-)Initialize the context. */ + memset(kbuf, 0, 32); + HMAC_SHA256_Init(ahc->ctx, kbuf, 32); + + /* Set the input. */ + for (i = 0; i < buflen; i++) + buf[i] = (uint8_t)(i & 0xff); + + /* Success! */ + return (0); +} + +static int +aesctr_hmac_func(void * cookie, uint8_t * buf, size_t buflen, size_t nreps) +{ + struct aesctr_hmac_cookie * ahc = cookie; + uint8_t hbuf[32]; + uint8_t pnum_exp[8]; + size_t i; + + /* Do the hashing. */ + for (i = 0; i < nreps; i++) { + /* + * In proto_crypt_enc(), we would append the length to buf, + * then encrypt the buffer + 4 bytes of length. After that, + * we'd hash the resulting (larger) buffer. For simplicity, + * this test does not imitate those details. + */ + crypto_aesctr_buf(ahc->k_aes, i, buf, buf, buflen); + HMAC_SHA256_Update(ahc->ctx, buf, buflen); + be64enc(pnum_exp, i); + HMAC_SHA256_Update(ahc->ctx, pnum_exp, 8); + } + HMAC_SHA256_Final(hbuf, ahc->ctx); + + /* Success! */ + return (0); +} + +static int +aesctr_hmac_perftest(void) +{ + struct aesctr_hmac_cookie aesctr_hmac_cookie; + struct aesctr_hmac_cookie * ahc = &aesctr_hmac_cookie; + HMAC_SHA256_CTX ctx; + uint8_t kbuf[32]; + + /* Report what we're doing. */ + printf("Testing HMAC_SHA256 with AES-CTR\n"); + + /* Initialize. */ + ahc->ctx = &ctx; + memset(kbuf, 0, 32); + if ((ahc->k_aes = crypto_aes_key_expand(kbuf, 32)) == NULL) + goto err0; + + /* Time the function. */ + if (perftest_buffers(nbytes_perftest, perfsizes, num_perf, + nbytes_warmup, 0, aesctr_hmac_init, aesctr_hmac_func, NULL, ahc)) { + warn0("perftest_buffers"); + goto err0; + } + + /* Clean up. */ + crypto_aes_key_free(ahc->k_aes); + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +} + +/* Cookie for proto_crypt_enc(). */ +struct pce { + struct proto_keys * k; +}; + +static int +pce_init(void * cookie, uint8_t * buf, size_t buflen) +{ + struct pce * pce = cookie; + uint8_t kbuf[64]; + size_t i; + + /* Set up encryption key. */ + memset(kbuf, 0, 64); + if ((pce->k = mkkeypair(kbuf)) == NULL) + goto err0; + + /* Set the input. */ + for (i = 0; i < buflen; i++) + buf[i] = (uint8_t)(i & 0xff); + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +static int +pce_func(void * cookie, uint8_t * buf, size_t buflen, size_t nreps) +{ + struct pce * pce = cookie; + uint8_t encbuf[PCRYPT_ESZ]; + size_t i; + + /* Encrypt a bunch of times. */ + for (i = 0; i < nreps; i++) + proto_crypt_enc(buf, buflen, encbuf, pce->k); + + /* Success! */ + return (0); +} + +static int +pce_cleanup(void * cookie) +{ + struct pce * pce = cookie; + + /* Clean up. */ + proto_crypt_free(pce->k); + + /* Success! */ + return (0); +} + +static int +pce_perftest(void) +{ + struct pce pce_actual; + struct pce * pce = &pce_actual; + + /* Report what we're doing. */ + printf("Testing proto_crypt_enc()\n"); + + /* Time the function. */ + if (perftest_buffers(nbytes_perftest, perfsizes, num_perf, + nbytes_warmup, 0, pce_init, pce_func, pce_cleanup, pce)) { + warn0("perftest_buffers"); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +} + +/* Cookie for proto_pipe */ +struct pipe { + struct proto_keys * k; + void * cancel_cookie; + pthread_t enc_thr; + pthread_t output_thr; + int in[2]; + int out[2]; + int status; + int done; +}; + +static int +pipe_callback_status(void * cookie) +{ + struct pipe * pipe = cookie; + + /* Was there an error? */ + if (pipe->status) { + warn0("proto_pipe callback status: %i", pipe->status); + return (-1); + } + + /* We've finished. */ + pipe->done = 1; + + /* Success! */ + return (0); +} + +/* Encrypt bytes sent to a socket, and send them to another socket. */ +static void * +pipe_enc_thread(void * cookie) +{ + struct pipe * pipe = cookie; + + /* Create the pipe. */ + if ((pipe->cancel_cookie = proto_pipe(pipe->in[1], pipe->out[0], 0, + pipe->k, &pipe->status, pipe_callback_status, pipe)) == NULL) + warn0("proto_pipe"); + + /* Let events happen. */ + if (events_spin(&pipe->done)) + warnp("events_spin"); + + /* Finished! */ + return (NULL); +} + +/* Drain bytes from pipe->out[1] as quickly as possible. */ +static void * +pipe_output_thread(void * cookie) +{ + struct pipe * pipe = cookie; + uint8_t mybuf[MAXOUTSIZE]; + ssize_t readlen; + + /* Loop until we hit EOF. */ + do { + /* + * This will almost always read 1060 bytes (size of an + * encrypted packet, PCRYPT_ESZ in proto_crypt.h), but it's + * not impossible to have more than that. + */ + if ((readlen = read(pipe->out[1], mybuf, MAXOUTSIZE)) == -1) { + warnp("read"); + return (NULL); + } + } while (readlen != 0); + + /* Success! */ + return (NULL); +} + +static int +pipe_init(void * cookie, uint8_t * buf, size_t buflen) +{ + struct pipe * pipe = cookie; + uint8_t kbuf[64]; + size_t i; + int rc; + + /* Sanity check for pipe_output_thread(). */ + assert(buflen <= MAXOUTSIZE); + + /* Set up encryption key. */ + memset(kbuf, 0, 64); + if ((pipe->k = mkkeypair(kbuf)) == NULL) + goto err0; + + /* Create socket pairs for the input and output. */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe->in)) { + warnp("socketpair"); + goto err0; + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe->out)) { + warnp("socketpair"); + goto err0; + } + + /* Set the input. */ + for (i = 0; i < buflen; i++) + buf[i] = (uint8_t)(i & 0xff); + + /* We haven't finished the event loop. */ + pipe->done = 0; + + /* Create the pipe threads. */ + if ((rc = pthread_create_blocking_np(&pipe->output_thr, NULL, + pipe_output_thread, pipe))) { + warn0("pthread_create: %s", strerror(rc)); + goto err0; + } + if ((rc = pthread_create_blocking_np(&pipe->enc_thr, NULL, + pipe_enc_thread, pipe))) { + warn0("pthread_create: %s", strerror(rc)); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +static int +pipe_func(void * cookie, uint8_t * buf, size_t buflen, size_t nreps) +{ + struct pipe * pipe = cookie; + size_t i; + int rc; + + /* Send bytes. */ + for (i = 0; i < nreps; i++) { + if (noeintr_write(pipe->in[0], buf, buflen) + != (ssize_t)buflen) { + warnp("network_write"); + goto err0; + } + } + + /* We've finished writing stuff. */ + if (close(pipe->in[0])) { + warnp("close"); + goto err0; + } + + /* Wait for threads to finish. */ + if ((rc = pthread_join(pipe->output_thr, NULL))) { + warn0("pthread_join: %s", strerror(rc)); + goto err0; + } + if ((rc = pthread_join(pipe->enc_thr, NULL))) { + warn0("pthread_join: %s", strerror(rc)); + goto err0; + } + + /* Clean up. */ + if (close(pipe->out[0])) { + warnp("close"); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +static int +pipe_cleanup(void * cookie) +{ + struct pipe * pipe = cookie; + + /* Clean up. */ + proto_pipe_cancel(pipe->cancel_cookie); + proto_crypt_free(pipe->k); + + /* Success! */ + return (0); +} + +static int +pipe_perftest(void) +{ + struct pipe pipe_actual; + + /* Report what we're doing. */ + printf("Testing proto_pipe()\n"); + + /* Time the function. */ + if (perftest_buffers(nbytes_perftest, perfsizes, num_perf, + nbytes_warmup, 0, pipe_init, pipe_func, pipe_cleanup, + &pipe_actual)) { + warn0("perftest_buffers"); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (1); +} + +int +main(int argc, char * argv[]) +{ + int desired_test; + + WARNP_INIT; + + /* Parse command line. */ + if (argc != 2) { + fprintf(stderr, "usage: test_standalone_enc NUM\n"); + exit(1); + } + if (PARSENUM(&desired_test, argv[1], 1, 5)) { + warnp("parsenum"); + goto err0; + } + + /* Report what we're doing. */ + print_hardware("Testing spiped speed limits"); + + /* Run the desired test. */ + switch(desired_test) { + case 1: + hmac_perftest(); + break; + case 2: + aesctr_perftest(); + break; + case 3: + aesctr_hmac_perftest(); + break; + case 4: + pce_perftest(); + break; + case 5: + pipe_perftest(); + break; + default: + warn0("invalid test number"); + goto err0; + } + + /* Success! */ + exit(0); + +err0: + /* Failure! */ + exit(1); +} diff -Nru spiped-1.6.1/perftests/standalone-enc/Makefile spiped-1.6.2/perftests/standalone-enc/Makefile --- spiped-1.6.1/perftests/standalone-enc/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/perftests/standalone-enc/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -0,0 +1,40 @@ +.POSIX: +# AUTOGENERATED FILE, DO NOT EDIT +PROG=test_standalone_enc +SRCS=main.c proto_crypt.c +IDIRS=-I../../lib/proto -I../../libcperciva/alg -I../../libcperciva/cpusupport -I../../libcperciva/crypto -I../../libcperciva/events -I../../libcperciva/util -I../../lib/util +LDADD_REQ=-lcrypto -lpthread +SUBDIR_DEPTH=../.. +RELATIVE_DIR=perftests/standalone-enc +LIBALL=../../liball/liball.a + +all: + if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ + cd ${SUBDIR_DEPTH}; \ + ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ + BUILD_TARGET=${PROG} buildsubdir; \ + else \ + ${MAKE} ${PROG}; \ + fi + +clean: + rm -f ${PROG} ${SRCS:.c=.o} + +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} + +main.o: main.c ../../libcperciva/cpusupport/cpusupport.h ../../cpusupport-config.h ../../libcperciva/crypto/crypto_aes.h ../../libcperciva/crypto/crypto_aesctr.h ../../libcperciva/events/events.h ../../libcperciva/util/noeintr.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/perftest.h ../../lib/proto/proto_crypt.h ../../libcperciva/crypto/crypto_dh.h ../../lib/proto/proto_pipe.h ../../lib/util/pthread_create_blocking_np.h ../../libcperciva/alg/sha256.h ../../libcperciva/util/sysendian.h ../../libcperciva/util/warnp.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DSTANDALONE_ENC_TESTING -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o +proto_crypt.o: ../../lib/proto/proto_crypt.c ../../libcperciva/crypto/crypto_aes.h ../../libcperciva/crypto/crypto_aesctr.h ../../libcperciva/crypto/crypto_verify_bytes.h ../../libcperciva/util/insecure_memzero.h ../../libcperciva/alg/sha256.h ../../libcperciva/util/sysendian.h ../../libcperciva/util/warnp.h ../../lib/proto/proto_crypt.h ../../libcperciva/crypto/crypto_dh.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DSTANDALONE_ENC_TESTING -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../lib/proto/proto_crypt.c -o proto_crypt.o + +perftest: + @${MAKE} all > /dev/null + @printf "# nblks\tbsize\ttime\tspeed\talg\n" + @for N in 1 2 3 4 5; do \ + ./test_standalone_enc $$N | \ + grep "blocks" | \ + awk -v N="$$N" \ + '{printf "%i\t%i\t%.6f\t%.6f\t%i\n", \ + $$1, $$5, $$6, $$8, N}'; \ + done diff -Nru spiped-1.6.1/proto/proto_conn.c spiped-1.6.2/proto/proto_conn.c --- spiped-1.6.1/proto/proto_conn.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/proto/proto_conn.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,401 +0,0 @@ -#include - -#include -#include - -#include -#include -#include - -#include "events.h" -#include "network.h" -#include "sock.h" - -#include "proto_crypt.h" -#include "proto_handshake.h" -#include "proto_pipe.h" - -#include "proto_conn.h" - -struct conn_state { - int (* callback_dead)(void *, int); - void * cookie; - struct sock_addr ** sas; - int decr; - int nopfs; - int requirepfs; - int nokeepalive; - const struct proto_secret * K; - double timeo; - int s; - int t; - void * connect_cookie; - void * connect_timeout_cookie; - void * handshake_cookie; - void * handshake_timeout_cookie; - struct proto_keys * k_f; - struct proto_keys * k_r; - void * pipe_f; - void * pipe_r; - int stat_f; - int stat_r; -}; - -static int callback_connect_done(void *, int); -static int callback_connect_timeout(void *); -static int callback_handshake_done(void *, struct proto_keys *, - struct proto_keys *); -static int callback_handshake_timeout(void *); -static int callback_pipestatus(void *); - -/* Start a handshake. */ -static int -starthandshake(struct conn_state * C, int s, int decr) -{ - - /* Start the handshake timer. */ - if ((C->handshake_timeout_cookie = events_timer_register_double( - callback_handshake_timeout, C, C->timeo)) == NULL) - goto err0; - - /* Start the handshake. */ - if ((C->handshake_cookie = proto_handshake(s, decr, C->nopfs, - C->requirepfs, C->K, callback_handshake_done, C)) == NULL) - goto err1; - - /* Success! */ - return (0); - -err1: - events_timer_cancel(C->handshake_timeout_cookie); - C->handshake_timeout_cookie = NULL; -err0: - /* Failure! */ - return (-1); -} - -/* Launch the two pipes. */ -static int -launchpipes(struct conn_state * C) -{ - int on = C->nokeepalive ? 0 : 1; - int one = 1; - - /* - * Attempt to turn keepalives on or off as requested. We ignore - * failures here since the sockets might not be of a type for which - * SO_KEEPALIVE is valid -- it is a socket level option, but protocol - * specific. In particular, it has no sensible meaning for UNIX - * sockets. - */ - (void)setsockopt(C->s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); - (void)setsockopt(C->t, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); - - /** - * Attempt to turn off nagling on both sockets. If the TCP stack has - * enough window space that it is always able to send packets, then on - * the encrypted end this will result in every 1060-byte spiped packet - * getting its own TCP segment, including 40 bytes of TCP/IP headers; - * this is fine. On the unencrypted end, we might send a single byte - * of data with 40 bytes of TCP/IP headers; this is not so good. - * - * However, a write over the unencrypted connection will only happen - * after an spiped packet has been read from the encrypted connection, - * so the worst case is 80 bytes of TCP/IP headers per 1061 bytes of - * TCP/IP payload (this may still be only a single byte of spiped - * payload, but that is not relevant to the question of overhead from - * small TCP/IP segments); and while the two sockets might not be on - * the same network, if they are on different networks it is almost - * guaranteed that the network over which the encrypted connection is - * passing would be a wider-area network which is both less secure and - * more expensive. Consequently, the maximum TCP/IP overhead ratio of - * 80/1061 is almost certain to hold even with weighted byte costs. - * - * We ignore errors since (as with keep-alives) we may be dealing with - * a non-TCP socket; and also because while POSIX requires TCP_NODELAY - * to be defined, it is not required to be implemented as a socket - * option. - */ - (void)setsockopt(C->s, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); - (void)setsockopt(C->t, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); - - /* Create two pipes. */ - if ((C->pipe_f = proto_pipe(C->s, C->t, C->decr, C->k_f, - &C->stat_f, callback_pipestatus, C)) == NULL) - goto err0; - if ((C->pipe_r = proto_pipe(C->t, C->s, !C->decr, C->k_r, - &C->stat_r, callback_pipestatus, C)) == NULL) - goto err0; - - /* Success! */ - return (0); - -err0: - /* Failure! */ - return (-1); -} - -/** - * proto_conn_drop(conn_cookie, reason): - * Drop connection and frees memory associated with ${conn_cookie}, due to - * ${reason}. Return success or failure. - */ -int -proto_conn_drop(void * conn_cookie, int reason) -{ - struct conn_state * C = conn_cookie; - int rc; - - /* Close the incoming connection. */ - close(C->s); - - /* Close the outgoing connection if it is open. */ - if (C->t != -1) - close(C->t); - - /* Stop connecting if a connection is in progress. */ - if (C->connect_cookie != NULL) - network_connect_cancel(C->connect_cookie); - - /* Free the target addresses if we haven't already done so. */ - sock_addr_freelist(C->sas); - - /* Stop handshaking if a handshake is in progress. */ - if (C->handshake_cookie != NULL) - proto_handshake_cancel(C->handshake_cookie); - - /* Kill timeouts if they are pending. */ - if (C->connect_timeout_cookie != NULL) - events_timer_cancel(C->connect_timeout_cookie); - if (C->handshake_timeout_cookie != NULL) - events_timer_cancel(C->handshake_timeout_cookie); - - /* Free protocol keys. */ - proto_crypt_free(C->k_f); - proto_crypt_free(C->k_r); - - /* Shut down pipes. */ - if (C->pipe_f != NULL) - proto_pipe_cancel(C->pipe_f); - if (C->pipe_r != NULL) - proto_pipe_cancel(C->pipe_r); - - /* Notify the upstream that we've dropped a connection. */ - rc = (C->callback_dead)(C->cookie, reason); - - /* Free the connection cookie. */ - free(C); - - /* Return success/fail status. */ - return (rc); -} - -/** - * proto_conn_create(s, sas, decr, nopfs, requirepfs, nokeepalive, K, timeo, - * callback_dead, cookie): - * Create a connection with one end at ${s} and the other end connecting to - * the target addresses ${sas}. If ${decr} is 0, encrypt the outgoing data; - * if ${decr} is nonzero, decrypt the incoming data. If ${nopfs} is non-zero, - * don't use perfect forward secrecy. If ${requirepfs} is non-zero, drop - * the connection if the other end tries to disable perfect forward secrecy. - * Enable transport layer keep-alives (if applicable) on both sockets if and - * only if ${nokeepalive} is zero. Drop the connection if the handshake or - * connecting to the target takes more than ${timeo} seconds. When the - * connection is dropped, invoke ${callback_dead}(${cookie}). Free ${sas} - * once it is no longer needed. Return a cookie which can be passed to - * proto_conn_drop. - */ -void * -proto_conn_create(int s, struct sock_addr ** sas, int decr, int nopfs, - int requirepfs, int nokeepalive, const struct proto_secret * K, - double timeo, int (* callback_dead)(void *, int), void * cookie) -{ - struct conn_state * C; - - /* Bake a cookie for this connection. */ - if ((C = malloc(sizeof(struct conn_state))) == NULL) - goto err0; - C->callback_dead = callback_dead; - C->cookie = cookie; - C->sas = sas; - C->decr = decr; - C->nopfs = nopfs; - C->requirepfs = requirepfs; - C->nokeepalive = nokeepalive; - C->K = K; - C->timeo = timeo; - C->s = s; - C->t = -1; - C->connect_cookie = NULL; - C->connect_timeout_cookie = NULL; - C->handshake_cookie = NULL; - C->handshake_timeout_cookie = NULL; - C->k_f = C->k_r = NULL; - C->pipe_f = C->pipe_r = NULL; - C->stat_f = C->stat_r = 1; - - /* Start the connect timer. */ - if ((C->connect_timeout_cookie = events_timer_register_double( - callback_connect_timeout, C, C->timeo)) == NULL) - goto err1; - - /* Connect to target. */ - if ((C->connect_cookie = - network_connect(C->sas, callback_connect_done, C)) == NULL) - goto err2; - - /* If we're decrypting, start the handshake. */ - if (C->decr) { - if (starthandshake(C, C->s, C->decr)) - goto err3; - } - - /* Success! */ - return (C); - -err3: - network_connect_cancel(C->connect_cookie); -err2: - events_timer_cancel(C->connect_timeout_cookie); -err1: - free(C); -err0: - /* Failure! */ - return (NULL); -} - -/* We have connected to the target. */ -static int -callback_connect_done(void * cookie, int t) -{ - struct conn_state * C = cookie; - - /* This connection attempt is no longer pending. */ - C->connect_cookie = NULL; - - /* Don't need the target address any more. */ - sock_addr_freelist(C->sas); - C->sas = NULL; - - /* We beat the clock. */ - events_timer_cancel(C->connect_timeout_cookie); - C->connect_timeout_cookie = NULL; - - /* Did we manage to connect? */ - if ((C->t = t) == -1) - return (proto_conn_drop(C, PROTO_CONN_CONNECT_FAILED)); - - /* If we're encrypting, start the handshake. */ - if (!C->decr) { - if (starthandshake(C, C->t, C->decr)) - goto err1; - } - - /* If the handshake already finished, start shuttling data. */ - if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { - if (launchpipes(C)) - goto err1; - } - - /* Success! */ - return (0); - -err1: - proto_conn_drop(C, PROTO_CONN_ERROR); - - /* Failure! */ - return (-1); -} - -/* Connecting to the target took too long. */ -static int -callback_connect_timeout(void * cookie) -{ - struct conn_state * C = cookie; - - /* This timeout is no longer pending. */ - C->connect_timeout_cookie = NULL; - - /* - * We could free C->sas here, but from a semantic point of view it - * could still be in use by the not-yet-cancelled connect operation. - * Instead, we free it in proto_conn_drop, after cancelling the - * connect. - */ - - /* Drop the connection. */ - return (proto_conn_drop(C, PROTO_CONN_ERROR)); -} - -/* We have performed the protocol handshake. */ -static int -callback_handshake_done(void * cookie, struct proto_keys * f, - struct proto_keys * r) -{ - struct conn_state * C = cookie; - - /* The handshake is no longer in progress. */ - C->handshake_cookie = NULL; - - /* We beat the clock. */ - events_timer_cancel(C->handshake_timeout_cookie); - C->handshake_timeout_cookie = NULL; - - /* If the protocol handshake failed, drop the connection. */ - if ((f == NULL) && (r == NULL)) - return (proto_conn_drop(C, PROTO_CONN_HANDSHAKE_FAILED)); - - /* We should have two keys. */ - assert(f != NULL); - assert(r != NULL); - - /* Record the keys so we can free them later. */ - C->k_f = f; - C->k_r = r; - - /* If we already connected to the target, start shuttling data. */ - if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { - if (launchpipes(C)) - goto err1; - } - - /* Success! */ - return (0); - -err1: - proto_conn_drop(C, PROTO_CONN_ERROR); - - /* Failure! */ - return (-1); -} - -/* The protocol handshake took too long. */ -static int -callback_handshake_timeout(void * cookie) -{ - struct conn_state * C = cookie; - - /* This timeout is no longer pending. */ - C->handshake_timeout_cookie = NULL; - - /* Drop the connection. */ - return (proto_conn_drop(C, PROTO_CONN_ERROR)); -} - -/* The status of one of the directions has changed. */ -static int -callback_pipestatus(void * cookie) -{ - struct conn_state * C = cookie; - - /* If we have an error in either direction, kill the connection. */ - if ((C->stat_f == -1) || (C->stat_r == -1)) - return (proto_conn_drop(C, PROTO_CONN_ERROR)); - - /* If both directions have been shut down, kill the connection. */ - if ((C->stat_f == 0) && (C->stat_r == 0)) - return (proto_conn_drop(C, PROTO_CONN_CLOSED)); - - /* Nothing to do. */ - return (0); -} diff -Nru spiped-1.6.1/proto/proto_conn.h spiped-1.6.2/proto/proto_conn.h --- spiped-1.6.1/proto/proto_conn.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/proto/proto_conn.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -#ifndef _PROTO_CONN_H_ -#define _PROTO_CONN_H_ - -/* Opaque structures. */ -struct proto_secret; -struct sock_addr; - -/* Reason why the connection was dropped. */ -enum { - PROTO_CONN_CLOSED = 0, /* Normal exit */ - PROTO_CONN_CANCELLED, /* Exit triggered by client code */ - PROTO_CONN_CONNECT_FAILED, /* Could not connect */ - PROTO_CONN_HANDSHAKE_FAILED, /* Handshake failed */ - PROTO_CONN_ERROR, /* Unspecified reason */ -}; - -/** - * proto_conn_create(s, sas, decr, nopfs, requirepfs, nokeepalive, K, timeo, - * callback_dead, cookie): - * Create a connection with one end at ${s} and the other end connecting to - * the target addresses ${sas}. If ${decr} is 0, encrypt the outgoing data; - * if ${decr} is nonzero, decrypt the outgoing data. If ${nopfs} is non-zero, - * don't use perfect forward secrecy. If ${requirepfs} is non-zero, drop - * the connection if the other end tries to disable perfect forward secrecy. - * Enable transport layer keep-alives (if applicable) on both sockets if and - * only if ${nokeepalive} is zero. Drop the connection if the handshake or - * connecting to the target takes more than ${timeo} seconds. When the - * connection is dropped, invoke ${callback_dead}(${cookie}). Free ${sas} - * once it is no longer needed. Return a cookie which can be passed to - * proto_conn_drop. - */ -void * proto_conn_create(int, struct sock_addr **, int, int, int, int, - const struct proto_secret *, double, int (*)(void *, int), void *); - -/** - * proto_conn_drop(conn_cookie, reason): - * Drop connection and frees memory associated with ${conn_cookie}, due to - * ${reason}. Return success or failure. - */ -int proto_conn_drop(void *, int); - -#endif /* !_PROTO_CONN_H_ */ diff -Nru spiped-1.6.1/proto/proto_crypt.c spiped-1.6.2/proto/proto_crypt.c --- spiped-1.6.1/proto/proto_crypt.c 2019-11-29 21:02:07.000000000 +0000 +++ spiped-1.6.2/proto/proto_crypt.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,407 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "crypto_aes.h" -#include "crypto_aesctr.h" -#include "crypto_verify_bytes.h" -#include "sha256.h" -#include "sysendian.h" -#include "warnp.h" - -#include "proto_crypt.h" - -struct proto_secret { - uint8_t K[32]; -}; - -struct proto_keys { - struct crypto_aes_key * k_aes; - uint8_t k_hmac[32]; - uint64_t pnum; -}; - -/** - * mkkeypair(kbuf): - * Convert the 64 bytes of ${kbuf} into a protocol key structure. - */ -static struct proto_keys * -mkkeypair(uint8_t kbuf[64]) -{ - struct proto_keys * k; - - /* Allocate a structure. */ - if ((k = malloc(sizeof(struct proto_keys))) == NULL) - goto err0; - - /* Expand the AES key. */ - if ((k->k_aes = crypto_aes_key_expand(&kbuf[0], 32)) == NULL) - goto err1; - - /* Fill in HMAC key. */ - memcpy(k->k_hmac, &kbuf[32], 32); - - /* The first packet will be packet number zero. */ - k->pnum = 0; - - /* Success! */ - return (k); - -err1: - free(k); -err0: - /* Failure! */ - return (NULL); -} - -/** - * proto_crypt_secret(filename): - * Read the key file ${filename} and return a protocol secret structure. - */ -struct proto_secret * -proto_crypt_secret(const char * filename) -{ - SHA256_CTX ctx; - FILE * f; - struct proto_secret * K; - uint8_t buf[BUFSIZ]; - size_t lenread; - - /* Allocate a protocol secret structure. */ - if ((K = malloc(sizeof(struct proto_secret))) == NULL) - goto err0; - - /* Open the file, or use stdin if requested. */ - if (strcmp(filename, STDIN_FILENAME) == 0) { - f = stdin; - } else if ((f = fopen(filename, "r")) == NULL) { - warnp("Cannot open file: %s", filename); - goto err1; - } - - /* Initialize the SHA256 hash context. */ - SHA256_Init(&ctx); - - /* Read the file until we hit EOF. */ - while ((lenread = fread(buf, 1, BUFSIZ, f)) > 0) - SHA256_Update(&ctx, buf, lenread); - - /* Did we hit EOF? */ - if (!feof(f)) { - if (f == stdin) { - warnp("Error reading from stdin"); - } else { - warnp("Error reading file: %s", filename); - } - - goto err2; - } - - /* Close the file if it isn't stdin. */ - if (f != stdin) - fclose(f); - - /* Compute the final hash. */ - SHA256_Final(K->K, &ctx); - - /* Success! */ - return (K); - -err2: - if (f != stdin) - fclose(f); -err1: - free(K); -err0: - /* Failure! */ - return (NULL); -} - -/** - * proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr): - * Using the protocol secret ${K}, and the local and remote nonces ${nonce_l} - * and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC - * keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S" - * and "remote" == "C"; otherwise the assignments are opposite. - */ -void -proto_crypt_dhmac(const struct proto_secret * K, - const uint8_t nonce_l[PCRYPT_NONCE_LEN], - const uint8_t nonce_r[PCRYPT_NONCE_LEN], - uint8_t dhmac_l[PCRYPT_DHMAC_LEN], uint8_t dhmac_r[PCRYPT_DHMAC_LEN], - int decr) -{ - uint8_t nonce_CS[PCRYPT_NONCE_LEN * 2]; - uint8_t dk_1[PCRYPT_DHMAC_LEN * 2]; - const uint8_t * nonce_c, * nonce_s; - uint8_t * dhmac_c, * dhmac_s; - - /* Figure out how {c, s} maps to {l, r}. */ - nonce_c = decr ? nonce_r : nonce_l; - dhmac_c = decr ? dhmac_r : dhmac_l; - nonce_s = decr ? nonce_l : nonce_r; - dhmac_s = decr ? dhmac_l : dhmac_r; - - /* Copy in nonces (in the right order). */ - memcpy(&nonce_CS[0], nonce_c, PCRYPT_NONCE_LEN); - memcpy(&nonce_CS[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN); - - /* Compute dk_1. */ - PBKDF2_SHA256(K->K, 32, nonce_CS, PCRYPT_NONCE_LEN * 2, 1, - dk_1, PCRYPT_DHMAC_LEN * 2); - - /* Copy out diffie-hellman parameter MAC keys (in the right order). */ - memcpy(dhmac_c, &dk_1[0], PCRYPT_DHMAC_LEN); - memcpy(dhmac_s, &dk_1[PCRYPT_DHMAC_LEN], PCRYPT_DHMAC_LEN); -} - -/** - * is_not_one(x, len): - * Return non-zero if the big-endian value stored at (${x}, ${len}) is not - * equal to 1. - */ -static int -is_not_one(const uint8_t * x, size_t len) -{ - size_t i; - char y; - - for (i = 0, y = 0; i < len - 1; i++) { - y |= x[i]; - } - - return (y | (x[len - 1] - 1)); -} - -/** - * proto_crypt_dh_validate(yh_r, dhmac_r, requirepfs): - * Return non-zero if the value ${yh_r} received from the remote party is not - * correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or - * if the included y value is >= the diffie-hellman group modulus, or if - * ${requirepfs} is non-zero and the included y value is 1. - */ -int -proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN], - const uint8_t dhmac_r[PCRYPT_DHMAC_LEN], int requirepfs) -{ - uint8_t hbuf[32]; - - /* Compute HMAC. */ - HMAC_SHA256_Buf(dhmac_r, PCRYPT_DHMAC_LEN, yh_r, CRYPTO_DH_PUBLEN, - hbuf); - - /* Check that the MAC matches. */ - if (crypto_verify_bytes(&yh_r[CRYPTO_DH_PUBLEN], hbuf, 32)) - return (1); - - /* Sanity-check the diffie-hellman value. */ - if (crypto_dh_sanitycheck(&yh_r[0])) - return (1); - - /* If necessary, enforce that the diffie-hellman value is != 1. */ - if (requirepfs) { - if (! is_not_one(&yh_r[0], CRYPTO_DH_PUBLEN)) - return (1); - } - - /* Everything is good. */ - return (0); -} - -/** - * proto_crypt_dh_generate(yh_l, x, dhmac_l, nopfs): - * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake - * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If - * ${nopfs} is non-zero, skip diffie-hellman generation and use y = 1. - */ -int -proto_crypt_dh_generate(uint8_t yh_l[PCRYPT_YH_LEN], uint8_t x[PCRYPT_X_LEN], - const uint8_t dhmac_l[PCRYPT_DHMAC_LEN], int nopfs) -{ - - /* Are we skipping the diffie-hellman generation? */ - if (nopfs) { - /* Set y_l to a big-endian 1. */ - memset(yh_l, 0, CRYPTO_DH_PUBLEN - 1); - yh_l[CRYPTO_DH_PUBLEN - 1] = 1; - } else { - /* Generate diffie-hellman parameters x and y. */ - if (crypto_dh_generate(yh_l, x)) - goto err0; - } - - /* Append an HMAC. */ - HMAC_SHA256_Buf(dhmac_l, PCRYPT_DHMAC_LEN, yh_l, CRYPTO_DH_PUBLEN, - &yh_l[CRYPTO_DH_PUBLEN]); - - /* Success! */ - return (0); - -err0: - /* Failure! */ - return (-1); -} - -/** - * proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nopfs, decr, eh_c, eh_s): - * Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and - * ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r}, - * and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and - * ${eh_s}. If ${nopfs} is non-zero, we are performing weak handshaking and - * y_SC is set to 1 rather than being computed. If ${decr} is non-zero, - * "local" == "S" and "remote" == "C"; otherwise the assignments are opposite. - */ -int -proto_crypt_mkkeys(const struct proto_secret * K, - const uint8_t nonce_l[PCRYPT_NONCE_LEN], - const uint8_t nonce_r[PCRYPT_NONCE_LEN], - const uint8_t yh_r[PCRYPT_YH_LEN], const uint8_t x[PCRYPT_X_LEN], - int nopfs, int decr, - struct proto_keys ** eh_c, struct proto_keys ** eh_s) -{ - uint8_t nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN]; - uint8_t dk_2[128]; - const uint8_t * nonce_c, * nonce_s; - - /* Copy in nonces (in the right order). */ - nonce_c = decr ? nonce_r : nonce_l; - nonce_s = decr ? nonce_l : nonce_r; - memcpy(&nonce_y[0], nonce_c, PCRYPT_NONCE_LEN); - memcpy(&nonce_y[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN); - - /* Are we bypassing the diffie-hellman computation? */ - if (nopfs) { - /* We sent y_l = 1, so y_SC is also 1. */ - memset(&nonce_y[PCRYPT_NONCE_LEN * 2], 0, - CRYPTO_DH_KEYLEN - 1); - nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN - 1] = 1; - } else { - /* Perform the diffie-hellman computation. */ - if (crypto_dh_compute(yh_r, x, - &nonce_y[PCRYPT_NONCE_LEN * 2])) - goto err0; - } - - /* Compute dk_2. */ - PBKDF2_SHA256(K->K, 32, nonce_y, - PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN, 1, dk_2, 128); - - /* Create key structures. */ - if ((*eh_c = mkkeypair(&dk_2[0])) == NULL) - goto err0; - if ((*eh_s = mkkeypair(&dk_2[64])) == NULL) - goto err1; - - /* Success! */ - return (0); - -err1: - proto_crypt_free(*eh_c); -err0: - /* Failure! */ - return (-1); -} - -/** - * proto_crypt_enc(ibuf, len, obuf, k): - * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in - * ${k}, and write the result into ${obuf}. - */ -void -proto_crypt_enc(uint8_t * ibuf, size_t len, uint8_t obuf[PCRYPT_ESZ], - struct proto_keys * k) -{ - HMAC_SHA256_CTX ctx; - uint8_t pnum_exp[8]; - - /* Sanity-check the length. */ - assert(len <= PCRYPT_MAXDSZ); - - /* Copy the decrypted data into the encrypted buffer. */ - memcpy(obuf, ibuf, len); - - /* Pad up to PCRYPT_MAXDSZ with zeroes. */ - memset(&obuf[len], 0, PCRYPT_MAXDSZ - len); - - /* Add the length. */ - be32enc(&obuf[PCRYPT_MAXDSZ], (uint32_t)len); - - /* Encrypt the buffer in-place. */ - crypto_aesctr_buf(k->k_aes, k->pnum, obuf, obuf, PCRYPT_MAXDSZ + 4); - - /* Append an HMAC. */ - be64enc(pnum_exp, k->pnum); - HMAC_SHA256_Init(&ctx, k->k_hmac, 32); - HMAC_SHA256_Update(&ctx, obuf, PCRYPT_MAXDSZ + 4); - HMAC_SHA256_Update(&ctx, pnum_exp, 8); - HMAC_SHA256_Final(&obuf[PCRYPT_MAXDSZ + 4], &ctx); - - /* Increment packet number. */ - k->pnum += 1; -} - -/** - * proto_crypt_dec(ibuf, obuf, k): - * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data - * is valid, write it into ${obuf} and return the length; otherwise, return - * -1. - */ -ssize_t -proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf, - struct proto_keys * k) -{ - HMAC_SHA256_CTX ctx; - uint8_t hbuf[32]; - uint8_t pnum_exp[8]; - size_t len; - - /* Verify HMAC. */ - be64enc(pnum_exp, k->pnum); - HMAC_SHA256_Init(&ctx, k->k_hmac, 32); - HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4); - HMAC_SHA256_Update(&ctx, pnum_exp, 8); - HMAC_SHA256_Final(hbuf, &ctx); - if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32)) - return (-1); - - /* Decrypt the buffer in-place. */ - crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4); - - /* Increment packet number. */ - k->pnum += 1; - - /* Parse length. */ - len = be32dec(&ibuf[PCRYPT_MAXDSZ]); - - /* Make sure nobody is being evil here... */ - if ((len == 0) || (len > PCRYPT_MAXDSZ)) - return (-1); - - /* Copy the bytes into the output buffer. */ - memcpy(obuf, ibuf, len); - - /* Return the decrypted length. */ - return ((ssize_t)len); -} - -/** - * proto_crypt_free(k): - * Free the protocol key structure ${k}. - */ -void -proto_crypt_free(struct proto_keys * k) -{ - - /* Be compatible with free(NULL). */ - if (k == NULL) - return; - - /* Free the AES key. */ - crypto_aes_key_free(k->k_aes); - - /* Free the key structure. */ - free(k); -} diff -Nru spiped-1.6.1/proto/proto_crypt.h spiped-1.6.2/proto/proto_crypt.h --- spiped-1.6.1/proto/proto_crypt.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/proto/proto_crypt.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -#ifndef _PROTO_CRYPT_H_ -#define _PROTO_CRYPT_H_ - -#include -#include - -#include "crypto_dh.h" - -/* Opaque structures. */ -struct proto_keys; -struct proto_secret; - -/* Size of nonce. */ -#define PCRYPT_NONCE_LEN 32 - -/* Size of temporary MAC keys used for Diffie-Hellman parameters. */ -#define PCRYPT_DHMAC_LEN 32 - -/* Size of private Diffie-Hellman value. */ -#define PCRYPT_X_LEN CRYPTO_DH_PRIVLEN - -/* Size of MACed Diffie-Hellman parameter. */ -#define PCRYPT_YH_LEN (CRYPTO_DH_PUBLEN + 32) - -/* Filename for stdin. */ -#define STDIN_FILENAME "-" - -/** - * proto_crypt_secret(filename): - * Read the key file ${filename} and return a protocol secret structure. - */ -struct proto_secret * proto_crypt_secret(const char *); - -/** - * proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr): - * Using the protocol secret ${K}, and the local and remote nonces ${nonce_l} - * and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC - * keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S" - * and "remote" == "C"; otherwise the assignments are opposite. - */ -void proto_crypt_dhmac(const struct proto_secret *, - const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN], - uint8_t[PCRYPT_DHMAC_LEN], uint8_t[PCRYPT_DHMAC_LEN], int); - -/** - * proto_crypt_dh_validate(yh_r, dhmac_r, requirepfs): - * Return non-zero if the value ${yh_r} received from the remote party is not - * correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or - * if the included y value is >= the diffie-hellman group modulus, or if - * ${requirepfs} is non-zero and the included y value is 1. - */ -int proto_crypt_dh_validate(const uint8_t[PCRYPT_YH_LEN], - const uint8_t[PCRYPT_DHMAC_LEN], int); - -/** - * proto_crypt_dh_generate(yh_l, x, dhmac_l, nopfs): - * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake - * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If - * ${nopfs} is non-zero, skip diffie-hellman generation and use y = 1. - */ -int proto_crypt_dh_generate(uint8_t[PCRYPT_YH_LEN], uint8_t[PCRYPT_X_LEN], - const uint8_t[PCRYPT_DHMAC_LEN], int); - -/** - * proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nopfs, decr, eh_c, eh_s): - * Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and - * ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r}, - * and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and - * ${eh_s}. If ${nopfs} is non-zero, we are performing weak handshaking and - * y_SC is set to 1 rather than being computed. If ${decr} is non-zero, - * "local" == "S" and "remote" == "C"; otherwise the assignments are opposite. - */ -int proto_crypt_mkkeys(const struct proto_secret *, - const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN], - const uint8_t[PCRYPT_YH_LEN], const uint8_t[PCRYPT_X_LEN], int, int, - struct proto_keys **, struct proto_keys **); - -/* Maximum size of an unencrypted packet. */ -#define PCRYPT_MAXDSZ 1024 - -/* Size of an encrypted packet. */ -#define PCRYPT_ESZ (PCRYPT_MAXDSZ + 4 /* len */ + 32 /* hmac */) - -/** - * proto_crypt_enc(ibuf, len, obuf, k): - * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in - * ${k}, and write the result into ${obuf}. - */ -void proto_crypt_enc(uint8_t *, size_t, uint8_t[PCRYPT_ESZ], - struct proto_keys *); - -/** - * proto_crypt_dec(ibuf, obuf, k): - * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data - * is valid, write it into ${obuf} and return the length; otherwise, return - * -1. - */ -ssize_t proto_crypt_dec(uint8_t[PCRYPT_ESZ], uint8_t *, struct proto_keys *); - -/** - * proto_crypt_free(k): - * Free the protocol key structure ${k}. - */ -void proto_crypt_free(struct proto_keys *); - -#endif /* !_PROTO_CRYPT_H_ */ diff -Nru spiped-1.6.1/proto/proto_handshake.c spiped-1.6.2/proto/proto_handshake.c --- spiped-1.6.1/proto/proto_handshake.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/proto/proto_handshake.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,329 +0,0 @@ -#include -#include -#include -#include - -#include "crypto_entropy.h" -#include "network.h" - -#include "proto_crypt.h" - -#include "proto_handshake.h" - -struct handshake_cookie { - int (* callback)(void *, struct proto_keys *, struct proto_keys *); - void * cookie; - int s; - int decr; - int nopfs; - int requirepfs; - const struct proto_secret * K; - uint8_t nonce_local[PCRYPT_NONCE_LEN]; - uint8_t nonce_remote[PCRYPT_NONCE_LEN]; - uint8_t dhmac_local[PCRYPT_DHMAC_LEN]; - uint8_t dhmac_remote[PCRYPT_DHMAC_LEN]; - uint8_t x[PCRYPT_X_LEN]; - uint8_t yh_local[PCRYPT_YH_LEN]; - uint8_t yh_remote[PCRYPT_YH_LEN]; - void * read_cookie; - void * write_cookie; -}; - -static int callback_nonce_write(void *, ssize_t); -static int callback_nonce_read(void *, ssize_t); -static int gotnonces(struct handshake_cookie *); -static int dhread(struct handshake_cookie *); -static int callback_dh_read(void *, ssize_t); -static int dhwrite(struct handshake_cookie *); -static int callback_dh_write(void *, ssize_t); -static int handshakedone(struct handshake_cookie *); - -/* The handshake failed. Call back and clean up. */ -static int -handshakefail(struct handshake_cookie * H) -{ - int rc; - - /* Cancel any pending network read or write. */ - if (H->read_cookie != NULL) - network_read_cancel(H->read_cookie); - if (H->write_cookie != NULL) - network_write_cancel(H->write_cookie); - - /* Perform the callback. */ - rc = (H->callback)(H->cookie, NULL, NULL); - - /* Free the cookie. */ - free(H); - - /* Return status from callback. */ - return (rc); -} - -/** - * proto_handshake(s, decr, nopfs, requirepfs, K, callback, cookie): - * Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are - * at the receiving end of the connection; otherwise at the sending end. If - * ${nopfs} is non-zero, perform a "weak" handshake without perfect forward - * secrecy. If ${requirepfs} is non-zero, drop the connection if the other - * end attempts to perform a "weak" handshake. The shared protocol secret is - * ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f - * contains the keys needed for the forward direction and r contains the keys - * needed for the reverse direction; or f = r = NULL if the handshake failed. - * Return a cookie which can be passed to proto_handshake_cancel to cancel the - * handshake. - */ -void * -proto_handshake(int s, int decr, int nopfs, int requirepfs, - const struct proto_secret * K, - int (* callback)(void *, struct proto_keys *, struct proto_keys *), - void * cookie) -{ - struct handshake_cookie * H; - - /* Bake a cookie. */ - if ((H = malloc(sizeof(struct handshake_cookie))) == NULL) - goto err0; - H->callback = callback; - H->cookie = cookie; - H->s = s; - H->decr = decr; - H->nopfs = nopfs; - H->requirepfs = requirepfs; - H->K = K; - - /* Generate a 32-byte connection nonce. */ - if (crypto_entropy_read(H->nonce_local, 32)) - goto err1; - - /* Send our nonce. */ - if ((H->write_cookie = network_write(s, H->nonce_local, 32, 32, - callback_nonce_write, H)) == NULL) - goto err1; - - /* Read the other party's nonce. */ - if ((H->read_cookie = network_read(s, H->nonce_remote, 32, 32, - callback_nonce_read, H)) == NULL) - goto err2; - - /* Success! */ - return (H); - -err2: - network_write_cancel(H->write_cookie); -err1: - free(H); -err0: - /* Failure! */ - return (NULL); -} - -/* We've written our nonce. */ -static int -callback_nonce_write(void * cookie, ssize_t len) -{ - struct handshake_cookie * H = cookie; - - /* This write is no longer pending. */ - H->write_cookie = NULL; - - /* Did we successfully write? */ - if (len < 32) - return (handshakefail(H)); - - /* If the nonce read is also done, move on to the next step. */ - if (H->read_cookie == NULL) - return (gotnonces(H)); - - /* Nothing to do. */ - return (0); -} - -/* We've read a nonce. */ -static int -callback_nonce_read(void * cookie, ssize_t len) -{ - struct handshake_cookie * H = cookie; - - /* This read is no longer pending. */ - H->read_cookie = NULL; - - /* Did we successfully read? */ - if (len < 32) - return (handshakefail(H)); - - /* If the nonce write is also done, move on to the next step. */ - if (H->write_cookie == NULL) - return (gotnonces(H)); - - /* Nothing to do. */ - return (0); -} - -/* We have two nonces. Start the DH exchange. */ -static int -gotnonces(struct handshake_cookie * H) -{ - - /* Compute the diffie-hellman parameter MAC keys. */ - proto_crypt_dhmac(H->K, H->nonce_local, H->nonce_remote, - H->dhmac_local, H->dhmac_remote, H->decr); - - /* - * If we're the server, we need to read the client's diffie-hellman - * parameter. If we're the client, we need to generate and send our - * diffie-hellman parameter. - */ - if (H->decr) - return (dhread(H)); - else - return (dhwrite(H)); - - /* NOTREACHED */ -} - -/* Read a diffie-hellman parameter. */ -static int -dhread(struct handshake_cookie * H) -{ - - /* Read the remote signed diffie-hellman parameter. */ - if ((H->read_cookie = network_read(H->s, H->yh_remote, PCRYPT_YH_LEN, - PCRYPT_YH_LEN, callback_dh_read, H)) == NULL) - goto err0; - - /* Success! */ - return (0); - -err0: - /* Failure! */ - return (-1); -} - -/* We have read a diffie-hellman parameter. */ -static int -callback_dh_read(void * cookie, ssize_t len) -{ - struct handshake_cookie * H = cookie; - - /* This read is no longer pending. */ - H->read_cookie = NULL; - - /* Did we successfully read? */ - if (len < PCRYPT_YH_LEN) - return (handshakefail(H)); - - /* Is the value we read valid? */ - if (proto_crypt_dh_validate(H->yh_remote, H->dhmac_remote, - H->requirepfs)) - return (handshakefail(H)); - - /* - * If we're the server, we need to send our diffie-hellman parameter - * next. If we're the client, move on to the final computation. - */ - if (H->decr) - return (dhwrite(H)); - else - return (handshakedone(H)); - - /* NOTREACHED */ -} - -/* Generate and write a diffie-hellman parameter. */ -static int -dhwrite(struct handshake_cookie * H) -{ - - /* Generate a signed diffie-hellman parameter. */ - if (proto_crypt_dh_generate(H->yh_local, H->x, H->dhmac_local, - H->nopfs)) - goto err0; - - /* Write our signed diffie-hellman parameter. */ - if ((H->write_cookie = network_write(H->s, H->yh_local, PCRYPT_YH_LEN, - PCRYPT_YH_LEN, callback_dh_write, H)) == NULL) - goto err0; - - /* Success! */ - return (0); - -err0: - /* Failure! */ - return (-1); -} - -/* We have written our diffie-hellman parameter. */ -static int -callback_dh_write(void * cookie, ssize_t len) -{ - struct handshake_cookie * H = cookie; - - /* This write is no longer pending. */ - H->write_cookie = NULL; - - /* Did we successfully write? */ - if (len < PCRYPT_YH_LEN) - return (handshakefail(H)); - - /* - * If we're the server, move on to the final computation. If we're - * the client, we need to read the server's parameter next. - */ - if (H->decr) - return (handshakedone(H)); - else - return (dhread(H)); - - /* NOTREACHED */ -} - -/* We've got all the bits; do the final computation and callback. */ -static int -handshakedone(struct handshake_cookie * H) -{ - struct proto_keys * c; - struct proto_keys * s; - int rc; - - /* Sanity-check: There should be no callbacks in progress. */ - assert(H->read_cookie == NULL); - assert(H->write_cookie == NULL); - - /* Perform the final computation. */ - if (proto_crypt_mkkeys(H->K, H->nonce_local, H->nonce_remote, - H->yh_remote, H->x, H->nopfs, H->decr, &c, &s)) - goto err0; - - /* Perform the callback. */ - rc = (H->callback)(H->cookie, c, s); - - /* Free the cookie. */ - free(H); - - /* Return status code from callback. */ - return (rc); - -err0: - /* Failure! */ - return (-1); -} - -/** - * proto_handshake_cancel(cookie): - * Cancel the handshake for which proto_handshake returned ${cookie}. - */ -void -proto_handshake_cancel(void * cookie) -{ - struct handshake_cookie * H = cookie; - - /* Cancel any in-progress network operations. */ - if (H->read_cookie != NULL) - network_read_cancel(H->read_cookie); - if (H->write_cookie != NULL) - network_write_cancel(H->write_cookie); - - /* Free the cookie. */ - free(H); -} diff -Nru spiped-1.6.1/proto/proto_handshake.h spiped-1.6.2/proto/proto_handshake.h --- spiped-1.6.1/proto/proto_handshake.h 2017-01-27 22:38:34.000000000 +0000 +++ spiped-1.6.2/proto/proto_handshake.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#ifndef _PROTO_HANDSHAKE_H_ -#define _PROTO_HANDSHAKE_H_ - -/* Opaque structures. */ -struct proto_keys; -struct proto_secret; - -/** - * proto_handshake(s, decr, nopfs, requirepfs, K, callback, cookie): - * Perform a protocol handshake on socket ${s}. If ${decr} is non-zero we are - * at the receiving end of the connection; otherwise at the sending end. If - * ${nopfs} is non-zero, perform a "weak" handshake without perfect forward - * secrecy. If ${requirepfs} is non-zero, drop the connection if the other - * end attempts to perform a "weak" handshake. The shared protocol secret is - * ${K}. Upon completion, invoke ${callback}(${cookie}, f, r), where f - * contains the keys needed for the forward direction and r contains the keys - * needed for the reverse direction; or f = r = NULL if the handshake failed. - * Return a cookie which can be passed to proto_handshake_cancel to cancel the - * handshake. - */ -void * proto_handshake(int, int, int, int, const struct proto_secret *, - int (*)(void *, struct proto_keys *, struct proto_keys *), void *); - -/** - * proto_handshake_cancel(cookie): - * Cancel the handshake for which proto_handshake returned ${cookie}. - */ -void proto_handshake_cancel(void *); - -#endif /* !_PROTO_HANDSHAKE_H_ */ diff -Nru spiped-1.6.1/proto/proto_pipe.c spiped-1.6.2/proto/proto_pipe.c --- spiped-1.6.1/proto/proto_pipe.c 2017-01-27 22:38:21.000000000 +0000 +++ spiped-1.6.2/proto/proto_pipe.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -#include -#include - -#include -#include - -#include "network.h" - -#include "proto_crypt.h" - -#include "proto_pipe.h" - -struct pipe_cookie { - int (* callback)(void *); - void * cookie; - int * status; - int s_in; - int s_out; - int decr; - struct proto_keys * k; - uint8_t dbuf[PCRYPT_MAXDSZ]; - uint8_t ebuf[PCRYPT_ESZ]; - void * read_cookie; - void * write_cookie; - ssize_t wlen; -}; - -static int callback_pipe_read(void *, ssize_t); -static int callback_pipe_write(void *, ssize_t); - -/** - * proto_pipe(s_in, s_out, decr, k, status, callback, cookie): - * Read bytes from ${s_in} and write them to ${s_out}. If ${decr} is non-zero - * then use ${k} to decrypt the bytes; otherwise use ${k} to encrypt them. - * If EOF is read, set ${status} to 0, and if an error is encountered set - * ${status} to -1; in either case, invoke ${callback}(${cookie}). Return a - * cookie which can be passed to proto_pipe_cancel. - */ -void * -proto_pipe(int s_in, int s_out, int decr, struct proto_keys * k, - int * status, int (* callback)(void *), void * cookie) -{ - struct pipe_cookie * P; - - /* Bake a cookie. */ - if ((P = malloc(sizeof(struct pipe_cookie))) == NULL) - goto err0; - P->callback = callback; - P->cookie = cookie; - P->status = status; - P->s_in = s_in; - P->s_out = s_out; - P->decr = decr; - P->k = k; - P->read_cookie = NULL; - P->write_cookie = NULL; - - /* Start reading. */ - if (P->decr) { - if ((P->read_cookie = network_read(P->s_in, P->ebuf, - PCRYPT_ESZ, PCRYPT_ESZ, callback_pipe_read, P)) == NULL) - goto err1; - } else { - if ((P->read_cookie = network_read(P->s_in, P->dbuf, - PCRYPT_MAXDSZ, 1, callback_pipe_read, P)) == NULL) - goto err1; - } - - /* Success! */ - return (P); - -err1: - free(P); -err0: - /* Failure! */ - return (NULL); -} - -/* Some data has been read. */ -static int -callback_pipe_read(void * cookie, ssize_t len) -{ - struct pipe_cookie * P = cookie; - - /* This read is no longer in progress. */ - P->read_cookie = NULL; - - /* Did we read EOF? */ - if (len == 0) - goto eof; - - /* Did the read fail? */ - if (len == -1) - goto fail; - - /* Did a packet read end prematurely? */ - if ((P->decr) && (len < PCRYPT_ESZ)) - goto fail; - - /* Encrypt or decrypt the data. */ - if (P->decr) { - if ((P->wlen = proto_crypt_dec(P->ebuf, P->dbuf, P->k)) == -1) - goto fail; - } else { - proto_crypt_enc(P->dbuf, (size_t)len, P->ebuf, P->k); - P->wlen = PCRYPT_ESZ; - } - - /* Write the encrypted or decrypted data. */ - if (P->decr) { - if ((P->write_cookie = network_write(P->s_out, P->dbuf, - (size_t)P->wlen, (size_t)P->wlen, callback_pipe_write, - P)) == NULL) - goto err0; - } else { - if ((P->write_cookie = network_write(P->s_out, P->ebuf, - (size_t)P->wlen, (size_t)P->wlen, callback_pipe_write, - P)) == NULL) - goto err0; - } - - /* Success! */ - return (0); - -fail: - /* Record that this connection is broken. */ - *(P->status) = -1; - - /* Inform the upstream that our status has changed. */ - return ((P->callback)(P->cookie)); - -eof: - /* We aren't going to write any more. */ - shutdown(P->s_out, SHUT_WR); - - /* Record that we have reached EOF. */ - *(P->status) = 0; - - /* Inform the upstream that our status has changed. */ - return ((P->callback)(P->cookie)); - -err0: - /* Failure! */ - return (-1); -} - -static int -callback_pipe_write(void * cookie, ssize_t len) -{ - struct pipe_cookie * P = cookie; - - /* This write is no longer in progress. */ - P->write_cookie = NULL; - - /* Did we fail to write everything? */ - if (len < P->wlen) - goto fail; - - /* Launch another read. */ - if (P->decr) { - if ((P->read_cookie = network_read(P->s_in, P->ebuf, - PCRYPT_ESZ, PCRYPT_ESZ, callback_pipe_read, P)) == NULL) - goto err0; - } else { - if ((P->read_cookie = network_read(P->s_in, P->dbuf, - PCRYPT_MAXDSZ, 1, callback_pipe_read, P)) == NULL) - goto err0; - } - - /* Success! */ - return (0); - -fail: - /* Record that this connection is broken. */ - *(P->status) = -1; - - /* Inform the upstream that our status has changed. */ - return ((P->callback)(P->cookie)); - -err0: - /* Failure! */ - return (-1); -} - -/** - * proto_pipe_cancel(cookie): - * Shut down the pipe created by proto_pipe for which ${cookie} was returned. - */ -void -proto_pipe_cancel(void * cookie) -{ - struct pipe_cookie * P = cookie; - - /* If a read or write is in progress, cancel it. */ - if (P->read_cookie) - network_read_cancel(P->read_cookie); - if (P->write_cookie) - network_write_cancel(P->write_cookie); - - /* Free the cookie. */ - free(P); -} diff -Nru spiped-1.6.1/proto/proto_pipe.h spiped-1.6.2/proto/proto_pipe.h --- spiped-1.6.1/proto/proto_pipe.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/proto/proto_pipe.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#ifndef _PROTO_PIPE_H_ -#define _PROTO_PIPE_H_ - -/* Opaque structure. */ -struct proto_keys; - -/** - * proto_pipe(s_in, s_out, decr, k, status, callback, cookie): - * Read bytes from ${s_in} and write them to ${s_out}. If ${decr} is non-zero - * then use ${k} to decrypt the bytes; otherwise use ${k} to encrypt them. - * If EOF is read, set ${status} to 0, and if an error is encountered set - * ${status} to -1; in either case, invoke ${callback}(${cookie}). Return a - * cookie which can be passed to proto_pipe_cancel. - */ -void * proto_pipe(int, int, int, struct proto_keys *, int *, - int (*)(void *), void *); - -/** - * proto_pipe_cancel(cookie): - * Shut down the pipe created by proto_pipe for which ${cookie} was returned. - */ -void proto_pipe_cancel(void *); - -#endif /* !_PROTO_PIPE_H_ */ diff -Nru spiped-1.6.1/spipe/main.c spiped-1.6.2/spipe/main.c --- spiped-1.6.1/spipe/main.c 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/spipe/main.c 2021-12-24 19:31:54.000000000 +0000 @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -50,6 +51,10 @@ ET->connection_error = 1; } + /* Shut it down if there's an error. */ + if (ET->connection_error) + graceful_shutdown_manual(); + /* Quit event loop. */ ET->conndone = 1; @@ -64,16 +69,25 @@ int rc; int i; - /* - * We need to cancel & join these threads in order, because otherwise - * we risk thread[1] closing a socket before thread[0] tries to - * shutdown() that socket. - */ + /* Cancel the threads. */ for (i = 0; i < 2; i++) { if ((rc = pthread_cancel(ET->threads[i])) != 0) { - warn0("pthread_cancel: %s", strerror(rc)); - goto err0; + /* + * According to the POSIX standard, a Thread ID should + * still be valid after pthread_exit has been invoked + * by the thread if pthread_join() has not yet been + * called. However, many platforms return ESRCH in + * this situation. + */ + if (rc != ESRCH) { + warn0("pthread_cancel: %s", strerror(rc)); + goto err0; + } } + } + + /* Wait for the threads to finish. */ + for (i = 0; i < 2; i++) { if ((rc = pthread_join(ET->threads[i], NULL)) != 0) { warn0("pthread_join: %s", strerror(rc)); goto err0; @@ -87,7 +101,7 @@ ET->conndone = 1; /* Success! */ - return(0); + return (0); err0: /* Failure! */ @@ -171,7 +185,7 @@ opt_t = optarg; break; GETOPT_OPT("-v"): - fprintf(stderr, "spipe 1.6.1\n"); + fprintf(stderr, "spipe 1.6.2\n"); exit(0); GETOPT_MISSING_ARG: warn0("Missing argument to %s", ch); @@ -241,34 +255,35 @@ if ((conn_cookie = proto_conn_create(s[1], sas_t, 0, opt_f, opt_g, opt_j, K, opt_o, callback_conndied, &ET)) == NULL) { warnp("Could not set up connection"); - goto err2; + goto err3; } - /* sas_t is now owned by proto_conn. */ + /* sas_t and s[1] are now owned by proto_conn. */ sas_t = NULL; + s[1] = -1; /* Push bits from the socket to stdout. */ if (pushbits(s[0], STDOUT_FILENO, &ET.threads[1])) { warnp("Could not push bits"); - goto err3; + goto err4; } /* Push bits from stdin into the socket. */ if (pushbits(STDIN_FILENO, s[0], &ET.threads[0])) { warnp("Could not push bits"); - goto err4; + goto err5; } /* Register a handler for SIGTERM. */ if (graceful_shutdown_initialize(&callback_graceful_shutdown, &ET)) { warn0("Failed to start graceful_shutdown timer"); - goto err5; + goto err6; } /* Loop until we're done with the connection. */ if (events_spin(&ET.conndone)) { warnp("Error running event loop"); - goto err3; + goto err4; } /* Wait for threads to finish (if necessary) */ @@ -284,7 +299,8 @@ } /* Clean up. */ - free(K); + close(s[0]); + proto_crypt_secret_free(K); /* Handle a connection error. */ if (ET.connection_error) @@ -293,20 +309,24 @@ /* Success! */ exit(0); -err5: +err6: if ((rc = pthread_cancel(ET.threads[0])) != 0) warn0("pthread_cancel: %s", strerror(rc)); if ((rc = pthread_join(ET.threads[0], NULL)) != 0) warn0("pthread_join: %s", strerror(rc)); -err4: +err5: if ((rc = pthread_cancel(ET.threads[1])) != 0) warn0("pthread_cancel: %s", strerror(rc)); if ((rc = pthread_join(ET.threads[1], NULL)) != 0) warn0("pthread_join: %s", strerror(rc)); -err3: +err4: proto_conn_drop(conn_cookie, PROTO_CONN_CANCELLED); +err3: + if (s[1] != -1) + close(s[1]); + close(s[0]); err2: - free(K); + proto_crypt_secret_free(K); err1: sock_addr_freelist(sas_t); err0: diff -Nru spiped-1.6.1/spipe/Makefile spiped-1.6.2/spipe/Makefile --- spiped-1.6.1/spipe/Makefile 2020-04-05 18:24:20.000000000 +0000 +++ spiped-1.6.2/spipe/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -2,11 +2,12 @@ # AUTOGENERATED FILE, DO NOT EDIT PROG=spipe MAN1=spipe.1 -SRCS=main.c pushbits.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c graceful_shutdown.c sha256.c sha256_shani.c elasticarray.c ptrheap.c timerqueue.c asprintf.c entropy.c getopt.c insecure_memzero.c monoclock.c noeintr.c sock.c warnp.c cpusupport_x86_aesni.c cpusupport_x86_rdrand.c cpusupport_x86_shani.c cpusupport_x86_ssse3.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c events.c network_connect.c network_read.c network_write.c crypto_aes.c crypto_aes_aesni.c crypto_aesctr.c crypto_dh.c crypto_dh_group14.c crypto_entropy.c crypto_entropy_rdrand.c crypto_verify_bytes.c -IDIRS=-I../proto -I../lib/util -I../libcperciva/alg -I../libcperciva/datastruct -I../libcperciva/util -I../libcperciva/cpusupport -I../libcperciva/events -I../libcperciva/network -I../libcperciva/crypto +SRCS=main.c pushbits.c +IDIRS=-I../libcperciva/crypto -I../libcperciva/events -I../libcperciva/util -I../lib/proto -I../lib/util LDADD_REQ=-lcrypto -lpthread SUBDIR_DEPTH=.. RELATIVE_DIR=spipe +LIBALL=../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -35,86 +36,10 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} -main.o: main.c ../libcperciva/events/events.h ../libcperciva/util/getopt.h ../lib/util/graceful_shutdown.h ../libcperciva/util/parsenum.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../proto/proto_conn.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h pushbits.h +main.o: main.c ../libcperciva/events/events.h ../libcperciva/util/getopt.h ../lib/util/graceful_shutdown.h ../libcperciva/util/parsenum.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../lib/proto/proto_conn.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h pushbits.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -pushbits.o: pushbits.c ../libcperciva/util/noeintr.h ../libcperciva/util/warnp.h pushbits.h +pushbits.o: pushbits.c ../libcperciva/util/noeintr.h ../lib/util/pthread_create_blocking_np.h ../libcperciva/util/warnp.h pushbits.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c pushbits.c -o pushbits.o -proto_conn.o: ../proto/proto_conn.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_handshake.h ../proto/proto_pipe.h ../proto/proto_conn.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_conn.c -o proto_conn.o -proto_crypt.o: ../proto/proto_crypt.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_verify_bytes.h ../libcperciva/alg/sha256.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_crypt.c -o proto_crypt.o -proto_handshake.o: ../proto/proto_handshake.c ../libcperciva/crypto/crypto_entropy.h ../libcperciva/network/network.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_handshake.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_handshake.c -o proto_handshake.o -proto_pipe.o: ../proto/proto_pipe.c ../libcperciva/network/network.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_pipe.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_pipe.c -o proto_pipe.o -graceful_shutdown.o: ../lib/util/graceful_shutdown.c ../libcperciva/events/events.h ../libcperciva/util/warnp.h ../lib/util/graceful_shutdown.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/graceful_shutdown.c -o graceful_shutdown.o -sha256.o: ../libcperciva/alg/sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256_shani.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../libcperciva/alg/sha256.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256.c -o sha256.o -sha256_shani.o: ../libcperciva/alg/sha256_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_SHANI} ${CFLAGS_X86_SSSE3} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256_shani.c -o sha256_shani.o -elasticarray.o: ../libcperciva/datastruct/elasticarray.c ../libcperciva/datastruct/elasticarray.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o -ptrheap.o: ../libcperciva/datastruct/ptrheap.c ../libcperciva/datastruct/elasticarray.h ../libcperciva/datastruct/ptrheap.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o -timerqueue.o: ../libcperciva/datastruct/timerqueue.c ../libcperciva/datastruct/ptrheap.h ../libcperciva/datastruct/timerqueue.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o -asprintf.o: ../libcperciva/util/asprintf.c ../libcperciva/util/asprintf.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/asprintf.c -o asprintf.o -entropy.o: ../libcperciva/util/entropy.c ../libcperciva/util/warnp.h ../libcperciva/util/entropy.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/entropy.c -o entropy.o -getopt.o: ../libcperciva/util/getopt.c ../libcperciva/util/getopt.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/getopt.c -o getopt.o -insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ../libcperciva/util/insecure_memzero.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o -monoclock.o: ../libcperciva/util/monoclock.c ../libcperciva/util/warnp.h ../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/monoclock.c -o monoclock.o -noeintr.o: ../libcperciva/util/noeintr.c ../libcperciva/util/noeintr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/noeintr.c -o noeintr.o -sock.o: ../libcperciva/util/sock.c ../libcperciva/util/imalloc.h ../libcperciva/util/parsenum.h ../libcperciva/util/warnp.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock.c -o sock.o -warnp.o: ../libcperciva/util/warnp.c ../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/warnp.c -o warnp.o -cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o -cpusupport_x86_rdrand.o: ../libcperciva/cpusupport/cpusupport_x86_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_rdrand.c -o cpusupport_x86_rdrand.o -cpusupport_x86_shani.o: ../libcperciva/cpusupport/cpusupport_x86_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_shani.c -o cpusupport_x86_shani.o -cpusupport_x86_ssse3.o: ../libcperciva/cpusupport/cpusupport_x86_ssse3.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_ssse3.c -o cpusupport_x86_ssse3.o -events_immediate.o: ../libcperciva/events/events_immediate.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o -events_network.o: ../libcperciva/events/events_network.c ../libcperciva/util/ctassert.h ../libcperciva/datastruct/elasticarray.h ../libcperciva/util/warnp.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network.c -o events_network.o -events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ../libcperciva/util/monoclock.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o -events_timer.o: ../libcperciva/events/events_timer.c ../libcperciva/util/monoclock.h ../libcperciva/datastruct/timerqueue.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_timer.c -o events_timer.o -events.o: ../libcperciva/events/events.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events.c -o events.o -network_connect.o: ../libcperciva/network/network_connect.c ../libcperciva/events/events.h ../libcperciva/util/sock.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_connect.c -o network_connect.o -network_read.o: ../libcperciva/network/network_read.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_read.c -o network_read.o -network_write.o: ../libcperciva/network/network_write.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/util/warnp.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_write.c -o network_write.o -crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o -crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o -crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o -crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_dh_group14.h ../libcperciva/crypto/crypto_entropy.h ../libcperciva/crypto/crypto_dh.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o -crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ../libcperciva/crypto/crypto_dh_group14.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o -crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h ../libcperciva/util/entropy.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/crypto/crypto_entropy.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o -crypto_entropy_rdrand.o: ../libcperciva/crypto/crypto_entropy_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_RDRAND} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy_rdrand.c -o crypto_entropy_rdrand.o -crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ../libcperciva/crypto/crypto_verify_bytes.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o diff -Nru spiped-1.6.1/spipe/pushbits.c spiped-1.6.2/spipe/pushbits.c --- spiped-1.6.1/spipe/pushbits.c 2019-11-06 00:04:00.000000000 +0000 +++ spiped-1.6.2/spipe/pushbits.c 2021-12-09 22:15:31.000000000 +0000 @@ -9,6 +9,7 @@ #include #include "noeintr.h" +#include "pthread_create_blocking_np.h" #include "warnp.h" #include "pushbits.h" @@ -24,9 +25,6 @@ { struct push * P = cookie; - /* Close the descriptor (we either hit EOF, or received a cancel). */ - close(P->in); - /* * Try to shut down the descriptor we're writing to. Ignore ENOTSOCK, * since it might, indeed, not be a socket. @@ -84,7 +82,9 @@ /** * pushbits(in, out, thr): * Create a thread which copies data from ${in} to ${out} and - * store the thread ID in ${thr}. + * store the thread ID in ${thr}. Wait until ${thr} has started. + * If ${out} is a socket, disable writing to it after the thread + * exits. */ int pushbits(int in, int out, pthread_t * thr) @@ -99,8 +99,8 @@ P->out = out; /* Create thread. */ - if ((rc = pthread_create(thr, NULL, workthread, P)) != 0) { - warn0("pthread_create: %s", strerror(rc)); + if ((rc = pthread_create_blocking_np(thr, NULL, workthread, P)) != 0) { + warn0("pthread_create_blocking_np: %s", strerror(rc)); goto err1; } diff -Nru spiped-1.6.1/spipe/pushbits.h spiped-1.6.2/spipe/pushbits.h --- spiped-1.6.1/spipe/pushbits.h 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/spipe/pushbits.h 2021-12-09 22:15:31.000000000 +0000 @@ -6,7 +6,9 @@ /** * pushbits(in, out, thr): * Create a thread which copies data from ${in} to ${out} and - * store the thread ID in ${thr}. + * store the thread ID in ${thr}. Wait until ${thr} has started. + * If ${out} is a socket, disable writing to it after the thread + * exits. */ int pushbits(int, int, pthread_t *); diff -Nru spiped-1.6.1/spipe/spipe.1 spiped-1.6.2/spipe/spipe.1 --- spiped-1.6.1/spipe/spipe.1 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/spipe/spipe.1 2021-12-24 19:31:54.000000000 +0000 @@ -22,7 +22,7 @@ .\" 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. -.TH SPIPE 1 "April 05, 2020" "spiped 1.6.1" "spipe README" +.TH SPIPE 1 "December 24, 2021" "spiped 1.6.2" "spipe README" .SH NAME spipe - spiped client utility .SH SYNOPSIS diff -Nru spiped-1.6.1/spiped/dispatch.c spiped-1.6.2/spiped/dispatch.c --- spiped-1.6.1/spiped/dispatch.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/spiped/dispatch.c 2020-12-05 21:26:44.000000000 +0000 @@ -92,6 +92,12 @@ { int rc = 0; + /* Warn about reaching nconn_max. */ + if (A->nconn >= A->nconn_max) { + warn0("Maximum number of connections (%zu) reached", + A->nconn_max); + } + /* If we can, accept a new connection. */ if ((A->nconn < A->nconn_max) && (A->accept_cookie == NULL) && !A->shutdown_requested) { @@ -224,9 +230,9 @@ * perfect forward secrecy. Enable transport layer keep-alives (if applicable) * if and only if ${nokeepalive} is zero. Drop connections if the handshake or * connecting to the target takes more than ${timeo} seconds. If - * dispatch_request_shutdown is called then ${conndone} is set to a non-zero + * dispatch_request_shutdown() is called then ${conndone} is set to a non-zero * value as soon as there are no active connections. Return a cookie which can - * be passed to dispatch_shutdown and dispatch_request_shutdown. + * be passed to dispatch_shutdown() and dispatch_request_shutdown(). */ void * dispatch_accept(int s, const char * tgt, double rtime, struct sock_addr ** sas, @@ -292,7 +298,7 @@ /** * dispatch_shutdown(dispatch_cookie): - * Stops and frees memory associated with the ${dispatch_cookie}. + * Stop the server, free memory, and close the listening socket. */ void dispatch_shutdown(void * dispatch_cookie) @@ -315,12 +321,13 @@ if (A->T != NULL) dnsthread_kill(A->T); sock_addr_freelist(A->sas); + close(A->s); free(A); } /** * dispatch_request_shutdown(dispatch_cookie): - * Requests a shutdown: Stop accepting new connections and notify once + * Request a shutdown: Stop accepting new connections and notify once * every existing connection ended. */ void diff -Nru spiped-1.6.1/spiped/dispatch.h spiped-1.6.2/spiped/dispatch.h --- spiped-1.6.1/spiped/dispatch.h 2017-04-21 06:04:42.000000000 +0000 +++ spiped-1.6.2/spiped/dispatch.h 2020-12-05 21:26:44.000000000 +0000 @@ -20,22 +20,22 @@ * perfect forward secrecy. Enable transport layer keep-alives (if applicable) * if and only if ${nokeepalive} is zero. Drop connections if the handshake or * connecting to the target takes more than ${timeo} seconds. If - * dispatch_request_shutdown is called then ${conndone} is set to a non-zero + * dispatch_request_shutdown() is called then ${conndone} is set to a non-zero * value as soon as there are no active connections. Return a cookie which can - * be passed to dispatch_shutdown and dispatch_request_shutdown. + * be passed to dispatch_shutdown() and dispatch_request_shutdown(). */ void * dispatch_accept(int, const char *, double, struct sock_addr **, int, int, int, int, const struct proto_secret *, size_t, double, int *); /** * dispatch_shutdown(dispatch_cookie): - * Stops and frees memory associated with the ${dispatch_cookie}. + * Stop the server, free memory, and close the listening socket. */ void dispatch_shutdown(void *); /** * dispatch_request_shutdown(dispatch_cookie): - * Requests a shutdown: Stop accepting new connections and notify once + * Request a shutdown: Stop accepting new connections and notify once * every existing connection ended. */ void dispatch_request_shutdown(void *); diff -Nru spiped-1.6.1/spiped/main.c spiped-1.6.2/spiped/main.c --- spiped-1.6.1/spiped/main.c 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/spiped/main.c 2021-12-24 19:31:54.000000000 +0000 @@ -27,7 +27,7 @@ "-t -k \n" " [-DFj] [-f | -g] [-n ] " "[-o ]\n" - " [-p ] [-r | -R]\n" + " [-p ] [-r | -R] [--syslog]\n" " [-u { | <:groupname> | }]\n" " spiped -v\n"); exit(1); @@ -40,7 +40,7 @@ dispatch_request_shutdown(dispatch_cookie); /* Success! */ - return(0); + return (0); } /* @@ -80,6 +80,7 @@ int opt_r_set = 0; double opt_r = 0.0; int opt_R = 0; + int opt_syslog = 0; const char * opt_s = NULL; const char * opt_t = NULL; const char * opt_u = NULL; @@ -177,6 +178,11 @@ usage(); opt_s = optarg; break; + GETOPT_OPT("--syslog"): + if (opt_syslog) + usage(); + opt_syslog = 1; + break; GETOPT_OPTARG("-t"): if (opt_t) usage(); @@ -188,7 +194,7 @@ opt_u = optarg; break; GETOPT_OPT("-v"): - fprintf(stderr, "spiped 1.6.1\n"); + fprintf(stderr, "spiped 1.6.2\n"); exit(0); GETOPT_MISSING_ARG: warn0("Missing argument to %s", ch); @@ -257,9 +263,15 @@ } /* Daemonize early if we're going to wait for DNS to be ready. */ - if (opt_D && !opt_F && daemonize(pidfilename)) { - warnp("Failed to daemonize"); - goto err1; + if (opt_D && !opt_F) { + if (daemonize(pidfilename)) { + warnp("Failed to daemonize"); + goto err1; + } + + /* Send to syslog (if applicable). */ + if (opt_syslog) + warnp_syslog(1); } /* Resolve source address. */ @@ -302,15 +314,20 @@ goto err4; /* Daemonize and write pid. */ - if (!opt_D && !opt_F && daemonize(pidfilename)) { - warnp("Failed to daemonize"); - goto err4; + if (!opt_D && !opt_F) { + if (daemonize(pidfilename)) { + warnp("Failed to daemonize"); + goto err5; + } + /* Send to syslog (if applicable). */ + if (opt_syslog) + warnp_syslog(1); } /* Drop privileges (if applicable). */ if (opt_u && setuidgid(opt_u, SETUIDGID_SGROUP_LEAVE_WARN)) { warnp("Failed to drop privileges"); - goto err4; + goto err5; } /* Start accepting connections. */ @@ -318,17 +335,18 @@ sas_t, opt_d, opt_f, opt_g, opt_j, K, opt_n, opt_o, &conndone)) == NULL) { warnp("Failed to initialize connection acceptor"); - goto err4; + goto err5; } - /* dispatch is now maintaining sas_t. */ + /* dispatch is now maintaining sas_t and s. */ sas_t = NULL; + s = -1; /* Register a handler for SIGTERM. */ if (graceful_shutdown_initialize(&callback_graceful_shutdown, dispatch_cookie)) { warn0("Failed to start graceful_shutdown timer"); - goto err5; + goto err6; } /* @@ -337,14 +355,14 @@ */ if (events_spin(&conndone)) { warnp("Error running event loop"); - goto err5; + goto err6; } /* Stop accepting connections and shut down the dispatcher. */ dispatch_shutdown(dispatch_cookie); /* Free the protocol secret structure. */ - free(K); + proto_crypt_secret_free(K); /* Free arrays of resolved addresses. */ sock_addr_freelist(sas_s); @@ -355,10 +373,13 @@ /* Success! */ exit(0); -err5: +err6: dispatch_shutdown(dispatch_cookie); +err5: + if (s != -1) + close(s); err4: - free(K); + proto_crypt_secret_free(K); err3: sock_addr_freelist(sas_t); err2: diff -Nru spiped-1.6.1/spiped/Makefile spiped-1.6.2/spiped/Makefile --- spiped-1.6.1/spiped/Makefile 2020-04-05 18:24:18.000000000 +0000 +++ spiped-1.6.2/spiped/Makefile 2021-12-24 19:31:53.000000000 +0000 @@ -2,11 +2,12 @@ # AUTOGENERATED FILE, DO NOT EDIT PROG=spiped MAN1=spiped.1 -SRCS=main.c dispatch.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c sha256.c sha256_shani.c elasticarray.c ptrheap.c timerqueue.c dnsthread.c graceful_shutdown.c asprintf.c daemonize.c entropy.c getopt.c insecure_memzero.c monoclock.c noeintr.c setuidgid.c sock.c sock_util.c warnp.c cpusupport_x86_aesni.c cpusupport_x86_rdrand.c cpusupport_x86_shani.c cpusupport_x86_ssse3.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c events.c network_accept.c network_connect.c network_read.c network_write.c crypto_aes.c crypto_aes_aesni.c crypto_aesctr.c crypto_dh.c crypto_dh_group14.c crypto_entropy.c crypto_entropy_rdrand.c crypto_verify_bytes.c -IDIRS=-I../proto -I../libcperciva/alg -I../libcperciva/datastruct -I../lib/dnsthread -I../lib/util -I../libcperciva/util -I../libcperciva/cpusupport -I../libcperciva/events -I../libcperciva/network -I../libcperciva/crypto +SRCS=main.c dispatch.c +IDIRS=-I../libcperciva/crypto -I../libcperciva/events -I../libcperciva/network -I../libcperciva/util -I../lib/dnsthread -I../lib/proto -I../lib/util LDADD_REQ=-lcrypto -lpthread SUBDIR_DEPTH=.. RELATIVE_DIR=spiped +LIBALL=../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -35,96 +36,10 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} -main.o: main.c ../libcperciva/util/asprintf.h ../libcperciva/util/daemonize.h ../libcperciva/events/events.h ../libcperciva/util/getopt.h ../lib/util/graceful_shutdown.h ../libcperciva/util/parsenum.h ../libcperciva/util/setuidgid.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h dispatch.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h +main.o: main.c ../libcperciva/util/asprintf.h ../libcperciva/util/daemonize.h ../libcperciva/events/events.h ../libcperciva/util/getopt.h ../lib/util/graceful_shutdown.h ../libcperciva/util/parsenum.h ../libcperciva/util/setuidgid.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h dispatch.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -dispatch.o: dispatch.c ../lib/dnsthread/dnsthread.h ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../libcperciva/util/sock_util.h ../libcperciva/util/warnp.h ../proto/proto_conn.h dispatch.h +dispatch.o: dispatch.c ../lib/dnsthread/dnsthread.h ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../libcperciva/util/sock_util.h ../libcperciva/util/warnp.h ../lib/proto/proto_conn.h dispatch.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c dispatch.c -o dispatch.o -proto_conn.o: ../proto/proto_conn.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_handshake.h ../proto/proto_pipe.h ../proto/proto_conn.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_conn.c -o proto_conn.o -proto_crypt.o: ../proto/proto_crypt.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_verify_bytes.h ../libcperciva/alg/sha256.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_crypt.c -o proto_crypt.o -proto_handshake.o: ../proto/proto_handshake.c ../libcperciva/crypto/crypto_entropy.h ../libcperciva/network/network.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_handshake.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_handshake.c -o proto_handshake.o -proto_pipe.o: ../proto/proto_pipe.c ../libcperciva/network/network.h ../proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../proto/proto_pipe.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../proto/proto_pipe.c -o proto_pipe.o -sha256.o: ../libcperciva/alg/sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256_shani.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../libcperciva/alg/sha256.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256.c -o sha256.o -sha256_shani.o: ../libcperciva/alg/sha256_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_SHANI} ${CFLAGS_X86_SSSE3} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256_shani.c -o sha256_shani.o -elasticarray.o: ../libcperciva/datastruct/elasticarray.c ../libcperciva/datastruct/elasticarray.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o -ptrheap.o: ../libcperciva/datastruct/ptrheap.c ../libcperciva/datastruct/elasticarray.h ../libcperciva/datastruct/ptrheap.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o -timerqueue.o: ../libcperciva/datastruct/timerqueue.c ../libcperciva/datastruct/ptrheap.h ../libcperciva/datastruct/timerqueue.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o -dnsthread.o: ../lib/dnsthread/dnsthread.c ../libcperciva/events/events.h ../libcperciva/util/noeintr.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../lib/dnsthread/dnsthread.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/dnsthread/dnsthread.c -o dnsthread.o -graceful_shutdown.o: ../lib/util/graceful_shutdown.c ../libcperciva/events/events.h ../libcperciva/util/warnp.h ../lib/util/graceful_shutdown.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/graceful_shutdown.c -o graceful_shutdown.o -asprintf.o: ../libcperciva/util/asprintf.c ../libcperciva/util/asprintf.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/asprintf.c -o asprintf.o -daemonize.o: ../libcperciva/util/daemonize.c ../libcperciva/util/noeintr.h ../libcperciva/util/warnp.h ../libcperciva/util/daemonize.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/daemonize.c -o daemonize.o -entropy.o: ../libcperciva/util/entropy.c ../libcperciva/util/warnp.h ../libcperciva/util/entropy.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/entropy.c -o entropy.o -getopt.o: ../libcperciva/util/getopt.c ../libcperciva/util/getopt.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/getopt.c -o getopt.o -insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ../libcperciva/util/insecure_memzero.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o -monoclock.o: ../libcperciva/util/monoclock.c ../libcperciva/util/warnp.h ../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/monoclock.c -o monoclock.o -noeintr.o: ../libcperciva/util/noeintr.c ../libcperciva/util/noeintr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/noeintr.c -o noeintr.o -setuidgid.o: ../libcperciva/util/setuidgid.c ../libcperciva/util/parsenum.h ../libcperciva/util/warnp.h ../libcperciva/util/setuidgid.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/setuidgid.c -o setuidgid.o -sock.o: ../libcperciva/util/sock.c ../libcperciva/util/imalloc.h ../libcperciva/util/parsenum.h ../libcperciva/util/warnp.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock.c -o sock.o -sock_util.o: ../libcperciva/util/sock_util.c ../libcperciva/util/asprintf.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h ../libcperciva/util/sock_util.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock_util.c -o sock_util.o -warnp.o: ../libcperciva/util/warnp.c ../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/warnp.c -o warnp.o -cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o -cpusupport_x86_rdrand.o: ../libcperciva/cpusupport/cpusupport_x86_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_rdrand.c -o cpusupport_x86_rdrand.o -cpusupport_x86_shani.o: ../libcperciva/cpusupport/cpusupport_x86_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_shani.c -o cpusupport_x86_shani.o -cpusupport_x86_ssse3.o: ../libcperciva/cpusupport/cpusupport_x86_ssse3.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_ssse3.c -o cpusupport_x86_ssse3.o -events_immediate.o: ../libcperciva/events/events_immediate.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o -events_network.o: ../libcperciva/events/events_network.c ../libcperciva/util/ctassert.h ../libcperciva/datastruct/elasticarray.h ../libcperciva/util/warnp.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network.c -o events_network.o -events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ../libcperciva/util/monoclock.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o -events_timer.o: ../libcperciva/events/events_timer.c ../libcperciva/util/monoclock.h ../libcperciva/datastruct/timerqueue.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_timer.c -o events_timer.o -events.o: ../libcperciva/events/events.c ../libcperciva/datastruct/mpool.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events.c -o events.o -network_accept.o: ../libcperciva/network/network_accept.c ../libcperciva/events/events.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_accept.c -o network_accept.o -network_connect.o: ../libcperciva/network/network_connect.c ../libcperciva/events/events.h ../libcperciva/util/sock.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_connect.c -o network_connect.o -network_read.o: ../libcperciva/network/network_read.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_read.c -o network_read.o -network_write.o: ../libcperciva/network/network_write.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/util/warnp.h ../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_write.c -o network_write.o -crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o -crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o -crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o -crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_dh_group14.h ../libcperciva/crypto/crypto_entropy.h ../libcperciva/crypto/crypto_dh.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o -crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ../libcperciva/crypto/crypto_dh_group14.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o -crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h ../libcperciva/util/entropy.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/crypto/crypto_entropy.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o -crypto_entropy_rdrand.o: ../libcperciva/crypto/crypto_entropy_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_RDRAND} -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy_rdrand.c -o crypto_entropy_rdrand.o -crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ../libcperciva/crypto/crypto_verify_bytes.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o diff -Nru spiped-1.6.1/spiped/spiped.1 spiped-1.6.2/spiped/spiped.1 --- spiped-1.6.1/spiped/spiped.1 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/spiped/spiped.1 2021-12-24 19:31:54.000000000 +0000 @@ -22,7 +22,7 @@ .\" 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. -.TH SPIPED 1 "April 05, 2020" "spiped 1.6.1" "spiped README" +.TH SPIPED 1 "December 24, 2021" "spiped 1.6.2" "spiped README" .SH NAME spiped - secure pipe daemon .SH SYNOPSIS @@ -35,8 +35,10 @@ [\-f | \-g] [\-n ] [\-o ] +.br [\-p ] [\-r | \-R] +[\-\-syslog] .br [\-u | <:groupname> | ] .br @@ -154,6 +156,10 @@ .B \-R Disable target address re-resolution. .TP +.B \-\-syslog +After daemonizing, send warnings to syslog instead of stderr. Has +no effect if -F (run in foreground) is used. +.TP .B \-u | <:groupname> | After binding a socket, change the user to .I username diff -Nru spiped-1.6.1/STYLE spiped-1.6.2/STYLE --- spiped-1.6.1/STYLE 2019-11-06 00:04:00.000000000 +0000 +++ spiped-1.6.2/STYLE 2021-07-04 18:08:39.000000000 +0000 @@ -176,9 +176,18 @@ different compiler flags. Such a file should start with #include "cpusupport.h" #ifdef CPUSUPPORT_FOO_BAR + /** + * CPUSUPPORT CFLAGS: FOO_BAR FOO_BAZ + */ and end with #endif /* CPUSUPPORT_FOO_BAR */ +For example, we could have + #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) + /** + * CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3 + */ + Functions for which special CPU-feature-exploiting variants exist should take the form { @@ -194,3 +203,6 @@ /* Normal implementation of the function. */ } + +If there are multiple CPU-feature-exploiting variants, the `if` could instead +be a `switch` which invokes the appropriate variant function. diff -Nru spiped-1.6.1/tests/01-connection-open-close-single.sh spiped-1.6.2/tests/01-connection-open-close-single.sh --- spiped-1.6.1/tests/01-connection-open-close-single.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/01-connection-open-close-single.sh 2020-09-02 04:32:10.000000000 +0000 @@ -17,7 +17,7 @@ setup_spiped_encryption_server # Open and close a connection. - setup_check_variables + setup_check_variables "open close" ( echo "" | ${nc_client_binary} ${src_sock} echo $? > ${c_exitfile} diff -Nru spiped-1.6.1/tests/02-connection-open-timeout-single.sh spiped-1.6.2/tests/02-connection-open-timeout-single.sh --- spiped-1.6.1/tests/02-connection-open-timeout-single.sh 2019-11-09 08:19:05.000000000 +0000 +++ spiped-1.6.2/tests/02-connection-open-timeout-single.sh 2020-09-02 04:32:10.000000000 +0000 @@ -18,7 +18,7 @@ setup_spiped_encryption_server # Open and close a connection, keeping it open for 2 seconds. - setup_check_variables + setup_check_variables "open 2 seconds close" ( ( echo "" ; sleep 2 ) | \ ${nc_client_binary} ${src_sock} diff -Nru spiped-1.6.1/tests/03-connection-open-close-double.sh spiped-1.6.2/tests/03-connection-open-close-double.sh --- spiped-1.6.1/tests/03-connection-open-close-double.sh 2019-11-09 08:19:05.000000000 +0000 +++ spiped-1.6.2/tests/03-connection-open-close-double.sh 2020-09-02 04:32:10.000000000 +0000 @@ -18,7 +18,7 @@ setup_spiped_encryption_server # Open and close a connection, keeping it open for 2 seconds. - setup_check_variables + setup_check_variables "multi open 2 seconds close" ( ( echo "" ; sleep 2 ) | \ ${nc_client_binary} ${src_sock} @@ -27,7 +27,8 @@ ) & # Open another connection (before the first has closed). - setup_check_variables + # Don't check that we've already finished the previous test. + setup_check_variables "multi open close" 0 ( echo "" | ${nc_client_binary} ${src_sock} echo $? > ${c_exitfile} diff -Nru spiped-1.6.1/tests/04-send-data-spipe.sh spiped-1.6.2/tests/04-send-data-spipe.sh --- spiped-1.6.1/tests/04-send-data-spipe.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/04-send-data-spipe.sh 2021-08-01 23:41:28.000000000 +0000 @@ -3,11 +3,14 @@ # Goal of this test: # - establish a connection to a spiped server. # - send data via spipe -# - the received file should match lorem-send.txt +# - the received file should match the original one +# - also, check that we quit immediately if we can't connect ### Constants c_valgrind_min=1 ncat_output="${s_basename}-ncat-output.txt" +bad_target_stderr="${s_basename}-bad-target-stderr.txt" +sendfile=${scriptdir}/shared_test_functions.sh ### Actual command scenario_cmd() { @@ -15,19 +18,21 @@ setup_spiped_decryption_server ${ncat_output} # Send data. - setup_check_variables + setup_check_variables "spipe send" ( - cat ${scriptdir}/lorem-send.txt | \ - ${c_valgrind_cmd} ${spipe_binary} \ - -t ${mid_sock} -k /dev/null + ${c_valgrind_cmd} ${spipe_binary} \ + -t ${mid_sock} -k /dev/null \ + < ${sendfile} echo $? > ${c_exitfile} ) # Wait for server(s) to quit. servers_stop - setup_check_variables - if ! cmp -s ${ncat_output} ${scriptdir}/lorem-send.txt; then + # Check output. This must be after nc-server has stopped, to + # ensure that no data is buffered and not yet written to disk. + setup_check_variables "spipe send output" + if ! cmp -s ${ncat_output} ${sendfile}; then if [ ${VERBOSE} -ne 0 ]; then printf "Test output does not match input;" 1>&2 printf -- " output is:\n----\n" 1>&2 @@ -38,4 +43,16 @@ else echo 0 fi > ${c_exitfile} + + # Disable normal valgrind use: the "spipe fail bad target" test + # invokes an `exit(1)` in pushbits.c, which does not attempt to + # clean up after itself. + c_valgrind_min=2 + + # Should quit immediately if the target fails to connect. + setup_check_variables "spipe fail bad target" + ${c_valgrind_cmd} ${spipe_binary} \ + -t /this-is-a-fake.socket -k /dev/null \ + 2> "${bad_target_stderr}" + expected_exitcode 1 $? > ${c_exitfile} } diff -Nru spiped-1.6.1/tests/05-send-data-spiped.sh spiped-1.6.2/tests/05-send-data-spiped.sh --- spiped-1.6.1/tests/05-send-data-spiped.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/05-send-data-spiped.sh 2021-08-01 23:41:28.000000000 +0000 @@ -3,12 +3,13 @@ # Goal of this test: # - create a pair of spiped servers (encryption, decryption) # - establish a connection to the encryption spiped server -# - open one connection, send lorem-send.txt, close the connection -# - the received file should match lorem-send.txt +# - open one connection, send a file, close the connection +# - the received file should match the original one ### Constants c_valgrind_min=1 ncat_output="${s_basename}-ncat-output.txt" +sendfile=${scriptdir}/shared_test_functions.sh ### Actual command scenario_cmd() { @@ -17,18 +18,17 @@ setup_spiped_encryption_server # Open and close a connection. - setup_check_variables + setup_check_variables "spiped send" ( - cat ${scriptdir}/lorem-send.txt | \ - ${nc_client_binary} ${src_sock} + ${nc_client_binary} ${src_sock} < ${sendfile} echo $? > ${c_exitfile} ) # Wait for server(s) to quit. servers_stop - setup_check_variables - if ! cmp -s ${ncat_output} ${scriptdir}/lorem-send.txt; then + setup_check_variables "spiped send output" + if ! cmp -s ${ncat_output} ${sendfile}; then if [ ${VERBOSE} -ne 0 ]; then printf "Test output does not match input;" 1>&2 printf -- " output is:\n----\n" 1>&2 diff -Nru spiped-1.6.1/tests/06-send-data-system-spiped.sh spiped-1.6.2/tests/06-send-data-system-spiped.sh --- spiped-1.6.1/tests/06-send-data-system-spiped.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/06-send-data-system-spiped.sh 2021-08-01 23:41:28.000000000 +0000 @@ -4,19 +4,20 @@ # - create a pair of spiped servers (encryption, decryption), where # the decryption server uses the system-installed spiped binary # - establish a connection to the encryption spiped server -# - open one connection, send lorem-send.txt, close the connection -# - the received file should match lorem-send.txt +# - open one connection, send a file, close the connection +# - the received file should match the original one ### Constants c_valgrind_min=1 ncat_output="${s_basename}-ncat-output.txt" +sendfile=${scriptdir}/shared_test_functions.sh ### Actual command scenario_cmd() { if [ ! -n "${system_spiped_binary}" ]; then - printf "no system spiped, or it is too old... " + printf "no system spiped, or it is too old... " 1>&2 # Suppress warning - setup_check_variables + setup_check_variables "system spiped skip" echo "-1" > ${c_exitfile} return; fi @@ -26,18 +27,17 @@ setup_spiped_encryption_server # Open and close a connection. - setup_check_variables + setup_check_variables "system spiped" ( - cat ${scriptdir}/lorem-send.txt | \ - ${nc_client_binary} ${src_sock} + ${nc_client_binary} ${src_sock} < ${sendfile} echo $? > ${c_exitfile} ) # Wait for server(s) to quit. servers_stop - setup_check_variables - if ! cmp -s ${ncat_output} ${scriptdir}/lorem-send.txt; then + setup_check_variables "system spiped output" + if ! cmp -s ${ncat_output} ${sendfile}; then if [ ${VERBOSE} -ne 0 ]; then printf "Test output does not match input;" 1>&2 printf -- " output is:\n----\n" 1>&2 diff -Nru spiped-1.6.1/tests/07-dnsthread-resolve.sh spiped-1.6.2/tests/07-dnsthread-resolve.sh --- spiped-1.6.1/tests/07-dnsthread-resolve.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/07-dnsthread-resolve.sh 2020-09-02 04:32:10.000000000 +0000 @@ -28,7 +28,7 @@ for addr in ${addrs} do - setup_check_variables + setup_check_variables "dnsthread-resolve ${addr}" ${c_valgrind_cmd} \ ${dnsthread_resolve} ${addr} >> ${addr_output} echo $? > ${c_exitfile} diff -Nru spiped-1.6.1/tests/08-send-data-spipe-limited-bps.sh spiped-1.6.2/tests/08-send-data-spipe-limited-bps.sh --- spiped-1.6.1/tests/08-send-data-spipe-limited-bps.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/08-send-data-spipe-limited-bps.sh 2021-08-01 23:41:28.000000000 +0000 @@ -7,21 +7,23 @@ ### Constants c_valgrind_min=1 echo_limited_output="${s_basename}-echo-limited-output.txt" +sendfile=${scriptdir}/shared_test_functions.sh ### Actual command scenario_cmd() { - # Send a file through a rate-limited echo server. Echo - # server is limited to 1000 bytes per second. - setup_check_variables + # Set up an echo server, limited to 1000 bytes per second. setup_spiped_decryption_server /dev/null 0 1 1000 - cat ${scriptdir}/lorem-send.txt \ - | ${c_valgrind_cmd} \ + + # Send a file through the rate-limited echo server. + setup_check_variables "spipe send rate-limited" + ${c_valgrind_cmd} \ ${spipe_binary} -t ${mid_sock} -k /dev/null \ + < ${sendfile} \ > ${echo_limited_output} echo $? > ${c_exitfile} - setup_check_variables - cmp -s ${scriptdir}/lorem-send.txt ${echo_limited_output} + setup_check_variables "spipe send rate-limited output" + cmp -s ${sendfile} ${echo_limited_output} echo $? > ${c_exitfile} # Clean up diff -Nru spiped-1.6.1/tests/09-pushbits.sh spiped-1.6.2/tests/09-pushbits.sh --- spiped-1.6.1/tests/09-pushbits.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/09-pushbits.sh 2021-12-09 22:15:31.000000000 +0000 @@ -5,31 +5,37 @@ ### Constants c_valgrind_min=1 +sendfile=${scriptdir}/shared_test_functions.sh ### Actual command scenario_cmd() { # Copy a file - setup_check_variables + setup_check_variables "test_pushbits 1" ${c_valgrind_cmd} ${scriptdir}/pushbits/test_pushbits \ - -i ${scriptdir}/lorem-send.txt -o ${s_basename}-copy 1 + -i ${sendfile} -o ${s_basename}-copy 1 echo $? > ${c_exitfile} - setup_check_variables - cmp -s ${scriptdir}/lorem-send.txt ${s_basename}-copy + setup_check_variables "test_pushbits 1 output" + cmp -s ${sendfile} ${s_basename}-copy echo $? > ${c_exitfile} # Echo stdin to stdout - setup_check_variables + setup_check_variables "test_pushbits 2" ${c_valgrind_cmd} ${scriptdir}/pushbits/test_pushbits 2 echo $? > ${c_exitfile} # Copy a message through one pushbits() - setup_check_variables + setup_check_variables "test_pushbits 3" ${c_valgrind_cmd} ${scriptdir}/pushbits/test_pushbits 3 echo $? > ${c_exitfile} # Copy a message through two pushbits() - setup_check_variables + setup_check_variables "test_pushbits 4" ${c_valgrind_cmd} ${scriptdir}/pushbits/test_pushbits 4 echo $? > ${c_exitfile} + + # Echo stdin to stdout, but cancel it immediately after starting + setup_check_variables "test_pushbits 5" + ${c_valgrind_cmd} ${scriptdir}/pushbits/test_pushbits 5 + echo $? > ${c_exitfile} } diff -Nru spiped-1.6.1/tests/10-pthread-create-blocking-np.sh spiped-1.6.2/tests/10-pthread-create-blocking-np.sh --- spiped-1.6.1/tests/10-pthread-create-blocking-np.sh 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/10-pthread-create-blocking-np.sh 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,13 @@ +#!/bin/sh + +### Constants +c_valgrind_min=1 +cmd="${scriptdir}/pthread_create_blocking_np/test_pthread_create_blocking_np" + +### Actual command +scenario_cmd() { + # Copy a file + setup_check_variables "test_pthread_create_blocking_np" + ${c_valgrind_cmd} ${cmd} + echo $? > ${c_exitfile} +} diff -Nru spiped-1.6.1/tests/dnsthread-resolve/main.c spiped-1.6.2/tests/dnsthread-resolve/main.c --- spiped-1.6.1/tests/dnsthread-resolve/main.c 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/dnsthread-resolve/main.c 2021-07-04 18:08:39.000000000 +0000 @@ -17,7 +17,7 @@ char * addr; int i; - (void)cookie; /* UNUSED */ + (void)cookie; /* UNUSED */ /* Sanity check. */ if (sas == NULL) diff -Nru spiped-1.6.1/tests/dnsthread-resolve/Makefile spiped-1.6.2/tests/dnsthread-resolve/Makefile --- spiped-1.6.1/tests/dnsthread-resolve/Makefile 2020-04-05 18:24:21.000000000 +0000 +++ spiped-1.6.2/tests/dnsthread-resolve/Makefile 2021-12-24 19:31:54.000000000 +0000 @@ -1,11 +1,12 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=dnsthread-resolve -SRCS=main.c elasticarray.c ptrheap.c timerqueue.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c events.c network_connect.c network_read.c network_write.c asprintf.c monoclock.c noeintr.c sock.c sock_util.c warnp.c dnsthread.c -IDIRS=-I../../libcperciva/datastruct -I../../libcperciva/events -I../../libcperciva/network -I../../libcperciva/util -I../../lib/dnsthread +SRCS=main.c +IDIRS=-I../../libcperciva/events -I../../libcperciva/util -I../../lib/dnsthread LDADD_REQ=-lpthread SUBDIR_DEPTH=../.. RELATIVE_DIR=tests/dnsthread-resolve +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -19,44 +20,8 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ../../libcperciva/events/events.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_util.h ../../libcperciva/util/warnp.h ../../lib/dnsthread/dnsthread.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -elasticarray.o: ../../libcperciva/datastruct/elasticarray.c ../../libcperciva/datastruct/elasticarray.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/elasticarray.c -o elasticarray.o -ptrheap.o: ../../libcperciva/datastruct/ptrheap.c ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/datastruct/ptrheap.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/ptrheap.c -o ptrheap.o -timerqueue.o: ../../libcperciva/datastruct/timerqueue.c ../../libcperciva/datastruct/ptrheap.h ../../libcperciva/datastruct/timerqueue.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/timerqueue.c -o timerqueue.o -events_immediate.o: ../../libcperciva/events/events_immediate.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_immediate.c -o events_immediate.o -events_network.o: ../../libcperciva/events/events_network.c ../../libcperciva/util/ctassert.h ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/util/warnp.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network.c -o events_network.o -events_network_selectstats.o: ../../libcperciva/events/events_network_selectstats.c ../../libcperciva/util/monoclock.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o -events_timer.o: ../../libcperciva/events/events_timer.c ../../libcperciva/util/monoclock.h ../../libcperciva/datastruct/timerqueue.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_timer.c -o events_timer.o -events.o: ../../libcperciva/events/events.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events.c -o events.o -network_connect.o: ../../libcperciva/network/network_connect.c ../../libcperciva/events/events.h ../../libcperciva/util/sock.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_connect.c -o network_connect.o -network_read.o: ../../libcperciva/network/network_read.c ../../libcperciva/events/events.h ../../libcperciva/datastruct/mpool.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_read.c -o network_read.o -network_write.o: ../../libcperciva/network/network_write.c ../../libcperciva/events/events.h ../../libcperciva/datastruct/mpool.h ../../libcperciva/util/warnp.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_write.c -o network_write.o -asprintf.o: ../../libcperciva/util/asprintf.c ../../libcperciva/util/asprintf.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/asprintf.c -o asprintf.o -monoclock.o: ../../libcperciva/util/monoclock.c ../../libcperciva/util/warnp.h ../../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/monoclock.c -o monoclock.o -noeintr.o: ../../libcperciva/util/noeintr.c ../../libcperciva/util/noeintr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/noeintr.c -o noeintr.o -sock.o: ../../libcperciva/util/sock.c ../../libcperciva/util/imalloc.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock.c -o sock.o -sock_util.o: ../../libcperciva/util/sock_util.c ../../libcperciva/util/asprintf.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h ../../libcperciva/util/sock_util.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock_util.c -o sock_util.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o -dnsthread.o: ../../lib/dnsthread/dnsthread.c ../../libcperciva/events/events.h ../../libcperciva/util/noeintr.h ../../libcperciva/util/sock.h ../../libcperciva/util/warnp.h ../../lib/dnsthread/dnsthread.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../lib/dnsthread/dnsthread.c -o dnsthread.o diff -Nru spiped-1.6.1/tests/lorem-send.txt spiped-1.6.2/tests/lorem-send.txt --- spiped-1.6.1/tests/lorem-send.txt 2016-06-29 20:57:55.000000000 +0000 +++ spiped-1.6.2/tests/lorem-send.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor -incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis -nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore -eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt -in culpa qui officia deserunt mollit anim id est laborum. diff -Nru spiped-1.6.1/tests/nc-client/Makefile spiped-1.6.2/tests/nc-client/Makefile --- spiped-1.6.1/tests/nc-client/Makefile 2020-04-05 18:24:21.000000000 +0000 +++ spiped-1.6.2/tests/nc-client/Makefile 2021-12-24 19:31:54.000000000 +0000 @@ -1,10 +1,11 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=nc-client -SRCS=main.c elasticarray.c ptrheap.c timerqueue.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c events.c network_connect.c network_read.c network_write.c monoclock.c sock.c warnp.c -IDIRS=-I../../libcperciva/datastruct -I../../libcperciva/events -I../../libcperciva/network -I../../libcperciva/util +SRCS=main.c +IDIRS=-I../../libcperciva/events -I../../libcperciva/network -I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=tests/nc-client +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -18,36 +19,8 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ../../libcperciva/events/events.h ../../libcperciva/network/network.h ../../libcperciva/util/sock.h ../../libcperciva/util/warnp.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -elasticarray.o: ../../libcperciva/datastruct/elasticarray.c ../../libcperciva/datastruct/elasticarray.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/elasticarray.c -o elasticarray.o -ptrheap.o: ../../libcperciva/datastruct/ptrheap.c ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/datastruct/ptrheap.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/ptrheap.c -o ptrheap.o -timerqueue.o: ../../libcperciva/datastruct/timerqueue.c ../../libcperciva/datastruct/ptrheap.h ../../libcperciva/datastruct/timerqueue.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/timerqueue.c -o timerqueue.o -events_immediate.o: ../../libcperciva/events/events_immediate.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_immediate.c -o events_immediate.o -events_network.o: ../../libcperciva/events/events_network.c ../../libcperciva/util/ctassert.h ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/util/warnp.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network.c -o events_network.o -events_network_selectstats.o: ../../libcperciva/events/events_network_selectstats.c ../../libcperciva/util/monoclock.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o -events_timer.o: ../../libcperciva/events/events_timer.c ../../libcperciva/util/monoclock.h ../../libcperciva/datastruct/timerqueue.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_timer.c -o events_timer.o -events.o: ../../libcperciva/events/events.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events.c -o events.o -network_connect.o: ../../libcperciva/network/network_connect.c ../../libcperciva/events/events.h ../../libcperciva/util/sock.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_connect.c -o network_connect.o -network_read.o: ../../libcperciva/network/network_read.c ../../libcperciva/events/events.h ../../libcperciva/datastruct/mpool.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_read.c -o network_read.o -network_write.o: ../../libcperciva/network/network_write.c ../../libcperciva/events/events.h ../../libcperciva/datastruct/mpool.h ../../libcperciva/util/warnp.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_write.c -o network_write.o -monoclock.o: ../../libcperciva/util/monoclock.c ../../libcperciva/util/warnp.h ../../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/monoclock.c -o monoclock.o -sock.o: ../../libcperciva/util/sock.c ../../libcperciva/util/imalloc.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock.c -o sock.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o diff -Nru spiped-1.6.1/tests/nc-server/main.c spiped-1.6.2/tests/nc-server/main.c --- spiped-1.6.1/tests/nc-server/main.c 2019-11-09 08:19:05.000000000 +0000 +++ spiped-1.6.2/tests/nc-server/main.c 2021-12-09 22:15:31.000000000 +0000 @@ -4,6 +4,7 @@ #include #include +#include "monoclock.h" #include "parsenum.h" #include "warnp.h" @@ -14,7 +15,7 @@ struct nc_cookie { FILE * out; - size_t bps; + size_t bps; /* Average bytes per second to send. */ }; /* Wait duration can be interrupted by signals. */ @@ -35,14 +36,35 @@ write_bps(int sock, uint8_t * buf, size_t buflen, size_t bps) { size_t remaining = buflen; - size_t bp_cs = bps / 100; /* bytes per centi-second. */ + size_t goal_send; + size_t actual_sent = 0; size_t to_send; + struct timeval orig, now; + + /* Get initial time. */ + if (monoclock_get(&orig)) { + warn0("monoclock_get"); + goto err0; + } do { - /* How much data should we send? */ - if (remaining >= bp_cs) - to_send = bp_cs; - else + /* Wait 10ms. */ + wait_ms(10); + + /* How much data should we have sent by now? */ + if (monoclock_get(&now)) { + warn0("monoclock_get"); + goto err0; + } + goal_send = (size_t)((double)bps * timeval_diff(orig, now)); + + /* If clocks did something really weird, loop again. */ + if (goal_send <= actual_sent) + continue; + + /* How data should we send to reach the time-based goal? */ + to_send = goal_send - actual_sent; + if (to_send > remaining) to_send = remaining; /* Send a burst. */ @@ -54,9 +76,7 @@ /* Record effect of sending. */ remaining -= to_send; buf += to_send; - - /* Wait 10ms. */ - wait_ms(10); + actual_sent += to_send; } while (remaining > 0); err0: diff -Nru spiped-1.6.1/tests/nc-server/Makefile spiped-1.6.2/tests/nc-server/Makefile --- spiped-1.6.1/tests/nc-server/Makefile 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/tests/nc-server/Makefile 2021-12-24 19:31:54.000000000 +0000 @@ -1,10 +1,11 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=nc-server -SRCS=main.c simple_server.c elasticarray.c ptrheap.c timerqueue.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c events.c network_accept.c network_read.c monoclock.c sock.c warnp.c -IDIRS=-I../../libcperciva/datastruct -I../../libcperciva/events -I../../libcperciva/network -I../../libcperciva/util +SRCS=main.c simple_server.c +IDIRS=-I../../libcperciva/events -I../../libcperciva/network -I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=tests/nc-server +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -18,36 +19,10 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} -main.o: main.c ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h simple_server.h +main.o: main.c ../../libcperciva/util/monoclock.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h simple_server.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o simple_server.o: simple_server.c ../../libcperciva/events/events.h ../../libcperciva/network/network.h ../../libcperciva/util/sock.h ../../libcperciva/util/warnp.h simple_server.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c simple_server.c -o simple_server.o -elasticarray.o: ../../libcperciva/datastruct/elasticarray.c ../../libcperciva/datastruct/elasticarray.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/elasticarray.c -o elasticarray.o -ptrheap.o: ../../libcperciva/datastruct/ptrheap.c ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/datastruct/ptrheap.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/ptrheap.c -o ptrheap.o -timerqueue.o: ../../libcperciva/datastruct/timerqueue.c ../../libcperciva/datastruct/ptrheap.h ../../libcperciva/datastruct/timerqueue.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/datastruct/timerqueue.c -o timerqueue.o -events_immediate.o: ../../libcperciva/events/events_immediate.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_immediate.c -o events_immediate.o -events_network.o: ../../libcperciva/events/events_network.c ../../libcperciva/util/ctassert.h ../../libcperciva/datastruct/elasticarray.h ../../libcperciva/util/warnp.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network.c -o events_network.o -events_network_selectstats.o: ../../libcperciva/events/events_network_selectstats.c ../../libcperciva/util/monoclock.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o -events_timer.o: ../../libcperciva/events/events_timer.c ../../libcperciva/util/monoclock.h ../../libcperciva/datastruct/timerqueue.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events_timer.c -o events_timer.o -events.o: ../../libcperciva/events/events.c ../../libcperciva/datastruct/mpool.h ../../libcperciva/events/events.h ../../libcperciva/events/events_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/events/events.c -o events.o -network_accept.o: ../../libcperciva/network/network_accept.c ../../libcperciva/events/events.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_accept.c -o network_accept.o -network_read.o: ../../libcperciva/network/network_read.c ../../libcperciva/events/events.h ../../libcperciva/datastruct/mpool.h ../../libcperciva/network/network.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/network/network_read.c -o network_read.o -monoclock.o: ../../libcperciva/util/monoclock.c ../../libcperciva/util/warnp.h ../../libcperciva/util/monoclock.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/monoclock.c -o monoclock.o -sock.o: ../../libcperciva/util/sock.c ../../libcperciva/util/imalloc.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../libcperciva/util/sock.h ../../libcperciva/util/sock_internal.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/sock.c -o sock.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o diff -Nru spiped-1.6.1/tests/pthread_create_blocking_np/main.c spiped-1.6.2/tests/pthread_create_blocking_np/main.c --- spiped-1.6.1/tests/pthread_create_blocking_np/main.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/pthread_create_blocking_np/main.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,79 @@ +#include +#include + +#include "pthread_create_blocking_np.h" +#include "timing.h" +#include "warnp.h" + +/* This is an arbitrary pointer to return via pthread_join(). */ +static int arbitrary_value; +static void * MY_RUN_RETURN = &arbitrary_value; + +static void * +workfunc(void * cookie) +{ + + (void)cookie; /* UNUSED */ + + /* Special value for testing; normally this would be NULL. */ + return (MY_RUN_RETURN); +} + +static int +check_basic(void) +{ + pthread_t thr; + void * rc_join = NULL; + void * rc_join_expected; + int rc; + + /* Try to make a thread. */ + if ((rc = pthread_create_blocking_np(&thr, NULL, workfunc, NULL))) { + warnp("pthread_create_blocking_np: %s", strerror(rc)); + goto err0; + } + + /* If we succeeded in making a thread, wait for it to finish. */ + if ((rc = pthread_join(thr, &rc_join))) { + warn0("pthread_join: %s", strerror(rc)); + goto err0; + } + + /* Check the value returned from the workfunc. */ + rc_join_expected = MY_RUN_RETURN; + if (rc_join != rc_join_expected) { + warn0("pthread_join expected to get %p; instead, got %p", + rc_join, rc_join_expected); + goto err0; + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +int +main(int argc, char ** argv) +{ + + WARNP_INIT; + (void)argc; /* UNUSED */ + + /* Check basic stuff. */ + if (check_basic()) + goto err0; + + /* Check the relative timing of points in the code. */ + if (check_timing()) + goto err0; + + /* Success! */ + exit(0); + +err0: + /* Failure! */ + exit(1); +} diff -Nru spiped-1.6.1/tests/pthread_create_blocking_np/Makefile spiped-1.6.2/tests/pthread_create_blocking_np/Makefile --- spiped-1.6.1/tests/pthread_create_blocking_np/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/pthread_create_blocking_np/Makefile 2021-12-24 19:31:54.000000000 +0000 @@ -0,0 +1,29 @@ +.POSIX: +# AUTOGENERATED FILE, DO NOT EDIT +PROG=test_pthread_create_blocking_np +SRCS=main.c timing.c +IDIRS=-I../../libcperciva/util -I../../lib/util +LDADD_REQ=-lpthread +SUBDIR_DEPTH=../.. +RELATIVE_DIR=tests/pthread_create_blocking_np +LIBALL=../../liball/liball.a + +all: + if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ + cd ${SUBDIR_DEPTH}; \ + ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ + BUILD_TARGET=${PROG} buildsubdir; \ + else \ + ${MAKE} ${PROG}; \ + fi + +clean: + rm -f ${PROG} ${SRCS:.c=.o} + +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} + +main.o: main.c ../../lib/util/pthread_create_blocking_np.h timing.h ../../libcperciva/util/warnp.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o +timing.o: timing.c ../../libcperciva/util/monoclock.h ../../lib/util/pthread_create_blocking_np.h ../../libcperciva/util/warnp.h timing.h + ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c timing.c -o timing.o diff -Nru spiped-1.6.1/tests/pthread_create_blocking_np/timing.c spiped-1.6.2/tests/pthread_create_blocking_np/timing.c --- spiped-1.6.1/tests/pthread_create_blocking_np/timing.c 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/pthread_create_blocking_np/timing.c 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,201 @@ +#include + +#include +#include +#include + +#include "monoclock.h" +#include "pthread_create_blocking_np.h" +#include "warnp.h" + +#include "timing.h" + +#define WAIT_MS 10 + +#define WAIT_THREAD_AFTER_START 0x01 +#define WAIT_PARENT_AFTER_BLOCK 0x02 + +static struct testcase { + int options; +} tests[] = { + {WAIT_THREAD_AFTER_START}, + {WAIT_PARENT_AFTER_BLOCK}, + {WAIT_THREAD_AFTER_START | WAIT_PARENT_AFTER_BLOCK}, + {0} +}; + +/* It's ok if "prev" and "next" are the same time. */ +#define CHECK_TIME(prev, next) do { \ + if (timeval_diff(prev, next) < 0) { \ + warn0(#prev " is after " #next); \ + goto err0; \ + } \ + } while(0) + +/* Each test. */ +struct info { + int options; + struct timeval parent_start; + struct timeval parent_after_block; + struct timeval parent_after_join; + struct timeval thr_start; + struct timeval thr_stop; +}; + +/* Wait duration can be interrupted by signals. */ +static int +wait_ms(size_t msec) +{ + struct timespec ts; + + /* Try to wait for the desired duration. */ + ts.tv_sec = msec / 1000; + ts.tv_nsec = (msec % 1000) * 1000000; + nanosleep(&ts, NULL); + + /* Success! */ + return (0); +} + +static void * +workfunc(void * cookie) +{ + struct info * info = cookie; + + /* For checking the order. */ + if (monoclock_get(&info->thr_start)) + warnp("monoclock_get"); + + /* Wait if the test calls for it. */ + if (info->options & WAIT_THREAD_AFTER_START) + wait_ms(WAIT_MS); + + /* For checking the order. */ + if (monoclock_get(&info->thr_stop)) + warnp("monoclock_get"); + + return (NULL); +} + +static int +runner(int options1, int options2) +{ + struct info info1, info2; + pthread_t thr1, thr2; + int rc; + + info1.options = options1; + info2.options = options2; + + /* + * Get starting time for each struct info. Do this with two separate + * monoclock_get() calls, to check that monoclock increases. + */ + if (monoclock_get(&info1.parent_start)) { + warnp("monoclock_get"); + goto err0; + } + if (monoclock_get(&info2.parent_start)) { + warnp("monoclock_get"); + goto err0; + } + + /* Launch thr1 and record time. */ + if ((rc = pthread_create_blocking_np(&thr1, NULL, workfunc, &info1))) { + warn0("pthread_create_blocking_np: %s", strerror(rc)); + goto err0; + } + if (monoclock_get(&info1.parent_after_block)) { + warnp("monoclock_get"); + goto err0; + } + + /* Launch thr2 and record time. */ + if ((rc = pthread_create_blocking_np(&thr2, NULL, workfunc, &info2))) { + warn0("pthread_create_blocking_np: %s", strerror(rc)); + goto err0; + } + if (monoclock_get(&info2.parent_after_block)) { + warnp("monoclock_get"); + goto err0; + } + + /* Wait if the test calls for it. */ + if (info1.options & WAIT_PARENT_AFTER_BLOCK) + wait_ms(WAIT_MS); + if (info2.options & WAIT_PARENT_AFTER_BLOCK) + wait_ms(WAIT_MS); + + /* Join thr1 and record time. */ + if ((rc = pthread_join(thr1, NULL))) { + warn0("pthread_join: %s", strerror(rc)); + goto err0; + } + if (monoclock_get(&info1.parent_after_join)) { + warnp("monoclock_get"); + goto err0; + } + + /* Join thr2 and record time. */ + if ((rc = pthread_join(thr2, NULL))) { + warn0("pthread_join: %s", strerror(rc)); + goto err0; + } + if (monoclock_get(&info2.parent_after_join)) { + warnp("monoclock_get"); + goto err0; + } + + /* Check each thread independently. */ + CHECK_TIME(info1.parent_start, info1.parent_after_block); + CHECK_TIME(info1.parent_after_block, info1.parent_after_join); + CHECK_TIME(info1.thr_start, info1.thr_stop); + CHECK_TIME(info2.parent_start, info2.parent_after_block); + CHECK_TIME(info2.parent_after_block, info2.parent_after_join); + CHECK_TIME(info2.thr_start, info2.thr_stop); + + /* Check inter-connectedness. */ + CHECK_TIME(info1.parent_start, info1.thr_start); + CHECK_TIME(info1.thr_stop, info1.parent_after_join); + CHECK_TIME(info2.parent_start, info2.thr_start); + CHECK_TIME(info2.thr_stop, info2.parent_after_join); + + /* Check inter-connectedness between 1 and 2. */ + CHECK_TIME(info1.parent_start, info2.parent_start); + CHECK_TIME(info1.parent_after_block, info2.parent_after_block); + CHECK_TIME(info1.parent_after_join, info2.parent_after_join); + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} + +/** + * check_timing(void): + * Check that pthread_create_blocking_np() results in the expected relative + * timing. + */ +int +check_timing(void) +{ + size_t i, j; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + for (j = 0; j < sizeof(tests) / sizeof(tests[0]); j++) { + if (runner(tests[i].options, tests[j].options)) { + warn0("failed test %zu", i); + goto err0; + } + } + } + + /* Success! */ + return (0); + +err0: + /* Failure! */ + return (-1); +} diff -Nru spiped-1.6.1/tests/pthread_create_blocking_np/timing.h spiped-1.6.2/tests/pthread_create_blocking_np/timing.h --- spiped-1.6.1/tests/pthread_create_blocking_np/timing.h 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/pthread_create_blocking_np/timing.h 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef _TIMING_H_ +#define _TIMING_H_ + +/** + * check_timing(void): + * Check that pthread_create_blocking_np() results in the expected relative + * timing. + */ +int check_timing(void); + +#endif /* !_TIMING_H_ */ diff -Nru spiped-1.6.1/tests/pushbits/main.c spiped-1.6.2/tests/pushbits/main.c --- spiped-1.6.1/tests/pushbits/main.c 2020-03-28 02:21:15.000000000 +0000 +++ spiped-1.6.2/tests/pushbits/main.c 2021-12-09 22:15:31.000000000 +0000 @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,13 @@ goto err0; } - /* Wait a short while, then cancel the thread. */ + /* + * Wait a short while, then cancel the thread. Note that if stdin + * returned an EOF, the thread might have already stopped, and + * certainly will not be running after a second. This is particularly + * relevant if running the tests inside a virtualization or container + * framework. + */ sleep(1); if ((rc = pthread_cancel(thread)) != 0) { /* @@ -177,6 +184,10 @@ warnp("read"); goto err2; } + if ((size_t)r != msglen) { + warn0("Message is not the expected length"); + goto err2; + } if (strncmp(buf, msg, msglen) != 0) { warn0("failed to get the (full?) message"); goto err2; @@ -189,13 +200,29 @@ } free(buf); + /* Clean up. */ + if (close(in[1])) { + warnp("close"); + goto err0; + } + if (close(out[0])) { + warnp("close"); + goto err0; + } + if (close(out[1])) { + warnp("close"); + goto err0; + } + /* Success! */ return (0); err3: - pthread_cancel(thread); + if ((rc = pthread_cancel(thread)) != 0) + warn0("pthread_cancel: %s", strerror(rc)); err2: - pthread_join(thread, NULL); + if ((rc = pthread_join(thread, NULL)) != 0) + warn0("pthread_join: %s", strerror(rc)); err1: free(buf); err0: @@ -275,6 +302,10 @@ warnp("read"); goto err2; } + if ((size_t)r != msglen) { + warn0("Message is not the expected length"); + goto err2; + } if (strncmp(buf, msg, msglen) != 0) { warn0("failed to get the (full?) message"); goto err2; @@ -287,15 +318,42 @@ } free(buf); + /* Clean up. */ + if (close(in[1])) { + warnp("close"); + goto err0; + } + if (close(middle[0])) { + warnp("close"); + goto err0; + } + if (close(middle[1])) { + warnp("close"); + goto err0; + } + if (close(out[0])) { + warnp("close"); + goto err0; + } + if (close(out[1])) { + warnp("close"); + goto err0; + } + + /* Success! */ return (0); err3: - pthread_cancel(thread[0]); - pthread_join(thread[0], NULL); + if ((rc = pthread_cancel(thread[0])) != 0) + warn0("pthread_cancel: %s", strerror(rc)); + if ((rc = pthread_join(thread[0], NULL)) != 0) + warn0("pthread_join: %s", strerror(rc)); err2: - pthread_cancel(thread[1]); - pthread_join(thread[1], NULL); + if ((rc = pthread_cancel(thread[1])) != 0) + warn0("pthread_cancel: %s", strerror(rc)); + if ((rc = pthread_join(thread[1], NULL)) != 0) + warn0("pthread_join: %s", strerror(rc)); err1: free(buf); err0: @@ -303,6 +361,60 @@ return (-1); } +static int +start_stop(void) +{ + pthread_t thread; + int in[2]; + int rc; + + /* Create socket pair for the input. */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, in)) { + warnp("socketpair"); + goto err0; + } + + /* Start echoing. */ + if (pushbits(in[1], STDOUT_FILENO, &thread)) { + warnp("pushbits"); + goto err1; + } + + /* Cancel the thread immediately. */ + if ((rc = pthread_cancel(thread)) != 0) { + warn0("pthread_cancel: %s", strerror(rc)); + goto err1; + } + + /* Wait for thread to finish. */ + if ((rc = pthread_join(thread, NULL)) != 0) { + warn0("pthread_join: %s", strerror(rc)); + goto err1; + } + + /* Clean up. */ + if (close(in[0])) { + warnp("close"); + goto err0; + } + if (close(in[1])) { + warnp("close"); + goto err0; + } + + /* Success! */ + return (0); + +err1: + if (close(in[0])) + warnp("close"); + if (close(in[1])) + warnp("close"); +err0: + /* Failure! */ + return (-1); +} + static void usage(void) { @@ -344,7 +456,7 @@ /* We should have processed all the arguments except for one. */ if (argc != 1) usage(); - if (PARSENUM(&desired_test, argv[0], 1, 4)) { + if (PARSENUM(&desired_test, argv[0], 1, 5)) { warnp("parsenum"); goto err0; } @@ -369,6 +481,10 @@ if (chain_two()) goto err0; break; + case 5: + if (start_stop()) + goto err0; + break; default: warn0("invalid test number"); goto err0; diff -Nru spiped-1.6.1/tests/pushbits/Makefile spiped-1.6.2/tests/pushbits/Makefile --- spiped-1.6.1/tests/pushbits/Makefile 2020-04-05 18:24:22.000000000 +0000 +++ spiped-1.6.2/tests/pushbits/Makefile 2021-12-24 19:31:54.000000000 +0000 @@ -1,11 +1,12 @@ .POSIX: # AUTOGENERATED FILE, DO NOT EDIT PROG=test_pushbits -SRCS=main.c getopt.c noeintr.c warnp.c pushbits.c -IDIRS=-I../../libcperciva/util -I../../spipe +SRCS=main.c pushbits.c +IDIRS=-I../../spipe -I../../libcperciva/util -I../../lib/util LDADD_REQ=-lpthread SUBDIR_DEPTH=../.. RELATIVE_DIR=tests/pushbits +LIBALL=../../liball/liball.a all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ @@ -19,16 +20,10 @@ clean: rm -f ${PROG} ${SRCS:.c=.o} -${PROG}:${SRCS:.c=.o} - ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} +${PROG}:${SRCS:.c=.o} ${LIBALL} + ${CC} -o ${PROG} ${SRCS:.c=.o} ${LIBALL} ${LDFLAGS} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ../../libcperciva/util/getopt.h ../../libcperciva/util/noeintr.h ../../libcperciva/util/parsenum.h ../../libcperciva/util/warnp.h ../../spipe/pushbits.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c main.c -o main.o -getopt.o: ../../libcperciva/util/getopt.c ../../libcperciva/util/getopt.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/getopt.c -o getopt.o -noeintr.o: ../../libcperciva/util/noeintr.c ../../libcperciva/util/noeintr.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/noeintr.c -o noeintr.o -warnp.o: ../../libcperciva/util/warnp.c ../../libcperciva/util/warnp.h - ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../libcperciva/util/warnp.c -o warnp.o -pushbits.o: ../../spipe/pushbits.c ../../libcperciva/util/noeintr.h ../../libcperciva/util/warnp.h ../../spipe/pushbits.h +pushbits.o: ../../spipe/pushbits.c ../../libcperciva/util/noeintr.h ../../lib/util/pthread_create_blocking_np.h ../../libcperciva/util/warnp.h ../../spipe/pushbits.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../../spipe/pushbits.c -o pushbits.o diff -Nru spiped-1.6.1/tests/shared_test_functions.sh spiped-1.6.2/tests/shared_test_functions.sh --- spiped-1.6.1/tests/shared_test_functions.sh 2019-11-09 08:19:05.000000000 +0000 +++ spiped-1.6.2/tests/shared_test_functions.sh 2021-12-09 22:15:31.000000000 +0000 @@ -41,43 +41,46 @@ VERBOSE=${VERBOSE:-0} # Keep the user-specified ${USE_VALGRIND}, or initialize to 0 (don't do memory -# tests). +# tests). If ${USE_VALGRIND_NO_REGEN} is non-zero, re-use the previous +# suppressions files instead of generating new ones. USE_VALGRIND=${USE_VALGRIND:-0} +USE_VALGRIND_NO_REGEN=${USE_VALGRIND_NO_REGEN:-0} -# A non-zero value unlikely to be used as an exit code by the programs being -# tested. -valgrind_exit_code=108 +# Load valgrind-related functions. These functions will bail on a per-check +# basis if the ${USE_VALGRIND} value does not indicate that we should run a +# valgrind for that check. +. ${scriptdir}/shared_valgrind_functions.sh # Set ${bindir} to $1 if given, else use "." for in-tree builds. bindir=$(CDPATH='' cd -- "$(dirname -- "${1-.}")" && pwd -P) +# Default value (should be set by tests). +NO_EXITFILE=/dev/null -## prepare_directories(): -# Delete any old directories, and create new ones as necessary. Must be run -# after check_optional_valgrind(). -prepare_directories() { - # Clean up previous directories. + +## prepare_directory(): +# Delete the previous test output directory, and create a new one. +prepare_directory() { if [ -d "${out}" ]; then rm -rf ${out} fi - if [ -d "${out_valgrind}" ]; then - rm -rf ${out_valgrind} - fi - - # Make new directories. mkdir ${out} - if [ "$USE_VALGRIND" -gt 0 ]; then - mkdir ${out_valgrind} - fi } -## find_system (cmd, args...): +## find_system (cmd, args): # Look for ${cmd} in the $PATH, and ensure that it supports ${args}. find_system() { cmd=$1 - cmd_with_args=$@ + cmd_with_args="$1 ${2:-}" + + # Sanity check. + if [ "$#" -gt "2" ]; then + printf "Programmer error: find_system: too many args\n" 1>&2 + exit 1 + fi + # Look for ${cmd}; the "|| true" and -} make this work with set -e. - system_binary=`command -v ${cmd}` || true + system_binary=$(command -v ${cmd}) || true if [ -z "${system_binary-}" ]; then system_binary="" printf "System ${cmd} not found.\n" 1>&2 @@ -95,7 +98,7 @@ # Look for ${cmd} in ps; return 0 if ${cmd} exists. has_pid() { cmd=$1 - pid=`ps -Aopid,args | grep -F "${cmd}" | grep -v "grep"` || true + pid=$(ps -Aopid,args | grep -F "${cmd}" | grep -v "grep") || true if [ -n "${pid}" ]; then return 0 fi @@ -114,117 +117,45 @@ done } -## check_optional_valgrind (): -# Return a $USE_VALGRIND variable defined; if it was previously defined and -# was greater than 0, then check that valgrind is available in the $PATH. -check_optional_valgrind() { - if [ "$USE_VALGRIND" -gt 0 ]; then - # Look for valgrind in $PATH. - if ! command -v valgrind >/dev/null 2>&1; then - printf "valgrind not found\n" 1>&2 - exit 1 - fi - fi -} - -## ensure_valgrind_suppresssion (potential_memleaks_binary): -# Run the ${potential_memleaks_binary} through valgrind, keeping -# track of any apparent memory leak in order to suppress reporting -# those leaks when testing other binaries. -ensure_valgrind_suppression() { - potential_memleaks_binary=$1 - - # Quit if we're not using valgrind. - if [ ! "$USE_VALGRIND" -gt 0 ]; then - return - fi; - - printf "Generating valgrind suppressions... " - valgrind_suppressions="${out_valgrind}/suppressions" - valgrind_suppressions_log="${out_valgrind}/suppressions.pre" - - # Start off with an empty suppression file - touch ${valgrind_suppressions} - - # Get list of tests - ${potential_memleaks_binary} | while read testname; do - this_valgrind_supp="${valgrind_suppressions_log}-${testname}" - - # Run valgrind on the binary, sending it a "\n" so that - # a test which uses STDIN will not wait for user input. - printf "\n" | (valgrind \ - --leak-check=full --show-leak-kinds=all \ - --gen-suppressions=all \ - --suppressions=${valgrind_suppressions} \ - --log-file=${this_valgrind_supp} \ - ${potential_memleaks_binary} \ - ${testname}) - - # Append name to suppressions file - printf "# ${testname}\n" >> ${valgrind_suppressions} - - # Strip out useless parts from the log file, and allow the - # suppressions to apply to other binaries by removing: - # - references to the main() function, - # - "pl_*" ("potential loss") functions, - # - references to the binary itself. - # Append to suppressions file. - (grep -v "^==" ${this_valgrind_supp} \ - | grep -v " fun:pl_" - \ - | grep -v " fun:main" - \ - | grep -v -E " obj:.*/potential-memleaks" - \ - >> ${valgrind_suppressions} ) || true - done - - # Clean up - rm -f ${valgrind_suppressions_log} - printf "done.\n" -} - -## setup_check_variables (): +## setup_check_variables (description, check_prev=1): # Set up the "check" variables ${c_exitfile} and ${c_valgrind_cmd}, the # latter depending on the previously-defined ${c_valgrind_min}. # Advances the number of checks ${s_count} so that the next call to this -# function will set up new filenames. +# function will set up new filenames. Write ${description} into a +# file. If ${check_prev} is non-zero, check that the previous +# ${c_exitfile} exists. setup_check_variables() { - # Set up the "exit" file. - c_exitfile="${s_basename}-`printf %02d ${s_count}`.exit" + description=$1 + check_prev=${2:-1} - # Set up the valgrind command if $USE_VALGRIND is greater - # than or equal to ${valgrind_min}; otherwise, produce an - # empty string. Using --error-exitcode means that if - # there is a serious problem (such that scrypt calls - # exit(1)) *and* a memory leak, the test suite reports an - # exit value of ${valgrind_exit_code}. However, if there - # is a serious problem but no memory leak, we still - # receive a non-zero exit code. The most important thing - # is that we only receive an exit code of 0 if both the - # program and valgrind are happy. - if [ "$USE_VALGRIND" -ge "${c_valgrind_min}" ]; then - val_logfilename=${s_val_basename}-`printf %02d ${s_count}`.log - c_valgrind_cmd="valgrind \ - --log-file=${val_logfilename} \ - --leak-check=full --show-leak-kinds=all \ - --errors-for-leak-kinds=all \ - --suppressions=${valgrind_suppressions} \ - --error-exitcode=${valgrind_exit_code} " - else - c_valgrind_cmd="" + # Should we check for the previous exitfile? + if [ "${c_exitfile}" != "${NO_EXITFILE}" ] && \ + [ "${check_prev}" -gt 0 ] ; then + # Check for the file. + if [ ! -f "${c_exitfile}" ] ; then + # We should have written the result of the + # previous test to this file. + echo "PROGRAMMING FAILURE" 1>&2 + echo "We should already have ${c_exitfile}" 1>&2 + exit 1 + fi fi + # Set up the "exit" file. + count_str=$(printf "%02d" "${s_count}") + c_exitfile="${s_basename}-${count_str}.exit" + + # Write the "description" file. + printf "${description}\n" > \ + "${s_basename}-${count_str}.desc" + + # Set up the valgrind command (or an empty string). + c_valgrind_cmd="$(valgrind_setup_cmd)" + # Advances the number of checks. s_count=$((s_count + 1)) } -## get_val_logfile (val_basename, exitfile): -# Return the valgrind logfile corresponding to ${exitfile}. -get_val_logfile() { - val_basename=$1 - exitfile=$2 - num=`echo "${exitfile}" | rev | cut -c 1-7 | rev | cut -c 1-2 ` - echo "${val_basename}-${num}.log" -} - ## expected_exitcode (expected, exitcode): # If ${exitcode} matches the ${expected} value, return 0. If the exitcode is # ${valgrind_exit_code}, return that. Otherwise, return 1 to indicate @@ -244,17 +175,19 @@ ## notify_success_or_fail (log_basename, val_log_basename): # Examine all "exit code" files beginning with ${log_basename} and -# print "SUCCESS!" or "FAILED!" as appropriate. If the test failed -# with the code ${valgrind_exit_code}, output the appropriate -# valgrind logfile to stdout. +# print "SUCCESS!", "FAILED!", "SKIP!", or "PARTIAL SUCCESS / SKIP!" +# as appropriate. Check any valgrind log files associated with the +# test and print "FAILED!" if appropriate, along with the valgrind +# logfile. If the test failed and ${VERBOSE} is non-zero, print +# the description to stderr. notify_success_or_fail() { log_basename=$1 val_log_basename=$2 # Bail if there's no exitfiles. - exitfiles=`ls ${log_basename}-*.exit` || true + exitfiles=$(ls ${log_basename}-*.exit) || true if [ -z "$exitfiles" ]; then - echo "FAILED" + echo "FAILED" 1>&2 s_retval=1 return fi @@ -264,37 +197,46 @@ skip_exitfiles=0 # Check each exitfile. - for exitfile in `echo $exitfiles | sort`; do - ret=`cat ${exitfile}` + for exitfile in $(echo $exitfiles | sort); do + ret=$(cat ${exitfile}) total_exitfiles=$(( total_exitfiles + 1 )) if [ "${ret}" -lt 0 ]; then skip_exitfiles=$(( skip_exitfiles + 1 )) fi + # Check for test failure. if [ "${ret}" -gt 0 ]; then - echo "FAILED!" - retval=${ret} + echo "FAILED!" 1>&2 if [ ${VERBOSE} -ne 0 ]; then printf "File ${exitfile} contains exit" 1>&2 printf " code ${ret}.\n" 1>&2 - fi - if [ "${ret}" -eq "${valgrind_exit_code}" ]; then - val_logfilename=$( get_val_logfile \ - ${val_log_basename} ${exitfile} ) - cat ${val_logfilename} + descfile=$(echo ${exitfile} | \ + sed 's/\.exit/\.desc/g') + printf "Test description: " 1>&2 + cat ${descfile} 1>&2 fi s_retval=${ret} return fi + + # Check valgrind logfile(s). + val_failed="$(valgrind_check_basenames "${exitfile}")" + if [ -n "${val_failed}" ]; then + echo "FAILED!" 1>&2 + s_retval="${valgrind_exit_code}" + cat "${val_failed}" 1>&2 + return + fi done + # Notify about skip or success. if [ ${skip_exitfiles} -gt 0 ]; then if [ ${skip_exitfiles} -eq ${total_exitfiles} ]; then - echo "SKIP!" + echo "SKIP!" 1>&2 else - echo "PARTIAL SUCCESS / SKIP!" + echo "PARTIAL SUCCESS / SKIP!" 1>&2 fi else - echo "SUCCESS!" + echo "SUCCESS!" 1>&2 fi } @@ -302,14 +244,14 @@ # Run a test scenario from ${scenario_filename}. scenario_runner() { scenario_filename=$1 - basename=`basename ${scenario_filename} .sh` + basename=$(basename ${scenario_filename} .sh) printf " ${basename}... " 1>&2 # Initialize "scenario" and "check" variables. s_basename=${out}/${basename} s_val_basename=${out_valgrind}/${basename} s_count=0 - c_exitfile=/dev/null + c_exitfile="${NO_EXITFILE}" c_valgrind_min=9 c_valgrind_cmd="" @@ -317,8 +259,8 @@ unset scenario_cmd . ${scenario_filename} if ! command -v scenario_cmd 1>/dev/null ; then - printf "ERROR: scenario_cmd() is not defined in\n" - printf " ${scenario_filename}\n" + printf "ERROR: scenario_cmd() is not defined in\n" 1>&2 + printf " ${scenario_filename}\n" 1>&2 exit 1 fi @@ -335,20 +277,23 @@ ## run_scenarios (scenario_filenames): # Run all scenarios matching ${scenario_filenames}. run_scenarios() { - # Check for optional valgrind. - check_optional_valgrind + # Get the test number(s) to run. + if [ "${N:-0}" -gt "0" ]; then + test_scenarios="$(printf "${scriptdir}/%02d-*.sh" "${N}")" + else + test_scenarios="${scriptdir}/??-*.sh" + fi + + # Clean up any previous directory, and create a new one. + prepare_directory - # Clean up previous directories, and create new ones. - prepare_directories + # Clean up any previous valgrind directory, and prepare for new + # valgrind tests (if applicable). + valgrind_init - # Generate valgrind suppression file if it is required. Must be - # done after preparing directories. - ensure_valgrind_suppression ${bindir}/tests/valgrind/potential-memleaks - - printf -- "Running tests\n" - printf -- "-------------\n" - scenario_filenames=$@ - for scenario in ${scenario_filenames}; do + printf -- "Running tests\n" 1>&2 + printf -- "-------------\n" 1>&2 + for scenario in ${test_scenarios}; do # We can't call this function with $( ... ) because we # want to allow it to echo values to stdout. scenario_runner ${scenario} diff -Nru spiped-1.6.1/tests/shared_valgrind_functions.sh spiped-1.6.2/tests/shared_valgrind_functions.sh --- spiped-1.6.1/tests/shared_valgrind_functions.sh 1970-01-01 00:00:00.000000000 +0000 +++ spiped-1.6.2/tests/shared_valgrind_functions.sh 2021-12-09 22:15:31.000000000 +0000 @@ -0,0 +1,366 @@ +#!/bin/sh + +set -o noclobber -o nounset + +### Design +# +# This file contains functions related to checking with valgrind. The POSIX sh +# language doesn't allow us to specify a "public API", but if we could, it +# would be: +# - valgrind_init(): +# Clear previous valgrind output, and prepare for running valgrind tests +# (if applicable). +# - valgrind_setup_cmd(): +# Set up the valgrind command if $USE_VALGRIND is greater than or equal to +# ${valgrind_min}. +# - valgrind_check_basenames(exitfile): +# Check for any memory leaks recorded in valgrind logfiles associated with a +# test exitfile. Return the filename if there's a leak; otherwise return an +# empty string. + +# A non-zero value unlikely to be used as an exit code by the programs being +# tested. +valgrind_exit_code=108 + +## valgrind_prepare_directory (): +# Clean up a previous valgrind directory, and prepare for new valgrind tests +# (if applicable). +valgrind_prepare_directory() { + # If we don't want to generate new suppressions files, move them. + if [ "${USE_VALGRIND_NO_REGEN}" -gt 0 ]; then + valgrind_suppressions="${out_valgrind}/suppressions" + fds="${out_valgrind}/fds.log" + # Bail if the file doesn't exist. + if [ ! -e "${valgrind_suppressions}" ]; then + echo "No valgrind suppressions file" 1>&2 + exit 1 + fi + + # Move the files away. + supp_tmp="$(mktemp /tmp/valgrind-suppressions.XXXXXX)" + fds_tmp="$(mktemp /tmp/valgrind-fds.XXXXXX)" + mv "${valgrind_suppressions}" "${supp_tmp}" + mv "${fds}" "${fds_tmp}" + fi + + # Always delete any previous valgrind directory. + if [ -d "${out_valgrind}" ]; then + rm -rf ${out_valgrind} + fi + + # Bail if we don't want valgrind at all. + if [ "$USE_VALGRIND" -eq 0 ]; then + return + fi + + mkdir ${out_valgrind} + + # If we don't want to generate a new suppressions file, restore it. + if [ "${USE_VALGRIND_NO_REGEN}" -gt 0 ]; then + # Move the files back. + mv "${supp_tmp}" "${valgrind_suppressions}" + mv "${fds_tmp}" "${fds}" + fi +} + +## valgrind_check_optional (): +# Return a $USE_VALGRIND variable defined; if it was previously defined and +# was greater than 0, then check that valgrind is available in the $PATH. +valgrind_check_optional() { + if [ "$USE_VALGRIND" -gt 0 ]; then + # Look for valgrind in $PATH. + if ! command -v valgrind >/dev/null 2>&1; then + printf "valgrind not found\n" 1>&2 + exit 1 + fi + + # Check the version. + version=$(valgrind --version | cut -d "-" -f 2) + major=$(echo "${version}" | cut -d "." -f 1) + minor=$(echo "${version}" | cut -d "." -f 2) + if [ "${major}" -lt "3" ]; then + printf "valgrind must be at least version 3.13\n" 1>&2 + exit 1; + fi + if [ "${major}" -eq "3" ] && [ "${minor}" -lt "13" ]; then + printf "valgrind must be at least version 3.13\n" 1>&2 + exit 1; + fi + fi +} + +## valgrind_process_suppresion_file(filename): +# Generalize suppressions from a valgrind suppression file by omitting the +# "fun:pl_*" and "fun:main" lines and anything below them. +valgrind_process_suppression_file() { + filename=$1 + + # How many segments do we have? + num_segments="$(grep -c "^{" "${filename}")" + + # Bail if there's nothing to do. + if [ "${num_segments}" -eq "0" ]; then + return + fi + + # Sanity check. + if [ "${num_segments}" -gt 100 ]; then + printf "More than 100 valgrind suppressions?!\n" 1>&2 + exit 1 + fi + + # Split into segments. + csplit -f "${filename}" "${filename}" "/{/" \ + "{$((num_segments - 1))}" > /dev/null + + # Skip "${filename}00" because that doesn't contain a suppression. + i=1 + while [ "$i" -le "${num_segments}" ]; do + segfilename="$(printf "%s%02i" "${filename}" "$i")" + + # Find last relevant line. + lastline="$(grep -n "}" "${segfilename}" | cut -f1 -d:)" + + # Cut off anything below "fun:pl_" (including that line). + funcline="$(grep -n "fun:pl_" "${segfilename}" | cut -f1 -d:)" + if [ -n "${funcline}" ]; then + if [ "${lastline}" -gt "${funcline}" ]; then + lastline="${funcline}" + fi + fi + + # Cut off anything below "fun:main" (including that line). + # (Due to linking and/or optimizations, some memory leaks + # occur without "fun:pl_" appearing in the valgrind + # suppression.) + funcline="$(grep -n "fun:main" "${segfilename}" | cut -f1 -d:)" + if [ -n "${funcline}" ]; then + if [ "${lastline}" -gt "${funcline}" ]; then + lastline="${funcline}" + fi + fi + + # Only keep the beginning of each suppression. + lastline="$((lastline - 1))" + head -n "$lastline" "${segfilename}" >> \ + "${valgrind_suppressions}" + printf "}\n" >> "${valgrind_suppressions}" + + # Advance to the next suppression. + i=$((i + 1)) + done +} + +## valgrind_ensure_suppression (potential_memleaks_binary): +# Run the ${potential_memleaks_binary} through valgrind, keeping +# track of any apparent memory leak in order to suppress reporting +# those leaks when testing other binaries. Record how many file descriptors +# are open at exit in ${valgrind_fds}. +valgrind_ensure_suppression() { + potential_memleaks_binary=$1 + + # Quit if we're not using valgrind. + if [ ! "$USE_VALGRIND" -gt 0 ]; then + return + fi; + + fds_log="${out_valgrind}/fds.log" + + if [ "${USE_VALGRIND_NO_REGEN}" -gt 0 ]; then + printf "Using old valgrind suppressions\n" 1>&2 + valgrind_fds=$(grep "FILE DESCRIPTORS" "${fds_log}" | \ + awk '{print $4}') + return + fi + + printf "Generating valgrind suppressions... " 1>&2 + valgrind_suppressions="${out_valgrind}/suppressions" + valgrind_suppressions_log="${out_valgrind}/suppressions.pre" + + # Start off with an empty suppression file + touch ${valgrind_suppressions} + + # Get list of tests and the number of open descriptors at a normal exit + valgrind_suppressions_tests="${out_valgrind}/suppressions-names.txt" + valgrind --track-fds=yes --log-file=${fds_log} \ + ${potential_memleaks_binary} > "${valgrind_suppressions_tests}" + valgrind_fds=$(grep "FILE DESCRIPTORS" "${fds_log}" | awk '{print $4}') + + # Generate suppressions for each test + while read testname; do + this_valgrind_supp="${valgrind_suppressions_log}-${testname}" + + # Run valgrind on the binary, sending it a "\n" so that + # a test which uses STDIN will not wait for user input. + printf "\n" | (valgrind \ + --leak-check=full --show-leak-kinds=all \ + --gen-suppressions=all \ + --suppressions=${valgrind_suppressions} \ + --log-file=${this_valgrind_supp} \ + ${potential_memleaks_binary} \ + ${testname}) \ + > /dev/null + + # Append name to suppressions file + printf "# ${testname}\n" >> ${valgrind_suppressions} + + # Strip out useless parts from the log file, and allow the + # suppressions to apply to other binaries. + valgrind_process_suppression_file "${this_valgrind_supp}" + done < "${valgrind_suppressions_tests}" + + # Clean up + rm -f ${valgrind_suppressions_log} + printf "done.\n" 1>&2 +} + +## valgrind_setup_cmd (): +# Set up the valgrind command if $USE_VALGRIND is greater than or equal to +# ${valgrind_min}. +valgrind_setup_cmd() { + # Bail if we don't want to use valgrind for this check. + if [ "${USE_VALGRIND}" -lt "${c_valgrind_min}" ]; then + return + fi + + val_logfilename="${s_val_basename}-${count_str}-%p.log" + c_valgrind_cmd="valgrind \ + --log-file=${val_logfilename} \ + --track-fds=yes \ + --leak-check=full --show-leak-kinds=all \ + --errors-for-leak-kinds=all \ + --suppressions=${valgrind_suppressions}" + echo "${c_valgrind_cmd}" +} + +## valgrind_get_basename (exitfile): +# Return the filename without ".log" of the valgrind logfile corresponding to +# ${exitfile}. +valgrind_get_basename() { + exitfile=$1 + basename=$(basename "${exitfile}" ".exit") + echo "${out_valgrind}/${basename}" +} + +## valgrind_check_logfile(logfile) +# Check for any (unsuppressed) memory leaks recorded in a valgrind logfile. +# Echo the filename if there's a leak; otherwise, echo nothing. +valgrind_check_logfile() { + logfile=$1 + + # Bytes in use at exit. + in_use=$(grep "in use at exit:" "${logfile}" | awk '{print $6}') + + # Sanity check. + if [ $(echo "${in_use}" | wc -w) -ne "1" ]; then + echo "Programmer error: invalid number valgrind outputs" 1>&2 + exit 1 + fi + + # Check for any leaks. Use string comparison, because valgrind formats + # the number with commas, and sh can't convert strings like "1,000" + # into an integer. + if [ "${in_use}" != "0" ] ; then + # Check if all of the leaked bytes are suppressed. The extra + # whitespace in " suppressed" is necessary to distinguish + # between two instances of "suppressed" in the log file. Use + # string comparison due to the format of the number. + suppressed=$(grep " suppressed:" "${logfile}" | \ + awk '{print $3}') + if [ "${in_use}" != "${suppressed}" ]; then + # There is an unsuppressed leak. + echo "${logfile}" + return + fi + fi + + # Check for the wrong number of open fds. On a normal desktop + # computer, we expect 4: std{in,out,err}, plus the valgrind logfile. + # If this is running inside a virtualized OS or container or shared + # CI setup (such as Travis-CI), there might be other open + # descriptors. The important thing is that the number of fds should + # match the simple test case (executing potential_memleaks without + # running any actual tests). + fds_in_use=$(grep "FILE DESCRIPTORS" "${logfile}" | awk '{print $4}') + if [ "${fds_in_use}" != "${valgrind_fds}" ] ; then + # There is an unsuppressed leak. + echo "${logfile}" + return + fi + + # Check the error summary. + num_errors=$(grep "ERROR SUMMARY: " "${logfile}" | awk '{print $4}') + if [ "${num_errors}" -gt 0 ]; then + # There was some other error(s) -- invalid read or write, + # conditional jump based on uninitialized value(s), invalid + # free, etc. + echo "${logfile}" + return + fi +} + +## valgrind_check_basenames (exitfile): +# Check for any memory leaks recorded in valgrind logfiles associated with a +# test exitfile. Return the filename if there's a leak; otherwise return an +# empty string. +valgrind_check_basenames() { + exitfile="$1" + val_basename=$( valgrind_get_basename ${exitfile} ) + + # Get list of files to check. (Yes, the star goes outside the quotes.) + logfiles=$(ls "${val_basename}"* 2>/dev/null) + num_logfiles=$(echo "${logfiles}" | wc -w) + + # Bail if we don't have any valgrind logfiles to check. + # Use numeric comparison, because wc leaves a tab in the output. + if [ "${num_logfiles}" -eq "0" ] ; then + return + fi + + # Check a single file. + if [ "${num_logfiles}" -eq "1" ]; then + valgrind_check_logfile "${logfiles}" + return + fi + + # If there's two files, there's a fork() -- likely within + # daemonize() -- so only pay attention to the child. + if [ "${num_logfiles}" -eq "2" ]; then + # Find both pids. + val_pids="" + for logfile in ${logfiles} ; do + val_pid=$(head -n 1 "${logfile}" | cut -d "=" -f 3) + val_pids="${val_pids} ${val_pid}" + done + + # Find the logfile which has a parent in the list of pids. + for logfile in ${logfiles} ; do + val_parent_pid=$(grep "Parent PID:" "${logfile}" | \ + awk '{ print $4 }') + if [ "${val_pids#*$val_parent_pid}" != \ + "${val_pids}" ]; then + valgrind_check_logfile "${logfile}" + return "$?" + fi + done + fi + + # Programmer error; hard bail. + echo "Programmer error: wrong number of valgrind logfiles!" 1>&2 + exit 1 +} + +## valgrind_init(): +# Clear previous valgrind output, and prepare for running valgrind tests +# (if applicable). +valgrind_init() { + # If we want valgrind, check that the version is high enough. + valgrind_check_optional + + # Remove any previous directory, and create a new one. + valgrind_prepare_directory + + # Generate valgrind suppression file if it is required. Must be + # done after preparing the directory. + valgrind_ensure_suppression ${bindir}/tests/valgrind/potential-memleaks +} diff -Nru spiped-1.6.1/tests/spiped_servers.sh spiped-1.6.2/tests/spiped_servers.sh --- spiped-1.6.1/tests/spiped_servers.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/spiped_servers.sh 2021-01-11 23:41:03.000000000 +0000 @@ -11,19 +11,19 @@ check_leftover_servers() { # Find old nc-server on ${dst_sock}. if [ -n "${nc_server_binary+set}" ]; then - if $( has_pid "${nc_server_binary} ${dst_sock}" ); then - echo "Error: Left-over nc-server from previous run." + if has_pid "${nc_server_binary} ${dst_sock}" ; then + echo "Error: Left-over nc-server from previous run." 1>&2 exit 1 fi fi # Find old spiped {-d, -e} servers on {${mid_sock}, ${src_sock}}. - if $( has_pid "spiped -d -s ${mid_sock}" ); then - echo "Error: Left-over spiped -d from previous run." + if has_pid "spiped -d -s ${mid_sock}" ; then + echo "Error: Left-over spiped -d from previous run." 1>&2 exit 1 fi - if $( has_pid "spiped -e -s ${src_sock}" ); then - echo "Error: Left-over spiped -e from previous run." + if has_pid "spiped -e -s ${src_sock}" ; then + echo "Error: Left-over spiped -e from previous run." 1>&2 exit 1 fi } @@ -45,7 +45,7 @@ check_leftover_servers # We need to set this up here so that ${c_valgrind_cmd} is set. - setup_check_variables + setup_check_variables "setup_spiped_decryption_server" # Select system or compiled spiped. if [ "${use_system_spiped}" -gt 0 ]; then @@ -69,6 +69,7 @@ -t ${dst_sock} \ -p ${s_basename}-spiped-d.pid \ -k /dev/null -o 1 + echo "$?" > "${c_exitfile}" } ## setup_spiped_decryption_server(basename): @@ -76,13 +77,14 @@ # to ${mid_sock}, saving the exit code to ${c_exitfile}. setup_spiped_encryption_server () { # Start spiped to connect source port to middle. - setup_check_variables + setup_check_variables "setup_spiped_encryption_server" ${c_valgrind_cmd} \ ${spiped_binary} -e \ -s ${src_sock} \ -t ${mid_sock} \ -p ${s_basename}-spiped-e.pid \ -k /dev/null -o 1 + echo "$?" > "${c_exitfile}" } ## servers_stop(): @@ -90,11 +92,11 @@ servers_stop() { # Signal spiped servers to stop if [ -e ${s_basename}-spiped-e.pid ]; then - kill `cat ${s_basename}-spiped-e.pid` + kill "$(cat ${s_basename}-spiped-e.pid)" rm ${s_basename}-spiped-e.pid fi if [ -e ${s_basename}-spiped-d.pid ]; then - kill `cat ${s_basename}-spiped-d.pid` + kill "$(cat ${s_basename}-spiped-d.pid)" rm ${s_basename}-spiped-d.pid fi @@ -102,24 +104,33 @@ sleep 1 # Waiting for servers to stop - while $( has_pid "spiped -e -s ${src_sock}" ); do + while has_pid "spiped -e -s ${src_sock}" ; do if [ ${VERBOSE} -ne 0 ]; then - echo "Waiting to stop: spiped -e" + echo "Waiting to stop: spiped -e" 1>&2 fi sleep 1 done - while $( has_pid "spiped -d -s ${mid_sock}" ); do + while has_pid "spiped -d -s ${mid_sock}" ; do if [ ${VERBOSE} -ne 0 ]; then - echo "Waiting to stop: spiped -d" + echo "Waiting to stop: spiped -d" 1>&2 fi sleep 1 done if [ -n "${nc_server_binary+set}" ]; then - while $( has_pid "${nc_server_binary} ${dst_sock}" ); do + while has_pid "${nc_server_binary} ${dst_sock}" ; do if [ ${VERBOSE} -ne 0 ]; then - echo "Waiting to stop: ncat" + echo "Waiting to stop: ncat" 1>&2 fi sleep 1 done fi + + # Give valgrind a chance to finish writing files + if [ -n "${c_valgrind_cmd}" ]; then + if [ "${VERBOSE}" -ne 0 ]; then + printf "Giving extra time for valgrind to write" + printf " the logfile\n" 1>&2 + fi + sleep 1 + fi } diff -Nru spiped-1.6.1/tests/test_spiped.sh spiped-1.6.2/tests/test_spiped.sh --- spiped-1.6.1/tests/test_spiped.sh 2019-10-29 18:43:35.000000000 +0000 +++ spiped-1.6.2/tests/test_spiped.sh 2021-07-04 18:08:39.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh ### Find script directory and load helper functions. -scriptdir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +scriptdir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P) . ${scriptdir}/shared_test_functions.sh @@ -11,9 +11,9 @@ out_valgrind="${bindir}/tests-valgrind" # This test script requires three sockets. -src_sock=[127.0.0.1]:8001 -mid_sock=[127.0.0.1]:8002 -dst_sock=[127.0.0.1]:8003 +src_sock="[127.0.0.1]:8001" +mid_sock="[127.0.0.1]:8002" +dst_sock="[127.0.0.1]:8003" # Find relative spiped binary paths. spiped_binary=${scriptdir}/../spiped/spiped @@ -40,4 +40,4 @@ ### Run tests using project-specific constants -run_scenarios ${scriptdir}/??-*.sh +run_scenarios diff -Nru spiped-1.6.1/tests/valgrind/potential-memleaks.c spiped-1.6.2/tests/valgrind/potential-memleaks.c --- spiped-1.6.1/tests/valgrind/potential-memleaks.c 2019-11-06 00:04:00.000000000 +0000 +++ spiped-1.6.2/tests/valgrind/potential-memleaks.c 2021-07-04 18:08:39.000000000 +0000 @@ -1,7 +1,14 @@ +#include +#include + +#include + +#include #include #include #include #include +#include /* Problem with FreeBSD 11.0 merely linking with -lrt. */ static void @@ -26,23 +33,114 @@ (void)len; } +/* Problem with FreeBSD 12.1 and printf(). */ +static void +pl_freebsd_printf_space(void) +{ + + printf(" "); +} + +/* Problem with FreeBSD 12.1 and printf(). */ +static void +pl_freebsd_printf_space_newline(void) +{ + + printf(" \n"); +} + /* Part of the pthread init. */ static void * -do_nothing(void * cookie) +pl_workthread_nothing(void * cookie) { - (void)cookie; + (void)cookie; /* UNUSED */ return (NULL); } /* Problem with FreeBSD 11.0 and creating/freeing a thread. */ static void -pl_freebsd_pthread(void) +pl_freebsd_pthread_nothing(void) +{ + pthread_t thr; + int rc; + + if ((rc = pthread_create(&thr, NULL, pl_workthread_nothing, NULL))) + fprintf(stderr, "pthread_create: %s", strerror(rc)); + if ((rc = pthread_join(thr, NULL))) + fprintf(stderr, "pthread_join: %s", strerror(rc)); +} + +/* Problem with FreeBSD and pthread with strerror and localtime_r. */ +static void * +pl_workthread_strerror_localtime(void * cookie) { - pthread_t thread; + char * str = strerror(1); + time_t now; + struct tm tm; + + (void)cookie; /* UNUSED */ + (void)str; /* UNUSED */ - pthread_create(&thread, NULL, do_nothing, NULL); - pthread_join(thread, NULL); + time(&now); + localtime_r(&now, &tm); + + return (NULL); +} + +static void +pl_freebsd_pthread_strerror_localtime(void) +{ + pthread_t thr; + int rc; + + if ((rc = pthread_create(&thr, NULL, + pl_workthread_strerror_localtime, NULL))) + fprintf(stderr, "pthread_create: %s", strerror(rc)); + if ((rc = pthread_join(thr, NULL))) + fprintf(stderr, "pthread_join: %s", strerror(rc)); +} + +/* Problem with FreeBSD and pthread with getaddrinfo. */ +static void * +pl_workthread_getaddrinfo(void * cookie) +{ + struct addrinfo hints; + struct addrinfo * res; + const char * addr = "localhost"; + const char * ports = "80"; + int error; + + (void)cookie; /* UNUSED */ + + /* Create hints structure. */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* Perform DNS lookup. */ + if ((error = getaddrinfo(addr, ports, &hints, &res)) != 0) + fprintf(stderr, "Error looking up %s: %s", addr, + gai_strerror(error)); + + /* Clean up. */ + freeaddrinfo(res); + + return (NULL); +} + +static void +pl_freebsd_pthread_getaddrinfo(void) +{ + pthread_t thr; + int rc; + + if ((rc = pthread_create(&thr, NULL, + pl_workthread_getaddrinfo, NULL))) + fprintf(stderr, "pthread_create: %s", strerror(rc)); + if ((rc = pthread_join(thr, NULL))) + fprintf(stderr, "pthread_join: %s", strerror(rc)); } #define MEMLEAKTEST(x) { #x, x } @@ -52,7 +150,11 @@ } tests[] = { MEMLEAKTEST(pl_freebsd_link_lrt), MEMLEAKTEST(pl_freebsd_strlen), - MEMLEAKTEST(pl_freebsd_pthread) + MEMLEAKTEST(pl_freebsd_printf_space), + MEMLEAKTEST(pl_freebsd_printf_space_newline), + MEMLEAKTEST(pl_freebsd_pthread_nothing), + MEMLEAKTEST(pl_freebsd_pthread_strerror_localtime), + MEMLEAKTEST(pl_freebsd_pthread_getaddrinfo) }; static const int num_tests = sizeof(tests) / sizeof(tests[0]); @@ -64,15 +166,25 @@ if (argc == 2) { /* Run the relevant function. */ for (i = 0; i < num_tests; i++) { - if ((strcmp(argv[1], tests[i].name)) == 0) + if ((strcmp(argv[1], tests[i].name)) == 0) { tests[i].func(); + goto success; + } } + + /* We didn't find the desired function name. */ + goto err0; } else { /* Print test names. */ for (i = 0; i < num_tests; i++) printf("%s\n", tests[i].name); } +success: /* Success! */ exit(0); + +err0: + /* Failure! */ + exit(1); }