added pcp_ed_verify_buffered() [doesnt work yet, needs debugging]

This commit is contained in:
TLINDEN
2014-01-23 23:36:57 +01:00
parent c717c060ec
commit 7b7aa6d395
5 changed files with 166 additions and 44 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -26,13 +26,31 @@
#define _HAVE_PCP_UTIL_H
#include <ctype.h>
#include <wctype.h>
// lowercase a string
static inline char *_lc(char *in) {
size_t len = strlen(in);
int i;
size_t i;
for(i=0; i<len; ++i)
in[i] = towlower(in[i]);
return in;
}
// find the offset of the beginning of a certain string within binary data
static inline int _findoffset(unsigned char *bin, size_t binlen, char *sigstart, size_t hlen) {
size_t i;
int sigfoot = 181; // yes, also bad. that's the armored sig footer
int offset = -1;
for(i=0; i<binlen-sigfoot; ++i) {
if(memcmp(&bin[i], sigstart, hlen) == 0) {
offset = i;
break;
}
}
return offset;
}
#endif // _HAVE_PCP_UTIL_H

View File

@@ -79,9 +79,7 @@ size_t pcp_ed_sign_buffered(FILE *in, FILE *out, pcp_key_t *s, int z85) {
crypto_sign(signature, &mlen, hash, crypto_generichash_BYTES_MAX, s->edsecret);
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;
}

View File

@@ -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;