started to implement pbp compatibility, added support for multiple -r options,

using it now to look through the vault for recipients, -i to follow. current
state: encrypt produces output without errors or crashes; decrypt is incompatible
for the moment.
This commit is contained in:
git@daemon.de
2014-01-21 16:11:04 +01:00
parent 6714dd1c3b
commit 26d4ee43c5
8 changed files with 229 additions and 24 deletions

View File

@@ -1,3 +1,10 @@
=head1 CAUTION
B<I'm currently in the process to rewrite major parts of PCP,
especially the asymetric crypto parts. Current master is incompatible
to earlier versions and might or might not work. Head back until
this message disappears. Thanks.>
=head1 DESCRIPTION
B<Pretty Curved Privacy> (pcp1) is a commandline utility which can

View File

@@ -19,37 +19,58 @@
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
// used for recipient- or keyid lists
/*
Simple linked list wrappers,
used for recipient- or keyid lists
*/
#ifndef _HAVE_PCP_PLIST_H
#define _HAVE_PCP_PLIST_H
#include <stdlib.h>
#include <stdio.h>
struct _plist_t {
char *value;
struct _plist_t *next;
struct _plist_t *first;
};
typedef struct _plist_t plist_t;
static inline void p_add(plist_t **lst, char *value) {
plist_t *newitem;
plist_t *lst_iter = *lst;
plist_t *iter = *lst;
newitem = (plist_t *)malloc(sizeof(plist_t));
newitem->value = malloc(strlen(value) + 1);
strncpy(newitem->value, value, strlen(value) + 1);
newitem->next = NULL;
if ( lst_iter != NULL ) {
while (lst_iter->next != NULL )
lst_iter = lst_iter->next;
lst_iter->next = newitem;
if ( iter != NULL ) {
while (iter->next != NULL ) {
iter = iter->next;
}
else
newitem->first = iter->first;
iter->next = newitem;
}
else {
newitem->first = newitem;
*lst = newitem;
}
}
static inline void p_clean(plist_t *lst) {
plist_t *iter = lst->first;
plist_t *tmp;
while (iter != NULL) {
tmp = iter;
iter = iter->next;
free(tmp->value);
free(tmp);
}
}
#endif // _HAVE_PCP_PLIST_H

38
include/pcp/util.h Normal file
View File

@@ -0,0 +1,38 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T. von Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
// various helpers
#ifndef _HAVE_PCP_UTIL_H
#define _HAVE_PCP_UTIL_H
#include <ctype.h>
static inline char *_lc(char *in) {
size_t len = strlen(in);
int i;
for(i=0; i<len; ++i)
in[i] = towlower(in[i]);
return in;
}
#endif // _HAVE_PCP_UTIL_H

View File

@@ -221,6 +221,125 @@ size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s) {
size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int self) {
unsigned char byte[1];
unsigned char *symkey;
int recipient_count;
unsigned char *recipients_cipher;
pcp_pubkey_t *cur, *t;
size_t es;
int nrec;
uint32_t lenrec;
size_t blocksize = 32 * 1024;
size_t cur_bufsize, rec_size, out_size;
unsigned char in_buf[blocksize];
unsigned char *buf_nonce;
unsigned char *buf_cipher;
/*
Correct format should be:
6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...)
where recipients is a concatenated list of
random_nonce|box(temp_keypair.privkey, recipient crypto pk, random_nonce, packet key)
*/
// preparation
// A, generate sym key
symkey = urmalloc(crypto_secretbox_KEYBYTES);
// B, encrypt it asymetrically for each recipient
recipient_count = HASH_COUNT(p);
rec_size = ((crypto_secretbox_KEYBYTES + crypto_box_ZEROBYTES) - crypto_box_BOXZEROBYTES) + crypto_secretbox_NONCEBYTES;
recipients_cipher = ucmalloc(rec_size * recipient_count);
nrec = 0;
HASH_ITER(hh, p, cur, t) {
unsigned char *rec_cipher;
rec_cipher = pcp_box_encrypt(s, cur, symkey, crypto_secretbox_KEYBYTES, &es);
if(es =! rec_size) {
fatal("invalid rec_size, expected %dl, got %dl\n", rec_size, es);
if(rec_cipher != NULL)
free(rec_cipher);
goto errec1;
}
memcpy(&recipients_cipher[nrec * rec_size], rec_cipher, rec_size); // already includes the nonce
nrec++;
free(rec_cipher);
}
// step 1, file header
uint8_t head = 5; // FIXME: use #define
fwrite(&head, 1, 1, out);
fprintf(stderr, "D: header - 1\n");
if(ferror(out) != 0) {
fatal("Failed to write encrypted output!\n");
goto errec1;
}
// step 2, sender's pubkey
fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out);
fprintf(stderr, "D: sender pub - %d\n", crypto_box_PUBLICKEYBYTES);
if(ferror(out) != 0)
goto errec1;
// step 3, len recipients, big endian
lenrec = recipient_count;
lenrec = htobe32(lenrec);
fwrite(&lenrec, 4, 1, out);
fprintf(stderr, "D: %d recipients - 4\n", recipient_count);
if(ferror(out) != 0)
goto errec1;
// step 4, recipient list
fwrite(recipients_cipher, rec_size * recipient_count, 1, out);
fprintf(stderr, "D: recipients - %d * %d\n", rec_size, recipient_count);
if(ferror(out) != 0)
goto errec1;
out_size = 5 + (rec_size * recipient_count) + crypto_box_PUBLICKEYBYTES;
// step 5, actual encrypted data
cur_bufsize = 0;
while(!feof(in)) {
cur_bufsize = fread(&in_buf, 1, blocksize, in);
if(cur_bufsize <= 0)
break;
buf_nonce = pcp_gennonce();
es = pcp_sodium_mac(&buf_cipher, in_buf, cur_bufsize, buf_nonce, symkey);
fwrite(buf_nonce, crypto_secretbox_NONCEBYTES, 1, out);
fprintf(stderr, "D: 32k buf nonce - %d\n", crypto_secretbox_NONCEBYTES);
fwrite(buf_cipher, es, 1, out);
fprintf(stderr, "D: 32k buf cipher - %d\n", es);
free(buf_nonce);
free(buf_cipher);
out_size += crypto_secretbox_NONCEBYTES + es;
}
if(ferror(out) != 0) {
fatal("Failed to write encrypted output!\n");
goto errec2;
}
fclose(in);
fclose(out); // FIXME: check for stdin/stdout
return out_size;
errec2:
errec1:
memset(symkey, 0, crypto_secretbox_KEYBYTES);
free(symkey);
free(recipients_cipher);
fclose(in);
fclose(out);
return 0;
}
size_t OLD_pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int self) {
unsigned char *input = NULL;
size_t inputBufSize = 0;
unsigned char byte[1];

View File

@@ -124,15 +124,33 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
}
else {
// found one by id, copy into local hash
pcp_pubkey_t *pub = ucmalloc(sizeof(pcp_pubkey_t));
pub = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(pub, tmp, sizeof(pcp_pubkey_t));
HASH_ADD_STR( pubhash, id, tmp);
}
}
else if(recipient != NULL) {
// lookup by recipient list
// FIXME: implement, iterate through global hashlist
// iterate through global hashlist
// copy matches into temporary pubhash
plist_t *rec;
pcphash_iteratepub(tmp) {
rec = recipient->first;
while (rec->next != NULL) {
_lc(rec->value);
if(strnstr(tmp->mail, rec->value, 255) != NULL || strnstr(tmp->owner, rec->value, 255) != NULL) {
pub = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(pub, tmp, sizeof(pcp_pubkey_t));
HASH_ADD_STR( pubhash, id, tmp);
//fprintf(stderr, " => found a matching key %s\n", tmp->id);
}
rec = rec->next;
}
}
if(HASH_COUNT(pubhash) == 0) {
fatal("no matching key found for specified recipient(s)!\n");
goto erren3;
}
}
else {
fatal("id or recipient list required!\n");
@@ -164,12 +182,22 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
size_t clen = pcp_encrypt_file(in, out, secret, pubhash, self);
if(clen > 0) {
if(id != NULL)
fprintf(stderr, "Encrypted %d bytes for 0x%s successfully\n", (int)clen, id);
else {
fprintf(stderr, "Encrypted %d bytes for:\n", (int)clen);
pcp_pubkey_t *cur, *t;
HASH_ITER(hh, pubhash, cur, t) {
fprintf(stderr, "%s <%s>\n", cur->owner, cur->mail);
}
free(t);
free(cur);
}
return 0;
}
erren2:
free(pubhash);
free(pubhash); // FIXME: it's a uthash, dont use free() but func instead
free(tmp);
free(pub);

View File

@@ -490,10 +490,3 @@ char *pcp_find_id_byrec(char *recipient) {
return id;
}
char *_lc(char *in) {
size_t len = strlen(in);
int i;
for(i=0; i<len; ++i)
in[i] = towlower(in[i]);
return in;
}

View File

@@ -38,6 +38,7 @@
#include "readpass.h"
#include "keyprint.h"
#include "keyhash.h"
#include "util.h"
#define _WITH_GETLINE
@@ -55,6 +56,5 @@ int pcp_importpublic (vault_t *vault, FILE *in);
int pcp_importsecret (vault_t *vault, FILE *in);
void pcpdelete_key(char *keyid);
char *pcp_find_id_byrec(char *recipient);
char *_lc(char *in);
#endif // _HAVE_KEYMGMT_H

View File

@@ -63,7 +63,6 @@ int main (int argc, char **argv) {
useid = 0;
userec = 0;
lo = 0;
static struct option longopts[] = {
// generics
{ "vault", required_argument, NULL, 'V' },
@@ -334,7 +333,7 @@ int main (int argc, char **argv) {
}
else if(useid == 0 && userec == 1) {
// multiple dst
pcpencrypt(id, infile, outfile, xpass, recipient);
pcpencrypt(NULL, infile, outfile, xpass, recipient);
}
else if(useid == 0 && userec == 0) {
// self mode
@@ -352,7 +351,7 @@ int main (int argc, char **argv) {
if(xpass != NULL)
free(xpass);
if(recipient != NULL)
free(recipient);
p_clean(recipient);
break;