diff --git a/.gitignore b/.gitignore index 3eadcbd..efe5eb0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ inproc tcp ipc da +ch +so example segfault diff --git a/Makefile b/Makefile index 8623d38..679ea13 100644 --- a/Makefile +++ b/Makefile @@ -25,35 +25,40 @@ LIB=$(shell pwd)/opt nanomsg=-Wno-implicit-function-declaration $(LIB)/lib/libnanomsg.a libmill=$(LIB)/lib/libmill.a +sodium=$(LIB)/lib/libsodium.a includes=-I$(LIB)/include -I$(LIB)/include/nanomsg -std=gnu99 clone=git clone --depth 1 https://github.com/ args=--disable-shared --prefix=$(LIB) build=./autogen.sh && ./configure $(args) && make -j 8 && make install ifeq ($(shell uname -s), Darwin) - flags=$(nanomsg) $(libmill) $(includes) + flags=$(nanomsg) $(libmill) $(sodium) $(includes) else - flags=$(nanomsg) $(libmill) -lanl -lrt -lpthread $(includes) -fvisibility=hidden -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_GNU_SOURCE -O3 + flags=$(sodium) $(nanomsg) $(libmill) -lanl -lrt -lpthread $(includes) -fvisibility=hidden -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_GNU_SOURCE -O3 endif - all: install install: @echo libraries will install now into $(shell pwd)/opt/lib sleep 2; rm -rf opt build; mkdir build - cd build; $(clone)sustrik/libmill.git && $(clone)nanomsg/nanomsg.git - cd build/libmill && $(build) && cd ../nanomsg && $(build) + cd build; $(clone)sustrik/libmill.git && $(clone)nanomsg/nanomsg.git && $(clone)jedisct1/libsodium + cd build/libmill && $(build) && cd ../nanomsg && $(build) && cd ../libsodium && $(build) check: cc -o inproc test/inproc.c $(flags) cc -o ipc test/ipc.c $(flags) cc -o tcp test/tcp.c $(flags) cc -o ch test/ch.c $(flags) - ./inproc && ./ipc && ./tcp && ./ch && rm inproc ipc tcp ch + cc -o so test/sodium.c $(flags) + ./inproc && ./ipc && ./tcp && ./ch && ./so && rm inproc ipc tcp ch so @echo verified consistent behavior among common transports +so: + cc -o so test/sodium.c $(flags) + ./so && rm so + run: example.c cc -o example example.c $(flags) ./example diff --git a/readme.markdown b/readme.markdown index d179621..24c8489 100644 --- a/readme.markdown +++ b/readme.markdown @@ -35,6 +35,12 @@ make make run ``` +## test + +```sh +make check +``` + ## contributors diff --git a/test/sodium.c b/test/sodium.c new file mode 100644 index 0000000..f9246d1 --- /dev/null +++ b/test/sodium.c @@ -0,0 +1,174 @@ +/* + + Copyright (c) 2016 Bent Cardan + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom + the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include + +#define MAX_INPUT_LEN 4096 +#define noncehex "e500906852935c3fa50a82ba5deed1cb36c3eb038da7838c" + +/* + * print_hex() is a wrapper around sodium_bin2hex() which allocates + * temporary memory then immediately prints the result followed by \n + */ +static void print_hex(const void *bin, const size_t bin_len) { + char *hex; + size_t hex_size; + + if ( bin_len >= SIZE_MAX / 2 ) + abort(); + + hex_size = bin_len * 2 + 1; + if ((hex = malloc(hex_size)) == NULL) + abort(); + + /* the library supplies a few utility functions like the one below */ + if (sodium_bin2hex(hex, hex_size, bin, bin_len) == NULL) + abort(); + + puts(hex); + free(hex); +} + +size_t reinterpret_msg (const char *normalchar, char *input) { + size_t actual_input_len = strlen(normalchar); + memcpy(input, normalchar, actual_input_len); + return actual_input_len; +} + +void whoswho(int z, char *alice, char *bob) { + if (z) { + strncpy(alice, "alice", 5); + strncpy(bob, "bob", 3); + } else { + strncpy(alice, "bob", 3); + strncpy(bob, "alice", 5); + } +} + + +static coroutine void alice_and_bob ( const char *original_msg, + chan ch, + unixsock s, + unsigned char *n, + unsigned char *n2, + int a) { + + size_t sz = crypto_box_PUBLICKEYBYTES * 2 + 1; /* HEX size of pub keys */ + char hex[sz]; + unsigned char pk[crypto_box_PUBLICKEYBYTES]; /* public key */ + unsigned char ppk[crypto_box_PUBLICKEYBYTES]; /* inbound pub key */ + unsigned char sk[crypto_box_SECRETKEYBYTES]; /* secret key */ + + /* hold the ciphertext */ + unsigned char ciphertext[crypto_box_MACBYTES + MAX_INPUT_LEN]; + unsigned char cphrtxtin[crypto_box_MACBYTES + MAX_INPUT_LEN]; + size_t cphr_len; + size_t msz = sizeof ciphertext * 2 + 1; + + unsigned char msg[MAX_INPUT_LEN]; /* used with msg_tmp for outbound */ + unsigned char msgrcv[MAX_INPUT_LEN]; /* used for inbound decipher */ + + /* generate public and private keys */ + crypto_box_keypair(pk, sk); + + /* public key exchange over unix sock */ + sodium_bin2hex(hex, sz, pk, sizeof pk); + unixsend(s, hex, sizeof hex, -1); + unixflush(s, -1); + + char buf[sz]; + size_t nbytes = unixrecv(s, buf, sizeof hex, -1); + buf[nbytes] = '\0'; + + char whoami[6]; + char whoarethey[6]; + whoswho(a, whoami, whoarethey); + + printf("-----\n%s public key: %s\n%s public key: %s\n", + whoami, hex, whoarethey, buf); + sodium_hex2bin(ppk, MAX_INPUT_LEN, buf, nbytes, NULL, NULL, NULL); + + size_t len = reinterpret_msg(original_msg, (char*)msg); + assert (crypto_box_easy(ciphertext, msg, len, n, ppk, sk) == 0); + + char msgout[msz]; + char msgin[msz]; + + cphr_len = crypto_box_MACBYTES + len; + sodium_bin2hex(msgout, msz, ciphertext, cphr_len); + + unixsend(s, msgout, sizeof msgout, -1); + unixflush(s, -1); + nbytes = unixrecv(s, msgin, sizeof msgout, -1); + msgin[nbytes] = '\0'; + + sodium_hex2bin(cphrtxtin, MAX_INPUT_LEN, msgin, nbytes, NULL, &cphr_len, NULL); + + printf("-----\n%s cipher: %s\n%s cipher: ", whoami, msgout, whoarethey); + print_hex(cphrtxtin, cphr_len); + + assert (crypto_box_open_easy(msgrcv, cphrtxtin, cphr_len, n2, ppk, sk) == 0); + + printf("%s's recv'd plaintext: ", whoami); + fwrite(msgrcv, 1U, len, stdout); + putchar('\n'); + + unixclose(s); + chs(ch, int, 1); +} + +int main (const int argc, const char **argv) { + + unsigned char nonce[crypto_box_NONCEBYTES]; + + unixsock a, b; + unixpair(&a, &b); + + if (sodium_init() == -1) + abort(); + + printf("Using libsodium %s\nGenerating nonces..\n", sodium_version_string()); + sodium_hex2bin(nonce, 4096, noncehex, sizeof nonce, NULL, NULL, NULL); + print_hex(nonce, crypto_box_NONCEBYTES); + print_hex(nonce + 1, crypto_box_NONCEBYTES); + + printf("Encrypting and authenticating with %s\n", crypto_box_primitive()); + + chan ch = chmake(int, 0); + + go(alice_and_bob("encrypt this", ch, a, nonce, nonce + 1, 1)); + go(alice_and_bob("encrypt that", ch, b, nonce + 1, nonce, 0)); + + chr(ch, int); + chr(ch, int); + chclose(ch); + + printf("-----\n"); + + return 0; +}