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
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
B<Pretty Curved Privacy> (pcp1) is a commandline utility which can
|
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>.
|
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
|
#ifndef _HAVE_PCP_PLIST_H
|
||||||
#define _HAVE_PCP_PLIST_H
|
#define _HAVE_PCP_PLIST_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
struct _plist_t {
|
struct _plist_t {
|
||||||
char *value;
|
char *value;
|
||||||
struct _plist_t *next;
|
struct _plist_t *next;
|
||||||
|
struct _plist_t *first;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _plist_t plist_t;
|
typedef struct _plist_t plist_t;
|
||||||
|
|
||||||
static inline void p_add(plist_t **lst, char *value) {
|
static inline void p_add(plist_t **lst, char *value) {
|
||||||
plist_t *newitem;
|
plist_t *newitem;
|
||||||
plist_t *lst_iter = *lst;
|
plist_t *iter = *lst;
|
||||||
|
|
||||||
newitem = (plist_t *)malloc(sizeof(plist_t));
|
newitem = (plist_t *)malloc(sizeof(plist_t));
|
||||||
newitem->value = malloc(strlen(value) + 1);
|
newitem->value = malloc(strlen(value) + 1);
|
||||||
strncpy(newitem->value, value, strlen(value) + 1);
|
strncpy(newitem->value, value, strlen(value) + 1);
|
||||||
newitem->next = NULL;
|
newitem->next = NULL;
|
||||||
|
|
||||||
if ( lst_iter != NULL ) {
|
if ( iter != NULL ) {
|
||||||
while (lst_iter->next != NULL )
|
while (iter->next != NULL ) {
|
||||||
lst_iter = lst_iter->next;
|
iter = iter->next;
|
||||||
lst_iter->next = newitem;
|
}
|
||||||
|
newitem->first = iter->first;
|
||||||
|
iter->next = newitem;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
newitem->first = newitem;
|
||||||
*lst = 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
|
#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) {
|
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;
|
unsigned char *input = NULL;
|
||||||
size_t inputBufSize = 0;
|
size_t inputBufSize = 0;
|
||||||
unsigned char byte[1];
|
unsigned char byte[1];
|
||||||
|
|||||||
@@ -124,15 +124,33 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// found one by id, copy into local hash
|
// 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));
|
memcpy(pub, tmp, sizeof(pcp_pubkey_t));
|
||||||
HASH_ADD_STR( pubhash, id, tmp);
|
HASH_ADD_STR( pubhash, id, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(recipient != NULL) {
|
else if(recipient != NULL) {
|
||||||
// lookup by recipient list
|
// lookup by recipient list
|
||||||
// FIXME: implement, iterate through global hashlist
|
// iterate through global hashlist
|
||||||
// copy matches into temporary pubhash
|
// 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 {
|
else {
|
||||||
fatal("id or recipient list required!\n");
|
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);
|
size_t clen = pcp_encrypt_file(in, out, secret, pubhash, self);
|
||||||
|
|
||||||
if(clen > 0) {
|
if(clen > 0) {
|
||||||
fprintf(stderr, "Encrypted %d bytes for 0x%s successfully\n", (int)clen, id);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
erren2:
|
erren2:
|
||||||
free(pubhash);
|
free(pubhash); // FIXME: it's a uthash, dont use free() but func instead
|
||||||
free(tmp);
|
free(tmp);
|
||||||
free(pub);
|
free(pub);
|
||||||
|
|
||||||
|
|||||||
@@ -490,10 +490,3 @@ char *pcp_find_id_byrec(char *recipient) {
|
|||||||
return id;
|
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 "readpass.h"
|
||||||
#include "keyprint.h"
|
#include "keyprint.h"
|
||||||
#include "keyhash.h"
|
#include "keyhash.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define _WITH_GETLINE
|
#define _WITH_GETLINE
|
||||||
|
|
||||||
@@ -55,6 +56,5 @@ int pcp_importpublic (vault_t *vault, FILE *in);
|
|||||||
int pcp_importsecret (vault_t *vault, FILE *in);
|
int pcp_importsecret (vault_t *vault, FILE *in);
|
||||||
void pcpdelete_key(char *keyid);
|
void pcpdelete_key(char *keyid);
|
||||||
char *pcp_find_id_byrec(char *recipient);
|
char *pcp_find_id_byrec(char *recipient);
|
||||||
char *_lc(char *in);
|
|
||||||
|
|
||||||
#endif // _HAVE_KEYMGMT_H
|
#endif // _HAVE_KEYMGMT_H
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ int main (int argc, char **argv) {
|
|||||||
useid = 0;
|
useid = 0;
|
||||||
userec = 0;
|
userec = 0;
|
||||||
lo = 0;
|
lo = 0;
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
// generics
|
// generics
|
||||||
{ "vault", required_argument, NULL, 'V' },
|
{ "vault", required_argument, NULL, 'V' },
|
||||||
@@ -334,7 +333,7 @@ int main (int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
else if(useid == 0 && userec == 1) {
|
else if(useid == 0 && userec == 1) {
|
||||||
// multiple dst
|
// multiple dst
|
||||||
pcpencrypt(id, infile, outfile, xpass, recipient);
|
pcpencrypt(NULL, infile, outfile, xpass, recipient);
|
||||||
}
|
}
|
||||||
else if(useid == 0 && userec == 0) {
|
else if(useid == 0 && userec == 0) {
|
||||||
// self mode
|
// self mode
|
||||||
@@ -352,7 +351,7 @@ int main (int argc, char **argv) {
|
|||||||
if(xpass != NULL)
|
if(xpass != NULL)
|
||||||
free(xpass);
|
free(xpass);
|
||||||
if(recipient != NULL)
|
if(recipient != NULL)
|
||||||
free(recipient);
|
p_clean(recipient);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user