1
mirror of https://github.com/jedisct1/libsodium.git synced 2024-12-19 01:55:02 -07:00

Compile curvecp. This will be optional and disabled by default as it is

not exactly portable.
This commit is contained in:
Frank Denis 2013-02-18 13:56:29 -08:00
parent 6774b47cd4
commit 60d788a444
62 changed files with 3131 additions and 1 deletions

7
.gitignore vendored
View File

@ -38,9 +38,13 @@ m4/lt~obsolete.m4
man/*.html
man/Makefile.in
missing
src/libsodium/curvecp/curvecpclient
src/libsodium/curvecp/curvecpmakekey
src/libsodium/curvecp/curvecpmessage
src/libsodium/curvecp/curvecpprintkey
src/libsodium/curvecp/curvecpserver
src/libsodium/include/sodium/version.h
stamp-*
testing
test/default/*.res
test/default/*.trs
test/default/auth
@ -76,3 +80,4 @@ test/default/stream
test/default/stream2
test/default/stream3
test/default/stream4
testing

View File

@ -227,6 +227,7 @@ AH_VERBATIM([NDEBUG], [/* Never ever ignore assertions */
AC_CONFIG_FILES([Makefile
src/Makefile
src/libsodium/Makefile
src/libsodium/curvecp/Makefile
src/libsodium/include/Makefile
src/libsodium/include/sodium/version.h
test/default/Makefile

View File

@ -93,4 +93,5 @@ libsodium_la_CPPFLAGS = \
-I$(top_srcdir)/src/libsodium/include/sodium
SUBDIRS = \
curvecp \
include

View File

@ -0,0 +1,97 @@
noinst_LTLIBRARIES = \
libcurvecp.la
libcurvecp_la_SOURCES = \
blocking.c \
blocking.h \
byte.h \
byte_copy.c \
byte_isequal.c \
byte_zero.c \
crypto_block.c \
crypto_block.h \
die.c \
die.h \
e.c \
e.h \
hexparse.c \
hexparse.h \
load.c \
load.h \
nameparse.c \
nameparse.h \
nanoseconds.c \
nanoseconds.h \
open.h \
open_cwd.c \
open_lock.c \
open_pipe.c \
open_read.c \
open_write.c \
portparse.c \
portparse.h \
randommod.c \
randommod.h \
safenonce.c \
safenonce.h \
savesync.c \
savesync.h \
socket.h \
socket_bind.c \
socket_recv.c \
socket_send.c \
socket_udp.c \
uint16_pack.c \
uint16_pack.h \
uint16_unpack.c \
uint16_unpack.h \
uint32_pack.c \
uint32_pack.h \
uint32_unpack.c \
uint32_unpack.h \
uint64_pack.c \
uint64_pack.h \
uint64_unpack.c \
uint64_unpack.h \
writeall.c \
writeall.h
libcurvecp_la_LIBADD = \
$(top_srcdir)/src/libsodium/libsodium.la
libcurvecp_la_LDFLAGS = \
$(AM_LDFLAGS) \
-no-undefined
libcurvecp_la_CPPFLAGS = \
$(LTDLINCL) \
-I$(top_srcdir)/src/libsodium/include/sodium
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsodium/include/sodium
LDADD = \
libcurvecp.la
bin_PROGRAMS = \
curvecpprintkey \
curvecpmakekey \
curvecpclient \
curvecpserver \
curvecpmessage
curvecpprintkey_SOURCES = \
curvecpprintkey.c
curvecpmakekey_SOURCES = \
curvecpmakekey.c
curvecpclient_SOURCES = \
curvecpclient.c
curvecpserver_SOURCES = \
curvecpserver.c
curvecpmessage_SOURCES = \
curvecpmessage.c

View File

@ -0,0 +1,12 @@
#include <fcntl.h>
#include "blocking.h"
void blocking_enable(int fd)
{
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
}
void blocking_disable(int fd)
{
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
}

View File

@ -0,0 +1,7 @@
#ifndef BLOCKING_H
#define BLOCKING_H
extern void blocking_enable(int);
extern void blocking_disable(int);
#endif

View File

@ -0,0 +1,8 @@
#ifndef BYTE_H
#define BYTE_H
extern void byte_zero(void *,long long);
extern void byte_copy(void *,long long,const void *);
extern int byte_isequal(const void *,long long,const void *);
#endif

View File

@ -0,0 +1,8 @@
#include "byte.h"
void byte_copy(void *yv,long long ylen,const void *xv)
{
char *y = yv;
const char *x = xv;
while (ylen > 0) { *y++ = *x++; --ylen; }
}

View File

@ -0,0 +1,10 @@
#include "byte.h"
int byte_isequal(const void *yv,long long ylen,const void *xv)
{
const unsigned char *y = yv;
const unsigned char *x = xv;
unsigned char diff = 0;
while (ylen > 0) { diff |= (*y++ ^ *x++); --ylen; }
return (256 - (unsigned int) diff) >> 8;
}

View File

@ -0,0 +1,7 @@
#include "byte.h"
void byte_zero(void *yv,long long ylen)
{
char *y = yv;
while (ylen > 0) { *y++ = 0; --ylen; }
}

View File

@ -0,0 +1,35 @@
#include "crypto_block.h"
#include "crypto_uint64.h"
#include "uint64_unpack.h"
#include "uint64_pack.h"
/*
TEA with double-size words.
XXX: Switch to crypto_block_aes256.
XXX: Build crypto_stream_aes256 on top of crypto_block_aes256.
*/
int crypto_block(
unsigned char *out,
const unsigned char *in,
const unsigned char *k
)
{
crypto_uint64 v0 = uint64_unpack(in + 0);
crypto_uint64 v1 = uint64_unpack(in + 8);
crypto_uint64 k0 = uint64_unpack(k + 0);
crypto_uint64 k1 = uint64_unpack(k + 8);
crypto_uint64 k2 = uint64_unpack(k + 16);
crypto_uint64 k3 = uint64_unpack(k + 24);
crypto_uint64 sum = 0;
crypto_uint64 delta = 0x9e3779b97f4a7c15;
int i;
for (i = 0;i < 32;++i) {
sum += delta;
v0 += ((v1<<7) + k0) ^ (v1 + sum) ^ ((v1>>12) + k1);
v1 += ((v0<<16) + k2) ^ (v0 + sum) ^ ((v0>>8) + k3);
}
uint64_pack(out + 0,v0);
uint64_pack(out + 8,v1);
return 0;
}

View File

@ -0,0 +1,4 @@
#define crypto_block_BYTES 16
#define crypto_block_KEYBYTES 32
extern int crypto_block(unsigned char *,const unsigned char *,const unsigned char *);

View File

@ -0,0 +1,476 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
#include "e.h"
#include "die.h"
#include "load.h"
#include "open.h"
#include "byte.h"
#include "socket.h"
#include "uint64_pack.h"
#include "uint64_unpack.h"
#include "nanoseconds.h"
#include "hexparse.h"
#include "nameparse.h"
#include "portparse.h"
#include "writeall.h"
#include "safenonce.h"
#include "randommod.h"
long long recent = 0;
#define NUMIP 8
long long hellowait[NUMIP] = {
1000000000
, 1500000000
, 2250000000
, 3375000000
, 5062500000
, 7593750000
, 11390625000
, 17085937500
} ;
#include "crypto_box.h"
#include "randombytes.h"
#if crypto_box_PUBLICKEYBYTES != 32
error!
#endif
#if crypto_box_NONCEBYTES != 24
error!
#endif
#if crypto_box_BOXZEROBYTES != 16
error!
#endif
#if crypto_box_ZEROBYTES != 32
error!
#endif
#if crypto_box_BEFORENMBYTES != 32
error!
#endif
int flagverbose = 1;
#define USAGE "\
curvecpclient: how to use:\n\
curvecpclient: -q (optional): no error messages\n\
curvecpclient: -Q (optional): print error messages (default)\n\
curvecpclient: -v (optional): print extra information\n\
curvecpclient: -c keydir (optional): use this public-key directory\n\
curvecpclient: sname: server's name\n\
curvecpclient: pk: server's public key\n\
curvecpclient: ip: server's IP address\n\
curvecpclient: port: server's UDP port\n\
curvecpclient: ext: server's extension\n\
curvecpclient: prog: run this client\n\
"
void die_usage(const char *s)
{
if (s) die_4(100,USAGE,"curvecpclient: fatal: ",s,"\n");
die_1(100,USAGE);
}
void die_fatal(const char *trouble,const char *d,const char *fn)
{
/* XXX: clean up? OS can do it much more reliably */
if (!flagverbose) die_0(111);
if (d) {
if (fn) die_9(111,"curvecpclient: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n");
die_7(111,"curvecpclient: fatal: ",trouble," ",d,": ",e_str(errno),"\n");
}
if (errno) die_5(111,"curvecpclient: fatal: ",trouble,": ",e_str(errno),"\n");
die_3(111,"curvecpclient: fatal: ",trouble,"\n");
}
int multiipparse(unsigned char *y,const char *x)
{
long long pos;
long long pos2;
long long ynum;
long long ypos;
long long j;
long long k;
long long d;
for (j = 0;j < 4 * NUMIP;++j) y[j] = 0;
ynum = 0;
while (ynum < 1000) {
++ynum;
ypos = randommod(ynum);
for (k = 0;k < 4;++k) {
pos = ypos * 4 + k;
pos2 = (ynum - 1) * 4 + k;
if (pos >= 0 && pos < 4 * NUMIP && pos2 >= 0 && pos2 < 4 * NUMIP) y[pos2] = y[pos];
d = 0;
for (j = 0;j < 3 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0');
if (j == 0) return 0;
x += j;
if (pos >= 0 && pos < 4 * NUMIP) y[pos] = d;
if (k < 3) {
if (*x != '.') return 0;
++x;
}
}
if (!*x) break;
if (*x != ',') return 0;
++x;
}
/* if fewer than 8 IP addresses, cycle through them: */
pos = 0;
pos2 = ynum * 4;
while (pos2 < 4 * NUMIP) {
if (pos >= 0 && pos < 4 * NUMIP && pos2 >= 0 && pos2 < 4 * NUMIP) y[pos2] = y[pos];
++pos2;
++pos;
}
return 1;
}
/* routing to the client: */
unsigned char clientextension[16];
long long clientextensionloadtime = 0;
int udpfd = -1;
void clientextension_init(void)
{
if (recent >= clientextensionloadtime) {
clientextensionloadtime = recent + 30000000000LL;
if (load("/etc/curvecpextension",clientextension,16) == -1)
if (errno == ENOENT || errno == ENAMETOOLONG)
byte_zero(clientextension,16);
}
}
/* client security: */
char *keydir = 0;
unsigned char clientlongtermpk[32];
unsigned char clientlongtermsk[32];
unsigned char clientshorttermpk[32];
unsigned char clientshorttermsk[32];
crypto_uint64 clientshorttermnonce;
unsigned char vouch[64];
void clientshorttermnonce_update(void)
{
++clientshorttermnonce;
if (clientshorttermnonce) return;
errno = EPROTO;
die_fatal("nonce space expired",0,0);
}
/* routing to the server: */
unsigned char serverip[4 * NUMIP];
unsigned char serverport[2];
unsigned char serverextension[16];
/* server security: */
unsigned char servername[256];
unsigned char serverlongtermpk[32];
unsigned char servershorttermpk[32];
unsigned char servercookie[96];
/* shared secrets: */
unsigned char clientshortserverlong[32];
unsigned char clientshortservershort[32];
unsigned char clientlongserverlong[32];
unsigned char allzero[128] = {0};
unsigned char nonce[24];
unsigned char text[2048];
unsigned char packet[4096];
unsigned char packetip[4];
unsigned char packetport[2];
crypto_uint64 packetnonce;
int flagreceivedmessage = 0;
crypto_uint64 receivednonce = 0;
struct pollfd p[3];
int fdwd = -1;
int tochild[2] = {-1,-1};
int fromchild[2] = {-1,-1};
pid_t child = -1;
int childstatus = 0;
unsigned char childbuf[4096];
long long childbuflen = 0;
unsigned char childmessage[2048];
long long childmessagelen = 0;
int main(int argc,char **argv)
{
long long hellopackets;
long long r;
long long nextaction;
signal(SIGPIPE,SIG_IGN);
if (!argv[0]) die_usage(0);
for (;;) {
char *x;
if (!argv[1]) break;
if (argv[1][0] != '-') break;
x = *++argv;
if (x[0] == '-' && x[1] == 0) break;
if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
while (*++x) {
if (*x == 'q') { flagverbose = 0; continue; }
if (*x == 'Q') { flagverbose = 1; continue; }
if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; }
if (*x == 'c') {
if (x[1]) { keydir = x + 1; break; }
if (argv[1]) { keydir = *++argv; break; }
}
die_usage(0);
}
}
if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots");
if (!hexparse(serverlongtermpk,32,*++argv)) die_usage("pk must be exactly 64 hex characters");
if (!multiipparse(serverip,*++argv)) die_usage("ip must be a comma-separated series of IPv4 addresses");
if (!portparse(serverport,*++argv)) die_usage("port must be an integer between 0 and 65535");
if (!hexparse(serverextension,16,*++argv)) die_usage("ext must be exactly 32 hex characters");
if (!*++argv) die_usage("missing prog");
for (;;) {
r = open_read("/dev/null");
if (r == -1) die_fatal("unable to open /dev/null",0,0);
if (r > 9) { close(r); break; }
}
if (keydir) {
fdwd = open_cwd();
if (fdwd == -1) die_fatal("unable to open current working directory",0,0);
if (chdir(keydir) == -1) die_fatal("unable to change to directory",keydir,0);
if (load("publickey",clientlongtermpk,sizeof clientlongtermpk) == -1) die_fatal("unable to read public key from",keydir,0);
if (load(".expertsonly/secretkey",clientlongtermsk,sizeof clientlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0);
} else {
crypto_box_keypair(clientlongtermpk,clientlongtermsk);
}
crypto_box_keypair(clientshorttermpk,clientshorttermsk);
clientshorttermnonce = randommod(281474976710656LL);
crypto_box_beforenm(clientshortserverlong,serverlongtermpk,clientshorttermsk);
crypto_box_beforenm(clientlongserverlong,serverlongtermpk,clientlongtermsk);
udpfd = socket_udp();
if (udpfd == -1) die_fatal("unable to create socket",0,0);
for (hellopackets = 0;hellopackets < NUMIP;++hellopackets) {
recent = nanoseconds();
/* send a Hello packet: */
clientextension_init();
clientshorttermnonce_update();
byte_copy(nonce,16,"CurveCP-client-H");
uint64_pack(nonce + 16,clientshorttermnonce);
byte_copy(packet,8,"QvnQ5XlH");
byte_copy(packet + 8,16,serverextension);
byte_copy(packet + 24,16,clientextension);
byte_copy(packet + 40,32,clientshorttermpk);
byte_copy(packet + 72,64,allzero);
byte_copy(packet + 136,8,nonce + 16);
crypto_box_afternm(text,allzero,96,nonce,clientshortserverlong);
byte_copy(packet + 144,80,text + 16);
socket_send(udpfd,packet,224,serverip + 4 * hellopackets,serverport);
nextaction = recent + hellowait[hellopackets] + randommod(hellowait[hellopackets]);
for (;;) {
long long timeout = nextaction - recent;
if (timeout <= 0) break;
p[0].fd = udpfd;
p[0].events = POLLIN;
if (poll(p,1,timeout / 1000000 + 1) < 0) p[0].revents = 0;
do { /* try receiving a Cookie packet: */
if (!p[0].revents) break;
r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport);
if (r != 200) break;
if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) &
byte_isequal(packetport,2,serverport) &
byte_isequal(packet,8,"RL3aNMXK") &
byte_isequal(packet + 8,16,clientextension) &
byte_isequal(packet + 24,16,serverextension)
)) break;
byte_copy(nonce,8,"CurveCPK");
byte_copy(nonce + 8,16,packet + 40);
byte_zero(text,16);
byte_copy(text + 16,144,packet + 56);
if (crypto_box_open_afternm(text,text,160,nonce,clientshortserverlong)) break;
byte_copy(servershorttermpk,32,text + 32);
byte_copy(servercookie,96,text + 64);
byte_copy(serverip,4,serverip + 4 * hellopackets);
goto receivedcookie;
} while (0);
recent = nanoseconds();
}
}
errno = ETIMEDOUT; die_fatal("no response from server",0,0);
receivedcookie:
crypto_box_beforenm(clientshortservershort,servershorttermpk,clientshorttermsk);
byte_copy(nonce,8,"CurveCPV");
if (keydir) {
if (safenonce(nonce + 8,0) == -1) die_fatal("nonce-generation disaster",0,0);
} else {
randombytes(nonce + 8,16);
}
byte_zero(text,32);
byte_copy(text + 32,32,clientshorttermpk);
crypto_box_afternm(text,text,64,nonce,clientlongserverlong);
byte_copy(vouch,16,nonce + 8);
byte_copy(vouch + 16,48,text + 16);
/* server is responding, so start child: */
if (open_pipe(tochild) == -1) die_fatal("unable to create pipe",0,0);
if (open_pipe(fromchild) == -1) die_fatal("unable to create pipe",0,0);
child = fork();
if (child == -1) die_fatal("unable to fork",0,0);
if (child == 0) {
if (keydir) if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0);
close(8);
if (dup(tochild[0]) != 8) die_fatal("unable to dup",0,0);
close(9);
if (dup(fromchild[1]) != 9) die_fatal("unable to dup",0,0);
/* XXX: set up environment variables */
signal(SIGPIPE,SIG_DFL);
execvp(*argv,argv);
die_fatal("unable to run",*argv,0);
}
close(fromchild[1]);
close(tochild[0]);
for (;;) {
p[0].fd = udpfd;
p[0].events = POLLIN;
p[1].fd = fromchild[0];
p[1].events = POLLIN;
if (poll(p,2,-1) < 0) {
p[0].revents = 0;
p[1].revents = 0;
}
do { /* try receiving a Message packet: */
if (!p[0].revents) break;
r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport);
if (r < 80) break;
if (r > 1152) break;
if (r & 15) break;
packetnonce = uint64_unpack(packet + 40);
if (flagreceivedmessage && packetnonce <= receivednonce) break;
if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) &
byte_isequal(packetport,2,serverport) &
byte_isequal(packet,8,"RL3aNMXM") &
byte_isequal(packet + 8,16,clientextension) &
byte_isequal(packet + 24,16,serverextension)
)) break;
byte_copy(nonce,16,"CurveCP-server-M");
byte_copy(nonce + 16,8,packet + 40);
byte_zero(text,16);
byte_copy(text + 16,r - 48,packet + 48);
if (crypto_box_open_afternm(text,text,r - 32,nonce,clientshortservershort)) break;
if (!flagreceivedmessage) {
flagreceivedmessage = 1;
randombytes(clientlongtermpk,sizeof clientlongtermpk);
randombytes(vouch,sizeof vouch);
randombytes(servername,sizeof servername);
randombytes(servercookie,sizeof servercookie);
}
receivednonce = packetnonce;
text[31] = (r - 64) >> 4;
/* child is responsible for reading all data immediately, so we won't block: */
if (writeall(tochild[1],text + 31,r - 63) == -1) goto done;
} while (0);
do { /* try receiving data from child: */
long long i;
if (!p[1].revents) break;
r = read(fromchild[0],childbuf,sizeof childbuf);
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
if (r <= 0) goto done;
childbuflen = r;
for (i = 0;i < childbuflen;++i) {
if (childmessagelen < 0) goto done;
if (childmessagelen >= sizeof childmessage) goto done;
childmessage[childmessagelen++] = childbuf[i];
if (childmessage[0] & 128) goto done;
if (childmessagelen == 1 + 16 * (unsigned long long) childmessage[0]) {
clientextension_init();
clientshorttermnonce_update();
uint64_pack(nonce + 16,clientshorttermnonce);
if (flagreceivedmessage) {
r = childmessagelen - 1;
if (r < 16) goto done;
if (r > 1088) goto done;
byte_copy(nonce,16,"CurveCP-client-M");
byte_zero(text,32);
byte_copy(text + 32,r,childmessage + 1);
crypto_box_afternm(text,text,r + 32,nonce,clientshortservershort);
byte_copy(packet,8,"QvnQ5XlM");
byte_copy(packet + 8,16,serverextension);
byte_copy(packet + 24,16,clientextension);
byte_copy(packet + 40,32,clientshorttermpk);
byte_copy(packet + 72,8,nonce + 16);
byte_copy(packet + 80,r + 16,text + 16);
socket_send(udpfd,packet,r + 96,serverip,serverport);
} else {
r = childmessagelen - 1;
if (r < 16) goto done;
if (r > 640) goto done;
byte_copy(nonce,16,"CurveCP-client-I");
byte_zero(text,32);
byte_copy(text + 32,32,clientlongtermpk);
byte_copy(text + 64,64,vouch);
byte_copy(text + 128,256,servername);
byte_copy(text + 384,r,childmessage + 1);
crypto_box_afternm(text,text,r + 384,nonce,clientshortservershort);
byte_copy(packet,8,"QvnQ5XlI");
byte_copy(packet + 8,16,serverextension);
byte_copy(packet + 24,16,clientextension);
byte_copy(packet + 40,32,clientshorttermpk);
byte_copy(packet + 72,96,servercookie);
byte_copy(packet + 168,8,nonce + 16);
byte_copy(packet + 176,r + 368,text + 16);
socket_send(udpfd,packet,r + 544,serverip,serverport);
}
childmessagelen = 0;
}
}
} while (0);
}
done:
do {
r = waitpid(child,&childstatus,0);
} while (r == -1 && errno == EINTR);
if (!WIFEXITED(childstatus)) { errno = 0; die_fatal("process killed by signal",0,0); }
return WEXITSTATUS(childstatus);
}

View File

@ -0,0 +1,57 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "die.h"
#include "e.h"
#include "savesync.h"
#include "randombytes.h"
#include "crypto_box.h"
void die_usage(void)
{
die_1(111,"curvecpmakekey: usage: curvecpmakekey keydir\n");
}
void die_fatal(const char *trouble,const char *d,const char *fn)
{
if (fn) die_9(111,"curvecpmakekey: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n");
die_7(111,"curvecpmakekey: fatal: ",trouble," ",d,": ",e_str(errno),"\n");
}
unsigned char pk[crypto_box_PUBLICKEYBYTES];
unsigned char sk[crypto_box_SECRETKEYBYTES];
unsigned char lock[1];
unsigned char noncekey[32];
unsigned char noncecounter[8];
void create(const char *d,const char *fn,const unsigned char *x,long long xlen)
{
if (savesync(fn,x,xlen) == -1) die_fatal("unable to create",d,fn);
}
int main(int argc,char **argv)
{
char *d;
if (!argv[0]) die_usage();
if (!argv[1]) die_usage();
d = argv[1];
umask(022);
if (mkdir(d,0755) == -1) die_fatal("unable to create directory",d,0);
if (chdir(d) == -1) die_fatal("unable to chdir to directory",d,0);
if (mkdir(".expertsonly",0700) == -1) die_fatal("unable to create directory",d,".expertsonly");
crypto_box_keypair(pk,sk);
create(d,"publickey",pk,sizeof pk);
randombytes(noncekey,sizeof noncekey);
umask(077);
create(d,".expertsonly/secretkey",sk,sizeof sk);
create(d,".expertsonly/lock",lock,sizeof lock);
create(d,".expertsonly/noncekey",noncekey,sizeof noncekey);
create(d,".expertsonly/noncecounter",noncecounter,sizeof noncecounter);
return 0;
}

View File

@ -0,0 +1,654 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <poll.h>
#include "open.h"
#include "blocking.h"
#include "e.h"
#include "die.h"
#include "randommod.h"
#include "byte.h"
#include "crypto_uint32.h"
#include "uint16_pack.h"
#include "uint32_pack.h"
#include "uint64_pack.h"
#include "uint16_unpack.h"
#include "uint32_unpack.h"
#include "uint64_unpack.h"
#include "nanoseconds.h"
#include "writeall.h"
int flagverbose = 1;
int flagserver = 1;
int wantping = 0; /* 1: ping after a second; 2: ping immediately */
#define USAGE "\
curvecpmessage: how to use:\n\
curvecpmessage: -q (optional): no error messages\n\
curvecpmessage: -Q (optional): print error messages (default)\n\
curvecpmessage: -v (optional): print extra information\n\
curvecpmessage: -c (optional): program is a client; server starts first\n\
curvecpmessage: -C (optional): program is a client that starts first\n\
curvecpmessage: -s (optional): program is a server (default)\n\
curvecpmessage: prog: run this program\n\
"
void die_usage(const char *s)
{
if (s) die_4(100,USAGE,"curvecpmessage: fatal: ",s,"\n");
die_1(100,USAGE);
}
void die_fatal(const char *trouble,const char *d,const char *fn)
{
if (!flagverbose) die_0(111);
if (d) {
if (fn) die_9(111,"curvecpmessage: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n");
die_7(111,"curvecpmessage: fatal: ",trouble," ",d,": ",e_str(errno),"\n");
}
if (errno) die_5(111,"curvecpmessage: fatal: ",trouble,": ",e_str(errno),"\n");
die_3(111,"curvecpmessage: fatal: ",trouble,"\n");
}
void die_badmessage(void)
{
errno = EPROTO;
die_fatal("unable to read from file descriptor 8",0,0);
}
void die_internalerror(void)
{
errno = EPROTO;
die_fatal("internal error",0,0);
}
int tochild[2] = {-1,-1};
int fromchild[2] = {-1,-1};
pid_t child = -1;
int childstatus;
struct pollfd p[3];
long long sendacked = 0; /* number of initial bytes sent and fully acknowledged */
long long sendbytes = 0; /* number of additional bytes to send */
unsigned char sendbuf[131072]; /* circular queue with the additional bytes; size must be power of 2 */
long long sendprocessed = 0; /* within sendbytes, number of bytes absorbed into blocks */
crypto_uint16 sendeof = 0; /* 2048 for normal eof after sendbytes, 4096 for error after sendbytes */
int sendeofprocessed = 0;
int sendeofacked = 0;
long long totalblocktransmissions = 0;
long long totalblocks = 0;
#define OUTGOING 128 /* must be power of 2 */
long long blocknum = 0; /* number of outgoing blocks being tracked */
long long blockfirst = 0; /* circular queue */
long long blockpos[OUTGOING]; /* position of block's first byte within stream */
long long blocklen[OUTGOING]; /* number of bytes in this block */
crypto_uint16 blockeof[OUTGOING]; /* 0, 2048, 4096 */
long long blocktransmissions[OUTGOING];
long long blocktime[OUTGOING]; /* time of last message sending this block; 0 means acked */
long long earliestblocktime = 0; /* if nonzero, minimum of active blocktime values */
crypto_uint32 blockid[OUTGOING]; /* ID of last message sending this block */
#define INCOMING 64 /* must be power of 2 */
long long messagenum = 0; /* number of messages in incoming queue */
long long messagefirst = 0; /* position of first message; circular queue */
unsigned char messagelen[INCOMING]; /* times 16 */
unsigned char message[INCOMING][1088];
unsigned char messagetodo[2048];
long long messagetodolen = 0;
long long receivebytes = 0; /* number of initial bytes fully received */
long long receivewritten = 0; /* within receivebytes, number of bytes given to child */
crypto_uint16 receiveeof = 0; /* 0, 2048, 4096 */
long long receivetotalbytes = 0; /* total number of bytes in stream, if receiveeof */
unsigned char receivebuf[131072]; /* circular queue beyond receivewritten; size must be power of 2 */
unsigned char receivevalid[131072]; /* 1 for byte successfully received; XXX: use buddy structure to speed this up */
long long maxblocklen = 512;
crypto_uint32 nextmessageid = 1;
unsigned char buf[4096];
long long lastblocktime = 0;
long long nsecperblock = 1000000000;
long long lastspeedadjustment = 0;
long long lastedge = 0;
long long lastdoubling = 0;
long long rtt;
long long rtt_delta;
long long rtt_average = 0;
long long rtt_deviation = 0;
long long rtt_lowwater = 0;
long long rtt_highwater = 0;
long long rtt_timeout = 1000000000;
long long rtt_seenrecenthigh = 0;
long long rtt_seenrecentlow = 0;
long long rtt_seenolderhigh = 0;
long long rtt_seenolderlow = 0;
long long rtt_phase = 0;
long long lastpanic = 0;
void earliestblocktime_compute(void) /* XXX: use priority queue */
{
long long i;
long long pos;
earliestblocktime = 0;
for (i = 0;i < blocknum;++i) {
pos = (blockfirst + i) & (OUTGOING - 1);
if (blocktime[pos]) {
if (!earliestblocktime)
earliestblocktime = blocktime[pos];
else
if (blocktime[pos] < earliestblocktime)
earliestblocktime = blocktime[pos];
}
}
}
void acknowledged(unsigned long long start,unsigned long long stop)
{
long long i;
long long pos;
if (stop == start) return;
for (i = 0;i < blocknum;++i) {
pos = (blockfirst + i) & (OUTGOING - 1);
if (blockpos[pos] >= start && blockpos[pos] + blocklen[pos] <= stop) {
blocktime[pos] = 0;
totalblocktransmissions += blocktransmissions[pos];
totalblocks += 1;
}
}
while (blocknum) {
pos = blockfirst & (OUTGOING - 1);
if (blocktime[pos]) break;
sendacked += blocklen[pos];
sendbytes -= blocklen[pos];
sendprocessed -= blocklen[pos];
++blockfirst;
--blocknum;
}
if (sendeof)
if (start == 0)
if (stop > sendacked + sendbytes)
if (!sendeofacked) {
sendeofacked = 1;
}
earliestblocktime_compute();
}
int main(int argc,char **argv)
{
long long pos;
long long len;
long long u;
long long r;
long long i;
long long k;
long long recent;
long long nextaction;
long long timeout;
struct pollfd *q;
struct pollfd *watch8;
struct pollfd *watchtochild;
struct pollfd *watchfromchild;
signal(SIGPIPE,SIG_IGN);
if (!argv[0]) die_usage(0);
for (;;) {
char *x;
if (!argv[1]) break;
if (argv[1][0] != '-') break;
x = *++argv;
if (x[0] == '-' && x[1] == 0) break;
if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
while (*++x) {
if (*x == 'q') { flagverbose = 0; continue; }
if (*x == 'Q') { flagverbose = 1; continue; }
if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; }
if (*x == 'c') { flagserver = 0; wantping = 2; continue; }
if (*x == 'C') { flagserver = 0; wantping = 1; continue; }
if (*x == 's') { flagserver = 1; wantping = 0; continue; }
die_usage(0);
}
}
if (!*++argv) die_usage("missing prog");
for (;;) {
r = open_read("/dev/null");
if (r == -1) die_fatal("unable to open /dev/null",0,0);
if (r > 9) { close(r); break; }
}
if (open_pipe(tochild) == -1) die_fatal("unable to create pipe",0,0);
if (open_pipe(fromchild) == -1) die_fatal("unable to create pipe",0,0);
blocking_enable(tochild[0]);
blocking_enable(fromchild[1]);
child = fork();
if (child == -1) die_fatal("unable to fork",0,0);
if (child == 0) {
close(8);
close(9);
if (flagserver) {
close(0);
if (dup(tochild[0]) != 0) die_fatal("unable to dup",0,0);
close(1);
if (dup(fromchild[1]) != 1) die_fatal("unable to dup",0,0);
} else {
close(6);
if (dup(tochild[0]) != 6) die_fatal("unable to dup",0,0);
close(7);
if (dup(fromchild[1]) != 7) die_fatal("unable to dup",0,0);
}
signal(SIGPIPE,SIG_DFL);
execvp(*argv,argv);
die_fatal("unable to run",*argv,0);
}
close(tochild[0]);
close(fromchild[1]);
recent = nanoseconds();
lastspeedadjustment = recent;
if (flagserver) maxblocklen = 1024;
for (;;) {
if (sendeofacked)
if (receivewritten == receivetotalbytes)
if (receiveeof)
if (tochild[1] < 0)
break; /* XXX: to re-ack should enter a TIME-WAIT state here */
q = p;
watch8 = q;
if (watch8) { q->fd = 8; q->events = POLLIN; ++q; }
watchtochild = q;
if (tochild[1] < 0) watchtochild = 0;
if (receivewritten >= receivebytes) watchtochild = 0;
if (watchtochild) { q->fd = tochild[1]; q->events = POLLOUT; ++q; }
watchfromchild = q;
if (sendeof) watchfromchild = 0;
if (sendbytes + 4096 > sizeof sendbuf) watchfromchild = 0;
if (watchfromchild) { q->fd = fromchild[0]; q->events = POLLIN; ++q; }
nextaction = recent + 60000000000LL;
if (wantping == 1) nextaction = recent + 1000000000;
if (wantping == 2)
if (nextaction > lastblocktime + nsecperblock) nextaction = lastblocktime + nsecperblock;
if (blocknum < OUTGOING)
if (!(sendeof ? sendeofprocessed : sendprocessed >= sendbytes))
if (nextaction > lastblocktime + nsecperblock) nextaction = lastblocktime + nsecperblock;
if (earliestblocktime)
if (earliestblocktime + rtt_timeout > lastblocktime + nsecperblock)
if (earliestblocktime + rtt_timeout < nextaction)
nextaction = earliestblocktime + rtt_timeout;
if (messagenum)
if (!watchtochild)
nextaction = 0;
if (nextaction <= recent)
timeout = 0;
else
timeout = (nextaction - recent) / 1000000 + 1;
if (poll(p,q - p,timeout) < 0) {
watch8 = 0;
watchtochild = 0;
watchfromchild = 0;
} else {
if (watch8) if (!watch8->revents) watch8 = 0;
if (watchtochild) if (!watchtochild->revents) watchtochild = 0;
if (watchfromchild) if (!watchfromchild->revents) watchfromchild = 0;
}
/* XXX: keepalives */
do { /* try receiving data from child: */
if (!watchfromchild) break;
if (sendeof) break;
if (sendbytes + 4096 > sizeof sendbuf) break;
pos = (sendacked & (sizeof sendbuf - 1)) + sendbytes;
if (pos < sizeof sendbuf) {
r = read(fromchild[0],sendbuf + pos,sizeof sendbuf - pos);
} else {
r = read(fromchild[0],sendbuf + pos - sizeof sendbuf,sizeof sendbuf - sendbytes);
}
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
if (r < 0) { sendeof = 4096; break; }
if (r == 0) { sendeof = 2048; break; }
sendbytes += r;
if (sendbytes >= 1152921504606846976LL) die_internalerror();
} while(0);
recent = nanoseconds();
do { /* try re-sending an old block: */
if (recent < lastblocktime + nsecperblock) break;
if (earliestblocktime == 0) break;
if (recent < earliestblocktime + rtt_timeout) break;
for (i = 0;i < blocknum;++i) {
pos = (blockfirst + i) & (OUTGOING - 1);
if (blocktime[pos] == earliestblocktime) {
if (recent > lastpanic + 4 * rtt_timeout) {
nsecperblock *= 2;
lastpanic = recent;
lastedge = recent;
}
goto sendblock;
}
}
} while(0);
do { /* try sending a new block: */
if (recent < lastblocktime + nsecperblock) break;
if (blocknum >= OUTGOING) break;
if (!wantping)
if (sendeof ? sendeofprocessed : sendprocessed >= sendbytes) break;
/* XXX: if any Nagle-type processing is desired, do it here */
pos = (blockfirst + blocknum) & (OUTGOING - 1);
++blocknum;
blockpos[pos] = sendacked + sendprocessed;
blocklen[pos] = sendbytes - sendprocessed;
if (blocklen[pos] > maxblocklen) blocklen[pos] = maxblocklen;
if ((blockpos[pos] & (sizeof sendbuf - 1)) + blocklen[pos] > sizeof sendbuf)
blocklen[pos] = sizeof sendbuf - (blockpos[pos] & (sizeof sendbuf - 1));
/* XXX: or could have the full block in post-buffer space */
sendprocessed += blocklen[pos];
blockeof[pos] = 0;
if (sendprocessed == sendbytes) {
blockeof[pos] = sendeof;
if (sendeof) sendeofprocessed = 1;
}
blocktransmissions[pos] = 0;
sendblock:
blocktransmissions[pos] += 1;
blocktime[pos] = recent;
blockid[pos] = nextmessageid;
if (!++nextmessageid) ++nextmessageid;
/* constraints: u multiple of 16; u >= 16; u <= 1088; u >= 48 + blocklen[pos] */
u = 64 + blocklen[pos];
if (u <= 192) u = 192;
else if (u <= 320) u = 320;
else if (u <= 576) u = 576;
else if (u <= 1088) u = 1088;
else die_internalerror();
if (blocklen[pos] < 0 || blocklen[pos] > 1024) die_internalerror();
byte_zero(buf + 8,u);
buf[7] = u / 16;
uint32_pack(buf + 8,blockid[pos]);
/* XXX: include any acknowledgments that have piled up */
uint16_pack(buf + 46,blockeof[pos] | (crypto_uint16) blocklen[pos]);
uint64_pack(buf + 48,blockpos[pos]);
byte_copy(buf + 8 + u - blocklen[pos],blocklen[pos],sendbuf + (blockpos[pos] & (sizeof sendbuf - 1)));
if (writeall(9,buf + 7,u + 1) == -1) die_fatal("unable to write descriptor 9",0,0);
lastblocktime = recent;
wantping = 0;
earliestblocktime_compute();
} while(0);
do { /* try receiving messages: */
if (!watch8) break;
r = read(8,buf,sizeof buf);
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
if (r == 0) die_badmessage();
if (r < 0) die_fatal("unable to read from file descriptor 8",0,0);
for (k = 0;k < r;++k) {
messagetodo[messagetodolen++] = buf[k];
u = 16 * (unsigned long long) messagetodo[0];
if (u < 16) die_badmessage();
if (u > 1088) die_badmessage();
if (messagetodolen == 1 + u) {
if (messagenum < INCOMING) {
pos = (messagefirst + messagenum) & (INCOMING - 1);
messagelen[pos] = messagetodo[0];
byte_copy(message[pos],u,messagetodo + 1);
++messagenum;
} else {
; /* drop tail */
}
messagetodolen = 0;
}
}
} while(0);
do { /* try processing a message: */
if (!messagenum) break;
if (tochild[1] >= 0 && receivewritten < receivebytes) break;
maxblocklen = 1024;
pos = messagefirst & (INCOMING - 1);
len = 16 * (unsigned long long) messagelen[pos];
do { /* handle this message if it's comprehensible: */
unsigned long long D;
unsigned long long SF;
unsigned long long startbyte;
unsigned long long stopbyte;
crypto_uint32 id;
long long i;
if (len < 48) break;
if (len > 1088) break;
id = uint32_unpack(message[pos] + 4);
for (i = 0;i < blocknum;++i) {
k = (blockfirst + i) & (OUTGOING - 1);
if (blockid[k] == id) {
rtt = recent - blocktime[k];
if (!rtt_average) {
nsecperblock = rtt;
rtt_average = rtt;
rtt_deviation = rtt / 2;
rtt_highwater = rtt;
rtt_lowwater = rtt;
}
/* Jacobson's retransmission timeout calculation: */
rtt_delta = rtt - rtt_average;
rtt_average += rtt_delta / 8;
if (rtt_delta < 0) rtt_delta = -rtt_delta;
rtt_delta -= rtt_deviation;
rtt_deviation += rtt_delta / 4;
rtt_timeout = rtt_average + 4 * rtt_deviation;
/* adjust for delayed acks with anti-spiking: */
rtt_timeout += 8 * nsecperblock;
/* recognizing top and bottom of congestion cycle: */
rtt_delta = rtt - rtt_highwater;
rtt_highwater += rtt_delta / 1024;
rtt_delta = rtt - rtt_lowwater;
if (rtt_delta > 0) rtt_lowwater += rtt_delta / 8192;
else rtt_lowwater += rtt_delta / 256;
if (rtt_average > rtt_highwater + 5000000) rtt_seenrecenthigh = 1;
else if (rtt_average < rtt_lowwater) rtt_seenrecentlow = 1;
if (recent >= lastspeedadjustment + 16 * nsecperblock) {
if (recent - lastspeedadjustment > 10000000000LL) {
nsecperblock = 1000000000; /* slow restart */
nsecperblock += randommod(nsecperblock / 8);
}
lastspeedadjustment = recent;
if (nsecperblock >= 131072) {
/* additive increase: adjust 1/N by a constant c */
/* rtt-fair additive increase: adjust 1/N by a constant c every nanosecond */
/* approximation: adjust 1/N by cN every N nanoseconds */
/* i.e., N <- 1/(1/N + cN) = N/(1 + cN^2) every N nanoseconds */
if (nsecperblock < 16777216) {
/* N/(1+cN^2) approx N - cN^3 */
u = nsecperblock / 131072;
nsecperblock -= u * u * u;
} else {
double d = nsecperblock;
nsecperblock = d/(1 + d*d / 2251799813685248.0);
}
}
if (rtt_phase == 0) {
if (rtt_seenolderhigh) {
rtt_phase = 1;
lastedge = recent;
nsecperblock += randommod(nsecperblock / 4);
}
} else {
if (rtt_seenolderlow) {
rtt_phase = 0;
}
}
rtt_seenolderhigh = rtt_seenrecenthigh;
rtt_seenolderlow = rtt_seenrecentlow;
rtt_seenrecenthigh = 0;
rtt_seenrecentlow = 0;
}
do {
if (recent - lastedge < 60000000000LL) {
if (recent < lastdoubling + 4 * nsecperblock + 64 * rtt_timeout + 5000000000LL) break;
} else {
if (recent < lastdoubling + 4 * nsecperblock + 2 * rtt_timeout) break;
}
if (nsecperblock <= 65535) break;
nsecperblock /= 2;
lastdoubling = recent;
if (lastedge) lastedge = recent;
} while(0);
}
}
stopbyte = uint64_unpack(message[pos] + 8);
acknowledged(0,stopbyte);
startbyte = stopbyte + (unsigned long long) uint32_unpack(message[pos] + 16);
stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 20);
acknowledged(startbyte,stopbyte);
startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 22);
stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 24);
acknowledged(startbyte,stopbyte);
startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 26);
stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 28);
acknowledged(startbyte,stopbyte);
startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 30);
stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 32);
acknowledged(startbyte,stopbyte);
startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 34);
stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 36);
acknowledged(startbyte,stopbyte);
D = uint16_unpack(message[pos] + 38);
SF = D & (2048 + 4096);
D -= SF;
if (D > 1024) break;
if (48 + D > len) break;
startbyte = uint64_unpack(message[pos] + 40);
stopbyte = startbyte + D;
if (stopbyte > receivewritten + sizeof receivebuf) {
break;
/* of course, flow control would avoid this case */
}
if (SF) {
receiveeof = SF;
receivetotalbytes = stopbyte;
}
for (k = 0;k < D;++k) {
unsigned char ch = message[pos][len - D + k];
unsigned long long where = startbyte + k;
if (where >= receivewritten && where < receivewritten + sizeof receivebuf) {
receivevalid[where & (sizeof receivebuf - 1)] = 1;
receivebuf[where & (sizeof receivebuf - 1)] = ch;
}
}
for (;;) {
if (receivebytes >= receivewritten + sizeof receivebuf) break;
if (!receivevalid[receivebytes & (sizeof receivebuf - 1)]) break;
++receivebytes;
}
if (!uint32_unpack(message[pos])) break; /* never acknowledge a pure acknowledgment */
/* XXX: delay acknowledgments */
u = 192;
byte_zero(buf + 8,u);
buf[7] = u / 16;
byte_copy(buf + 12,4,message[pos]);
if (receiveeof && receivebytes == receivetotalbytes) {
uint64_pack(buf + 16,receivebytes + 1);
} else
uint64_pack(buf + 16,receivebytes);
/* XXX: incorporate selective acknowledgments */
if (writeall(9,buf + 7,u + 1) == -1) die_fatal("unable to write descriptor 9",0,0);
} while(0);
++messagefirst;
--messagenum;
} while(0);
do { /* try sending data to child: */
if (!watchtochild) break;
if (tochild[1] < 0) { receivewritten = receivebytes; break; }
if (receivewritten >= receivebytes) break;
pos = receivewritten & (sizeof receivebuf - 1);
len = receivebytes - receivewritten;
if (pos + len > sizeof receivebuf) len = sizeof receivebuf - pos;
r = write(tochild[1],receivebuf + pos,len);
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
if (r <= 0) {
close(tochild[1]);
tochild[1] = -1;
break;
}
byte_zero(receivevalid + pos,r);
receivewritten += r;
} while(0);
do { /* try closing pipe to child: */
if (!receiveeof) break;
if (receivewritten < receivetotalbytes) break;
if (tochild[1] < 0) break;
if (receiveeof == 4096)
; /* XXX: UNIX doesn't provide a way to signal an error through a pipe */
close(tochild[1]);
tochild[1] = -1;
} while(0);
}
do {
r = waitpid(child,&childstatus,0);
} while (r == -1 && errno == EINTR);
if (!WIFEXITED(childstatus)) { errno = 0; die_fatal("process killed by signal",0,0); }
return WEXITSTATUS(childstatus);
}

View File

@ -0,0 +1,46 @@
#include <unistd.h>
#include "die.h"
#include "e.h"
#include "load.h"
#include "writeall.h"
#include "crypto_box.h"
unsigned char pk[crypto_box_PUBLICKEYBYTES];
unsigned char out[crypto_box_PUBLICKEYBYTES * 2 + 1];
void die_usage(void)
{
die_1(111,"curvecpprintkey: usage: curvecpprintkey keydir\n");
}
void die_fatal(const char *trouble,const char *d,const char *fn)
{
if (d) {
if (fn) die_9(111,"curvecpmakekey: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n");
die_7(111,"curvecpmakekey: fatal: ",trouble," ",d,": ",e_str(errno),"\n");
}
die_5(111,"curvecpmakekey: fatal: ",trouble,": ",e_str(errno),"\n");
}
int main(int argc,char **argv)
{
char *d;
long long j;
if (!argv[0]) die_usage();
if (!argv[1]) die_usage();
d = argv[1];
if (chdir(d) == -1) die_fatal("unable to chdir to directory",d,0);
if (load("publickey",pk,sizeof pk) == -1) die_fatal("unable to read",d,"publickey");
for (j = 0;j < crypto_box_PUBLICKEYBYTES;++j) {
out[2 * j + 0] = "0123456789abcdef"[15 & (int) (pk[j] >> 4)];
out[2 * j + 1] = "0123456789abcdef"[15 & (int) (pk[j] >> 0)];
}
out[2 * j] = '\n';
if (writeall(1,out,sizeof out) == -1) die_fatal("unable to write output",0,0);
return 0;
}

View File

@ -0,0 +1,497 @@
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include "e.h"
#include "die.h"
#include "byte.h"
#include "open.h"
#include "load.h"
#include "socket.h"
#include "uint64_pack.h"
#include "uint64_unpack.h"
#include "writeall.h"
#include "nanoseconds.h"
#include "safenonce.h"
#include "nameparse.h"
#include "hexparse.h"
#include "portparse.h"
#include "randommod.h"
#include "randombytes.h"
#include "crypto_box.h"
#include "crypto_secretbox.h"
#if crypto_box_PUBLICKEYBYTES != 32
error!
#endif
#if crypto_box_NONCEBYTES != 24
error!
#endif
#if crypto_box_BOXZEROBYTES != 16
error!
#endif
#if crypto_box_ZEROBYTES != 32
error!
#endif
#if crypto_box_BEFORENMBYTES != 32
error!
#endif
#if crypto_secretbox_KEYBYTES != 32
error!
#endif
#if crypto_secretbox_NONCEBYTES != 24
error!
#endif
#if crypto_secretbox_BOXZEROBYTES != 16
error!
#endif
#if crypto_secretbox_ZEROBYTES != 32
error!
#endif
int flagverbose;
#define USAGE "\
curvecpserver: how to use:\n\
curvecpserver: -q (optional): no error messages\n\
curvecpserver: -Q (optional): print error messages (default)\n\
curvecpserver: -v (optional): print extra information\n\
curvecpserver: -c n (optional): allow at most n clients at once (default 100)\n\
curvecpserver: sname: server's name\n\
curvecpserver: keydir: use this public-key directory\n\
curvecpserver: ip: server's IP address\n\
curvecpserver: port: server's UDP port\n\
curvecpserver: ext: server's extension\n\
curvecpserver: prog: run this server\n\
"
void die_usage(const char *s)
{
if (s) die_4(100,USAGE,"curvecpserver: fatal: ",s,"\n");
die_1(100,USAGE);
}
void die_fatal(const char *trouble,const char *d,const char *fn)
{
if (!flagverbose) die_0(111);
if (d) {
if (fn) die_9(111,"curvecpserver: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n");
die_7(111,"curvecpserver: fatal: ",trouble," ",d,": ",e_str(errno),"\n");
}
die_5(111,"curvecpserver: fatal: ",trouble,": ",e_str(errno),"\n");
}
int ipparse(unsigned char *y,const char *x)
{
long long j;
long long k;
long long d;
for (k = 0;k < 4;++k) y[k] = 0;
for (k = 0;k < 4;++k) {
d = 0;
for (j = 0;j < 3 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0');
if (j == 0) return 0;
x += j;
if (k >= 0 && k < 4) y[k] = d;
if (k < 3) {
if (*x != '.') return 0;
++x;
}
}
if (*x) return 0;
return 1;
}
int maxparse(long long *y,const char *x)
{
long long d;
long long j;
d = 0;
for (j = 0;j < 9 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0');
if (x[j]) return 0;
if (d < 1) return 0;
if (d > 65535) return 0;
*y = d;
return 1;
}
/* cookies: */
long long nextminute;
unsigned char minutekey[32];
unsigned char lastminutekey[32];
/* routing to the server: */
unsigned char serverip[4];
unsigned char serverport[2];
unsigned char serverextension[16];
int udpfd = -1;
/* server security: */
char *keydir = 0;
unsigned char servername[256];
unsigned char serverlongtermsk[32];
unsigned char servershorttermpk[32];
unsigned char servershorttermsk[32];
/* routing to the client: */
unsigned char clientextension[16];
/* client security: */
unsigned char clientlongtermpk[32];
unsigned char clientshorttermpk[32];
/* shared secrets: */
unsigned char clientshortserverlong[32];
unsigned char clientshortservershort[32];
unsigned char clientlongserverlong[32];
unsigned char allzero[128] = {0};
unsigned char nonce[24];
unsigned char text[2048];
unsigned char packetip[4];
unsigned char packetport[2];
unsigned char packet[4096];
crypto_uint64 packetnonce;
#define MESSAGELEN 1104
struct activeclient {
unsigned char clientshorttermpk[32];
unsigned char clientshortservershort[32];
crypto_uint64 receivednonce;
crypto_uint64 sentnonce;
long long messagelen;
pid_t child;
int tochild;
int fromchild;
unsigned char clientextension[16];
unsigned char clientip[4];
unsigned char clientport[2];
unsigned char message[MESSAGELEN];
} ;
const char *strmaxactiveclients = "100";
long long maxactiveclients = 0;
long long numactiveclients = 0;
struct activeclient *activeclients = 0;
struct pollfd *p;
int fdwd = -1;
int pi0[2];
int pi1[2];
unsigned char childbuf[4096];
long long childbuflen = 0;
unsigned char childmessage[2048];
long long childmessagelen = 0;
int main(int argc,char **argv)
{
long long r;
long long i;
long long k;
signal(SIGPIPE,SIG_IGN);
signal(SIGCHLD,SIG_IGN);
if (!argv[0]) die_usage(0);
for (;;) {
char *x;
if (!argv[1]) break;
if (argv[1][0] != '-') break;
x = *++argv;
if (x[0] == '-' && x[1] == 0) break;
if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
while (*++x) {
if (*x == 'q') { flagverbose = 0; continue; }
if (*x == 'Q') { flagverbose = 1; continue; }
if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; }
if (*x == 'c') {
if (x[1]) { strmaxactiveclients = x + 1; break; }
if (argv[1]) { strmaxactiveclients = *++argv; break; }
}
die_usage(0);
}
}
if (!maxparse(&maxactiveclients,strmaxactiveclients)) die_usage("concurrency must be between 1 and 65535");
if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots");
keydir = *++argv; if (!keydir) die_usage("missing keydir");
if (!ipparse(serverip,*++argv)) die_usage("ip must be an IPv4 address");
if (!portparse(serverport,*++argv)) die_usage("port must be an integer between 0 and 65535");
if (!hexparse(serverextension,16,*++argv)) die_usage("ext must be exactly 32 hex characters");
if (!*++argv) die_usage("missing prog");
for (;;) {
r = open_read("/dev/null");
if (r == -1) die_fatal("unable to open /dev/null",0,0);
if (r > 9) { close(r); break; }
}
activeclients = malloc(maxactiveclients * sizeof(struct activeclient));
if (!activeclients) die_fatal("unable to create activeclients array",0,0);
randombytes((void *) activeclients,maxactiveclients * sizeof(struct activeclient));
for (i = 0;i < maxactiveclients;++i) {
activeclients[i].child = -1;
activeclients[i].tochild = -1;
activeclients[i].fromchild = -1;
activeclients[i].receivednonce = 0;
activeclients[i].sentnonce = randommod(281474976710656LL);
}
p = malloc((1 + maxactiveclients) * sizeof(struct pollfd));
if (!p) die_fatal("unable to create poll array",0,0);
fdwd = open_cwd();
if (fdwd == -1) die_fatal("unable to open current directory",0,0);
if (chdir(keydir) == -1) die_fatal("unable to chdir to",keydir,0);
if (load(".expertsonly/secretkey",serverlongtermsk,sizeof serverlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0);
udpfd = socket_udp();
if (udpfd == -1) die_fatal("unable to create socket",0,0);
if (socket_bind(udpfd,serverip,serverport) == -1) die_fatal("unable to bind socket",0,0);
randombytes(minutekey,sizeof minutekey);
randombytes(lastminutekey,sizeof lastminutekey);
nextminute = nanoseconds() + 60000000000ULL;
for (;;) {
long long timeout = nextminute - nanoseconds();
if (timeout <= 0) {
timeout = 60000000000ULL;
byte_copy(lastminutekey,sizeof lastminutekey,minutekey);
randombytes(minutekey,sizeof minutekey);
nextminute = nanoseconds() + timeout;
randombytes(packet,sizeof packet);
randombytes(packetip,sizeof packetip);
randombytes(packetport,sizeof packetport);
randombytes(clientshorttermpk,sizeof clientshorttermpk);
randombytes(clientshortserverlong,sizeof clientshortserverlong);
randombytes(nonce,sizeof nonce);
randombytes(text,sizeof text);
randombytes(childbuf,sizeof childbuf);
randombytes(childmessage,sizeof childmessage);
randombytes(servershorttermpk,sizeof servershorttermpk);
randombytes(servershorttermsk,sizeof servershorttermsk);
}
for (i = 0;i < numactiveclients;++i) {
p[i].fd = activeclients[i].fromchild;
p[i].events = POLLIN;
}
p[numactiveclients].fd = udpfd;
p[numactiveclients].events = POLLIN;
if (poll(p,1 + numactiveclients,timeout / 1000000 + 1) < 0) continue;
do { /* try receiving a packet: */
if (!p[numactiveclients].revents) break;
r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport);
if (r < 80) break;
if (r > 1184) break;
if (r & 15) break;
if (!(byte_isequal(packet,7,"QvnQ5Xl") & byte_isequal(packet + 8,16,serverextension))) break;
byte_copy(clientextension,16,packet + 24);
if (packet[7] == 'H') { /* Hello packet: */
if (r != 224) break;
byte_copy(clientshorttermpk,32,packet + 40);
crypto_box_beforenm(clientshortserverlong,clientshorttermpk,serverlongtermsk);
byte_copy(nonce,16,"CurveCP-client-H");
byte_copy(nonce + 16,8,packet + 136);
byte_zero(text,16);
byte_copy(text + 16,80,packet + 144);
if (crypto_box_open_afternm(text,text,96,nonce,clientshortserverlong)) break;
/* send Cookie packet: */
crypto_box_keypair(servershorttermpk,servershorttermsk);
byte_zero(text + 64,32);
byte_copy(text + 96,32,clientshorttermpk);
byte_copy(text + 128,32,servershorttermsk);
byte_copy(nonce,8,"minute-k");
if (safenonce(nonce + 8,1) == -1) die_fatal("nonce-generation disaster",0,0);
crypto_secretbox(text + 64,text + 64,96,nonce,minutekey);
byte_copy(text + 64,16,nonce + 8);
byte_zero(text,32);
byte_copy(text + 32,32,servershorttermpk);
byte_copy(nonce,8,"CurveCPK"); /* reusing the other 16 bytes */
crypto_box_afternm(text,text,160,nonce,clientshortserverlong);
byte_copy(packet,8,"RL3aNMXK");
byte_copy(packet + 8,16,clientextension);
byte_copy(packet + 24,16,serverextension);
byte_copy(packet + 40,16,nonce + 8);
byte_copy(packet + 56,144,text + 16);
socket_send(udpfd,packet,200,packetip,packetport);
}
if (packet[7] == 'I') { /* Initiate packet: */
if (r < 560) break;
for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */
if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40))
break;
if (i < numactiveclients) {
packetnonce = uint64_unpack(packet + 168);
if (packetnonce <= activeclients[i].receivednonce) break;
byte_copy(nonce,16,"CurveCP-client-I");
byte_copy(nonce + 16,8,packet + 168);
byte_zero(text,16);
byte_copy(text + 16,r - 176,packet + 176);
if (crypto_box_open_afternm(text,text,r - 160,nonce,activeclients[i].clientshortservershort)) break;
/* XXX: update clientip, clientextension; but not if client has spoken recently */
activeclients[i].receivednonce = packetnonce;
text[383] = (r - 544) >> 4;
if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1)
; /* child is gone; will see eof later */
break;
}
if (i == maxactiveclients) break;
byte_copy(nonce,8,"minute-k");
byte_copy(nonce + 8,16,packet + 72);
byte_zero(text,16);
byte_copy(text + 16,80,packet + 88);
if (crypto_secretbox_open(text,text,96,nonce,minutekey)) {
byte_zero(text,16);
byte_copy(text + 16,80,packet + 88);
if (crypto_secretbox_open(text,text,96,nonce,lastminutekey)) break;
}
if (!byte_isequal(packet + 40,32,text + 32)) break;
byte_copy(servershorttermsk,32,text + 64);
byte_copy(clientshorttermpk,32,packet + 40);
crypto_box_beforenm(clientshortservershort,clientshorttermpk,servershorttermsk);
byte_copy(nonce,16,"CurveCP-client-I");
byte_copy(nonce + 16,8,packet + 168);
byte_zero(text,16);
byte_copy(text + 16,r - 176,packet + 176);
if (crypto_box_open_afternm(text,text,r - 160,nonce,clientshortservershort)) break;
if (!byte_isequal(text + 128,256,servername)) break;
/* XXX skip if client authentication is not desired: */
byte_copy(clientlongtermpk,32,text + 32);
/* XXX impose policy limitations on clients: known, maxconn */
/* XXX for known clients, retrieve shared secret from cache: */
crypto_box_beforenm(clientlongserverlong,clientlongtermpk,serverlongtermsk);
byte_copy(nonce,8,"CurveCPV");
byte_copy(nonce + 8,16,text + 64);
byte_zero(text + 64,16);
if (crypto_box_open_afternm(text + 64,text + 64,64,nonce,clientlongserverlong)) break;
if (!byte_isequal(text + 96,32,clientshorttermpk)) break;
if (open_pipe(pi0) == -1) break; /* XXX: error message */
if (open_pipe(pi1) == -1) { close(pi0[0]); close(pi0[1]); break; } /* XXX: error message */
activeclients[i].child = fork();
if (activeclients[i].child == -1) {
close(pi0[0]); close(pi0[1]);
close(pi1[0]); close(pi1[1]);
break; /* XXX: error message */
}
if (activeclients[i].child == 0) {
if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0);
close(8);
if (dup(pi0[0]) != 8) die_fatal("unable to dup",0,0);
close(9);
if (dup(pi1[1]) != 9) die_fatal("unable to dup",0,0);
/* XXX: set up environment variables */
signal(SIGPIPE,SIG_DFL);
signal(SIGCHLD,SIG_DFL);
execvp(*argv,argv);
die_fatal("unable to run",*argv,0);
}
activeclients[i].tochild = pi0[1]; close(pi0[0]);
activeclients[i].fromchild = pi1[0]; close(pi1[1]);
activeclients[i].messagelen = 0;
byte_copy(activeclients[i].clientshorttermpk,32,clientshorttermpk);
byte_copy(activeclients[i].clientshortservershort,32,clientshortservershort);
activeclients[i].receivednonce = uint64_unpack(packet + 168);
byte_copy(activeclients[i].clientextension,16,clientextension);
byte_copy(activeclients[i].clientip,4,packetip);
byte_copy(activeclients[i].clientport,2,packetport);
++numactiveclients;
text[383] = (r - 544) >> 4;
if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1)
; /* child is gone; will see eof later */
}
if (packet[7] == 'M') { /* Message packet: */
if (r < 112) break;
for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */
if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40))
break;
if (i < numactiveclients) {
packetnonce = uint64_unpack(packet + 72);
if (packetnonce <= activeclients[i].receivednonce) break;
byte_copy(nonce,16,"CurveCP-client-M");
byte_copy(nonce + 16,8,packet + 72);
byte_zero(text,16);
byte_copy(text + 16,r - 80,packet + 80);
if (crypto_box_open_afternm(text,text,r - 64,nonce,activeclients[i].clientshortservershort)) break;
/* XXX: update clientip, clientextension */
activeclients[i].receivednonce = packetnonce;
text[31] = (r - 96) >> 4;
if (writeall(activeclients[i].tochild,text + 31,r - 95) == -1)
; /* child is gone; will see eof later */
break;
}
}
} while (0);
for (i = numactiveclients - 1;i >= 0;--i) {
do {
if (!p[i].revents) break;
r = read(activeclients[i].fromchild,childbuf,sizeof childbuf);
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
if (r <= 0) goto endconnection;
childbuflen = r;
for (k = 0;k < childbuflen;++k) {
r = activeclients[i].messagelen;
if (r < 0) goto endconnection;
if (r >= MESSAGELEN) goto endconnection;
activeclients[i].message[r] = childbuf[k];
if (r == 0) if (childbuf[k] & 128) goto endconnection;
activeclients[i].messagelen = r + 1;
if (r == 16 * (unsigned long long) activeclients[i].message[0]) {
if (r < 16) goto endconnection;
if (r > 1088) goto endconnection;
byte_copy(nonce,16,"CurveCP-server-M");
uint64_pack(nonce + 16,++activeclients[i].sentnonce);
byte_zero(text,32);
byte_copy(text + 32,r,activeclients[i].message + 1);
crypto_box_afternm(text,text,r + 32,nonce,activeclients[i].clientshortservershort);
byte_copy(packet,8,"RL3aNMXM");
byte_copy(packet + 8,16,clientextension);
byte_copy(packet + 24,16,serverextension);
byte_copy(packet + 40,8,nonce + 16);
byte_copy(packet + 48,r + 16,text + 16);
socket_send(udpfd,packet,r + 64,activeclients[i].clientip,activeclients[i].clientport);
activeclients[i].messagelen = 0;
}
}
break;
endconnection:
/* XXX: cache cookie if it's recent */
close(activeclients[i].fromchild); activeclients[i].fromchild = -1;
close(activeclients[i].tochild); activeclients[i].tochild = -1;
--numactiveclients;
activeclients[i] = activeclients[numactiveclients];
randombytes((void *) &activeclients[numactiveclients],sizeof(struct activeclient));
} while (0);
}
}
}

View File

@ -0,0 +1,42 @@
#include <unistd.h>
#include "writeall.h"
#include "die.h"
void die_9(int e
,const char *s0
,const char *s1
,const char *s2
,const char *s3
,const char *s4
,const char *s5
,const char *s6
,const char *s7
,const char *s8
)
{
const char *s[9];
const char *x;
char buf[1024];
int buflen = 0;
int i;
s[0] = s0;
s[1] = s1;
s[2] = s2;
s[3] = s3;
s[4] = s4;
s[5] = s5;
s[6] = s6;
s[7] = s7;
s[8] = s8;
for (i = 0;i < 9;++i) {
x = s[i];
if (!x) continue;
while (*x) {
if (buflen == sizeof buf) { writeall(2,buf,buflen); buflen = 0; }
buf[buflen++] = *x++;
}
}
writeall(2,buf,buflen);
_exit(e);
}

View File

@ -0,0 +1,16 @@
#ifndef DIE_H
#define DIE_H
extern void die_9(int,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *);
#define die_8(x,a,b,c,d,e,f,g,h) die_9(x,a,b,c,d,e,f,g,h,0)
#define die_7(x,a,b,c,d,e,f,g) die_8(x,a,b,c,d,e,f,g,0)
#define die_6(x,a,b,c,d,e,f) die_7(x,a,b,c,d,e,f,0)
#define die_5(x,a,b,c,d,e) die_6(x,a,b,c,d,e,0)
#define die_4(x,a,b,c,d) die_5(x,a,b,c,d,0)
#define die_3(x,a,b,c) die_4(x,a,b,c,0)
#define die_2(x,a,b) die_3(x,a,b,0)
#define die_1(x,a) die_2(x,a,0)
#define die_0(x) die_1(x,0)
#endif

106
src/libsodium/curvecp/e.c Normal file
View File

@ -0,0 +1,106 @@
#include "e.h"
#define X(e,s) if (i == e) return s;
const char *e_str(int i)
{
X(0,"no error");
X(EINTR,"interrupted system call")
X(ENOMEM,"out of memory")
X(ENOENT,"file does not exist")
X(ETXTBSY,"text busy")
X(EIO,"input/output error")
X(EEXIST,"file already exists")
X(ETIMEDOUT,"timed out")
X(EINPROGRESS,"operation in progress")
X(EAGAIN,"temporary failure")
X(EWOULDBLOCK,"input/output would block")
X(EPIPE,"broken pipe")
X(EPERM,"permission denied")
X(EACCES,"access denied")
X(ENODEV,"device not configured")
X(EPROTO,"protocol error")
X(EISDIR,"is a directory")
X(ESRCH,"no such process")
X(E2BIG,"argument list too long")
X(ENOEXEC,"exec format error")
X(EBADF,"file descriptor not open")
X(ECHILD,"no child processes")
X(EDEADLK,"operation would cause deadlock")
X(EFAULT,"bad address")
X(ENOTBLK,"not a block device")
X(EBUSY,"device busy")
X(EXDEV,"cross-device link")
X(ENODEV,"device does not support operation")
X(ENOTDIR,"not a directory")
X(EINVAL,"invalid argument")
X(ENFILE,"system cannot open more files")
X(EMFILE,"process cannot open more files")
X(ENOTTY,"not a tty")
X(EFBIG,"file too big")
X(ENOSPC,"out of disk space")
X(ESPIPE,"unseekable descriptor")
X(EROFS,"read-only file system")
X(EMLINK,"too many links")
X(EDOM,"input out of range")
X(ERANGE,"output out of range")
X(EALREADY,"operation already in progress")
X(ENOTSOCK,"not a socket")
X(EDESTADDRREQ,"destination address required")
X(EMSGSIZE,"message too long")
X(EPROTOTYPE,"incorrect protocol type")
X(ENOPROTOOPT,"protocol not available")
X(EPROTONOSUPPORT,"protocol not supported")
X(ESOCKTNOSUPPORT,"socket type not supported")
X(EOPNOTSUPP,"operation not supported")
X(EPFNOSUPPORT,"protocol family not supported")
X(EAFNOSUPPORT,"address family not supported")
X(EADDRINUSE,"address already used")
X(EADDRNOTAVAIL,"address not available")
X(ENETDOWN,"network down")
X(ENETUNREACH,"network unreachable")
X(ENETRESET,"network reset")
X(ECONNABORTED,"connection aborted")
X(ECONNRESET,"connection reset")
X(ENOBUFS,"out of buffer space")
X(EISCONN,"already connected")
X(ENOTCONN,"not connected")
X(ESHUTDOWN,"socket shut down")
X(ETOOMANYREFS,"too many references")
X(ECONNREFUSED,"connection refused")
X(ELOOP,"symbolic link loop")
X(ENAMETOOLONG,"file name too long")
X(EHOSTDOWN,"host down")
X(EHOSTUNREACH,"host unreachable")
X(ENOTEMPTY,"directory not empty")
X(EPROCLIM,"too many processes")
X(EUSERS,"too many users")
X(EDQUOT,"disk quota exceeded")
X(ESTALE,"stale NFS file handle")
X(EREMOTE,"too many levels of remote in path")
X(EBADRPC,"RPC structure is bad")
X(ERPCMISMATCH,"RPC version mismatch")
X(EPROGUNAVAIL,"RPC program unavailable")
X(EPROGMISMATCH,"program version mismatch")
X(EPROCUNAVAIL,"bad procedure for program")
X(ENOLCK,"no locks available")
X(ENOSYS,"system call not available")
X(EFTYPE,"bad file type")
X(EAUTH,"authentication error")
X(ENEEDAUTH,"not authenticated")
X(ENOSTR,"not a stream device")
X(ETIME,"timer expired")
X(ENOSR,"out of stream resources")
X(ENOMSG,"no message of desired type")
X(EBADMSG,"bad message type")
X(EIDRM,"identifier removed")
X(ENONET,"machine not on network")
X(EREMOTE,"object not local")
X(ENOLINK,"link severed")
X(EADV,"advertise error")
X(ESRMNT,"srmount error")
X(ECOMM,"communication error")
X(EMULTIHOP,"multihop attempted")
X(EREMCHG,"remote address changed")
return "unknown error";
}

438
src/libsodium/curvecp/e.h Normal file
View File

