added pcpstream, which wraps buffers or file i/o, so crypto code doesn't have to know if it works with a file or a buffer. makes the api much more flexible

This commit is contained in:
TLINDEN
2014-02-15 13:10:51 +01:00
parent 347f155341
commit e78269fceb
12 changed files with 325 additions and 72 deletions

View File

@@ -44,6 +44,11 @@
this one as well is independent of internal structs
in pcp and should therefore be future proof.
Internal api change: added pcpstream, which is a
wrapper around file i/o or buffer i/o. It's used
in libpcp/crypto.c (more to follow), so it depends
on the caller if it works on files or on buffers.
Lots of refactoring have been done to clear things
out and make the system work with the changes
above.

7
TODO
View File

@@ -29,6 +29,13 @@ Unitttests:
- sometimes secret key is empty
libpcp/crypto.c: the stream versions must return the output streams, not close them
crypto.c: In function 'pcp_encrypt_stream':
crypto.c:379: warning: assignment makes integer from pointer without a cast
crypto.c:383: warning: assignment makes integer from pointer without a cast

View File

@@ -43,15 +43,23 @@ Crypto::Crypto(Vault &v, Key &skey, PubKey &pkey) {
bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
pcp_pubkey_t *pubhash = NULL;
HASH_ADD_STR( pubhash, id, P.K);
size_t clen = pcp_encrypt_file(in, out, S.K, pubhash, sign);
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
size_t clen = pcp_encrypt_stream(pin, pout, S.K, pubhash, sign);
if(clen <= 0)
throw exception();
ps_close(pin);
ps_close(pout);
return true;
}
bool Crypto::decrypt(FILE *in, FILE *out, bool verify) {
if(pcp_decrypt_file(in, out, S.K, NULL, verify) <= 0)
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
if(pcp_decrypt_stream(pin, pout, S.K, NULL, verify) <= 0)
throw exception();
ps_close(pin);
ps_close(pout);
return true;
}

View File

@@ -21,6 +21,7 @@ PCPEXPORT = pcp.h \
pcp/base85.h \
pcp/buffer.h \
pcp/mgmt.h \
pcp/pcpstream.h \
pcp/keysig.h
nobase_include_HEADERS = $(PCPEXPORT)

View File

@@ -22,6 +22,7 @@ extern "C" {
#include "pcp/mem.h"
#include "pcp/mgmt.h"
#include "pcp/pad.h"
#include "pcp/pcpstream.h"
#include "pcp/platform.h"
#include "pcp/plist.h"
#include "pcp/randomart.h"

View File

@@ -34,6 +34,7 @@
#include "key.h"
#include "keyhash.h"
#include "ed.h"
#include "pcpstream.h"
size_t pcp_sodium_box(unsigned char **cipher,
unsigned char *cleartext,
@@ -54,13 +55,11 @@ unsigned char *pcp_box_decrypt(pcp_key_t *secret, pcp_pubkey_t *pub,
unsigned char *cipher, size_t ciphersize,
size_t *dsize);
size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt);
size_t pcp_encrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt);
size_t pcp_encrypt_stream_sym(Pcpstream *in, Pcpstream* out, unsigned char *symkey, int havehead, pcp_rec_t *recsign);
size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey, int verify);
size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int havehead, pcp_rec_t *recsign);
size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, pcp_rec_t *recverify);
size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, unsigned char *symkey, int verify);
size_t pcp_decrypt_stream_sym(Pcpstream *in, Pcpstream* out, unsigned char *symkey, pcp_rec_t *recverify);
pcp_rec_t *pcp_rec_new(unsigned char *cipher, size_t clen, pcp_key_t *secret, pcp_pubkey_t *pub);
void pcp_rec_free(pcp_rec_t *r);

90
include/pcp/pcpstream.h Normal file
View File

