From 7b7aa6d395361bb8fec1400215c594a187cb3858 Mon Sep 17 00:00:00 2001 From: TLINDEN Date: Thu, 23 Jan 2014 23:36:57 +0100 Subject: [PATCH] added pcp_ed_verify_buffered() [doesnt work yet, needs debugging] --- include/pcp/defines.h | 7 ++- include/pcp/ed.h | 4 ++ include/pcp/util.h | 20 ++++++- libpcp/ed.c | 136 +++++++++++++++++++++++++++++++++++++++++- src/signature.c | 43 ++----------- 5 files changed, 166 insertions(+), 44 deletions(-) diff --git a/include/pcp/defines.h b/include/pcp/defines.h index 2510c31..fcbd155 100644 --- a/include/pcp/defines.h +++ b/include/pcp/defines.h @@ -40,9 +40,10 @@ typedef unsigned int qbyte; // Quad byte = 32 bits #define PCP_ZFILE_HEADER "----- BEGIN Z85 ENCODED FILE -----" #define PCP_ZFILE_FOOTER "------ END Z85 ENCODED FILE ------" -#define PCP_SIG_HEADER "----- BEGIN PCP SIGNED MESSAGE -----" -#define PCP_SIG_START "----- BEGIN PCP SIGNATURE -----" -#define PCP_SIG_END "------ END PCP SIGNATURE ------" +#define PCP_SIG_HEADER "----- BEGIN ED25519 SIGNED MESSAGE -----" +#define PCP_SIG_START "----- BEGIN ED25519 SIGNATURE -----" +#define PCP_SIG_END "------ END ED25519 SIGNATURE ------" +#define PCP_SIGPREFIX "\nnacl-" #define PCP_ME "Pretty Curved Privacy" diff --git a/include/pcp/ed.h b/include/pcp/ed.h index adeeb79..9e0bbe3 100644 --- a/include/pcp/ed.h +++ b/include/pcp/ed.h @@ -35,6 +35,8 @@ #include "platform.h" #include "mem.h" #include "key.h" +#include "keyhash.h" +#include "util.h" /* sign a message of messagesize using s->edsecret, if it works return message+signature (size: messagesize + crypto_sign_BYTES), @@ -51,4 +53,6 @@ unsigned char * pcp_ed_verify(unsigned char *signature, size_t siglen, pcp_pubke sig only to the output */ size_t pcp_ed_sign_buffered(FILE *in, FILE *out, pcp_key_t *s, int z85); +unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p); + #endif // _HAVE_PCP_ED_H diff --git a/include/pcp/util.h b/include/pcp/util.h index 82020c0..9746006 100644 --- a/include/pcp/util.h +++ b/include/pcp/util.h @@ -26,13 +26,31 @@ #define _HAVE_PCP_UTIL_H #include +#include +// lowercase a string static inline char *_lc(char *in) { size_t len = strlen(in); - int i; + size_t i; for(i=0; iedsecret); if(z85) { - if(in_buf[cur_bufsize] != '\n') - fprintf(out, "\n"); - fprintf(out, "%s\nVersion: PCP v%d.%d.%d\n\n", PCP_SIG_START, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH); + fprintf(out, "\n%s\nVersion: PCP v%d.%d.%d\n\n", PCP_SIG_START, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH); size_t zlen; char *z85encoded = pcp_z85_encode((unsigned char*)signature, crypto_sign_BYTES, &zlen); fprintf(out, "%s\n%s\n", z85encoded, PCP_SIG_END); @@ -99,3 +97,135 @@ size_t pcp_ed_sign_buffered(FILE *in, FILE *out, pcp_key_t *s, int z85) { return mlen; // ??? } + + +unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) { + unsigned char in_buf[PCP_BLOCK_SIZE]; + size_t cur_bufsize = 0; + int z85 = 0; + crypto_generichash_state *st = ucmalloc(sizeof(crypto_generichash_state)); + unsigned char hash[crypto_generichash_BYTES_MAX]; + char *zhead; + size_t hlen = strlen(PCP_SIG_HEADER); + size_t nextsize = 0; + size_t restsize = 0; + size_t mlen = + crypto_sign_BYTES + crypto_generichash_BYTES_MAX; + unsigned char z85encoded[181]; + unsigned char sighash[mlen]; + unsigned char sig[crypto_sign_BYTES]; + char z85sigstart[] = PCP_SIG_START; + char binsigstart[] = PCP_SIGPREFIX; + int offset = -1; + + crypto_generichash_init(st, NULL, 0, 0); + + // determine sig type, clear or bin + cur_bufsize = hlen + 14; // header + hash name + 3x newline + fread(&in_buf, 1, cur_bufsize, in); + zhead = ucmalloc(cur_bufsize); + memcpy(zhead, in_buf, hlen); + memset(&zhead[hlen], 0, 1); + + if(strncmp(zhead, PCP_SIG_HEADER, hlen) == 0) + z85 = 1; + else + nextsize = cur_bufsize; + + while(!feof(in)) { + if(z85 == 0 && nextsize > 0) { + // bin sig, read blocksize - header and put zheader in front of it again + cur_bufsize = fread(&in_buf[hlen], 1, PCP_BLOCK_SIZE - hlen, in); + memcpy(in_buf, zhead, hlen); + cur_bufsize += hlen; + } + else + cur_bufsize = fread(&in_buf, 1, PCP_BLOCK_SIZE, in); + + if(cur_bufsize <= 0) + break; + + if(z85) { + // look if we need to cut something from the current block + offset = _findoffset(in_buf, cur_bufsize, z85sigstart, strlen(z85sigstart)); + if(offset > 0) { + // we need to cut + restsize = cur_bufsize - offset; // the start of the armor sig + cur_bufsize -= restsize; // bin stuff in front of it, if any + memcpy(z85encoded, &in_buf[offset], restsize); // save the armor sig chunk + } + } + else { + // do the same for the bin sig + offset = _findoffset(in_buf, cur_bufsize, binsigstart, strlen(binsigstart)); + if(offset > 0) { + // we need to cut + restsize = cur_bufsize - offset + strlen(binsigstart); // the start of the bin sig + cur_bufsize -= offset; // bin stuff in front of it, if any + memcpy(sighash, &in_buf[offset + strlen(binsigstart)], restsize); // save the armor sig chunk + } + } + + if(offset == -1) + crypto_generichash_update(st, in_buf, cur_bufsize); + } + + if(offset == -1) { + fatal("Error, the signature doesn't contain the ed25519 signed hash\n"); + goto errvb1; + } + + crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX); + + // pull in the remainder + cur_bufsize = fread(&in_buf, 1, restsize, in); + + // put hashsig together + if(z85) { + memcpy(&z85encoded[restsize], in_buf, cur_bufsize); + char *z85block = pcp_readz85string(z85encoded, restsize + cur_bufsize); + if(z85block == NULL) + goto errvb1; + size_t dstlen; + unsigned char *z85decoded = pcp_z85_decode(z85block, &dstlen); + if(dstlen != mlen) { + fatal("z85 decoded signature didn't result in a proper signed hash\n"); + goto errvb1; + } + memcpy(sighash, z85decoded, mlen); + } + else { + memcpy(&sighash[restsize], in_buf, cur_bufsize); // FIXME: check if cur_bufsize holds enough + } + + // huh, how did we made it til here? + unsigned char *verifiedhash = NULL; + if(p == NULL) { + pcphash_iteratepub(p) { + verifiedhash = pcp_ed_verify(sighash, mlen, p); + if(verifiedhash != NULL) + break; + } + } + else { + verifiedhash = pcp_ed_verify(sighash, mlen, p); + } + + if(verifiedhash == NULL) + goto errvb1; + + + if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) { + // sig verified, but the hash doesn't + fatal("signed hash doesn't match with actual hash of signed file content\n"); + free(verifiedhash); + } + + return verifiedhash; + + + errvb1: + free(st); + free(zhead); + return NULL; +} + diff --git a/src/signature.c b/src/signature.c index 6447767..ad99630 100644 --- a/src/signature.c +++ b/src/signature.c @@ -99,60 +99,29 @@ int pcpverify(char *infile, char *id) { if(id != NULL) HASH_FIND_STR(pcppubkey_hash, id, pub); - /* - if(pub == NULL) { - fatal("Could not find a usable public key in vault %s!\n", - vault->filename); - goto errv3; - } - */ - - unsigned char *input = NULL; - size_t inputBufSize = 0; - unsigned char byte[1]; - - while(!feof(in)) { - if(!fread(&byte, 1, 1, in)) - break; - unsigned char *tmp = realloc(input, inputBufSize + 1); - input = tmp; - memmove(&input[inputBufSize], byte, 1); - inputBufSize ++; - } - fclose(in); - - if(inputBufSize == 0) { - fatal("Input file is empty!\n"); - goto errv4; - } - if(pub != NULL) { - message = pcp_ed_verify(input, inputBufSize, pub); + message = pcp_ed_verify_buffered(in, pub); if(message != NULL) { fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail); } } else { - pcphash_iteratepub(pub) { - message = pcp_ed_verify(input, inputBufSize, pub); - if(message != NULL) { - fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail); - break; - } + // put public key as pub, so verify iterates over our keys + message = pcp_ed_verify_buffered(in, pub); + if(message != NULL) { + fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail); } } if(message == NULL) { - fprintf(stderr, "Could not verify ignature\n"); + fprintf(stderr, "Could not verify signature\n"); } else free(message); - free(input); return 0; errv4: - free(input); errv1: return 1;