spiped-1.4.1/000755 001751 001751 00000000000 12403117335 014434 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/spiped/000755 001751 001751 00000000000 12403117335 015720 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/spipe/000755 001751 001751 00000000000 12403117336 015555 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/BUILDING000644 001751 001751 00000003772 12403117255 015566 0ustar00cpercivacperciva000000 000000 To build and install spiped, run: # make BINDIR=/path/to/target/directory install To install man pages, add MAN1DIR=/path/to/man.1/directory to the command line (e.g., MAN1DIR=/usr/local/man/man1 on FreeBSD). Spiped should build and run on any IEEE Std 1003.1 (POSIX) compliant system which 1. Includes the Software Development Utilities option, 2. Has OpenSSL available via -lcrypto and #include , and 3. Provides /dev/urandom. On some platforms (Solaris, maybe others), additional compiler and/or linker options are required to find OpenSSL or system libraries; these can be provided by adding e.g., CFLAGS="-I/path/to/openssl/headers" (compiler option) or LDADD_EXTRA="-L/usr/sfw/lib -lsocket -lnsl" (linker option) to the make command line. On OS X, the version of OpenSSL included with the operating system is outdated (0.9.8) and deprecated, and it is recommended that spiped be built with an updated version of OpenSSL. After installing a newer version of OpenSSL, use CFLAGS="-I /path/to/openssl/headers" and LDADD_EXTRA="-L /path/to/openssl/lib" to build spiped with your newer OpenSSL. Note that spiped will still build if you set these options wrong: If you see warning: 'AES_set_encrypt_key' is deprecated during the build then spiped is still using the outdated version of OpenSSL from OS X. 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 libcperciva/util/sock_util.c proto/proto_conn.c spipe/main.c spipe/pushbits.c due to a POSIX-compliance bug on those platforms. On some platforms (mostly Linuxes) it is possible to install OpenSSL libaries wihout the associated header files; the header files are usually in packages named "openssl-devel", "libssl-dev", or similar. If your OS provides random bytes via some mechanism other than /dev/urandom, please make local changes to lib/util/entropy.c and notify the author. If spiped fails to build or run for other reasons, please notify the author. spiped-1.4.1/CHANGELOG000644 001751 001751 00000003655 12403117256 015661 0ustar00cpercivacperciva000000 000000 spiped-1.4.1 * Fix build on OS X, and improve strict POSIX compliance. * Improved zeroing of sensitive cryptographic data. spiped-1.4.0 * Add automatic detection of compiler support (at compile-time) and CPU support (at run-time) for x86 "AES New Instructions"; and when available, use these to improve cryptographic performance. * Add support for -g option, which makes {spiped, spipe} require perfect forward secrecy by dropping connections if the peer endpoint is detected to be running using the -f option. spiped-1.3.1 * Fix build by adding missing #include. * Minor code cleanups. spiped-1.3.0 * Bug fix: spiped now correctly closes connections which have been reset; in earlier versions spiped could erronously hold "dead" connections open as long as they remained idle. * Man pages added. * Protocol-layer keep-alives are now enabled by default. * New option -j (spipe/spiped): Disable protocol-layer keep-alives. * In spiped the target address is now re-resolved every 60 seconds by default. * New option -R (spiped): Do not re-resolve target address. * New option -r (spiped): Re-resolve target address every seconds. spiped-1.2.2 * Build fixes for some strictly POSIX-conforming platforms. * Detect and work around compilers which are POSIX-noncompliant in their handling of -rt and -lxnet options. * Minor documentation and typo fixes. spiped-1.2.1 * Fix build by adding missing #include. spiped-1.2.0 * New utility "spipe": A client for the spiped protocol, handling a single connection with standard input/output as one end. * Code rearrangement with no functional consequences. * Minor bug and documentation fixes. spiped-1.1.0 * New option -D: Wait until DNS lookups succeed. * New option -F: Don't daemonize. * Use SO_REUSEADDR to avoid 'socket address already in use' error (most importantly, if spiped is killed and restarted). * Minor bug and style fixes. spiped-1.0.0 * Initial release spiped-1.4.1/COPYRIGHT000644 001751 001751 00000003102 12403117256 015725 0ustar00cpercivacperciva000000 000000 The included code and documentation ("spiped") is distributed under the following terms: Copyright 2005-2014 Colin Percival. All rights reserved. Copyright 2014 Sean Kelly. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. In addition to the above, some files are: Copyright 2012 Andreas Olsson and distributed under the same terms. Such files contain individual copyright statements and licenses. spiped-1.4.1/README000644 001751 001751 00000021431 12403117255 015316 0ustar00cpercivacperciva000000 000000 spiped design ============= Introduction ------------ spiped (pronounced "ess-pipe-dee") is a utility for creating symmetrically encrypted and authenticated pipes between socket addresses, so that one may connect to one address (e.g., a UNIX socket on localhost) and transparently have a connection established to another address (e.g., a UNIX socket on a different system). This is similar to 'ssh -L' functionality, but does not use SSH and requires a pre-shared symmetric key. spipe (pronounced "ess-pipe") is a utility which acts as an spiped protocol client (i.e., connects to an spiped daemon), taking input from the standard input and writing data read back to the standard output. Note that spiped: 1. Requires a strong key file: The file specified via the -k option should have at least 256 bits of entropy. ('dd if=/dev/urandom bs=32 count=1' is your friend.) 2. Requires strong entropy from /dev/urandom. (Make sure your kernel's random number generator is seeded at boot time!) 3. Does not provide any protection against information leakage via packet timing: Running telnet over spiped will protect a password from being directly read from the network, but will not obscure the typing rhythm. 4. Can significantly increase bandwidth usage for interactive sessions: It sends data in packets of 1024 bytes, and pads smaller messages up to this length, so a 1 byte write could be expanded to 1024 bytes if it cannot be coalesced with adjacent bytes. 5. Uses a symmetric key -- so anyone who can connect to an spiped "server" is also able to impersonate it. Example usage ------------- To set up an encrypted and authenticated pipe for sending email between two systems (in the author's case, from many systems around the internet to his central SMTP server, which then relays email to the rest of the world), one might run # dd if=/dev/urandom bs=32 count=1 of=keyfile # spiped -d -s '[0.0.0.0]:8025' -t '[127.0.0.1]:25' -k keyfile on a server and after copying keyfile to the local system, run # spiped -e -s '[127.0.0.1]:25' -t $SERVERNAME:8025 -k keyfile at which point mail delivered via localhost:25 on the local system will be securely transmitted to port 25 on the server. You can also use spiped to protect SSH servers from attackers: Since data is authenticated before being forwarded to the target, this can allow you to SSH to a host while protecting you in the event that someone finds an exploitable bug in the SSH daemon -- this serves the same purpose as port knocking or a firewall which restricts source IP addresses which can connect to SSH. On the SSH server, run # dd if=/dev/urandom bs=32 count=1 of=/etc/ssh/spiped.key # spiped -d -s '[0.0.0.0]:8022' -t '[127.0.0.1]:22' -k /etc/ssh/spiped.key then copy the server's /etc/ssh/spiped.key to ~/.ssh/spiped_HOSTNAME_key on your local system and add the lines Host HOSTNAME ProxyCommand spipe -t %h:8022 -k ~/.ssh/spiped_%h_key to the ~/.ssh/config file. This will cause "ssh HOSTNAME" to automatically connect using the spipe client via the spiped daemon; you can then firewall off all incoming traffic on port tcp/22. For a detailed list of the command-line options to spiped and spipe, see the README files in the respective subdirectories. Security requirements --------------------- The user is responsible for ensuring that: 1. The key file contains 256 or more bits of entropy. 2. The same key file is not used for more than 2^64 connections. 3. Any individual connection does not transmit more than 2^64 bytes. Encrypted protocol ------------------ The client and server share a key file with 256 or more bits of entropy. On launch, they read the key file and compute K = SHA256(key file). When a connection is established: C1. The client generates a 256-bit random value nonce_C and sends it. S1. The server generates a 256-bit random value nonce_S and sends it. C2. The client receives a 256-bit value nonce_S. S2. The server receives a 256-bit value nonce_C. C3/S3. Both parties now compute the 512-bit value dk_1 = PBKDF2-SHA256(K, nonce_C || nonce_S, 1) and parse it as a pair of 256-bit values dhmac_C || dhmac_S = dk_1. C4. The client picks* a value x_C and computes** y_C = 2^x_C mod p, where p is the Diffie-Hellman "group #14" modulus, and h_C = HMAC-SHA256(dhmac_C, y_C). The client sends y_C || h_C to the server. S4. The server receives a 2304-bit value which it parses as y_C || h_C, where y_C is 2048 bits and h_C is 256 bits; and drops the connection if h_C is not equal to HMAC-SHA256(dhmac_C, y_C) or y_C >= p. S5. The server picks* a value x_S and computes** y_S = 2^x_S mod p and h_S = HMAC-SHA256(dhmac_S, y_S). The server sends y_S || h_S to the client. C5. The client receives a 2304-bit value which it parses as y_S || h_S, where y_S is 2048 bits and h_S is 256 bits; and drops the connection if h_S is not equal to HMAC-SHA256(dhmac_S, y_S) or y_S >= p. C6. The client computes** y_SC = y_S^x_C mod p. S6. The server computes** y_SC = y_C^x_S mod p. (Note that these two compute values are identical.) C7/S7. Both parties now compute the 1024-bit value dk_2 = PBKDF2-SHA256(K, nonce_C || nonce_S || y_SC, 1) and parse it as a 4-tuple of 256-bit values E_C || H_C || E_S || H_S. Thereafter, the client and server exchange 1060-byte packets P generated from plaintext messages M of 1--1024 bytes msg_padded = M || ( 0x00 x (1024 - length(M))) || bigendian32(length(M)) msg_encrypted = AES256-CTR(E, msg_padded, packet#) P = msg_encrypted || HMAC-SHA256(H, msg_encrypted || bigendian64(packet#)) where E and H are E_C and H_C or E_S and H_S depending on whether the packet is being sent by the client or the server, and AES256-CTR is computed with nonce equal to the packet #, which starts at zero and increments for each packet sent in the same direction. * The values x_C, x_S picked must either be 0 (if forward perfect secrecy is not desired) or have 256 bits of entropy (if forward perfect secrecy is desired). ** The values y_C, y_S, and y_SC are 2048 bits and big-endian. Security proof -------------- 1. Under the random oracle model, K has at least 255 bits of entropy (it's a 256-bit hash computed from a value with at least 256 bits of entropy). 2. Provided that at least one party is following the protocol and the key file has been used for fewer than 2^64 connections, the probability of the tuple (K, nonce_C, nonce_S) being non-unique is less than 2^(-192). 3. Under the random oracle model, the probability of an attacker without access to K guessing either of dhmac_C and dhmac_S is less than P(attacker guesses K) + P(the tuple has been input to the oracle before) + P(the attacker directly guesses), which is less than 2^(-255) + 2^(-192) + 2^(-255) = 2^(-192) + 2^(-254). 4. Consequently, in order for an attacker to convince a protocol-obeying party that a tuple (y, h) is legitimate, the attacker must do at least 2^190 expected work (which we consider to be computationally infeasible and do not consider any further). 5. If one of the parties opts to not have perfect forward secrecy, then the value y_SC will be equal to 1 and dk_2 will have the same security properties as dk_1, i.e., it will be computationally infeasible for an attacker without access to K to compute dk_2. 6. If both parties opt for perfect forward secrecy, an attacker who can compute y_SC has solved a Diffie-Hellman problem over the 2048-bit group #14, which is (under the CDH assumption) computationally infeasible. 7. Consequently, if both parties opt for perfect forward secrecy, an attacker who obtains access to K after the handshake has completed will continue to be unable to compute dk_2 from information exchanged during the handshake. 8. Under the random oracle model, the packets P are indistinguishable from random 1060-byte packets; thus no information about the keys used or the plaintext being transmitted is revealed by post-key-exchange communications. 9. Because the values (msg_encrypted || bigendian(packet#)) are distinct for each packet, under the random oracle model it is infeasible for an attacker without access to the value H to generate a packet which will be accepted as valid. Code layout ----------- spiped/* -- Code specific to the spiped utility. main.c -- Command-line parsing, initialization, and event loop. dispatch.c -- Accepts connections and hands them off to protocol code. spipe/* -- Code specific to the spipe utility. main.c -- Command-line parsing, initialization, and event loop. pushbits.c -- Copies data between standard input/output and a socket. proto/* -- Implements the spiped protocol. _conn.c -- Manages the lifecycle of a connection. _handshake.c -- Performs the handshaking portion of the protocol. _pipe.c -- Performs the data-shuttling portion of the protocol. _crypt.c -- Does the cryptographic bits needed by _handshake and _pipe. lib/* -- Library code (mostly originating from tarsnap and kivaloo). spiped-1.4.1/STYLE000644 001751 001751 00000012347 12403117255 015267 0ustar00cpercivacperciva000000 000000 Code style ========== In general, FreeBSD style(9) should be followed unless it is irrelevant (e.g., $FreeBSD$ tags). Functions with external linkage are declared like this: /** * module_func(arg1, arg2): * Description of what the function does, referring to arguments as * ${arg1} or suchlike. */ int module_func(void *, int); The identical comment appears in the C file where the function is defined. Static functions may have the above form of comment, or simply a /* Brief description of what the function does. */ line before the function. In general, functions should return (int)(-1) or NULL to indicate error. Errors should be printed via warnp (if errno is relevant) or warn0 (if errno is not relevant) when they are first detected and also at higher levels where useful. As an exception to this, malloc failures (i.e., errno = ENOMEM) can result in failure being passed back up the call chain without being printed immediately. (Naturally, other errors can be passed back where a function definition so specifies; e.g., ENOENT in cases where a file not existing is not erronous.) The first statement in main(), after variable declarations, should be "WARNP_INIT;" in order to set the program name used for printing warnings. In general, functions should be structured with one return statement per status, e.g., one return() for success and one return() for failure. Errors should be handled by using goto to enter the error return path, e.g., int foo(int bar) { if (something fails) goto err0; /* ... */ if (something else fails) goto err1; /* ... */ if (yet another operation fails) goto err2; /* Success! */ return (0); err2: /* Clean up something. */ err1: /* Clean up something else. */ err0: /* Failure! */ return (-1); } As an exception to the above, if there is only one way for the function to fail, the idioms return (baz(bar)); and int rc; rc = baz(bar); /* ... cleanup code here ... */ return (rc); are allowed; furthermore, in cases such as foo_free(), the idiom if (we shouldn't do anything) return; is preferred over if (we shouldn't do anything) goto done; at the start of a function. Headers should be included in the following groups, with a blank line after each (non-empty) group: 1. , with first followed by others alphabetically. 2. , in alphabetical order. 3. <*.h>, in alphabetical order. 4. header files from /lib/, in alphabetical order. 5. header files from the program being built, in alphabetical order. 6. header files (usually just one) defining the interface for this C file. If ssize_t is needed, should be included to provide it. If size_t is needed, should be included to provide it unless , , , or is already required. If the C99 integer types (uint8_t, int64_t, etc.) are required, should be included to provide them unless is already required. The type 'char' should only be used to represent human-readable characters (input from users, output to users, pathnames, et cetera). The type 'char *' should normally be a NUL-terminated string. The types 'signed char' and 'unsigned char' should never be used; C99 integer types should be used instead. When a variable is declared to have a pointer type, there should be a space between the '*' and the variable name, e.g., int main(int argc, char * argv[]) { char * opt_p = NULL; Note that this is inconsistent with FreeBSD style(9). When used as a unary operator, '*' is not separated from its argument, e.g., while (*p != '\0') p++; When a struct is referenced, the idiom /* Opaque types. */ struct foo; struct bar * bar_from_foo(struct foo *); is preferable to #include "foo.h" /* needed for struct foo */ struct bar * bar_from_foo(struct foo *); unless there is some reason why the internal layout of struct foo is needed (e.g., if struct bar contains a struct foo rather than a struct foo *). Such struct declarations should be sorted alphabetically. The file foo.c should only export symbols of the following forms: foo_* -- most symbols should be of this form. FOO_* / BAR_FOO_* -- allowed in cases where FOO or BAR_FOO is idiomatic (e.g., MD5, HMAC_SHA256). foo() / defoo() / unfoo() -- where "foo" is a verb and this improves code clarity. Functions named foo_free should return void, and foo_free(NULL) should have no effect. If static variables need to be initialized to 0 (or NULL) then they should be explicitly declared that way; implicit initialization should not be used. In non-trivial code, comments should be included which describe in English what is being done by the surrounding code with sufficient detail that if the code were removed, it could be replaced based on reading the comments without requiring any significant creativity. Comments and documentation should be written in en-GB-oed; i.e., with the 'u' included in words such as "honour", "colour", and "neighbour", and the ending '-ize' in words such as "organize" and "realize". The Oxford (aka. serial) comma should be used in lists. Quotation marks should be placed logically, i.e., not including punctuation marks which do not form a logical part of the quoted text. Two spaces should be used after a period which ends a sentence. spiped-1.4.1/POSIX/000755 001751 001751 00000000000 12403117256 015340 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/lib/000755 001751 001751 00000000000 12403117256 015204 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/000755 001751 001751 00000000000 12403117256 016721 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/proto/000755 001751 001751 00000000000 12403117256 015601 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/Makefile000644 001751 001751 00000001415 12403117335 016075 0ustar00cpercivacperciva000000 000000 .POSIX: PROGS= spiped spipe BINDIR_DEFAULT= /usr/local/bin CFLAGS_DEFAULT= -O2 all: export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \ export LDADD_POSIX=`export CC="${CC}"; cd POSIX && command -p sh posix-l.sh`; \ export CFLAGS_POSIX=`export CC="${CC}"; cd POSIX && command -p sh posix-cflags.sh`; \ ( export CC="${CC}"; cd libcperciva/cpusupport/Build && command -p sh cpusupport.sh ) > cpusupport-config.h; \ . ./cpusupport-config.h; \ for D in ${PROGS}; do \ ( cd $${D} && ${MAKE} all ) || exit 2; \ done install: all export BINDIR=$${BINDIR:-${BINDIR_DEFAULT}}; \ for D in ${PROGS}; do \ ( cd $${D} && ${MAKE} install ) || exit 2; \ done clean: rm -f cpusupport-config.h for D in ${PROGS}; do \ ( cd $${D} && ${MAKE} clean ) || exit 2; \ done spiped-1.4.1/proto/proto_crypt.h000644 001751 001751 00000007163 12403117256 020345 0ustar00cpercivacperciva000000 000000 #ifndef _PCRYPT_H_ #define _PCRYPT_H_ #include #include #include "crypto_dh.h" 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) /** * 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, requirefps): * 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 * ${requirefps} 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, nofps): * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If * ${nofps} 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, nofps, 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 ${nofps} 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 /* !_PCRYPT_H_ */ spiped-1.4.1/proto/proto_handshake.c000644 001751 001751 00000017321 12403117256 021122 0ustar00cpercivacperciva000000 000000 #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 nofps; int requirefps; 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, nofps, requirefps, 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 * ${nofps} is non-zero, perform a "weak" handshake without forward perfect * secrecy. If ${requirefps} 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 nofps, int requirefps, 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->nofps = nofps; H->requirefps = requirefps; 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->requirefps)) 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->nofps)) 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->nofps, 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); } spiped-1.4.1/proto/proto_handshake.h000644 001751 001751 00000002325 12403117256 021125 0ustar00cpercivacperciva000000 000000 #ifndef _PROTO_HANDSHAKE_H_ #define _PROTO_HANDSHAKE_H_ /* Opaque structures. */ struct proto_keys; struct proto_secret; /** * proto_handshake(s, decr, nofps, requirefps, 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 * ${nofps} is non-zero, perform a "weak" handshake without forward perfect * secrecy. If ${requirefps} 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_ */ spiped-1.4.1/proto/proto_conn.c000644 001751 001751 00000021206 12403117256 020126 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "events.h" #include "network.h" #include "sock.h" #include "proto_handshake.h" #include "proto_pipe.h" #include "proto_crypt.h" #include "proto_conn.h" struct conn_state { int (* callback_dead)(void *); void * cookie; struct sock_addr ** sas; int decr; int nofps; int requirefps; 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->nofps, C->requirefps, 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; /* * 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)); /* 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); } /* Drop a connection. */ static int dropconn(struct conn_state * C) { 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); /* Free the connection cookie. */ free(C); /* Return success/fail status. */ return (rc); } /** * proto_conn_create(s, sas, decr, nofps, requirefps, 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 ${nofps} is non-zero, * don't use perfect forward secrecy. If ${requirefps} 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. */ int proto_conn_create(int s, struct sock_addr ** sas, int decr, int nofps, int requirefps, int nokeepalive, const struct proto_secret * K, double timeo, int (* callback_dead)(void *), 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->nofps = nofps; C->requirefps = requirefps; 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 (0); err3: network_connect_cancel(C->connect_cookie); err2: events_timer_cancel(C->connect_timeout_cookie); err1: free(C); err0: /* Failure! */ return (-1); } /* 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 (dropconn(C)); /* If we're encrypting, start the handshake. */ if (!C->decr) { if (starthandshake(C, C->t, C->decr)) goto err1; } /* If we have connections and keys, start shuttling data. */ if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { if (launchpipes(C)) goto err1; } /* Success! */ return (0); err1: dropconn(C); /* 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 dropconn, after cancelling the connect. */ /* Drop the connection. */ return (dropconn(C)); } /* 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 (dropconn(C)); /* 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 have connections and keys, start shuttling data. */ if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) { if (launchpipes(C)) goto err1; } /* Success! */ return (0); err1: dropconn(C); /* 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 (dropconn(C)); } /* 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 (dropconn(C)); /* If both directions have been shut down, kill the connection. */ if ((C->stat_f == 0) && (C->stat_r == 0)) return (dropconn(C)); /* Nothing to do. */ return (0); } spiped-1.4.1/proto/proto_pipe.c000644 001751 001751 00000010505 12403117256 020126 0ustar00cpercivacperciva000000 000000 #include #include #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, 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, P->wlen, P->wlen, callback_pipe_write, P)) == NULL) goto err0; } else { if ((P->write_cookie = network_write(P->s_out, P->ebuf, P->wlen, 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); } spiped-1.4.1/proto/proto_crypt.c000644 001751 001751 00000023370 12403117256 020336 0ustar00cpercivacperciva000000 000000 #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. */ 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)) { warnp("Error reading file: %s", filename); goto err2; } /* Close the file. */ fclose(f); /* Compute the final hash. */ SHA256_Final(K->K, &ctx); /* Success! */ return (K); err2: fclose(f); err1: free(K); err0: /* Failure! */ return (NULL); } /** * proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr): * Using the key file hash ${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): * Returns 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, requirefps): * 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 * ${requirefps} 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 requirefps) { 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 (requirefps) { 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, nofps): * Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake * parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If * ${nofps} 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 nofps) { /* Are we skipping the diffie-hellman generation? */ if (nofps) { /* 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, nofps, 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 ${nofps} 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 nofps, 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 (nofps) { /* 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], 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 (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); } spiped-1.4.1/proto/proto_conn.h000644 001751 001751 00000002116 12403117256 020132 0ustar00cpercivacperciva000000 000000 #ifndef _PROTO_CONN_H_ #define _PROTO_CONN_H_ /* Opaque structures. */ struct proto_secret; struct sock_addr; /** * proto_conn_create(s, sas, decr, nofps, requirefps, 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 ${nofps} is non-zero, * don't use perfect forward secrecy. If ${requirefps} 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. */ int proto_conn_create(int, struct sock_addr **, int, int, int, int, const struct proto_secret *, double, int (*)(void *), void *); #endif /* !_CONN_H_ */ spiped-1.4.1/proto/proto_pipe.h000644 001751 001751 00000001375 12403117256 020140 0ustar00cpercivacperciva000000 000000 #ifndef _PROTO_PIPE_H_ #define _PROTO_PIPE_H_ 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_ */ spiped-1.4.1/libcperciva/alg/000755 001751 001751 00000000000 12403117256 017464 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/cpusupport/000755 001751 001751 00000000000 12403117256 021145 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/events/000755 001751 001751 00000000000 12403117256 020225 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/network/000755 001751 001751 00000000000 12403117256 020412 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/util/000755 001751 001751 00000000000 12403117256 017676 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/datastruct/000755 001751 001751 00000000000 12403117256 021077 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/crypto/000755 001751 001751 00000000000 12403117256 020241 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/crypto/crypto_verify_bytes.h000644 001751 001751 00000000632 12403117256 024525 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_VERIFY_BYTES_H_ #define _CRYPTO_VERIFY_BYTES_H_ #include #include /** * crypto_verify_bytes(buf0, buf1, len): * Return zero if and only if buf0[0 .. len - 1] and buf1[0 .. len - 1] are * identical. Do not leak any information via timing side channels. */ uint8_t crypto_verify_bytes(const uint8_t *, const uint8_t *, size_t); #endif /* !_CRYPTO_VERIFY_BYTES_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_dh.h000644 001751 001751 00000002713 12403117256 022410 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_DH_H_ #define _CRYPTO_DH_H_ #include /* Sizes of Diffie-Hellman private, public, and exchanged keys. */ #define CRYPTO_DH_PRIVLEN 32 #define CRYPTO_DH_PUBLEN 256 #define CRYPTO_DH_KEYLEN 256 /** * crypto_dh_generate_pub(pub, priv): * Compute ${pub} equal to 2^(2^258 + ${priv}) in Diffie-Hellman group #14. */ int crypto_dh_generate_pub(uint8_t[CRYPTO_DH_PUBLEN], const uint8_t[CRYPTO_DH_PRIVLEN]); /** * crypto_dh_generate(pub, priv): * Generate a 256-bit private key ${priv}, and compute ${pub} equal to * 2^(2^258 + ${priv}) mod p where p is the Diffie-Hellman group #14 modulus. * Both values are stored as big-endian integers. */ int crypto_dh_generate(uint8_t[CRYPTO_DH_PUBLEN], uint8_t[CRYPTO_DH_PRIVLEN]); /** * 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 * made by the *other* participant in the key exchange. */ int crypto_dh_compute(const uint8_t[CRYPTO_DH_PUBLEN], const uint8_t[CRYPTO_DH_PRIVLEN], uint8_t[CRYPTO_DH_KEYLEN]); /** * crypto_dh_sanitycheck(pub): * Sanity-check the Diffie-Hellman public value ${pub} by checking that it * is less than the group #14 modulus. Return 0 if sane, -1 if insane. */ int crypto_dh_sanitycheck(const uint8_t[CRYPTO_DH_PUBLEN]); #endif /* !_CRYPTO_DH_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_entropy.c000644 001751 001751 00000011353 12403117256 023510 0ustar00cpercivacperciva000000 000000 #include #include #include #include "entropy.h" #include "insecure_memzero.h" #include "sha256.h" #include "crypto_entropy.h" /** * This system implements the HMAC_DRBG pseudo-random number generator as * specified in section 10.1.2 of the NIST SP 800-90 standard. In this * implementation, the optional personalization_string and additional_input * specified in the standard are not implemented. */ /* Internal HMAC_DRBG state. */ static struct { uint8_t Key[32]; uint8_t V[32]; uint32_t reseed_counter; } drbg; /* Set to non-zero once the PRNG has been instantiated. */ static int instantiated = 0; /* Could be as high as 2^48 if we wanted... */ #define RESEED_INTERVAL 256 /* Limited to 2^16 by specification. */ #define GENERATE_MAXLEN 65536 static int instantiate(void); static void update(uint8_t *, size_t); static int reseed(void); static void generate(uint8_t *, size_t); /** * instantiate(void): * Initialize the DRBG state. (Section 10.1.2.3) */ static int instantiate(void) { uint8_t seed_material[48]; /* Obtain random seed_material = (entropy_input || nonce). */ if (entropy_read(seed_material, 48)) return (-1); /* Initialize Key, V, and reseed_counter. */ memset(drbg.Key, 0x00, 32); memset(drbg.V, 0x01, 32); drbg.reseed_counter = 1; /* Mix the random seed into the state. */ update(seed_material, 48); /* Clean the stack. */ insecure_memzero(seed_material, 48); /* Success! */ return (0); } /** * update(data, datalen): * Update the DRBG state using the provided data. (Section 10.1.2.2) */ static void update(uint8_t * data, size_t datalen) { HMAC_SHA256_CTX ctx; uint8_t K[32]; uint8_t Vx[33]; /* Load (Key, V) into (K, Vx). */ memcpy(K, drbg.Key, 32); memcpy(Vx, drbg.V, 32); /* K <- HMAC(K, V || 0x00 || data). */ Vx[32] = 0x00; HMAC_SHA256_Init(&ctx, K, 32); HMAC_SHA256_Update(&ctx, Vx, 33); HMAC_SHA256_Update(&ctx, data, datalen); HMAC_SHA256_Final(K, &ctx); /* V <- HMAC(K, V). */ HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); /* If the provided data is non-Null, perform another mixing stage. */ if (datalen != 0) { /* K <- HMAC(K, V || 0x01 || data). */ Vx[32] = 0x01; HMAC_SHA256_Init(&ctx, K, 32); HMAC_SHA256_Update(&ctx, Vx, 33); HMAC_SHA256_Update(&ctx, data, datalen); HMAC_SHA256_Final(K, &ctx); /* V <- HMAC(K, V). */ HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); } /* Copy (K, Vx) back to (Key, V). */ memcpy(drbg.Key, K, 32); memcpy(drbg.V, Vx, 32); /* Clean the stack. */ insecure_memzero(K, 32); insecure_memzero(Vx, 33); } /** * reseed(void): * Reseed the DRBG state (mix in new entropy). (Section 10.1.2.4) */ static int reseed(void) { uint8_t seed_material[32]; /* Obtain random seed_material = entropy_input. */ if (entropy_read(seed_material, 32)) return (-1); /* Mix the random seed into the state. */ update(seed_material, 32); /* Reset the reseed_counter. */ drbg.reseed_counter = 1; /* Clean the stack. */ insecure_memzero(seed_material, 32); /* Success! */ return (0); } /** * generate(buf, buflen): * Fill the provided buffer with random bits, assuming that reseed_counter * is less than RESEED_INTERVAL (the caller is responsible for calling * reseed() as needed) and ${buflen} is less than 2^16 (the caller is * responsible for splitting up larger requests). (Section 10.1.2.5) */ static void generate(uint8_t * buf, size_t buflen) { size_t bufpos; assert(buflen <= GENERATE_MAXLEN); assert(drbg.reseed_counter <= RESEED_INTERVAL); /* Iterate until we've filled the buffer. */ for (bufpos = 0; bufpos < buflen; bufpos += 32) { HMAC_SHA256_Buf(drbg.Key, 32, drbg.V, 32, drbg.V); if (buflen - bufpos >= 32) memcpy(&buf[bufpos], drbg.V, 32); else memcpy(&buf[bufpos], drbg.V, buflen - bufpos); } /* Mix up state. */ update(NULL, 0); /* We're one data-generation step closer to needing a reseed. */ drbg.reseed_counter += 1; } /** * crypto_entropy_read(buf, buflen): * Fill the buffer with unpredictable bits. */ int crypto_entropy_read(uint8_t * buf, size_t buflen) { size_t bytes_to_provide; /* Instantiate if needed. */ if (instantiated == 0) { /* Try to instantiate the PRNG. */ if (instantiate()) return (-1); /* We have instantiated the PRNG. */ instantiated = 1; } /* Loop until we've filled the buffer. */ while (buflen > 0) { /* Do we need to reseed? */ if (drbg.reseed_counter > RESEED_INTERVAL) { if (reseed()) return (-1); } /* How much data are we generating in this step? */ if (buflen > GENERATE_MAXLEN) bytes_to_provide = GENERATE_MAXLEN; else bytes_to_provide = buflen; /* Generate bytes. */ generate(buf, bytes_to_provide); /* We've done part of the buffer. */ buf += bytes_to_provide; buflen -= bytes_to_provide; } /* Success! */ return (0); } spiped-1.4.1/libcperciva/crypto/crypto_aesctr.c000644 001751 001751 00000005435 12403117256 023275 0ustar00cpercivacperciva000000 000000 #include #include #include "crypto_aes.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]; }; /** * 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. */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce) { struct crypto_aesctr * stream; /* Allocate memory. */ if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) goto err0; /* Initialize values. */ stream->key = key; stream->nonce = nonce; stream->bytectr = 0; /* Success! */ return (stream); err0: /* Failure! */ return (NULL); } /** * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR 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_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]; /* Move to the next byte of cipherstream. */ stream->bytectr += 1; } } /** * crypto_aesctr_free(stream): * Free the provided stream object. */ void crypto_aesctr_free(struct crypto_aesctr * stream) { int i; /* Be compatible with free(NULL). */ if (stream == NULL) return; /* Zero potentially sensitive information. */ for (i = 0; i < 16; i++) stream->buf[i] = 0; stream->bytectr = stream->nonce = 0; /* Free the stream. */ free(stream); } /** * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): * Equivalent to init(key, nonce); stream(inbuf, outbuf, buflen); free. */ void crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { struct crypto_aesctr stream_rec; struct crypto_aesctr * stream = &stream_rec; int i; /* Initialize values. */ stream->key = key; stream->nonce = nonce; stream->bytectr = 0; /* Perform the encryption. */ crypto_aesctr_stream(stream, inbuf, outbuf, buflen); /* Zero potentially sensitive information. */ for (i = 0; i < 16; i++) stream->buf[i] = 0; stream->bytectr = stream->nonce = 0; } spiped-1.4.1/libcperciva/crypto/crypto_dh_group14.h000644 001751 001751 00000000312 12403117256 023762 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_DH_GROUP14_H_ #define _CRYPTO_DH_GROUP14_H_ #include /* Diffie-Hellman group #14, from RFC 3526. */ extern uint8_t crypto_dh_group14[]; #endif /* !_CRYPTO_DH_GROUP14_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_entropy.h000644 001751 001751 00000000467 12403117256 023521 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_ENTROPY_H_ #define _CRYPTO_ENTROPY_H_ #include #include /** * crypto_entropy_read(buf, buflen): * Fill the buffer with unpredictable bits. The value ${buflen} must be * less than 2^16. */ int crypto_entropy_read(uint8_t *, size_t); #endif /* !_CRYPTO_ENTROPY_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_aesctr.h000644 001751 001751 00000002272 12403117256 023276 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_AESCTR_H_ #define _CRYPTO_AESCTR_H_ #include #include /* Opaque type. */ struct crypto_aes_key; /** * 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. */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key *, uint64_t); /** * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR 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_stream(struct crypto_aesctr *, const uint8_t *, uint8_t *, size_t); /** * crypto_aesctr_free(stream): * Free the provided stream object. */ void crypto_aesctr_free(struct crypto_aesctr *); /** * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): * Equivalent to init(key, nonce); stream(inbuf, outbuf, buflen); free. */ void crypto_aesctr_buf(const struct crypto_aes_key *, uint64_t, const uint8_t *, uint8_t *, size_t); #endif /* !_CRYPTO_AESCTR_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_aes_aesni.c000644 001751 001751 00000016552 12403117256 023745 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_AESNI #include #include #include #include #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes_aesni.h" /* Expanded-key structure. */ struct crypto_aes_key_aesni { __m128i rkeys[15]; size_t nr; }; /* Compute an AES-128 round key. */ #define MKRKEY128(rkeys, i, rcon) do { \ __m128i _s = rkeys[i - 1]; \ __m128i _t = rkeys[i - 1]; \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \ _t = _mm_aeskeygenassist_si128(_t, rcon); \ _t = _mm_shuffle_epi32(_t, 0xff); \ rkeys[i] = _mm_xor_si128(_s, _t); \ } while (0) /** * crypto_aes_key_expand_128_aesni(key, rkeys): * Expand the 128-bit AES key ${key} into the 11 round keys ${rkeys}. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ static void crypto_aes_key_expand_128_aesni(const uint8_t key[16], __m128i rkeys[11]) { /* 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 * bug: The cast to (const __m128i *) is invalid since it increases * the alignment requirement of the pointer. Alas, until compilers * get fixed intrinsics, all we can do is code the bug and require * that alignment-requirement-increasing compiler warnings get * disabled. */ rkeys[0] = _mm_loadu_si128((const __m128i *)&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. Unfortunately, 'rcon' * is encoded as an immediate value, so we need to write the loop out * ourselves rather than allowing the compiler to expand it. */ 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, shuffle, rcon) do { \ __m128i _s = rkeys[i - 2]; \ __m128i _t = rkeys[i - 1]; \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \ _t = _mm_aeskeygenassist_si128(_t, rcon); \ _t = _mm_shuffle_epi32(_t, shuffle); \ rkeys[i] = _mm_xor_si128(_s, _t); \ } while (0) /** * crypto_aes_key_expand_256_aesni(key, rkeys): * Expand the 256-bit AES key ${key} into the 15 round keys ${rkeys}. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ static void crypto_aes_key_expand_256_aesni(const uint8_t key[32], __m128i rkeys[15]) { /* 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 * bug: The cast to (const __m128i *) is invalid since it increases * the alignment requirement of the pointer. Alas, until compilers * get fixed intrinsics, all we can do is code the bug and require * that alignment-requirement-increasing compiler warnings get * disabled. */ rkeys[0] = _mm_loadu_si128((const __m128i *)&key[0]); rkeys[1] = _mm_loadu_si128((const __m128i *)&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 aeskeygenassist instruction computes * both, and we use 0xff or 0xaa to select the one we need. The rcon * value used is irrelevant for odd rounds since we ignore the value * which it feeds into. Unfortunately, the 'shuffle' and 'rcon' * values are encoded into the instructions as immediates, so we need * to write the loop out ourselves rather than allowing the compiler * to expand it. */ MKRKEY256(rkeys, 2, 0xff, 0x01); MKRKEY256(rkeys, 3, 0xaa, 0x00); MKRKEY256(rkeys, 4, 0xff, 0x02); MKRKEY256(rkeys, 5, 0xaa, 0x00); MKRKEY256(rkeys, 6, 0xff, 0x04); MKRKEY256(rkeys, 7, 0xaa, 0x00); MKRKEY256(rkeys, 8, 0xff, 0x08); MKRKEY256(rkeys, 9, 0xaa, 0x00); MKRKEY256(rkeys, 10, 0xff, 0x10); MKRKEY256(rkeys, 11, 0xaa, 0x00); MKRKEY256(rkeys, 12, 0xff, 0x20); MKRKEY256(rkeys, 13, 0xaa, 0x00); MKRKEY256(rkeys, 14, 0xff, 0x40); } /** * 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 * 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_key_expand_aesni(const uint8_t * key, size_t len) { struct crypto_aes_key_aesni * kexp; /* Allocate structure. */ if ((kexp = malloc(sizeof(struct crypto_aes_key_aesni))) == NULL) goto err0; /* Compute round keys. */ if (len == 16) { kexp->nr = 10; crypto_aes_key_expand_128_aesni(key, kexp->rkeys); } else if (len == 32) { kexp->nr = 14; crypto_aes_key_expand_256_aesni(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_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. */ void crypto_aes_encrypt_block_aesni(const uint8_t * in, uint8_t * out, const void * key) { const struct crypto_aes_key_aesni * _key = key; const __m128i * aes_key = _key->rkeys; __m128i aes_state; 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]); aes_state = _mm_aesenc_si128(aes_state, aes_key[3]); aes_state = _mm_aesenc_si128(aes_state, aes_key[4]); aes_state = _mm_aesenc_si128(aes_state, aes_key[5]); aes_state = _mm_aesenc_si128(aes_state, aes_key[6]); aes_state = _mm_aesenc_si128(aes_state, aes_key[7]); aes_state = _mm_aesenc_si128(aes_state, aes_key[8]); aes_state = _mm_aesenc_si128(aes_state, aes_key[9]); 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_aesenclast_si128(aes_state, aes_key[nr]); _mm_storeu_si128((__m128i *)out, aes_state); } /** * crypto_aes_key_free_aesni(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_aesni(void * key) { /* Attempt to zero the expanded key. */ insecure_memzero(key, sizeof(struct crypto_aes_key_aesni)); /* Free the key. */ free(key); } #endif /* CPUSUPPORT_X86_AESNI */ spiped-1.4.1/libcperciva/crypto/crypto_aes.c000644 001751 001751 00000007157 12403117256 022567 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "cpusupport.h" #include "crypto_aes_aesni.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes.h" /** * 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, * it's just an opaque pointer; but declaring it as a named structure type * prevents type-mismatch bugs in upstream code. */ struct crypto_aes_key; #ifdef CPUSUPPORT_X86_AESNI /* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */ static int aesnitest(uint8_t ptext[16], uint8_t * key, size_t keylen) { AES_KEY kexp_openssl; void * kexp_aesni; uint8_t ctext_openssl[16]; uint8_t ctext_aesni[16]; /* Expand the key. */ AES_set_encrypt_key(key, keylen * 8, &kexp_openssl); if ((kexp_aesni = crypto_aes_key_expand_aesni(key, keylen)) == NULL) goto err0; /* Encrypt the block. */ AES_encrypt(ptext, ctext_openssl, &kexp_openssl); crypto_aes_encrypt_block_aesni(ptext, ctext_aesni, kexp_aesni); /* Free the AESNI expanded key. */ crypto_aes_key_free_aesni(kexp_aesni); /* Do the outputs match? */ return (memcmp(ctext_openssl, ctext_aesni, 16)); err0: /* Failure! */ return (-1); } /* Should we use AESNI? */ static int useaesni(void) { static int aesnigood = -1; uint8_t key[32]; uint8_t ptext[16]; size_t i; /* 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; for (i = 0; i < 32; i++) key[i] = i; /* 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; } /* AESNI works; use it. */ aesnigood = 1; } return (aesnigood); } #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. */ struct crypto_aes_key * crypto_aes_key_expand(const uint8_t * key, size_t len) { AES_KEY * kexp; /* Sanity-check. */ assert((len == 16) || (len == 32)); #ifdef CPUSUPPORT_X86_AESNI /* Use AESNI if we can. */ if (useaesni()) return (crypto_aes_key_expand_aesni(key, len)); #endif /* Allocate structure. */ if ((kexp = malloc(sizeof(AES_KEY))) == NULL) goto err0; /* Expand the key. */ AES_set_encrypt_key(key, len * 8, kexp); /* Success! */ return ((void *)kexp); err0: /* Failure! */ return (NULL); } /** * crypto_aes_encrypt_block(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. */ void crypto_aes_encrypt_block(const uint8_t * in, uint8_t * out, const struct crypto_aes_key * key) { #ifdef CPUSUPPORT_X86_AESNI if (useaesni()) { crypto_aes_encrypt_block_aesni(in, out, (const void *)key); return; } #endif /* Get AES to do the work. */ AES_encrypt(in, out, (const void *)key); } /** * crypto_aes_key_free(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free(struct crypto_aes_key * key) { #ifdef CPUSUPPORT_X86_AESNI if (useaesni()) { crypto_aes_key_free_aesni((void *)key); return; } #endif /* Attempt to zero the expanded key. */ insecure_memzero(key, sizeof(AES_KEY)); /* Free the key. */ free(key); } spiped-1.4.1/libcperciva/crypto/crypto_verify_bytes.c000644 001751 001751 00000000715 12403117256 024522 0ustar00cpercivacperciva000000 000000 #include #include #include "crypto_verify_bytes.h" /** * crypto_verify_bytes(buf0, buf1, len): * Return zero if and only if buf0[0 .. len - 1] and buf1[0 .. len - 1] are * identical. Do not leak any information via timing side channels. */ uint8_t crypto_verify_bytes(const uint8_t * buf0, const uint8_t * buf1, size_t len) { uint8_t rc = 0; size_t i; for (i = 0; i < len; i++) rc = rc | (buf0[i] ^ buf1[i]); return (rc); } spiped-1.4.1/libcperciva/crypto/crypto_dh.c000644 001751 001751 00000015461 12403117256 022407 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "warnp.h" #include "crypto_entropy.h" #include "crypto_dh_group14.h" #include "crypto_dh.h" static int blinded_modexp(uint8_t r[CRYPTO_DH_PUBLEN], BIGNUM * a, const uint8_t priv[CRYPTO_DH_PRIVLEN]); /* Big-endian representation of 2^256. */ static uint8_t two_exp_256[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /** * blinded_modexp(r, a, priv): * Compute ${r} = ${a}^(2^258 + ${priv}), where ${r} and ${priv} are treated * as big-endian integers; and avoid leaking timing data in this process. */ static int blinded_modexp(uint8_t r[CRYPTO_DH_PUBLEN], BIGNUM * a, const uint8_t priv[CRYPTO_DH_PRIVLEN]) { BIGNUM * two_exp_256_bn; BIGNUM * priv_bn; uint8_t blinding[CRYPTO_DH_PRIVLEN]; BIGNUM * blinding_bn; BIGNUM * priv_blinded; BIGNUM * m_bn; BN_CTX * ctx; BIGNUM * r1; BIGNUM * r2; size_t rlen; /* Construct 2^256 in BN representation. */ if ((two_exp_256_bn = BN_bin2bn(two_exp_256, 33, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } /* Construct 2^258 + ${priv} in BN representation. */ if ((priv_bn = BN_bin2bn(priv, CRYPTO_DH_PRIVLEN, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err1; } if ((!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn)) || (!BN_add(priv_bn, priv_bn, two_exp_256_bn))) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err2; } /* Generate blinding exponent. */ if (crypto_entropy_read(blinding, CRYPTO_DH_PRIVLEN)) goto err2; if ((blinding_bn = BN_bin2bn(blinding, CRYPTO_DH_PRIVLEN, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err2; } if (!BN_add(blinding_bn, blinding_bn, two_exp_256_bn)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err3; } /* Generate blinded exponent. */ if ((priv_blinded = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err3; } if (!BN_sub(priv_blinded, priv_bn, blinding_bn)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err4; } /* Construct group #14 modulus in BN representation. */ if ((m_bn = BN_bin2bn(crypto_dh_group14, 256, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err4; } /* Allocate BN context. */ if ((ctx = BN_CTX_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err5; } /* Allocate space for storing results of exponentiations. */ if ((r1 = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err6; } if ((r2 = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err7; } /* Perform modular exponentiations. */ if (!BN_mod_exp(r1, a, blinding_bn, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } if (!BN_mod_exp(r2, a, priv_blinded, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } /* Compute final result and export to big-endian integer format. */ if (!BN_mod_mul(r1, r1, r2, m_bn, ctx)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err8; } rlen = BN_num_bytes(r1); if (rlen > CRYPTO_DH_PUBLEN) { warn0("Exponent result too large!"); goto err8; } memset(r, 0, CRYPTO_DH_PUBLEN - rlen); BN_bn2bin(r1, r + CRYPTO_DH_PUBLEN - rlen); /* Free space allocated by BN_new. */ BN_clear_free(r2); BN_clear_free(r1); /* Free context allocated by BN_CTX_new. */ BN_CTX_free(ctx); /* Free space allocated by BN_bin2bn. */ BN_free(m_bn); /* Free space allocated by BN_new. */ BN_clear_free(priv_blinded); /* Free space allocated by BN_bin2bn. */ BN_clear_free(blinding_bn); BN_clear_free(priv_bn); BN_free(two_exp_256_bn); /* Success! */ return (0); err8: BN_clear_free(r2); err7: BN_clear_free(r1); err6: BN_CTX_free(ctx); err5: BN_free(m_bn); err4: BN_clear_free(priv_blinded); err3: BN_clear_free(blinding_bn); err2: BN_clear_free(priv_bn); err1: BN_free(two_exp_256_bn); err0: /* Failure! */ return (-1); } /** * crypto_dh_generate_pub(pub, priv): * Compute ${pub} equal to 2^(2^258 + ${priv}) in Diffie-Hellman group #14. */ int crypto_dh_generate_pub(uint8_t pub[CRYPTO_DH_PUBLEN], const uint8_t priv[CRYPTO_DH_PRIVLEN]) { BIGNUM * two; /* Generate BN representation for 2. */ if ((two = BN_new()) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } if (!BN_set_word(two, 2)) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err1; } /* Compute pub = two^(2^258 + priv). */ if (blinded_modexp(pub, two, priv)) goto err1; /* Free storage allocated by BN_new. */ BN_free(two); /* Success! */ return (0); err1: BN_free(two); err0: /* Failure! */ return (-1); } /** * crypto_dh_generate(pub, priv): * Generate a 256-bit private key ${priv}, and compute ${pub} equal to * 2^(2^258 + ${priv}) mod p where p is the Diffie-Hellman group #14 modulus. * Both values are stored as big-endian integers. */ int crypto_dh_generate(uint8_t pub[CRYPTO_DH_PUBLEN], uint8_t priv[CRYPTO_DH_PRIVLEN]) { /* Generate a random private key. */ if (crypto_entropy_read(priv, CRYPTO_DH_PRIVLEN)) goto err0; /* Compute the public key. */ if (crypto_dh_generate_pub(pub, priv)) goto err0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * 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 * made by the *other* participant in the key exchange. */ int crypto_dh_compute(const uint8_t pub[CRYPTO_DH_PUBLEN], const uint8_t priv[CRYPTO_DH_PRIVLEN], uint8_t key[CRYPTO_DH_KEYLEN]) { BIGNUM * a; /* Convert ${pub} into BN representation. */ if ((a = BN_bin2bn(pub, CRYPTO_DH_PUBLEN, NULL)) == NULL) { warn0("%s", ERR_error_string(ERR_get_error(), NULL)); goto err0; } /* Compute key = pub^(2^258 + priv). */ if (blinded_modexp(key, a, priv)) goto err1; /* Free storage allocated by BN_bin2bn. */ BN_free(a); /* Success! */ return (0); err1: BN_free(a); err0: /* Failure! */ return (-1); } /** * crypto_dh_sanitycheck(pub): * Sanity-check the Diffie-Hellman public value ${pub} by checking that it * is less than the group #14 modulus. Return 0 if sane, -1 if insane. */ int crypto_dh_sanitycheck(const uint8_t pub[CRYPTO_DH_PUBLEN]) { if (memcmp(pub, crypto_dh_group14, 256) >= 0) return (-1); /* Value is sane. */ return (0); } spiped-1.4.1/libcperciva/crypto/crypto_aes_aesni.h000644 001751 001751 00000002070 12403117256 023740 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_AES_AESNI_H_ #define _CRYPTO_AES_AESNI_H_ #include #include /** * 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 * 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_key_expand_aesni(const uint8_t *, size_t); /** * 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. */ void crypto_aes_encrypt_block_aesni(const uint8_t *, uint8_t *, const void *); /** * crypto_aes_key_free_aesni(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_aesni(void *); #endif /* !_CRYPTO_AES_AESNI_H_ */ spiped-1.4.1/libcperciva/crypto/crypto_dh_group14.c000644 001751 001751 00000003745 12403117256 023772 0ustar00cpercivacperciva000000 000000 #include #include "crypto_dh_group14.h" /** * This is the big-endian representation of * p = 2^2048 - 2^1984 + 2^64 * floor(2^1918 pi + 124476) - 1 * where the value 124476 is chosen to be the least positive integer such * that both p and (p - 1)/2 are prime. Diffie-Hellman operations are done * in the group of quadratic residues modulo p, and the integer 2 is a * generator of this group. */ 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, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed, 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d, 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36, 0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f, 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56, 0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d, 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b, 0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2, 0xec, 0x07, 0xa2, 0x8f, 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9, 0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7c, 0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10, 0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xac, 0xaa, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; spiped-1.4.1/libcperciva/crypto/crypto_aes.h000644 001751 001751 00000001445 12403117256 022566 0ustar00cpercivacperciva000000 000000 #ifndef _CRYPTO_AES_H_ #define _CRYPTO_AES_H_ #include #include /* Opaque structure. */ struct crypto_aes_key; /** * 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. */ 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}. */ void crypto_aes_encrypt_block(const uint8_t *, uint8_t *, const struct crypto_aes_key *); /** * crypto_aes_key_free(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free(struct crypto_aes_key *); #endif /* !_CRYPTO_AES_H_ */ spiped-1.4.1/libcperciva/datastruct/elasticarray.c000644 001751 001751 00000013332 12403117256 023730 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "elasticarray.h" struct elasticarray { size_t size; size_t alloc; void * buf; }; /** * resize(EA, nsize): * Resize the virtual buffer for ${EA} to length ${nsize} bytes. The actual * buffer may or may not need to be resized. On failure, the buffer will be * unmodified. */ static int resize(struct elasticarray * EA, size_t nsize) { size_t nalloc; void * nbuf; /* Figure out how large an allocation we want. */ if (EA->alloc < nsize) { /* We need to enlarge the buffer. */ nalloc = EA->alloc * 2; if (nalloc < nsize) nalloc = nsize; } else if (EA->alloc > nsize * 4) { /* We need to shrink the buffer. */ nalloc = nsize * 2; } else { nalloc = EA->alloc; } /* Reallocate if necessary. */ if (nalloc != EA->alloc) { nbuf = realloc(EA->buf, nalloc); if ((nbuf == NULL) && (nalloc > 0)) goto err0; EA->buf = nbuf; EA->alloc = nalloc; } /* Record the new array size. */ EA->size = nsize; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_init(nrec, reclen): * Create and return an elastic array holding ${nrec} (uninitialized) records * of length ${reclen}. Takes O(nrec * reclen) time. */ struct elasticarray * elasticarray_init(size_t nrec, size_t reclen) { struct elasticarray * EA; /* Allocate structure. */ if ((EA = malloc(sizeof(struct elasticarray))) == NULL) goto err0; /* The array is empty for now. */ EA->size = EA->alloc = 0; EA->buf = NULL; /* Reallocate to the requested length. */ if (elasticarray_resize(EA, nrec, reclen)) goto err1; /* Success! */ return (EA); err1: elasticarray_free(EA); err0: /* Failure! */ return (NULL); } /** * elasticarray_resize(EA, nrec, reclen): * Resize the elastic array pointed to by ${EA} to hold ${nrec} records of * length ${reclen}. If ${nrec} exceeds the number of records previously * held by the array, the additional records will be uninitialized. Takes * O(nrec * reclen) time. */ int elasticarray_resize(struct elasticarray * EA, size_t nrec, size_t reclen) { /* Check for overflow. */ if (nrec > SIZE_MAX / reclen) { errno = ENOMEM; goto err0; } /* Resize the buffer. */ if (resize(EA, nrec * reclen)) goto err0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_getsize(EA, reclen): * Return the number of length-${reclen} records in the array, rounding down * if there is a partial record (which can only occur if elasticarray_* * functions have been called with different values of reclen). */ size_t elasticarray_getsize(struct elasticarray * EA, size_t reclen) { return (EA->size / reclen); } /** * elasticarray_append(EA, buf, nrec, reclen): * Append to the elastic array ${EA} the ${nrec} records of length ${reclen} * stored in ${buf}. Takes O(nrec * reclen) amortized time. */ int elasticarray_append(struct elasticarray * EA, const void * buf, size_t nrec, size_t reclen) { size_t bufpos = EA->size; /* Check for overflow. */ if ((nrec > SIZE_MAX / reclen) || (nrec * reclen > SIZE_MAX - EA->size)) { errno = ENOMEM; goto err0; } /* Resize the buffer. */ if (resize(EA, EA->size + nrec * reclen)) goto err0; /* Copy bytes in. */ memcpy((uint8_t *)(EA->buf) + bufpos, buf, nrec * reclen); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_shrink(EA, nrec, reclen): * Delete the final ${nrec} records of length ${reclen} from the elastic * array ${EA}. If there are fewer than ${nrec} records, all records * present will be deleted. * * As an exception to the normal rule, an elastic array may occupy more than * 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 * EA, size_t nrec, size_t reclen) { size_t nsize; /* Figure out how much to keep. */ if ((nrec > SIZE_MAX / reclen) || (nrec * reclen > EA->size)) nsize = 0; else nsize = EA->size - nrec * reclen; /* Resize the buffer... */ if (resize(EA, nsize)) { /* * ... and if we fail to reallocate, just record the new * length and continue using the old buffer. */ EA->size = nsize; } } /** * elasticarray_truncate(EA): * Release any spare space in the elastic array ${EA}. */ int elasticarray_truncate(struct elasticarray * EA) { void * nbuf; /* If there is spare space, reallocate. */ if (EA->alloc > EA->size) { nbuf = realloc(EA->buf, EA->size); if ((nbuf == NULL) && (EA->size > 0)) goto err0; EA->buf = nbuf; EA->alloc = EA->size; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_get(EA, pos, reclen): * Return a pointer to record number ${pos} of length ${reclen} in the * elastic array ${EA}. Takes O(1) time. */ void * elasticarray_get(struct elasticarray * EA, size_t pos, size_t reclen) { return ((uint8_t *)(EA->buf) + pos * reclen); } /** * elasticarray_free(EA): * Free the elastic array ${EA}. Takes O(1) time. */ void elasticarray_free(struct elasticarray * EA) { /* Be compatible with free(NULL). */ if (EA == NULL) return; free(EA->buf); free(EA); } /** * elasticarray_export(EA, buf, nrec, reclen): * Return the data in the elastic array ${EA} as a buffer ${buf} containing * ${nrec} records of length ${reclen}. Free the elastic array ${EA}. */ int elasticarray_export(struct elasticarray * EA, void ** buf, size_t * nrec, size_t reclen) { /* Remove any spare space. */ if (elasticarray_truncate(EA)) goto err0; /* Return the buffer and number of records. */ *buf = EA->buf; *nrec = elasticarray_getsize(EA, reclen); /* Success! */ return (0); err0: /* Failure! */ return (-1); } spiped-1.4.1/libcperciva/datastruct/ptrheap.c000644 001751 001751 00000020503 12403117256 022706 0ustar00cpercivacperciva000000 000000 #include #include "elasticarray.h" #include "ptrheap.h" ELASTICARRAY_DECL(PTRLIST, ptrlist, void *); struct ptrheap { int (* compar)(void *, const void *, const void *); void (* setreccookie)(void *, void *, size_t); void * cookie; PTRLIST elems; size_t nelems; }; /** * swap(elems, i, j, setreccookie, cookie): * Swap elements ${i} and ${j} in ${elems}. If ${setreccookie} is non-NULL, * invoke ${setreccookie}(${cookie}, elem, pos) for each of the elements and * their new positions in the tree. */ static void swap(PTRLIST elems, size_t i, size_t j, void (* setreccookie)(void *, void *, size_t), void * cookie) { void * tmp; /* Swap the elements. */ tmp = *ptrlist_get(elems, i); *ptrlist_get(elems, i) = *ptrlist_get(elems, j); *ptrlist_get(elems, j) = tmp; /* Notify about the moved elements. */ if (setreccookie != NULL) { setreccookie(cookie, *ptrlist_get(elems, i), i); setreccookie(cookie, *ptrlist_get(elems, j), j); } } /** * heapifyup(elems, i, compar, setreccookie, cookie): * Sift up element ${i} of the elements ${elems}, using the comparison * function ${compar} and the cookie ${cookie}. If elements move and * ${setreccookie} is non-NULL, use it to notify about the updated position * of elements in the heap. */ static void heapifyup(PTRLIST elems, size_t i, int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { /* Iterate up the tree. */ do { /* If we're at the root, we have nothing to do. */ if (i == 0) break; /* If this is >= its parent, we're done. */ if (compar(cookie, *ptrlist_get(elems, i), *ptrlist_get(elems, (i - 1) / 2)) >= 0) break; /* Swap with the parent. */ swap(elems, i, (i - 1) / 2, setreccookie, cookie); /* Move up the tree. */ i = (i - 1) / 2; } while (1); } /** * heapify(elems, i, N, compar, setreccookie, cookie): * Sift down element number ${i} out of ${N} of the elements ${elems}, using * the comparison function ${compar} and the cookie ${cookie}. If elements * move and ${setreccookie} is non-NULL, use it to notify about the updated * position of elements in the heap. */ static void heapify(PTRLIST elems, size_t i, size_t N, int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { size_t min; /* Iterate down the tree. */ do { /* Look for the minimum element out of {i, 2i+1, 2i+2}. */ min = i; /* Is this bigger than element 2i+1? */ if ((2 * i + 1 < N) && (compar(cookie, *ptrlist_get(elems, min), *ptrlist_get(elems, 2 * i + 1)) > 0)) min = 2 * i + 1; /* Is this bigger than element 2i+2? */ if ((2 * i + 2 < N) && (compar(cookie, *ptrlist_get(elems, min), *ptrlist_get(elems, 2 * i + 2)) > 0)) min = 2 * i + 2; /* If the minimum is i, we have heap-property. */ if (min == i) break; /* Move the minimum into position i. */ swap(elems, min, i, setreccookie, cookie); /* Move down the tree. */ i = min; } while (1); } /** * ptrheap_init(compar, setreccookie, cookie): * Create and return an empty heap. The function ${compar}(${cookie}, x, y) * should return less than, equal to, or greater than 0 depending on whether * x is less than, equal to, or greater than y; and if ${setreccookie} is * non-zero it will be called as ${setreccookie}(${cookie}, ${ptr}, ${rc}) to * indicate that the value ${rc} is the current record cookie for the pointer * ${ptr}. The function ${setreccookie} may not make any ptrheap_* calls. */ struct ptrheap * ptrheap_init(int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { /* Let ptrheap_create handle this. */ return (ptrheap_create(compar, setreccookie, cookie, 0, NULL)); } /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): * 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. */ struct ptrheap * ptrheap_create(int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie, size_t N, void ** ptrs) { struct ptrheap * H; size_t i; /* Allocate structure. */ if ((H = malloc(sizeof(struct ptrheap))) == NULL) goto err0; /* Store parameters. */ H->compar = compar; H->setreccookie = setreccookie; H->cookie = cookie; /* We will have N elements. */ H->nelems = N; /* Allocate space for N heap elements. */ if ((H->elems = ptrlist_init(N)) == NULL) goto err1; /* Copy the heap elements in. */ for (i = 0; i < N; i++) *ptrlist_get(H->elems, i) = ptrs[i]; /* Turn this into a heap. */ for (i = N - 1; i < N; i--) heapify(H->elems, i, N, H->compar, NULL, H->cookie); /* Advise the caller about the record cookies. */ if (H->setreccookie != NULL) for (i = 0; i < N; i++) (H->setreccookie)(H->cookie, *ptrlist_get(H->elems, i), i); /* Success! */ return (H); err1: free(H); err0: /* Failure! */ return (NULL); } /** * ptrheap_add(H, ptr): * Add the pointer ${ptr} to the heap ${H}. */ int ptrheap_add(struct ptrheap * H, void * ptr) { /* Add the element to the end of the heap. */ if (ptrlist_append(H->elems, &ptr, 1)) goto err0; H->nelems += 1; /* Advise the caller about the current location of this record. */ if (H->setreccookie != NULL) (H->setreccookie)(H->cookie, ptr, H->nelems - 1); /* Move the new element up in the tree if necessary. */ heapifyup(H->elems, H->nelems - 1, H->compar, H->setreccookie, H->cookie); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * ptrheap_getmin(H): * Return the minimum pointer in the heap ${H}. If the heap is empty, NULL * is returned. */ void * ptrheap_getmin(struct ptrheap * H) { /* If we have any elements, the minimum is in position 0. */ if (H->nelems) return (*ptrlist_get(H->elems, 0)); else return (NULL); } /** * ptrheap_delete(H, rc): * Delete from the heap ${H} the element ptr for which the function call * setreccookie(cookie, ptr, ${rc}) was most recently made. */ void ptrheap_delete(struct ptrheap * H, size_t rc) { /* * If the element we're deleting is not at the end of the heap, * replace it with the element which is currently at the end. */ if (rc != H->nelems - 1) { /* Move ptr from position H->nelems - 1 into position rc. */ *ptrlist_get(H->elems, rc) = *ptrlist_get(H->elems, H->nelems - 1); if (H->setreccookie != NULL) (H->setreccookie)(H->cookie, *ptrlist_get(H->elems, rc), rc); /* Is this too small to be in position ${rc}? */ if ((rc > 0) && (H->compar(H->cookie, *ptrlist_get(H->elems, rc), *ptrlist_get(H->elems, (rc - 1) / 2)) < 0)) { /* Swap with the parent, and keep moving up. */ swap(H->elems, rc, (rc - 1) / 2, H->setreccookie, H->cookie); heapifyup(H->elems, (rc - 1) / 2, H->compar, H->setreccookie, H->cookie); } else { /* Maybe we need to move it down instead? */ heapify(H->elems, rc, H->nelems, H->compar, H->setreccookie, H->cookie); } } /* * We've got everything we want to keep in positions 0 .. nelems - 2, * and we have heap-nature, so all we need to do is strip off the * final pointer. */ ptrlist_shrink(H->elems, 1); H->nelems--; } /** * ptrheap_deletemin(H): * Delete the minimum element in the heap ${H}. */ void ptrheap_deletemin(struct ptrheap * H) { /* Let ptrheap_delete handle this. */ ptrheap_delete(H, 0); } /** * ptrheap_increase(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has incrased. */ void ptrheap_increase(struct ptrheap * H, size_t rc) { /* Move the element down if necessary. */ heapify(H->elems, rc, H->nelems, H->compar, H->setreccookie, H->cookie); } /** * ptrheap_increasemin(H): * Adjust the heap ${H} to account for the fact that the (formerly) minimum * element has increased. */ void ptrheap_increasemin(struct ptrheap * H) { /* Move the element down if necessary. */ heapify(H->elems, 0, H->nelems, H->compar, H->setreccookie, H->cookie); } /** * ptrheap_free(H): * Free the pointer heap ${H}. */ void ptrheap_free(struct ptrheap * H) { /* Be compatible with free(NULL). */ if (H == NULL) return; ptrlist_free(H->elems); free(H); } spiped-1.4.1/libcperciva/datastruct/timerqueue.c000644 001751 001751 00000011352 12403117256 023432 0ustar00cpercivacperciva000000 000000 #include #include #include #include "ptrheap.h" #include "timerqueue.h" struct timerqueue { struct ptrheap * H; }; struct timerrec { struct timeval tv; size_t rc; void * ptr; }; /* Compare two timevals. */ static int tvcmp(const struct timeval * x, const struct timeval * y) { /* Does one have more seconds? */ if (x->tv_sec > y->tv_sec) return (1); if (x->tv_sec < y->tv_sec) return (-1); /* Does one have more microseconds? */ if (x->tv_usec > y->tv_usec) return (1); if (x->tv_usec < y->tv_usec) return (-1); /* They must be equal. */ return (0); } /* Record-comparison callback from ptrheap. */ static int compar(void * cookie, const void * x, const void * y) { const struct timerrec * _x = x; const struct timerrec * _y = y; (void)cookie; /* UNUSED */ return (tvcmp(&_x->tv, &_y->tv)); } /* Cookie-recording callback from ptrheap. */ static void setreccookie(void * cookie, void * ptr, size_t rc) { struct timerrec * rec = ptr; (void)cookie; /* UNUSED */ rec->rc = rc; } /** * timerqueue_init(void): * Create and return an empty timer priority queue. */ struct timerqueue * timerqueue_init(void) { struct timerqueue * Q; /* Allocate structure. */ if ((Q = malloc(sizeof(struct timerqueue))) == NULL) goto err0; /* Allocate heap. */ if ((Q->H = ptrheap_init(compar, setreccookie, Q)) == NULL) goto err1; /* Success! */ return (Q); err1: free(Q); err0: /* Failure! */ return (NULL); } /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Returns a cookie * which can be passed to timerqueue_delete or timerqueue_increase. */ void * timerqueue_add(struct timerqueue * Q, const struct timeval * tv, void * ptr) { struct timerrec * r; /* Allocate (timeval, ptr) pair record. */ if ((r = malloc(sizeof(struct timerrec))) == NULL) goto err0; /* Fill in values. */ memcpy(&r->tv, tv, sizeof(struct timeval)); r->ptr = ptr; /* * Add the record to the heap. The value r->rc will be filled in * by setreccookie which will be called by ptrheap_add. */ if (ptrheap_add(Q->H, r)) goto err1; /* Success! */ return (r); err1: free(r); err0: /* Failure! */ return (NULL); } /** * timerqueue_delete(Q, cookie): * Delete the (timeval, ptr) pair associated with the cookie ${cookie} from * the priority queue ${Q}. */ void timerqueue_delete(struct timerqueue * Q, void * cookie) { struct timerrec * r = cookie; /* Remove the record from the heap. */ ptrheap_delete(Q->H, r->rc); /* Free the record. */ free(r); } /** * timerqueue_increase(Q, cookie, tv): * Increase the timer associated with the cookie ${cookie} in the priority * queue ${Q} to ${tv}. */ void timerqueue_increase(struct timerqueue * Q, void * cookie, const struct timeval * tv) { struct timerrec * r = cookie; /* Adjust timer value. */ memcpy(&r->tv, tv, sizeof(struct timeval)); /* Inform the heap that the record value has increased. */ ptrheap_increase(Q->H, r->rc); } /** * timerqueue_getmin(Q): * Return a pointer to the least timeval in ${Q}, or NULL if the priority * queue is empty. The pointer will remain valid until the next call to a * timerqueue_* function. This function cannot fail. */ const struct timeval * timerqueue_getmin(struct timerqueue * Q) { struct timerrec * r; /* Get the minimum element from the heap. */ r = ptrheap_getmin(Q->H); /* If we have an element, return its timeval; otherwise, NULL. */ if (r != NULL) return (&r->tv); else return (NULL); } /** * timerqueue_getptr(Q, tv): * If the least timeval in ${Q} is less than or equal to ${tv}, return the * associated pointer and remove the pair from the priority queue. If not, * return NULL. */ void * timerqueue_getptr(struct timerqueue * Q, const struct timeval * tv) { struct timerrec * r; void * ptr; /* * Get the minimum element from the heap. Return NULL if the heap * has no minimum element (i.e., is empty). */ if ((r = ptrheap_getmin(Q->H)) == NULL) return (NULL); /* If the minimum timeval is greater than ${tv}, return NULL. */ if (tvcmp(&r->tv, tv) > 0) return (NULL); /* Remove this record from the heap. */ ptrheap_deletemin(Q->H); /* Extract its pointer. */ ptr = r->ptr; /* Free the record. */ free(r); /* * And finally return the pointer which was associated with the * (formerly) minimum timeval in the heap. */ return (ptr); } /** * timerqueue_free(Q): * Free the timer priority queue ${Q}. */ void timerqueue_free(struct timerqueue * Q) { struct timerrec * r; /* Extract elements from the heap and free them one by one. */ while ((r = ptrheap_getmin(Q->H)) != NULL) { free(r); ptrheap_deletemin(Q->H); } /* Free the heap. */ ptrheap_free(Q->H); /* Free the timer priority queue structure. */ free(Q); } spiped-1.4.1/libcperciva/datastruct/elasticarray.h000644 001751 001751 00000013302 12403117256 023732 0ustar00cpercivacperciva000000 000000 #ifndef _ELASTICARRAY_H_ #define _ELASTICARRAY_H_ #include /** * Elastic Arrays are dynamically resizing arrays which remain within a * factor of 4 of the optimal size for the data they contain and have (within * a constant factor) amortized optimal running time providing that all of * the allocated space is accessed at some point. Functions return NULL or * (int)(-1) on error and set errno; other return types indicate that failure * is not possible. On error, the array will be unmodified. * * The ELASTICARRAY_DECL(type, prefix, rectype) macro can be used to create a * more friendly interface, at the expense of restricting the array to only * holding a single data type. */ /* Opaque elastic array type. */ struct elasticarray; /** * elasticarray_init(nrec, reclen): * Create and return an elastic array holding ${nrec} (uninitialized) records * of length ${reclen}. Takes O(nrec * reclen) time. */ struct elasticarray * elasticarray_init(size_t, size_t); /** * elasticarray_resize(EA, nrec, reclen): * Resize the elastic array pointed to by ${EA} to hold ${nrec} records of * length ${reclen}. If ${nrec} exceeds the number of records previously * held by the array, the additional records will be uninitialized. Takes * O(nrec * reclen) time. */ int elasticarray_resize(struct elasticarray *, size_t, size_t); /** * elasticarray_getsize(EA, reclen): * Return the number of length-${reclen} records in the array, rounding down * if there is a partial record (which can only occur if elasticarray_* * functions have been called with different values of reclen). The value * ${reclen} must be positive. */ size_t elasticarray_getsize(struct elasticarray *, size_t); /** * elasticarray_append(EA, buf, nrec, reclen): * Append to the elastic array ${EA} the ${nrec} records of length ${reclen} * stored in ${buf}. Takes O(nrec * reclen) amortized time. */ int elasticarray_append(struct elasticarray *, const void *, size_t, size_t); /** * elasticarray_shrink(EA, nrec, reclen): * Delete the final ${nrec} records of length ${reclen} from the elastic * array ${EA}. If there are fewer than ${nrec} records, all records * present will be deleted. * * As an exception to the normal rule, an elastic array may occupy more than * 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); /** * elasticarray_truncate(EA): * Release any spare space in the elastic array ${EA}. */ int elasticarray_truncate(struct elasticarray *); /** * elasticarray_get(EA, pos, reclen): * Return a pointer to record number ${pos} of length ${reclen} in the * elastic array ${EA}. Takes O(1) time. */ void * elasticarray_get(struct elasticarray *, size_t, size_t); /** * elasticarray_free(EA): * Free the elastic array ${EA}. Takes O(1) time. */ void elasticarray_free(struct elasticarray *); /** * elasticarray_export(EA, buf, nrec, reclen): * Return the data in the elastic array ${EA} as a buffer ${buf} containing * ${nrec} records of length ${reclen}. Free the elastic array ${EA}. */ int elasticarray_export(struct elasticarray *, void **, size_t *, size_t); /** * ELASTICARRAY_DECL(type, prefix, rectype): * Declare the type ${type} and the following functions: * ${type} ${prefix}_init(size_t nrec); * int ${prefix}_resize(${type} EA, size_t nrec); * size_t ${prefix}_getsize(${type} EA); * int ${prefix}_append(${type} EA, const void * buf, size_t nrec); * void ${prefix}_shrink(${type} EA, size_t nrec); * int ${prefix}_truncate(${type} EA); * ${rectype} * ${prefix}_get(${type} EA, size_t pos); * void ${prefix}_free(${type} EA); */ #define ELASTICARRAY_DECL(type, prefix, rectype) \ static inline struct prefix##_struct * \ prefix##_init(size_t nrec) \ { \ struct elasticarray * EA; \ \ EA = elasticarray_init(nrec, sizeof(rectype)); \ return ((struct prefix##_struct *)EA); \ } \ static inline int \ prefix##_resize(struct prefix##_struct * EA, size_t nrec) \ { \ return (elasticarray_resize((struct elasticarray *)EA, \ nrec, sizeof(rectype))); \ } \ static inline size_t \ prefix##_getsize(struct prefix##_struct * EA) \ { \ return (elasticarray_getsize((struct elasticarray *)EA, \ sizeof(rectype))); \ } \ static inline int \ prefix##_append(struct prefix##_struct * EA, \ rectype const * buf, size_t nrec) \ { \ return (elasticarray_append((struct elasticarray *)EA, \ buf, nrec, sizeof(rectype))); \ } \ static inline void \ prefix##_shrink(struct prefix##_struct * EA, size_t nrec) \ { \ elasticarray_shrink((struct elasticarray *)EA, \ nrec, sizeof(rectype)); \ } \ static inline int \ prefix##_truncate(struct prefix##_struct * EA) \ { \ return (elasticarray_truncate( \ (struct elasticarray *)EA)); \ } \ static inline rectype * \ prefix##_get(struct prefix##_struct * EA, size_t pos) \ { \ rectype * rec; \ \ rec = elasticarray_get((struct elasticarray *)EA, \ pos, sizeof(rectype)); \ return (rec); \ } \ static inline void \ prefix##_free(struct prefix##_struct * EA) \ { \ elasticarray_free((struct elasticarray *)EA); \ } \ static inline int \ prefix##_export(struct prefix##_struct * EA, rectype ** buf, \ size_t * nrec) \ { \ return (elasticarray_export((struct elasticarray *)EA, \ (void **)buf, nrec, sizeof(rectype))); \ } \ typedef struct prefix##_struct * type #endif /* !_ELASTICARRAY_H_ */ spiped-1.4.1/libcperciva/datastruct/ptrheap.h000644 001751 001751 00000005732 12403117256 022722 0ustar00cpercivacperciva000000 000000 #ifndef _PTRHEAP_H_ #define _PTRHEAP_H_ #include /** * Pointer-heap data structure. Arbitrary pointers can be inserted and are * compared using a provided callback; the usual heapy getmin / increasemin / * deletemin algorithms are supported. To use two additional functions, * ptrheap_delete and ptrheap_increase, a setreccookie callback needs to be * provided. Both functions require a record cookie to identify the element * to increase or delete; each time a record's record cookie changes, the * setreccookie callback will be called. Functions return NULL or (int)(-1) * on error and set errno; other return types indicate that failure is not * possible. On error, the heap will be unmodified. */ /* Opaque pointer-heap type. */ struct ptrheap; /** * ptrheap_init(compar, setreccookie, cookie): * Create and return an empty heap. The function ${compar}(${cookie}, x, y) * should return less than, equal to, or greater than 0 depending on whether * x is less than, equal to, or greater than y; and if ${setreccookie} is * non-zero it will be called as ${setreccookie}(${cookie}, ${ptr}, ${rc}) to * indicate that the value ${rc} is the current record cookie for the pointer * ${ptr}. The function ${setreccookie} may not make any ptrheap_* calls. */ struct ptrheap * ptrheap_init(int (*)(void *, const void *, const void *), void (*)(void *, void *, size_t), void *); /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): * 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. */ struct ptrheap * ptrheap_create(int (*)(void *, const void *, const void *), void (*)(void *, void *, size_t), void *, size_t, void **); /** * ptrheap_add(H, ptr): * Add the pointer ${ptr} to the heap ${H}. */ int ptrheap_add(struct ptrheap *, void *); /** * ptrheap_getmin(H): * Return the minimum pointer in the heap ${H}. If the heap is empty, NULL * is returned. */ void * ptrheap_getmin(struct ptrheap *); /** * ptrheap_delete(H, rc): * Delete from the heap ${H} the element ptr for which the function call * setreccookie(cookie, ptr, ${rc}) was most recently made. */ void ptrheap_delete(struct ptrheap *, size_t); /** * ptrheap_deletemin(H): * Delete the minimum element in the heap ${H}. The heap must not be empty. */ void ptrheap_deletemin(struct ptrheap *); /** * ptrheap_increase(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has increased. */ void ptrheap_increase(struct ptrheap *, size_t); /** * ptrheap_increasemin(H): * Adjust the heap ${H} to account for the fact that the (formerly) minimum * element has increased. */ void ptrheap_increasemin(struct ptrheap *); /** * ptrheap_free(H): * Free the pointer heap ${H}. */ void ptrheap_free(struct ptrheap *); #endif /* !_PTRHEAP_H_ */ spiped-1.4.1/libcperciva/datastruct/timerqueue.h000644 001751 001751 00000003333 12403117256 023437 0ustar00cpercivacperciva000000 000000 #ifndef _TIMERQUEUE_H_ #define _TIMERQUEUE_H_ #include /* Timer priority queue. Contains (timeval, ptr) pairs. */ /* Opaque timer priority queue type. */ struct timerqueue; /** * timerqueue_init(void): * Create and return an empty timer priority queue. */ struct timerqueue * timerqueue_init(void); /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Returns a cookie * which can be passed to timerqueue_delete or timerqueue_increase. */ void * timerqueue_add(struct timerqueue *, const struct timeval *, void *); /** * timerqueue_delete(Q, cookie): * Delete the (timeval, ptr) pair associated with the cookie ${cookie} from * the priority queue ${Q}. */ void timerqueue_delete(struct timerqueue *, void *); /** * timerqueue_increase(Q, cookie, tv): * Increase the timer associated with the cookie ${cookie} in the priority * queue ${Q} to ${tv}. */ void timerqueue_increase(struct timerqueue *, void *, const struct timeval *); /** * timerqueue_getmin(Q): * Return a pointer to the least timeval in ${Q}, or NULL if the priority * queue is empty. The pointer will remain valid until the next call to a * timerqueue_* function. This function cannot fail. */ const struct timeval * timerqueue_getmin(struct timerqueue *); /** * timerqueue_getptr(Q, tv): * If the least timeval in ${Q} is less than or equal to ${tv}, return the * associated pointer and remove the pair from the priority queue. If not, * return NULL. This function cannot fail. */ void * timerqueue_getptr(struct timerqueue *, const struct timeval *); /** * timerqueue_free(Q): * Free the timer priority queue ${Q}. */ void timerqueue_free(struct timerqueue *); #endif /* !_TIMERQUEUE_H_ */ spiped-1.4.1/libcperciva/datastruct/mpool.h000644 001751 001751 00000004370 12403117256 022402 0ustar00cpercivacperciva000000 000000 #ifndef _MPOOL_H_ #define _MPOOL_H_ #include /** * Memory allocator cache. Memory allocations can be returned to the pool * and reused by a subsequent allocation without returning all the way to * free/malloc. In effect, this is an optimization for the case where we * know we will want another allocation of the same size soon, at the expense * of allowing the memory to be reused by some other code. */ /** * MPOOL(name, type, size): * Define the functions * * ${type} * mpool_${name}_malloc(void); * void mpool_${name}_free(${type} *); * * which allocate and free structures of type ${type}. Up to ${size} * such structures are kept cached after _free is called in order to * allow future _malloc calls to be rapidly serviced. * * Cached structures will be freed at program exit time in order to aid * in the detection of memory leaks. */ #define MPOOL(name, type, size) \ static struct mpool_##name##_struct { \ size_t stacklen; \ void * top; \ int atexit_set; \ } mpool_##name##_rec = {0, NULL, 0}; \ \ static void \ mpool_##name##_atexit(void) \ { \ void * top; \ \ while ((top = mpool_##name##_rec.top) != NULL) { \ mpool_##name##_rec.top = *(void **)top; \ free(top); \ } \ } \ \ static inline type * \ mpool_##name##_malloc(void) \ { \ type * p; \ \ if (mpool_##name##_rec.stacklen) { \ p = mpool_##name##_rec.top; \ mpool_##name##_rec.top = *(void **)p; \ mpool_##name##_rec.stacklen -= 1; \ } else { \ if (mpool_##name##_rec.atexit_set == 0) { \ atexit(mpool_##name##_atexit); \ mpool_##name##_rec.atexit_set = 1; \ } \ p = malloc((sizeof(type) > sizeof(void *)) ? \ sizeof(type) : sizeof(void *)); \ } \ \ return (p); \ } \ \ static inline void \ mpool_##name##_free(type * p) \ { \ \ if (p == NULL) \ return; \ \ if (mpool_##name##_rec.stacklen < size) { \ *(void **)p = mpool_##name##_rec.top; \ mpool_##name##_rec.top = p; \ mpool_##name##_rec.stacklen += 1; \ } else { \ free(p); \ } \ } \ \ struct mpool_##name##_dummy #endif /* !_MPOOL_H_ */ spiped-1.4.1/libcperciva/util/asprintf.h000644 001751 001751 00000000505 12403117256 021675 0ustar00cpercivacperciva000000 000000 #ifndef _ASPRINTF_H_ #define _ASPRINTF_H_ /* Avoid namespace collisions with BSD/GNU asprintf. */ #ifdef asprintf #undef asprintf #endif #define asprintf libcperciva_asprintf /** * asprintf(ret, format, ...): * Do asprintf(3) like GNU and BSD do. */ int asprintf(char **, const char *, ...); #endif /* !_ASPRINTF_H_ */ spiped-1.4.1/libcperciva/util/sock_util.c000644 001751 001751 00000014021 12403117256 022034 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include "asprintf.h" #include "sock.h" #include "sock_util.h" #include "sock_internal.h" /** * sock_addr_cmp(sa1, sa2): * Return non-zero iff the socket addresses ${sa1} and ${sa2} are different. */ int sock_addr_cmp(const struct sock_addr * sa1, const struct sock_addr * sa2) { /* Family, socket type, and name length must match. */ if ((sa1->ai_family != sa2->ai_family) || (sa1->ai_socktype != sa2->ai_socktype) || (sa1->namelen != sa2->namelen)) return (1); /* The required length of the sockaddr must match. */ if (memcmp(sa1->name, sa2->name, sa1->namelen) != 0) return (1); /* Everything matched. */ return (0); } /** * sock_addr_dup(sa): * Duplicate the provided socket address. */ struct sock_addr * sock_addr_dup(const struct sock_addr * sa) { struct sock_addr * sa2; /* Allocate a struct sock_addr and copy fields. */ if ((sa2 = malloc(sizeof(struct sock_addr))) == NULL) goto err0; sa2->ai_family = sa->ai_family; sa2->ai_socktype = sa->ai_socktype; sa2->namelen = sa->namelen; /* Allocate and copy the sockaddr. */ if ((sa2->name = malloc(sa2->namelen)) == NULL) goto err1; memcpy(sa2->name, sa->name, sa2->namelen); /* Success! */ return (sa2); err1: free(sa2); err0: /* Failure! */ return (NULL); } /** * sock_addr_duplist(sas): * Duplicate the provided list of socket addresses. */ struct sock_addr ** sock_addr_duplist(struct sock_addr * const * sas) { struct sock_addr ** sas2; size_t i; /* Count socket addresses. */ for (i = 0; sas[i] != NULL; i++) continue; /* Allocate the list to hold addresses plus a NULL terminator. */ if ((sas2 = malloc((i + 1) * sizeof(struct sock_addr *))) == NULL) goto err0; /* Duplicate addresses and NULL-terminate. */ for (i = 0; sas[i] != NULL; i++) { if ((sas2[i] = sock_addr_dup(sas[i])) == NULL) goto err1; } sas2[i] = NULL; /* Success! */ return (sas2); err1: /* * Regardless of how many addresses we managed to duplicate before * failing and being sent here, we have a valid socket address list, * since the erroring sock_addr_dup call NULL-terminated it for us; * so we can free it and its constituent addresses easily. */ sock_addr_freelist(sas2); err0: /* Failure! */ return (NULL); } /** * sock_addr_serialize(sa, buf, buflen): * Allocate a buffer and serialize the socket address ${sa} into it. Return * the buffer via ${buf} and its length via ${buflen}. The serialization is * machine and operating system dependent. */ int sock_addr_serialize(const struct sock_addr * sa, uint8_t ** buf, size_t * buflen) { uint8_t * p; /* Compute buffer length and allocate buffer. */ *buflen = 2 * sizeof(int) + sizeof(socklen_t) + sa->namelen; if ((p = *buf = malloc(*buflen)) == NULL) goto err0; /* Copy in data. */ memcpy(p, &sa->ai_family, sizeof(int)); p += sizeof(int); memcpy(p, &sa->ai_socktype, sizeof(int)); p += sizeof(int); memcpy(p, &sa->namelen, sizeof(socklen_t)); p += sizeof(socklen_t); memcpy(p, sa->name, sa->namelen); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * sock_addr_deserialize(buf, buflen): * Deserialize the ${buflen}-byte serialized socket address from ${buf}. */ struct sock_addr * sock_addr_deserialize(const uint8_t * buf, size_t buflen) { struct sock_addr * sa; /* Sanity check. */ if (buflen < 2 * sizeof(int) + sizeof(socklen_t)) goto err0; /* Allocate a structure and copy in fields. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err0; memcpy(&sa->ai_family, buf, sizeof(int)); buf += sizeof(int); memcpy(&sa->ai_socktype, buf, sizeof(int)); buf += sizeof(int); memcpy(&sa->namelen, buf, sizeof(socklen_t)); buf += sizeof(socklen_t); /* Allocate and copy the sockaddr. */ if (buflen != 2 * sizeof(int) + sizeof(socklen_t) + sa->namelen) goto err1; if ((sa->name = malloc(sa->namelen)) == NULL) goto err1; memcpy(sa->name, buf, sa->namelen); /* Success! */ return (sa); err1: free(sa); err0: /* Failure! */ return (NULL); } /* Prettyprint an IPv4 address. */ static char * prettyprint_ipv4(struct sockaddr * name, size_t namelen) { struct sockaddr_in sa_in; char addr[INET_ADDRSTRLEN]; char * s; /* Check name length. */ if (namelen != sizeof(struct sockaddr_in)) return (NULL); /* Copy into buffer for alignment. */ memcpy(&sa_in, name, namelen); /* Convert IP address to string. */ if (inet_ntop(AF_INET, &sa_in.sin_addr, addr, sizeof(addr)) == NULL) return (NULL); /* Construct address string. */ if (asprintf(&s, "[%s]:%d", addr, ntohs(sa_in.sin_port)) == -1) return (NULL); /* Success! */ return (s); } /* Prettyprint an IPv6 address. */ static char * prettyprint_ipv6(struct sockaddr * name, size_t namelen) { struct sockaddr_in6 sa_in6; char addr[INET6_ADDRSTRLEN]; char * s; /* Check name length. */ if (namelen != sizeof(struct sockaddr_in6)) return (NULL); /* Copy into buffer for alignment. */ memcpy(&sa_in6, name, namelen); /* Convert IPv6 address to string. */ if (inet_ntop(AF_INET6, &sa_in6.sin6_addr, addr, sizeof(addr)) == NULL) return (NULL); /* Construct address string. */ if (asprintf(&s, "[%s]:%d", addr, ntohs(sa_in6.sin6_port)) == -1) return (NULL); /* Success! */ return (s); } /* Prettyprint a UNIX address. */ static char * prettyprint_unix(struct sockaddr_un * name) { /* Just strdup the path. */ return (strdup(name->sun_path)); } /** * sock_addr_prettyprint(sa): * Allocate and return a string in one of the forms * /path/to/unix/socket * [ip.v4.ad.dr]:port * [ipv6:add::ress]:port * representing the provided socket address. */ char * sock_addr_prettyprint(const struct sock_addr * sa) { /* Handle different types of addresses differently. */ switch (sa->ai_family) { case AF_INET: return (prettyprint_ipv4(sa->name, sa->namelen)); case AF_INET6: return (prettyprint_ipv6(sa->name, sa->namelen)); case AF_UNIX: return (prettyprint_unix((struct sockaddr_un *)(sa->name))); default: return (strdup("Unknown address")); } } spiped-1.4.1/libcperciva/util/warnp.h000644 001751 001751 00000002525 12403117256 021202 0ustar00cpercivacperciva000000 000000 #ifndef _WARNP_H_ #define _WARNP_H_ #include /* Avoid namespace collisions with BSD . */ #define warn libcperciva_warn #define warnx libcperciva_warnx /** * warnp_setprogname(progname): * Set the program name to be used by warn() and warnx() to ${progname}. */ void warnp_setprogname(const char *); #define WARNP_INIT do { \ if (argv[0] != NULL) \ warnp_setprogname(argv[0]); \ } while (0) /* As in BSD . */ void warn(const char *, ...); void warnx(const char *, ...); /* * If compiled with DEBUG defined, print __FILE__ and __LINE__. */ #ifdef DEBUG #define warnline do { \ warnx("%s, %d", __FILE__, __LINE__); \ } while (0) #else #define warnline #endif /* * Call warn(3) or warnx(3) depending upon whether errno == 0; and clear * errno (so that the standard error message isn't repeated later). */ #define warnp(...) do { \ warnline; \ if (errno != 0) { \ warn(__VA_ARGS__); \ errno = 0; \ } else \ warnx(__VA_ARGS__); \ } while (0) /* * 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. */ #define warn0(...) do { \ warnline; \ warnx(__VA_ARGS__); \ errno = 0; \ } while (0) #endif /* !_WARNP_H_ */ spiped-1.4.1/libcperciva/util/sock.c000644 001751 001751 00000023544 12403117256 021011 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include #include #include #include #include "imalloc.h" #include "warnp.h" #include "sock.h" #include "sock_internal.h" /* Convert a path into a socket address. */ static struct sock_addr ** sock_resolve_unix(const char * addr) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_un * sa_un; /* Allocate and populate a sockaddr_un structure. */ if ((sa_un = calloc(1, sizeof(struct sockaddr_un))) == NULL) goto err0; sa_un->sun_family = AF_UNIX; if (strlen(addr) >= sizeof(sa_un->sun_path)) { warn0("socket path too long: %s", addr); goto err1; } strcpy(sa_un->sun_path, addr); /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_UNIX; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sa_un; sa->namelen = sizeof(struct sockaddr_un); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sa_un); err0: /* Failure! */ return (NULL); } /* Resolve a host into a list of socket addresses. */ static struct sock_addr ** sock_resolve_host(const char * addr, const char * ports) { struct addrinfo hints; struct addrinfo * res; struct addrinfo * r; struct sock_addr ** sas; size_t n; int error; /* 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) { warn0("Error looking up %s: %s", addr, gai_strerror(error)); goto err0; } /* Count addresses returned. */ for (n = 0, r = res; r != NULL; r = r->ai_next) n++; /* Allocate our response array. */ if (IMALLOC(sas, n + 1, struct sock_addr *)) goto err1; /* Create address structures. */ for (n = 0, r = res; r != NULL; n++, r = r->ai_next) { /* Allocate a structure. */ if ((sas[n] = malloc(sizeof(struct sock_addr))) == NULL) goto err2; /* Copy in the address metadata. */ sas[n]->ai_family = r->ai_family; sas[n]->ai_socktype = r->ai_socktype; sas[n]->namelen = r->ai_addrlen; /* Duplicate the address. */ if ((sas[n]->name = malloc(sas[n]->namelen)) == NULL) goto err3; memcpy(sas[n]->name, r->ai_addr, sas[n]->namelen); } /* Terminate array with a NULL. */ sas[n] = NULL; /* Free the linked list of addresses returned by getaddrinfo. */ freeaddrinfo(res); /* Success! */ return (sas); err3: free(sas[n]); err2: for (; n > 0; n--) sock_addr_free(sas[n - 1]); free(sas); err1: freeaddrinfo(res); err0: /* Failure! */ return (NULL); } /* Parse an IPv6 address into a socket address. */ static struct sock_addr ** sock_resolve_ipv6(const char * addr, in_port_t p) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_in6 * sin6; /* Allocate and populate a sockaddr_in6 structure. */ if ((sin6 = calloc(1, sizeof(struct sockaddr_in6))) == NULL) goto err0; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(p); if (inet_pton(AF_INET6, addr, &sin6->sin6_addr) != 1) { warn0("Error parsing IP address: %s", addr); goto err1; } /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_INET6; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sin6; sa->namelen = sizeof(struct sockaddr_in6); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sin6); err0: /* Failure! */ return (NULL); } /* Parse an IPv4 address into a socket address. */ static struct sock_addr ** sock_resolve_ipv4(const char * addr, in_port_t p) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_in * sin; /* Allocate and populate a sockaddr_in structure. */ if ((sin = calloc(1, sizeof(struct sockaddr_in))) == NULL) goto err0; sin->sin_family = AF_INET; sin->sin_port = htons(p); if (inet_pton(AF_INET, addr, &sin->sin_addr) != 1) { warn0("Error parsing IP address: %s", addr); goto err1; } /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_INET; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sin; sa->namelen = sizeof(struct sockaddr_in); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sin); err0: /* Failure! */ return (NULL); } /** * sock_resolve(addr): * Return a NULL-terminated array of pointers to sock_addr structures. */ struct sock_addr ** sock_resolve(const char * addr) { struct sock_addr ** res; char * s; char * ports; char * ips; long p; /* If the address starts with '/', it's a unix socket. */ if (addr[0] == '/') { res = sock_resolve_unix(addr); goto done0; } /* Copy the address so that we can mangle it. */ if ((s = strdup(addr)) == NULL) goto err0; /* The address should end with :port. Look for the last ':'. */ if ((ports = strrchr(s, ':')) == NULL) { warn0("Address must contain port number: %s", s); goto err1; } *ports++ = '\0'; /* If the address doesn't start with '[', it's a host name. */ if (s[0] != '[') { res = sock_resolve_host(s, ports); goto done1; } /* The address (sans :port) should end with ']'. */ if (s[strlen(s) - 1] != ']') { warn0("Invalid [IP address]: %s", s); goto err1; } /* Extract the IP address string. */ ips = &s[1]; ips[strlen(ips) - 1] = '\0'; /* * Parse the port number. If strtol fails to parse the port number, * it will return 0; but that's fine since port 0 is invalid anyway. */ p = strtol(ports, NULL, 10); if ((p <= 0) || (p >= 65536)) { warn0("Invalid port number: %s", ports); goto err1; } /* If the IP address contains ':', it's IPv6; otherwise, IPv4. */ if (strchr(ips, ':') != NULL) res = sock_resolve_ipv6(ips, p); else res = sock_resolve_ipv4(ips, p); done1: /* Free string allocated by strdup. */ free(s); done0: /* Return result from sock_resolve_foo. */ return (res); err1: free(s); err0: /* Failure! */ return (NULL); } /** * 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. */ int sock_listener(const struct sock_addr * sa) { int s; int val = 1; /* Create a socket. */ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1) { warnp("socket(%d, %d)", sa->ai_family, sa->ai_socktype); goto err0; } /* Set SO_REUSEADDR. */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { warnp("setsockopt(SO_REUSEADDR)"); goto err1; } /* Bind the socket. */ if (bind(s, sa->name, sa->namelen)) { warnp("Error binding socket"); goto err1; } /* Mark the socket as listening. */ if (listen(s, 10)) { warnp("Error marking socket as listening"); goto err1; } /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Error marking socket as non-blocking"); goto err1; } /* Success! */ return (s); err1: close(s); err0: /* Failure! */ return (-1); } /** * sock_connect(sas): * Iterate through the addresses in ${sas}, attempting to create a socket and * connect (blockingly). Once connected, stop iterating, mark the socket as * non-blocking, and return it. */ int sock_connect(struct sock_addr * const * sas) { int s = -1; /* Iterate through the addresses provided. */ for (; sas[0] != NULL; sas++) { /* Create a socket. */ if ((s = socket(sas[0]->ai_family, sas[0]->ai_socktype, 0)) == -1) continue; /* Attempt to connect. */ if (connect(s, sas[0]->name, sas[0]->namelen) == 0) break; /* Close the socket; this address didn't work. */ close(s); } /* Did we manage to connect? */ if (sas[0] == NULL) { warn0("Could not connect"); goto err0; } /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Cannot make connection non-blocking"); goto err1; } /* Success! */ return (s); err1: close(s); err0: /* Failure! */ return (-1); } /** * sock_connect_nb(sa): * Create a socket, mark it as non-blocking, and attempt to connect to the * address ${sa}. Return the socket (connected or in the process of * connecting) or -1 on error. */ int sock_connect_nb(const struct sock_addr * sa) { int s; /* Create a socket. */ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1) goto err0; /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Cannot make socket non-blocking"); goto err1; } /* Attempt to connect. */ if ((connect(s, sa->name, sa->namelen) == -1) && (errno != EINPROGRESS) && (errno != EINTR)) goto err1; /* We have a connect(ed|ing) socket. */ return (s); err1: close(s); err0: /* We failed to connect to this address. */ return (-1); } /** * sock_addr_free(sa): * Free the provided sock_addr structure. */ void sock_addr_free(struct sock_addr * sa) { /* Compatibility with free(NULL). */ if (sa == NULL) return; /* Free the protocol-specific address structure and our struct. */ free(sa->name); free(sa); } /** * sock_addr_freelist(sas): * Free the provided NULL-terminated array of sock_addr structures. */ void sock_addr_freelist(struct sock_addr ** sas) { struct sock_addr ** p; /* Compatibility with free(NULL). */ if (sas == NULL) return; /* Free structures until we hit NULL. */ for (p = sas; *p != NULL; p++) sock_addr_free(*p); /* Free the list. */ free(sas); } spiped-1.4.1/libcperciva/util/sock_internal.h000644 001751 001751 00000000364 12403117256 022705 0ustar00cpercivacperciva000000 000000 #ifndef _SOCK_INTERNAL_H_ #define _SOCK_INTERNAL_H_ #include /* Socket address structure. */ struct sock_addr { int ai_family; int ai_socktype; struct sockaddr * name; socklen_t namelen; }; #endif /* !_SOCK_INTERNAL_H_ */ spiped-1.4.1/libcperciva/util/entropy.c000644 001751 001751 00000002743 12403117256 021550 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "warnp.h" #include "entropy.h" /** * XXX Portability * XXX We obtain random bytes from the operating system by opening * XXX /dev/urandom and reading them from that device; this works on * XXX modern UNIX-like operating systems but not on systems like * XXX win32 where there is no concept of /dev/urandom. */ /** * 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) { 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); goto err0; } /* Open /dev/urandom. */ if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { warnp("open(/dev/urandom)"); goto err0; } /* Read bytes until we have filled the buffer. */ while (buflen > 0) { if ((lenread = read(fd, buf, buflen)) == -1) { warnp("read(/dev/urandom)"); goto err1; } /* The random device should never EOF. */ if (lenread == 0) { warn0("EOF on /dev/urandom?"); goto err1; } /* We've filled a portion of the buffer. */ buf += lenread; buflen -= lenread; } /* Close the device. */ while (close(fd) == -1) { if (errno != EINTR) { warnp("close(/dev/urandom)"); goto err0; } } /* Success! */ return (0); err1: close(fd); err0: /* Failure! */ return (-1); } spiped-1.4.1/libcperciva/util/sock_util.h000644 001751 001751 00000002550 12403117256 022045 0ustar00cpercivacperciva000000 000000 #ifndef _SOCK_UTIL_H_ #define _SOCK_UTIL_H_ #include /* Opaque address structure. */ struct sock_addr; /** * sock_addr_cmp(sa1, sa2): * Return non-zero iff the socket addresses ${sa1} and ${sa2} are different. */ int sock_addr_cmp(const struct sock_addr *, const struct sock_addr *); /** * sock_addr_dup(sa): * Duplicate the provided socket address. */ struct sock_addr * sock_addr_dup(const struct sock_addr *); /** * sock_addr_duplist(sas): * Duplicate the provided list of socket addresses. */ struct sock_addr ** sock_addr_duplist(struct sock_addr * const *); /** * sock_addr_serialize(sa, buf, buflen): * Allocate a buffer and serialize the socket address ${sa} into it. Return * the buffer via ${buf} and its length via ${buflen}. The serialization is * machine and operating system dependent. */ int sock_addr_serialize(const struct sock_addr *, uint8_t **, size_t *); /** * sock_addr_deserialize(buf, buflen): * Deserialize the ${buflen}-byte serialized socket address from ${buf}. */ struct sock_addr * sock_addr_deserialize(const uint8_t *, size_t); /** * sock_addr_prettyprint(sa): * Allocate and return a string in one of the forms * /path/to/unix/socket * [ip.v4.ad.dr]:port * [ipv6:add::ress]:port * representing the provided socket address. */ char * sock_addr_prettyprint(const struct sock_addr *); #endif /* !_SOCK_H_ */ spiped-1.4.1/libcperciva/util/sysendian.h000644 001751 001751 00000006113 12403117256 022045 0ustar00cpercivacperciva000000 000000 #ifndef _SYSENDIAN_H_ #define _SYSENDIAN_H_ #include /* Avoid namespace collisions with BSD . */ #define be16dec libcperciva_be16dec #define be16enc libcperciva_be16enc #define be32dec libcperciva_be32dec #define be32enc libcperciva_be32enc #define be64dec libcperciva_be64dec #define be64enc libcperciva_be64enc #define le16dec libcperciva_le16dec #define le16enc libcperciva_le16enc #define le32dec libcperciva_le32dec #define le32enc libcperciva_le32enc #define le64dec libcperciva_le64dec #define le64enc libcperciva_le64enc static inline uint16_t be16dec(const void * pp) { const uint8_t * p = (uint8_t const *)pp; return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8)); } static inline void be16enc(void * pp, uint16_t x) { uint8_t * p = (uint8_t *)pp; p[1] = x & 0xff; p[0] = (x >> 8) & 0xff; } static inline uint32_t be32dec(const void * pp) { 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)); } static inline void be32enc(void * pp, uint32_t x) { uint8_t * p = (uint8_t *)pp; p[3] = x & 0xff; p[2] = (x >> 8) & 0xff; p[1] = (x >> 16) & 0xff; p[0] = (x >> 24) & 0xff; } static inline uint64_t be64dec(const void * pp) { 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)); } static inline void be64enc(void * pp, uint64_t x) { uint8_t * p = (uint8_t *)pp; p[7] = x & 0xff; p[6] = (x >> 8) & 0xff; p[5] = (x >> 16) & 0xff; p[4] = (x >> 24) & 0xff; p[3] = (x >> 32) & 0xff; p[2] = (x >> 40) & 0xff; p[1] = (x >> 48) & 0xff; p[0] = (x >> 56) & 0xff; } static inline uint16_t le16dec(const void * pp) { const uint8_t * p = (uint8_t const *)pp; return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8)); } static inline void le16enc(void * pp, uint16_t x) { uint8_t * p = (uint8_t *)pp; p[0] = x & 0xff; p[1] = (x >> 8) & 0xff; } static inline uint32_t le32dec(const void * pp) { 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)); } static inline void le32enc(void * pp, uint32_t x) { uint8_t * p = (uint8_t *)pp; p[0] = x & 0xff; p[1] = (x >> 8) & 0xff; p[2] = (x >> 16) & 0xff; p[3] = (x >> 24) & 0xff; } static inline uint64_t le64dec(const void * pp) { 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)); } static inline void le64enc(void * pp, uint64_t x) { uint8_t * p = (uint8_t *)pp; p[0] = x & 0xff; p[1] = (x >> 8) & 0xff; p[2] = (x >> 16) & 0xff; p[3] = (x >> 24) & 0xff; p[4] = (x >> 32) & 0xff; p[5] = (x >> 40) & 0xff; p[6] = (x >> 48) & 0xff; p[7] = (x >> 56) & 0xff; } #endif /* !_SYSENDIAN_H_ */ spiped-1.4.1/libcperciva/util/sock.h000644 001751 001751 00000002564 12403117256 021015 0ustar00cpercivacperciva000000 000000 #ifndef _SOCK_H_ #define _SOCK_H_ /** * Address strings are of the following forms: * /path/to/unix/socket * [ip.v4.ad.dr]:port * [ipv6:add::ress]:port * host.name:port */ /* Opaque address structure. */ struct sock_addr; /** * sock_resolve(addr): * Return a NULL-terminated array of pointers to sock_addr structures. */ struct sock_addr ** sock_resolve(const char *); /** * 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. */ int sock_listener(const struct sock_addr *); /** * sock_connect(sas): * Iterate through the addresses in ${sas}, attempting to create a socket and * connect (blockingly). Once connected, stop iterating, mark the socket as * non-blocking, and return it. */ int sock_connect(struct sock_addr * const *); /** * sock_connect_nb(sa): * Create a socket, mark it as non-blocking, and attempt to connect to the * address ${sa}. Return the socket (connected or in the process of * connecting) or -1 on error. */ int sock_connect_nb(const struct sock_addr *); /** * sock_addr_free(sa): * Free the provided sock_addr structure. */ void sock_addr_free(struct sock_addr *); /** * sock_addr_freelist(sas): * Free the provided NULL-terminated array of sock_addr structures. */ void sock_addr_freelist(struct sock_addr **); #endif /* !_SOCK_H_ */ spiped-1.4.1/libcperciva/util/entropy.h000644 001751 001751 00000000405 12403117256 021546 0ustar00cpercivacperciva000000 000000 #ifndef _ENTROPY_H_ #define _ENTROPY_H_ #include #include /** * entropy_read(buf, buflen): * Fill the given buffer with random bytes provided by the operating system. */ int entropy_read(uint8_t *, size_t); #endif /* !_ENTROPY_H_ */ spiped-1.4.1/libcperciva/util/insecure_memzero.c000644 001751 001751 00000000624 12403117256 023417 0ustar00cpercivacperciva000000 000000 #include #include #include "insecure_memzero.h" /* Fucntion which does the zeroing. */ static void insecure_memzero_func(volatile void * buf, size_t len) { volatile uint8_t * _buf = buf; size_t i; for (i = 0; i < len; i++) _buf[i] = 0; } /* Pointer to memory-zeroing function. */ void (* volatile insecure_memzero_ptr)(volatile void *, size_t) = insecure_memzero_func; spiped-1.4.1/libcperciva/util/daemonize.c000644 001751 001751 00000004541 12403117256 022021 0ustar00cpercivacperciva000000 000000 #include #include #include #include "noeintr.h" #include "warnp.h" #include "daemonize.h" /** * daemonize(spid): * Daemonize and write the process ID in decimal to a file named ${spid}. * The parent process will exit only after the child has written its pid. * On success, the child will return 0; on failure, the parent will return * -1. */ int daemonize(const char * spid) { FILE * f; int fd[2]; char dummy = 0; /* * Create a pipe for the child to notify the parent when it has * finished daemonizing. */ if (pipe(fd)) { warnp("pipe"); goto err0; } /* * Fork into the parent process (which waits for a poke and exits) * and the child process (which keeps going). */ switch (fork()) { case -1: /* Fork failed. */ warnp("fork"); goto err2; case 0: /* In child process. */ break; default: /* * In parent process. Close write end of pipe so that if the * client dies we will notice the pipe being reset. */ while (close(fd[1])) { if (errno == EINTR) continue; warnp("close"); goto err1; } do { switch (read(fd[0], &dummy, 1)) { case -1: /* Error in read. */ break; case 0: /* EOF -- the child died without poking us. */ goto err1; case 1: /* We have been poked by the child. Exit. */ _exit(0); } /* Anything other than EINTR is bad. */ if (errno != EINTR) { warnp("read"); goto err1; } } while (1); } /* Set ourselves to be a session leader. */ if (setsid() == -1) { warnp("setsid"); goto die; } /* Write out our pid file. */ if ((f = fopen(spid, "w")) == NULL) { warnp("fopen(%s)", spid); goto die; } if (fprintf(f, "%d", getpid()) < 0) { warnp("fprintf"); goto die; } if (fclose(f)) { warnp("fclose"); goto die; } /* Tell the parent to suicide. */ if (noeintr_write(fd[1], &dummy, 1) == -1) { warnp("write"); goto die; } /* Close the pipe. */ while (close(fd[0])) { if (errno == EINTR) continue; warnp("close"); goto die; } while (close(fd[1])) { if (errno == EINTR) continue; warnp("close"); goto die; } /* Success! */ return (0); err2: close(fd[1]); err1: close(fd[0]); err0: /* Failure! */ return (-1); die: /* * We're in the child and something bad happened; the parent will be * notified when we die thanks to the pipe being closed. */ _exit(0); } spiped-1.4.1/libcperciva/util/noeintr.c000644 001751 001751 00000002161 12403117256 021520 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "noeintr.h" /** * noeintr_write(d, buf, nbytes): * Write ${nbytes} bytes of data from ${buf} to the file descriptor ${d} per * the write(2) system call, but looping until completion if interrupted by * a signal. Return ${nbytes} on success or -1 on error. */ ssize_t noeintr_write(int d, const void * buf, size_t nbyte) { const uint8_t * p = buf; size_t len = nbyte; ssize_t lenwrit; /* Implementation-defined: Don't allow oversized writes. */ assert(nbyte <= SSIZE_MAX); /* Loop until we have no data left to write. */ while (len > 0) { if ((lenwrit = write(d, p, len)) == -1) { /* EINTR is harmless. */ if (errno == EINTR) continue; /* Anything else isn't. */ goto err0; } /* Sanity check. */ assert(lenwrit >= 0); assert(lenwrit <= (ssize_t)len); /* * We might have done a partial write; advance the buffer * pointer and adjust the remaining write length. */ p += lenwrit; len -= lenwrit; } /* Success! */ return (nbyte); err0: /* Failure! */ return (-1); } spiped-1.4.1/libcperciva/util/insecure_memzero.h000644 001751 001751 00000002430 12403117256 023421 0ustar00cpercivacperciva000000 000000 #ifndef _INSECURE_MEMZERO_H_ #define _INSECURE_MEMZERO_H_ #include /* Pointer to memory-zeroing function. */ extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t); /** * insecure_memzero(buf, len): * Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers' * best (standards-compliant) attempts to remove the buffer-zeroing. In * particular, to avoid performing the zeroing, a compiler would need to * use optimistic devirtualization; recognize that non-volatile objects do not * need to be treated as volatile, even if they are accessed via volatile * qualified pointers; and perform link-time optimization; in addition to the * dead-code elimination which often causes buffer-zeroing to be elided. * * Note however that zeroing a buffer does nto guarantee that the data held * in the buffer is not stored elsewhere; in particular, there may be copies * held in CPU registers or in anonymous allocations on the stack, even if * every named variable is successfully sanitized. Solving the "wipe data * from the system" problem will require a C language extension which does not * yet exist. */ static inline void insecure_memzero(volatile void * buf, size_t len) { (insecure_memzero_ptr)(buf, len); } #endif /* !_INSECURE_MEMZERO_H_ */ spiped-1.4.1/libcperciva/util/daemonize.h000644 001751 001751 00000000315 12403117256 022021 0ustar00cpercivacperciva000000 000000 #ifndef _DAEMONIZE_H_ #define _DAEMONIZE_H_ /** * daemonize(spid): * Daemonize and write the process ID in decimal to a file named ${spid}. */ int daemonize(const char *); #endif /* !_DAEMONIZE_H_ */ spiped-1.4.1/libcperciva/util/noeintr.h000644 001751 001751 00000000607 12403117256 021530 0ustar00cpercivacperciva000000 000000 #ifndef _NOEINTR_H_ #define _NOEINTR_H_ #include /** * noeintr_write(d, buf, nbytes): * Write ${nbytes} bytes of data from ${buf} to the file descriptor ${d} per * the write(2) system call, but looping until completion if interrupted by * a signal. Return ${nbytes} on success or -1 on error. */ ssize_t noeintr_write(int, const void *, size_t); #endif /* _NOEINTR_H_ */ spiped-1.4.1/libcperciva/util/monoclock.c000644 001751 001751 00000002040 12403117256 022022 0ustar00cpercivacperciva000000 000000 #include #include #include "warnp.h" #include "monoclock.h" /** * monoclock_get(tv): * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if * available) or gettimeofday(2). */ int monoclock_get(struct timeval * tv) { #if defined(CLOCK_MONOTONIC) || !defined(POSIXFAIL_CLOCK_REALTIME) struct timespec tp; #endif #ifdef CLOCK_MONOTONIC if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { tv->tv_sec = tp.tv_sec; tv->tv_usec = tp.tv_nsec / 1000; } else if ((errno != ENOSYS) && (errno != EINVAL)) { warnp("clock_gettime(CLOCK_MONOTONIC)"); goto err0; } else #endif #ifndef POSIXFAIL_CLOCK_REALTIME if (clock_gettime(CLOCK_REALTIME, &tp) == 0) { tv->tv_sec = tp.tv_sec; tv->tv_usec = tp.tv_nsec / 1000; } else { warnp("clock_gettime(CLOCK_REALTIME)"); goto err0; } #else if (gettimeofday(tv, NULL)) { warnp("gettimeofday"); goto err0; } #endif /* Success! */ return (0); err0: /* Failure! */ return (-1); } spiped-1.4.1/libcperciva/util/imalloc.h000644 001751 001751 00000001246 12403117256 021472 0ustar00cpercivacperciva000000 000000 #ifndef _IMALLOC_H_ #define _IMALLOC_H_ #include #include #include /** * imalloc(nrec, reclen): * Allocate ${nrec} records of length ${reclen}. Check for size_t overflow. */ static inline void * imalloc(size_t nrec, size_t reclen) { if (nrec > SIZE_MAX / reclen) { errno = ENOMEM; return (NULL); } else { return (malloc(nrec * reclen)); } } /** * IMALLOC(p, nrec, type): * Allocate ${nrec} records of type ${type} and store the pointer in ${p}. * Return non-zero on failure. */ #define IMALLOC(p, nrec, type) \ ((((p) = (type *)imalloc((nrec), sizeof(type))) == NULL) && \ ((nrec) > 0)) #endif /* !_IMALLOC_H_ */ spiped-1.4.1/libcperciva/util/asprintf.c000644 001751 001751 00000001426 12403117256 021673 0ustar00cpercivacperciva000000 000000 #include #include #include #include "asprintf.h" /** * asprintf(ret, format, ...): * Do asprintf(3) like GNU and BSD do. */ int asprintf(char ** ret, const char * format, ...) { va_list ap; int len; size_t buflen; /* Figure out how long the string needs to be. */ va_start(ap, format); len = vsnprintf(NULL, 0, format, ap); va_end(ap); /* Did we fail? */ if (len < 0) goto err0; buflen = (size_t)(len) + 1; /* Allocate memory. */ if ((*ret = malloc(buflen)) == NULL) goto err0; /* Actually generate the string. */ va_start(ap, format); len = vsnprintf(*ret, buflen, format, ap); va_end(ap); /* Did we fail? */ if (len < 0) goto err1; /* Success! */ return (len); err1: free(*ret); err0: /* Failure! */ return (-1); } spiped-1.4.1/libcperciva/util/warnp.c000644 001751 001751 00000002477 12403117256 021203 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "warnp.h" static int initialized = 0; static char * name = NULL; /* Free the name string. */ static void done(void) { free(name); name = NULL; } /** * warnp_setprogname(progname): * Set the program name to be used by warn() and warnx() to ${progname}. */ void warnp_setprogname(const char * progname) { const char * p; /* Free the name if we already have one. */ free(name); /* Find the last segment of the program name. */ for (p = progname; progname[0] != '\0'; progname++) if (progname[0] == '/') p = progname + 1; /* Copy the name string. */ name = strdup(p); /* If we haven't already done so, register our exit handler. */ if (initialized == 0) { atexit(done); initialized = 1; } } void warn(const char * fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); if (fmt != NULL) { fprintf(stderr, ": "); vfprintf(stderr, fmt, ap); } fprintf(stderr, ": %s\n", strerror(errno)); va_end(ap); } void warnx(const char * fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); if (fmt != NULL) { fprintf(stderr, ": "); vfprintf(stderr, fmt, ap); } fprintf(stderr, "\n"); va_end(ap); } spiped-1.4.1/libcperciva/util/monoclock.h000644 001751 001751 00000000531 12403117256 022032 0ustar00cpercivacperciva000000 000000 #ifndef _MONOCLOCK_H_ #define _MONOCLOCK_H_ #include /** * monoclock_get(tv): * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if * available) or gettimeofday(2). */ int monoclock_get(struct timeval *); #endif /* !_MONOCLOCK_H_ */ spiped-1.4.1/libcperciva/network/network.h000644 001751 001751 00000006732 12403117256 022264 0ustar00cpercivacperciva000000 000000 #ifndef _NETWORK_H_ #define _NETWORK_H_ #include #include #include #include /* Opaque address structure. */ struct sock_addr; /** * network_accept(fd, callback, cookie): * Asynchronously accept a connection on the socket ${fd}, which must be * 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. */ 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. */ void network_accept_cancel(void *); /** * network_connect(sas, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * 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 * the connection attempt. */ void * network_connect(struct sock_addr * const *, int (*)(void *, int), void *); /** * network_connect_timeo(sas, timeo, callback, cookie): * 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 *, int (*)(void *, int), void *); /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by * network_connect. Do not invoke the associated callback. */ void network_connect_cancel(void *); /** * network_read(fd, buf, buflen, minread, callback, cookie): * Asynchronously read up to ${buflen} bytes of data from ${fd} into ${buf}. * 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 * order to cancel the read. */ void * network_read(int, uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); /** * 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. */ void network_read_cancel(void *); /** * network_write(fd, buf, buflen, minwrite, callback, cookie): * Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}. * 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 * order to cancel the write. */ void * network_write(int, const uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); /** * 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. */ void network_write_cancel(void *); #endif /* !_NETWORK_H_ */ spiped-1.4.1/libcperciva/network/network_connect.c000644 001751 001751 00000013217 12403117256 023764 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "events.h" #include "sock.h" #include "network.h" struct connect_cookie { int (* callback)(void *, int); void * cookie; struct sock_addr * const * sas; struct timeval timeo; void * cookie_immediate; int s; int timeo_enabled; void * cookie_timeo; }; static int tryconnect(struct connect_cookie *); /* Invoke the upstream callback and clean up. */ static int docallback(void * cookie) { struct connect_cookie * C = cookie; int rc; /* Invoke the upstream callback. */ rc = (C->callback)(C->cookie, C->s); /* Free the cookie. */ free(C); /* Return status from upstream callback. */ return (rc); } /* An address failed to connect. */ static int dofailed(struct connect_cookie * C) { /* Close the socket which failed to connect. */ close(C->s); /* We don't have an open socket any more. */ C->s = -1; /* This address didn't work. */ C->sas++; /* Try other addresses until we run out of options. */ return (tryconnect(C)); } /* Callback when connect(2) succeeds or fails. */ static int callback_connect(void * cookie) { struct connect_cookie * C = cookie; int sockerr; socklen_t sockerrlen = sizeof(int); /* Stop waiting for the timer callback. */ if (C->cookie_timeo != NULL) { events_timer_cancel(C->cookie_timeo); C->cookie_timeo = NULL; } /* Did we succeed? */ if (getsockopt(C->s, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen)) goto err1; if (sockerr != 0) return (dofailed(C)); /* * Perform the callback (this can be done here rather than being * scheduled as an immediate callback, as we're already running from * callback context). */ return (docallback(C)); err1: close(C->s); free(C); /* Fatal error! */ return (-1); } /* Callback when a timer expires. */ static int callback_timeo(void * cookie) { struct connect_cookie * C = cookie; /* We're not waiting for a timer callback any more. */ C->cookie_timeo = NULL; /* Stop listening for this socket. */ events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE); /* This connect attempt failed. */ return (dofailed(C)); } /* Try to launch a connection. Free the cookie on fatal errors. */ static int tryconnect(struct connect_cookie * C) { /* Try addresses until we find one which doesn't fail immediately. */ for (; C->sas[0] != NULL; C->sas++) { /* Can we try to connect to this address? */ if ((C->s = sock_connect_nb(C->sas[0])) != -1) break; } /* Did we run out of addresses to try? */ if (C->sas[0] == NULL) goto failed; /* If we've been asked to have a timeout, set one. */ if (C->timeo_enabled) { if ((C->cookie_timeo = events_timer_register(callback_timeo, C, &C->timeo)) == NULL) goto err1; } else { C->cookie_timeo = NULL; } /* Wait until this socket connects or fails to do so. */ if (events_network_register(callback_connect, C, C->s, EVENTS_NETWORK_OP_WRITE)) goto err2; /* Success! */ return (0); failed: /* Schedule a callback. */ if ((C->cookie_immediate = events_immediate_register(docallback, C, 0)) == NULL) goto err1; /* Failure successfully handled. */ return (0); err2: if (C->cookie_timeo != NULL) events_timer_cancel(C->cookie_timeo); err1: if (C->s != -1) close(C->s); free(C); /* Fatal error. */ return (-1); } /** * network_connect(sas, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * 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 * the connection attempt. */ void * network_connect(struct sock_addr * const * sas, int (* callback)(void *, int), void * cookie) { /* Let network_connect_timeo handle this. */ return (network_connect_timeo(sas, NULL, callback, cookie)); } /** * network_connect_timeo(sas, timeo, callback, cookie): * 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 * sas, const struct timeval * timeo, int (* callback)(void *, int), void * cookie) { struct connect_cookie * C; /* Bake a cookie. */ if ((C = malloc(sizeof(struct connect_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->sas = sas; C->cookie_immediate = NULL; C->cookie_timeo = NULL; C->s = -1; /* Do we have a timeout? */ if (timeo != NULL) { memcpy(&C->timeo, timeo, sizeof(struct timeval)); C->timeo_enabled = 1; } else { C->timeo_enabled = 0; } /* Try to connect to the first address. */ if (tryconnect(C)) goto err0; /* Success! */ return (C); err0: /* Failure! */ return (NULL); } /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by * network_connect. Do not invoke the associated callback. */ void network_connect_cancel(void * cookie) { struct connect_cookie * C = cookie; /* We should have either an immediate callback or a socket. */ assert((C->cookie_immediate != NULL) || (C->s != -1)); assert((C->cookie_immediate == NULL) || (C->s == -1)); /* Cancel any timer. */ if (C->cookie_timeo != NULL) events_timer_cancel(C->cookie_timeo); /* Cancel any immediate callback. */ if (C->cookie_immediate != NULL) events_immediate_cancel(C->cookie_immediate); /* Close any socket. */ if (C->s != -1) { events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE); close(C->s); } /* Free the cookie. */ free(C); } spiped-1.4.1/libcperciva/network/network_write.c000644 001751 001751 00000010617 12403117256 023466 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include #include "events.h" #include "warnp.h" #include "network.h" /** * POSIX.1-2008 requires that MSG_NOSIGNAL be defined as a flag for send(2) * which has the effect of preventing SIGPIPE from being raised when writing * to a descriptor which has been shut down. Unfortunately there are some * platforms which are not POSIX.1-2008 compliant; we provide a workaround * (-DPOSIXFAIL_MSG_NOSIGNAL) which instead blocks the SIGPIPE signal on such * platforms. * * (This workaround could be used automatically, but requiring that it be * explicitly enabled helps to get platforms fixed.) */ #ifdef POSIXFAIL_MSG_NOSIGNAL #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #endif struct network_write_cookie { int (*callback)(void *, ssize_t); void * cookie; int fd; const uint8_t * buf; size_t buflen; size_t minlen; size_t bufpos; }; /* Invoke the callback, clean up, and return the callback's status. */ static int docallback(struct network_write_cookie * C, ssize_t nbytes) { int rc; /* Invoke the callback. */ rc = (C->callback)(C->cookie, nbytes); /* Clean up. */ free(C); /* Return the callback's status. */ return (rc); } /* The socket is ready for reading/writing. */ static int callback_buf(void * cookie) { struct network_write_cookie * C = cookie; size_t oplen; ssize_t len; #ifdef POSIXFAIL_MSG_NOSIGNAL void (*oldsig)(int); #endif /* If we don't have MSG_NOSIGNAL, catch SIGPIPE. */ #ifdef POSIXFAIL_MSG_NOSIGNAL if ((oldsig = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) { warnp("signal(SIGPIPE)"); goto failed; } #endif /* Attempt to read/write data to/from the buffer. */ oplen = C->buflen - C->bufpos; len = send(C->fd, C->buf + C->bufpos, oplen, MSG_NOSIGNAL); /* We should never see a send length of zero. */ assert(len != 0); /* If we set a SIGPIPE handler, restore the old one. */ #ifdef POSIXFAIL_MSG_NOSIGNAL if (signal(SIGPIPE, oldsig) == SIG_ERR) { warnp("signal(SIGPIPE)"); goto failed; } #endif /* Failure? */ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) goto tryagain; /* Something went wrong. */ goto failed; } /* We processed some data. Do we need to keep going? */ if ((C->bufpos += len) < C->minlen) goto tryagain; /* Invoke the callback and return. */ return (docallback(C, C->bufpos)); tryagain: /* Reset the event. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_WRITE)) goto failed; /* Callback was reset. */ return (0); failed: /* Invoke the callback with a failure status and return. */ return (docallback(C, -1)); } /** * network_write(fd, buf, buflen, minwrite, callback, cookie): * Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}. * 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 * order to cancel the write. */ void * network_write(int fd, const uint8_t * buf, size_t buflen, size_t minwrite, int (* callback)(void *, ssize_t), void * cookie) { struct network_write_cookie * C; /* Make sure buflen is non-zero. */ assert(buflen != 0); /* Sanity-check: # bytes must fit into a ssize_t. */ assert(buflen <= SSIZE_MAX); /* Bake a cookie. */ if ((C = malloc(sizeof(struct network_write_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; C->buf = buf; C->buflen = buflen; C->minlen = minwrite; C->bufpos = 0; /* Register a callback for network readiness. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_WRITE)) goto err1; /* Success! */ return (C); err1: free(C); err0: /* Failure! */ return (NULL); } /** * 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. */ void network_write_cancel(void * cookie) { struct network_write_cookie * C = cookie; /* Kill the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_WRITE); /* Free the cookie. */ free(C); } spiped-1.4.1/libcperciva/network/network_read.c000644 001751 001751 00000006643 12403117256 023253 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "events.h" #include "warnp.h" #include "network.h" struct network_read_cookie { int (*callback)(void *, ssize_t); void * cookie; int fd; uint8_t * buf; size_t buflen; size_t minlen; size_t bufpos; }; /* Invoke the callback, clean up, and return the callback's status. */ static int docallback(struct network_read_cookie * C, ssize_t nbytes) { int rc; /* Invoke the callback. */ rc = (C->callback)(C->cookie, nbytes); /* Clean up. */ free(C); /* Return the callback's status. */ return (rc); } /* The socket is ready for reading/writing. */ static int callback_buf(void * cookie) { struct network_read_cookie * C = cookie; size_t oplen; ssize_t len; /* Attempt to read/write data to/from the buffer. */ oplen = C->buflen - C->bufpos; len = recv(C->fd, C->buf + C->bufpos, oplen, 0); /* Failure? */ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) goto tryagain; /* Something went wrong. */ goto failed; } else if (len == 0) { /* The socket was shut down by the remote host. */ goto eof; } /* We processed some data. Do we need to keep going? */ if ((C->bufpos += len) < C->minlen) goto tryagain; /* Invoke the callback and return. */ return (docallback(C, C->bufpos)); tryagain: /* Reset the event. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_READ)) goto failed; /* Callback was reset. */ return (0); eof: /* Invoke the callback with an EOF status and return. */ return (docallback(C, 0)); failed: /* Invoke the callback with a failure status and return. */ return (docallback(C, -1)); } /** * network_read(fd, buf, buflen, minread, callback, cookie): * Asynchronously read up to ${buflen} bytes of data from ${fd} into ${buf}. * 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 * order to cancel the read. */ void * network_read(int fd, uint8_t * buf, size_t buflen, size_t minread, int (* callback)(void *, ssize_t), void * cookie) { struct network_read_cookie * C; /* Make sure buflen is non-zero. */ assert(buflen != 0); /* Sanity-check: # bytes must fit into a ssize_t. */ assert(buflen <= SSIZE_MAX); /* Bake a cookie. */ if ((C = malloc(sizeof(struct network_read_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; C->buf = buf; C->buflen = buflen; C->minlen = minread; C->bufpos = 0; /* Register a callback for network readiness. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_READ)) goto err1; /* Success! */ return (C); err1: free(C); err0: /* Failure! */ return (NULL); } /** * 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. */ void network_read_cancel(void * cookie) { struct network_read_cookie * C = cookie; /* Kill the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ); /* Free the cookie. */ free(C); } spiped-1.4.1/libcperciva/network/network_accept.c000644 001751 001751 00000004465 12403117256 023577 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "events.h" #include "network.h" struct accept_cookie { int (* callback)(void *, int); void * cookie; int fd; }; /* Accept the connection and invoke the callback. */ static int callback_accept(void * cookie) { struct accept_cookie * C = cookie; int s; int rc; /* Attempt to accept a new connection. */ if ((s = accept(C->fd, NULL, NULL)) == -1) { /* If a connection isn't available, reset the callback. */ if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == ECONNABORTED) || (errno == EINTR)) goto tryagain; } /* Call the upstream callback. */ rc = (C->callback)(C->cookie, s); /* Free the cookie. */ free(C); /* Return status from upstream callback. */ return (rc); tryagain: /* Reset the callback. */ return (events_network_register(callback_accept, C, C->fd, EVENTS_NETWORK_OP_READ)); } /** * network_accept(fd, callback, cookie): * Asynchronously accept a connection on the socket ${fd}, which must be * 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. */ void * network_accept(int fd, int (* callback)(void *, int), void * cookie) { struct accept_cookie * C; /* Bake a cookie. */ if ((C = malloc(sizeof(struct accept_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; /* * Register a network event. A connection arriving on a listening * socket is treated by select(2) as the socket becoming readable. */ if (events_network_register(callback_accept, C, C->fd, EVENTS_NETWORK_OP_READ)) goto err1; /* Success! */ return (C); err1: free(C); err0: /* Failure! */ return (NULL); } /** * 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. */ void network_accept_cancel(void * cookie) { struct accept_cookie * C = cookie; /* Cancel the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ); /* Free the cookie. */ free(C); } spiped-1.4.1/libcperciva/events/events.c000644 001751 001751 00000010047 12403117256 021677 0ustar00cpercivacperciva000000 000000 #include #include #include #include "mpool.h" #include "events_internal.h" #include "events.h" /* Event structure. */ struct eventrec { int (*func)(void *); void * cookie; }; MPOOL(eventrec, struct eventrec, 4096); /* Zero timeval, for use with non-blocking event runs. */ static const struct timeval tv_zero = {0, 0}; /** * events_mkrec(func, cookie): * Package ${func}, ${cookie} into a struct eventrec. */ struct eventrec * events_mkrec(int (*func)(void *), void * cookie) { struct eventrec * r; /* Allocate structure. */ if ((r = mpool_eventrec_malloc()) == NULL) goto err0; /* Initialize. */ r->func = func; r->cookie = cookie; /* Success! */ return (r); err0: /* Failure! */ return (NULL); } /** * events_freerec(r): * Free the eventrec ${r}. */ void events_freerec(struct eventrec * r) { mpool_eventrec_free(r); } /* Do an event. This makes events_run cleaner. */ static inline int doevent(struct eventrec * r) { int rc; /* Invoke the callback. */ rc = (r->func)(r->cookie); /* Free the event record. */ mpool_eventrec_free(r); /* Return the status code from the callback. */ return (rc); } /** * events_run(void): * 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. */ int events_run(void) { struct eventrec * r; struct timeval * tv; struct timeval tv2; int rc = 0; /* If we have any immediate events, process them and return. */ if ((r = events_immediate_get()) != NULL) { while (r != NULL) { /* Process the event. */ if ((rc = doevent(r)) != 0) goto done; /* Get the next event. */ r = events_immediate_get(); } /* We've processed at least one event; time to return. */ goto done; } /* * Figure out the maximum duration to block, and wait up to that * duration for network events to become available. */ if (events_timer_min(&tv)) goto err0; if (events_network_select(tv)) goto err1; free(tv); /* * Check for available immediate events, network events, and timer * events, in that order of priority; exit only when no more events * are available. */ do { /* Run an immediate event, if one is available. */ if ((r = events_immediate_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Run a network event, if one is available. */ if ((r = events_network_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Check if any new network events are available. */ memcpy(&tv2, &tv_zero, sizeof(struct timeval)); if (events_network_select(&tv2)) goto err0; if ((r = events_network_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Run a timer event, if one is available. */ if (events_timer_get(&r)) goto err0; if (r != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* No events available. */ break; } while (1); done: /* Success! */ return (rc); err1: free(tv); err0: /* Failure! */ return (-1); } /** * events_spin(done): * Run events 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). */ int events_spin(int * done) { int rc = 0; /* Loop until we're done or have a non-zero status. */ while ((done[0] == 0) && (rc == 0)) { /* Run events. */ rc = events_run(); } /* Return status code. */ return (rc); } /** * events_shutdown(void): * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_shutdown(void) { events_network_shutdown(); events_timer_shutdown(); } spiped-1.4.1/libcperciva/events/events_timer.c000644 001751 001751 00000013027 12403117256 023100 0ustar00cpercivacperciva000000 000000 #include #include #include #include "monoclock.h" #include "timerqueue.h" #include "events_internal.h" #include "events.h" struct timerrec { struct eventrec * r; void * cookie; struct timeval tv_orig; }; static struct timerqueue * Q = NULL; /* Set tv := + tdelta. */ static int gettimeout(struct timeval * tv, struct timeval * tdelta) { if (monoclock_get(tv)) goto err0; tv->tv_sec += tdelta->tv_sec; if ((tv->tv_usec += tdelta->tv_usec) >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec += 1; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * 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. */ void * events_timer_register(int (*func)(void *), void * cookie, const struct timeval * timeo) { struct eventrec * r; struct timerrec * t; struct timeval tv; /* Create the timer queue if it doesn't exist yet. */ if (Q == NULL) { if ((Q = timerqueue_init()) == NULL) goto err0; } /* Bundle into an eventrec record. */ if ((r = events_mkrec(func, cookie)) == NULL) goto err0; /* Create a timer record. */ if ((t = malloc(sizeof(struct timerrec))) == NULL) goto err1; t->r = r; memcpy(&t->tv_orig, timeo, sizeof(struct timeval)); /* Compute the absolute timeout. */ if (gettimeout(&tv, &t->tv_orig)) goto err2; /* Add this to the timer queue. */ if ((t->cookie = timerqueue_add(Q, &tv, t)) == NULL) goto err2; /* Success! */ return (t); err2: free(t); err1: events_freerec(r); err0: /* Failure! */ return (NULL); } /** * 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. */ void * events_timer_register_double(int (*func)(void *), void * cookie, double timeo) { struct timeval tv; /* Convert timeo to a struct timeval. */ tv.tv_sec = timeo; tv.tv_usec = (timeo - tv.tv_sec) * 1000000.0; /* Schedule the timeout. */ return (events_timer_register(func, cookie, &tv)); } /** * events_timer_cancel(cookie): * Cancel the timer for which the cookie ${cookie} was returned by * events_timer_register. */ void events_timer_cancel(void * cookie) { struct timerrec * t = cookie; /* Remove from the timer queue. */ timerqueue_delete(Q, t->cookie); /* Free the eventrec and timer records. */ events_freerec(t->r); free(t); } /** * events_timer_reset(cookie): * Reset the timer for which the cookie ${cookie} was returned by * events_timer_register to its initial value. */ int events_timer_reset(void * cookie) { struct timerrec * t = cookie; struct timeval tv; /* Compute the new timeout. */ if (gettimeout(&tv, &t->tv_orig)) goto err0; /* Adjust the timer. */ timerqueue_increase(Q, t->cookie, &tv); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_timer_min(timeo): * Return via ${timeo} a pointer to the minimum time which must be waited * before a timer will expire; or to NULL if there are no timers. The caller * is responsible for freeing the returned pointer. */ int events_timer_min(struct timeval ** timeo) { struct timeval tnow; const struct timeval * tv; /* If we have no queue, we have no timers; return NULL. */ if (Q == NULL) { *timeo = NULL; goto done; } /* Get the minimum timer from the queue. */ tv = timerqueue_getmin(Q); /* If there are no timers, return NULL. */ if (tv == NULL) { *timeo = NULL; goto done; } /* Allocate space for holding the returned timeval. */ if ((*timeo = malloc(sizeof(struct timeval))) == NULL) goto err0; /* Get the current time... */ if (monoclock_get(&tnow)) goto err1; /* ... and compare it to the minimum timer. */ if ((tnow.tv_sec > tv->tv_sec) || ((tnow.tv_sec == tv->tv_sec) && (tnow.tv_usec > tv->tv_usec))) { /* The timer has already expired, so return zero. */ (*timeo)->tv_sec = 0; (*timeo)->tv_usec = 0; } else { /* Compute the difference. */ (*timeo)->tv_sec = tv->tv_sec - tnow.tv_sec; (*timeo)->tv_usec = tv->tv_usec - tnow.tv_usec; if (tv->tv_usec < tnow.tv_usec) { (*timeo)->tv_usec += 1000000; (*timeo)->tv_sec -= 1; } } done: /* Success! */ return (0); err1: free(*timeo); err0: /* Failure! */ return (-1); } /** * events_timer_get(r): * Return via ${r} a pointer to an eventrec structure corresponding to an * expired timer, and delete said timer; or to NULL if there are no expired * timers. The caller is responsible for freeing the returned pointer. */ int events_timer_get(struct eventrec ** r) { struct timeval tnow; struct timerrec * t; /* If we have no queue, we have no timers; return NULL. */ if (Q == NULL) { *r = NULL; goto done; } /* Get current time. */ if (monoclock_get(&tnow)) goto err0; /* Get an expired timer, if there is one. */ t = timerqueue_getptr(Q, &tnow); /* If there is an expired timer... */ if (t != NULL) { /* ... pass back the eventrec and free the timer. */ *r = t->r; free(t); } else { /* Otherwise, return NULL. */ *r = NULL; } done: /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_timer_shutdown(void): * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_timer_shutdown(void) { /* If we have a queue and it is empty, free it. */ if ((Q != NULL) && (timerqueue_getmin(Q) == NULL)) { timerqueue_free(Q); Q = NULL; } } spiped-1.4.1/libcperciva/events/events_internal.h000644 001751 001751 00000005454 12403117256 023606 0ustar00cpercivacperciva000000 000000 #ifndef _EVENTS_INTERNAL_H_ #define _EVENTS_INTERNAL_H_ #include /* Opaque event structure. */ struct eventrec; /** * events_mkrec(func, cookie): * Package ${func}, ${cookie} into a struct eventrec. */ struct eventrec * events_mkrec(int (*)(void *), void *); /** * events_freerec(r): * Free the eventrec ${r}. */ void events_freerec(struct eventrec *); /** * events_immediate_get(void): * Remove and return an eventrec structure from the immediate event queue, * or return NULL if there are no such events. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_immediate_get(void); /** * events_network_select(tv): * Check for socket readiness events, waiting up to ${tv} time if there are * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value * stored in ${tv} may be modified. */ int events_network_select(struct timeval *); /** * events_network_selectstats_startclock(void): * Start the inter-select duration clock: There is a selectable event. */ void events_network_selectstats_startclock(void); /** * events_network_selectstats_stopclock(void): * Stop the inter-select duration clock: There are no selectable events. */ void events_network_selectstats_stopclock(void); /** * events_network_selectstats_select(void): * Update inter-select duration statistics in relation to an upcoming * select(2) call. */ void events_network_selectstats_select(void); /** * events_network_get(void): * Find a socket readiness event which was identified by a previous call to * events_network_select, and return it as an eventrec structure; or return * NULL if there are no such events available. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_network_get(void); /** * events_network_shutdown(void) * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_network_shutdown(void); /** * events_timer_min(timeo): * Return via ${timeo} a pointer to the minimum time which must be waited * before a timer will expire; or to NULL if there are no timers. The caller * is responsible for freeing the returned pointer. */ int events_timer_min(struct timeval **); /** * events_timer_get(r): * Return via ${r} a pointer to an eventrec structure corresponding to an * expired timer, and delete said timer; or to NULL if there are no expired * timers. The caller is responsible for freeing the returned pointer. */ int events_timer_get(struct eventrec **); /** * events_timer_shutdown(void): * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_timer_shutdown(void); #endif /* !_EVENTS_INTERNAL_H_ */ spiped-1.4.1/libcperciva/events/events.h000644 001751 001751 00000007001 12403117256 021700 0ustar00cpercivacperciva000000 000000 #ifndef _EVENTS_H_ #define _EVENTS_H_ #include /** * 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. */ 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. */ void events_immediate_cancel(void *); /* "op" parameter to events_network_register. */ #define EVENTS_NETWORK_OP_READ 0 #define EVENTS_NETWORK_OP_WRITE 1 /** * events_network_register(func, cookie, s, op): * Register ${func}(${cookie}) to be run when socket ${s} is ready for * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for * this ${s}/${op} pair, errno will be set to EEXIST and the function will * fail. */ int events_network_register(int (*)(void *), void *, int, int); /** * events_network_cancel(s, op): * Cancel the event registered for the socket/operation pair ${s}/${op}. If * there is no such registration, errno will be set to ENOENT and the * function will fail. */ int events_network_cancel(int, int); /** * events_network_selectstats(N, mu, va, max): * Return statistics on the inter-select durations since the last time this * function was called. */ void events_network_selectstats(double *, double *, double *, double *); /** * 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. */ 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. */ 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. */ 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. */ int events_timer_reset(void *); /** * events_run(void): * 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. */ int events_run(void); /** * events_spin(done): * Run events 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). */ int events_spin(int *); /** * events_shutdown(void): * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_shutdown(void); #endif /* !_EVENTS_H_ */ spiped-1.4.1/libcperciva/events/events_network_selectstats.c000644 001751 001751 00000004146 12403117256 026071 0ustar00cpercivacperciva000000 000000 #include #include "monoclock.h" #include "events.h" #include "events_internal.h" /* Time when inter-select duration clock started. */ static struct timeval st; static int running = 0; /* Statistics on inter-select durations. */ static double N = 0.0; static double mu = 0.0; static double M2 = 0.0; static double max = 0.0; /** * events_network_selectstats_startclock(void): * Start the inter-select duration clock: There is a selectable event. */ void events_network_selectstats_startclock(void) { /* If the clock is already running, return silently. */ if (running) return; /* Get the current time; return silently on error. */ if (monoclock_get(&st)) return; /* The clock is now running. */ running = 1; } /** * events_network_selectstats_stopclock(void): * Stop the inter-select duration clock: There are no selectable events. */ void events_network_selectstats_stopclock(void) { /* The clock is no longer running. */ running = 0; } /** * events_network_selectstats_select(void): * Update inter-select duration statistics in relation to an upcoming * select(2) call. */ void events_network_selectstats_select(void) { struct timeval tnow; double t, d; /* If the clock is not running, return silently. */ if (!running) return; /* If we can't get the current time, fail silently. */ if (monoclock_get(&tnow)) goto done; /* Compute inter-select duration in seconds. */ t = (tnow.tv_sec - st.tv_sec) + (tnow.tv_usec - st.tv_usec) * 0.000001; /* Adjust statistics. We track running mean, variance * N, and max. */ N += 1.0; d = t - mu; mu += d / N; M2 += d * (t - mu); if (max < t) max = t; done: /* The clock is no longer running. */ running = 0; } /** * events_network_selectstats(N, mu, va, max): * Return statistics on the inter-select durations since the last time this * function was called. */ void events_network_selectstats(double * _N, double * _mu, double * _va, double * _max) { /* Copy statistics out. */ *_N = N; *_mu = mu; if (N > 1.0) *_va = M2 / (N - 1.0); else *_va = 0.0; *_max = max; /* Zero statistics. */ N = mu = M2 = max = 0.0; } spiped-1.4.1/libcperciva/events/events_network.c000644 001751 001751 00000016755 12403117256 023464 0ustar00cpercivacperciva000000 000000 #include #include #include #include "elasticarray.h" #include "warnp.h" #include "events_internal.h" #include "events.h" /* Structure for holding readability and writability events for a socket. */ struct socketrec { struct eventrec * reader; struct eventrec * writer; }; /* List of sockets. */ ELASTICARRAY_DECL(SOCKETLIST, socketlist, struct socketrec); static SOCKETLIST S = NULL; /* File descriptor sets containing unevented ready sockets. */ static fd_set readfds; static fd_set writefds; /* Position to which events_network_get has scanned in *fds. */ static size_t fdscanpos; /* Number of registered events. */ static size_t nev; /* Initialize the socket list if we haven't already done so. */ static int initsocketlist(void) { /* If we're already initialized, do nothing. */ if (S != NULL) goto done; /* Initialize the socket list. */ if ((S = socketlist_init(0)) == NULL) goto err0; /* There are no events registered. */ nev = 0; /* There are no unevented ready sockets. */ fdscanpos = FD_SETSIZE; done: /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Grow the socket list and initialize new records. */ static int growsocketlist(size_t nrec) { size_t i; /* Get the old size. */ i = socketlist_getsize(S); /* Grow the list. */ if (socketlist_resize(S, nrec)) goto err0; /* Initialize new members. */ for (; i < nrec; i++) { socketlist_get(S, i)->reader = NULL; socketlist_get(S, i)->writer = NULL; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_register(func, cookie, s, op): * Register ${func}(${cookie}) to be run when socket ${s} is ready for * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for * this ${s}/${op} pair, errno will be set to EEXIST and the function will * fail. */ int events_network_register(int (*func)(void *), void * cookie, int s, int op) { struct eventrec ** r; /* Initialize if necessary. */ if (initsocketlist()) goto err0; /* Sanity-check socket number. */ if ((s < 0) || (s >= (int)FD_SETSIZE)) { warn0("Invalid file descriptor for network event: %d", s); goto err0; } /* Sanity-check operation. */ if ((op != EVENTS_NETWORK_OP_READ) && (op != EVENTS_NETWORK_OP_WRITE)) { warn0("Invalid operation for network event: %d", op); goto err0; } /* Grow the array if necessary. */ if (((size_t)(s) >= socketlist_getsize(S)) && (growsocketlist(s + 1) != 0)) goto err0; /* Look up the relevant event pointer. */ if (op == EVENTS_NETWORK_OP_READ) r = &socketlist_get(S, s)->reader; else r = &socketlist_get(S, s)->writer; /* Error out if we already have an event registered. */ if (*r != NULL) { errno = EEXIST; goto err0; } /* Register the new event. */ if ((*r = events_mkrec(func, cookie)) == NULL) goto err0; /* * Increment events-registered counter; and if it was zero, start the * inter-select duration clock. */ if (nev++ == 0) events_network_selectstats_startclock(); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_cancel(s, op): * Cancel the event registered for the socket/operation pair ${s}/${op}. If * there is no such registration, errno will be set to ENOENT and the * function will fail. */ int events_network_cancel(int s, int op) { struct eventrec ** r; /* Initialize if necessary. */ if (initsocketlist()) goto err0; /* Sanity-check socket number. */ if ((s < 0) || (s >= (int)FD_SETSIZE)) { warn0("Invalid file descriptor for network event: %d", s); goto err0; } /* Sanity-check operation. */ if ((op != EVENTS_NETWORK_OP_READ) && (op != EVENTS_NETWORK_OP_WRITE)) { warn0("Invalid operation for network event: %d", op); goto err0; } /* We have no events registered beyond the end of the array. */ if ((size_t)(s) >= socketlist_getsize(S)) { errno = ENOENT; goto err0; } /* Look up the relevant event pointer. */ if (op == EVENTS_NETWORK_OP_READ) r = &socketlist_get(S, s)->reader; else r = &socketlist_get(S, s)->writer; /* Check if we have an event. */ if (*r == NULL) { errno = ENOENT; goto err0; } /* Free the event. */ events_freerec(*r); *r = NULL; /* * Since there is no longer an event registered for this socket / * operation pair, it doesn't make any sense for it to be ready. */ if (op == EVENTS_NETWORK_OP_READ) FD_CLR(s, &readfds); else FD_CLR(s, &writefds); /* * Decrement events-registered counter; and if it is becoming zero, * stop the inter-select duration clock. */ if (--nev == 0) events_network_selectstats_stopclock(); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_select(tv): * Check for socket readiness events, waiting up to ${tv} time if there are * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value * stored in ${tv} may be modified. */ int events_network_select(struct timeval * tv) { size_t i; /* Initialize if necessary. */ if (initsocketlist()) goto err0; /* Zero the fd sets... */ FD_ZERO(&readfds); FD_ZERO(&writefds); /* ... and add the ones we care about. */ for (i = 0; i < socketlist_getsize(S); i++) { if (socketlist_get(S, i)->reader) FD_SET(i, &readfds); if (socketlist_get(S, i)->writer) FD_SET(i, &writefds); } /* We're about to call select! */ events_network_selectstats_select(); /* Select. */ while (select(socketlist_getsize(S), &readfds, &writefds, NULL, tv) == -1) { /* EINTR is harmless. */ if (errno == EINTR) continue; /* Anything else is an error. */ warnp("select()"); goto err0; } /* If we have any events registered, start the clock again. */ if (nev > 0) events_network_selectstats_startclock(); /* We should start scanning for events at the beginning. */ fdscanpos = 0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_get(void): * Find a socket readiness event which was identified by a previous call to * events_network_select, and return it as an eventrec structure; or return * NULL if there are no such events available. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_network_get(void) { struct eventrec * r; size_t nfds = socketlist_getsize(S); /* We haven't found any events yet. */ r = NULL; /* Scan through the fd sets looking for ready sockets. */ for (; fdscanpos < nfds; fdscanpos++) { /* Are we ready for reading? */ if (FD_ISSET(fdscanpos, &readfds)) { r = socketlist_get(S, fdscanpos)->reader; socketlist_get(S, fdscanpos)->reader = NULL; if (--nev == 0) events_network_selectstats_stopclock(); FD_CLR(fdscanpos, &readfds); break; } /* Are we ready for writing? */ if (FD_ISSET(fdscanpos, &writefds)) { r = socketlist_get(S, fdscanpos)->writer; socketlist_get(S, fdscanpos)->writer = NULL; if (--nev == 0) events_network_selectstats_stopclock(); FD_CLR(fdscanpos, &writefds); break; } } /* Return the event we found, or NULL if we didn't find any. */ return (r); } /** * events_network_shutdown(void) * Clean up and free memory. This call is not necessary on program exit and * is only expected to be useful when checking for memory leaks. */ void events_network_shutdown(void) { /* If we're not initialized, do nothing. */ if (S == NULL) return; /* If we have any registered events, do nothing. */ if (nev > 0) return; /* Free the socket list. */ socketlist_free(S); S = NULL; } spiped-1.4.1/libcperciva/events/events_immediate.c000644 001751 001751 00000006267 12403117256 023726 0ustar00cpercivacperciva000000 000000 #include #include #include #include "mpool.h" #include "events_internal.h" #include "events.h" struct eventq { struct eventrec * r; struct eventq * next; struct eventq * prev; int prio; }; MPOOL(eventq, struct eventq, 4096); /* First nodes in the linked lists. */ static struct eventq * heads[32] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* For non-NULL heads[i], tails[i] is the last node in the list. */ static struct eventq * tails[32]; /* For i < minq, heads[i] == NULL. */ static int minq = 32; /** * 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. */ void * events_immediate_register(int (*func)(void *), void * cookie, int prio) { struct eventrec * r; struct eventq * q; /* Sanity check. */ assert((prio >= 0) && (prio < 32)); /* Bundle into an eventrec record. */ if ((r = events_mkrec(func, cookie)) == NULL) goto err0; /* Create a linked list node. */ if ((q = mpool_eventq_malloc()) == NULL) goto err1; q->r = r; q->next = NULL; q->prev = NULL; q->prio = prio; /* Add to the queue. */ if (heads[prio] == NULL) { heads[prio] = q; if (prio < minq) minq = prio; } else { tails[prio]->next = q; q->prev = tails[prio]; } tails[prio] = q; /* Success! */ return (q); err1: events_freerec(r); err0: /* Failure! */ return (NULL); } /** * events_immediate_cancel(cookie): * Cancel the immediate event for which the cookie ${cookie} was returned by * events_immediate_register. */ void events_immediate_cancel(void * cookie) { struct eventq * q = cookie; int prio = q->prio; /* If we have a predecessor, point it at our successor. */ if (q->prev != NULL) q->prev->next = q->next; else heads[prio] = q->next; /* If we have a successor, point it at our predecessor. */ if (q->next != NULL) q->next->prev = q->prev; else tails[prio] = q->prev; /* Free the eventrec. */ events_freerec(q->r); /* Return the node to the malloc pool. */ mpool_eventq_free(q); } /** * events_immediate_get(void): * Remove and return an eventrec structure from the immediate event queue, * or return NULL if there are no such events. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_immediate_get(void) { struct eventq * q; struct eventrec * r; /* Advance past priorities which have no events. */ while ((minq < 32) && (heads[minq] == NULL)) minq++; /* Are there any events? */ if (minq == 32) return (NULL); /* * Remove the first node from the highest priority non-empty linked * list. */ q = heads[minq]; heads[minq] = q->next; if (heads[minq] != NULL) heads[minq]->prev = NULL; /* Extract the eventrec. */ r = q->r; /* Return the node to the malloc pool. */ mpool_eventq_free(q); /* Return the eventrec. */ return (r); } spiped-1.4.1/libcperciva/cpusupport/cpusupport.h000644 001751 001751 00000004735 12403117256 023553 0ustar00cpercivacperciva000000 000000 #ifndef _CPUSUPPORT_H_ #define _CPUSUPPORT_H_ /* * To enable support for non-portable CPU features at compile time, one or * more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done * directly on the compiler command line; or a file can be created with the * necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h * (or similar) can be provided to include that file here. */ #ifdef CPUSUPPORT_CONFIG_FILE #include CPUSUPPORT_CONFIG_FILE #endif /* * The CPUSUPPORT_FEATURE macro declares the necessary variables and * functions for detecting CPU feature support at run time. The function * defined in the macro acts to cache the result of the ..._detect function * using the ..._present and ..._init variables. */ #define CPUSUPPORT_FEATURE(arch, feature) \ extern int cpusupport_ ## arch ## _ ## feature ## _present; \ extern int cpusupport_ ## arch ## _ ## feature ## _init; \ int cpusupport_ ## arch ## _ ## feature ## _detect(void); \ \ static inline int \ cpusupport_ ## arch ## _ ## feature(void) \ { \ \ if (cpusupport_ ## arch ## _ ## feature ## _present) \ return (1); \ else if (cpusupport_ ## arch ## _ ## feature ## _init) \ return (0); \ cpusupport_ ## arch ## _ ## feature ## _present = \ cpusupport_ ## arch ##_ ## feature ## _detect(); \ cpusupport_ ## arch ## _ ## feature ## _init = 1; \ return (cpusupport_ ## arch ## _ ## feature ## _present); \ } \ struct cpusupport_ ## arch ## _ ## feature ## _dummy /* * 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 * function body following this macro expansion must return nonzero if the * feature is present, or zero if the feature is not present or the detection * fails for any reason. */ #define CPUSUPPORT_FEATURE_DECL(arch, feature) \ int cpusupport_ ## arch ## _ ## feature ## _present = 0; \ int cpusupport_ ## arch ## _ ## feature ## _init = 0; \ int \ cpusupport_ ## arch ## _ ## feature ## _detect(void) /* * Any features listed here must have associated C files compiled and linked * in, since the macro references symbols which must be defined. Projects * which do not need to detect certain CPU features may wish to remove lines * from this list so that the associated C files can be omitted. */ CPUSUPPORT_FEATURE(x86, aesni); #endif /* !_CPUSUPPORT_H_ */ spiped-1.4.1/libcperciva/cpusupport/Build/000755 001751 001751 00000000000 12403117256 022204 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/libcperciva/cpusupport/cpusupport_x86_aesni.c000644 001751 001751 00000001076 12403117256 025425 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #endif #define CPUID_AESNI_BIT (1 << 25) CPUSUPPORT_FEATURE_DECL(x86, aesni) { #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 (ecx & CPUID_AESNI_BIT); unsupported: #endif return (0); } spiped-1.4.1/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c000644 001751 001751 00000000304 12403117256 026011 0ustar00cpercivacperciva000000 000000 #include static char a[16]; int main(void) { __m128i x, y; x = _mm_loadu_si128((__m128i *)a); y = _mm_aesenc_si128(x, x); _mm_storeu_si128((__m128i *)a, y); return (a[0]); } spiped-1.4.1/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c000644 001751 001751 00000000152 12403117256 026017 0ustar00cpercivacperciva000000 000000 #include int main(void) { unsigned int a, b, c, d; return __get_cpuid(0, &a, &b, &c, &d); } spiped-1.4.1/libcperciva/cpusupport/Build/cpusupport.sh000755 001751 001751 00000002015 12403117256 024765 0ustar00cpercivacperciva000000 000000 # Should be sourced by `command -p sh mk-h.sh` from within a Makefile # 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. feature() { ARCH=$1 FEATURE=$2 shift 2; printf "Checking if compiler supports $ARCH $FEATURE feature..." 1>&2 for CFLAG in "$@"; do if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L ${CFLAG} \ cpusupport-$ARCH-$FEATURE.c 2>/dev/null; then rm -f a.out break; fi CFLAG=NOTSUPPORTED; done case $CFLAG in NOTSUPPORTED) echo " no" 1>&2 ;; "") echo " yes" 1>&2 echo "#define CPUSUPPORT_${ARCH}_${FEATURE}" ;; *) echo " yes, via $CFLAG" 1>&2 echo "#define CPUSUPPORT_${ARCH}_${FEATURE}" echo "#ifdef cpusupport_dummy" echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CFLAG}\"" echo "#endif" ;; esac } feature X86 CPUID "" feature X86 AESNI "" "-maes" "-maes -Wno-cast-align" "-maes -Wno-missing-prototypes -Wno-cast-qual" spiped-1.4.1/libcperciva/alg/sha256.h000644 001751 001751 00000005323 12403117256 020650 0ustar00cpercivacperciva000000 000000 #ifndef _SHA256_H_ #define _SHA256_H_ #include #include /* * Use #defines in order to avoid namespace collisions with anyone else's * SHA256 code (e.g., the code in OpenSSL). */ #define SHA256_Init libcperciva_SHA256_Init #define SHA256_Update libcperciva_SHA256_Update #define SHA256_Final libcperciva_SHA256_Final #define SHA256_Buf libcperciva_SHA256_Buf #define SHA256_CTX libcperciva_SHA256_CTX #define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init #define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update #define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final #define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf #define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX /* Context structure for SHA256 operations. */ typedef struct { uint32_t state[8]; uint64_t count; uint8_t buf[64]; } SHA256_CTX; /** * SHA256_Init(ctx): * Initialize the SHA256 context ${ctx}. */ void SHA256_Init(SHA256_CTX *); /** * SHA256_Update(ctx, in, len): * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. */ void SHA256_Update(SHA256_CTX *, const void *, size_t); /** * SHA256_Final(digest, ctx): * Output the SHA256 hash of the data input to the context ${ctx} into the * buffer ${digest}. */ void SHA256_Final(uint8_t[32], SHA256_CTX *); /** * SHA256_Buf(in, len, digest): * Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}. */ void SHA256_Buf(const void *, size_t, uint8_t[32]); /* Context structure for HMAC-SHA256 operations. */ typedef struct { SHA256_CTX ictx; SHA256_CTX octx; } HMAC_SHA256_CTX; /** * HMAC_SHA256_Init(ctx, K, Klen): * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from * ${K}. */ void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); /** * HMAC_SHA256_Update(ctx, in, len): * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. */ void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); /** * HMAC_SHA256_Final(digest, ctx): * Output the HMAC-SHA256 of the data input to the context ${ctx} into the * buffer ${digest}. */ void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *); /** * HMAC_SHA256_Buf(K, Klen, in, len, digest): * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of * length ${Klen}, and write the result to ${digest}. */ void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]); /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, uint8_t *, size_t); #endif /* !_SHA256_H_ */ spiped-1.4.1/libcperciva/alg/sha256.c000644 001751 001751 00000025261 12403117256 020646 0ustar00cpercivacperciva000000 000000 #include #include #include #include "insecure_memzero.h" #include "sysendian.h" #include "sha256.h" /* * Encode a length len/4 vector of (uint32_t) into a length len vector of * (uint8_t) in big-endian form. Assumes len is a multiple of 4. */ static void be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len) { size_t i; /* Sanity-check. */ assert(len % 4 == 0); /* Encode vector, one word at a time. */ for (i = 0; i < len / 4; i++) be32enc(dst + i * 4, src[i]); } /* * Decode a big-endian length len vector of (uint8_t) into a length * len/4 vector of (uint32_t). Assumes len is a multiple of 4. */ static void be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len) { size_t i; /* Sanity-check. */ assert(len % 4 == 0); /* Decode vector, one word at a time. */ for (i = 0; i < len / 4; i++) dst[i] = be32dec(src + i * 4); } /* 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 SHR(x, n) (x >> n) #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)) #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) /* SHA256 round function */ #define RND(a, b, c, d, e, f, g, h, k) \ t0 = h + S1(e) + Ch(e, f, g) + k; \ t1 = S0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; /* Adjusted round function for rotating state */ #define RNDr(S, W, i, k) \ RND(S[(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] + k) /* * SHA256 block compression function. The 256-bit state is transformed via * the 512-bit input block to produce a new state. */ static void SHA256_Transform(uint32_t * state, const uint8_t block[64]) { uint32_t W[64]; uint32_t S[8]; uint32_t t0, t1; int i; /* 1. Prepare message schedule W. */ be32dec_vect(W, block, 64); for (i = 16; i < 64; i++) W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; /* 2. Initialize working variables. */ memcpy(S, state, 32); /* 3. Mix. */ RNDr(S, W, 0, 0x428a2f98); RNDr(S, W, 1, 0x71374491); RNDr(S, W, 2, 0xb5c0fbcf); RNDr(S, W, 3, 0xe9b5dba5); RNDr(S, W, 4, 0x3956c25b); RNDr(S, W, 5, 0x59f111f1); RNDr(S, W, 6, 0x923f82a4); RNDr(S, W, 7, 0xab1c5ed5); RNDr(S, W, 8, 0xd807aa98); RNDr(S, W, 9, 0x12835b01); RNDr(S, W, 10, 0x243185be); RNDr(S, W, 11, 0x550c7dc3); RNDr(S, W, 12, 0x72be5d74); RNDr(S, W, 13, 0x80deb1fe); RNDr(S, W, 14, 0x9bdc06a7); RNDr(S, W, 15, 0xc19bf174); RNDr(S, W, 16, 0xe49b69c1); RNDr(S, W, 17, 0xefbe4786); RNDr(S, W, 18, 0x0fc19dc6); RNDr(S, W, 19, 0x240ca1cc); RNDr(S, W, 20, 0x2de92c6f); RNDr(S, W, 21, 0x4a7484aa); RNDr(S, W, 22, 0x5cb0a9dc); RNDr(S, W, 23, 0x76f988da); RNDr(S, W, 24, 0x983e5152); RNDr(S, W, 25, 0xa831c66d); RNDr(S, W, 26, 0xb00327c8); RNDr(S, W, 27, 0xbf597fc7); RNDr(S, W, 28, 0xc6e00bf3); RNDr(S, W, 29, 0xd5a79147); RNDr(S, W, 30, 0x06ca6351); RNDr(S, W, 31, 0x14292967); RNDr(S, W, 32, 0x27b70a85); RNDr(S, W, 33, 0x2e1b2138); RNDr(S, W, 34, 0x4d2c6dfc); RNDr(S, W, 35, 0x53380d13); RNDr(S, W, 36, 0x650a7354); RNDr(S, W, 37, 0x766a0abb); RNDr(S, W, 38, 0x81c2c92e); RNDr(S, W, 39, 0x92722c85); RNDr(S, W, 40, 0xa2bfe8a1); RNDr(S, W, 41, 0xa81a664b); RNDr(S, W, 42, 0xc24b8b70); RNDr(S, W, 43, 0xc76c51a3); RNDr(S, W, 44, 0xd192e819); RNDr(S, W, 45, 0xd6990624); RNDr(S, W, 46, 0xf40e3585); RNDr(S, W, 47, 0x106aa070); RNDr(S, W, 48, 0x19a4c116); RNDr(S, W, 49, 0x1e376c08); RNDr(S, W, 50, 0x2748774c); RNDr(S, W, 51, 0x34b0bcb5); RNDr(S, W, 52, 0x391c0cb3); RNDr(S, W, 53, 0x4ed8aa4a); RNDr(S, W, 54, 0x5b9cca4f); RNDr(S, W, 55, 0x682e6ff3); RNDr(S, W, 56, 0x748f82ee); RNDr(S, W, 57, 0x78a5636f); RNDr(S, W, 58, 0x84c87814); RNDr(S, W, 59, 0x8cc70208); RNDr(S, W, 60, 0x90befffa); RNDr(S, W, 61, 0xa4506ceb); RNDr(S, W, 62, 0xbef9a3f7); RNDr(S, W, 63, 0xc67178f2); /* 4. Mix local working variables into global state. */ for (i = 0; i < 8; i++) state[i] += S[i]; /* Clean the stack. */ insecure_memzero(W, 256); insecure_memzero(S, 32); insecure_memzero(&t0, sizeof(uint32_t)); insecure_memzero(&t1, sizeof(uint32_t)); } static uint8_t PAD[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* Add padding and terminating bit-count. */ static void SHA256_Pad(SHA256_CTX * ctx) { uint8_t len[8]; uint32_t r, plen; /* * Convert length to a vector of bytes -- we do this now rather * than later because the length will change after we pad. */ be64enc(len, ctx->count); /* Add 1--64 bytes so that the resulting length is 56 mod 64. */ r = (ctx->count >> 3) & 0x3f; plen = (r < 56) ? (56 - r) : (120 - r); SHA256_Update(ctx, PAD, (size_t)plen); /* Add the terminating bit-count. */ SHA256_Update(ctx, len, 8); } /* Magic initialization constants. */ static const uint32_t initstate[8] = { 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 }; /** * SHA256_Init(ctx): * Initialize the SHA256 context ${ctx}. */ void SHA256_Init(SHA256_CTX * ctx) { /* Zero bits processed so far. */ ctx->count = 0; /* Initialize state. */ memcpy(ctx->state, initstate, sizeof(initstate)); } /** * SHA256_Update(ctx, in, len): * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. */ void SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len) { uint32_t r; const uint8_t * src = in; /* Return immediately if we have nothing to do. */ if (len == 0) return; /* Number of bytes left in the buffer from previous updates. */ r = (ctx->count >> 3) & 0x3f; /* Update number of bits. */ ctx->count += (uint64_t)(len) << 3; /* Handle the case where we don't need to perform any transforms. */ if (len < 64 - r) { memcpy(&ctx->buf[r], src, len); return; } /* Finish the current block. */ memcpy(&ctx->buf[r], src, 64 - r); SHA256_Transform(ctx->state, ctx->buf); src += 64 - r; len -= 64 - r; /* Perform complete blocks. */ while (len >= 64) { SHA256_Transform(ctx->state, src); src += 64; len -= 64; } /* Copy left over data into buffer. */ memcpy(ctx->buf, src, len); } /** * SHA256_Final(digest, ctx): * Output the SHA256 hash of the data input to the context ${ctx} into the * buffer ${digest}. */ void SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx) { /* Add padding. */ SHA256_Pad(ctx); /* Write the hash. */ be32enc_vect(digest, ctx->state, 32); /* Clear the context state. */ insecure_memzero(ctx, sizeof(SHA256_CTX)); } /** * SHA256_Buf(in, len, digest): * Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}. */ void SHA256_Buf(const void * in, size_t len, uint8_t digest[32]) { SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, in, len); SHA256_Final(digest, &ctx); } /** * HMAC_SHA256_Init(ctx, K, Klen): * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from * ${K}. */ void HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) { uint8_t pad[64]; uint8_t khash[32]; const uint8_t * K = _K; size_t i; /* If Klen > 64, the key is really SHA256(K). */ if (Klen > 64) { SHA256_Init(&ctx->ictx); SHA256_Update(&ctx->ictx, K, Klen); SHA256_Final(khash, &ctx->ictx); K = khash; Klen = 32; } /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ SHA256_Init(&ctx->ictx); memset(pad, 0x36, 64); for (i = 0; i < Klen; i++) pad[i] ^= K[i]; SHA256_Update(&ctx->ictx, pad, 64); /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ SHA256_Init(&ctx->octx); memset(pad, 0x5c, 64); for (i = 0; i < Klen; i++) pad[i] ^= K[i]; SHA256_Update(&ctx->octx, pad, 64); /* Clean the stack. */ insecure_memzero(khash, 32); insecure_memzero(pad, 64); } /** * HMAC_SHA256_Update(ctx, in, len): * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. */ void HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len) { /* Feed data to the inner SHA256 operation. */ SHA256_Update(&ctx->ictx, in, len); } /** * HMAC_SHA256_Final(digest, ctx): * Output the HMAC-SHA256 of the data input to the context ${ctx} into the * buffer ${digest}. */ void HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx) { uint8_t ihash[32]; /* Finish the inner SHA256 operation. */ SHA256_Final(ihash, &ctx->ictx); /* Feed the inner hash to the outer SHA256 operation. */ SHA256_Update(&ctx->octx, ihash, 32); /* Finish the outer SHA256 operation. */ SHA256_Final(digest, &ctx->octx); /* Clean the stack. */ insecure_memzero(ihash, 32); } /** * HMAC_SHA256_Buf(K, Klen, in, len, digest): * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of * length ${Klen}, and write the result to ${digest}. */ void HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len, uint8_t digest[32]) { HMAC_SHA256_CTX ctx; HMAC_SHA256_Init(&ctx, K, Klen); HMAC_SHA256_Update(&ctx, in, len); HMAC_SHA256_Final(digest, &ctx); } /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ void PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) { HMAC_SHA256_CTX PShctx, hctx; size_t i; uint8_t ivec[4]; uint8_t U[32]; uint8_t T[32]; uint64_t j; int k; size_t clen; /* Sanity-check. */ assert(dkLen <= 32 * (size_t)(UINT32_MAX)); /* Compute HMAC state after processing P and S. */ HMAC_SHA256_Init(&PShctx, passwd, passwdlen); HMAC_SHA256_Update(&PShctx, salt, saltlen); /* Iterate through the blocks. */ for (i = 0; i * 32 < dkLen; i++) { /* Generate INT(i + 1). */ be32enc(ivec, (uint32_t)(i + 1)); /* Compute U_1 = PRF(P, S || INT(i)). */ memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); HMAC_SHA256_Update(&hctx, ivec, 4); HMAC_SHA256_Final(U, &hctx); /* T_i = U_1 ... */ memcpy(T, U, 32); for (j = 2; j <= c; j++) { /* Compute U_j. */ HMAC_SHA256_Init(&hctx, passwd, passwdlen); HMAC_SHA256_Update(&hctx, U, 32); HMAC_SHA256_Final(U, &hctx); /* ... xor U_j ... */ for (k = 0; k < 32; k++) T[k] ^= U[k]; } /* Copy as many bytes as necessary into buf. */ clen = dkLen - i * 32; if (clen > 32) clen = 32; memcpy(&buf[i * 32], T, clen); } /* Clean PShctx, since we never called _Final on it. */ insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX)); } spiped-1.4.1/lib/dnsthread/000755 001751 001751 00000000000 12403117256 017160 5ustar00cpercivacperciva000000 000000 spiped-1.4.1/lib/dnsthread/dnsthread.h000644 001751 001751 00000002667 12403117256 021320 0ustar00cpercivacperciva000000 000000 #ifndef _DNSTHREAD_H_ #define _DNSTHREAD_H_ /* Opaque address structure. */ struct sock_addr; /* Opaque thread token. */ typedef struct dnsthread_internal * DNSTHREAD; /** * dnsthread_spawn(void): * Spawn a thread for performing address resolution. Return a token which can * 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, fail with * EALREADY. Upon completion, invoke ${callback}(${cookie}, sas), where * ${sas} is a NULL-terminated array of pointers to sock_addr structures or * NULL on resolution failure. */ int dnsthread_resolveone(DNSTHREAD, const char *, int (*)(void *, struct sock_addr **), void *); /** * dnsthread_kill(T): * Instruct an address resolution thread to die. If the thread does not have * an address resolution operation currently pending, wait for the thread to * die before returning. */ int dnsthread_kill(DNSTHREAD); /** * dnsthread_resolve(addr, callback, cookie): * Perform a non-blocking address resolution of ${addr}. This function may * spawn a thread internally. */ int dnsthread_resolve(const char *, int (*)(void *, struct sock_addr **), void *); #endif /* !_DNSTHREAD_H_ */ spiped-1.4.1/lib/dnsthread/dnsthread.c000644 001751 001751 00000024664 12403117256 021314 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "events.h" #include "noeintr.h" #include "sock.h" #include "warnp.h" #include "dnsthread.h" /* Thread management structure. */ struct dnsthread_internal { /* Threading glue. */ pthread_t thr; /* Thread ID. */ pthread_mutex_t mtx; /* Controls access to this structure. */ pthread_cond_t cv; /* Thread sleeps on this. */ /* State management. */ int state; /* THREAD_* as below. */ int wakeupsock[2]; /* Writes to [0], reads from [1]. */ /* Address resolution variables. */ char * addr; /* Address to be resolved. */ struct sock_addr ** sas; /* Results. */ int res_errno; /* Errno to be passed back on failure. */ /* Callback to occur when resolution is complete. */ int (*callback)(void *, struct sock_addr **); /* Callback. */ void * cookie; /* Cookie. */ }; /* Cookie used by dnsthread_resolve. */ struct resolve_cookie { int (*callback)(void *, struct sock_addr **); void * cookie; DNSTHREAD T; }; /* * Thread states. _resolveone moves the thread from SLEEPING to HASWORK; * workthread moves the thread from HASWORK to SLEEPING; and _kill moves the * thread from either state to SUICIDE. */ #define THREAD_SLEEPING 0 #define THREAD_HASWORK 1 #define THREAD_SUICIDE 2 /* Callback functions used below. */ static int callback_resolveone(void * cookie); static int callback_resolve(void *, struct sock_addr **); /* Address resolution thread. */ static void * workthread(void * cookie) { struct dnsthread_internal * T = cookie; char * addr; struct sock_addr ** sas; int res_errno = 0; int rc; uint8_t zero = 0; /* Grab the mutex. */ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); exit(1); } /* Infinite loop doing work until told to suicide. */ do { /* * Sleep on the condition variable as long as we're in the * SLEEPING state. */ while (T->state == THREAD_SLEEPING) { /* Sleep until we're woken up. */ if ((rc = pthread_cond_wait(&T->cv, &T->mtx)) != 0) { warn0("pthread_cond_wait: %s", strerror(rc)); exit(1); } } /* If we need to kill ourself, stop looping. */ if (T->state == THREAD_SUICIDE) break; /* Grab the work. */ addr = T->addr; /* Release the mutex. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); exit(1); } /* Perform the address resolution. */ if ((sas = sock_resolve(addr)) == NULL) res_errno = errno; /* Grab the mutex again. */ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); exit(1); } /* Write the answer back. */ T->sas = sas; T->res_errno = res_errno; /* Send a completion message. */ if (noeintr_write(T->wakeupsock[0], &zero, 1) != 1) { warnp("Error writing to wakeup socket"); exit(1); } /* Return to sleeping, unless we were instructed to die. */ if (T->state != THREAD_SUICIDE) T->state = THREAD_SLEEPING; } while (1); /* Close the socket pair. */ close(T->wakeupsock[1]); close(T->wakeupsock[0]); /* Destroy the condition variable. */ if ((rc = pthread_cond_destroy(&T->cv)) != 0) { warn0("pthread_cond_destroy: %s", strerror(rc)); exit(1); } /* Release the mutex. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); exit(1); } /* Destroy the mutex. */ if ((rc = pthread_mutex_destroy(&T->mtx)) != 0) { warn0("pthread_mutex_destroy: %s", strerror(rc)); exit(1); } /* Free the control structure. */ free(T); /* Successful thread termination. */ return (NULL); } /** * dnsthread_spawn(void): * Spawn a thread for performing address resolution. Return a token which can * be passed to dnsthread_resolveone and dnsthread_kill. */ DNSTHREAD dnsthread_spawn(void) { struct dnsthread_internal * T; int rc; /* Allocate a thread management structure. */ if ((T = malloc(sizeof(struct dnsthread_internal))) == NULL) goto err0; /* Create and lock a mutex. */ if ((rc = pthread_mutex_init(&T->mtx, NULL)) != 0) { warn0("pthread_mutex_init: %s", strerror(rc)); goto err1; } if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); goto err2; } /* Create state-changed condition variable. */ if ((rc = pthread_cond_init(&T->cv, NULL)) != 0) { warn0("pthread_cond_init: %s", strerror(rc)); goto err3; } /* Create wakeup socketpair. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, T->wakeupsock)) { warnp("socketpair"); goto err4; } /* The thread starts out sleeping. */ T->state = THREAD_SLEEPING; /* Create the thread. */ if ((rc = pthread_create(&T->thr, NULL, workthread, T)) != 0) { warn0("pthread_create: %s", strerror(rc)); goto err5; } /* Unlock the mutex. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); goto err0; } /* Success! */ return (T); err5: close(T->wakeupsock[1]); close(T->wakeupsock[0]); err4: pthread_cond_destroy(&T->cv); err3: pthread_mutex_unlock(&T->mtx); err2: pthread_mutex_destroy(&T->mtx); err1: free(T); err0: /* Failure! */ return (NULL); } /** * 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 * 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 * resolution failure. */ int dnsthread_resolveone(DNSTHREAD T, const char * addr, int (* callback)(void *, struct sock_addr **), void * cookie) { int err = 0; int rc; /* Grab the mutex. */ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); goto err0; } /* If the resolver is already busy, fail. */ if (T->state == THREAD_HASWORK) { err = EALREADY; goto ealready; } /* Duplicate the address to be resolved. */ if ((T->addr = strdup(addr)) == NULL) goto err1; /* Remember what callback we'll need to do eventually. */ T->callback = callback; T->cookie = cookie; /* There is now work for the thread to do. */ T->state = THREAD_HASWORK; /* Wake up the worker thread. */ if ((rc = pthread_cond_signal(&T->cv)) != 0) { warn0("pthread_cond_signal: %s", strerror(rc)); goto err1; } /* We want a callback when the worker thread pokes us. */ if (events_network_register(callback_resolveone, T, T->wakeupsock[1], EVENTS_NETWORK_OP_READ)) { warnp("Error registering wakeup listener"); goto err1; } ealready: /* Release the mutex. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); goto err0; } /* If err was set earlier, store the value in errno. */ if (err) errno = err; /* Success! */ return (0); err1: pthread_mutex_unlock(&T->mtx); err0: /* Failure! */ return (-1); } /* Callback for dnsthread_resolveone, from wakeup socket. */ static int callback_resolveone(void * cookie) { struct dnsthread_internal * T = cookie; struct sock_addr ** sas; uint8_t zero; int res_errno = 0; int (*callback)(void *, struct sock_addr **); void * cb_cookie; int rc; /* Drain the byte from the socketpair. */ if (read(T->wakeupsock[1], &zero, 1) != 1) { warn0("Error reading from wakeup socket"); goto err0; } /* Grab the mutex. */ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); goto err0; } /* Free the (strduped) address which was to be resolved. */ free(T->addr); /* Grab the result. */ sas = T->sas; res_errno = T->res_errno; /* Grab the callback. */ callback = T->callback; cb_cookie = T->cookie; /* Release the mutex. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); goto err0; } /* Perform the callback. */ if (sas == NULL) errno = res_errno; return ((callback)(cb_cookie, sas)); err0: /* Failure! */ return (-1); } /** * dnsthread_kill(T): * Instruct an address resolution thread to die. If the thread does not have * an address resolution operation currently pending, wait for the thread to * die before returning. */ int dnsthread_kill(DNSTHREAD T) { int rc; int ostate; pthread_t thr; /* Lock the control structure. */ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) { warn0("pthread_mutex_lock: %s", strerror(rc)); goto err0; } /* Remember what state the thread is currently in. */ ostate = T->state; /* Grab the thread ID. */ thr = T->thr; /* Tell the thread to die, and wake it up. */ T->state = THREAD_SUICIDE; if ((rc = pthread_cond_signal(&T->cv)) != 0) { warn0("pthread_cond_signal: %s", strerror(rc)); goto err1; } /* Unlock the control structure. */ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) { warn0("pthread_mutex_unlock: %s", strerror(rc)); goto err0; } /* If the thread was sleeping, wait for it to wake up and die. */ if (ostate == THREAD_SLEEPING) { if ((rc = pthread_join(thr, NULL)) != 0) { warn0("pthread_join: %s", strerror(rc)); goto err0; } } /* Success! */ return (0); err1: pthread_mutex_unlock(&T->mtx); err0: /* Failure! */ return (-1); } /** * dnsthread_resolve(addr, callback, cookie): * Perform a non-blocking address resolution of ${addr}. This function may * spawn a thread internally. */ int dnsthread_resolve(const char * addr, int (* callback)(void *, struct sock_addr **), void * cookie) { struct resolve_cookie * R; /* Bake a cookie. */ if ((R = malloc(sizeof(struct resolve_cookie))) == NULL) goto err0; R->callback = callback; R->cookie = cookie; /* Spawn a thread. */ if ((R->T = dnsthread_spawn()) == NULL) goto err1; /* Launch the request. */ if (dnsthread_resolveone(R->T, addr, callback_resolve, R)) goto err2; /* Success! */ return (0); err2: dnsthread_kill(R->T); err1: free(R); err0: /* Failure! */ return (-1); } /* Callback for dnsthread_resolve, from dnsthread_resolveone. */ static int callback_resolve(void * cookie, struct sock_addr ** sas) { struct resolve_cookie * R = cookie; int rc; /* Invoke the upstream callback. */ rc = (R->callback)(R->cookie, sas); /* Kill the resolver thread. */ if (dnsthread_kill(R->T)) rc = -1; /* Free our cookie. */ free(R); /* Return upstream return code or failure. */ return (rc); } spiped-1.4.1/POSIX/README000644 001751 001751 00000000775 12403117255 016230 0ustar00cpercivacperciva000000 000000 POSIX compatibility code ------------------------ This code exists to work around some common POSIX compatibility issues. POSIX specifies that if the first line of a Makefile is ".POSIX:" then the Makefile should be processed according to POSIX rules, including with CC=c99. Further, c99 is required to understand the -lrt and -lxnet options (and ignore them if the routines they specify linkage for are already in the standard C library). Unfortunately some systems fail or one or both of these accounts. spiped-1.4.1/POSIX/posix-clock_realtime.c000644 001751 001751 00000000067 12403117255 021623 0ustar00cpercivacperciva000000 000000 #include int main() {return CLOCK_REALTIME;} spiped-1.4.1/POSIX/posix-msg_nosignal.c000644 001751 001751 00000000073 12403117256 021324 0ustar00cpercivacperciva000000 000000 #include int main() {return MSG_NOSIGNAL;} spiped-1.4.1/POSIX/posix-l.sh000755 001751 001751 00000000545 12403117256 017276 0ustar00cpercivacperciva000000 000000 # Should be sourced by `command -p sh posix-l.sh` from within a Makefile. FIRST=YES for LIB in rt xnet; do if ${CC} -l${LIB} posix-l.c 2>/dev/null; then if [ ${FIRST} = "NO" ]; then printf " "; fi printf "%s" "-l${LIB}"; FIRST=NO; else echo "WARNING: POSIX violation: make's CC doesn't understand -l${LIB}" >/dev/stderr fi rm -f a.out done spiped-1.4.1/POSIX/posix-cflags.sh000755 001751 001751 00000000765 12403117256 020306 0ustar00cpercivacperciva000000 000000 # Should be sourced by `command -p sh posix-cflags.sh` from within a Makefile if ! ${CC} -D_POSIX_C_SOURCE=200809L posix-msg_nosignal.c 2>/dev/null; then printf %s "-DPOSIXFAIL_MSG_NOSIGNAL " echo "WARNING: POSIX violation: not defining MSG_NOSIGNAL" >/dev/stderr fi if ! ${CC} -D_POSIX_C_SOURCE=200809L posix-clock_realtime.c 2>/dev/null; then printf %s "-DPOSIXFAIL_CLOCK_REALTIME" echo "WARNING: POSIX violation: not defining CLOCK_REALTIME" >/dev/stderr fi rm -f a.out spiped-1.4.1/POSIX/posix-l.c000644 001751 001751 00000000027 12403117256 017076 0ustar00cpercivacperciva000000 000000 int main() {return 0;} spiped-1.4.1/spipe/spipe.1000644 001751 001751 00000004352 12403117255 016763 0ustar00cpercivacperciva000000 000000 .\"- .\" Copyright (c) 2012 Andreas Olsson .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .TH SPIPE 1 "April 2, 2013" "spiped 1.3.0" "spipe README" .SH NAME spipe \- spiped client utility .SH SYNOPSIS .B spipe \-t \-k [\-f | \-g] [\-j] [\-o ] .SH OPTIONS .TP .B \-t Address to which spipe should connect. .TP .B \-k Use the provided key file to authenticate and encrypt. .TP .B \-f Use fast/weak handshaking: This reduces the CPU time spent in the initial connection setup, at the expense of losing perfect forward secrecy. .TP .B \-g Require perfect forward secrecy by dropping connections if the other host is using the -f option. .TP .B \-j Disable transport layer keep-alives. (By default they are enabled.) .TP .B \-o Timeout, in seconds, after which an attempt to connect to the target or a protocol handshake will be aborted (and the connection dropped) if not completed. Defaults to 5s. .SH SEE ALSO .BR spiped (1). spiped-1.4.1/spipe/pushbits.c000644 001751 001751 00000003300 12403117255 017556 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "noeintr.h" #include "warnp.h" #include "pushbits.h" struct push { uint8_t buf[BUFSIZ]; int in; int out; }; /* Bit-pushing thread. */ static void * workthread(void * cookie) { struct push * P = cookie; ssize_t readlen; /* Infinite loop unless we hit EOF or an error. */ do { /* Read data and die on error. */ if ((readlen = read(P->in, P->buf, BUFSIZ)) == -1) { if (errno == EINTR) continue; warnp("Error reading"); exit(1); } /* If we hit EOF, exit the loop. */ if (readlen == 0) break; /* Write the data back out. */ if (noeintr_write(P->out, &P->buf, readlen) != readlen) { warnp("Error writing"); exit(1); } } while (1); /* Close the descriptor we hit EOF on. */ close(P->in); /* * Try to shut down the descriptor we're writing to. Ignore ENOTSOCK, * since it might, indeed, not be a socket. */ if (shutdown(P->out, SHUT_WR)) { if (errno != ENOTSOCK) { warnp("Error shutting down socket"); exit(1); } } /* Free our parameters. */ free(P); /* We're done. */ return (NULL); } /** * pushbits(in, out): * Create a thread which copies data from ${in} to ${out}. */ int pushbits(int in, int out) { struct push * P; pthread_t thr; int rc; /* Allocate structure. */ if ((P = malloc(sizeof(struct push))) == NULL) goto err0; P->in = in; P->out = out; /* Create thread. */ if ((rc = pthread_create(&thr, NULL, workthread, P)) != 0) { warn0("pthread_create: %s", strerror(rc)); goto err1; } /* Success! */ return (0); err1: free(P); err0: /* Failure! */ return (-1); } spiped-1.4.1/spipe/main.c000644 001751 001751 00000006543 12403117255 016655 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include "asprintf.h" #include "events.h" #include "sha256.h" #include "sock.h" #include "warnp.h" #include "proto_conn.h" #include "proto_crypt.h" #include "pushbits.h" static int callback_conndied(void * cookie) { (void)cookie; /* UNUSED */ /* We're done! */ exit(0); } static void usage(void) { fprintf(stderr, "usage: spipe -t -k " " [-f | -g] [-j] [-o ]\n"); exit(1); } /* Simplify error-handling in command-line parse loop. */ #define OPT_EPARSE(opt, arg) do { \ warnp("Error parsing argument: -%c %s", opt, arg); \ exit(1); \ } while (0) int main(int argc, char * argv[]) { /* Command-line parameters. */ int opt_f = 0; int opt_g = 0; int opt_j = 0; const char * opt_k = NULL; double opt_o = 0.0; const char * opt_t = NULL; /* Working variables. */ struct sock_addr ** sas_t; struct proto_secret * K; int ch; int s[2]; WARNP_INIT; /* Parse the command line. */ while ((ch = getopt(argc, argv, "fgjk:o:t:")) != -1) { switch (ch) { case 'f': if (opt_f) usage(); opt_f = 1; break; case 'g': if (opt_g) usage(); opt_g = 1; break; case 'j': if (opt_j) usage(); opt_j = 1; break; case 'k': if (opt_k) usage(); opt_k = optarg; break; case 'o': if (opt_o != 0.0) usage(); if ((opt_o = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -o %s", optarg); exit(1); } break; case 't': if (opt_t) usage(); opt_t = optarg; break; default: usage(); } } /* We should have processed all the arguments. */ if (argc != optind) usage(); /* Set defaults. */ if (opt_o == 0.0) opt_o = 5.0; /* Sanity-check options. */ if (opt_f && opt_g) usage(); if (opt_k == NULL) usage(); if (!(opt_o > 0.0)) usage(); if (opt_t == NULL) usage(); /* Resolve target address. */ if ((sas_t = sock_resolve(opt_t)) == NULL) { warnp("Error resolving socket address: %s", opt_t); exit(1); } if (sas_t[0] == NULL) { warn0("No addresses found for %s", opt_t); exit(1); } /* Load the keying data. */ if ((K = proto_crypt_secret(opt_k)) == NULL) { warnp("Error reading shared secret"); exit(1); } /* * Create a socket pair to push bits through. The spiped protocol * code expects to be handed a socket to read/write bits to, and our * stdin/stdout might not be sockets (in fact, almost certainly aren't * sockets); so we'll hand one end of the socket pair to the spiped * protocol code and shuttle bits between stdin/stdout and the other * end of the socket pair ourselves. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, s)) { warnp("socketpair"); exit(1); } /* Set up a connection. */ if (proto_conn_create(s[1], sas_t, 0, opt_f, opt_g, opt_j, K, opt_o, callback_conndied, NULL)) { warnp("Could not set up connection"); exit(1); } /* Push bits from stdin into the socket. */ if (pushbits(STDIN_FILENO, s[0]) || pushbits(s[0], STDOUT_FILENO)) { warnp("Could not push bits"); exit(1); } /* Loop until we die. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (1); /* NOTREACHED */ /* * If we could reach this point, we would free memory, close sockets, * and otherwise clean up here. */ } spiped-1.4.1/spipe/pushbits.h000644 001751 001751 00000000270 12403117255 017566 0ustar00cpercivacperciva000000 000000 #ifndef _PUSHBITS_H_ #define _PUSHBITS_H_ /** * pushbits(in, out): * Create a thread which copies data from ${in} to ${out}. */ int pushbits(int, int); #endif /* !_PUSHBITS_H_ */ spiped-1.4.1/spipe/README000644 001751 001751 00000001442 12403117255 016436 0ustar00cpercivacperciva000000 000000 spipe usage =========== usage: spipe -t -k [-f | -g] [-j] [-o ] Options: -t Address to which spipe should connect. -k Use the provided key file to authenticate and encrypt. -f Use fast/weak handshaking: This reduces the CPU time spent in the initial connection setup, at the expense of losing perfect forward secrecy. -g Require perfect forward secrecy by dropping connections if the other host is using the -f option. -j Disable transport layer keep-alives. (By default they are enabled.) -o Timeout, in seconds, after which an attempt to connect to the target or a protocol handshake will be aborted (and the connection dropped) if not completed. Defaults to 5s. spiped-1.4.1/spipe/Makefile000644 001751 001751 00000021335 12403117337 017222 0ustar00cpercivacperciva000000 000000 .POSIX: PROG=spipe MAN1=spipe.1 SRCS=main.c pushbits.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c sha256.c elasticarray.c ptrheap.c timerqueue.c asprintf.c entropy.c insecure_memzero.c monoclock.c noeintr.c sock.c warnp.c cpusupport_x86_aesni.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_verify_bytes.c IDIRS=-I ../proto -I ../libcperciva/alg -I ../libcperciva/datastruct -I ../libcperciva/util -I ../libcperciva/cpusupport -I ../libcperciva/events -I ../libcperciva/network -I ../libcperciva/crypto LDADD_REQ=-lcrypto -lpthread all: ${PROG} install:${PROG} mkdir -p ${BINDIR} cp ${PROG} ${BINDIR}/_inst.${PROG}.$$$$_ && \ strip ${BINDIR}/_inst.${PROG}.$$$$_ && \ chmod 0555 ${BINDIR}/_inst.${PROG}.$$$$_ && \ mv -f ${BINDIR}/_inst.${PROG}.$$$$_ ${BINDIR}/${PROG} if ! [ -z "${MAN1DIR}" ]; then \ for MPAGE in ${MAN1}; do \ cp $$MPAGE ${MAN1DIR}/_inst.$$MPAGE.$$$$_ && \ chmod 0444 ${MAN1DIR}/_inst.$$MPAGE.$$$$_ && \ mv -f ${MAN1DIR}/_inst.$$MPAGE.$$$$_ ${MAN1DIR}/$$MPAGE; \ done; \ fi clean: rm -f ${PROG} ${SRCS:.c=.o} ${PROG}:${SRCS:.c=.o} ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c main.c -o main.o pushbits.o: pushbits.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c pushbits.c -o pushbits.o proto_conn.o: ../proto/proto_conn.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_conn.c -o proto_conn.o proto_crypt.o: ../proto/proto_crypt.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_crypt.c -o proto_crypt.o proto_handshake.o: ../proto/proto_handshake.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_handshake.c -o proto_handshake.o proto_pipe.o: ../proto/proto_pipe.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_pipe.c -o proto_pipe.o sha256.o: ../libcperciva/alg/sha256.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/alg/sha256.c -o sha256.o elasticarray.o: ../libcperciva/datastruct/elasticarray.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o ptrheap.o: ../libcperciva/datastruct/ptrheap.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o timerqueue.o: ../libcperciva/datastruct/timerqueue.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o asprintf.o: ../libcperciva/util/asprintf.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/asprintf.c -o asprintf.o entropy.o: ../libcperciva/util/entropy.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/entropy.c -o entropy.o insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o monoclock.o: ../libcperciva/util/monoclock.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/monoclock.c -o monoclock.o noeintr.o: ../libcperciva/util/noeintr.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/noeintr.c -o noeintr.o sock.o: ../libcperciva/util/sock.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/sock.c -o sock.o warnp.o: ../libcperciva/util/warnp.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/warnp.c -o warnp.o cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o events_immediate.o: ../libcperciva/events/events_immediate.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o events_network.o: ../libcperciva/events/events_network.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_network.c -o events_network.o events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o events_timer.o: ../libcperciva/events/events_timer.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_timer.c -o events_timer.o events.o: ../libcperciva/events/events.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events.c -o events.o network_connect.o: ../libcperciva/network/network_connect.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_connect.c -o network_connect.o network_read.o: ../libcperciva/network/network_read.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_read.c -o network_read.o network_write.o: ../libcperciva/network/network_write.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_write.c -o network_write.o crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o spiped-1.4.1/spiped/spiped.1000644 001751 001751 00000007646 12403117256 017305 0ustar00cpercivacperciva000000 000000 .\"- .\" Copyright (c) 2012 Andreas Olsson .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .TH SPIPED 1 "April 2, 2013" "spiped 1.3.0" "spiped README" .SH NAME spiped \- secure pipe daemon .SH SYNOPSIS .B spiped {\-e | \-d} \-s \-t \-k .br [\-DFj] [\-f | \-g] [\-n ] [\-o ] [\-p ] [\-r | \-R] .SH OPTIONS .TP .B \-e Take unencrypted connections from the source socket and send encrypted connections to the target socket. .TP .B \-d Take encrypted connections from the source socket and send unencrypted connections to the target socket. .TP .B \-s Address on which spiped should listen for incoming connections. Must be in one of the following formats: /absolute/path/to/unix/socket host.name:port [ip.v4.ad.dr]:port [ipv6::addr]:port Note that hostnames are resolved when spiped is launched and are not re\-resolved later; thus if DNS entries change spiped will continue to connect to the expired address. .TP .B \-t Address to which spiped should connect. .TP .B \-k Use the provided key file to authenticate and encrypt. .TP .B \-D Wait for DNS. Normally when spiped is launched it resolves addresses and binds to its source socket before the parent process returns; with this option it will daemonize first and retry failed DNS lookups until they succeed. This allows spiped to launch even if DNS isn't set up yet, but at the expense of losing the guarantee that once spiped has finished launching it will be ready to create pipes. .TP .B \-f Use fast/weak handshaking: This reduces the CPU time spent in the initial connection setup, at the expense of losing perfect forward secrecy. .TP .B \-g Require perfect forward secrecy by dropping connections if the other host is using the -f option. .TP .B \-F Run in foreground. This can be useful with systems like daemontools. .TP .B \-j Disable transport layer keep-alives. (By default they are enabled.) .TP .B \-n Limit on the number of simultaneous connections allowed. This value must be between 1 and 500. Defaults to 100 connections. .TP .B \-o Timeout, in seconds, after which an attempt to connect to the target or a protocol handshake will be aborted (and the connection dropped) if not completed. Defaults to 5s. .TP .B \-p File to which spiped's process ID should be written. Defaults to .pid (in the current directory if is not an absolute path). .TP .B \-r Re-resolve the address of every seconds. Defaults to re-resolution every 60 seconds. .TP .B \-R Disable target address re-resolution. .SH SEE ALSO .BR spipe (1). spiped-1.4.1/spiped/dispatch.h000644 001751 001751 00000002226 12403117256 017674 0ustar00cpercivacperciva000000 000000 #ifndef _DISPATCH_H_ #define _DISPATCH_H_ #include /* Opaque structures. */ struct proto_secret; struct sock_addr; /** * dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K, * nconn_max, timeo): * Start accepting connections on the socket ${s}. Connect to the target * ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address * resolution failure use the most recent successfully obtained addresses, or * the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if * ${decr} is non-zero, decrypt the incoming connections. Don't accept more * than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect * forward secrecy. If {$requirefps} is non-zero, require that both ends use * 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. */ int dispatch_accept(int, const char *, double, struct sock_addr **, int, int, int, int, const struct proto_secret *, size_t, double); #endif /* !_DISPATCH_H_ */ spiped-1.4.1/spiped/main.c000644 001751 001751 00000011763 12403117256 017022 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "asprintf.h" #include "daemonize.h" #include "events.h" #include "sock.h" #include "warnp.h" #include "dispatch.h" #include "proto_crypt.h" static void usage(void) { fprintf(stderr, "usage: spiped {-e | -d} -s " "-t -k \n" " [-DFj] [-f | -g] [-n ] " "[-o ]\n" " [-p ] [-r | -R]\n"); exit(1); } /* Simplify error-handling in command-line parse loop. */ #define OPT_EPARSE(opt, arg) do { \ warnp("Error parsing argument: -%c %s", opt, arg); \ exit(1); \ } while (0) int main(int argc, char * argv[]) { /* Command-line parameters. */ int opt_d = 0; int opt_D = 0; int opt_e = 0; int opt_f = 0; int opt_g = 0; int opt_F = 0; int opt_j = 0; const char * opt_k = NULL; intmax_t opt_n = 0; double opt_o = 0.0; char * opt_p = NULL; double opt_r = 0.0; int opt_R = 0; const char * opt_s = NULL; const char * opt_t = NULL; /* Working variables. */ struct sock_addr ** sas_s; struct sock_addr ** sas_t; struct proto_secret * K; int ch; int s; WARNP_INIT; /* Parse the command line. */ while ((ch = getopt(argc, argv, "dDefFgjk:n:o:r:Rp:s:t:")) != -1) { switch (ch) { case 'd': if (opt_d || opt_e) usage(); opt_d = 1; break; case 'D': if (opt_D) usage(); opt_D = 1; break; case 'e': if (opt_d || opt_e) usage(); opt_e = 1; break; case 'f': if (opt_f) usage(); opt_f = 1; break; case 'F': if (opt_F) usage(); opt_F = 1; break; case 'g': if (opt_g) usage(); opt_g = 1; break; case 'j': if (opt_j) usage(); opt_j = 1; break; case 'k': if (opt_k) usage(); opt_k = optarg; break; case 'n': if (opt_n != 0) usage(); if ((opt_n = strtoimax(optarg, NULL, 0)) == 0) { warn0("Invalid option: -n %s", optarg); exit(1); } if ((opt_n <= 0) || (opt_n > 500)) { warn0("The parameter to -n must be between 1 and 500\n"); exit(1); } break; case 'o': if (opt_o != 0.0) usage(); if ((opt_o = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -o %s", optarg); exit(1); } break; case 'p': if (opt_p) usage(); if ((opt_p = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; case 'r': if (opt_r != 0.0) usage(); if ((opt_r = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -r %s", optarg); exit(1); } break; case 'R': if (opt_R) usage(); opt_R = 1; break; case 's': if (opt_s) usage(); opt_s = optarg; break; case 't': if (opt_t) usage(); opt_t = optarg; break; default: usage(); } } /* We should have processed all the arguments. */ if (argc != optind) usage(); /* Set defaults. */ if (opt_n == 0) opt_n = 100; if (opt_o == 0.0) opt_o = 5.0; if (opt_r == 0.0) opt_r = 60.0; /* Sanity-check options. */ if (!opt_d && !opt_e) usage(); if (opt_f && opt_g) usage(); if (opt_k == NULL) usage(); if (!(opt_o > 0.0)) usage(); if ((opt_r != 60.0) && opt_R) usage(); if (opt_s == NULL) usage(); if (opt_t == NULL) usage(); /* Figure out where our pid should be written. */ if (opt_p == NULL) { if (asprintf(&opt_p, "%s.pid", opt_s) == -1) { warnp("asprintf"); exit(1); } } /* Daemonize early if we're going to wait for DNS to be ready. */ if (opt_D && !opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Resolve source address. */ while ((sas_s = sock_resolve(opt_s)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_s); exit(1); } sleep(1); } if (sas_s[0] == NULL) { warn0("No addresses found for %s", opt_s); exit(1); } /* Resolve target address. */ while ((sas_t = sock_resolve(opt_t)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_t); exit(1); } sleep(1); } if (sas_t[0] == NULL) { warn0("No addresses found for %s", opt_t); exit(1); } /* Load the keying data. */ if ((K = proto_crypt_secret(opt_k)) == NULL) { warnp("Error reading shared secret"); exit(1); } /* Create and bind a socket, and mark it as listening. */ if (sas_s[1] != NULL) warn0("Listening on first of multiple addresses found for %s", opt_s); if ((s = sock_listener(sas_s[0])) == -1) exit(1); /* Daemonize and write pid. */ if (!opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Start accepting connections. */ if (dispatch_accept(s, opt_t, opt_R ? 0.0 : opt_r, sas_t, opt_d, opt_f, opt_g, opt_j, K, opt_n, opt_o)) { warnp("Failed to initialize connection acceptor"); exit(1); } /* Infinite loop handling events. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (1); /* NOTREACHED */ /* * If we could reach this point, we would free memory, close sockets, * and otherwise clean up here. */ } spiped-1.4.1/spiped/README000644 001751 001751 00000004674 12403117256 016615 0ustar00cpercivacperciva000000 000000 spiped usage ============ usage: spiped {-e | -d} -s -t -k [-DFj] [-f | -g] [-n ] [-o ] [-p ] [-r | -R] Options: -e Take unencrypted connections from the source socket and send encrypted connections to the target socket. -d Take encrypted connections from the source socket and send unencrypted connections to the target socket. -s Address on which spiped should listen for incoming connections. Must be in one of the following formats: /absolute/path/to/unix/socket host.name:port [ip.v4.ad.dr]:port [ipv6::addr]:port Note that hostnames are resolved when spiped is launched and are not re-resolved later; thus if DNS entries change spiped will continue to connect to the expired address. -t Address to which spiped should connect. -k Use the provided key file to authenticate and encrypt. -D Wait for DNS. Normally when spiped is launched it resolves addresses and binds to its source socket before the parent process returns; with this option it will daemonize first and retry failed DNS lookups until they succeed. This allows spiped to launch even if DNS isn't set up yet, but at the expense of losing the guarantee that once spiped has finished launching it will be ready to create pipes. -f Use fast/weak handshaking: This reduces the CPU time spent in the initial connection setup, at the expense of losing perfect forward secrecy. -g Require perfect forward secrecy by dropping connections if the other host is using the -f option. -F Run in foreground. This can be useful with systems like daemontools. -j Disable transport layer keep-alives. (By default they are enabled.) -n Limit on the number of simultaneous connections allowed. Defaults to 100 connections. -o Timeout, in seconds, after which an attempt to connect to the target or a protocol handshake will be aborted (and the connection dropped) if not completed. Defaults to 5s. -p File to which spiped's process ID should be written. Defaults to .pid (in the current directory if is not an absolute path). -r Re-resolve the address of every seconds. Defaults to re-resolution every 60 seconds. -R Do not re-resolve the address of . spiped-1.4.1/spiped/dispatch.c000644 001751 001751 00000011450 12403117256 017666 0ustar00cpercivacperciva000000 000000 #include #include #include #include "dnsthread.h" #include "events.h" #include "network.h" #include "sock.h" #include "sock_util.h" #include "warnp.h" #include "proto_conn.h" #include "dispatch.h" struct accept_state { int s; const char * tgt; struct sock_addr ** sas; double rtime; int decr; int nofps; int requirefps; int nokeepalive; const struct proto_secret * K; size_t nconn; size_t nconn_max; double timeo; void * accept_cookie; DNSTHREAD T; }; static int callback_gotconn(void *, int); static int callback_resolveagain(void *); /* Callback from address resolution. */ static int callback_resolve(void * cookie, struct sock_addr ** sas) { struct accept_state * A = cookie; /* If the address resolution succeeded... */ if (sas != NULL) { /* Free the old addresses. */ sock_addr_freelist(A->sas); /* Use the new addresses. */ A->sas = sas; } /* Wait a while before resolving again. */ if (events_timer_register_double(callback_resolveagain, A, A->rtime) == NULL) goto err0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Timer callback to trigger another address resolution. */ static int callback_resolveagain(void * cookie) { struct accept_state * A = cookie; /* Re-resolve the target address. */ return (dnsthread_resolveone(A->T, A->tgt, callback_resolve, A)); } /* Non-blocking accept, if we can have more connections. */ static int doaccept(struct accept_state * A) { int rc = 0; /* If we can, accept a new connection. */ if ((A->nconn < A->nconn_max) && (A->accept_cookie == NULL)) { if ((A->accept_cookie = network_accept(A->s, callback_gotconn, A)) == NULL) rc = -1; } /* Return success/fail status. */ return (rc); } /* A connection has closed. Accept more if necessary. */ static int callback_conndied(void * cookie) { struct accept_state * A = cookie; /* We've lost a connection. */ A->nconn -= 1; /* Maybe accept more connections. */ return (doaccept(A)); } /* Handle an incoming connection. */ static int callback_gotconn(void * cookie, int s) { struct accept_state * A = cookie; struct sock_addr ** sas; /* This accept is no longer in progress. */ A->accept_cookie = NULL; /* If we got a -1 descriptor, something went seriously wrong. */ if (s == -1) { warnp("network_accept failed"); goto err0; } /* We have gained a connection. */ A->nconn += 1; /* Duplicate the target address list. */ if ((sas = sock_addr_duplist(A->sas)) == NULL) goto err1; /* Create a new connection. */ if (proto_conn_create(s, sas, A->decr, A->nofps, A->requirefps, A->nokeepalive, A->K, A->timeo, callback_conndied, A)) { warnp("Failure setting up new connection"); goto err2; } /* Accept another connection if we can. */ if (doaccept(A)) goto err0; /* Success! */ return (0); err2: sock_addr_freelist(sas); err1: A->nconn -= 1; close(s); err0: /* Failure! */ return (-1); } /** * dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K, * nconn_max, timeo): * Start accepting connections on the socket ${s}. Connect to the target * ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address * resolution failure use the most recent successfully obtained addresses, or * the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if * ${decr} is non-zero, decrypt the incoming connections. Don't accept more * than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect * forward secrecy. If {$requirefps} is non-zero, require that both ends use * 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. */ int dispatch_accept(int s, const char * tgt, double rtime, struct sock_addr ** sas, int decr, int nofps, int requirefps, int nokeepalive, const struct proto_secret * K, size_t nconn_max, double timeo) { struct accept_state * A; /* Bake a cookie. */ if ((A = malloc(sizeof(struct accept_state))) == NULL) goto err0; A->s = s; A->tgt = tgt; A->sas = sas; A->rtime = rtime; A->decr = decr; A->nofps = nofps; A->requirefps = requirefps; A->nokeepalive = nokeepalive; A->K = K; A->nconn = 0; A->nconn_max = nconn_max; A->timeo = timeo; A->accept_cookie = NULL; /* If address re-resolution is enabled... */ if (rtime > 0.0) { /* Launch an address resolution thread. */ A->T = dnsthread_spawn(); /* Re-resolve the target address after a while. */ if (events_timer_register_double(callback_resolveagain, A, A->rtime) == NULL) goto err1; } /* Accept a connection. */ if (doaccept(A)) goto err1; /* Success! */ return (0); err1: if (rtime > 0.0) dnsthread_kill(A->T); free(A); err0: /* Failure! */ return (-1); } spiped-1.4.1/spiped/Makefile000644 001751 001751 00000023250 12403117336 017363 0ustar00cpercivacperciva000000 000000 .POSIX: PROG=spiped MAN1=spiped.1 SRCS=main.c dispatch.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c sha256.c elasticarray.c ptrheap.c timerqueue.c dnsthread.c asprintf.c daemonize.c entropy.c insecure_memzero.c monoclock.c noeintr.c sock.c sock_util.c warnp.c cpusupport_x86_aesni.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_verify_bytes.c IDIRS=-I ../proto -I ../libcperciva/alg -I ../libcperciva/datastruct -I ../lib/dnsthread -I ../libcperciva/util -I ../libcperciva/cpusupport -I ../libcperciva/events -I ../libcperciva/network -I ../libcperciva/crypto LDADD_REQ=-lcrypto -lpthread all: ${PROG} install:${PROG} mkdir -p ${BINDIR} cp ${PROG} ${BINDIR}/_inst.${PROG}.$$$$_ && \ strip ${BINDIR}/_inst.${PROG}.$$$$_ && \ chmod 0555 ${BINDIR}/_inst.${PROG}.$$$$_ && \ mv -f ${BINDIR}/_inst.${PROG}.$$$$_ ${BINDIR}/${PROG} if ! [ -z "${MAN1DIR}" ]; then \ for MPAGE in ${MAN1}; do \ cp $$MPAGE ${MAN1DIR}/_inst.$$MPAGE.$$$$_ && \ chmod 0444 ${MAN1DIR}/_inst.$$MPAGE.$$$$_ && \ mv -f ${MAN1DIR}/_inst.$$MPAGE.$$$$_ ${MAN1DIR}/$$MPAGE; \ done; \ fi clean: rm -f ${PROG} ${SRCS:.c=.o} ${PROG}:${SRCS:.c=.o} ${CC} -o ${PROG} ${SRCS:.c=.o} ${LDADD_EXTRA} ${LDADD_REQ} ${LDADD_POSIX} main.o: main.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c main.c -o main.o dispatch.o: dispatch.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c dispatch.c -o dispatch.o proto_conn.o: ../proto/proto_conn.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_conn.c -o proto_conn.o proto_crypt.o: ../proto/proto_crypt.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_crypt.c -o proto_crypt.o proto_handshake.o: ../proto/proto_handshake.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_handshake.c -o proto_handshake.o proto_pipe.o: ../proto/proto_pipe.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../proto/proto_pipe.c -o proto_pipe.o sha256.o: ../libcperciva/alg/sha256.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/alg/sha256.c -o sha256.o elasticarray.o: ../libcperciva/datastruct/elasticarray.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o ptrheap.o: ../libcperciva/datastruct/ptrheap.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o timerqueue.o: ../libcperciva/datastruct/timerqueue.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o dnsthread.o: ../lib/dnsthread/dnsthread.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../lib/dnsthread/dnsthread.c -o dnsthread.o asprintf.o: ../libcperciva/util/asprintf.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/asprintf.c -o asprintf.o daemonize.o: ../libcperciva/util/daemonize.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/daemonize.c -o daemonize.o entropy.o: ../libcperciva/util/entropy.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/entropy.c -o entropy.o insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o monoclock.o: ../libcperciva/util/monoclock.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/monoclock.c -o monoclock.o noeintr.o: ../libcperciva/util/noeintr.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/noeintr.c -o noeintr.o sock.o: ../libcperciva/util/sock.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/sock.c -o sock.o sock_util.o: ../libcperciva/util/sock_util.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/sock_util.c -o sock_util.o warnp.o: ../libcperciva/util/warnp.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/util/warnp.c -o warnp.o cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o events_immediate.o: ../libcperciva/events/events_immediate.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o events_network.o: ../libcperciva/events/events_network.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_network.c -o events_network.o events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o events_timer.o: ../libcperciva/events/events_timer.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events_timer.c -o events_timer.o events.o: ../libcperciva/events/events.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/events/events.c -o events.o network_accept.o: ../libcperciva/network/network_accept.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_accept.c -o network_accept.o network_connect.o: ../libcperciva/network/network_connect.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_connect.c -o network_connect.o network_read.o: ../libcperciva/network/network_read.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_read.c -o network_read.o network_write.o: ../libcperciva/network/network_write.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/network/network_write.c -o network_write.o crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" ${CFLAGS_X86_AESNI} -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ${CC} ${CFLAGS} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I .. ${IDIRS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o