@@ -0,0 +1,90 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.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: <tom AT vondein DOT org>.
*/
/*
Simple wrapper around FILE streams or Buffers, depending
how the user initialized them. The Pcpstream object behaves
always the same and it doesn't matter how it's backed.
We use it in the lib, e.g. in the crypto routines. That way
we can support blockwise crypto on buffers or files.
Streams are, just like iostreams in c++, either output or
input mode.
*/
#ifndef HAVE_PCP_PCPSTEAM_H
#define HAVE_PCP_PCPSTEAM_H
#include <stdio.h>
#include "mem.h"
#include "util.h"
#include "defines.h"
#include "buffer.h"
struct _pcp_stream_t {
FILE *fd;
Buffer *b;
uint8_t is_buffer;
uint8_t eof;
uint8_t err;
};
typedef struct _pcp_stream_t Pcpstream;
/* initialize a new empty stream */
Pcpstream *ps_init(void);
/* create a new stream, backed with open file
maybe used for in- or output */
Pcpstream *ps_new_file(FILE *backendfd);
/* create a new istream, backed with filled buffer */
Pcpstream *ps_new_inbuffer(Buffer *b);
/* create a new ostream, backed with buffer, which we allocate */
Pcpstream *ps_new_outbuffer();
/* read n bytes from the stream into given buf, return read size.
if there's nothing more to read, it returns 0.
sets eof=1 if end of file or end of buffer has been reached.
sets err=1 if an error occurred, fatals() maybe set, or errno */
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes);
/* write n bytes from the given buf to the stream, return the
number of bytes written. in case of errors it returns 0 and
sets eof and err respectively as ps_read() does. */
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes);
/* return the current read or write offset */
size_t ps_tell(Pcpstream *stream);
/* closes the stream and frees allocated memory, if present */
void ps_close(Pcpstream *stream);
/* returns true (1) of we reached EOF */
int ps_end(Pcpstream *stream);
/* returns true (1) of we had an error */
int ps_err(Pcpstream *stream);
#endif // HAVE_PCP_PCPSTEAM_H

View File

@@ -30,6 +30,6 @@ libpcp1_la_SOURCES = mac.c mem.c pad.c version.c \
vault.c fatal.c jenhash.c digital_crc32.c \
crypto.c ed.c keyhash.c scrypt.c \
scrypt/crypto/sha256.c scrypt/crypto/crypto_scrypt-nosse.c \
base85.c util.c buffer.c mgmt.c keysig.c
base85.c util.c buffer.c mgmt.c keysig.c pcpstream.c
include_HEADERS = ../include/pcp.h

View File

