Compile curvecp. This will be optional and disabled by default as it is
not exactly portable.
This commit is contained in:
parent
6774b47cd4
commit
60d788a444
7
.gitignore
vendored
7
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -93,4 +93,5 @@ libsodium_la_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libsodium/include/sodium
|
||||
|
||||
SUBDIRS = \
|
||||
curvecp \
|
||||
include
|
||||
|
97
src/libsodium/curvecp/Makefile.am
Normal file
97
src/libsodium/curvecp/Makefile.am
Normal 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
|
12
src/libsodium/curvecp/blocking.c
Normal file
12
src/libsodium/curvecp/blocking.c
Normal 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);
|
||||
}
|
7
src/libsodium/curvecp/blocking.h
Normal file
7
src/libsodium/curvecp/blocking.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef BLOCKING_H
|
||||
#define BLOCKING_H
|
||||
|
||||
extern void blocking_enable(int);
|
||||
extern void blocking_disable(int);
|
||||
|
||||
#endif
|
8
src/libsodium/curvecp/byte.h
Normal file
8
src/libsodium/curvecp/byte.h
Normal 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
|
8
src/libsodium/curvecp/byte_copy.c
Normal file
8
src/libsodium/curvecp/byte_copy.c
Normal 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; }
|
||||
}
|
10
src/libsodium/curvecp/byte_isequal.c
Normal file
10
src/libsodium/curvecp/byte_isequal.c
Normal 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;
|
||||
}
|
7
src/libsodium/curvecp/byte_zero.c
Normal file
7
src/libsodium/curvecp/byte_zero.c
Normal 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; }
|
||||
}
|
35
src/libsodium/curvecp/crypto_block.c
Normal file
35
src/libsodium/curvecp/crypto_block.c
Normal 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;
|
||||
}
|
4
src/libsodium/curvecp/crypto_block.h
Normal file
4
src/libsodium/curvecp/crypto_block.h
Normal 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 *);
|
476
src/libsodium/curvecp/curvecpclient.c
Normal file
476
src/libsodium/curvecp/curvecpclient.c
Normal 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);
|
||||
}
|
57
src/libsodium/curvecp/curvecpmakekey.c
Normal file
57
src/libsodium/curvecp/curvecpmakekey.c
Normal 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;
|
||||
}
|
654
src/libsodium/curvecp/curvecpmessage.c
Normal file
654
src/libsodium/curvecp/curvecpmessage.c
Normal 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);
|
||||
}
|
46
src/libsodium/curvecp/curvecpprintkey.c
Normal file
46
src/libsodium/curvecp/curvecpprintkey.c
Normal 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;
|
||||
}
|
497
src/libsodium/curvecp/curvecpserver.c
Normal file
497
src/libsodium/curvecp/curvecpserver.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
42
src/libsodium/curvecp/die.c
Normal file
42
src/libsodium/curvecp/die.c
Normal 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);
|
||||
}
|
16
src/libsodium/curvecp/die.h
Normal file
16
src/libsodium/curvecp/die.h
Normal 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
106
src/libsodium/curvecp/e.c
Normal 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
438
src/libsodium/curvecp/e.h
Normal 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
|
25
src/libsodium/curvecp/hexparse.c
Normal file
25
src/libsodium/curvecp/hexparse.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/hexparse.h
Normal file
6
src/libsodium/curvecp/hexparse.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef HEXPARSE_H
|
||||
#define HEXPARSE_H
|
||||
|
||||
extern int hexparse(unsigned char *,long long,const char *);
|
||||
|
||||
#endif
|
33
src/libsodium/curvecp/load.c
Normal file
33
src/libsodium/curvecp/load.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/load.h
Normal file
6
src/libsodium/curvecp/load.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef LOAD_H
|
||||
#define LOAD_H
|
||||
|
||||
extern int load(const char *,void *,long long);
|
||||
|
||||
#endif
|
19
src/libsodium/curvecp/nameparse.c
Normal file
19
src/libsodium/curvecp/nameparse.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/nameparse.h
Normal file
6
src/libsodium/curvecp/nameparse.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef NAMEPARSE_H
|
||||
#define NAMEPARSE_H
|
||||
|
||||
extern int nameparse(unsigned char *,const char *);
|
||||
|
||||
#endif
|
19
src/libsodium/curvecp/nanoseconds.c
Normal file
19
src/libsodium/curvecp/nanoseconds.c
Normal 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
|
||||
}
|
6
src/libsodium/curvecp/nanoseconds.h
Normal file
6
src/libsodium/curvecp/nanoseconds.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef NANOSECONDS_H
|
||||
#define NANOSECONDS_H
|
||||
|
||||
extern long long nanoseconds(void);
|
||||
|
||||
#endif
|
10
src/libsodium/curvecp/open.h
Normal file
10
src/libsodium/curvecp/open.h
Normal 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
|
6
src/libsodium/curvecp/open_cwd.c
Normal file
6
src/libsodium/curvecp/open_cwd.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "open.h"
|
||||
|
||||
int open_cwd(void)
|
||||
{
|
||||
return open_read(".");
|
||||
}
|
19
src/libsodium/curvecp/open_lock.c
Normal file
19
src/libsodium/curvecp/open_lock.c
Normal 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;
|
||||
}
|
15
src/libsodium/curvecp/open_pipe.c
Normal file
15
src/libsodium/curvecp/open_pipe.c
Normal 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;
|
||||
}
|
17
src/libsodium/curvecp/open_read.c
Normal file
17
src/libsodium/curvecp/open_read.c
Normal 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
|
||||
}
|
17
src/libsodium/curvecp/open_write.c
Normal file
17
src/libsodium/curvecp/open_write.c
Normal 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
|
||||
}
|
14
src/libsodium/curvecp/portparse.c
Normal file
14
src/libsodium/curvecp/portparse.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/portparse.h
Normal file
6
src/libsodium/curvecp/portparse.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PORTPARSE_H
|
||||
#define PORTPARSE_H
|
||||
|
||||
extern int portparse(unsigned char *,const char *);
|
||||
|
||||
#endif
|
14
src/libsodium/curvecp/randommod.c
Normal file
14
src/libsodium/curvecp/randommod.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/randommod.h
Normal file
6
src/libsodium/curvecp/randommod.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef RANDOMMOD_H
|
||||
#define RANDOMMOD_H
|
||||
|
||||
extern long long randommod(long long);
|
||||
|
||||
#endif
|
74
src/libsodium/curvecp/safenonce.c
Normal file
74
src/libsodium/curvecp/safenonce.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/safenonce.h
Normal file
6
src/libsodium/curvecp/safenonce.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef SAFENONCE_H
|
||||
#define SAFENONCE_H
|
||||
|
||||
extern int safenonce(unsigned char *,int);
|
||||
|
||||
#endif
|
24
src/libsodium/curvecp/savesync.c
Normal file
24
src/libsodium/curvecp/savesync.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/savesync.h
Normal file
6
src/libsodium/curvecp/savesync.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef SAVESYNC_H
|
||||
#define SAVESYNC_H
|
||||
|
||||
extern int savesync(const char *,const void *,long long);
|
||||
|
||||
#endif
|
9
src/libsodium/curvecp/socket.h
Normal file
9
src/libsodium/curvecp/socket.h
Normal 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
|
15
src/libsodium/curvecp/socket_bind.c
Normal file
15
src/libsodium/curvecp/socket_bind.c
Normal 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);
|
||||
}
|
24
src/libsodium/curvecp/socket_recv.c
Normal file
24
src/libsodium/curvecp/socket_recv.c
Normal 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;
|
||||
}
|
20
src/libsodium/curvecp/socket_send.c
Normal file
20
src/libsodium/curvecp/socket_send.c
Normal 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);
|
||||
}
|
36
src/libsodium/curvecp/socket_udp.c
Normal file
36
src/libsodium/curvecp/socket_udp.c
Normal 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;
|
||||
}
|
7
src/libsodium/curvecp/uint16_pack.c
Normal file
7
src/libsodium/curvecp/uint16_pack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint16_pack.h
Normal file
8
src/libsodium/curvecp/uint16_pack.h
Normal 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
|
9
src/libsodium/curvecp/uint16_unpack.c
Normal file
9
src/libsodium/curvecp/uint16_unpack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint16_unpack.h
Normal file
8
src/libsodium/curvecp/uint16_unpack.h
Normal 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
|
9
src/libsodium/curvecp/uint32_pack.c
Normal file
9
src/libsodium/curvecp/uint32_pack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint32_pack.h
Normal file
8
src/libsodium/curvecp/uint32_pack.h
Normal 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
|
11
src/libsodium/curvecp/uint32_unpack.c
Normal file
11
src/libsodium/curvecp/uint32_unpack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint32_unpack.h
Normal file
8
src/libsodium/curvecp/uint32_unpack.h
Normal 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
|
13
src/libsodium/curvecp/uint64_pack.c
Normal file
13
src/libsodium/curvecp/uint64_pack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint64_pack.h
Normal file
8
src/libsodium/curvecp/uint64_pack.h
Normal 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
|
15
src/libsodium/curvecp/uint64_unpack.c
Normal file
15
src/libsodium/curvecp/uint64_unpack.c
Normal 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;
|
||||
}
|
8
src/libsodium/curvecp/uint64_unpack.h
Normal file
8
src/libsodium/curvecp/uint64_unpack.h
Normal 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
|
27
src/libsodium/curvecp/writeall.c
Normal file
27
src/libsodium/curvecp/writeall.c
Normal 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;
|
||||
}
|
6
src/libsodium/curvecp/writeall.h
Normal file
6
src/libsodium/curvecp/writeall.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef WRITEALL_H
|
||||
#define WRITEALL_H
|
||||
|
||||
extern int writeall(int,const void *,long long);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user