@ -0,0 +1,438 @@
#ifndef E_H
#define E_H
#include <errno.h>
extern const char *e_str(int);
#ifndef EPERM
#define EPERM (-5001)
#endif
#ifndef ENOENT
#define ENOENT (-5002)
#endif
#ifndef ESRCH
#define ESRCH (-5003)
#endif
#ifndef EINTR
#define EINTR (-5004)
#endif
#ifndef EIO
#define EIO (-5005)
#endif
#ifndef ENXIO
#define ENXIO (-5006)
#endif
#ifndef E2BIG
#define E2BIG (-5007)
#endif
#ifndef ENOEXEC
#define ENOEXEC (-5008)
#endif
#ifndef EBADF
#define EBADF (-5009)
#endif
#ifndef ECHILD
#define ECHILD (-5010)
#endif
#ifndef EAGAIN
#define EAGAIN (-5011)
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK (-7011)
#endif
#ifndef ENOMEM
#define ENOMEM (-5012)
#endif
#ifndef EACCES
#define EACCES (-5013)
#endif
#ifndef EFAULT
#define EFAULT (-5014)
#endif
#ifndef ENOTBLK
#define ENOTBLK (-5015)
#endif
#ifndef EBUSY
#define EBUSY (-5016)
#endif
#ifndef EEXIST
#define EEXIST (-5017)
#endif
#ifndef EXDEV
#define EXDEV (-5018)
#endif
#ifndef ENODEV
#define ENODEV (-5019)
#endif
#ifndef ENOTDIR
#define ENOTDIR (-5020)
#endif
#ifndef EISDIR
#define EISDIR (-5021)
#endif
#ifndef EINVAL
#define EINVAL (-5022)
#endif
#ifndef ENFILE
#define ENFILE (-5023)
#endif
#ifndef EMFILE
#define EMFILE (-5024)
#endif
#ifndef ENOTTY
#define ENOTTY (-5025)
#endif
#ifndef ETXTBSY
#define ETXTBSY (-5026)
#endif
#ifndef EFBIG
#define EFBIG (-5027)
#endif
#ifndef ENOSPC
#define ENOSPC (-5028)
#endif
#ifndef ESPIPE
#define ESPIPE (-5029)
#endif
#ifndef EROFS
#define EROFS (-5030)
#endif
#ifndef EMLINK
#define EMLINK (-5031)
#endif
#ifndef EPIPE
#define EPIPE (-5032)
#endif
#ifndef EDOM
#define EDOM (-5033)
#endif
#ifndef ERANGE
#define ERANGE (-5034)
#endif
#ifndef EDEADLK
#define EDEADLK (-5035)
#endif
#ifndef EDEADLOCK
#define EDEADLOCK (-7035)
#endif
#ifndef ENAMETOOLONG
#define ENAMETOOLONG (-5036)
#endif
#ifndef ENOLCK
#define ENOLCK (-5037)
#endif
#ifndef ENOSYS
#define ENOSYS (-5038)
#endif
#ifndef ENOTEMPTY
#define ENOTEMPTY (-5039)
#endif
#ifndef ELOOP
#define ELOOP (-5040)
#endif
#ifndef ENOMSG
#define ENOMSG (-5042)
#endif
#ifndef EIDRM
#define EIDRM (-5043)
#endif
#ifndef ECHRNG
#define ECHRNG (-5044)
#endif
#ifndef EL2NSYNC
#define EL2NSYNC (-5045)
#endif
#ifndef EL3HLT
#define EL3HLT (-5046)
#endif
#ifndef EL3RST
#define EL3RST (-5047)
#endif
#ifndef ELNRNG
#define ELNRNG (-5048)
#endif
#ifndef EUNATCH
#define EUNATCH (-5049)
#endif
#ifndef ENOCSI
#define ENOCSI (-5050)
#endif
#ifndef EL2HLT
#define EL2HLT (-5051)
#endif
#ifndef EBADE
#define EBADE (-5052)
#endif
#ifndef EBADR
#define EBADR (-5053)
#endif
#ifndef EXFULL
#define EXFULL (-5054)
#endif
#ifndef ENOANO
#define ENOANO (-5055)
#endif
#ifndef EBADRQC
#define EBADRQC (-5056)
#endif
#ifndef EBADSLT
#define EBADSLT (-5057)
#endif
#ifndef EBFONT
#define EBFONT (-5059)
#endif
#ifndef ENOSTR
#define ENOSTR (-5060)
#endif
#ifndef ENODATA
#define ENODATA (-5061)
#endif
#ifndef ETIME
#define ETIME (-5062)
#endif
#ifndef ENOSR
#define ENOSR (-5063)
#endif
#ifndef ENONET
#define ENONET (-5064)
#endif
#ifndef ENOPKG
#define ENOPKG (-5065)
#endif
#ifndef EREMOTE
#define EREMOTE (-5066)
#endif
#ifndef ENOLINK
#define ENOLINK (-5067)
#endif
#ifndef EADV
#define EADV (-5068)
#endif
#ifndef ESRMNT
#define ESRMNT (-5069)
#endif
#ifndef ECOMM
#define ECOMM (-5070)
#endif
#ifndef EPROTO
#define EPROTO (-5071)
#endif
#ifndef EMULTIHOP
#define EMULTIHOP (-5072)
#endif
#ifndef EDOTDOT
#define EDOTDOT (-5073)
#endif
#ifndef EBADMSG
#define EBADMSG (-5074)
#endif
#ifndef EOVERFLOW
#define EOVERFLOW (-5075)
#endif
#ifndef ENOTUNIQ
#define ENOTUNIQ (-5076)
#endif
#ifndef EBADFD
#define EBADFD (-5077)
#endif
#ifndef EREMCHG
#define EREMCHG (-5078)
#endif
#ifndef ELIBACC
#define ELIBACC (-5079)
#endif
#ifndef ELIBBAD
#define ELIBBAD (-5080)
#endif
#ifndef ELIBSCN
#define ELIBSCN (-5081)
#endif
#ifndef ELIBMAX
#define ELIBMAX (-5082)
#endif
#ifndef ELIBEXEC
#define ELIBEXEC (-5083)
#endif
#ifndef EILSEQ
#define EILSEQ (-5084)
#endif
#ifndef ERESTART
#define ERESTART (-5085)
#endif
#ifndef ESTRPIPE
#define ESTRPIPE (-5086)
#endif
#ifndef EUSERS
#define EUSERS (-5087)
#endif
#ifndef ENOTSOCK
#define ENOTSOCK (-5088)
#endif
#ifndef EDESTADDRREQ
#define EDESTADDRREQ (-5089)
#endif
#ifndef EMSGSIZE
#define EMSGSIZE (-5090)
#endif
#ifndef EPROTOTYPE
#define EPROTOTYPE (-5091)
#endif
#ifndef ENOPROTOOPT
#define ENOPROTOOPT (-5092)
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT (-5093)
#endif
#ifndef ESOCKTNOSUPPORT
#define ESOCKTNOSUPPORT (-5094)
#endif
#ifndef EOPNOTSUPP
#define EOPNOTSUPP (-5095)
#endif
#ifndef EPFNOSUPPORT
#define EPFNOSUPPORT (-5096)
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT (-5097)
#endif
#ifndef EADDRINUSE
#define EADDRINUSE (-5098)
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL (-5099)
#endif
#ifndef ENETDOWN
#define ENETDOWN (-5100)
#endif
#ifndef ENETUNREACH
#define ENETUNREACH (-5101)
#endif
#ifndef ENETRESET
#define ENETRESET (-5102)
#endif
#ifndef ECONNABORTED
#define ECONNABORTED (-5103)
#endif
#ifndef ECONNRESET
#define ECONNRESET (-5104)
#endif
#ifndef ENOBUFS
#define ENOBUFS (-5105)
#endif
#ifndef EISCONN
#define EISCONN (-5106)
#endif
#ifndef ENOTCONN
#define ENOTCONN (-5107)
#endif
#ifndef ESHUTDOWN
#define ESHUTDOWN (-5108)
#endif
#ifndef ETOOMANYREFS
#define ETOOMANYREFS (-5109)
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT (-5110)
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED (-5111)
#endif
#ifndef EHOSTDOWN
#define EHOSTDOWN (-5112)
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH (-5113)
#endif
#ifndef EALREADY
#define EALREADY (-5114)
#endif
#ifndef EINPROGRESS
#define EINPROGRESS (-5115)
#endif
#ifndef ESTALE
#define ESTALE (-5116)
#endif
#ifndef EUCLEAN
#define EUCLEAN (-5117)
#endif
#ifndef ENOTNAM
#define ENOTNAM (-5118)
#endif
#ifndef ENAVAIL
#define ENAVAIL (-5119)
#endif
#ifndef EISNAM
#define EISNAM (-5120)
#endif
#ifndef EREMOTEIO
#define EREMOTEIO (-5121)
#endif
#ifndef EDQUOT
#define EDQUOT (-5122)
#endif
#ifndef ENOMEDIUM
#define ENOMEDIUM (-5123)
#endif
#ifndef EMEDIUMTYPE
#define EMEDIUMTYPE (-5124)
#endif
#ifndef ECANCELED
#define ECANCELED (-5125)
#endif
#ifndef ENOKEY
#define ENOKEY (-5126)
#endif
#ifndef EKEYEXPIRED
#define EKEYEXPIRED (-5127)
#endif
#ifndef EKEYREVOKED
#define EKEYREVOKED (-5128)
#endif
#ifndef EKEYREJECTED
#define EKEYREJECTED (-5129)
#endif
#ifndef EOWNERDEAD
#define EOWNERDEAD (-5130)
#endif
#ifndef ENOTRECOVERABLE
#define ENOTRECOVERABLE (-5131)
#endif
#ifndef ERFKILL
#define ERFKILL (-5132)
#endif
#ifndef EPROCLIM
#define EPROCLIM (-6067)
#endif
#ifndef EBADRPC
#define EBADRPC (-6072)
#endif
#ifndef ERPCMISMATCH
#define ERPCMISMATCH (-6073)
#endif
#ifndef EPROGUNAVAIL
#define EPROGUNAVAIL (-6074)
#endif
#ifndef EPROGMISMATCH
#define EPROGMISMATCH (-6075)
#endif
#ifndef EPROCUNAVAIL
#define EPROCUNAVAIL (-6076)
#endif
#ifndef EFTYPE
#define EFTYPE (-6079)
#endif
#ifndef EAUTH
#define EAUTH (-6080)
#endif
#ifndef ENEEDAUTH
#define ENEEDAUTH (-6081)
#endif
#ifndef ENOATTR
#define ENOATTR (-6087)
#endif
#ifndef ENOTCAPABLE
#define ENOTCAPABLE (-6093)
#endif
#endif

View File

@ -0,0 +1,25 @@
#include "hexparse.h"
static int hexdigit(char x)
{
if (x >= '0' && x <= '9') return x - '0';
if (x >= 'a' && x <= 'f') return 10 + (x - 'a');
if (x >= 'A' && x <= 'F') return 10 + (x - 'A');
return -1;
}
int hexparse(unsigned char *y,long long len,const char *x)
{
if (!x) return 0;
while (len > 0) {
int digit0;
int digit1;
digit0 = hexdigit(x[0]); if (digit0 == -1) return 0;
digit1 = hexdigit(x[1]); if (digit1 == -1) return 0;
*y++ = digit1 + 16 * digit0;
--len;
x += 2;
}
if (x[0]) return 0;
return 1;
}

View File

@ -0,0 +1,6 @@
#ifndef HEXPARSE_H
#define HEXPARSE_H
extern int hexparse(unsigned char *,long long,const char *);
#endif

View File

@ -0,0 +1,33 @@
#include <unistd.h>
#include "open.h"
#include "e.h"
#include "load.h"
static int readall(int fd,void *x,long long xlen)
{
long long r;
while (xlen > 0) {
r = xlen;
if (r > 1048576) r = 1048576;
r = read(fd,x,r);
if (r == 0) errno = EPROTO;
if (r <= 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue;
return -1;
}
x += r;
xlen -= r;
}
return 0;
}
int load(const char *fn,void *x,long long xlen)
{
int fd;
int r;
fd = open_read(fn);
if (fd == -1) return -1;
r = readall(fd,x,xlen);
close(fd);
return r;
}

View File

@ -0,0 +1,6 @@
#ifndef LOAD_H
#define LOAD_H
extern int load(const char *,void *,long long);
#endif

View File

@ -0,0 +1,19 @@
#include "nameparse.h"
int nameparse(unsigned char *s,const char *x)
{
long long pos;
long long j;
if (!x) return 0;
for (pos = 0;pos < 256;++pos) s[pos] = 0;
pos = 0;
while (*x) {
if (*x == '.') { ++x; continue; }
for (j = 0;x[j];++j) if (x[j] == '.') break;
if (j > 63) return 0;
if (pos < 0 || pos >= 256) return 0; s[pos++] = j;
while (j > 0) { if (pos < 0 || pos >= 256) return 0; s[pos++] = *x++; --j; }
}
if (pos < 0 || pos >= 256) return 0; s[pos++] = 0;
return 1;
}

View File

@ -0,0 +1,6 @@
#ifndef NAMEPARSE_H
#define NAMEPARSE_H
extern int nameparse(unsigned char *,const char *);
#endif

View File

@ -0,0 +1,19 @@
#include <sys/time.h>
#include <time.h>
#include "nanoseconds.h"
/* XXX: Y2036 problems; should upgrade to a 128-bit type for this */
/* XXX: nanosecond granularity limits users to 1 terabyte per second */
long long nanoseconds(void)
{
#ifdef CLOCK_REALTIME
struct timespec t;
if (clock_gettime(CLOCK_REALTIME,&t) != 0) return -1;
return t.tv_sec * 1000000000LL + t.tv_nsec;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000000LL + tv.tv_usec * 1000LL;
#endif
}

View File

@ -0,0 +1,6 @@
#ifndef NANOSECONDS_H
#define NANOSECONDS_H
extern long long nanoseconds(void);
#endif

View File

@ -0,0 +1,10 @@
#ifndef OPEN_H
#define OPEN_H
extern int open_read(const char *);
extern int open_write(const char *);
extern int open_lock(const char *);
extern int open_cwd(void);
extern int open_pipe(int *);
#endif

View File

@ -0,0 +1,6 @@
#include "open.h"
int open_cwd(void)
{
return open_read(".");
}

View File

@ -0,0 +1,19 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "open.h"
int open_lock(const char *fn)
{
#ifdef O_CLOEXEC
int fd = open(fn,O_RDWR | O_CLOEXEC);
if (fd == -1) return -1;
#else
int fd = open(fn,O_RDWR);
if (fd == -1) return -1;
fcntl(fd,F_SETFD,1);
#endif
if (lockf(fd,F_LOCK,0) == -1) { close(fd); return -1; }
return fd;
}

View File

@ -0,0 +1,15 @@
#include <unistd.h>
#include <fcntl.h>
#include "open.h"
#include "blocking.h"
int open_pipe(int *fd)
{
int i;
if (pipe(fd) == -1) return -1;
for (i = 0;i < 2;++i) {
fcntl(fd[i],F_SETFD,1);
blocking_disable(fd[i]);
}
return 0;
}

View File

@ -0,0 +1,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "open.h"
int open_read(const char *fn)
{
#ifdef O_CLOEXEC
return open(fn,O_RDONLY | O_NONBLOCK | O_CLOEXEC);
#else
int fd = open(fn,O_RDONLY | O_NONBLOCK);
if (fd == -1) return -1;
fcntl(fd,F_SETFD,1);
return fd;
#endif
}

View File

@ -0,0 +1,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "open.h"
int open_write(const char *fn)
{
#ifdef O_CLOEXEC
return open(fn,O_CREAT | O_WRONLY | O_NONBLOCK | O_CLOEXEC,0644);
#else
int fd = open(fn,O_CREAT | O_WRONLY | O_NONBLOCK,0644);
if (fd == -1) return -1;
fcntl(fd,F_SETFD,1);
return fd;
#endif
}

View File

@ -0,0 +1,14 @@
#include "portparse.h"
int portparse(unsigned char *y,const char *x)
{
long long d = 0;
long long j;
for (j = 0;j < 5 && x[j] >= '0' && x[j] <= '9';++j)
d = d * 10 + (x[j] - '0');
if (j == 0) return 0;
if (x[j]) return 0;
y[0] = d >> 8;
y[1] = d;
return 1;
}

View File

@ -0,0 +1,6 @@
#ifndef PORTPARSE_H
#define PORTPARSE_H
extern int portparse(unsigned char *,const char *);
#endif

View File

@ -0,0 +1,14 @@
#include "randombytes.h"
/* XXX: current implementation is limited to n<2^55 */
long long randommod(long long n)
{
long long result = 0;
long long j;
unsigned char r[32];
if (n <= 1) return 0;
randombytes(r,32);
for (j = 0;j < 32;++j) result = (result * 256 + (unsigned long long) r[j]) % n;
return result;
}

View File

@ -0,0 +1,6 @@
#ifndef RANDOMMOD_H
#define RANDOMMOD_H
extern long long randommod(long long);
#endif

View File

@ -0,0 +1,74 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "crypto_uint64.h"
#include "uint64_pack.h"
#include "uint64_unpack.h"
#include "savesync.h"
#include "open.h"
#include "load.h"
#include "randombytes.h"
#include "safenonce.h"
#include "crypto_block.h"
#if crypto_block_BYTES != 16
error!
#endif
#if crypto_block_KEYBYTES != 32
error!
#endif
/*
Output: 128-bit nonce y[0],...,y[15].
Reads and writes existing 8-byte file ".expertsonly/noncecounter",
locked via existing 1-byte file ".expertsonly/lock".
Also reads existing 32-byte file ".expertsonly/noncekey".
Not thread-safe.
Invariants:
This process is free to use counters that are >=counterlow and <counterhigh.
The 8-byte file contains a counter that is safe to use and >=counterhigh.
XXX: should rewrite file in background, rather than briefly pausing
*/
static crypto_uint64 counterlow = 0;
static crypto_uint64 counterhigh = 0;
static unsigned char flagkeyloaded = 0;
static unsigned char noncekey[32];
static unsigned char data[16];
int safenonce(unsigned char *y,int flaglongterm)
{
if (!flagkeyloaded) {
int fdlock;
fdlock = open_lock(".expertsonly/lock");
if (fdlock == -1) return -1;
if (load(".expertsonly/noncekey",noncekey,sizeof noncekey) == -1) { close(fdlock); return -1; }
close(fdlock);
flagkeyloaded = 1;
}
if (counterlow >= counterhigh) {
int fdlock;
fdlock = open_lock(".expertsonly/lock");
if (fdlock == -1) return -1;
if (load(".expertsonly/noncecounter",data,8) == -1) { close(fdlock); return -1; }
counterlow = uint64_unpack(data);
if (flaglongterm)
counterhigh = counterlow + 1048576;
else
counterhigh = counterlow + 1;
uint64_pack(data,counterhigh);
if (savesync(".expertsonly/noncecounter",data,8) == -1) { close(fdlock); return -1; }
close(fdlock);
}
randombytes(data + 8,8);
uint64_pack(data,counterlow++);
crypto_block(y,data,noncekey);
return 0;
}

View File

@ -0,0 +1,6 @@
#ifndef SAFENONCE_H
#define SAFENONCE_H
extern int safenonce(unsigned char *,int);
#endif

View File

@ -0,0 +1,24 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "open.h"
#include "savesync.h"
#include "writeall.h"
static int writesync(int fd,const void *x,long long xlen)
{
if (writeall(fd,x,xlen) == -1) return -1;
return fsync(fd);
}
int savesync(const char *fn,const void *x,long long xlen)
{
int fd;
int r;
fd = open_write(fn);
if (fd == -1) return -1;
r = writesync(fd,x,xlen);
close(fd);
return r;
}

View File

@ -0,0 +1,6 @@
#ifndef SAVESYNC_H
#define SAVESYNC_H
extern int savesync(const char *,const void *,long long);
#endif

View File

@ -0,0 +1,9 @@
#ifndef SOCKET_H
#define SOCKET_H
extern int socket_udp(void);
extern int socket_bind(int,const unsigned char *,const unsigned char *);
extern int socket_send(int,const unsigned char *,long long,const unsigned char *,const unsigned char *);
extern long long socket_recv(int,unsigned char *,long long,unsigned char *,unsigned char *);
#endif

View File

@ -0,0 +1,15 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "socket.h"
#include "byte.h"
int socket_bind(int fd,const unsigned char *ip,const unsigned char *port)
{
struct sockaddr_in sa;
byte_zero(&sa,sizeof sa);
byte_copy(&sa.sin_addr,4,ip);
byte_copy(&sa.sin_port,2,port);
return bind(fd,(struct sockaddr *) &sa,sizeof sa);
}

View File

@ -0,0 +1,24 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "e.h"
#include "socket.h"
#include "byte.h"
long long socket_recv(int fd,unsigned char *x,long long xlen,unsigned char *ip,unsigned char *port)
{
struct sockaddr_in sa;
socklen_t salen;
int r;
if (xlen < 0) { errno = EPROTO; return -1; }
if (xlen > 1048576) xlen = 1048576;
byte_zero(&sa,sizeof sa);
salen = sizeof sa;
r = recvfrom(fd,x,xlen,0,(struct sockaddr *) &sa,&salen);
byte_copy(ip,4,&sa.sin_addr);
byte_copy(port,2,&sa.sin_port);
return r;
}

View File

@ -0,0 +1,20 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "e.h"
#include "socket.h"
#include "byte.h"
int socket_send(int fd,const unsigned char *x,long long xlen,const unsigned char *ip,const unsigned char *port)
{
struct sockaddr_in sa;
if (xlen < 0 || xlen > 1048576) { errno = EPROTO; return -1; }
byte_zero(&sa,sizeof sa);
sa.sin_family = AF_INET;
byte_copy(&sa.sin_addr,4,ip);
byte_copy(&sa.sin_port,2,port);
return sendto(fd,x,xlen,0,(struct sockaddr *) &sa,sizeof sa);
}

View File

@ -0,0 +1,36 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "socket.h"
#include "blocking.h"
static void enable_bsd_fragmentation(int fd)
{
#ifdef IP_DONTFRAG
const int x = 0;
setsockopt(fd,SOL_IP,IP_DONTFRAG,&x,sizeof x);
#endif
}
static void enable_linux_fragmentation(int fd)
{
#ifdef IP_MTU_DISCOVER
#ifdef IP_PMTUDISC_DONT
const int x = IP_PMTUDISC_DONT;
setsockopt(fd,SOL_IP,IP_MTU_DISCOVER,&x,sizeof x);
#endif
#endif
}
int socket_udp(void)
{
int fd = socket(PF_INET,SOCK_DGRAM,0);
if (fd == -1) return -1;
fcntl(fd,F_SETFD,1);
blocking_disable(fd);
enable_bsd_fragmentation(fd);
enable_linux_fragmentation(fd);
return fd;
}

View File

@ -0,0 +1,7 @@
#include "uint16_pack.h"
void uint16_pack(unsigned char *y,crypto_uint16 x)
{
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT16_PACK_H
#define UINT16_PACK_H
#include "crypto_uint16.h"
extern void uint16_pack(unsigned char *,crypto_uint16);
#endif

View File

@ -0,0 +1,9 @@
#include "uint16_unpack.h"
crypto_uint16 uint16_unpack(const unsigned char *x)
{
crypto_uint16 result;
result = x[1];
result <<= 8; result |= x[0];
return result;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT16_UNPACK_H
#define UINT16_UNPACK_H
#include "crypto_uint16.h"
extern crypto_uint16 uint16_unpack(const unsigned char *);
#endif

View File

@ -0,0 +1,9 @@
#include "uint32_pack.h"
void uint32_pack(unsigned char *y,crypto_uint32 x)
{
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT32_PACK_H
#define UINT32_PACK_H
#include "crypto_uint32.h"
extern void uint32_pack(unsigned char *,crypto_uint32);
#endif

View File

@ -0,0 +1,11 @@
#include "uint32_unpack.h"
crypto_uint32 uint32_unpack(const unsigned char *x)
{
crypto_uint32 result;
result = x[3];
result <<= 8; result |= x[2];
result <<= 8; result |= x[1];
result <<= 8; result |= x[0];
return result;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT32_UNPACK_H
#define UINT32_UNPACK_H
#include "crypto_uint32.h"
extern crypto_uint32 uint32_unpack(const unsigned char *);
#endif

View File

@ -0,0 +1,13 @@
#include "uint64_pack.h"
void uint64_pack(unsigned char *y,crypto_uint64 x)
{
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
*y++ = x; x >>= 8;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT64_PACK_H
#define UINT64_PACK_H
#include "crypto_uint64.h"
extern void uint64_pack(unsigned char *,crypto_uint64);
#endif

View File

@ -0,0 +1,15 @@
#include "uint64_unpack.h"
crypto_uint64 uint64_unpack(const unsigned char *x)
{
crypto_uint64 result;
result = x[7];
result <<= 8; result |= x[6];
result <<= 8; result |= x[5];
result <<= 8; result |= x[4];
result <<= 8; result |= x[3];
result <<= 8; result |= x[2];
result <<= 8; result |= x[1];
result <<= 8; result |= x[0];
return result;
}

View File

@ -0,0 +1,8 @@
#ifndef UINT64_UNPACK_H
#define UINT64_UNPACK_H
#include "crypto_uint64.h"
extern crypto_uint64 uint64_unpack(const unsigned char *);
#endif

View File

@ -0,0 +1,27 @@
#include <poll.h>
#include <unistd.h>
#include "e.h"
#include "writeall.h"
int writeall(int fd,const void *x,long long xlen)
{
long long w;
while (xlen > 0) {
w = xlen;
if (w > 1048576) w = 1048576;
w = write(fd,x,w);
if (w < 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
struct pollfd p;
p.fd = fd;
p.events = POLLOUT | POLLERR;
poll(&p,1,-1);
continue;
}
return -1;
}
x += w;
xlen -= w;
}
return 0;
}

View File

@ -0,0 +1,6 @@
#ifndef WRITEALL_H
#define WRITEALL_H
extern int writeall(int,const void *,long long);
#endif