diff --git a/TODO b/TODO index d166f19..c56fcea 100644 --- a/TODO +++ b/TODO @@ -25,6 +25,10 @@ Symmetric decrypt mode tries to open vault pcp_find_primary_secret() makes a copy ??? +sym encrypt mac => mac, mac => freebsd and freebsd => mac doesnt work + +c++ destructor double free mess + Python binding, e.g.: py % cdll.LoadLibrary("libsodium.so.8") diff --git a/configure.ac b/configure.ac index fc28e95..382d148 100755 --- a/configure.ac +++ b/configure.ac @@ -62,6 +62,7 @@ AC_TYPE_SIZE_T # Checks for library functions. AC_CHECK_FUNCS( \ arc4random_buf \ + arc4random \ fread \ fopen \ free \ @@ -75,6 +76,7 @@ AC_CHECK_FUNCS( \ memcpy \ perror \ strnlen \ + strnstr \ strlen \ strtol \ sizeof \ diff --git a/include/pcp/config.h.in b/include/pcp/config.h.in index e1afb04..6a08a31 100644 --- a/include/pcp/config.h.in +++ b/include/pcp/config.h.in @@ -1,5 +1,8 @@ /* include/pcp/config.h.in. Generated from configure.ac by autoheader. */ +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + /* Define to 1 if you have the `arc4random_buf' function. */ #undef HAVE_ARC4RANDOM_BUF @@ -115,6 +118,9 @@ /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN +/* Define to 1 if you have the `strnstr' function. */ +#undef HAVE_STRNSTR + /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL diff --git a/include/pcp/platform.h b/include/pcp/platform.h index 3bae160..46c1295 100644 --- a/include/pcp/platform.h +++ b/include/pcp/platform.h @@ -33,11 +33,14 @@ # include # ifndef HAVE_BE32TOH # /* openbsd, use aliases */ +# define be16toh betoh16 # define be32toh betoh32 # define be64toh betoh64 # endif # else /* no sys/endian.h */ # ifdef __CPU_IS_BIG_ENDIAN +# define be16toh(x) (x) +# define htobe16(x) (x) # define be32toh(x) (x) # define htobe32(x) (x) # define be64toh(x) (x) @@ -52,6 +55,8 @@ # error Need either netinet/in.h or arpa/inet.h for ntohl() and htonl() # endif # endif +# define be16toh(x) ((u_int16_t)ntohl((u_int16_t)(x))) +# define htobe16(x) ((u_int16_t)htonl((u_int16_t)(x))) # define be32toh(x) ((u_int32_t)ntohl((u_int32_t)(x))) # define htobe32(x) ((u_int32_t)htonl((u_int32_t)(x))) # define be64toh(x) ((u_int64_t)ntohl((u_int64_t)(x))) @@ -61,20 +66,18 @@ #endif /* HAVE_ENDIAN_H */ -#ifndef HAVE_ARC4RANDOM_BUF -/* shitty OS. we're using libsodium's implementation */ - +#ifndef HAVE_ARC4RANDOM #include - static inline u_int32_t arc4random() { return randombytes_random(); } +#endif +#ifndef HAVE_ARC4RANDOM_BUF +#include static inline void arc4random_buf(void *buf, size_t nbytes) { randombytes((unsigned char*)buf, nbytes); } - - #endif @@ -140,6 +143,47 @@ int vasprintf(char **ret, const char *format, va_list args) { #endif +#ifndef HAVE_STRNLEN +static inline size_t +strnlen(const char *msg, size_t maxlen) +{ + size_t i; + + for (i=0; i +static inline char * +strnstr(const char *s, const char *find, size_t slen) +{ + char c, sc; + size_t len; + + if ((c = *find++) != '\0') { + len = strlen(find); + do { + do { + if (slen-- < 1 || (sc = *s++) == '\0') + return (NULL); + } while (sc != c); + if (len > slen) + return (NULL); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} +#endif + #endif /* !_HAVE_PCP_PLATFORM_H */ + diff --git a/libpcp/buffer.c b/libpcp/buffer.c index 5cae71e..1603380 100644 --- a/libpcp/buffer.c +++ b/libpcp/buffer.c @@ -19,6 +19,8 @@ You can contact me by mail: . */ +#define _GNU_SOURCE /* vasprintf() linux */ + #include "buffer.h" void buffer_init(Buffer *b, size_t blocksize, char *name) { @@ -88,11 +90,12 @@ void buffer_add_str(Buffer *b, const char * fmt, ...) { va_list ap; char *dst; va_start(ap, fmt); - vasprintf(&dst, fmt, ap); + if(vasprintf(&dst, fmt, ap) >= 0) { + if(b->end > 0) + b->end--; + buffer_add(b, dst, strlen(dst)+1); + } va_end(ap); - if(b->end > 0) - b->end--; - buffer_add(b, dst, strlen(dst)+1); free(dst); } diff --git a/libpcp/crypto.c b/libpcp/crypto.c index ec66b4f..e8a796e 100644 --- a/libpcp/crypto.c +++ b/libpcp/crypto.c @@ -600,7 +600,6 @@ size_t pcp_decrypt_stream_sym(Pcpstream *in, Pcpstream* out, byte *symkey, pcp_r #endif } - free(buf_nonce); free(buf_cipher); if(recverify != NULL) { @@ -637,6 +636,8 @@ size_t pcp_decrypt_stream_sym(Pcpstream *in, Pcpstream* out, byte *symkey, pcp_r free(signature_cr); } + free(buf_nonce); + return out_size; } @@ -655,8 +656,8 @@ pcp_rec_t *pcp_rec_new(byte *cipher, size_t clen, pcp_key_t *secret, pcp_pubkey_ r->secret = NULL; if(pub != NULL) { - r->pub = ucmalloc(sizeof(pcp_key_t)); - memcpy(r->pub, pub, sizeof(pcp_key_t)); + r->pub = ucmalloc(sizeof(pcp_pubkey_t)); + memcpy(r->pub, pub, sizeof(pcp_pubkey_t)); } else r->pub = NULL; diff --git a/libpcp/ed.c b/libpcp/ed.c index 9d744a2..a8e1ba5 100644 --- a/libpcp/ed.c +++ b/libpcp/ed.c @@ -22,7 +22,7 @@ #include "ed.h" byte * pcp_ed_verify_key(byte *signature, size_t siglen, pcp_pubkey_t *p) { - byte *message = ucmalloc(siglen - crypto_sign_BYTES); + byte *message = ucmalloc(siglen); unsigned long long mlen; if(crypto_sign_open(message, &mlen, signature, siglen, p->masterpub) != 0) { @@ -142,7 +142,7 @@ pcp_pubkey_t *pcp_ed_verify_buffered(Pcpstream *in, pcp_pubkey_t *p) { byte sighash[mlen]; char z85sigstart[] = "\n" PCP_SIG_START; /* FIXME: verifies, but it misses the \r! */ char binsigstart[] = PCP_SIGPREFIX; - char sigstart[] = PCP_SIG_START; + char sigstart[] = "\n" PCP_SIG_START; size_t siglen, startlen; size_t offset = -1; @@ -172,8 +172,8 @@ pcp_pubkey_t *pcp_ed_verify_buffered(Pcpstream *in, pcp_pubkey_t *p) { } if(z85 == 1) { + /* keep sigstart as is, it's per default set to z85 sigstart */ siglen = zlen; - strcpy(sigstart, z85sigstart); startlen = strlen(z85sigstart); } else { diff --git a/libpcp/fatal.c b/libpcp/fatal.c index 8c84275..9614d2c 100644 --- a/libpcp/fatal.c +++ b/libpcp/fatal.c @@ -19,10 +19,12 @@ You can contact me by mail: . */ +#define _GNU_SOURCE /* vasprintf() linux */ #include "defines.h" #include "platform.h" + #include #include #include @@ -38,11 +40,14 @@ void fatal(const char * fmt, ...) { va_list ap; va_start(ap, fmt); - vasprintf(&PCP_ERR, fmt, ap); - - va_end(ap); - - PCP_ERRSET = 1; + if(vasprintf(&PCP_ERR, fmt, ap) >= 0) { + va_end(ap); + PCP_ERRSET = 1; + } + else { + fprintf(stderr, "Could not store fatal error message %s!\n", fmt); + PCP_ERRSET = 1; + } } void fatals_reset() { @@ -51,7 +56,7 @@ void fatals_reset() { void fatals_ifany() { if(PCP_ERRSET == 1) { - fprintf(stderr, PCP_ERR); + fprintf(stderr, "%s", PCP_ERR); if(errno) { fprintf(stderr, "Error: %s\n", strerror(errno)); } diff --git a/libpcp/mgmt.c b/libpcp/mgmt.c index cfd5e0f..dc142b8 100644 --- a/libpcp/mgmt.c +++ b/libpcp/mgmt.c @@ -19,6 +19,8 @@ You can contact me by mail: . */ +#define _XOPEN_SOURCE /* strptime, linux glibc*/ +#define _BSD_SOURCE #include "mgmt.h" @@ -76,7 +78,7 @@ int _check_sigsubs(Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader) { uint16_t nsize = buffer_get16na(blob); uint16_t vsize = buffer_get16na(blob); - char *notation = ucmalloc(nsize); + char *notation = ucmalloc(nsize+1); if(buffer_get_chunk(blob, notation, nsize) == 0) return 1; diff --git a/libpcp/pcpstream.c b/libpcp/pcpstream.c index 938e04f..361b14c 100644 --- a/libpcp/pcpstream.c +++ b/libpcp/pcpstream.c @@ -19,6 +19,7 @@ You can contact me by mail: . */ +#define _GNU_SOURCE /* vasprintf() linux */ #include "pcpstream.h" Pcpstream *ps_init(void) { @@ -618,17 +619,22 @@ size_t ps_print(Pcpstream *stream, const char * fmt, ...) { va_list ap; char *dst; va_start(ap, fmt); - vasprintf(&dst, fmt, ap); - va_end(ap); - size_t len = strlen(dst); + if(vasprintf(&dst, fmt, ap) >= 0) { + va_end(ap); + size_t len = strlen(dst); - if(stream->is_buffer) { - buffer_add(stream->b, dst, len); + if(stream->is_buffer) { + buffer_add(stream->b, dst, len); + } + else { + len = ps_write(stream, dst, len); + } + + free(dst); return len; } - else { - return ps_write(stream, dst, len); - } + va_end(ap); + return 0; } void ps_close(Pcpstream *stream) { diff --git a/libpcp/scrypt/crypto/crypto_scrypt-nosse.c b/libpcp/scrypt/crypto/crypto_scrypt-nosse.c index cad4d0e..a79b2ac 100644 --- a/libpcp/scrypt/crypto/crypto_scrypt-nosse.c +++ b/libpcp/scrypt/crypto/crypto_scrypt-nosse.c @@ -79,7 +79,7 @@ blkxor(void * dest, void * src, size_t len) static void salsa20_8(uint32_t B[16]) { - uint32_t x[16]; + uint32_t x[16] = {0}; size_t i; blkcpy(x, B, 64); diff --git a/libpcp/vault.c b/libpcp/vault.c index 88cacd8..c0b7e15 100644 --- a/libpcp/vault.c +++ b/libpcp/vault.c @@ -318,7 +318,7 @@ int pcpvault_copy(vault_t *tmp, vault_t *vault) { int tmpsize = ftell(tmp->fd); fseek(tmp->fd, 0, SEEK_SET); byte *in = ucmalloc(tmpsize); - fread(in, tmpsize, 1, tmp->fd); + tmpsize = fread(in, 1, tmpsize, tmp->fd); /* and put it into the new file */ vault->fd = freopen(vault->filename, "wb+", vault->fd); @@ -407,16 +407,21 @@ vault_item_header_t * ih2native(vault_item_header_t *h) { int pcpvault_fetchall(vault_t *vault) { + size_t got = 0; fseek(vault->fd, 0, SEEK_SET); vault_header_t *header = ucmalloc(sizeof(vault_header_t)); vault_item_header_t *item = ucmalloc(sizeof(vault_item_header_t)); - fread(header, sizeof(vault_header_t), 1, vault->fd); + got = fread(header, 1, sizeof(vault_header_t), vault->fd); + if(got < sizeof(vault_header_t)) { + fatal("empty or invalid vault header size (got %ld, expected %ld)\n", got, sizeof(vault_header_t)); + goto err; + } vh2native(header); if(header->fileid == PCP_VAULT_ID && header->version == PCP_VAULT_VERSION) { /* loop over the file and slurp everything in */ - int readpos = 0; + size_t readpos = 0; pcp_key_t *key; pcp_pubkey_t *pubkey; int bytesleft = 0; @@ -431,7 +436,7 @@ int pcpvault_fetchall(vault_t *vault) { readpos = ftell(vault->fd); if(vault->size - readpos >= sizeof(vault_item_header_t)) { /* an item header follows */ - fread(item, sizeof(vault_item_header_t), 1, vault->fd); + got = fread(item, sizeof(vault_item_header_t), 1, vault->fd); ih2native(item); if(item->size > 0) { @@ -444,14 +449,14 @@ int pcpvault_fetchall(vault_t *vault) { item->type == PCP_KEY_TYPE_SECRET) { /* read a secret key */ key = ucmalloc(sizeof(pcp_key_t)); - fread(key, PCP_RAW_KEYSIZE, 1, vault->fd); + got = fread(key, PCP_RAW_KEYSIZE, 1, vault->fd); key2native(key); pcphash_add((void *)key, item->type); } else if(item->type == PCP_KEY_TYPE_PUBLIC) { /* read a public key */ pubkey = ucmalloc(sizeof(pcp_pubkey_t)); - fread(pubkey, PCP_RAW_PUBKEYSIZE, 1, vault->fd); + got = fread(pubkey, PCP_RAW_PUBKEYSIZE, 1, vault->fd); pubkey2native(pubkey); pcphash_add((void *)pubkey, item->type); } diff --git a/src/encryption.c b/src/encryption.c index ad13695..6d8c924 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -70,10 +70,10 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i } else { passphrase = ucmalloc(strlen(passwd)+1); - strncpy(passphrase, passwd, strlen(passwd)+1); + strncpy(passphrase, passwd, strlen(passwd)); } - symkey = pcp_scrypt(passphrase, crypto_secretbox_KEYBYTES, salt, 90); + symkey = pcp_scrypt(passphrase, strlen(passphrase), salt, 90); free(salt); } else { @@ -159,12 +159,12 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec } else { passphrase = ucmalloc(strlen(passwd)+1); - strncpy(passphrase, passwd, strlen(passwd)+1); + strncpy(passphrase, passwd, strlen(passwd)); } byte *salt = ucmalloc(90); /* FIXME: use random salt, concat it with result afterwards */ char stsalt[] = PBP_COMPAT_SALT; memcpy(salt, stsalt, 90); - symkey = pcp_scrypt(passphrase, crypto_secretbox_KEYBYTES, salt, 90); + symkey = pcp_scrypt(passphrase, strlen(passphrase), salt, 90); free(salt); } else if(id != NULL && recipient == NULL) { diff --git a/src/keymgmt.c b/src/keymgmt.c index 1961bb3..86934a8 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -555,7 +555,7 @@ char *pcp_find_id_byrec(char *recipient) { int pcp_import (vault_t *vault, FILE *in, char *passwd) { - byte *buf = ucmalloc(2048); + byte *buf = ucmalloc(PCP_BLOCK_SIZE); size_t bufsize; pcp_pubkey_t *pub = NULL; pcp_key_t *sk = NULL; diff --git a/tests/cpptest.cpp b/tests/cpptest.cpp index 0a62b6c..16d5ae4 100644 --- a/tests/cpptest.cpp +++ b/tests/cpptest.cpp @@ -60,7 +60,8 @@ void test0() { DECRYPTED = _openrd("testcppdecrypted"); char *got = (char *)ucmalloc(10); - fread(got, 1, 6, DECRYPTED); + size_t h; + h = fread(got, 1, 6, DECRYPTED); if(strncmp(got, "HALLO", 5) != 0) { throw pcp::exception(); } diff --git a/tests/md5 b/tests/md5 new file mode 100755 index 0000000..788a152 --- /dev/null +++ b/tests/md5 @@ -0,0 +1,7 @@ +#!/bin/sh +file=$1 +if type md5 > /dev/null 2>&1; then + md5 -q $* +else + md5sum $* | awk '{print $1}' +fi diff --git a/tests/unittests.cfg b/tests/unittests.cfg index 7d30764..316f92e 100644 --- a/tests/unittests.cfg +++ b/tests/unittests.cfg @@ -38,33 +38,33 @@ include keys.cfg - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 8 8 e < ../COPYING | ./pipetest 8 8 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 8 8 e < ../COPYING | ./pipetest 8 8 d | ./md5 expect = /$md5/ - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 8 16 e < ../COPYING | ./pipetest 8 16 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 8 16 e < ../COPYING | ./pipetest 8 16 d | ./md5 expect = /$md5/ - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 16 8 e < ../COPYING | ./pipetest 16 8 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 16 8 e < ../COPYING | ./pipetest 16 8 d | ./md5 expect = /$md5/ - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 64 32 e < ../COPYING | ./pipetest 64 32 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 64 32 e < ../COPYING | ./pipetest 64 32 d | ./md5 expect = /$md5/ - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 32 64 e < ../COPYING | ./pipetest 32 64 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 32 64 e < ../COPYING | ./pipetest 32 64 d | ./md5 expect = /$md5/ - md5 = `md5 -q ../COPYING` - cmd = ./pipetest 64 64 e < ../COPYING | ./pipetest 64 64 d | md5 -q + md5 = `./md5 ../COPYING` + cmd = ./pipetest 64 64 e < ../COPYING | ./pipetest 64 64 d | ./md5 expect = /$md5/