@@ -161,8 +161,7 @@ unsigned char *pcp_box_decrypt(pcp_key_t *secret, pcp_pubkey_t *pub,
return NULL;
}
size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey, int verify) {
size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, unsigned char *symkey, int verify) {
pcp_pubkey_t *cur = NULL;
pcp_pubkey_t *sender = NULL;
unsigned char *reccipher = NULL;
@@ -178,15 +177,15 @@ size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey
#endif
int self = 0;
if(ftell(in) == 1) {
if(ps_tell(in) == 1) {
/* header has already been determined outside the lib */
if(symkey != NULL)
self = 1;
}
else {
/* step 1, check header */
cur_bufsize = fread(head, 1, 1, in);
if(cur_bufsize != 1 && !feof(in) && !ferror(in)) {
cur_bufsize = ps_read(in, head, 1); /* fread(head, 1, 1, in); */
if(cur_bufsize != 1 && !ps_end(in) && !ps_err(in)) {
if(head[0] == PCP_SYM_CIPHER) {
if(symkey != NULL)
self = 1;
@@ -203,21 +202,21 @@ size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey
if(self) {
/* just decrypt symetrically and go outa here */
return pcp_decrypt_file_sym(in, out, symkey, NULL);
return pcp_decrypt_stream_sym(in, out, symkey, NULL);
}
#ifdef PCP_ASYM_ADD_SENDER_PUB
/* step 2, sender's pubkey */
cur_bufsize = fread(&in_buf, 1, crypto_box_PUBLICKEYBYTES, in);
if(cur_bufsize != crypto_box_PUBLICKEYBYTES && !feof(in) && !ferror(in)) {
cur_bufsize = ps_read(in, &in_buf, crypto_box_PUBLICKEYBYTES); /* fread(&in_buf, 1, crypto_box_PUBLICKEYBYTES, in); */
if(cur_bufsize != crypto_box_PUBLICKEYBYTES && !ps_end(in) && !ps_err(in)) {
fatal("Error: input file doesn't contain senders public key\n");
goto errdef1;
}
#endif
/* step 3, check len recipients */
cur_bufsize = fread(&lenrec, 1, 4, in);
if(cur_bufsize != 4 && !feof(in) && !ferror(in)) {
cur_bufsize = ps_read(in, &lenrec, 4); /* fread(&lenrec, 1, 4, in); */
if(cur_bufsize != 4 && !ps_end(in) && !ps_err(in)) {
fatal("Error: input file doesn't contain recipient count\n");
goto errdef1;
}
@@ -231,8 +230,8 @@ size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey
/* step 4, fetch recipient list and try to decrypt it for us */
for(nrec=0; nrec<lenrec; nrec++) {
cur_bufsize = fread(&rec_buf, 1, PCP_ASYM_RECIPIENT_SIZE, in);
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !feof(in) && !ferror(in)) {
cur_bufsize = ps_read(in, &rec_buf, PCP_ASYM_RECIPIENT_SIZE); /* fread(&rec_buf, 1, PCP_ASYM_RECIPIENT_SIZE, in); */
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
fatal("Error: input file corrupted, incomplete or no recipients\n");
goto errdef1;
}
@@ -267,18 +266,18 @@ size_t pcp_decrypt_file(FILE *in, FILE* out, pcp_key_t *s, unsigned char *symkey
/* step 5, actually decrypt the file, finally */
if(verify) {
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur);
return pcp_decrypt_file_sym(in, out, symkey, rec);
return pcp_decrypt_stream_sym(in, out, symkey, rec);
pcp_rec_free(rec);
}
else
return pcp_decrypt_file_sym(in, out, symkey, NULL);
return pcp_decrypt_stream_sym(in, out, symkey, NULL);
errdef1:
return 0;
}
size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int sign) {
size_t pcp_encrypt_stream(Pcpstream *in, Pcpstream *out, pcp_key_t *s, pcp_pubkey_t *p, int sign) {
unsigned char *symkey;
int recipient_count;
unsigned char *recipients_cipher;
@@ -325,33 +324,37 @@ size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int
/* step 1, file header */
head[0] = PCP_ASYM_CIPHER;
fwrite(head, 1, 1, out);
ps_write(out, head, 1);
/* fwrite(head, 1, 1, out); */
/* fprintf(stderr, "D: header - 1\n"); */
if(ferror(out) != 0) {
if(ps_err(out) != 0) {
fatal("Failed to write encrypted output!\n");
goto errec1;
}
#ifdef PCP_ASYM_ADD_SENDER_PUB
/* step 2, sender's pubkey */
fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out);
ps_write(out, s->pub, crypto_box_PUBLICKEYBYTES);
/*fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out); */
/* fprintf(stderr, "D: sender pub - %d\n", crypto_box_PUBLICKEYBYTES); */
if(ferror(out) != 0)
if(ps_err(out) != 0)
goto errec1;
#endif
/* step 3, len recipients, big endian */
lenrec = recipient_count;
lenrec = htobe32(lenrec);
fwrite(&lenrec, 4, 1, out);
ps_write(out, &lenrec, 4);
/* fwrite(&lenrec, 4, 1, out); */
/* fprintf(stderr, "D: %d recipients - 4\n", recipient_count); */
if(ferror(out) != 0)
if(ps_err(out) != 0)
goto errec1;
/* step 4, recipient list */
fwrite(recipients_cipher, rec_size * recipient_count, 1, out);
ps_write(out, recipients_cipher, rec_size * recipient_count);
/* fwrite(recipients_cipher, rec_size * recipient_count, 1, out); */
/* fprintf(stderr, "D: recipients - %ld * %d\n", rec_size, recipient_count); */
if(ferror(out) != 0)
if(ps_err(out) != 0)
goto errec1;
out_size = 5 + (rec_size * recipient_count) + crypto_box_PUBLICKEYBYTES;
@@ -360,11 +363,11 @@ size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int
size_t sym_size = 0;
if(sign) {
pcp_rec_t *rec = pcp_rec_new(recipients_cipher, rec_size * recipient_count, s, NULL);
sym_size = pcp_encrypt_file_sym(in, out, symkey, 1, rec);
sym_size = pcp_encrypt_stream_sym(in, out, symkey, 1, rec);
pcp_rec_free(rec);
}
else
sym_size = pcp_encrypt_file_sym(in, out, symkey, 1, NULL);
sym_size = pcp_encrypt_stream_sym(in, out, symkey, 1, NULL);
if(sym_size == 0)
goto errec1;
@@ -379,15 +382,13 @@ size_t pcp_encrypt_file(FILE *in, FILE* out, pcp_key_t *s, pcp_pubkey_t *p, int
free(symkey);
free(recipients_cipher);
if(fileno(in) != 0)
fclose(in);
if(fileno(out) != 1)
fclose(out);
return 0;
}
size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int havehead, pcp_rec_t *recsign) {
size_t pcp_encrypt_stream_sym(Pcpstream *in, Pcpstream *out, unsigned char *symkey, int havehead, pcp_rec_t *recsign) {
/*
havehead = 0: write the whole thing from here
havehead = 1: no header, being called from asym...
@@ -411,8 +412,9 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
if(havehead == 0) {
head[0] = PCP_SYM_CIPHER;
es = fwrite(head, 1, 1, out);
if(ferror(out) != 0) {
es = ps_write(out, head, 1);
/* es = fwrite(head, 1, 1, out); */
if(ps_err(out) != 0) {
fatal("Failed to write encrypted output!\n");
return 0;
}
@@ -424,13 +426,17 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
/* PCP_BLOCK_SIZE as IV. */
unsigned char *iv = urmalloc(PCP_BLOCK_SIZE);
unsigned char *ivpad = urmalloc(PCP_BLOCK_SIZE_IN - PCP_BLOCK_SIZE);
ps_write(out, ivpad, PCP_BLOCK_SIZE_IN - PCP_BLOCK_SIZE);
ps_write(out, iv, PCP_BLOCK_SIZE);
/*
fwrite(ivpad, PCP_BLOCK_SIZE_IN - PCP_BLOCK_SIZE, 1, out);
fwrite(iv, PCP_BLOCK_SIZE, 1, out);
fwrite(iv, PCP_BLOCK_SIZE, 1, out);*/
#endif
/* 32k-ECB-mode. FIXME: maybe support CBC as well or only use CBC? */
while(!feof(in)) {
cur_bufsize = fread(&in_buf, 1, PCP_BLOCK_SIZE, in);
while(!ps_end(in)) {
cur_bufsize = ps_read(in, &in_buf, PCP_BLOCK_SIZE); /* fread(&in_buf, 1, PCP_BLOCK_SIZE, in); */
if(cur_bufsize <= 0)
break;
buf_nonce = pcp_gennonce();
@@ -441,9 +447,13 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
#endif
es = pcp_sodium_mac(&buf_cipher, in_buf, cur_bufsize, buf_nonce, symkey);
fwrite(buf_nonce, crypto_secretbox_NONCEBYTES, 1, out);
fwrite(buf_cipher, es, 1, out);
ps_write(out, buf_nonce, crypto_secretbox_NONCEBYTES);
ps_write(out, buf_cipher, es);
/*
fwrite(buf_nonce, crypto_secretbox_NONCEBYTES, 1, out);
fwrite(buf_cipher, es, 1, out); */
free(buf_nonce);
free(buf_cipher);
out_size += crypto_secretbox_NONCEBYTES + es;
@@ -457,7 +467,7 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
#endif
}
if(ferror(out) != 0) {
if(ps_err(out) != 0) {
fatal("Failed to write encrypted output!\n");
goto errsym1;
}
@@ -474,19 +484,18 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
/* encrypt it as well */
buf_nonce = pcp_gennonce();
es = pcp_sodium_mac(&buf_cipher, signature, siglen, buf_nonce, symkey);
ps_write(out, buf_nonce, crypto_secretbox_NONCEBYTES);
ps_write(out, buf_cipher, es);
/*
fwrite(buf_nonce, crypto_secretbox_NONCEBYTES, 1, out);
fwrite(buf_cipher, es, 1, out);
fwrite(buf_cipher, es, 1, out); */
free(st);
free(signature);
free(hash);
}
if(fileno(in) != 0)
fclose(in);
if(fileno(out) != 1)
fclose(out);
return out_size;
errsym1:
@@ -494,10 +503,10 @@ size_t pcp_encrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, int have
free(st);
free(hash);
}
return 0;
return NULL;
}
size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, pcp_rec_t *recverify) {
size_t pcp_decrypt_stream_sym(Pcpstream *in, Pcpstream* out, unsigned char *symkey, pcp_rec_t *recverify) {
unsigned char *buf_nonce;
unsigned char *buf_cipher;
unsigned char *buf_clear;
@@ -527,13 +536,13 @@ size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, pcp_rec_
unsigned char *iv = NULL; /* will be filled during 1st loop */
#endif
while(!feof(in)) {
cur_bufsize = fread(&in_buf, 1, PCP_BLOCK_SIZE_IN, in);
while(!ps_end(in)) {
cur_bufsize = ps_read(in, &in_buf, PCP_BLOCK_SIZE_IN); /* fread(&in_buf, 1, PCP_BLOCK_SIZE_IN, in); */
if(cur_bufsize <= PCP_CRYPTO_ADD)
break; /* no valid cipher block */
if(recverify != NULL) {
if(cur_bufsize < PCP_BLOCK_SIZE_IN || feof(in)) {
if(cur_bufsize < PCP_BLOCK_SIZE_IN || ps_end(in)) {
/* pull out signature */
memcpy(signature_cr, &in_buf[cur_bufsize - siglen_cr], siglen_cr);
cur_bufsize -= siglen_cr;
@@ -563,14 +572,15 @@ size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, pcp_rec_
out_size += ciphersize - PCP_CRYPTO_ADD;
if(es == 0) {
fwrite(buf_clear, ciphersize - PCP_CRYPTO_ADD, 1, out);
ps_write(out, buf_clear, ciphersize - PCP_CRYPTO_ADD);
/* fwrite(buf_clear, ciphersize - PCP_CRYPTO_ADD, 1, out); */
if(recverify != NULL)
crypto_generichash_update(st, buf_clear, ciphersize - PCP_CRYPTO_ADD);
free(buf_clear);
if(ferror(out) != 0) {
if(ps_err(out) != 0) {
fatal("Failed to write decrypted output!\n");
out_size = 0;
break;
@@ -625,11 +635,6 @@ size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey, pcp_rec_
free(signature_cr);
}
if(fileno(in) != 0)
fclose(in);
if(fileno(out) != 1)
fclose(out);
return out_size;
}

125
libpcp/pcpstream.c Normal file
View File

@@ -0,0 +1,125 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.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: <tom AT vondein DOT org>.
*/
#include "pcpstream.h"
Pcpstream *ps_init(void) {
Pcpstream *stream = ucmalloc(sizeof(Pcpstream));
stream->b = NULL;
stream->fd = NULL;
stream->is_buffer = 0;
stream->eof = 0;
stream->err = 0;
return stream;
}
Pcpstream *ps_new_file(FILE *backendfd) {
Pcpstream *stream = ps_init();
stream->fd = backendfd;
return stream;
}
Pcpstream *ps_new_inbuffer(Buffer *b) {
Pcpstream *stream = ps_init();
stream->b = b;
stream->is_buffer = 1;
return stream;
}
Pcpstream *ps_new_outbuffer() {
Pcpstream *stream = ps_init();
stream->b = buffer_new(32, "Pcpstream");
stream->is_buffer = 1;
return stream;
}
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
size_t gotbytes = 0;
if(stream->is_buffer) {
gotbytes = buffer_get_chunk(stream->b, buf, readbytes);
if(gotbytes == 0) {
/* this should not happen with buffers */
stream->eof = 1;
stream->err = 1;
}
}
else {
gotbytes = fread(buf, 1, readbytes, stream->fd);
if(gotbytes == 0) {
if(feof(stream->fd) != 0)
stream->eof = 1;
if(ferror(stream->fd) != 0)
stream->err = 1;
}
}
return gotbytes;
}
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
size_t donebytes = 0;
if(stream->is_buffer) {
buffer_add(stream->b, buf, writebytes);
donebytes = writebytes;
}
else {
donebytes = fwrite(buf, 1, writebytes, stream->fd);
if(ferror(stream->fd) != 0 || donebytes < writebytes)
stream->err = 1;
}
return writebytes;
}
void ps_close(Pcpstream *stream) {
if(stream->is_buffer) {
buffer_clear(stream->b);
free(stream);
}
else {
/* only close files, not terminal devices */
if(fileno(stream->fd) > 2)
fclose(stream->fd);
free(stream);
}
}
int ps_end(Pcpstream *stream) {
return stream->eof;
}
int ps_err(Pcpstream *stream) {
return stream->err;
}
size_t ps_tell(Pcpstream *stream) {
if(stream->is_buffer) {
if(stream->b->end > stream->b->offset)
return stream->b->end; /* write buffer */
else
return stream->b->offset; /* read buffer */
}
else {
return ftell(stream->fd);
}
}

View File

@@ -30,8 +30,6 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
size_t dlen;
uint8_t head;
if(infile == NULL)
in = stdin;
else {
@@ -112,10 +110,16 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
goto errde3;
}
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
if(symkey == NULL)
dlen = pcp_decrypt_file(in, out, secret, NULL, verify);
dlen = pcp_decrypt_stream(pin, pout, secret, NULL, verify);
else
dlen = pcp_decrypt_file(in, out, NULL, symkey, verify);
dlen = pcp_decrypt_stream(pin, pout, NULL, symkey, verify);
ps_close(pin);
ps_close(pout);
if(dlen > 0) {
if(verify)
@@ -259,10 +263,17 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
size_t clen = 0;
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
if(self == 1)
clen = pcp_encrypt_file_sym(in, out, symkey, 0, NULL);
clen = pcp_encrypt_stream_sym(pin, pout, symkey, 0, NULL);
else
clen = pcp_encrypt_file(in, out, secret, pubhash, signcrypt);
clen = pcp_encrypt_stream(pin, pout, secret, pubhash, signcrypt);
ps_close(pin);
ps_close(pout);
if(clen > 0) {
if(id == NULL && recipient == NULL)

View File

@@ -35,6 +35,7 @@
#include "keyprint.h"
#include "keyhash.h"
#include "plist.h"
#include "pcpstream.h"
int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, int verify);
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt);