mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
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:
@@ -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
|
||||
|
||||
@@ -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
38
include/pcp/util.h
Normal 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
|
||||
119
libpcp/crypto.c
119
libpcp/crypto.c
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user