98 Commits

Author SHA1 Message Date
Thomas von Dein
5e726d6b69 using direkt buffer_add() in pcp_export_json_pub() as well 2016-10-26 08:24:05 +02:00
Thomas von Dein
5255a076db fixed off-by-one bug in buffer_add_str() 2016-10-26 08:23:34 +02:00
Thomas von Dein
56f35a66d8 regen 2016-10-26 08:23:16 +02:00
Thomas von Dein
3f7410c1e3 added hints about installing jansson and python stuff 2016-10-26 06:53:55 +02:00
Thomas von Dein
652c60e546 re-generated 2016-10-26 06:53:42 +02:00
Thomas von Dein
b999baf858 added hints about installing jansson and python stuff 2016-10-26 06:50:27 +02:00
Thomas von Dein
5b9b0c3dca added unittests, now that perl isnt involved anymore 2016-10-26 06:49:57 +02:00
Thomas von Dein
e1e0a3e53c removed perl stuff, not needed anymore 2016-10-26 06:49:30 +02:00
Thomas von Dein
7663df792d not required anymore 2016-10-26 06:39:54 +02:00
Thomas von Dein
48947064bf fixed missing free() errors 2016-10-25 22:07:08 +02:00
Thomas von Dein
918fa997f9 rm 2016-10-25 21:33:28 +02:00
Thomas von Dein
9c78f3ad63 last perl tests migrated to unittests.sh 2016-10-25 21:33:16 +02:00
Thomas von Dein
2cb91c93e0 move from unittest perl tp shell script, more portable and easier to understand 2016-10-25 16:33:12 +02:00
Thomas von Dein
0b1e843ee8 fix segfault bug if given vault is NULL 2016-10-25 16:32:05 +02:00
Thomas von Dein
7672be2a8d forgot to add writing of keysigs after deletions 2016-10-25 16:31:29 +02:00
Thomas von Dein
55ac156754 forgot to add writing of keysigs after deletions 2016-10-25 16:31:12 +02:00
Thomas von Dein
753d5bb51f regenerated 2016-10-25 16:30:42 +02:00
Thomas von Dein
e0ef92cb29 regen 2016-10-25 13:19:01 +02:00
Thomas von Dein
ceca615fef catch missing input 2016-10-25 13:18:24 +02:00
Thomas von Dein
c68c1626a6 wrong call 2016-10-25 13:18:11 +02:00
Thomas von Dein
a997a9fe55 added missing header(freebsd) 2016-10-25 11:29:53 +02:00
Thomas von Dein
f182c64796 regen 2016-10-21 10:23:01 +02:00
Thomas von Dein
0af5822abd added keysig to checksum calculation 2016-10-21 10:19:41 +02:00
Thomas von Dein
f657cfa703 better sig2blob and back wrappers 2016-10-21 10:19:17 +02:00
Thomas von Dein
cb654bd48f del unused funcs, rename blob2sig 2016-10-21 10:04:46 +02:00
Thomas von Dein
b8008d1207 removed endian conversion code, now we just write in big-endian on output with shifts, not swaps etc 2016-10-20 23:14:14 +02:00
Thomas von Dein
f664cc24c4 bump 2016-10-20 23:12:00 +02:00
Thomas von Dein
94ea152460 just include this, dammit 2016-10-20 23:11:07 +02:00
Thomas von Dein
19aa89be0c regen, added missing headers 2016-10-16 23:42:58 +02:00
Thomas von Dein
2ad190e921 fix indent error 2016-10-16 22:14:25 +02:00
git@daemon.de
28981bdbb1 better error handling for sscanf output in pbp import 2016-10-05 13:34:49 +02:00
git@daemon.de
8235272c41 rm unneeded defs 2016-10-05 13:34:09 +02:00
git@daemon.de
e953979ef6 get rid of strptime 2016-10-05 12:26:21 +02:00
git@daemon.de
af2418eb17 fix strptime compilation error 2016-10-05 11:48:22 +02:00
T.v.Dein
875ddd0991 Merge pull request #18 from aloisdg/patch-1
fix typo
2016-10-05 11:41:25 +02:00
TLINDEN
fcc16e17f4 more verbosity on -v 2016-08-26 15:45:04 +02:00
TLINDEN
39eaeaba0e more length shortcuts 2016-08-26 15:44:42 +02:00
TLINDEN
9132dd53bc using -v instead of -D to show number of recipients 2016-08-24 21:26:37 +02:00
git@daemon.de
ab5b6c0b13 display number of recipients with -D -d, see: http://www.daemon.de/blog/2017/08/24/436/how-backdoor-store-and-forward-public-key-crypto/ for details 2016-08-24 17:25:57 +02:00
T.v.Dein
3f1c2d9b15 Merge pull request #17 from torchhound/master
Fixed typos in README and README.pod
2016-07-11 10:31:23 +02:00
Joseph E.S. Cieslik
086e2407a6 Added fixes to README.pod that didn't get copied from README in the previous commit 2016-07-10 20:43:21 -04:00
Joseph E.S. Cieslik
c112136bba fixed typos in README and README.pod 2016-07-10 20:40:02 -04:00
TLINDEN
240d5f0a4a fix #16: look for glibtoolize on macosx 2016-07-10 20:50:14 +02:00
Alois
8cd4a18c40 fix typo 2016-07-05 14:56:35 +02:00
TLINDEN
46d93eb275 Merge branch 'master' of github.com:TLINDEN/pcp 2016-05-09 22:40:19 +02:00
TLINDEN
671352bc29 unfortunately my tab/spc config was wrong for a couple of years. fixed all tabs=>spaces+re-indent 2016-05-09 22:24:13 +02:00
git@daemon.de
59bf973859 regenerated 2016-01-21 13:14:18 +01:00
git@daemon.de
71c35bf815 fixed POD format bug: missing newline before heading 2016-01-21 13:13:59 +01:00
git@daemon.de
46ab78c56f fixed format warn 2016-01-21 13:13:21 +01:00
TLINDEN
a67149229f added is_utf8 license 2016-01-15 21:06:18 +01:00
git@daemon.de
feaa022b10 migrate to container, 4 try 2015-12-08 18:40:14 +01:00
git@daemon.de
26508281e8 migrate to container, 3 try 2015-12-08 18:36:15 +01:00
git@daemon.de
4b30a94f52 migrate to container, 2 try 2015-12-08 18:30:15 +01:00
git@daemon.de
fcca6f5a08 migrate to container, 1 try 2015-12-08 18:26:39 +01:00
TLINDEN
88b49e611b using blake2 checksums (pcp1 -C) now 2015-12-07 20:10:13 +01:00
TLINDEN
e847e7057d fix #14: use longterm secret key for signing in -Ac mode (anonymous encrypt+sign) 2015-12-07 14:13:27 +01:00
TLINDEN
d8c1f3cbd3 remove call to sodium_init() because already done on context.c 2015-11-15 17:11:30 +01:00
TLINDEN
ea1d20e0af remove call to sodium_init() because already done on context.c 2015-11-15 17:03:19 +01:00
TLINDEN
f7aa9d7aaf catch sodium_init() return 2015-11-15 17:02:51 +01:00
TLINDEN
ab3ff3182e fix POD 2015-11-15 16:46:43 +01:00
TLINDEN
935e28dff6 fix #15: dont free localtime() returned pointer 2015-11-15 16:35:56 +01:00
git@daemon.de
4e5c27c58c rm dbg print, fix #13 2015-10-23 12:25:52 +02:00
git@daemon.de
c7108ec47f fixed stream-reader bug on aix@ppc, which ignored the last z85 pkt sometimes due invalid call to ps_end() 2015-10-16 17:25:17 +02:00
git@daemon.de
4165e5d996 add aix pipe bug 2015-10-15 17:18:28 +02:00
git@daemon.de
5080e28e56 nothing 2015-10-15 17:18:15 +02:00
git@daemon.de
aa1aeb6975 nothing 2015-10-15 17:18:02 +02:00
git@daemon.de
b55e4ceb61 use openssl if no native md5 tool exists 2015-10-15 13:31:51 +02:00
git@daemon.de
0c5ab80654 fixed err() implementation, exit(eval) according to spec 2015-10-15 13:13:44 +02:00
git@daemon.de
359be6bce7 rm stdin=NULL, catched in main() anyway 2015-10-15 13:13:03 +02:00
git@daemon.de
a6940f8b87 abandon warn() not used anywhere else 2015-10-15 13:12:22 +02:00
TLINDEN
ae5be44182 fixed _gen_ctr_nonce(), reported in #12: invalid ctr comparision did lead to counter underflow 2015-10-14 19:53:03 +02:00
git@daemon.de
3a8d8c010f fixed memory leak during decrypt, reported in #10 2015-10-12 12:17:51 +02:00
git@daemon.de
61d3cbae83 regen 2015-10-12 12:17:16 +02:00
git@daemon.de
b4f264aab3 streamlined 2015-10-12 12:17:05 +02:00
TLINDEN
bbdda67a6e using constant time memcmp by C.Meessen 2015-08-27 11:19:24 +02:00
git@daemon.de
1b7681ee83 fix format for json int values 2015-08-24 20:31:04 +02:00
git@daemon.de
46bd857cc2 added osx support 2015-08-24 20:15:09 +02:00
git@daemon.de
44347793c1 rm printf 2015-08-24 20:14:54 +02:00
git@daemon.de
79874d5915 using json_int_t for uint32_ts json import 2015-08-24 16:31:18 +02:00
git@daemon.de
da70c4479e removed support to store unencrypted secret key 2015-08-19 20:53:46 +02:00
git@daemon.de
a9d4ef6ff3 updated 2015-08-17 20:25:42 +02:00
git@daemon.de
64a45583d0 added check for weak passphrase using entropy test 2015-08-17 20:15:20 +02:00
git@daemon.de
8fb7369d64 regenerated 2015-08-17 20:14:41 +02:00
TLINDEN
d04e5f3baf fixed decrypt from out buf 2015-08-17 11:17:12 +02:00
TLINDEN
d2ee10f071 fixed invalid free 2015-08-17 11:17:04 +02:00
TLINDEN
48283e7e04 fix :565:18: error, again, was a typo. not =- 1, but = -1. 2015-08-17 09:24:21 +02:00
TLINDEN
ac09fc1a2b fix :565:18: error: use of unary operator that may be intended as compound 2015-08-17 09:00:52 +02:00
TLINDEN
0d7282ad35 add entropy check for entered passphrases 2015-08-16 21:35:06 +02:00
TLINDEN
32030afd62 fix double free, add todo 2015-08-16 21:34:39 +02:00
TLINDEN
3b6933d34f regenerated 2015-08-15 20:39:02 +02:00
TLINDEN
c363dce7de using libsodiums size constants everywhere (keysizes and the likes) 2015-08-15 20:38:33 +02:00
TLINDEN
05741acd1a found another bug 2015-08-15 20:37:50 +02:00
TLINDEN
420e48d4e3 new error 2015-08-15 16:31:11 +02:00
TLINDEN
f091a28589 use mzero instead of wasting randomness 2015-08-15 13:04:30 +02:00
TLINDEN
7b3005e790 added context to pcp_readpass(), rm libpcp/getpass.c 2015-07-30 11:47:03 +02:00
TLINDEN
0046db9136 added extpass option 2015-07-30 11:46:17 +02:00
TLINDEN
deeb15e851 add pass idea 2015-07-29 17:47:55 +02:00
TLINDEN
27a9a96ae4 -C uses facilities of -x and -X 2015-07-22 07:59:28 +02:00
94 changed files with 4460 additions and 4046 deletions

View File

@@ -1,34 +1,26 @@
sudo: false
language: c
os:
- linux
addons:
apt:
packages:
- python-pip
- texinfo
compiler:
- clang
- gcc
before_install:
# runtime dependency
- git clone https://github.com/jedisct1/libsodium
- cd libsodium
- ./autogen.sh
- ./configure --prefix=/usr
- ./configure --prefix=$HOME/usr
- make
- sudo make install
- cd ..
#
# unittest dependencies, perl modules
- wget http://search.cpan.org/CPAN/authors/id/T/TL/TLINDEN/Config-General-2.56.tar.gz
- tar xvzf Config-General-2.56.tar.gz
- cd Config-General-2.56
- perl Makefile.PL && make
- sudo make install
- cd ..
- wget http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/Tie-IxHash-1.23.tar.gz
- tar xvzf Tie-IxHash-1.23.tar.gz
- cd Tie-IxHash-1.23
- perl Makefile.PL && make
- sudo make install
- cd ..
- wget http://search.cpan.org/CPAN/authors/id/I/IN/INGY/YAML-1.14.tar.gz
- tar xvfz YAML-1.14.tar.gz
- cd YAML-1.14
- perl Makefile.PL && make
- sudo make install
- make install
- cd ..
#
# for debugging - just in case, uncomment this and the next if needed
@@ -45,24 +37,21 @@ before_install:
#- sudo apt-get install libc6-dbg
#
# python bindings runtime dependencies
- sudo apt-get update -qq
- sudo apt-get install python-pip texinfo
- git clone https://github.com/atgreen/libffi
- cd libffi
- ./autogen.sh
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
- sudo pip install cffi
#- git clone https://github.com/atgreen/libffi
#- cd libffi
#- ./autogen.sh
#- ./configure --prefix=/usr
#- make
#- sudo make install
#- cd ..
#- sudo pip install cffi
#
# finally prepare autoconf stuff
- ./autogen.sh
compiler:
- clang
- gcc
script:
- ./configure --enable-python-binding
#- ./configure --enable-python-binding
- LD_LIBRARY_PATH=$HOME/usr/lib ./configure --with-libsodium=$HOME/usr
- make
- make check
- make test

View File

@@ -1,3 +1,37 @@
0.4.0
Changed -C again: doesnt support a key argument
anymore, instead I use the facilities I already
have in place (-x and -X). Also, I don't generate
an extra hash for the key anymore.
Removed libpcp/getpass.c, not used anymore.
Added --extpass (implementation from encfs, but
somewhat modified).
Moved src/readpass.c to libpcp/.
Added check for weak passphrases using entropy
test. Used with -k.
Removed support for unencrypted secret key storage
so, pcp aims to be secure by default and fails
safely.
Using cst_time_memcpy by Christophe Meessen instead
of libc's memcpy: constant time memcpy is much more
secure than the default, especially in our context.
Anonymous encrypted files are now signed with primary
secret key, so that the recipient will be able to
verify the signature.
Added -v support for -d and -e.
Removed endian conversion stuff. see util.c for details.
Fixed: use key signatures for vault checksum calc as well.
0.3.0
Changed publuc key signature storage, previously
I didn't add the actual signature, therefore a

2
FAQ
View File

@@ -9,7 +9,7 @@ make LDFLAGS="-all-static -s"
A passphrase like Ahc<e3% is not really secure. First
it's difficult to memorize, second it's easy for a computer
to compute. The better aproach is to use a passphrase
you can easily momorize and which is hard for a computer
you can easily memorize and which is hard for a computer
to compute (i.e. to guess) like: Phantom orchestra boredom popcorn.
Read [1] to learn more.

18
README
View File

@@ -95,8 +95,9 @@ FILES AND PIPES
input file you cannot use -X -, and vice versa. IF you use -X - the
passphrase will be read from standard input, which then can't be used
further for input files elsewhere. Pcp will exit with an error in such a
case. =head1 INSTALLATION
case.
INSTALLATION
There are currently no packages available, so pcp has to be compiled
from source. Follow these steps:
@@ -110,7 +111,20 @@ FILES AND PIPES
sudo ldconfig
cd ..
Next, pcp:
If you want to have JSON support, you'll need to install the Jansson
library (optional):
git clone git://github.com/akheron/jansson.git
cd jansson
autoreconf -i
./configure && make
sudo make install
cd ..
In order to use the python binding, you need to install the cffi python
package.
Next, build pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp

View File

@@ -113,6 +113,7 @@ specify an input file you cannot use B<-X ->, and vice versa. IF
you use B<-X -> the passphrase will be read from standard input, which
then can't be used further for input files elsewhere. Pcp will exit
with an error in such a case.
=head1 INSTALLATION
There are currently no packages available, so B<pcp> has to be
@@ -128,7 +129,20 @@ First, you will need libsodium:
sudo ldconfig
cd ..
Next, pcp:
If you want to have JSON support, you'll need to install the
Jansson library (optional):
git clone git://github.com/akheron/jansson.git
cd jansson
autoreconf -i
./configure && make
sudo make install
cd ..
In order to use the python binding, you need to install the
B<cffi> python package.
Next, build pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp

8
TODO
View File

@@ -1,3 +1,6 @@
JSON output has \0 always appended check from where this comes
pcpstream.c: use static tmp buffers, avoid alloc mem during each iteration
detach keysig generation from pub key export, so that an existing
keysig can be verified later.
@@ -10,12 +13,7 @@ malloc() new pointers in functions only if not NULL, e.g. pcp_gennonce()
check pub key count in pcp.c before calling verify signature, croak if count==0
vault checksum: add keysigs as well
Add newlines to headers in define.h, so strlen() later catches the whole length.
Check is_utf8 license.
also found in https://gd.meizo.com/_files/lpc/ext/utf8.c
c++ destructor double free mess

View File

@@ -1 +1 @@
0.3.0
0.4.0

View File

@@ -26,3 +26,5 @@ build_script:
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; cat config.log"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make check"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make test"'

View File

@@ -72,9 +72,12 @@ fi
if test "$mode" = "config"; then
mkdir -p ./config
lt=libtoolize
case `uname` in Darwin*) lt=glibtoolize;; esac
if ! command -v libtoolize >/dev/null 2>&1; then
echo "could not find libtool." 1>&2
if ! command -v $lt >/dev/null 2>&1 ; then
echo "could not find $lt." 1>&2
exit 1
fi

View File

@@ -54,7 +54,7 @@ bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, pubhash, sign, 0); // FIXME: add anon support
size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, S.K, pubhash, sign, 0); // FIXME: add anon support
if(clen <= 0)
throw exception(PTX);
ps_close(pin);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -41,12 +41,12 @@ namespace pcp {
std::string msg;
PCPCTX *ptx = P->ptx;
if(ptx->pcp_errset == 1) {
msg = ptx->pcp_err;
msg = ptx->pcp_err;
}
if(errno) {
msg += std::string("\nError: ")
+ std::string(strerror(errno))
+ std::string("\n");
msg += std::string("\nError: ")
+ std::string(strerror(errno))
+ std::string("\n");
}
return msg;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -83,8 +83,8 @@ namespace pcp {
Key(PcpContext *P, bool generate);
Key(PcpContext *P, const std::string& passphrase);
Key(PcpContext *P, const std::string& passphrase,
const std::string& owner,
const std::string& mail);
const std::string& owner,
const std::string& mail);
Key(PcpContext *P, pcp_key_t *k);
Key(PcpContext *P, pcp_key_t *k, bool store);
Key(PcpContext *P, std::string &z85encoded, std::string& passphrase);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -53,8 +53,8 @@ Key::Key(PcpContext *P, const string& passphrase) {
}
Key::Key(PcpContext *P, const string& passphrase,
const string& owner,
const string& mail) {
const string& owner,
const string& mail) {
stored = false;
pcp_key_t *_K = pcpkey_new();
K = pcpkey_encrypt(P->ptx, _K, (char *)passphrase.c_str());

View File

@@ -2,28 +2,28 @@
use Data::Dumper;
my %sobytes = (
'crypto_box_NONCEBYTES' => 24,
'crypto_box_PUBLICKEYBYTES' => 32,
'crypto_box_SECRETKEYBYTES' => 32,
'crypto_box_ZEROBYTES' => 32,
'crypto_box_BOXZEROBYTES' => 16,
'crypto_box_MACBYTES' => 16,
'crypto_secretbox_KEYBYTES' => 32,
'crypto_secretbox_NONCEBYTES' => 24,
'crypto_secretbox_ZEROBYTES' => 32,
'crypto_secretbox_BOXZEROBYTES' => 16,
'crypto_secretbox_MACBYTES' => 16,
'crypto_sign_PUBLICKEYBYTES' => 32,
'crypto_sign_SECRETKEYBYTES' => 64,
'crypto_sign_SEEDBYTES' => 32,
'crypto_sign_BYTES' => 64,
'crypto_stream_KEYBYTES' => 32,
'crypto_stream_NONCEBYTES' => 24,
'crypto_generichash_BYTES' => 32,
'crypto_scalarmult_curve25519_BYTES' => 32,
'crypto_scalarmult_BYTES' => 32,
'crypto_generichash_BYTES_MAX' => 64,
);
'crypto_box_NONCEBYTES' => 24,
'crypto_box_PUBLICKEYBYTES' => 32,
'crypto_box_SECRETKEYBYTES' => 32,
'crypto_box_ZEROBYTES' => 32,
'crypto_box_BOXZEROBYTES' => 16,
'crypto_box_MACBYTES' => 16,
'crypto_secretbox_KEYBYTES' => 32,
'crypto_secretbox_NONCEBYTES' => 24,
'crypto_secretbox_ZEROBYTES' => 32,
'crypto_secretbox_BOXZEROBYTES' => 16,
'crypto_secretbox_MACBYTES' => 16,
'crypto_sign_PUBLICKEYBYTES' => 32,
'crypto_sign_SECRETKEYBYTES' => 64,
'crypto_sign_SEEDBYTES' => 32,
'crypto_sign_BYTES' => 64,
'crypto_stream_KEYBYTES' => 32,
'crypto_stream_NONCEBYTES' => 24,
'crypto_generichash_BYTES' => 32,
'crypto_scalarmult_curve25519_BYTES' => 32,
'crypto_scalarmult_BYTES' => 32,
'crypto_generichash_BYTES_MAX' => 64,
);
my @ignore = qw(uthash.h);
@@ -87,19 +87,19 @@ foreach my $head (@ARGV) {
print "PCP_RAW_CODE = '''\n";
print qq(
typedef enum {
JSON_OBJECT,
JSON_ARRAY,
JSON_STRING,
JSON_INTEGER,
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
JSON_OBJECT,
JSON_ARRAY,
JSON_STRING,
JSON_INTEGER,
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
} json_type;
typedef struct json_t {
json_type type;
size_t refcount;
json_type type;
size_t refcount;
} json_t;
);
print join "\n", @typedefs;

View File

@@ -1,28 +1,28 @@
PCP_RAW_CODE = '''
typedef enum {
JSON_OBJECT,
JSON_ARRAY,
JSON_STRING,
JSON_INTEGER,
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
JSON_OBJECT,
JSON_ARRAY,
JSON_STRING,
JSON_INTEGER,
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
} json_type;
typedef struct json_t {
json_type type;
size_t refcount;
json_type type;
size_t refcount;
} json_t;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */
/*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned char byte;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */
/*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned short dbyte;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */
/*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned int qbyte;
/*** ./gencffi.pl: from ../../include/pcp/plist.h:83 */
@@ -84,45 +84,44 @@ struct _plist_t {
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pcp_key_t {
byte masterpub[32]; /**< ED25519 master public key signing key */
byte mastersecret[64]; /**< ED25519 master secret key signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte secret[32]; /**< Curve25519 encryption secret key */
byte edpub[32]; /**< ED25519 public signing key */
byte edsecret[64]; /**< ED25519 secret signing key */
byte nonce[24]; /**< random nonce used to encrypt secret keys */
byte encrypted[176]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte mastersecret[LEDSEC]; /**< ED25519 master secret key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte secret[LBOXSEC]; /**< Curve25519 encryption secret key */
byte edpub[LEDPUB]; /**< ED25519 public signing key */
byte edsecret[LEDSEC]; /**< ED25519 secret signing key */
byte nonce[LNONCE]; /**< random nonce used to encrypt secret keys */
byte encrypted[LSEC]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
byte hh[56];
};
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pcp_pubkey_t {
byte masterpub[32]; /**< ED25519 master public key signing key */
byte sigpub[32]; /**< ED25519 public signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte edpub[32]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
uint8_t valid; /**< 1 if import signature verified, 0 if not */
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte edpub[LEDPUB]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
uint8_t valid; /**< 1 if import signature verified, 0 if not */
byte signature[128]; /**< raw binary blob of pubkey export signature */
byte hh[56];
};
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pbp_pubkey_t {
byte sigpub[32];
byte masterpub[32];
byte edpub[32];
byte pub[32];
char iso_ctime[32];
@@ -143,7 +142,7 @@ struct _pcp_keysig_t {
uint8_t type;
uint32_t size;
char id[17];
byte checksum[32];
byte checksum[LSHA];
byte *blob;
byte hh[56];
};
@@ -170,14 +169,14 @@ struct _vault_t {
time_t modified; /**< mtime */
mode_t mode; /**< File mode */
uint32_t version; /**< Vault version */
byte checksum[32]; /**< SHA256 checksum over the whole vault */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _vault_header_t {
uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */
uint32_t version; /**< File version */
byte checksum[32]; /**< SHA256 checksum over the whole vault */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
@@ -185,7 +184,7 @@ struct _vault_item_header_t {
uint8_t type; /**< Item type (secret key, public, key, keysig, \see _PCP_KEY_TYPES */
uint32_t size; /**< Size of the item */
uint32_t version; /**< Version of the item */
byte checksum[32]; /**< SHA256 checksum of the item */
byte checksum[LSHA]; /**< SHA256 checksum of the item */
};
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
@@ -207,6 +206,7 @@ struct _pcp_stream_t {
Buffer *cache; /**< The caching Buffer object (for look ahead read) */
Buffer *next; /**< The caching Next-Buffer object (for look ahead read) */
Buffer *save; /**< Temporary buffer to backup overflow data */
byte *xb; /**< Temporary byte buffer for reading/writing data */
uint8_t is_buffer; /**< Set to 1 if the backend is a Buffer */
uint8_t eof; /**< Set to 1 if EOF reached */
uint8_t err; /**< Set to 1 if an error occured */
@@ -404,31 +404,28 @@ void final(const char * fmt, ...);
/*** ./gencffi.pl: from ../../include/pcp/context.h:96 */
void ptx_dump(PCPCTX *ptx);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt, int anon);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, int havehead, pcp_rec_t *recsign);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify, int anon);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, pcp_rec_t *recverify);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
int pcp_checksum(PCPCTX *ptx, Pcpstream *in, byte *checksum, byte *key, size_t keylen);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
pcp_rec_t *pcp_rec_new(byte *cipher, size_t clen, pcp_key_t *secret, pcp_pubkey_t *pub);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
void pcp_rec_free(pcp_rec_t *r);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
byte *_gen_ctr_nonce(uint64_t ctr);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
uint64_t _get_nonce_ctr(byte *nonce);
/*** ./gencffi.pl: from ../../include/pcp/ed.h:202 */
@@ -467,81 +464,90 @@ char *pcp_get_passphrase(char *prompt);
/*** ./gencffi.pl: from ../../include/pcp/jenhash.h:25 */
unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval );
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t *pcpkey_new ();
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
char *pcppubkey_get_art(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
char *pcpkey_get_art(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
char *pcp_getkeyid(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
char *pcp_getpubkeyid(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
byte *pcppubkey_getchecksum(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
byte *pcpkey_getchecksum(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t * key2be(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t *key2native(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
byte * pcp_gennonce();
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcp_seckeyblob(Buffer *b, pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
Buffer *pcp_keyblob(void *k, int type);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_key_t *pcp_blob2key(Buffer *b);
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
pcp_pubkey_t *pcp_blob2pubkey(Buffer *b);
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcp_dumpkey(pcp_key_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcp_dumppubkey(pcp_pubkey_t *k);
/*** ./gencffi.pl: from ../../include/pcp/key.h:314 */
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail);
/*** ./gencffi.pl: from ../../include/pcp/key.h:324 */
double pcp_getentropy(char *source);
/*** ./gencffi.pl: from ../../include/pcp/keyhash.h:153 */
void pcphash_del(PCPCTX *ptx, void *key, int type);
@@ -569,19 +575,16 @@ int pcphash_countpub(PCPCTX *ptx);
/*** ./gencffi.pl: from ../../include/pcp/keyhash.h:153 */
pcp_keysig_t *pcphash_keysigexists(PCPCTX *ptx, char *id);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
pcp_keysig_t *keysig2be(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
pcp_keysig_t *keysig2native(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
Buffer *pcp_keysigblob(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
Buffer *pcp_keysig2blob(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
pcp_keysig_t *pcp_blob2keysig(Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
void pcp_dumpkeysig(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/mem.h:58 */
@@ -605,61 +608,61 @@ void ucfree(void *d, size_t len);
/*** ./gencffi.pl: from ../../include/pcp/mem.h:58 */
void sfree(void *d);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
json_t *pcp_sk2json(pcp_key_t *sk, byte *sig,size_t siglen);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
json_t *pcp_pk2json(pcp_pubkey_t *pk);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
Buffer *pcp_import_secret_json(PCPCTX *ptx, Buffer *json);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk);
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */
/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:193 */
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader);
/*** ./gencffi.pl: from ../../include/pcp/pcpstream.h:291 */
@@ -740,27 +743,51 @@ int ps_readline(Pcpstream *stream, Buffer *line);
/*** ./gencffi.pl: from ../../include/pcp/randomart.h:54 */
char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len);
/*** ./gencffi.pl: from ../../include/pcp/readpass.h:69 */
int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass);
/*** ./gencffi.pl: from ../../include/pcp/scrypt.h:42 */
byte * pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_t noncelen);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
char *_lc(char *in);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
long int _findoffset(byte *bin, size_t binlen, char *sigstart, size_t hlen);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
void _xorbuf(byte *iv, byte *buf, size_t xlen);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
void _dump(char *n, byte *d, size_t s);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
char *_bin2hex(byte *bin, size_t len);
/*** ./gencffi.pl: from ../../include/pcp/util.h:120 */
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_array_max);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
int cst_time_memcmp(const void *m1, const void *m2, size_t n);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
uint64_t _wireto64(byte *data);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
uint32_t _wireto32(byte *data);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
uint16_t _wireto16(byte *data);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
void _64towire(uint64_t i, byte *data);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
void _32towire(uint32_t i, byte *data);
/*** ./gencffi.pl: from ../../include/pcp/util.h:142 */
void _16towire(uint16_t i, byte *data);
/*** ./gencffi.pl: from ../../include/pcp/vault.h:230 */
vault_t *pcpvault_init(PCPCTX *ptx, char *filename);
@@ -866,149 +893,145 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
/*** ./gencffi.pl: from ../../include/pcp/zmq_z85.h:31 */
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);'''
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_FORMAT_PBP = 2
# ./gencffi.pl: from ../../include/pcp/defines.h:172
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ASYM_CIPHER = 5
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_CIPHER = 0x23
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_PK_HEADER = "----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_HASH_CIPHER = 0x22
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_HASH_NAME = "BLAKE2"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_CRYPTO_ADD = (32 - 16)
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ASYM_CIPHER_SIG = 24
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_SUB_KEYFLAGS = 27
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_SUB_NOTATION = 20
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_VAULT_ID = 14
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SK_HEADER = "----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ENFILE_HEADER = "----- BEGIN PCP ENCRYPTED FILE -----\r\n"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_SIG_HEADER = "----- BEGIN ED25519 SIGNED MESSAGE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_SIGPREFIX = "\nnacl-"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ZFILE_FOOTER = "----- END Z85 ENCODED FILE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SK_FOOTER = "----- END ED25519-CURVE29915 PRIVATE KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_SIG_END = "----- END ED25519 SIGNATURE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_RFC_CIPHER = 0x21
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ENCRYPT_MAC = 56
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ME = "Pretty Curved Privacy"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ASYM_CIPHER_ANON = 6
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ENFILE_FOOTER = "\r\n----- END PCP ENCRYPTED FILE -----\r\n"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_SUB_CTIME = 2
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_SIG_START = "----- BEGIN ED25519 SIGNATURE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ZFILE_HEADER = "----- BEGIN Z85 ENCODED FILE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_SUB_SIGEXPIRE = 3
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_CIPHER_NAME = "ED25519"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_PK_CIPHER = 0x21
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_PK_FOOTER = "----- END ED25519-CURVE29915 PUBLIC KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_SIG_SUB_KEYEXPIRE = 9
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_FORMAT_NATIVE = 1
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_SYM_CIPHER = 23
# ./gencffi.pl: from ../../include/pcp/defines.h:172
EXP_PK_CIPHER_NAME = "CURVE25519-ED25519-POLY1305-SALSA20"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PBP_COMPAT_SALT = "qa~t](84z<1t<1oz:ik.@IRNyhG=8q(on9}4#!/_h#a7wqK{Nt$T?W>,mt8NqYq&6U<GB1$,<$j>,rSYI2GRDd:Bcm"
# ./gencffi.pl: from ../../include/pcp/defines.h:172
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_BLOCK_SIZE = 32 * 1024
# ./gencffi.pl: from ../../include/pcp/defines.h:172
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_PK_HEADER = "----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SK_FOOTER = "----- END ED25519-CURVE29915 PRIVATE KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ENFILE_HEADER = "----- BEGIN PCP ENCRYPTED FILE -----\r\n"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_FORMAT_NATIVE = 1
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PBP_COMPAT_SALT = "qa~t](84z<1t<1oz:ik.@IRNyhG=8q(on9}4#!/_h#a7wqK{Nt$T?W>,mt8NqYq&6U<GB1$,<$j>,rSYI2GRDd:Bcm"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_HASH_CIPHER = 0x22
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_HASH_NAME = "BLAKE2"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_SUB_NOTATION = 20
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_CIPHER_NAME = "ED25519"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_CIPHER = 0x23
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ZFILE_HEADER = "----- BEGIN Z85 ENCODED FILE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_SIG_END = "----- END ED25519 SIGNATURE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_PK_CIPHER = 0x21
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_RFC_CIPHER = 0x21
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ASYM_CIPHER_ANON = 6
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ENFILE_FOOTER = "\r\n----- END PCP ENCRYPTED FILE -----\r\n"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_SYM_CIPHER = 23
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_TYPE = 0x1F
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_SUB_KEYFLAGS = 27
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SK_HEADER = "----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_SIGPREFIX = "\nnacl-"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ME = "Pretty Curved Privacy"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ZFILE_FOOTER = "----- END Z85 ENCODED FILE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_SUB_SIGEXPIRE = 3
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_SUB_CTIME = 2
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_PK_FOOTER = "----- END ED25519-CURVE29915 PUBLIC KEY -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_VAULT_ID = 14
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ASYM_CIPHER_ANON_SIG = 7
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_SIG_HEADER = "----- BEGIN ED25519 SIGNED MESSAGE -----"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_ASYM_CIPHER_SIG = 24
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_PK_CIPHER_NAME = "CURVE25519-ED25519-POLY1305-SALSA20"
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_FORMAT_PBP = 2
# ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_SIG_SUB_KEYEXPIRE = 9
# ./gencffi.pl: from ../../include/pcp/defines.h:185
PCP_SIG_START = "----- BEGIN ED25519 SIGNATURE -----"

View File

@@ -58,8 +58,8 @@ AC_CANONICAL_HOST
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(errno.h err.h stdlib.h string.h unistd.h stdio.h getopt.h\
limits.h stddef.h stdint.h sys/types.h sys/stat.h endian.h \
sys/endian.h termios.h arpa/inet.h netinet/in.h wctype.h)
limits.h stddef.h stdint.h sys/types.h sys/stat.h \
termios.h arpa/inet.h netinet/in.h wctype.h)
AC_TYPE_SIZE_T
@@ -94,39 +94,6 @@ AC_CHECK_FUNCS( \
vasprintf
)
AC_MSG_CHECKING([for be32toh])
AC_TRY_LINK([
#include "libpcp/pcp/config.h"
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
], [
(void)be32toh(0);
], [AC_MSG_RESULT([no])], [
AC_DEFINE(HAVE_BE32TOH,, Define if be32toh() is available)
AC_MSG_RESULT([yes])
])
AC_MSG_CHECKING([for htobe32])
AC_TRY_LINK([
#include "libpcp/pcp/config.h"
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
], [
(void)htobe32(0);
], [AC_MSG_RESULT([no])], [
AC_DEFINE(HAVE_HTOBE32,, Define if htobe32() is available)
AC_MSG_RESULT([yes])
])
cross_compile="no"
AC_MSG_CHECKING([compiler and flags for sanity])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ exit(0); ]])],
@@ -309,27 +276,6 @@ AC_LANG_PROGRAM([[
)
fi
if test "$cross_compile" = "no"; then
# check endianess
# program returns 0 on little and 1 on big endian systems
AC_MSG_CHECKING([are we on a big endian system])
AC_RUN_IFELSE([
AC_LANG_PROGRAM([[]],[[long one= 1; exit(!(*((char *)(&one)))); ]])],
[
AC_MSG_RESULT([no])
bigendian="no"
],
[
AC_MSG_RESULT([yes])
bigendian="yes"
]
)
fi
if test "x$bigendian" = "xyes"; then
CFLAGS="$CFLAGS -D__CPU_IS_BIG_ENDIAN=1"
fi
# prepare FLAGS
CFLAGS="$CFLAGS -Werror -Wextra -Wall"
@@ -360,6 +306,8 @@ AS_IF([test "x$enable_optimize" != "xno"], [
CXXFLAGS="$CFLAGS"
# FIXME: check for libm
LIBS="$LIBS -lm"
# conditionals for bindings and stuff
@@ -408,28 +356,28 @@ AC_CONFIG_FILES([Makefile include/Makefile libpcp/Makefile src/Makefile man/Make
AC_OUTPUT
AC_MSG_RESULT([
Build configured for $PACKAGE $VERSION:
CC: ${CC}
CFLAGS: ${CFLAGS}
CXX: ${CXX}
CXXFLAGS: ${CXXFLAGS}
LDFLAGS: ${LDFLAGS}
LIBS: ${LIBS}
debug: ${enable_debug}
optimize: ${enable_optimize}
prefix: ${prefix}
libdir: ${libdir}
includedir: ${includedir}
target platform: ${host}
big endian cpu: ${bigendian}
cross compile: ${cross_compile}
build python binding: ${python}
build c++ binding: ${enable_cpp_binding}
json support ${_have_json}
Type 'make' to build, 'make install' to install.
To execute unit tests, type 'make test'.
Build configured for $PACKAGE $VERSION:
CC: ${CC}
CFLAGS: ${CFLAGS}
CXX: ${CXX}
CXXFLAGS: ${CXXFLAGS}
LDFLAGS: ${LDFLAGS}
LIBS: ${LIBS}
DEBUG: ${enable_debug}
optimize: ${enable_optimize}
prefix: ${prefix}
libdir: ${libdir}
includedir: ${includedir}
target platform: ${host}
cross compile: ${cross_compile}
build python binding: ${python}
build c++ binding: ${enable_cpp_binding}
json support: ${_have_json}
Type 'make' to build, 'make install' to install.
To execute unit tests, type 'make test'.
])

View File

@@ -8,6 +8,7 @@ PCPEXPORT = pcp.h \
pcp/keyhash.h \
pcp/mem.h \
pcp/platform.h \
pcp/plist.h \
pcp/randomart.h \
pcp/uthash.h \
pcp/vault.h \
@@ -22,7 +23,7 @@ PCPEXPORT = pcp.h \
pcp/context.h \
pcp/structs.h \
pcp/util.h \
pcp/plist.h \
pcp/readpass.h \
pcp/scrypt.h
nobase_include_HEADERS = $(PCPEXPORT)

View File

@@ -22,6 +22,7 @@ extern "C" {
#include "pcp/platform.h"
#include "pcp/plist.h"
#include "pcp/randomart.h"
#include "pcp/readpass.h"
#include "pcp/scrypt.h"
#include "pcp/structs.h"
#include "pcp/uthash.h"

View File

@@ -9,15 +9,9 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define if be32toh() is available */
#undef HAVE_BE32TOH
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
@@ -51,9 +45,6 @@
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* Define if htobe32() is available */
#undef HAVE_HTOBE32
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@@ -126,9 +117,6 @@
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the <sys/endian.h> header file. */
#undef HAVE_SYS_ENDIAN_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
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
@@ -141,7 +141,7 @@
*/
byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *message, size_t messagesize,
size_t *csize);
size_t *csize);
/** Asymmetrically decrypt a message.
@@ -167,7 +167,7 @@ byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
*/
byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *cipher, size_t ciphersize,
size_t *dsize);
size_t *dsize);
/** Asymmetrically encrypt a file or a buffer stream.
@@ -183,7 +183,9 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
\param[out] out Stream to write encrypted result to.
\param[in] s Secret key structure of the sender.
\param[in] s Secret key structure of the sender for encryption.
\param[in] s Secret key structure of the sender for signing.
\param[in] p Public key hash containing a list of the recipients.
@@ -193,7 +195,8 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt, int anon);
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s,
pcp_key_t *ss, pcp_pubkey_t *p, int signcrypt, int anon);
/** Symmetrically encrypt a file or a buffer stream.

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -57,6 +57,8 @@ typedef unsigned char byte; /* Single unsigned byte = 8 bits */
typedef unsigned short dbyte; /* Double byte = 16 bits */
typedef unsigned int qbyte; /* Quad byte = 32 bits */
/* key stuff, deprecated. */
#define PCP_ENFILE_HEADER "----- BEGIN PCP ENCRYPTED FILE -----\r\n"
#define PCP_ENFILE_FOOTER "\r\n----- END PCP ENCRYPTED FILE -----\r\n"
@@ -102,8 +104,18 @@ typedef enum _PCP_KEY_TYPES {
/** @}
*/
/* save typing, dammit */
#define PCP_ENCRYPT_MAC crypto_secretbox_ZEROBYTES + crypto_secretbox_NONCEBYTES
/* shortcuts for key lengths and stuff to save typing */
#define LEDPUB crypto_sign_PUBLICKEYBYTES
#define LEDSEC crypto_sign_SECRETKEYBYTES
#define LBOXPUB crypto_box_PUBLICKEYBYTES
#define LBOXSEC crypto_box_SECRETKEYBYTES
#define LNONCE crypto_secretbox_NONCEBYTES
#define LMAC crypto_secretbox_MACBYTES
#define LSEC LBOXSEC + LEDSEC + LEDSEC + crypto_secretbox_MACBYTES
#define LSHA 32 /* sha256 hash length */
#define LHASH crypto_generichash_BYTES_MAX
#define LSIG crypto_sign_BYTES
/* vault id */
#define PCP_VAULT_ID 14
@@ -115,13 +127,14 @@ typedef enum _PCP_KEY_TYPES {
/* crypto file format stuff */
#define PCP_ASYM_CIPHER 5
#define PCP_ASYM_CIPHER_ANON 6
#define PCP_ASYM_CIPHER_ANON_SIG 7
#define PCP_SYM_CIPHER 23
#define PCP_ASYM_CIPHER_SIG 24
#define PCP_BLOCK_SIZE 32 * 1024
#define PCP_CRYPTO_ADD (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
#define PCP_BLOCK_SIZE_IN (PCP_BLOCK_SIZE) + PCP_CRYPTO_ADD + crypto_secretbox_NONCEBYTES
#define PCP_ASYM_RECIPIENT_SIZE crypto_secretbox_KEYBYTES + PCP_CRYPTO_ADD + crypto_secretbox_NONCEBYTES
//#define PCP_CRYPTO_ADD (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
#define PCP_BLOCK_SIZE_IN (PCP_BLOCK_SIZE) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
#define PCP_ASYM_RECIPIENT_SIZE crypto_secretbox_KEYBYTES + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
/* #define PCP_ASYM_ADD_SENDER_PUB */

View File

@@ -28,6 +28,10 @@
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
@@ -267,6 +271,10 @@ void pcp_seckeyblob(Buffer *b, pcp_key_t *k);
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k);
Buffer *pcp_keyblob(void *k, int type); /* allocates blob */
/* reads key from blob */
pcp_key_t *pcp_blob2key(Buffer *b); /* allocates key */
pcp_pubkey_t *pcp_blob2pubkey(Buffer *b);
/** Make a sanity check of the given public key structure.
\param[in] ptx pcp context.
@@ -309,6 +317,8 @@ void pcp_dumppubkey(pcp_pubkey_t *k);
*/
void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail);
double pcp_getentropy(char *source);
#endif /* _HAVE_PCP_KEYPAIR_H */
/**@}*/

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
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
@@ -54,7 +54,7 @@
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iterate(ptx, key) \
#define pcphash_iterate(ptx, key) \
pcp_key_t *__k = NULL; \
HASH_ITER(hh, ptx->pcpkey_hash, key, __k)
@@ -73,7 +73,7 @@
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iteratepub(ptx, key) \
#define pcphash_iteratepub(ptx, key) \
pcp_pubkey_t *__p = NULL; \
HASH_ITER(hh, ptx->pcppubkey_hash, key, __p)
@@ -142,7 +142,7 @@ int pcphash_countpub(PCPCTX *ptx);
#define pcphash_iteratekeysig(ptx, key) \
#define pcphash_iteratekeysig(ptx, key) \
pcp_keysig_t *__s = NULL; \
HASH_ITER(hh, ptx->pcpkeysig_hash, key, __s)

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -35,16 +35,14 @@
#define PCP_RAW_KEYSIGSIZE sizeof(pcp_keysig_t) - sizeof(UT_hash_handle)
pcp_keysig_t *keysig2be(pcp_keysig_t *s);
pcp_keysig_t *keysig2native(pcp_keysig_t *s);
/* put a keysig into a buffer, convert to big endian while at it */
Buffer *pcp_keysig2blob(pcp_keysig_t *s);
void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s);
/* same, but allocs buffer */
Buffer *pcp_keysigblob(pcp_keysig_t *s);
/* fetch a keysig from a buffer, usually loaded from vault */
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
pcp_keysig_t *pcp_blob2keysig(Buffer *blob);
/* debug print a keysig */
void pcp_dumpkeysig(pcp_keysig_t *s);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2014 T.v.Dein.
Copyright (C) 2014-2016 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
@@ -38,6 +38,11 @@
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif
#
# ifndef __USE_XOPEN
# define __USE_XOPEN 1
# endif
#
#else
# define _BSD_SOURCE 1
#endif

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -25,47 +25,6 @@
#include "config.h"
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#else /* no endian.h */
# ifdef HAVE_SYS_ENDIAN_H
# include <sys/types.h>
# include <sys/endian.h>
# ifndef HAVE_BE32TOH
# /* openbsd, use aliases */
# define be16toh betoh16
# define be32toh betoh32
# define be64toh betoh64
# endif
# else /* no sys/endian.h */
# ifdef __CPU_IS_BIG_ENDIAN
# define be16toh(x) (x)
# define htobe16(x) (x)
# define be32toh(x) (x)
# define htobe32(x) (x)
# define be64toh(x) (x)
# define htobe64(x) (x)
# else
# ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
# else
# ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
# else
# error Need either netinet/in.h or arpa/inet.h for ntohl() and htonl()
# endif
# endif
# define be16toh(x) ((uint16_t)ntohl((uint16_t)(x)))
# define htobe16(x) ((uint16_t)htonl((uint16_t)(x)))
# define be32toh(x) ((uint32_t)ntohl((uint32_t)(x)))
# define htobe32(x) ((uint32_t)htonl((uint32_t)(x)))
# define be64toh(x) ((uint64_t)ntohl((uint64_t)(x)))
# define htobe64(x) ((uint64_t)htonl((uint64_t)(x)))
# endif
# endif /* HAVE_SYS_ENDIAN_H */
#endif /* HAVE_ENDIAN_H */
#ifndef HAVE_ARC4RANDOM
#include <sodium.h>
#define arc4random() randombytes_random()

View File

@@ -35,9 +35,14 @@
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "defines.h"
#include "context.h"
#include "pcp.h"
#include "util.h"
#define MAXPASSLEN 2048
@@ -52,6 +57,13 @@
* ${passwd}. The obscure name is to avoid namespace collisions due to the
* getpass / readpass / readpassphrase / etc. functions in various libraries.
*/
int pcp_readpass(char **, const char *, const char *, int, char *);
int pcp_readpass(PCPCTX *ptx, char **passwd, const char *prompt,
const char *confirmprompt, int devtty, char *readfromfile);
/**
from encfs getUserKey().
*/
int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass);
#endif /* !_READPASS_H_ */

View File

@@ -70,21 +70,21 @@
*/
struct _pcp_key_t {
byte masterpub[32]; /**< ED25519 master public key signing key */
byte mastersecret[64]; /**< ED25519 master secret key signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte secret[32]; /**< Curve25519 encryption secret key */
byte edpub[32]; /**< ED25519 public signing key */
byte edsecret[64]; /**< ED25519 secret signing key */
byte nonce[24]; /**< random nonce used to encrypt secret keys */
byte encrypted[176]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte mastersecret[LEDSEC]; /**< ED25519 master secret key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte secret[LBOXSEC]; /**< Curve25519 encryption secret key */
byte edpub[LEDPUB]; /**< ED25519 public signing key */
byte edsecret[LEDSEC]; /**< ED25519 secret signing key */
byte nonce[LNONCE]; /**< random nonce used to encrypt secret keys */
byte encrypted[LSEC]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
UT_hash_handle hh;
};
@@ -99,18 +99,17 @@ typedef struct _pcp_key_t pcp_key_t;
without the secret and nonce fields.
*/
struct _pcp_pubkey_t {
byte masterpub[32]; /**< ED25519 master public key signing key */
byte sigpub[32]; /**< ED25519 public signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte edpub[32]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
uint8_t valid; /**< 1 if import signature verified, 0 if not */
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte edpub[LEDPUB]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
uint8_t valid; /**< 1 if import signature verified, 0 if not */
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES]; /**< raw binary blob of pubkey export signature */
UT_hash_handle hh;
};
@@ -122,7 +121,7 @@ typedef struct _pcp_pubkey_t pcp_pubkey_t;
/* the PBP public key format */
/* keys.mp+keys.cp+keys.sp+keys.name */
struct _pbp_pubkey_t {
byte sigpub[crypto_sign_PUBLICKEYBYTES];
byte masterpub[crypto_sign_PUBLICKEYBYTES];
byte edpub[crypto_sign_PUBLICKEYBYTES];
byte pub[crypto_box_PUBLICKEYBYTES];
char iso_ctime[32];
@@ -158,7 +157,7 @@ struct _pcp_keysig_t {
uint8_t type;
uint32_t size;
char id[17];
byte checksum[32];
byte checksum[LSHA];
byte *blob;
UT_hash_handle hh;
};
@@ -229,7 +228,7 @@ struct _vault_t {
time_t modified; /**< mtime */
mode_t mode; /**< File mode */
uint32_t version; /**< Vault version */
byte checksum[32]; /**< SHA256 checksum over the whole vault */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/** Name of the struct */
@@ -240,7 +239,7 @@ typedef struct _vault_t vault_t;
struct _vault_header_t {
uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */
uint32_t version; /**< File version */
byte checksum[32]; /**< SHA256 checksum over the whole vault */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/** Name of the struct */
@@ -252,7 +251,7 @@ struct _vault_item_header_t {
uint8_t type; /**< Item type (secret key, public, key, keysig, \see _PCP_KEY_TYPES */
uint32_t size; /**< Size of the item */
uint32_t version; /**< Version of the item */
byte checksum[32]; /**< SHA256 checksum of the item */
byte checksum[LSHA]; /**< SHA256 checksum of the item */
};
/** Name of the struct */
@@ -312,6 +311,7 @@ struct _pcp_stream_t {
Buffer *cache; /**< The caching Buffer object (for look ahead read) */
Buffer *next; /**< The caching Next-Buffer object (for look ahead read) */
Buffer *save; /**< Temporary buffer to backup overflow data */
byte *xb; /**< Temporary byte buffer for reading/writing data */
uint8_t is_buffer; /**< Set to 1 if the backend is a Buffer */
uint8_t eof; /**< Set to 1 if EOF reached */
uint8_t err; /**< Set to 1 if an error occured */

View File

@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "platform.h"
#include "defines.h"
@@ -115,6 +116,27 @@ char *_bin2hex(byte *bin, size_t len);
*/
size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_array_max);
/** compare two memory regions in a constant time
\param[in] m1 array1
\param[in] m2 array2
\param[in] n size in bytes to compare
\return 0 if m1 and m2 are equal up to n
*/
int cst_time_memcmp(const void *m1, const void *m2, size_t n);
// be32toh
uint64_t _wireto64(byte *data);
uint32_t _wireto32(byte *data);
uint16_t _wireto16(byte *data);
// htobe32
void _64towire(uint64_t i, byte *data);
void _32towire(uint32_t i, byte *data);
void _16towire(uint16_t i, byte *data);
#endif /* _HAVE_PCP_UTIL_H */
/**@}*/

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -24,7 +24,7 @@
#define _HAVE_PCP_VERSION
#define PCP_VERSION_MAJOR 0
#define PCP_VERSION_MINOR 3
#define PCP_VERSION_MINOR 4
#define PCP_VERSION_PATCH 0
#define PCP_VERSION PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH)

View File

@@ -18,7 +18,7 @@
#
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
AM_CFLAGS = -I../include/pcp -Iscrypt/util
AM_CFLAGS = -I../include/pcp
lib_LTLIBRARIES = libpcp1.la
@@ -27,7 +27,7 @@ pkgconfig_DATA = libpcp1.pc
libpcp1_la_SOURCES = platform.c mem.c version.c \
context.c z85.c zmq_z85.c key.c randomart.c \
vault.c jenhash.c \
vault.c jenhash.c readpass.c \
crypto.c ed.c keyhash.c scrypt.c \
util.c buffer.c mgmt.c keysig.c pcpstream.c

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -62,7 +62,7 @@ void buffer_free(Buffer *b) {
if(b->allocated == 1) {
/* free the underlying data pointer only if we allocated it */
if(b->end > 0) {
buffer_clear(b);
buffer_clear(b);
}
free(b->buf);
b->allocated = 0;
@@ -95,7 +95,7 @@ void buffer_add_str(Buffer *b, const char * fmt, ...) {
if(vasprintf(&dst, fmt, ap) >= 0) {
if(b->end > 0)
b->end--;
buffer_add(b, dst, strlen(dst)+1);
buffer_add(b, dst, strlen(dst));
}
va_end(ap);
free(dst);
@@ -132,7 +132,7 @@ byte *buffer_get(Buffer *b) {
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
if(len > b->end - b->offset) {
final("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
b->name, len, b->end - b->offset, b->offset);
b->name, len, b->end - b->offset, b->offset);
}
else if(len == 0) {
/* FIXME: check how this happens */
@@ -148,7 +148,7 @@ size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
size_t buffer_fwd_offset(Buffer *b, size_t fwdby) {
if(fwdby > b->end - b->offset) {
final("[buffer %s] attempt to set offset %ld bytes forward data from buffer with %ld bytes left at offset %ld\n",
b->name, fwdby, b->end - b->offset, b->offset);
b->name, fwdby, b->end - b->offset, b->offset);
}
else if(fwdby == 0) {
return 0;
@@ -161,7 +161,7 @@ size_t buffer_fwd_offset(Buffer *b, size_t fwdby) {
size_t buffer_get_chunk_tobuf(Buffer *b, Buffer *dst, size_t len) {
if(len > b->end - b->offset) {
final("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
b->name, len, b->end - b->offset, b->offset);
b->name, len, b->end - b->offset, b->offset);
}
else if(len == 0) {
/* FIXME: check how this happens */
@@ -221,30 +221,27 @@ uint64_t buffer_get64(Buffer *b) {
}
uint16_t buffer_get16na(Buffer *b) {
uint16_t i;
if(buffer_get_chunk(b, &i, 2) > 0) {
i = be16toh(i);
return i;
uint8_t bin[2];
if(buffer_get_chunk(b, bin, 2) > 0) {
return _wireto16(bin);
}
else
return 0;
}
uint32_t buffer_get32na(Buffer *b) {
uint32_t i;
if(buffer_get_chunk(b, &i, 4) > 0) {
i = be32toh(i);
return i;
uint8_t bin[4];
if(buffer_get_chunk(b, bin, 4) > 0) {
return _wireto32(bin);
}
else
return 0;
}
uint64_t buffer_get64na(Buffer *b) {
uint64_t i;
if(buffer_get_chunk(b, &i, 8) > 0) {
i = be64toh(i);
return i;
uint8_t bin[8];
if(buffer_get_chunk(b, bin, 8) > 0) {
return _wireto64(bin);
}
else
return 0;
@@ -362,19 +359,19 @@ void buffer_add64(Buffer *b, uint64_t v) {
}
void buffer_add16be(Buffer *b, uint16_t v) {
uint16_t e = v;
e = htobe16(e);
buffer_add(b, &e, 2);
uint8_t bin[2];
_16towire(v, bin);
buffer_add(b, bin, 2);
}
void buffer_add32be(Buffer *b, uint32_t v) {
uint32_t e = v;
e = htobe32(e);
buffer_add(b, &e, 4);
uint8_t bin[4];
_32towire(v, bin);
buffer_add(b, bin, 4);
}
void buffer_add64be(Buffer *b, uint64_t v) {
uint64_t e = v;
e = htobe64(e);
buffer_add(b, &e, 8);
uint8_t bin[8];
_64towire(v, bin);
buffer_add(b, bin, 8);
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -43,7 +43,10 @@ PCPCTX *ptx_new() {
p->pcppubkey_hash = NULL;
p->pcpkeysig_hash = NULL;
sodium_init();
if(sodium_init() == -1) {
perror("failed to initialize libsodium");
exit(1);
}
return p;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -24,11 +24,10 @@
/* asym encr */
byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *message, size_t messagesize,
size_t *csize) {
byte *message, size_t messagesize,
size_t *csize) {
byte *nonce = pcp_gennonce();
@@ -44,14 +43,14 @@ byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
}
/* put nonce and cipher together */
byte *combined = ucmalloc(es + crypto_secretbox_NONCEBYTES);
memcpy(combined, nonce, crypto_secretbox_NONCEBYTES);
memcpy(&combined[crypto_secretbox_NONCEBYTES], cipher, es);
byte *combined = ucmalloc(es + LNONCE);
memcpy(combined, nonce, LNONCE);
memcpy(&combined[LNONCE], cipher, es);
free(cipher);
free(nonce);
*csize = es + crypto_secretbox_NONCEBYTES;
*csize = es + LNONCE;
return combined;
@@ -66,21 +65,21 @@ byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
/* asym decr */
byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *cipher, size_t ciphersize,
size_t *dsize) {
byte *cipher, size_t ciphersize,
size_t *dsize) {
byte *message = NULL;
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
byte *cipheronly = ucmalloc(ciphersize - crypto_secretbox_NONCEBYTES);
byte *nonce = ucmalloc(LNONCE);
byte *cipheronly = ucmalloc(ciphersize - LNONCE);
memcpy(nonce, cipher, crypto_secretbox_NONCEBYTES);
memcpy(cipheronly, &cipher[crypto_secretbox_NONCEBYTES],
ciphersize - crypto_secretbox_NONCEBYTES);
memcpy(nonce, cipher, LNONCE);
memcpy(cipheronly, &cipher[LNONCE],
ciphersize - LNONCE);
message = ucmalloc(ciphersize - crypto_secretbox_NONCEBYTES - crypto_box_MACBYTES);
if(crypto_box_open_easy(message, cipheronly, ciphersize - crypto_secretbox_NONCEBYTES,
nonce, pub->pub, secret->secret) != 0) {
message = ucmalloc(ciphersize - LNONCE - crypto_box_MACBYTES);
if(crypto_box_open_easy(message, cipheronly, ciphersize - LNONCE,
nonce, pub->pub, secret->secret) != 0) {
fatal(ptx, "failed to decrypt message!\n");
goto errbed;
}
@@ -90,7 +89,7 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
/* resulting size: */
/* ciphersize - crypto_secretbox_ZEROBYTES */
*dsize = ciphersize - crypto_secretbox_NONCEBYTES - PCP_CRYPTO_ADD;
*dsize = ciphersize - LNONCE - LMAC;
return message;
errbed:
@@ -104,29 +103,28 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
/* sym encr */
size_t pcp_sodium_mac(byte **cipher,
byte *cleartext,
size_t clearsize,
byte *nonce,
byte *key) {
byte *cleartext,
size_t clearsize,
byte *nonce,
byte *key) {
*cipher = ucmalloc(clearsize + crypto_secretbox_MACBYTES);
*cipher = ucmalloc(clearsize + LMAC);
crypto_secretbox_easy(*cipher, cleartext, clearsize, nonce, key);
return clearsize + crypto_secretbox_MACBYTES;
return clearsize + LMAC;
}
/* sym decr */
int pcp_sodium_verify_mac(byte **cleartext, byte* message,
size_t messagesize, byte *nonce,
byte *key) {
size_t messagesize, byte *nonce,
byte *key) {
*cleartext = ucmalloc(messagesize - crypto_secretbox_MACBYTES);
return crypto_secretbox_open_easy(*cleartext, message, messagesize, nonce, key);
}
size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify, int anon) {
pcp_pubkey_t *cur = NULL;
pcp_pubkey_t *cur = NULL, *fromsec = NULL;
byte *reccipher = NULL;
int recmatch, self;
uint32_t lenrec;
@@ -147,31 +145,41 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
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;
else {
fatal(ptx, "Input is symetrically encrypted but no key have been specified (lib usage failure)\n");
goto errdef1;
}
if(symkey != NULL)
self = 1;
else {
fatal(ptx, "Input is symetrically encrypted but no key have been specified (lib usage failure)\n");
goto errdef1;
}
}
else if(head[0] == PCP_ASYM_CIPHER_ANON) {
self = 0;
anon = 1;
self = 0;
anon = 1;
}
else if(head[0] == PCP_ASYM_CIPHER_ANON_SIG) {
self = 0;
anon = 1;
verify = 1;
}
else if(head[0] == PCP_ASYM_CIPHER) {
self = 0;
self = 0;
}
else if(head[0] == PCP_ASYM_CIPHER_SIG) {
self = 0;
verify = 1;
self = 0;
verify = 1;
}
else {
fatal(ptx, "Unknown file header (got: %02x)\n", head[0]);
goto errdef1;
fatal(ptx, "Unknown file header (got: %02x)\n", head[0]);
goto errdef1;
}
}
}
if(ptx->verbose) {
fprintf(stderr, "crypto.c: header <= self: %d, anon: %d, verify:%d\n",
self, anon, verify);
}
if(self) {
/* just decrypt symetrically and go outa here */
return pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
@@ -185,81 +193,119 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
fatal(ptx, "Error: input file doesn't contain senders public key\n");
goto errdef1;
}
if(ptx->verbose) {
fprintf(stderr, "crypto.c: <= sender anon pub key:\n");
pcp_dumppubkey(senderpub);
}
}
/* step 3, check len recipients */
cur_bufsize = ps_read(in, &lenrec, 4); /* fread(&lenrec, 1, 4, in); */
byte li[4];
cur_bufsize = ps_read(in, li, 4); /* fread(&lenrec, 1, 4, in); */
if(cur_bufsize != 4 && !ps_end(in) && !ps_err(in)) {
fatal(ptx, "Error: input file doesn't contain recipient count\n");
goto errdef1;
}
lenrec = be32toh(lenrec);
lenrec = _wireto32(li);
if (ptx->verbose) {
fprintf(stderr, "crypto.c: input is encrypted for %ld recipients\n", (long int)lenrec);
}
if(verify) {
reccipher = ucmalloc(lenrec * PCP_ASYM_RECIPIENT_SIZE);
}
/* step 4, fetch recipient list and try to decrypt it for us */
rec_buf = ucmalloc(PCP_ASYM_RECIPIENT_SIZE);
for(nrec=0; nrec<lenrec; nrec++) {
cur_bufsize = ps_read(in, rec_buf, PCP_ASYM_RECIPIENT_SIZE);
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
fatal(ptx, "Error: input file corrupted, incomplete or no recipients (got %ld, exp %ld)\n",
cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
ucfree(rec_buf, PCP_ASYM_RECIPIENT_SIZE);
goto errdef1;
}
recmatch = 0;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: <= rec_cipher:\n");
_dump("crypto.c: encrypted rec cipher", rec_buf, cur_bufsize);
}
if(anon) {
/* anonymous sender */
byte *recipient;
recipient = pcp_box_decrypt(ptx, s, senderpub, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
ucfree(senderpub, sizeof(pcp_pubkey_t));
break;
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
ucfree(senderpub, sizeof(pcp_pubkey_t));
if(verify) {
memcpy(reccipher, rec_buf, PCP_ASYM_RECIPIENT_SIZE);
}
nrec++; /* otherwise missing */
if(ptx->verbose) {
_dump("crypto.c: got anon symkey", symkey, crypto_secretbox_KEYBYTES);
}
break;
}
free(recipient);
}
else {
/* dig through our list of known public keys for a match */
pcphash_iteratepub(ptx, cur) {
byte *recipient;
recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
break;
}
free(recipient);
byte *recipient;
recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
if(ptx->verbose) {
fprintf(stderr, "crypto.c: matching pub key:\n");
pcp_dumppubkey(cur);
_dump("crypto.c: got recipient symkey", symkey, crypto_secretbox_KEYBYTES);
}
break;
}
free(recipient);
}
/* do the same with our secret keys, just in case the sender used -M */
if(recmatch == 0) {
pcp_key_t *k;
pcphash_iterate(ptx, k) {
cur = pcpkey_pub_from_secret(k);
byte *recipient;
recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
break;
}
}
pcp_key_t *k;
pcphash_iterate(ptx, k) {
if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t)); /* avoid overwrite of used mem */
fromsec = pcpkey_pub_from_secret(k);
byte *recipient;
recipient = pcp_box_decrypt(ptx, s, fromsec, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
cur = fromsec;
if(ptx->verbose) {
_dump("crypto.c: got my own sec symkey", symkey, crypto_secretbox_KEYBYTES);
}
break;
}
}
}
}
if(verify) {
@@ -278,35 +324,40 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
/* step 5, actually decrypt the file, finally */
if(verify) {
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur);
size_t s = pcp_decrypt_stream_sym(ptx, in, out, symkey, rec);
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * (PCP_ASYM_RECIPIENT_SIZE), NULL, cur);
nrec = pcp_decrypt_stream_sym(ptx, in, out, symkey, rec);
pcp_rec_free(rec);
ucfree(reccipher, lenrec * PCP_ASYM_RECIPIENT_SIZE);
sfree(symkey);
return s;
}
else {
size_t s = pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
sfree(symkey);
return s;
nrec = pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
}
if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t));
sfree(symkey);
return nrec;
errdef1:
if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t));
sfree(symkey);
return 0;
}
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t *s, pcp_pubkey_t *p, int sign, int anon) {
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t *secret,
pcp_key_t *signsecret, pcp_pubkey_t *p, int sign, int anon) {
byte *symkey;
int recipient_count;
byte *recipients_cipher;
pcp_pubkey_t *cur, *t;
size_t es;
int nrec;
uint32_t lenrec;
size_t rec_size, out_size;
byte head[1];
byte bo[4];
/*
6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...)
where recipients is a concatenated list of
@@ -317,22 +368,36 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
/* A, generate sym key */
symkey = srmalloc(crypto_secretbox_KEYBYTES);
if(ptx->verbose) {
_dump("crypto.c: new symkey", symkey, crypto_secretbox_KEYBYTES);
}
/* B, encrypt it asymetrically for each recipient */
recipient_count = HASH_COUNT(p);
rec_size = PCP_ASYM_RECIPIENT_SIZE;
recipients_cipher = ucmalloc(rec_size * recipient_count);
nrec = 0;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: async recipients: %d\n", recipient_count);
}
HASH_ITER(hh, p, cur, t) {
byte *rec_cipher;
rec_cipher = pcp_box_encrypt(ptx, s, cur, symkey, crypto_secretbox_KEYBYTES, &es);
rec_cipher = pcp_box_encrypt(ptx, secret, cur, symkey, crypto_secretbox_KEYBYTES, &es);
if(es != rec_size) {
fatal(ptx, "invalid rec_size, expected %dl, got %dl\n", rec_size, es);
if(rec_cipher != NULL)
free(rec_cipher);
free(rec_cipher);
goto errec1;
}
if(ptx->verbose) {
fprintf(stderr, "crypto.c: recipient pub key:\n");
pcp_dumppubkey(cur);
_dump("crypto.c: encrypted rec cipher", rec_cipher, rec_size);
}
/* put it into the recipient list, already includes the nonce */
memcpy(&recipients_cipher[nrec * rec_size], rec_cipher, rec_size);
nrec++;
@@ -340,14 +405,21 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
}
/* step 1, file header */
if(sign)
head[0] = PCP_ASYM_CIPHER_SIG;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: header => anon: %d, verify:%d\n",
anon, sign);
}
if(sign && anon)
head[0] = PCP_ASYM_CIPHER_ANON_SIG;
else if(sign)
head[0] = PCP_ASYM_CIPHER_SIG;
else if(anon)
head[0] = PCP_ASYM_CIPHER_ANON;
else
else
head[0] = PCP_ASYM_CIPHER;
ps_write(out, head, 1);
if(ps_err(out) != 0) {
fatal(ptx, "Failed to write encrypted output!\n");
goto errec1;
@@ -355,26 +427,25 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
if(anon) {
/* step 2, sender's pubkey */
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); */
ps_write(out, secret->pub, crypto_box_PUBLICKEYBYTES);
if(ps_err(out) != 0)
goto errec1;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: => anon pub key:\n");
_dump("crypto.c: => anon pub key", secret->pub, 32);
}
}
/* step 3, len recipients, big endian */
lenrec = recipient_count;
lenrec = htobe32(lenrec);
ps_write(out, &lenrec, 4);
/* fwrite(&lenrec, 4, 1, out); */
/* fprintf(stderr, "D: %d recipients - 4\n", recipient_count); */
_32towire(recipient_count, bo);
ps_write(out, bo, 4);
if(ps_err(out) != 0)
goto errec1;
/* step 4, recipient list */
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(ps_err(out) != 0)
goto errec1;
@@ -383,7 +454,7 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
/* step 5, actual encrypted data */
size_t sym_size = 0;
if(sign) {
pcp_rec_t *rec = pcp_rec_new(recipients_cipher, rec_size * recipient_count, s, NULL);
pcp_rec_t *rec = pcp_rec_new(recipients_cipher, rec_size * recipient_count, signsecret, NULL);
sym_size = pcp_encrypt_stream_sym(ptx, in, out, symkey, 1, rec);
pcp_rec_free(rec);
}
@@ -440,11 +511,13 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
if(havehead == 0) {
head[0] = PCP_SYM_CIPHER;
es = ps_write(out, head, 1);
/* es = fwrite(head, 1, 1, out); */
if(ps_err(out) != 0) {
fatal(ptx, "Failed to write encrypted output!\n");
return 0;
}
if(ptx->verbose) {
fprintf(stderr, "crypto.c: => header: self: 1\n");
}
}
/* 32k-Block-mode. */
@@ -458,15 +531,15 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
buf_nonce = _gen_ctr_nonce(ctr++);
es = pcp_sodium_mac(&buf_cipher, in_buf, cur_bufsize, buf_nonce, symkey);
ps_write(out, buf_nonce, crypto_secretbox_NONCEBYTES);
ps_write(out, buf_nonce, LNONCE);
ps_write(out, buf_cipher, es);
out_size += crypto_secretbox_NONCEBYTES + es;
out_size += LNONCE + es;
if(recsign != NULL)
crypto_generichash_update(st, buf_cipher, es);
ucfree(buf_nonce, crypto_secretbox_NONCEBYTES);
ucfree(buf_nonce, LNONCE);
free(buf_cipher);
}
@@ -479,26 +552,32 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
if(recsign != NULL) {
/* add encrypted recipient list to the hash */
crypto_generichash_update(st, recsign->cipher, recsign->ciphersize);
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
crypto_generichash_final(st, hash, LHASH);
/* generate the actual signature */
byte *signature = pcp_ed_sign(hash, crypto_generichash_BYTES_MAX, recsign->secret);
size_t siglen = crypto_sign_BYTES + crypto_generichash_BYTES_MAX;
byte *signature = pcp_ed_sign(hash, LHASH, recsign->secret);
size_t siglen = LSIG + LHASH;
/* 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_nonce, LNONCE);
ps_write(out, buf_cipher, es);
if(ptx->verbose) {
_dump("crypto.c: => sig", signature, siglen);
_dump("crypto.c: => nonce", buf_nonce, LNONCE);
_dump("crypto.c: => enc sig", buf_cipher, es);
}
free(st);
free(hash);
ucfree(buf_nonce, crypto_secretbox_NONCEBYTES);
ucfree(buf_nonce, LNONCE);
free(buf_cipher);
ucfree(signature, siglen);
}
ucfree(in_buf, PCP_BLOCK_SIZE);
return out_size;
@@ -512,17 +591,18 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
return 0;
}
size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, pcp_rec_t *recverify) {
size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out,
byte *symkey, pcp_rec_t *recverify) {
byte *buf_nonce;
byte *buf_cipher;
byte *buf_clear;
size_t out_size, cur_bufsize, es;
size_t ciphersize = (PCP_BLOCK_SIZE_IN) - crypto_secretbox_NONCEBYTES;
size_t ciphersize = (PCP_BLOCK_SIZE_IN) - LNONCE;
byte *in_buf = NULL;
uint64_t ctr, pastctr;
pastctr = 0;
buf_nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
buf_nonce = ucmalloc(LNONCE);
buf_cipher = ucmalloc(ciphersize);
buf_clear = ucmalloc(ciphersize);
out_size = 0;
@@ -530,7 +610,7 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
byte *signature = NULL;
byte *signature_cr = NULL;
size_t siglen = crypto_sign_BYTES + crypto_generichash_BYTES_MAX;
size_t siglen_cr = siglen + PCP_CRYPTO_ADD + crypto_secretbox_NONCEBYTES;
size_t siglen_cr = siglen + LMAC + LNONCE;
crypto_generichash_state *st = NULL;
byte *hash = NULL;
@@ -539,26 +619,27 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
hash = ucmalloc(crypto_generichash_BYTES_MAX);
crypto_generichash_init(st, NULL, 0, 0);
signature_cr = ucmalloc(siglen_cr);
signature = ucmalloc(siglen);
}
in_buf = ucmalloc(PCP_BLOCK_SIZE_IN);
while(!ps_end(in)) {
cur_bufsize = ps_read(in, in_buf, PCP_BLOCK_SIZE_IN);
if(cur_bufsize <= PCP_CRYPTO_ADD)
if(cur_bufsize <= LMAC)
break; /* no valid cipher block */
if(recverify != NULL) {
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;
/* pull out signature */
memcpy(signature_cr, &in_buf[cur_bufsize - siglen_cr], siglen_cr);
cur_bufsize -= siglen_cr;
}
}
ciphersize = cur_bufsize - crypto_secretbox_NONCEBYTES;
memcpy(buf_nonce, in_buf, crypto_secretbox_NONCEBYTES);
memcpy(buf_cipher, &in_buf[crypto_secretbox_NONCEBYTES], ciphersize);
ciphersize = cur_bufsize - LNONCE;
memcpy(buf_nonce, in_buf, LNONCE);
memcpy(buf_cipher, &in_buf[LNONCE], ciphersize);
/* extract counter from nonce and check if it is in line with previous one
TODO: save unordered buffers to disk and continue writing to out if
@@ -566,25 +647,25 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
ctr = _get_nonce_ctr(buf_nonce);
if(ctr -1 != pastctr) {
fatal(ptx, "Mangled packet order, bailing out (got: %ld, expected: %ld)!\n",
ctr, pastctr+1);
ctr, pastctr+1);
out_size = 0;
break;
}
pastctr = ctr;
es = pcp_sodium_verify_mac(&buf_clear, buf_cipher, ciphersize, buf_nonce, symkey);
out_size += ciphersize - PCP_CRYPTO_ADD;
out_size += ciphersize - LMAC;
if(es == 0) {
ps_write(out, buf_clear, ciphersize - PCP_CRYPTO_ADD);
ps_write(out, buf_clear, ciphersize - LMAC);
if(recverify != NULL)
crypto_generichash_update(st, buf_cipher, ciphersize);
crypto_generichash_update(st, buf_cipher, ciphersize);
if(ps_err(out) != 0) {
fatal(ptx, "Failed to write decrypted output!\n");
out_size = 0;
break;
fatal(ptx, "Failed to write decrypted output!\n");
out_size = 0;
break;
}
}
else {
@@ -596,30 +677,50 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
ucfree(in_buf, PCP_BLOCK_SIZE_IN);
ucfree(buf_cipher, ciphersize);
ucfree(buf_clear, ciphersize - PCP_CRYPTO_ADD);
ucfree(buf_clear, ciphersize - LMAC);
if(recverify != NULL) {
/* decrypt the signature */
memcpy(buf_nonce, signature_cr, crypto_secretbox_NONCEBYTES);
memcpy(buf_nonce, signature_cr, LNONCE);
es = pcp_sodium_verify_mac(&signature, &signature_cr[crypto_secretbox_NONCEBYTES],
siglen_cr - crypto_secretbox_NONCEBYTES, buf_nonce, symkey);
es = pcp_sodium_verify_mac(&signature, &signature_cr[LNONCE],
siglen_cr - LNONCE, buf_nonce, symkey);
if(es == 0) {
/* add encrypted recipient list to the hash */
crypto_generichash_update(st, recverify->cipher, recverify->ciphersize);
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
byte *verifiedhash = NULL;
verifiedhash = pcp_ed_verify(ptx, signature, siglen, recverify->pub);
if(verifiedhash == NULL)
out_size = 0;
if(recverify->pub == NULL) {
/* anonymous encrypted but with known pub signed,
dig through our list of known public keys for a match */
pcp_pubkey_t *cur;
pcphash_iteratepub(ptx, cur) {
verifiedhash = pcp_ed_verify(ptx, signature, siglen, cur);
if(verifiedhash != NULL)
break;
}
}
else {
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't match */
fatal(ptx, "signed hash doesn't match actual hash of signed decrypted file content\n");
out_size = 0;
}
free(verifiedhash);
verifiedhash = pcp_ed_verify(ptx, signature, siglen, recverify->pub);
}
if(verifiedhash == NULL)
out_size = 0;
else {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't match */
fatal(ptx, "signed hash doesn't match actual hash of signed decrypted file content\n");
out_size = 0;
}
free(verifiedhash);
}
if(ptx->verbose) {
_dump("crypto.c: <= sig", signature, siglen);
_dump("crypto.c: <= nonce", buf_nonce, LNONCE);
_dump("crypto.c: <= enc sig", &signature_cr[LNONCE], siglen_cr - LNONCE);
}
}
else {
@@ -643,7 +744,6 @@ pcp_rec_t *pcp_rec_new(byte *cipher, size_t clen, pcp_key_t *secret, pcp_pubkey_
r->cipher = ucmalloc(clen);
memcpy(r->cipher, cipher, clen);
r->ciphersize = clen;
if(secret != NULL) {
r->secret = ucmalloc(sizeof(pcp_key_t));
memcpy(r->secret, secret, sizeof(pcp_key_t));
@@ -690,30 +790,25 @@ void pcp_rec_free(pcp_rec_t *r) {
uint64_t _get_nonce_ctr(byte *nonce) {
uint64_t ctr = 0;
uint8_t i = nonce[0];
uint16_t m16 = 0;
uint32_t m32 = 0;
if(i > 16) {
/* counter bigger than max allowed by protocol, could lead to overflow, therefore die hard here */
fprintf(stderr, "invalid counter size %d!", i);
abort();
}
switch(i) {
case 1:
ctr = nonce[1];
break;
case 2:
memcpy(&m16, &nonce[1], 2);
ctr = be16toh(m16);
ctr = _wireto16(&nonce[1]);
break;
case 4:
memcpy(&m32, &nonce[1], 4);
ctr = be32toh(m32);
ctr = _wireto32(&nonce[1]);
break;
case 8:
memcpy(&ctr, &nonce[1], 8);
ctr = be64toh(ctr);
ctr = _wireto64(&nonce[1]);
break;
}
@@ -777,25 +872,21 @@ byte *_gen_ctr_nonce(uint64_t ctr) {
uint8_t m8 = -1;
uint16_t m16 = -1;
uint32_t m32 = -1;
uint64_t m64 = -1;
uint8_t i = 1;
byte *nonce = pcp_gennonce();
if(ctr > m32) {
i = 8;
m64 = htobe64(ctr);
memcpy(&nonce[1], &m64, 8);
_64towire(ctr, &nonce[1]);
}
else if(ctr < m32 && ctr > m16) {
else if(ctr <= m32 && ctr > m16) {
i = 4;
m32 = htobe32(ctr);
memcpy(&nonce[1], &m32, 4);
_32towire(ctr, &nonce[1]);
}
else if(ctr < m16 && ctr > m8) {
else if(ctr <= m16 && ctr > m8) {
i = 2;
m16 = htobe16(ctr);
memcpy(&nonce[1], &m16, 2);
_16towire(ctr, &nonce[1]);
}
else {
i = 1;

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -212,11 +212,11 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
cur_bufsize = offset;
gotsig = 1;
if(z85) {
cur_bufsize -= 1;
memcpy(z85encoded, &in_full[offset], zlen);
cur_bufsize -= 1;
memcpy(z85encoded, &in_full[offset], zlen);
}
else
memcpy(sighash, &in_full[offset + strlen(binsigstart)], mlen);
memcpy(sighash, &in_full[offset + strlen(binsigstart)], mlen);
}
else if(full_bufsize - offset == siglen) {
/* sig fits within the 2nd half */
@@ -225,11 +225,11 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
next_bufsize -= siglen;
gotsig = 1;
if(z85) {
cur_bufsize -= 1;
memcpy(z85encoded, &in_full[full_bufsize - siglen], siglen);
cur_bufsize -= 1;
memcpy(z85encoded, &in_full[full_bufsize - siglen], siglen);
}
else
memcpy(sighash, &in_full[full_bufsize - mlen], mlen);
memcpy(sighash, &in_full[full_bufsize - mlen], mlen);
}
else
offset = 0;
@@ -276,7 +276,7 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
pcphash_iteratepub(ptx, p) {
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, p);
if(verifiedhash != NULL)
break;
break;
}
/* no pubkey found yet, try our own */
@@ -284,13 +284,13 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
pcp_pubkey_t *pub;
pcphash_iterate(ptx, k) {
if(k->type == PCP_KEY_TYPE_MAINSECRET) {
pub = pcpkey_pub_from_secret(k);
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, pub);
if(verifiedhash != NULL) {
/* good, self-signed */
p = pub;
break;
}
pub = pcpkey_pub_from_secret(k);
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, pub);
if(verifiedhash != NULL) {
/* good, self-signed */
p = pub;
break;
}
}
}
}
@@ -301,7 +301,7 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
if(verifiedhash == NULL)
goto errvb1;
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
free(verifiedhash);
@@ -341,7 +341,7 @@ size_t pcp_ed_detachsign_buffered(Pcpstream *in, Pcpstream *out, pcp_key_t *s) {
size_t mlen = + crypto_sign_BYTES + crypto_generichash_BYTES_MAX;
ps_print(out, "%s\r\nVersion: PCP v%d.%d.%d\r\n",
PCP_SIG_START, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
PCP_SIG_START, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
size_t zlen;
char *z85encoded = pcp_z85_encode((byte*)signature, mlen, &zlen, 1);
ps_print(out, "%s\r\n%s\r\n", z85encoded, PCP_SIG_END);
@@ -416,7 +416,7 @@ pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream
pcphash_iteratepub(ptx, p) {
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, p);
if(verifiedhash != NULL)
break;
break;
}
/* no pubkey found yet, try our own */
@@ -424,13 +424,13 @@ pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream
pcp_pubkey_t *pub;
pcphash_iterate(ptx, k) {
if(k->type == PCP_KEY_TYPE_MAINSECRET) {
pub = pcpkey_pub_from_secret(k);
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, pub);
if(verifiedhash != NULL) {
/* good, self-signed */
p = pub;
break;
}
pub = pcpkey_pub_from_secret(k);
verifiedhash = pcp_ed_verify(ptx, sighash, mlen, pub);
if(verifiedhash != NULL) {
/* good, self-signed */
p = pub;
break;
}
}
}
}
@@ -441,7 +441,7 @@ pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream
if(verifiedhash == NULL)
goto errdea4;
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
goto errdea5;

View File

@@ -9,14 +9,14 @@ unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval ) {
while ( len >= 12 ) {
a += ( k[0] + ( (unsigned)k[1] << 8 )
+ ( (unsigned)k[2] << 16 )
+ ( (unsigned)k[3] << 24 ) );
+ ( (unsigned)k[2] << 16 )
+ ( (unsigned)k[3] << 24 ) );
b += ( k[4] + ( (unsigned)k[5] << 8 )
+ ( (unsigned)k[6] << 16 )
+ ( (unsigned)k[7] << 24 ) );
+ ( (unsigned)k[6] << 16 )
+ ( (unsigned)k[7] << 24 ) );
c += ( k[8] + ( (unsigned)k[9] << 8 )
+ ( (unsigned)k[10] << 16 )
+ ( (unsigned)k[11] << 24 ) );
+ ( (unsigned)k[10] << 16 )
+ ( (unsigned)k[11] << 24 ) );
jen_mix ( a, b, c );

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -33,7 +33,7 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
size_t plen = strnlen(passphrase, 255);
/* create the scrypt hash */
byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, crypto_secretbox_NONCEBYTES);
byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, LNONCE);
/* make a hash from the scrypt() result */
crypto_hash_sha256(key, (byte*)scrypted, 64);
@@ -51,8 +51,8 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
char *pcp_getkeyid(pcp_key_t *k) {
uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT);
p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s);
return id;
@@ -61,8 +61,8 @@ char *pcp_getkeyid(pcp_key_t *k) {
/* same as above but for imported pbp keys */
char *pcp_getpubkeyid(pcp_pubkey_t *k) {
uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT);
p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s);
return id;
@@ -95,24 +95,24 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
}
pcp_key_t * pcpkey_new () {
byte *mp = ucmalloc(32);
byte *ms = ucmalloc(64);
byte *sp = ucmalloc(32);
byte *ss = ucmalloc(64);
byte *cp = ucmalloc(32);
byte *cs = ucmalloc(32);
byte *mp = ucmalloc(LEDPUB);
byte *ms = ucmalloc(LEDSEC);
byte *sp = ucmalloc(LEDPUB);
byte *ss = ucmalloc(LEDSEC);
byte *cp = ucmalloc(LBOXPUB);
byte *cs = ucmalloc(LBOXSEC);
/* generate key material */
pcp_keypairs(ms, mp, cs, cp, ss, sp);
/* fill in our struct */
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
memcpy (key->masterpub, mp, 32);
memcpy (key->mastersecret, ms, 64);
memcpy (key->pub, cp, 32);
memcpy (key->secret, cs, 32);
memcpy (key->edpub, sp, 32);
memcpy (key->edsecret, ss, 64);
memcpy (key->masterpub, mp, LEDPUB);
memcpy (key->mastersecret, ms, LEDSEC);
memcpy (key->pub, cp, LBOXPUB);
memcpy (key->secret, cs, LBOXSEC);
memcpy (key->edpub, sp, LEDPUB);
memcpy (key->edsecret, ss, LEDSEC);
char *id = pcp_getkeyid(key);
memcpy (key->id, id, 17);
@@ -128,19 +128,19 @@ pcp_key_t * pcpkey_new () {
key->mail[0] = '\0';
/* clean up */
ucfree(ms, 64);
ucfree(ss, 64);
ucfree(mp, 32);
ucfree(sp, 32);
ucfree(cs, 32);
ucfree(cp, 32);
ucfree(ms, LEDSEC);
ucfree(ss, LEDSEC);
ucfree(mp, LEDPUB);
ucfree(sp, LEDPUB);
ucfree(cs, LBOXSEC);
ucfree(cp, LBOXPUB);
return key;
}
byte * pcp_gennonce() {
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
byte *nonce = ucmalloc(LNONCE);
arc4random_buf(nonce, LNONCE);
return nonce;
}
@@ -152,8 +152,8 @@ void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail) {
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
if(key->nonce[0] == 0) {
byte *nonce = pcp_gennonce();
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
memcpy (key->nonce, nonce, LNONCE);
ucfree(nonce, LNONCE);
}
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
@@ -162,25 +162,22 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
size_t es;
Buffer *both = buffer_new(128, "keypack");
buffer_add(both, key->mastersecret, 64);
buffer_add(both, key->edsecret, 64);
buffer_add(both, key->secret, 32);
buffer_add(both, key->mastersecret, LEDSEC);
buffer_add(both, key->edsecret, LEDSEC);
buffer_add(both, key->secret, LBOXSEC);
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both), key->nonce, encryptkey);
buffer_free(both);
sfree(encryptkey);
if(es == 176) { /* FIXME: calc! */
if(es == LSEC) {
/* success */
memcpy(key->encrypted, encrypted, 176);
memcpy(key->encrypted, encrypted, LSEC);
ucfree(encrypted, es);
arc4random_buf(key->secret, 32);
arc4random_buf(key->edsecret, 64);
arc4random_buf(key->mastersecret, 64);
key->secret[0] = 0;
key->edsecret[0] = 0;
key->mastersecret[0] = 0;
memset(key->secret, 0, LBOXSEC);
memset(key->edsecret, 0, LEDSEC);
memset(key->mastersecret, 0, LEDSEC);
}
else {
fatal(ptx, "failed to encrypt the secret key!\n");
@@ -195,23 +192,23 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *decrypted;
byte *decrypted = ucmalloc(LSEC - crypto_secretbox_MACBYTES);
size_t es;
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, 176, key->nonce, encryptkey);
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, LSEC, key->nonce, encryptkey);
sfree(encryptkey);
if(es == 0) {
/* success */
memcpy(key->mastersecret, decrypted, 64);
memcpy(key->edsecret, decrypted + 64, 64);
memcpy(key->secret, decrypted +128, 32);
ucfree(decrypted, 160);
memcpy(key->mastersecret, decrypted, LEDSEC);
memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
memcpy(key->secret, decrypted + LEDSEC + LEDSEC, LBOXSEC);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
}
else {
fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es);
ucfree(decrypted, 160);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
return NULL;
}
@@ -220,9 +217,9 @@ pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key) {
pcp_pubkey_t *pub = urmalloc(sizeof (pcp_pubkey_t));
memcpy(pub->masterpub, key->masterpub, 32);
memcpy(pub->pub, key->pub, 32);
memcpy(pub->edpub, key->edpub, 32);
memcpy(pub->masterpub, key->masterpub, LEDPUB);
memcpy(pub->pub, key->pub, LBOXPUB);
memcpy(pub->edpub, key->edpub, LEDSEC);
memcpy(pub->owner, key->owner, 255);
memcpy(pub->mail, key->mail, 255);
memcpy(pub->id, key->id, 17);
@@ -245,108 +242,88 @@ char *pcpkey_get_art(pcp_key_t *k) {
byte *pcppubkey_getchecksum(pcp_pubkey_t *k) {
byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32);
crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash;
}
byte *pcpkey_getchecksum(pcp_key_t *k) {
byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32);
crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash;
}
pcp_key_t * key2be(pcp_key_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
uint32_t version = k->version;
byte* p = (byte*)&version;
if(p[0] != 0) {
k->version = htobe32(k->version);
k->serial = htobe32(k->serial);
k->ctime = htobe64(k->ctime);
}
return k;
#endif
}
pcp_key_t *key2native(pcp_key_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
k->version = be32toh(k->version);
k->serial = be32toh(k->serial);
k->ctime = be64toh(k->ctime);
return k;
#endif
}
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
uint32_t version = k->version;
byte* p = (byte*)&version;
if(p[0] != 0) {
k->version = htobe32(k->version);
k->serial = htobe32(k->serial);
k->ctime = htobe64(k->ctime);
}
return k;
#endif
}
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
k->version = be32toh(k->version);
k->serial = be32toh(k->serial);
k->ctime = be64toh(k->ctime);
return k;
#endif
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) {
buffer_add(b, k->masterpub, LEDPUB);
buffer_add(b, k->pub, LBOXPUB);
buffer_add(b, k->edpub, LEDPUB);
buffer_add(b, k->owner, 255);
buffer_add(b, k->mail, 255);
buffer_add(b, k->id, 17);
buffer_add8(b, k->type);
buffer_add64be(b, k->ctime);
buffer_add32be(b, k->version);
buffer_add32be(b, k->serial);
buffer_add8(b, k->valid);
}
void pcp_seckeyblob(Buffer *b, pcp_key_t *k) {
buffer_add(b, k->masterpub, 32);
buffer_add(b, k->mastersecret, 64);
buffer_add(b, k->pub, 32);
buffer_add(b, k->secret, 32);
buffer_add(b, k->edpub, 32);
buffer_add(b, k->edsecret, 64);
buffer_add(b, k->nonce, 24);
buffer_add(b, k->encrypted, 176);
buffer_add(b, k->masterpub, LEDPUB);
buffer_add(b, k->mastersecret, LEDSEC);
buffer_add(b, k->pub, LBOXPUB);
buffer_add(b, k->secret, LBOXPUB);
buffer_add(b, k->edpub, LEDPUB);
buffer_add(b, k->edsecret, LEDSEC);
buffer_add(b, k->nonce, LNONCE);
buffer_add(b, k->encrypted, LSEC);
buffer_add(b, k->owner, 255);
buffer_add(b, k->mail, 255);
buffer_add(b, k->id, 17);
buffer_add8(b, k->type);
buffer_add64(b, k->ctime);
buffer_add32(b, k->version);
buffer_add32(b, k->serial);
buffer_add64be(b, k->ctime);
buffer_add32be(b, k->version);
buffer_add32be(b, k->serial);
}
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) {
buffer_add(b, k->masterpub, 32);
buffer_add(b, k->sigpub, 32);
buffer_add(b, k->pub, 32);
buffer_add(b, k->edpub, 32);
pcp_key_t *pcp_blob2key(Buffer *b) {
pcp_key_t *k = ucmalloc(sizeof(pcp_key_t));
buffer_get_chunk(b, k->masterpub, LEDPUB);
buffer_get_chunk(b, k->mastersecret, LEDSEC);
buffer_get_chunk(b, k->pub, LBOXPUB);
buffer_get_chunk(b, k->secret, LBOXPUB);
buffer_get_chunk(b, k->edpub, LEDPUB);
buffer_get_chunk(b, k->edsecret, LEDSEC);
buffer_get_chunk(b, k->nonce, LNONCE);
buffer_get_chunk(b, k->encrypted, LSEC);
buffer_get_chunk(b, k->owner, 255);
buffer_get_chunk(b, k->mail, 255);
buffer_get_chunk(b, k->id, 17);
buffer_add(b, k->owner, 255);
buffer_add(b, k->mail, 255);
buffer_add(b, k->id, 17);
k->type = buffer_get8(b);
k->ctime = buffer_get64na(b);
k->version = buffer_get32na(b);
k->serial = buffer_get32na(b);
buffer_add8(b, k->type);
buffer_add64(b, k->ctime);
buffer_add32(b, k->version);
buffer_add32(b, k->serial);
buffer_add8(b, k->valid);
return k;
}
pcp_pubkey_t *pcp_blob2pubkey(Buffer *b) {
pcp_pubkey_t *k = ucmalloc(sizeof(pcp_key_t));
buffer_get_chunk(b, k->masterpub, LEDPUB);
buffer_get_chunk(b, k->pub, LBOXPUB);
buffer_get_chunk(b, k->edpub, LEDPUB);
buffer_get_chunk(b, k->owner, 255);
buffer_get_chunk(b, k->mail, 255);
buffer_get_chunk(b, k->id, 17);
k->type = buffer_get8(b);
k->ctime = buffer_get64na(b);
k->version = buffer_get32na(b);
k->serial = buffer_get32na(b);
k->valid = buffer_get8(b);
return k;
}
Buffer *pcp_keyblob(void *k, int type) {
@@ -371,13 +348,13 @@ int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
if(key->type != PCP_KEY_TYPE_PUBLIC) {
fatal(ptx, "Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: %02x)!\n",
PCP_KEY_TYPE_PUBLIC, key->type);
PCP_KEY_TYPE_PUBLIC, key->type);
return 1;
}
if(key->version != PCP_KEY_VERSION) {
fatal(ptx, "Pubkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
PCP_KEY_VERSION, key->version);
PCP_KEY_VERSION, key->version);
return 1;
}
@@ -422,13 +399,13 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
if(key->type != PCP_KEY_TYPE_SECRET && key->type != PCP_KEY_TYPE_MAINSECRET) {
fatal(ptx, "Secretkey sanity check: key type is not SECRET (expected: %02x, got: %02x)!\n",
PCP_KEY_TYPE_SECRET, key->type);
PCP_KEY_TYPE_SECRET, key->type);
return 1;
}
if(key->version != PCP_KEY_VERSION) {
fatal(ptx, "Secretkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
PCP_KEY_VERSION, key->version);
PCP_KEY_VERSION, key->version);
return 1;
}
@@ -465,40 +442,40 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
}
void pcp_dumpkey(pcp_key_t *k) {
int i;
unsigned int i;
printf("Dumping pcp_key_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->masterpub[i]);
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->masterpub[i]);
printf("\n");
printf(" public: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->pub[i]);
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->pub[i]);
printf("\n");
printf(" edpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->edpub[i]);
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->edpub[i]);
printf("\n");
printf("mastersec: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->mastersecret[i]);
for ( i = 0;i < LEDSEC;++i) printf("%02x",(unsigned int) k->mastersecret[i]);
printf("\n");
printf(" secret: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->secret[i]);
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->secret[i]);
printf("\n");
printf(" edsecret: ");
for ( i = 0;i < 64;++i) printf("%02x",(unsigned int) k->edsecret[i]);
for ( i = 0;i < LEDSEC;++i) printf("%02x",(unsigned int) k->edsecret[i]);
printf("\n");
printf(" nonce: ");
for ( i = 0;i < 24;++i) printf("%02x",(unsigned int) k->nonce[i]);
for ( i = 0;i < LNONCE;++i) printf("%02x",(unsigned int) k->nonce[i]);
printf("\n");
printf("encrypted: ");
for ( i = 0;i < 80;++i) printf("%02x",(unsigned int) k->encrypted[i]);
for ( i = 0;i < LSEC;++i) printf("%02x",(unsigned int) k->encrypted[i]);
printf("\n");
printf(" owner: %s\n", k->owner);
@@ -518,19 +495,19 @@ void pcp_dumpkey(pcp_key_t *k) {
void pcp_dumppubkey(pcp_pubkey_t *k) {
int i;
unsigned int i;
printf("Dumping pcp_pubkey_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->masterpub[i]);
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->masterpub[i]);
printf("\n");
printf(" public: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->pub[i]);
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->pub[i]);
printf("\n");
printf(" edpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->edpub[i]);
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->edpub[i]);
printf("\n");
printf(" owner: %s\n", k->owner);
@@ -547,3 +524,38 @@ void pcp_dumppubkey(pcp_pubkey_t *k) {
printf(" type: 0x%02X\n", k->type);
}
/*
via
http://rosettacode.org/wiki/Entropy#C
*/
double pcp_getentropy(char *source) {
int len;
int *hist;
double H;
int wherechar[256];
int i,histlen;
histlen = 0;
H = 0;
len = (int)strlen(source);
hist = (int*)calloc(len, sizeof(int));
for(i=0; i<256; i++)
wherechar[i] = -1;
for(i=0; i<len; i++){
if(wherechar[(int)source[i]] == -1) {
wherechar[(int)source[i]] = histlen;
histlen++;
}
hist[wherechar[(int)source[i]]]++;
}
for(i=0; i<histlen; i++) {
H -= (double)hist[i] / len * log2((double)hist[i] / len);
}
return H;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -22,39 +22,21 @@
#include "keysig.h"
pcp_keysig_t * keysig2be(pcp_keysig_t *s) {
#ifdef __CPU_IS_BIG_ENDIAN
return s;
#else
uint32_t size = s->size;
byte* p = (byte*)&size;
if(p[0] != 0) {
s->size = htobe32(s->size);
}
return s;
#endif
}
pcp_keysig_t *keysig2native(pcp_keysig_t *s) {
#ifdef __CPU_IS_BIG_ENDIAN
return s;
#else
s->size = be32toh(s->size);
return s;
#endif
}
Buffer *pcp_keysig2blob(pcp_keysig_t *s) {
Buffer *b = buffer_new(256, "keysig2blob");
void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s) {
buffer_add8(b, s->type);
buffer_add32be(b, s->size);
buffer_add(b, s->id, 17);
buffer_add(b, s->checksum, 32);
buffer_add(b, s->checksum, LSHA);
buffer_add(b, s->blob, s->size);
}
Buffer *pcp_keysigblob(pcp_keysig_t *s) {
Buffer *b = buffer_new(256, "keysig2blob");
pcp_keysig2blob(b, s);
return b;
}
pcp_keysig_t *pcp_keysig_new(Buffer *blob) {
pcp_keysig_t *pcp_blob2keysig(Buffer *blob) {
pcp_keysig_t *sk = ucmalloc(sizeof(pcp_keysig_t));
uint8_t type = buffer_get8(blob);
@@ -62,17 +44,17 @@ pcp_keysig_t *pcp_keysig_new(Buffer *blob) {
buffer_get_chunk(blob, sk->id, 17);
byte *checksum = ucmalloc(32);
buffer_get_chunk(blob, checksum, 32);
byte *checksum = ucmalloc(LSHA);
buffer_get_chunk(blob, checksum, LSHA);
sk->blob = ucmalloc(size);
buffer_get_chunk(blob, sk->blob, size);
sk->size = size;
sk->type = type;
memcpy(sk->checksum, checksum, 32);
memcpy(sk->checksum, checksum, LSHA);
ucfree(checksum, 32);
ucfree(checksum, LSHA);
return sk;
}
@@ -86,7 +68,7 @@ void pcp_dumpkeysig(pcp_keysig_t *s) {
printf(" size: %ld\n", (long int)s->size);
printf(" checksum: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) s->checksum[i]);
for ( i = 0;i < LSHA;++i) printf("%02x",(unsigned int) s->checksum[i]);
printf("\n");
_dump(" blob:", s->blob, s->size);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -83,7 +83,7 @@ void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
byte *value = realloc (d, newlen);
if (value == NULL) {
err(errno, "Cannot reallocate %ld bytes of memory", newlen);
err(errno, "Cannot reallocate %"FMT_SIZE_T" bytes of memory", (SIZE_T_CAST)newlen);
exit(-1);
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -25,9 +25,9 @@
int _get_pk(Buffer *blob, pcp_pubkey_t *p) {
if(buffer_left(blob) >= 96) {
buffer_get_chunk(blob, p->masterpub, 32);
buffer_get_chunk(blob, p->edpub, 32);
buffer_get_chunk(blob, p->pub, 32);
buffer_get_chunk(blob, p->masterpub, LEDPUB);
buffer_get_chunk(blob, p->edpub, LEDPUB);
buffer_get_chunk(blob, p->pub, LBOXPUB);
return 0;
}
else
@@ -36,20 +36,23 @@ int _get_pk(Buffer *blob, pcp_pubkey_t *p) {
int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h) {
if(buffer_left(blob) >= sizeof(rfc_pub_sig_h)) {
buffer_get_chunk(blob, h, sizeof(rfc_pub_sig_h));
buffer_get_chunk(blob, h, sizeof(rfc_pub_sig_h)); /* FIXME: blog 2 struct? thafck */
h->numsubs = be16toh(h->numsubs);
h->numsubs = _wireto16((byte *)&h->numsubs);
if(h->version != EXP_SIG_VERSION) {
fatal(ptx, "Unsupported pubkey signature version %d, expected %d\n", h->version, EXP_SIG_VERSION);
fatal(ptx, "Unsupported pubkey signature version %d, expected %d\n",
h->version, EXP_SIG_VERSION);
return 1;
}
if(h->type != EXP_SIG_TYPE) {
fatal(ptx, "Unsupported pubkey signature type %d, expected %d\n", h->type, EXP_SIG_TYPE);
fatal(ptx, "Unsupported pubkey signature type %d, expected %d\n",
h->type, EXP_SIG_TYPE);
return 1;
}
if(h->pkcipher != EXP_SIG_CIPHER) {
fatal(ptx, "Unsupported pubkey signature cipher %d, expected %d\n", h->pkcipher, EXP_SIG_CIPHER);
fatal(ptx, "Unsupported pubkey signature cipher %d, expected %d\n",
h->pkcipher, EXP_SIG_CIPHER);
return 1;
}
if(h->hashcipher != EXP_HASH_CIPHER) {
@@ -58,7 +61,7 @@ int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h) {
}
if(h->numsubs > 0 && buffer_left(blob) < sizeof(rfc_pub_sig_s) * h->numsubs) {
fatal(ptx, "Signature size specification invalid (sig: %ld, bytes left: %ld, numsubs: %ld\n",
sizeof(rfc_pub_sig_s) * h->numsubs, buffer_left(blob), h->numsubs);
sizeof(rfc_pub_sig_s) * h->numsubs, buffer_left(blob), h->numsubs);
return 1;
}
return 0;
@@ -104,14 +107,14 @@ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *su
if(strncmp(notation, "owner", 5) == 0) {
if(buffer_get_chunk(blob, p->owner, vsize) == 0) {
fatal(ptx, "Invalid 'owner' notation, expected %ld bytes, but got 0\n", vsize);
goto sgcerr;
fatal(ptx, "Invalid 'owner' notation, expected %ld bytes, but got 0\n", vsize);
goto sgcerr;
}
}
else if(strncmp(notation, "mail", 4) == 0) {
if(buffer_get_chunk(blob, p->mail, vsize) == 0) {
fatal(ptx, "Invalid 'mail' notation, expected %ld bytes, but got 0\n", vsize);
goto sgcerr;
fatal(ptx, "Invalid 'mail' notation, expected %ld bytes, but got 0\n", vsize);
goto sgcerr;
}
}
else if(strncmp(notation, "serial", 6) == 0) {
@@ -178,7 +181,7 @@ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
/* compare them */
if(memcmp(hash, verifyhash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(hash, verifyhash, crypto_generichash_BYTES_MAX) != 0) {
fatal(ptx, "Signature verifies but signed hash doesn't match signature contents\n");
goto chker2;
}
@@ -381,23 +384,31 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
}
b = ucmalloc(sizeof(pbp_pubkey_t)); /* FIXME: separate type really needed? */
buffer_get_chunk(blob, b->sigpub, crypto_sign_PUBLICKEYBYTES);
buffer_get_chunk(blob, b->masterpub, crypto_sign_PUBLICKEYBYTES);
buffer_get_chunk(blob, b->edpub, crypto_sign_PUBLICKEYBYTES);
buffer_get_chunk(blob, b->pub, crypto_box_PUBLICKEYBYTES);
buffer_get_chunk(blob, date, 18);
date[19] = '\0';
struct tm c;
if(strptime(date, "%Y-%m-%dT%H:%M:%S", &c) == NULL) {
c.tm_isdst = -1;
int tmok = sscanf(date, "%4d-%2d-%2dT%2d:%2d:%2d",
&c.tm_year, &c.tm_mon, &c.tm_mday, &c.tm_hour, &c.tm_min, &c.tm_sec);
if(tmok <= 0 || c.tm_hour >= 24 || c.tm_mon >= 59 || c.tm_sec >= 59) {
/* check returned tm values, which will look like this when input
was no string: 30867--12305-0 4229688:8:21790784
or: sscanf failed altogether.
*/
fatal(ptx, "Failed to parse creation time in PBP public key file\n");
free(date);
ucfree(b, sizeof(pbp_pubkey_t));
goto errimp2;
}
buffer_fwd_offset(blob, 46);
memcpy(b->name, buffer_get(blob), buffer_left(blob));
c.tm_mon -= 1;
c.tm_year -= 1900;
/* parse the name */
parts = strtok (b->name, "<>");
pnum = 0;
@@ -427,9 +438,9 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) {
_lc(pub->owner);
ucfree(b, sizeof(pbp_pubkey_t));
/* edpub used for signing, might differ */
/* masterpub used for signing, might differ */
tmp = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(tmp->edpub, b->sigpub, crypto_sign_PUBLICKEYBYTES);
memcpy(tmp->masterpub, b->masterpub, crypto_sign_PUBLICKEYBYTES);
byte *verify = pcp_ed_verify(ptx, buffer_get(blob), buffer_size(blob), tmp);
free(tmp);
@@ -473,9 +484,9 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
Buffer *sig = buffer_new(320, "pbsig01");
/* add raw key material */
buffer_add(sig, sk->edpub, crypto_sign_PUBLICKEYBYTES);
buffer_add(sig, sk->edpub, crypto_sign_PUBLICKEYBYTES);
buffer_add(sig, sk->pub, crypto_box_PUBLICKEYBYTES);
buffer_add(sig, sk->edpub, LEDPUB);
buffer_add(sig, sk->masterpub, LEDPUB);
buffer_add(sig, sk->pub, LBOXPUB);
/* add creatioin and expire time as 32byte iso time string */
time_t t = (time_t)sk->ctime;
@@ -484,10 +495,10 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
v = localtime(&vt);
date = ucmalloc(65);
sprintf(date, "%04d-%02d-%02dT%02d:%02d:%02d.000000 %04d-%02d-%02dT%02d:%02d:%02d.000000 ",
c->tm_year+1900-1, c->tm_mon+1, c->tm_mday, // wtf? why -1?
c->tm_hour, c->tm_min, c->tm_sec,
v->tm_year+1900-1, v->tm_mon+1, v->tm_mday,
v->tm_hour, v->tm_min, v->tm_sec);
c->tm_year+1900-1, c->tm_mon+1, c->tm_mday, // wtf? why -1?
c->tm_hour, c->tm_min, c->tm_sec,
v->tm_year+1900-1, v->tm_mon+1, v->tm_mday,
v->tm_hour, v->tm_min, v->tm_sec);
buffer_add(sig, date, 64);
/* add owner */
@@ -504,7 +515,6 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
free(date);
buffer_free(sig);
free(v);
return out;
@@ -512,7 +522,7 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
buffer_free(sig);
buffer_free(out);
free(date);
free(v);
return NULL;
}
@@ -527,9 +537,9 @@ Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk) {
buffer_add8(out, EXP_PK_CIPHER);
/* add the keys */
buffer_add(raw, sk->masterpub, 32);
buffer_add(raw, sk->edpub, 32);
buffer_add(raw, sk->pub, 32);
buffer_add(raw, sk->masterpub, LEDPUB);
buffer_add(raw, sk->edpub, LEDPUB);
buffer_add(raw, sk->pub, LBOXPUB);
/* add the sig header */
buffer_add8(raw, EXP_SIG_VERSION);
@@ -625,7 +635,7 @@ Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk) {
Buffer *jout = pcp_export_json_pub(ptx, sk, jsig, siglen);
buffer_free(out);
ucfree(jsig, siglen);
out = jout;
}
#endif
@@ -636,6 +646,7 @@ Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk) {
free(hash);
memset(sig, 0, crypto_sign_BYTES + crypto_generichash_BYTES_MAX);
free(sig);
free(st);
if(out->end < 32)
fatal(ptx, "failed to export public key");
@@ -652,13 +663,13 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase) {
Buffer *raw = buffer_new(512, "secretbuf");
Buffer *out = buffer_new(512, "secretcipherblob");
buffer_add(raw, sk->mastersecret, 64);
buffer_add(raw, sk->secret, 32);
buffer_add(raw, sk->edsecret, 64);
buffer_add(raw, sk->mastersecret, LEDSEC);
buffer_add(raw, sk->secret, LBOXSEC);
buffer_add(raw, sk->edsecret, LEDSEC);
buffer_add(raw, sk->masterpub, 32);
buffer_add(raw, sk->pub, 32);
buffer_add(raw, sk->edpub, 32);
buffer_add(raw, sk->masterpub, LEDPUB);
buffer_add(raw, sk->pub, LBOXPUB);
buffer_add(raw, sk->edpub, LEDPUB);
if(strlen(sk->owner) > 0) {
buffer_add16be(raw, strlen(sk->owner));
@@ -678,9 +689,9 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase) {
buffer_add32be(raw, sk->version);
buffer_add32be(raw, sk->serial);
nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
nonce = ucmalloc(LNONCE);
arc4random_buf(nonce, LNONCE);
symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), nonce, LNONCE);
es = pcp_sodium_mac(&cipher, buffer_get(raw), buffer_size(raw), nonce, symkey);
@@ -693,7 +704,7 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase) {
else {
#endif
buffer_add(out, nonce, crypto_secretbox_NONCEBYTES);
buffer_add(out, nonce, LNONCE);
buffer_add(out, cipher, es);
#ifdef HAVE_JSON
@@ -701,7 +712,7 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase) {
#endif
buffer_free(raw);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(nonce, LNONCE);
sfree(symkey);
ucfree(cipher, es);
@@ -752,11 +763,11 @@ pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passp
pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase) {
pcp_key_t *sk = ucmalloc(sizeof(pcp_key_t));
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
byte *nonce = ucmalloc(LNONCE);
byte *symkey = NULL;
byte *clear = NULL;
size_t cipherlen = 0;
size_t minlen = (64 * 2) + (32 * 4) + 8 + 4 + 4; /* key material and mandatory field sizes */
size_t minlen = (LEDSEC * 2) + (LBOXPUB * 2) + (LEDPUB * 2) + 8 + 4 + 4; /* key material and mandatory field sizes */
uint16_t notationlen = 0;
Buffer *blob = buffer_new(512, "secretdecryptbuf");
@@ -771,42 +782,44 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
}
#endif
if(buffer_get_chunk(cipher, nonce, crypto_secretbox_NONCEBYTES) == 0)
if(buffer_get_chunk(cipher, nonce, LNONCE) == 0)
goto impserr1;
symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), nonce, LNONCE);
cipherlen = buffer_left(cipher);
if(cipherlen < minlen) {
fatal(ptx, "failed to decrypt the secret key file:\n"
"expected encrypted secret key size %ld is less than minimum len %ld\n",
cipherlen, minlen);
"expected encrypted secret key size %ld is less than minimum len %ld\n",
cipherlen, minlen);
goto impserr1;
}
/* decrypt the blob */
clear = ucmalloc(cipherlen - LMAC);
if(pcp_sodium_verify_mac(&clear, buffer_get_remainder(cipher),
cipherlen, nonce, symkey) != 0) {
cipherlen, nonce, symkey) != 0) {
fatal(ptx, "failed to decrypt the secret key file\n");
goto impserr1;
goto impserr2;
}
/* prepare the extraction buffer */
buffer_add(blob, clear, cipherlen - PCP_CRYPTO_ADD);
buffer_add(blob, clear, cipherlen - LMAC);
/* extract the raw data into the structure */
buffer_get_chunk(blob, sk->mastersecret, 64);
buffer_get_chunk(blob, sk->secret, 32);
buffer_get_chunk(blob, sk->edsecret, 64);
buffer_get_chunk(blob, sk->mastersecret, LEDSEC);
buffer_get_chunk(blob, sk->secret, LBOXSEC);
buffer_get_chunk(blob, sk->edsecret, LEDSEC);
buffer_get_chunk(blob, sk->masterpub, 32);
buffer_get_chunk(blob, sk->pub, 32);
buffer_get_chunk(blob, sk->edpub, 32);
buffer_get_chunk(blob, sk->masterpub, LEDPUB);
buffer_get_chunk(blob, sk->pub, LBOXPUB);
buffer_get_chunk(blob, sk->edpub, LEDPUB);
notationlen = buffer_get16na(blob);
if(notationlen > 255) {
fatal(ptx, "Invalid notation value size for owner\n");
fatal(ptx, "Invalid notation value size for owner (got: %ld, expected: 255)\n",
notationlen);
goto impserr2;
}
else if(notationlen > 0)
@@ -814,7 +827,8 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
notationlen = buffer_get16na(blob);
if(notationlen > 255) {
fatal(ptx, "Invalid notation value size for mail\n");
fatal(ptx, "Invalid notation value size for mail (got: %ld, expected: 255)\n",
notationlen);
goto impserr2;
}
else if(notationlen > 0)
@@ -834,8 +848,8 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
sk->type = PCP_KEY_TYPE_SECRET;
/* ready */
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(clear, cipherlen - LMAC);
ucfree(nonce, LNONCE);
buffer_free(blob);
sfree(symkey);
free(id);
@@ -843,16 +857,14 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
return sk;
impserr2:
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
ucfree(clear, cipherlen - LMAC);
impserr1:
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(nonce, LNONCE);
ucfree(sk, sizeof(pcp_key_t));
buffer_free(blob);
if(symkey != NULL)
sfree(symkey);
if(clear != NULL)
free(clear);
return NULL;
}
@@ -874,9 +886,9 @@ json_t *pcp_pk2json(pcp_pubkey_t *pk) {
pcp_key_t *sk = malloc(sizeof(pcp_key_t));
memcpy(sk->masterpub, pk->masterpub, 32);
memcpy(sk->pub, pk->pub, 32);
memcpy(sk->edpub, pk->edpub, 32);
memcpy(sk->masterpub, pk->masterpub, LEDPUB);
memcpy(sk->pub, pk->pub, LBOXPUB);
memcpy(sk->edpub, pk->edpub, LEDPUB);
memcpy(sk->owner, pk->owner, 255);
memcpy(sk->mail, pk->mail, 255);
memcpy(sk->id, pk->id, 17);
@@ -895,11 +907,11 @@ json_t *pcp_sk2json(pcp_key_t *sk, byte *sig, size_t siglen) {
json_t *jout;
char *cryptpub, *sigpub, *masterpub, *ssig;
char *jformat = "{sssssssisisisissssssssssss}";
char *jformat = "{sssssssIsIsIsIssssssssssss}";
cryptpub = _bin2hex(sk->pub, 32);
sigpub = _bin2hex(sk->edpub, 32);
masterpub= _bin2hex(sk->masterpub, 32);
cryptpub = _bin2hex(sk->pub, LBOXPUB);
sigpub = _bin2hex(sk->edpub, LEDPUB);
masterpub= _bin2hex(sk->masterpub, LEDPUB);
if(sig != NULL) {
ssig = _bin2hex(sig, siglen);
@@ -907,24 +919,24 @@ json_t *pcp_sk2json(pcp_key_t *sk, byte *sig, size_t siglen) {
else {
ssig = malloc(1);
ssig[0] = '\0';
jformat = "{sssssssisisisissssssssss}";
jformat = "{sssssssIsIsIsIssssssssss}";
}
jout = json_pack(jformat,
"id", sk->id,
"owner", sk->owner,
"mail", sk->mail,
"ctime", (int)sk->ctime,
"expire", (int)sk->ctime+31536000,
"version", (int)sk->version,
"serial", (int)sk->serial,
"type", "public",
"cipher", EXP_PK_CIPHER_NAME,
"cryptpub", cryptpub,
"sigpub", sigpub,
"masterpub", masterpub,
"signature", ssig
);
"id" , sk->id,
"owner" , sk->owner,
"mail" , sk->mail,
"ctime" , (json_int_t)sk->ctime,
"expire" , (json_int_t)sk->ctime+31536000,
"version" , (json_int_t)sk->version,
"serial" , (json_int_t)sk->serial,
"type" , "public",
"cipher" , EXP_PK_CIPHER_NAME,
"cryptpub" , cryptpub,
"sigpub" , sigpub,
"masterpub" , masterpub,
"signature" , ssig
);
free(cryptpub);
free(sigpub);
@@ -946,14 +958,13 @@ Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *ci
jout = pcp_sk2json(sk, NULL, 0);
xcipher = _bin2hex(cipher, clen);
xnonce = _bin2hex(nonce, crypto_secretbox_NONCEBYTES);
xnonce = _bin2hex(nonce, LNONCE);
json_object_set(jout, "type", json_string("secret"));
json_object_set(jout, "secrets", json_string(xcipher));
json_object_set(jout, "nonce", json_string(xnonce));
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
if(jdump != NULL) {
buffer_add(b, jdump, strlen(jdump));
free(jdump);
@@ -979,7 +990,7 @@ Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
if(jdump != NULL) {
buffer_add_str(b, jdump);
buffer_add(b, jdump, strlen(jdump));
free(jdump);
}
else {
@@ -1070,8 +1081,8 @@ pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize) {
jtmp = json_object_get(jin, "cryptpub");
if(jtmp == NULL)
goto jerr2;
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32)
memcpy(p->pub, blob, 32);
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == LBOXPUB)
memcpy(p->pub, blob, LBOXPUB);
else {
strcpy(jerror.text, hexerr);
goto jerr2;
@@ -1080,8 +1091,8 @@ pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize) {
jtmp = json_object_get(jin, "sigpub");
if(jtmp == NULL)
goto jerr2;
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32)
memcpy(p->edpub, blob, 32);
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == LEDPUB)
memcpy(p->edpub, blob, LEDPUB);
else {
strcpy(jerror.text, hexerr);
goto jerr2;
@@ -1090,8 +1101,8 @@ pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize) {
jtmp = json_object_get(jin, "masterpub");
if(jtmp == NULL)
goto jerr2;
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32)
memcpy(p->masterpub, blob, 32);
if(_hex2bin(json_string_value(jtmp), blob, maxblob) == LEDPUB)
memcpy(p->masterpub, blob, LEDPUB);
else {
strcpy(jerror.text, hexerr);
goto jerr2;

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -103,18 +103,18 @@ void ps_rewind(Pcpstream *stream, void *buf, size_t bufsize) {
size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
size_t gotbytes = 0;
size_t idx = 0;
if(buffer_left(stream->save) > 0) {
/* something left from last rewind, first use this */
if(buffer_left(stream->save) >= readbytes) {
gotbytes = buffer_get_chunk(stream->save, buf, readbytes);
if(buffer_left(stream->save) == 0)
buffer_clear(stream->save);
buffer_clear(stream->save);
goto rawdone;
}
else {
/* fetch the remainder of the save buffer, remember how much
to fetch from source next */
to fetch from source next */
idx = buffer_get_chunk(stream->save, buf, buffer_left(stream->save));
buffer_clear(stream->save);
readbytes -= idx;
@@ -137,6 +137,7 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
}
else {
size_t got = fread(buf+idx, 1, readbytes, stream->fd);
gotbytes += got;
if(feof(stream->fd) != 0)
stream->eof = 1;
@@ -146,7 +147,8 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
rawdone:
//_dump("ps_read_raw", buf, gotbytes);
//_dump(" ps_read_raw first byte:", buf, 1);
//fprintf(stderr, " ps_read_raw, gotbytes: %ld\n", gotbytes);
return gotbytes;
}
@@ -157,10 +159,10 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
/*
fprintf(stderr, "%ld <= %ld && %ld <= %ld\n",
readbytes, buffer_left(stream->cache), readbytes, stream->blocksize) ;
readbytes, buffer_left(stream->cache), readbytes, stream->blocksize) ;
fprintf(stderr, "%d == 1 && %ld >= %ld\n",
ps_end(stream), readbytes, buffer_left(stream->cache));
ps_end(stream), readbytes, buffer_left(stream->cache));
*/
if(readbytes <= buffer_left(stream->cache) && readbytes <= stream->blocksize) {
/* enough left in current cache */
@@ -173,7 +175,8 @@ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
}
else {
// fprintf(stderr, " fetch next\n");
/* request for chunk larger than what we've got in the cache */
/* request for chunk larger than what we've got in the cache */
// FIXME: use static buffer !
Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadchunktmp");
if( buffer_left(stream->cache) > 0) {
@@ -191,35 +194,35 @@ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
/* not enough cached, fetch the next chunk */
// fprintf(stderr, " fetch next read_next\n");
if(ps_read_next(stream) == 0)
break;
break;
// fprintf(stderr, " fetch next read_continue\n");
/* need to fetch more? */
left = readbytes - (buffer_size(tmp) + buffer_size(stream->next));
if(left < 0) {
/* no more to fetch, in fact there's more than we need */
/* determine overlapping bytes */
size_t overlap = readbytes - buffer_size(tmp);
/* no more to fetch, in fact there's more than we need */
/* determine overlapping bytes */
size_t overlap = readbytes - buffer_size(tmp);
/* avoid overflow */
if(overlap > buffer_size(stream->next))
overlap = buffer_size(stream->next);
/* avoid overflow */
if(overlap > buffer_size(stream->next))
overlap = buffer_size(stream->next);
/* add the overlap from next to tmp */
buffer_get_chunk_tobuf(stream->next, tmp, overlap);
/* add the overlap from next to tmp */
buffer_get_chunk_tobuf(stream->next, tmp, overlap);
/* move the rest of stream->next into cache */
buffer_clear(stream->cache);
buffer_get_chunk_tobuf(stream->next, stream->cache, buffer_left(stream->next));
buffer_clear(stream->next);
/* move the rest of stream->next into cache */
buffer_clear(stream->cache);
buffer_get_chunk_tobuf(stream->next, stream->cache, buffer_left(stream->next));
buffer_clear(stream->next);
}
else {
/* we've got precisely what we need, no need to calculate any overlap
OR there's more to fetch, we don't have enough stuff yet,
put next into tmp, reset next and loop again - same behavior */
buffer_add_buf(tmp, stream->next);
buffer_clear(stream->next);
/* we've got precisely what we need, no need to calculate any overlap
OR there's more to fetch, we don't have enough stuff yet,
put next into tmp, reset next and loop again - same behavior */
buffer_add_buf(tmp, stream->next);
buffer_clear(stream->next);
}
}
@@ -257,6 +260,7 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
size_t got = 0;
if(stream->cache == NULL) {
got = ps_read_raw(stream, buf, readbytes);
// fprintf(stderr, "%ld = ps_read_raw(stream, buf, readbytes); // no cache\n", got);
}
else if(buffer_size(stream->cache) > 0) {
/* use cache */
@@ -274,26 +278,27 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
}
else if(stream->armor == 1) {
/* z85 encoding has already been determined, therefore the cache
is now filled, use it then */
is now filled, use it then */
got = ps_read_cached(stream, buf, readbytes);
// fprintf(stderr, "%ld = ps_read_cached(stream, buf, readbytes);\n", got);
}
else {
/* read directly from source */
got = ps_read_raw(stream, buf, readbytes);
// fprintf(stderr, "%ld = ps_read_raw(stream, buf, readbytes);\n", got);
}
}
stream->pos += got;
// fprintf(stderr, " ps_read(): %ld\n", got);
//fprintf(stderr, " ps_read(): %ld\n", got);
return got;
}
int ps_readline(Pcpstream *stream, Buffer *line) {
int c = -1, max = 1;
byte b[1];
while(c<PSMAXLINE) {
while(c<PSMAXLINE) { // && ps_end(stream) != 1
//fprintf(stderr, " ps_readline: call raw\n");
if(ps_read_raw(stream, b, 1) < 1) {
//fprintf(stderr, " ps_readline: raw returned < 1\n");
@@ -304,7 +309,7 @@ int ps_readline(Pcpstream *stream, Buffer *line) {
//fprintf(stderr, " ps_readline: raw found CR\n");
continue;
}
else if(*b == '\n' || ps_end(stream) == 1) {
else if(*b == '\n') {
//fprintf(stderr, " ps_readline: raw found NL\n");
c++;
max = 0;
@@ -326,7 +331,8 @@ int ps_readline(Pcpstream *stream, Buffer *line) {
return -1;
}
// fprintf(stderr, " ps_readline: raw return %d\n", c);
//fprintf(stderr, " ps_readline: raw return %d, last b: <%c>\n", c, b[0]);
//buffer_info(line);
return c;
}
@@ -389,61 +395,63 @@ size_t ps_read_decode(Pcpstream *stream) {
while(buffer_size(z) < stream->blocksize) {
buffer_clear(line);
if(ps_readline(stream, line) >= 0) {
//fprintf(stderr, "got: <%s>\n", buffer_get_str(line));
if(z85_isbegin(line) && stream->have_begin == 0) {
/* begin header encountered */
stream->have_begin = 1; /* otherwise ignore it */
continue;
}
else if(z85_isend(line)) {
/* end header encountered */
break;
}
else if(z85_isempty(line)) {
/* ignore empty lines */
continue;
}
else {
/* regular z85 encoded content */
// fprintf(stderr, "regular\n");
// fprintf(stderr, " %ld + %ld > %ld\n", buffer_size(z), buffer_size(line), stream->blocksize);
if(buffer_size(z) + buffer_size(line) > stream->blocksize) {
/* we've got more than needed.
put what we need into z and the remainder
into the save buffer for further reading. */
/* fprintf(stderr, "overflow %ld + %ld > %ld\n",
buffer_size(z), buffer_size(line), stream->blocksize);
*/
buffer_get_chunk_tobuf(line, z, stream->blocksize - buffer_size(z));
buffer_get_chunk_tobuf(line, stream->save, buffer_left(line));
if(!ps_left(stream)) {
/* only add the newline if there's no more to follow */
buffer_add8(stream->save, '\n');
}
break;
}
else {
/* not enough yet, store it and go on */
buffer_add_buf(z, line);
}
}
//fprintf(stderr, "got: <%s>\n", buffer_get_str(line));
if(z85_isbegin(line) && stream->have_begin == 0) {
/* begin header encountered */
stream->have_begin = 1; /* otherwise ignore it */
continue;
}
else if(z85_isend(line)) {
/* end header encountered */
break;
}
else if(z85_isempty(line)) {
/* ignore empty lines */
continue;
}
else {
/* regular z85 encoded content */
// fprintf(stderr, "regular\n");
// fprintf(stderr, " %ld + %ld > %ld\n", buffer_size(z), buffer_size(line), stream->blocksize);
if(buffer_size(z) + buffer_size(line) > stream->blocksize) {
/* we've got more than needed.
put what we need into z and the remainder
into the save buffer for further reading. */
/* fprintf(stderr, "overflow %ld + %ld > %ld\n",
buffer_size(z), buffer_size(line), stream->blocksize);
*/
buffer_get_chunk_tobuf(line, z, stream->blocksize - buffer_size(z));
buffer_get_chunk_tobuf(line, stream->save, buffer_left(line));
if(!ps_left(stream)) {
/* only add the newline if there's no more to follow */
buffer_add8(stream->save, '\n');
}
break;
}
else {
/* not enough yet, store it and go on */
buffer_add_buf(z, line);
}
}
}
else {
// fprintf(stderr, " ps_read_next readline returned 0\n");
/* eof or err */
break;
// fprintf(stderr, " ps_read_next readline returned 0\n");
/* eof or err */
break;
}
}
}
//fprintf(stderr, "%s\n", buffer_get_str(z));
//buffer_info(z);
//buffer_dump(z);
//fprintf(stderr, "\n%s\n", buffer_get_str(z));
/* finally, decode it and put into next */
size_t binlen, outlen;
byte *bin = pcp_z85_decode(ptx, buffer_get_str(z), &binlen);
//fprintf(stderr, "ps_read_decode decoding z: %ld, got: %ld\n", buffer_size(z), binlen);
//_dump("bin", bin, binlen);
//fatals_ifany();
fatals_ifany(ptx);
if(bin == NULL) {
/* it's not z85 encoded, so threat it as binary */
@@ -495,15 +503,15 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
buffer_add_buf(tmp, stream->cache);
while (buffer_left(tmp) > stream->blocksize) {
/* iterate over tmp blockwise, encode each block, write it out until there's a rest */
buffer_clear(stream->cache);
buffer_get_chunk_tobuf(tmp, stream->cache, stream->blocksize);
ps_write_encode(stream, z);
/* iterate over tmp blockwise, encode each block, write it out until there's a rest */
buffer_clear(stream->cache);
buffer_get_chunk_tobuf(tmp, stream->cache, stream->blocksize);
ps_write_encode(stream, z);
}
/* now, z contains a couple of z85 encoded blocks, tmp contains the
remainder of the write buffer, store the rest in the cache and
go on as nothing did happen */
remainder of the write buffer, store the rest in the cache and
go on as nothing did happen */
buffer_clear(stream->cache);
buffer_add(stream->cache, buffer_get_remainder(tmp), buffer_left(tmp));
buffer_free(tmp);
@@ -515,14 +523,14 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
void *aside = NULL;
size_t overlap = (buffer_size(stream->cache) + writebytes) - stream->blocksize;
if(overlap > 0) {
/* yes, store the overlap, put the left part into the cache */
aside = ucmalloc(overlap);
memcpy(aside, buf + (writebytes - overlap), overlap); /* FIXME: check if this works */
buffer_add(stream->cache, buf, writebytes - overlap);
/* yes, store the overlap, put the left part into the cache */
aside = ucmalloc(overlap);
memcpy(aside, buf + (writebytes - overlap), overlap); /* FIXME: check if this works */
buffer_add(stream->cache, buf, writebytes - overlap);
}
else {
/* cache+buf == blocksize */
buffer_add(stream->cache, buf, writebytes);
/* cache+buf == blocksize */
buffer_add(stream->cache, buf, writebytes);
}
/* encode the cache into z */
@@ -530,10 +538,10 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
buffer_clear(stream->cache);
if(aside != NULL) {
/* there is an overlapping rest, put it into the cache
the caller needs to call ps_finish() to put it out */
buffer_add(stream->cache, aside, overlap);
free(aside);
/* there is an overlapping rest, put it into the cache
the caller needs to call ps_finish() to put it out */
buffer_add(stream->cache, aside, overlap);
free(aside);
}
}
}
@@ -637,7 +645,7 @@ void ps_close(Pcpstream *stream) {
if(stream->cache != NULL) {
if(stream->is_output == 1) {
if(buffer_left(stream->cache) != 0)
buffer_info(stream->cache);
buffer_info(stream->cache);
assert(buffer_left(stream->cache) == 0); /* there's something left in the cache, call ps_finish() */
}
buffer_free(stream->cache);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -32,6 +32,12 @@ void err(int eval, const char *fmt, ...) {
}
fprintf(stderr, ": %s\n", strerror(errno));
va_end(ap);
/* from the FreeBSD err() manpage:
The err(), verr(), errc(), verrc(), errx(), and verrx() functions do not
return, but exit with the value of the argument eval.
*/
exit(eval);
}
#endif
@@ -48,9 +54,9 @@ int vasprintf(char **ret, const char *format, va_list args) {
if (buffer != NULL) {
count = vsnprintf(buffer, count + 1, format, copy);
if (count < 0)
free(buffer);
free(buffer);
else
*ret = buffer;
*ret = buffer;
}
}
va_end(copy); /* Each va_start() or va_copy() needs a va_end() */
@@ -86,11 +92,11 @@ strnstr(const char *s, const char *find, size_t slen)
len = strlen(find);
do {
do {
if (slen-- < 1 || (sc = *s++) == '\0')
return (NULL);
if (slen-- < 1 || (sc = *s++) == '\0')
return (NULL);
} while (sc != c);
if (len > slen)
return (NULL);
return (NULL);
} while (strncmp(s, find, len) != 0);
s--;
}

278
libpcp/readpass.c Normal file
View File

@@ -0,0 +1,278 @@
/*-
* Copyright 2009 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Modifications (c) 2013 - 2015 by T.v.Dein, same license as this file.
*/
#include "readpass.h"
/**
* tarsnap_getpass(passwd, prompt, confirmprompt, devtty)
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
* not, read from stdin. If reading from a tty (either /dev/tty or stdin),
* disable echo and prompt the user by printing ${prompt} to stderr. If
* ${confirmprompt} is non-NULL, read a second password (prompting if a
* terminal is being used) and repeat until the user enters the same password
* twice. Return the password as a malloced NUL-terminated string via
* ${passwd}. The obscure name is to avoid namespace collisions due to the
* getpass / readpass / readpassphrase / etc. functions in various libraries.
*/
int
pcp_readpass(PCPCTX *ptx, char ** passwd, const char * prompt,
const char * confirmprompt, int devtty, char *readfromfile)
{
FILE * readfrom;
char passbuf[MAXPASSLEN];
char confpassbuf[MAXPASSLEN];
struct termios term, term_old;
int usingtty;
/*
* If devtty != 0, try to open /dev/tty; if that fails, or if devtty
* is zero, we'll read the password from stdin instead.
*
* Added by tlinden: however, if readfromfile is defined, we'll
* read the password from there, but if it is '-' we'll use stdin
* as well.
*/
if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) {
if(readfromfile != NULL) {
// FIXME: check if readfromfile is executable,
// if yes, call askextpass(tobewritten) and
// read from the returned fd somehow
if(readfromfile[0] == '-') {
readfrom = stdin;
}
else {
if((readfrom = fopen(readfromfile, "r")) == NULL) {
fatal(ptx, "Could not open password file '%s'\n", readfromfile);
goto err1;
}
}
}
else {
readfrom = stdin;
}
}
/* If we're reading from a terminal, try to disable echo. */
if ((usingtty = isatty(fileno(readfrom))) != 0) {
if (tcgetattr(fileno(readfrom), &term_old)) {
fatal(ptx, "Cannot read terminal settings\n");
goto err1;
}
memcpy(&term, &term_old, sizeof(struct termios));
term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
fatal(ptx, "Cannot set terminal settings\n");
goto err1;
}
}
retry:
/* If we have a terminal, prompt the user to enter the password. */
if (usingtty)
fprintf(stderr, "%s: ", prompt);
/* Read the password. */
if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
fatal(ptx, "Cannot read password\n");
goto err2;
}
/* Confirm the password if necessary. */
if (confirmprompt != NULL) {
if (usingtty)
fprintf(stderr, "%s: ", confirmprompt);
if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
fatal(ptx, "Cannot read password\n");
goto err2;
}
if (strcmp(passbuf, confpassbuf)) {
fprintf(stderr,
"Passwords mismatch, please try again\n");
goto retry;
}
}
/* Terminate the string at the first "\r" or "\n" (if any). */
passbuf[strcspn(passbuf, "\r\n")] = '\0';
/* enforce no empty passwords */
if (strnlen(passbuf, MAXPASSLEN) == 0) {
fprintf(stderr,
"Empty password not allowed, please try again\n");
goto retry;
}
/* If we changed terminal settings, reset them. */
if (usingtty)
tcsetattr(fileno(readfrom), TCSANOW, &term_old);
/* Close /dev/tty if we opened it.
if readfromfile is defined and set to -, disable stdin */
if (readfrom != stdin) {
fclose(readfrom);
}
/* Copy the password out. */
char *p = smalloc(strlen(passbuf) + 1);
memcpy(p, passbuf, strlen(passbuf) + 1 );
*passwd = p;
/* Zero any stored passwords. */
memset(passbuf, 0, MAXPASSLEN);
memset(confpassbuf, 0, MAXPASSLEN);
/* Success! */
return (0);
err2:
/* Reset terminal settings if necessary. */
if (usingtty)
tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
err1:
/* Close /dev/tty if we opened it. */
if (readfrom != stdin)
fclose(readfrom);
/* Failure! */
return (-1);
}
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2004, Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* modified by tlinden@cpan.org (c++ => c, pcp api)
*/
int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass) {
// have a child process run the command and get the result back to us.
int fds[2], pid;
int res;
char passbuf[MAXPASSLEN];
res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
if (res == -1) {
fatal(ptx, "Internal error: socketpair() failed");
goto aerr1;
}
pid = fork();
if (pid == -1) {
fatal( ptx, "Internal error: fork() failed");
close(fds[0]);
close(fds[1]);
goto aerr1;
}
if (pid == 0) {
const char *argv[4];
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = askpass;
argv[3] = 0;
// child process.. run the command and send output to fds[0]
close(fds[1]); // we don't use the other half..
// make a copy of stdout and stderr descriptors, and set an environment
// variable telling where to find them, in case a child wants it..
int stdOutCopy = dup(STDOUT_FILENO);
int stdErrCopy = dup(STDERR_FILENO);
// replace STDOUT with our socket, which we'll used to receive the
// password..
dup2(fds[0], STDOUT_FILENO);
// ensure that STDOUT_FILENO and stdout/stderr are not closed on exec..
fcntl(STDOUT_FILENO, F_SETFD, 0); // don't close on exec..
fcntl(stdOutCopy, F_SETFD, 0);
fcntl(stdErrCopy, F_SETFD, 0);
char tmpBuf[8];
snprintf(tmpBuf, sizeof(tmpBuf) - 1, "%i", stdOutCopy);
setenv("PCP_ENV_STDOUT", tmpBuf, 1);
snprintf(tmpBuf, sizeof(tmpBuf) - 1, "%i", stdErrCopy);
setenv("PCP_ENV_STDERR", tmpBuf, 1);
execvp(argv[0], (char *const *)argv); // returns only on error..
fatal(ptx, "Internal error: failed to exec program");
goto aerr1;
}
close(fds[0]);
memset(passbuf, 0, MAXPASSLEN);
if ( recv(fds[1], passbuf, MAXPASSLEN, 0) <= 0) {
fatal(ptx, "Cannot read password\n");
goto aerr1;
}
close(fds[1]);
waitpid(pid, NULL, 0);
/* Terminate the string at the first "\r" or "\n" (if any). */
passbuf[strcspn(passbuf, "\r\n")] = '\0';
/* Copy the password out. */
char *p = smalloc(strlen(passbuf) + 1);
memcpy(p, passbuf, strlen(passbuf) + 1 );
*passwd = p;
/* Zero any stored passwords. */
memset(passbuf, 0, MAXPASSLEN);
return 0;
aerr1:
return -1;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -30,8 +30,8 @@ byte* pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_
nonce, noncelen, NULL, 0);
int status = crypto_pwhash_scryptsalsa208sha256(dk, 64, passwd, passwdlen, salt,
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
ucfree(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
if (status == 0) {

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T. von Dein.
Copyright (C) 2013-2016 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
@@ -69,7 +69,7 @@ void _dump(char *n, byte *d, size_t s) {
if(i % 36 == 35 && i > 0) {
fprintf(stderr, "\n");
for(c=0; c<l; ++c)
fprintf(stderr, " ");
fprintf(stderr, " ");
}
}
fprintf(stderr, "\n");
@@ -119,3 +119,114 @@ size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_arra
return byte_array_size;
}
/*
* Convert byte arrays from big endian to numbers and vice versa. Do
* not take care about host endianess. In Rob Pikes' words:
* https://commandcenter.blogspot.de/2012/04/byte-order-fallacy.html
*
* With this, we remove all calls to byte swap functions like b64toh
* and the likes. They are problematic and I really hated the ifdef
* mess in platform.h anyway.
*/
uint64_t _wireto64(byte *data) {
uint64_t i =
((uint64_t)data[7]<<0) |
((uint64_t)data[6]<<8) |
((uint64_t)data[5]<<16) |
((uint64_t)data[4]<<24) |
((uint64_t)data[3]<<32) |
((uint64_t)data[2]<<40) |
((uint64_t)data[1]<<48) |
((uint64_t)data[0]<<56);
return i;
}
uint32_t _wireto32(byte *data) {
uint32_t i =
((uint32_t)data[3]<<0) |
((uint32_t)data[2]<<8) |
((uint32_t)data[1]<<16) |
((uint32_t)data[0]<<24);
return i;
}
uint16_t _wireto16(byte *data) {
uint16_t i =
((uint16_t)data[1]<<0) |
((uint16_t)data[0]<<8);
return i;
}
void _64towire(uint64_t i, byte *data) {
data[0] = (i >> 56) & 0xFF;
data[1] = (i >> 48) & 0xFF;
data[2] = (i >> 40) & 0xFF;
data[3] = (i >> 32) & 0xFF;
data[4] = (i >> 24) & 0xFF;
data[5] = (i >> 16) & 0xFF;
data[6] = (i >> 8) & 0xFF;
data[7] = i & 0xFF;
}
void _32towire(uint32_t i, byte *data) {
data[0] = (i >> 24) & 0xFF;
data[1] = (i >> 16) & 0xFF;
data[2] = (i >> 8) & 0xFF;
data[3] = i & 0xFF;
}
void _16towire(uint16_t i, byte *data) {
data[0] = (i >> 8) & 0xFF;
data[1] = i & 0xFF;
}
/* via https://github.com/chmike/cst_time_memcmp
Licensed as:
The MIT License (MIT)
Copyright (c) 2015 Christophe Meessen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This is the safest1 variant using subscriptions.
*/
int cst_time_memcmp(const void *m1, const void *m2, size_t n) {
int res = 0, diff;
if (m1 != m2 && n && m1 && m2) {
const unsigned char *pm1 = (const unsigned char *)m1;
const unsigned char *pm2 = (const unsigned char *)m2;
do {
--n;
diff = pm1[n] - pm2[n];
res = (res & (((diff - 1) & ~diff) >> 8)) | diff;
} while (n != 0);
}
return ((res - 1) >> 8) + (res >> 8) + 1;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -29,15 +29,15 @@ vault_t *pcpvault_init(PCPCTX *ptx, char *filename) {
if(vault != NULL) {
if(vault->isnew == 1) {
if(pcpvault_create(ptx, vault) != 0) {
pcpvault_close(ptx, vault);
return NULL;
pcpvault_close(ptx, vault);
return NULL;
}
}
else {
if(pcpvault_fetchall(ptx, vault) != 0) {
errno = 0; /* weird, something sets it to ENOENT and it's not me */
pcpvault_close(ptx, vault);
return NULL;
errno = 0; /* weird, something sets it to ENOENT and it's not me */
pcpvault_close(ptx, vault);
return NULL;
}
}
}
@@ -57,7 +57,7 @@ vault_t *pcpvault_new(PCPCTX *ptx, char *filename, int is_tmp) {
b = arc4random();
snprintf(vault->filename, 1024, "%s-%08x%08x", filename, a, b);
if (stat (vault->filename, &stat_buf) != 0)
break;
break;
}
unlink(vault->filename);
vault->size = 0;
@@ -111,7 +111,7 @@ int pcpvault_create(PCPCTX *ptx, vault_t *vault) {
header->version = PCP_VAULT_VERSION;
vault->version = header->version;
memcpy(vault->checksum, header->checksum, 32);
memcpy(vault->checksum, header->checksum, LSHA);
vh2be(header);
@@ -164,9 +164,7 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
itemsize = PCP_RAW_PUBKEYSIZE;
saveitem = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(saveitem, item, sizeof(pcp_pubkey_t));
pubkey2be((pcp_pubkey_t *)item);
blob = buffer_new(PCP_RAW_KEYSIZE, "bs");
pcp_pubkeyblob(blob, (pcp_pubkey_t *)item);
blob = pcp_keyblob(item, type);
}
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_PBP) {
saveitem = ucmalloc(sizeof(pcp_keysig_t));
@@ -176,16 +174,14 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
memcpy(ksout, ksin, sizeof(pcp_keysig_t));
ksout->blob = ucmalloc(ksin->size);
memcpy(ksout->blob, ksin->blob, ksin->size);
blob = pcp_keysig2blob(item);
blob = pcp_keysigblob(ksin);
itemsize = buffer_size(blob);
}
else {
itemsize = PCP_RAW_KEYSIZE;
saveitem = ucmalloc(sizeof(pcp_key_t));
memcpy(saveitem, item, sizeof(pcp_key_t));
key2be((pcp_key_t *)item);
blob = pcp_keyblob(item, type);
pcp_seckeyblob(blob, (pcp_key_t *)item);
}
if(tmp != NULL) {
@@ -224,27 +220,43 @@ int pcpvault_writeall(PCPCTX *ptx, vault_t *vault) {
if(tmp != NULL) {
if(pcpvault_create(ptx, tmp) == 0) {
pcp_key_t *k = NULL;
Buffer *blob = buffer_new(PCP_RAW_PUBKEYSIZE, "bs");
pcphash_iterate(ptx, k) {
pcp_seckeyblob(blob, k);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_KEYSIZE, PCP_KEY_TYPE_SECRET) != 0) {
buffer_free(blob);
goto errwa;
}
buffer_clear(blob);
}
pcp_pubkey_t *p = NULL;
pcphash_iteratepub(ptx, p) {
pcp_pubkeyblob(blob, p);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_PUBKEYSIZE, PCP_KEY_TYPE_PUBLIC) != 0) {
buffer_free(blob);
goto errwa;
}
buffer_clear(blob);
pcp_keysig_t *s = NULL;
Buffer *blob = buffer_new(PCP_RAW_PUBKEYSIZE, "bs");
pcphash_iterate(ptx, k) {
pcp_seckeyblob(blob, k);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_KEYSIZE,
PCP_KEY_TYPE_SECRET) != 0) {
buffer_free(blob);
goto errwa;
}
buffer_clear(blob);
}
pcphash_iteratepub(ptx, p) {
pcp_pubkeyblob(blob, p);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_PUBKEYSIZE,
PCP_KEY_TYPE_PUBLIC) != 0) {
buffer_free(blob);
goto errwa;
}
buffer_clear(blob);
}
pcphash_iteratekeysig(ptx, s) {
pcp_keysig2blob(blob, s);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), buffer_size(blob),
PCP_KEYSIG_NATIVE) != 0) {
buffer_free(blob);
goto errwa;
}
buffer_clear(blob);
}
pcpvault_update_checksum(ptx, tmp);
if(pcpvault_copy(ptx, tmp, vault) == 0) {
pcpvault_unlink(tmp);
pcpvault_unlink(tmp);
}
pcpvault_free(tmp);
buffer_free(blob);
@@ -268,9 +280,9 @@ void pcpvault_update_checksum(PCPCTX *ptx, vault_t *vault) {
vault_header_t *header = ucmalloc(sizeof(vault_header_t));
header->fileid = PCP_VAULT_ID;
header->version = PCP_VAULT_VERSION;
memcpy(header->checksum, checksum, 32);
memcpy(vault->checksum, checksum, 32);
ucfree(checksum, 32);
memcpy(header->checksum, checksum, LSHA);
memcpy(vault->checksum, checksum, LSHA);
ucfree(checksum, LSHA);
vh2be(header);
@@ -292,36 +304,33 @@ byte *pcpvault_create_checksum(PCPCTX *ptx) {
size_t datasize = ((PCP_RAW_KEYSIZE) * numskeys) +
((PCP_RAW_PUBKEYSIZE) * numpkeys);
byte *data = ucmalloc(datasize);
byte *checksum = ucmalloc(32);
byte *checksum = ucmalloc(LSHA);
pcphash_iterate(ptx, k) {
key2be(k);
pcp_seckeyblob(blob, (pcp_key_t *)k);
memcpy(&data[datapos], buffer_get(blob), PCP_RAW_KEYSIZE);
memcpy(&data[datapos], buffer_get(blob), buffer_size(blob));
buffer_clear(blob);
key2native(k);
datapos += PCP_RAW_KEYSIZE;
datapos += buffer_size(blob);
}
pcp_pubkey_t *p = NULL;
pcphash_iteratepub(ptx, p) {
/* pcp_dumppubkey(p); */
pubkey2be(p);
pcp_pubkeyblob(blob, (pcp_pubkey_t *)p);
memcpy(&data[datapos], buffer_get(blob), PCP_RAW_PUBKEYSIZE);
memcpy(&data[datapos], buffer_get(blob), buffer_size(blob));
buffer_clear(blob);
pubkey2native(p);
datapos += PCP_RAW_PUBKEYSIZE;
datapos += buffer_size(blob);
}
pcp_keysig_t *s = NULL;
pcphash_iteratekeysig(ptx, s) {
pcp_keysig2blob(blob, (pcp_keysig_t *)s);
memcpy(&data[datapos], buffer_get(blob), buffer_size(blob));
buffer_clear(blob);
datapos += buffer_size(blob);
}
buffer_free(blob);
/*
printf("PUB: %d, SEC: %d\n", PCP_RAW_PUBKEYSIZE, PCP_RAW_KEYSIZE);
printf("DATA (%d) (s: %d, p: %d):\n", (int)datasize, numskeys, numpkeys);
_dump("data", data, datasize);
*/
crypto_hash_sha256(checksum, data, datasize);
memset(data, 0, datasize);
@@ -343,7 +352,7 @@ int pcpvault_copy(PCPCTX *ptx, vault_t *tmp, vault_t *vault) {
vault->fd = freopen(vault->filename, "wb+", vault->fd);
if(fwrite(in, tmpsize, 1, vault->fd) != 1) {
fatal(ptx, "Failed to copy %s to %s (write) [keeping %s]\n",
tmp->filename, vault->filename, tmp->filename);
tmp->filename, vault->filename, tmp->filename);
ucfree(in, tmpsize);
return 1;
}
@@ -351,7 +360,7 @@ int pcpvault_copy(PCPCTX *ptx, vault_t *tmp, vault_t *vault) {
if(fflush(vault->fd) != 0) {
fatal(ptx, "Failed to copy %s to %s (flush) [keeping %s]\n",
tmp->filename, vault->filename, tmp->filename);
tmp->filename, vault->filename, tmp->filename);
return 1;
}
@@ -378,7 +387,7 @@ int pcpvault_close(PCPCTX *ptx, vault_t *vault) {
if(vault != NULL) {
if(vault->fd) {
if(vault->unsafed == 1) {
pcpvault_writeall(ptx, vault);
pcpvault_writeall(ptx, vault);
}
fclose(vault->fd);
}
@@ -396,45 +405,30 @@ void pcpvault_free(vault_t *vault) {
}
vault_header_t * vh2be(vault_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN
_32towire(h->version, (byte *)&h->version);
return h;
#else
h->version = htobe32(h->version);
return h;
#endif
}
vault_header_t * vh2native(vault_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN
h->version = _wireto32((byte *)&h->version);
return h;
#else
h->version = be32toh(h->version);
return h;
#endif
}
vault_item_header_t * ih2be(vault_item_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN
_32towire(h->version, (byte *)&h->version);
_32towire(h->size, (byte *)&h->size);
return h;
#else
h->version = htobe32(h->version);
h->size = htobe32(h->size);
return h;
#endif
}
vault_item_header_t * ih2native(vault_item_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN
h->version = _wireto32((byte *)&h->version);
h->size = _wireto32((byte *)&h->size);
return h;
#else
h->version = be32toh(h->version);
h->size = be32toh(h->size);
return h;
#endif
}
int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
Buffer *raw = NULL;
size_t got = 0;
fseek(vault->fd, 0, SEEK_SET);
@@ -443,7 +437,7 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
got = fread(header, 1, sizeof(vault_header_t), vault->fd);
if(got < sizeof(vault_header_t)) {
fatal(ptx, "empty or invalid vault header size (got %ld, expected %ld)\n",
got, sizeof(vault_header_t));
got, sizeof(vault_header_t));
goto err;
}
vh2native(header);
@@ -455,66 +449,66 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
pcp_pubkey_t *pubkey;
int bytesleft = 0;
int ksize = PCP_RAW_KEYSIGSIZE; /* smallest possbile item */
raw = buffer_new(256, "rawin");
vault->version = header->version;
memcpy(vault->checksum, header->checksum, 32);
memcpy(vault->checksum, header->checksum, LSHA);
for(;;) {
readpos = ftell(vault->fd);
if(vault->size - readpos >= sizeof(vault_item_header_t)) {
/* an item header follows */
got = fread(item, sizeof(vault_item_header_t), 1, vault->fd);
ih2native(item);
/* an item header follows */
got = fread(item, sizeof(vault_item_header_t), 1, vault->fd);
ih2native(item);
if(item->size > 0) {
/* item is valid */
readpos = ftell(vault->fd);
bytesleft = vault->size - readpos;
if(bytesleft >= ksize) {
/* a key follows */
if(item->type == PCP_KEY_TYPE_MAINSECRET ||
item->type == PCP_KEY_TYPE_SECRET) {
/* read a secret key */
key = ucmalloc(sizeof(pcp_key_t));
got = fread(key, PCP_RAW_KEYSIZE, 1, vault->fd);
key2native(key);
pcphash_add(ptx, (void *)key, item->type);
}
else if(item->type == PCP_KEY_TYPE_PUBLIC) {
/* read a public key */
pubkey = ucmalloc(sizeof(pcp_pubkey_t));
got = fread(pubkey, PCP_RAW_PUBKEYSIZE, 1, vault->fd);
pubkey2native(pubkey);
pcphash_add(ptx, (void *)pubkey, item->type);
}
else if(item->type == PCP_KEYSIG_NATIVE || item->type == PCP_KEYSIG_PBP) {
Buffer *rawks = buffer_new(256, "keysig");
buffer_fd_read(rawks, vault->fd, item->size);
pcp_keysig_t *s = pcp_keysig_new(rawks);
pcphash_add(ptx, (void *)s, item->type);
buffer_free(rawks);
}
else {
fatal(ptx, "Failed to read vault - invalid key type: %02X! at %d\n",
item->type, readpos);
goto err;
}
}
else {
fatal(ptx, "Failed to read vault - that's no pcp key at %d (size %ld)!\n",
readpos, bytesleft);
goto err;
}
}
else {
fatal(ptx, "Failed to read vault - invalid key item header size at %d!\n",
readpos);
goto err;
}
if(item->size > 0) {
/* item is valid */
readpos = ftell(vault->fd);
bytesleft = vault->size - readpos;
if(bytesleft >= ksize) {
/* a key follows */
if(item->type == PCP_KEY_TYPE_MAINSECRET ||
item->type == PCP_KEY_TYPE_SECRET) {
/* read a secret key */
buffer_fd_read(raw, vault->fd, item->size);
key = pcp_blob2key(raw);
pcphash_add(ptx, (void *)key, item->type);
buffer_clear(raw);
}
else if(item->type == PCP_KEY_TYPE_PUBLIC) {
/* read a public key */
buffer_fd_read(raw, vault->fd, item->size);
pubkey = pcp_blob2pubkey(raw);
pcphash_add(ptx, (void *)pubkey, item->type);
buffer_clear(raw);
}
else if(item->type == PCP_KEYSIG_NATIVE || item->type == PCP_KEYSIG_PBP) {
buffer_fd_read(raw, vault->fd, item->size);
pcp_keysig_t *s = pcp_blob2keysig(raw);
pcphash_add(ptx, (void *)s, item->type);
buffer_clear(raw);
}
else {
fatal(ptx, "Failed to read vault - invalid key type: %02X! at %d\n",
item->type, readpos);
goto err;
}
}
else {
fatal(ptx, "Failed to read vault - that's no pcp key at %d (size %ld)!\n",
readpos, bytesleft);
goto err;
}
}
else {
fatal(ptx, "Failed to read vault - invalid key item header size at %d!\n",
readpos);
goto err;
}
}
else {
/* no more items */
break;
/* no more items */
break;
}
}
}
@@ -526,14 +520,9 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
byte *checksum = NULL;
checksum = pcpvault_create_checksum(ptx);
/*
_dump(" calc checksum", checksum, 32);
_dump("vault checksum", vault->checksum, 32);
*/
if(pcphash_count(ptx) + pcphash_countpub(ptx) > 0) {
/* only validate the checksum if there are keys */
if(memcmp(checksum, vault->checksum, 32) != 0) {
if(cst_time_memcmp(checksum, vault->checksum, LSHA) != 0) {
fatal(ptx, "Error: the checksum of the key vault doesn't match its contents!\n");
goto err;
}
@@ -542,11 +531,13 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
free(checksum);
free(item);
free(header);
buffer_free(raw);
return 0;
err:
free(item);
free(header);
buffer_free(raw);
/* pcphash_clean(); */
return -1;

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -35,6 +35,9 @@ static char *begins[] = {
/* via http://stackoverflow.com/a/1031773, slightly modified,
licensed under CC-BY-SA, written by Christoph
*/
uint8_t is_utf8(const byte *bytes) {
if( (// non-overlong 2-byte
(0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
@@ -51,8 +54,8 @@ uint8_t is_utf8(const byte *bytes) {
) ||
(// straight 3-byte
((0xE1 <= bytes[0] && bytes[0] <= 0xEC) ||
bytes[0] == 0xEE ||
bytes[0] == 0xEF) &&
bytes[0] == 0xEE ||
bytes[0] == 0xEF) &&
(0x80 <= bytes[1] && bytes[1] <= 0xBF) &&
(0x80 <= bytes[2] && bytes[2] <= 0xBF)
) ||
@@ -104,25 +107,25 @@ size_t _buffer_is_binary(byte *buf, size_t len) {
/* check for utf8 */
wide[0] = buf[pos];
for(i=1; i<3; i++) {
/* check for 2, 3 or 4 byte utf8 char */
if(pos+i < len) {
/* only if there's enough space of course */
wide[i] = buf[pos+i];
if(is_utf8(wide) > 1) {
pos += i; /* jump over the utf we already found */
utf = 1;
break;
}
}
else
break;
/* check for 2, 3 or 4 byte utf8 char */
if(pos+i < len) {
/* only if there's enough space of course */
wide[i] = buf[pos+i];
if(is_utf8(wide) > 1) {
pos += i; /* jump over the utf we already found */
utf = 1;
break;
}
}
else
break;
}
memset(wide, 0, 4);
if(utf == 1) {
/* it's a utf8 char, continue checking, reset wide */
utf = 0;
continue;
/* it's a utf8 char, continue checking, reset wide */
utf = 0;
continue;
}
break; /* if we reach this, then it's binary and not utf8, stop checking */
}
@@ -173,7 +176,6 @@ byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen) {
byte padblob[4];
srclen = strlen(z85block);
if(srclen == 0) {
/* FIXME: check how this happens, pcpstream decoder call */
*dstlen = 0;
@@ -212,7 +214,7 @@ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock) {
char *padblob = NULL;
char *z85 = NULL;
char *z85block = NULL;
if(srclen %4 == 0) {
/* no padding required */
padded = raw;
@@ -254,12 +256,12 @@ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock) {
while(*z != '\0') {
if(pos >= 71) {
*B++ = '\r';
*B++ = '\n';
pos = 1;
*B++ = '\r';
*B++ = '\n';
pos = 1;
}
else {
pos++;
pos++;
}
*B++ = *z++;
}
@@ -329,27 +331,27 @@ char *pcp_readz85string(PCPCTX *ptx, unsigned char *input, size_t bufsize) {
else if(input[i] == '\n') {
/* a line is complete */
if(z85_isbegin(line) && begin == 0) {
/* a begin header, reset whatever we've got so far in z buffer */
begin = 1;
buffer_clear(line);
buffer_clear(z);
continue;
/* a begin header, reset whatever we've got so far in z buffer */
begin = 1;
buffer_clear(line);
buffer_clear(z);
continue;
}
else if(z85_isend(line)){
/* an end header */
buffer_clear(line);
end = 1;
break;
/* an end header */
buffer_clear(line);
end = 1;
break;
}
else if(z85_isempty(line) || z85_iscomment(line)) {
/* a comment */
buffer_clear(line);
continue;
/* a comment */
buffer_clear(line);
continue;
}
else {
/* regular z85 encoded content */
buffer_add_buf(z, line);
buffer_clear(line);
/* regular z85 encoded content */
buffer_add_buf(z, line);
buffer_clear(line);
}
}
else {
@@ -467,7 +469,7 @@ int z85_isbegin(Buffer *buf) {
blen = strlen(begin);
if(blen <= len)
if(_findoffset(line+buf->offset, len, (char *)begin, blen) >= 0)
isb = i; /* i = ENUM ZBEGINS */
isb = i; /* i = ENUM ZBEGINS */
}
free(line);

View File

@@ -55,27 +55,27 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
if (size % 4 != 0)
return NULL; /* !assert */
unsigned int char_nbr = 0;
unsigned int byte_nbr = 0;
uint32_t value = 0;
while (byte_nbr < size) {
/* Accumulate value in base 256 (binary) */
value = value * 256 + data [byte_nbr++];
if (byte_nbr % 4 == 0) {
/* Output value in base 85 */
unsigned int divisor = 85 * 85 * 85 * 85;
while (divisor) {
dest [char_nbr++] = encoder [value / divisor % 85];
divisor /= 85;
}
value = 0;
}
unsigned int char_nbr = 0;
unsigned int byte_nbr = 0;
uint32_t value = 0;
while (byte_nbr < size) {
/* Accumulate value in base 256 (binary) */
value = value * 256 + data [byte_nbr++];
if (byte_nbr % 4 == 0) {
/* Output value in base 85 */
unsigned int divisor = 85 * 85 * 85 * 85;
while (divisor) {
dest [char_nbr++] = encoder [value / divisor % 85];
divisor /= 85;
}
value = 0;
}
if (char_nbr != size * 5 / 4)
return NULL; /* !assert */
}
if (char_nbr != size * 5 / 4)
return NULL; /* !assert */
dest [char_nbr] = 0;
return dest;
dest [char_nbr] = 0;
return dest;
}

View File

@@ -286,6 +286,26 @@ B<In short: don NOT use this software for production purposes!>
=head1 INTERNALS
=head2 PASSPHRASES
Passphrases are used to protect secret data at rest on various instances
by pcp, like secret keys or symmetric encrypted data.
Pcp doesn't use the passphrase directly but uses a key derivation function
to calculate a secure key from the passphrase: libsodium's
B<crypto_pwhash_scryptsalsa208sha256()> function.
In order to properly protect secret keys, pcp measures the entropy
of a given passphrase and warns the user about the possible weak
passphrase. This measurement is calculated using the Claude E. Shannon
method, where a value of 8.0 means maximum available entropy (e.g.
truly random 256 chars in no comprehensible order) and 0.0 stands
for the worst like passphrases like "aaa" or "x".
Pcp considers passphrases with an entropy measurement of 3.32 or higher
as acceptable. This may change in the future.
=head2 VAULT FORMAT
The vault file contains all public and secret keys. It's a portable

View File

@@ -1,3 +1,4 @@
=head1 INSTALLATION
There are currently no packages available, so B<pcp> has to be
@@ -13,7 +14,20 @@ First, you will need libsodium:
sudo ldconfig
cd ..
Next, pcp:
If you want to have JSON support, you'll need to install the
Jansson library (optional):
git clone git://github.com/akheron/jansson.git
cd jansson
autoreconf -i
./configure && make
sudo make install
cd ..
In order to use the python binding, you need to install the
B<cffi> python package.
Next, build pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp

View File

@@ -1,3 +1,4 @@
=head1 OPTIONS
Usage: pcp1 [options]
@@ -9,10 +10,13 @@
will be used.
-I --infile <file> Input file. If not specified, stdin
will be used.
-x --xpass <passwd> Provide password. B<INSECURE>! Use for
testing or debugging only!
-X --password-file <file> Read passphrase from <file>. If <file>
is -, read from stdin. This takes
precedence over other uses of stdin
elsewhere, see below for more details.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id to import/export.
-r --recipient <string> Specify a recpipient, used for public
key export and encryption.
@@ -26,7 +30,7 @@
--version Print program version.
-D --debug Enable debug output.
-v --verbose Enable verbose output.
Keymanagement Options:
-k --keygen Generate a CURVE25519 secret key. If
the generated key is the first one in
@@ -35,9 +39,7 @@
been specified, don't store the generated
key to the vault but export it to the
file instead. You will be asked for
an owner, mail and a passphrase. If you
leave the passphrase empty, the key will
be stored unencrypted.
an owner, mail and a passphrase.
-l --listkeys List all keys currently stored in your
vault. Only the key id's and some info
about the keys will be printed, not the
@@ -132,11 +134,9 @@
uses stdin/stdout
Misc Options:
-C --checksum [<key>] Calculate a Blake2b checksum of one or more files.
If <key> is provided, an authenticated hash will
be calculated, otherwise a normal hash. If you don't
want to generate an authenticated hash, specify
-- after -C.
-C --checksum Calculate a Blake2b checksum of one or more files.
If -x is provided, an authenticated hash will
be calculated, otherwise a normal hash.
Use -I to specify one file or put multiple file
names after -C like "pcp1 -C -- file1 file2 file3".

View File

@@ -1,4 +1,4 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -38,8 +38,6 @@
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
@@ -50,24 +48,17 @@
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
.ie \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.el \{\
. de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
@@ -133,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "PCP1 1"
.TH PCP1 1 "2015-07-21" "PCP 0.3.0" "USER CONTRIBUTED DOCUMENTATION"
.TH PCP1 1 "2016-10-26" "PCP 0.4.0" "USER CONTRIBUTED DOCUMENTATION"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -158,7 +149,10 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& \-V \-\-vault <vaultfile> Specify an alternate vault file.
\& \-O \-\-outfile <file> Output file. STDOUT if unspecified.
\& \-I \-\-infile <file> Input file. STDIN if unspecified.
\& \-x \-\-xpass <passwd> Provide password. INSECURE! Use for testing
\& or debugging only!
\& \-X \-\-password\-file <file> Read passphrase from <file>.
\& \-\-extpass <program> Use external program for password prompt.
\& \-i \-\-keyid <id> Specify a key id for various operations.
\& \-r \-\-recipient <string> Specify a recpipient, multiple allowed.
\& \-t \-\-text Print textual representation of ojects.
@@ -193,13 +187,16 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& \-a \-\-armor \-\-textmode same as \-z
\&
\& Misc Options:
\& \-C \-\-checksum [<key>] calculate a Blake2 checksum of one or more files.
\& \-C \-\-checksum calculate a Blake2 checksum of one or more files.
\& add \-x <key> to compute an authenticated hash.
\&
\& Arguments:
\& Extra arguments after options are treated as filenames or
\& recipients, depending on operation mode.
\&=head1 OPTIONS
\&
.Ve
.SH "OPTIONS"
.IX Header "OPTIONS"
.Vb 1
\& Usage: pcp1 [options]
\&
\& General Options:
@@ -209,10 +206,13 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& will be used.
\& \-I \-\-infile <file> Input file. If not specified, stdin
\& will be used.
\& \-x \-\-xpass <passwd> Provide password. B<INSECURE>! Use for
\& testing or debugging only!
\& \-X \-\-password\-file <file> Read passphrase from <file>. If <file>
\& is \-, read from stdin. This takes
\& precedence over other uses of stdin
\& elsewhere, see below for more details.
\& \-\-extpass <program> Use external program for password prompt.
\& \-i \-\-keyid <id> Specify a key id to import/export.
\& \-r \-\-recipient <string> Specify a recpipient, used for public
\& key export and encryption.
@@ -226,7 +226,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& \-\-version Print program version.
\& \-D \-\-debug Enable debug output.
\& \-v \-\-verbose Enable verbose output.
\&
\&
\& Keymanagement Options:
\& \-k \-\-keygen Generate a CURVE25519 secret key. If
\& the generated key is the first one in
@@ -235,9 +235,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& been specified, don\*(Aqt store the generated
\& key to the vault but export it to the
\& file instead. You will be asked for
\& an owner, mail and a passphrase. If you
\& leave the passphrase empty, the key will
\& be stored unencrypted.
\& an owner, mail and a passphrase.
\& \-l \-\-listkeys List all keys currently stored in your
\& vault. Only the key id\*(Aqs and some info
\& about the keys will be printed, not the
@@ -332,11 +330,9 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& uses stdin/stdout
\&
\& Misc Options:
\& \-C \-\-checksum [<key>] Calculate a Blake2b checksum of one or more files.
\& If <key> is provided, an authenticated hash will
\& be calculated, otherwise a normal hash. If you don\*(Aqt
\& want to generate an authenticated hash, specify
\& \-\- after \-C.
\& \-C \-\-checksum Calculate a Blake2b checksum of one or more files.
\& If \-x is provided, an authenticated hash will
\& be calculated, otherwise a normal hash.
\& Use \-I to specify one file or put multiple file
\& names after \-C like "pcp1 \-C \-\- file1 file2 file3".
.Ve
@@ -346,7 +342,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
be used to encrypt files. \fBpcp1\fR uses eliptc curve cryptography
for encryption (\s-1CURVE25519\s0 by Dan J. Bernstein). While \s-1CURVE25519\s0
is no worldwide accepted standard it hasn't been compromised by
the \s-1NSA \-\s0 which might be better, depending on your point of view.
the \s-1NSA\s0 \- which might be better, depending on your point of view.
.PP
\&\fBCaution\fR: since \s-1CURVE25519\s0 is no accepted standard, \fBpcp1\fR has
to be considered as experimental software. In fact, I wrote it just
@@ -672,10 +668,10 @@ Enable debugging output, where supported. Same as \fB\-D\fR.
.IX Header "EXIT STATUS"
Pcp may return one of several error codes if it encounters problems.
.IP "0 No problems occurred." 4
.IX Item "0 No problems occurred."
.IX Item "0 No problems occurred."
.PD 0
.IP "1 Generic error code." 4
.IX Item "1 Generic error code."
.IX Item "1 Generic error code."
.PD
.SH "FILES"
.IX Header "FILES"
@@ -724,7 +720,25 @@ don't use it for anything remotely serious.
\&\fBIn short: don \s-1NOT\s0 use this software for production purposes!\fR
.SH "INTERNALS"
.IX Header "INTERNALS"
.SS "\s-1VAULT FORMAT\s0"
.SS "\s-1PASSPHRASES\s0"
.IX Subsection "PASSPHRASES"
Passphrases are used to protect secret data at rest on various instances
by pcp, like secret keys or symmetric encrypted data.
.PP
Pcp doesn't use the passphrase directly but uses a key derivation function
to calculate a secure key from the passphrase: libsodium's
\&\fB\f(BIcrypto_pwhash_scryptsalsa208sha256()\fB\fR function.
.PP
In order to properly protect secret keys, pcp measures the entropy
of a given passphrase and warns the user about the possible weak
passphrase. This measurement is calculated using the Claude E. Shannon
method, where a value of 8.0 means maximum available entropy (e.g.
truly random 256 chars in no comprehensible order) and 0.0 stands
for the worst like passphrases like \*(L"aaa\*(R" or \*(L"x\*(R".
.PP
Pcp considers passphrases with an entropy measurement of 3.32 or higher
as acceptable. This may change in the future.
.SS "\s-1VAULT\s0 \s-1FORMAT\s0"
.IX Subsection "VAULT FORMAT"
The vault file contains all public and secret keys. It's a portable
binary file.
@@ -771,7 +785,7 @@ Type can be one of:
.Ve
.PP
The key header is followed by the actual key, see below.
.SS "\s-1SECRET KEY FORMAT\s0"
.SS "\s-1SECRET\s0 \s-1KEY\s0 \s-1FORMAT\s0"
.IX Subsection "SECRET KEY FORMAT"
A secret key is a binary structure with the following format:
.PP
@@ -840,7 +854,7 @@ are otherwise unrelated. If one of them leaks, the other
cannot be recalculated from it.
.PP
Take a look at the function \fB\f(BIpcp_keypairs()\fB\fR for details.
.SS "\s-1PUBLIC KEY EXPORT FORMAT\s0"
.SS "\s-1PUBLIC\s0 \s-1KEY\s0 \s-1EXPORT\s0 \s-1FORMAT\s0"
.IX Subsection "PUBLIC KEY EXPORT FORMAT"
Exported public and secret keys will be written in a portable
way. Pcp uses \s-1RFC4880\s0 export format for public keys with some
@@ -944,7 +958,7 @@ So, a full pubkey export looks like this
\& hash
\& signature
.Ve
.SS "\s-1SECRET KEY EXPORT FORMAT\s0"
.SS "\s-1SECRET\s0 \s-1KEY\s0 \s-1EXPORT\s0 \s-1FORMAT\s0"
.IX Subsection "SECRET KEY EXPORT FORMAT"
Secret keys are exported in a proprietary format.
.PP
@@ -976,7 +990,7 @@ to encrypt the data and looks after encryption as such:
.Vb 1
\& Nonce | Cipher
.Ve
.SS "\s-1ENCRYPTED OUTPUT FORMAT\s0"
.SS "\s-1ENCRYPTED\s0 \s-1OUTPUT\s0 \s-1FORMAT\s0"
.IX Subsection "ENCRYPTED OUTPUT FORMAT"
The encryption protocol used by \s-1PCP\s0 uses mostly standard
libsodium facilities with the exception that \s-1PCP\s0 uses counter
@@ -1069,7 +1083,7 @@ of the sender.
The encrypted output maybe Z85 encoded. In this case the Z85
encoding will be done blockwise with blocks of 16k bytes. The
decoded content inside will be as described above.
.SS "\s-1SIGNATURE FORMAT\s0"
.SS "\s-1SIGNATURE\s0 \s-1FORMAT\s0"
.IX Subsection "SIGNATURE FORMAT"
There are different signature formats. Standard binary \s-1NACL\s0
signatures have the following format:
@@ -1121,15 +1135,15 @@ Armored signatures have the following format:
.PP
The Z85 encoded signature at the end contains the same signature
contents as the binary signature outlined above (hash+sig).
.SS "\s-1SIGNED ENCRYPTION FORMAT\s0"
.SS "\s-1SIGNED\s0 \s-1ENCRYPTION\s0 \s-1FORMAT\s0"
.IX Subsection "SIGNED ENCRYPTION FORMAT"
Signed encrypted files are in binary form only. The first part is
the standard encrypted file as described in \fB\s-1ENCRYPTED OUTPUT FORMAT\s0\fR
followed by the binary encrypted signature described in \fB\s-1SIGNATURE FORMAT\s0\fR
the standard encrypted file as described in \fB\s-1ENCRYPTED\s0 \s-1OUTPUT\s0 \s-1FORMAT\s0\fR
followed by the binary encrypted signature described in \fB\s-1SIGNATURE\s0 \s-1FORMAT\s0\fR
without the offset separator.
.PP
However, not only the hash of the file content will be signed but the
recipient list described in \fB\s-1ENCRYPTED OUTPUT FORMAT\s0\fR as well. A
recipient list described in \fB\s-1ENCRYPTED\s0 \s-1OUTPUT\s0 \s-1FORMAT\s0\fR as well. A
valid recipient is therefore not able to re-encrypt the decrypted
message, append the original signature and send it to other recipients.
The signature would not match since the recipient list differs and
@@ -1169,7 +1183,7 @@ Before encryption the signature format is:
\& +\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
.Ve
.PP
where R is: C(recipient)|C(recipient)... (see \fB\s-1ENCRYPTED OUTPUT FORMAT\s0\fR).
where R is: C(recipient)|C(recipient)... (see \fB\s-1ENCRYPTED\s0 \s-1OUTPUT\s0 \s-1FORMAT\s0\fR).
.PP
Pseudocode:
.PP
@@ -1236,9 +1250,9 @@ pcp1 \-z \-I file \-O file.z85
Reverse the process:
.PP
pcp1 \-Z \-I file.z85 \-O file
.SS "\s-1PBP COMPATIBILITY\s0"
.SS "\s-1PBP\s0 \s-1COMPATIBILITY\s0"
.IX Subsection "PBP COMPATIBILITY"
\&\s-1PCP\s0 tries to be fully compatible with \s-1PBP \s0(https://github.com/stef/pbp). Encrypted
\&\s-1PCP\s0 tries to be fully compatible with \s-1PBP\s0 (https://github.com/stef/pbp). Encrypted
files and signatures \- at least their binary versions \- should be exchangable. However,
this is a work in progress and might not work under all circumstances. Also there's currently
no shared key format between pbp and pcp. However, it is possible to export and
@@ -1262,8 +1276,8 @@ functions:
.PD
.PP
\&\s-1JSON\s0 support can be used either with the commandline tool \fBpcp1\fR or programmatically
using the C, \*(C+ or Python \s-1API.\s0
.SS "\s-1USING JSON FROM THE C API\s0"
using the C, \*(C+ or Python \s-1API\s0.
.SS "\s-1USING\s0 \s-1JSON\s0 \s-1FROM\s0 \s-1THE\s0 C \s-1API\s0"
.IX Subsection "USING JSON FROM THE C API"
In order to use \s-1JSON\s0 all you've got to do is to switch a context flag:
.PP
@@ -1273,9 +1287,9 @@ In order to use \s-1JSON\s0 all you've got to do is to switch a context flag:
.Ve
.PP
That all to it. Now any function normally used for key import and export works
with \s-1JSON,\s0 just fill the \fBBuffer\fR object with a \s-1JSON\s0 string for imports or
with \s-1JSON\s0, just fill the \fBBuffer\fR object with a \s-1JSON\s0 string for imports or
fetch the Buffer content of an export function as a string.
.SS "\s-1USING JSON FROM THE COMMANDLINE\s0"
.SS "\s-1USING\s0 \s-1JSON\s0 \s-1FROM\s0 \s-1THE\s0 \s-1COMMANDLINE\s0"
.IX Subsection "USING JSON FROM THE COMMANDLINE"
In order to use \s-1JSON\s0 on the commandline, add \fB\-j\fR. This can be used in
conjunction with the following options:
@@ -1293,9 +1307,9 @@ Public and secret key import.
Text view mode (aka inspect mode).
.PP
The \fB\-z\fR and \fB\-Z\fR options are ignored in \s-1JSON\s0 mode.
.SS "\s-1JSON OBJECT STRUCTURE\s0"
.SS "\s-1JSON\s0 \s-1OBJECT\s0 \s-1STRUCTURE\s0"
.IX Subsection "JSON OBJECT STRUCTURE"
\fI\s-1JSON PUBLIC KEY \s0(pcp1 \-p \-j)\fR
\fI\s-1JSON\s0 \s-1PUBLIC\s0 \s-1KEY\s0 (pcp1 \-p \-j)\fR
.IX Subsection "JSON PUBLIC KEY (pcp1 -p -j)"
.PP
The \s-1JSON\s0 object for a public key looks like this:
@@ -1324,7 +1338,7 @@ Fields containing byte arrays are hex encoded.
.PP
Numbers are represented as literal integers.
.PP
\fI\s-1JSON SECRET KEY \s0(pcp1 \-s \-j)\fR
\fI\s-1JSON\s0 \s-1SECRET\s0 \s-1KEY\s0 (pcp1 \-s \-j)\fR
.IX Subsection "JSON SECRET KEY (pcp1 -s -j)"
.PP
The \s-1JSON\s0 object for a public key looks like this:
@@ -1355,7 +1369,7 @@ secret key material. Pcp does not support exporting a secret key unencrypted.
The \fBnonce\fR is required for a later import and shall not be changed or
decoupled from \fBsecrets\fR. This may change in the future.
.PP
\fI\s-1JSON VAULT \s0(pcp1 \-t)\fR
\fI\s-1JSON\s0 \s-1VAULT\s0 (pcp1 \-t)\fR
.IX Subsection "JSON VAULT (pcp1 -t)"
.PP
The \s-1JSON\s0 object for the vault looks like this:
@@ -1374,7 +1388,7 @@ The \s-1JSON\s0 object for the vault looks like this:
The field \fBkeys\fR is an array containing one or more of the already
described key objects.
.PP
\fI\s-1JSON PROGRAM OUTPUT\s0\fR
\fI\s-1JSON\s0 \s-1PROGRAM\s0 \s-1OUTPUT\s0\fR
.IX Subsection "JSON PROGRAM OUTPUT"
.PP
Currently pcp does not support \s-1JSON\s0 program output, that is, success or
@@ -1423,7 +1437,7 @@ under the \fB\s-1GPL\s0\fR as well.
\&\fIT.v.Dein <tom \s-1AT\s0 vondein \s-1DOT\s0 org\fR>
.SH "LICENSE"
.IX Header "LICENSE"
Licensed under the \s-1GNU GENERAL PUBLIC LICENSE\s0 version 3.
Licensed under the \s-1GNU\s0 \s-1GENERAL\s0 \s-1PUBLIC\s0 \s-1LICENSE\s0 version 3.
.SH "HOME"
.IX Header "HOME"
The homepage of Pretty Curved Privacy can be found on

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,10 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
-V --vault <vaultfile> Specify an alternate vault file.
-O --outfile <file> Output file. STDOUT if unspecified.
-I --infile <file> Input file. STDIN if unspecified.
-x --xpass <passwd> Provide password. INSECURE! Use for testing
or debugging only!
-X --password-file <file> Read passphrase from <file>.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id for various operations.
-r --recipient <string> Specify a recpipient, multiple allowed.
-t --text Print textual representation of ojects.
@@ -56,11 +59,13 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
-a --armor --textmode same as -z
Misc Options:
-C --checksum [<key>] calculate a Blake2 checksum of one or more files.
-C --checksum calculate a Blake2 checksum of one or more files.
add -x <key> to compute an authenticated hash.
Arguments:
Extra arguments after options are treated as filenames or
recipients, depending on operation mode.
=head1 OPTIONS
Usage: pcp1 [options]
@@ -72,10 +77,13 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
will be used.
-I --infile <file> Input file. If not specified, stdin
will be used.
-x --xpass <passwd> Provide password. B<INSECURE>! Use for
testing or debugging only!
-X --password-file <file> Read passphrase from <file>. If <file>
is -, read from stdin. This takes
precedence over other uses of stdin
elsewhere, see below for more details.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id to import/export.
-r --recipient <string> Specify a recpipient, used for public
key export and encryption.
@@ -89,7 +97,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
--version Print program version.
-D --debug Enable debug output.
-v --verbose Enable verbose output.
Keymanagement Options:
-k --keygen Generate a CURVE25519 secret key. If
the generated key is the first one in
@@ -98,9 +106,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
been specified, don't store the generated
key to the vault but export it to the
file instead. You will be asked for
an owner, mail and a passphrase. If you
leave the passphrase empty, the key will
be stored unencrypted.
an owner, mail and a passphrase.
-l --listkeys List all keys currently stored in your
vault. Only the key id's and some info
about the keys will be printed, not the
@@ -195,11 +201,9 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
uses stdin/stdout
Misc Options:
-C --checksum [<key>] Calculate a Blake2b checksum of one or more files.
If <key> is provided, an authenticated hash will
be calculated, otherwise a normal hash. If you don't
want to generate an authenticated hash, specify
-- after -C.
-C --checksum Calculate a Blake2b checksum of one or more files.
If -x is provided, an authenticated hash will
be calculated, otherwise a normal hash.
Use -I to specify one file or put multiple file
names after -C like "pcp1 -C -- file1 file2 file3".
@@ -596,6 +600,26 @@ B<In short: don NOT use this software for production purposes!>
=head1 INTERNALS
=head2 PASSPHRASES
Passphrases are used to protect secret data at rest on various instances
by pcp, like secret keys or symmetric encrypted data.
Pcp doesn't use the passphrase directly but uses a key derivation function
to calculate a secure key from the passphrase: libsodium's
B<crypto_pwhash_scryptsalsa208sha256()> function.
In order to properly protect secret keys, pcp measures the entropy
of a given passphrase and warns the user about the possible weak
passphrase. This measurement is calculated using the Claude E. Shannon
method, where a value of 8.0 means maximum available entropy (e.g.
truly random 256 chars in no comprehensible order) and 0.0 stands
for the worst like passphrases like "aaa" or "x".
Pcp considers passphrases with an entropy measurement of 3.32 or higher
as acceptable. This may change in the future.
=head2 VAULT FORMAT
The vault file contains all public and secret keys. It's a portable

View File

@@ -20,14 +20,14 @@
#
AM_CFLAGS = -I../include/pcp -I../libpcp/scrypt/crypto
AM_CFLAGS = -I../include/pcp
EXTRA_DIST = *.h
bin_PROGRAMS = pcp1
pcp1_LDADD = ../libpcp/.libs/libpcp1.a
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c \
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c \
encryption.c z85util.c signature.c \
compat_getopt.c

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
Copyright (C) 2013-2016 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
@@ -66,57 +66,61 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase for symetric decryption", NULL, 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter passphrase for symetric decryption", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd) + 1);
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd) + 1);
}
symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), salt, 90);
sfree(passphrase);
free(salt);
}
else if(head == PCP_ASYM_CIPHER || head == PCP_ASYM_CIPHER_SIG || head == PCP_ASYM_CIPHER_ANON) {
else if(head == PCP_ASYM_CIPHER || head == PCP_ASYM_CIPHER_SIG
|| head == PCP_ASYM_CIPHER_ANON || head == PCP_ASYM_CIPHER_ANON_SIG) {
/* asymetric mode */
if(useid) {
secret = pcphash_keyexists(ptx, id);
if(secret == NULL) {
fatal(ptx, "Could not find a secret key with id 0x%s in vault %s!\n",
id, vault->filename);
goto errde3;
}
secret = pcphash_keyexists(ptx, id);
if(secret == NULL) {
fatal(ptx, "Could not find a secret key with id 0x%s in vault %s!\n",
id, vault->filename);
goto errde3;
}
}
else {
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
goto errde3;
}
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
goto errde3;
}
}
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errde3;
char *passphrase;
if(passwd == NULL) {
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
if(head == PCP_ASYM_CIPHER_ANON)
anon = 1;
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errde3;
if(head == PCP_ASYM_CIPHER_ANON)
anon = 1;
if(head == PCP_ASYM_CIPHER_SIG)
verify = 1;
if(head == PCP_ASYM_CIPHER_SIG)
verify = 1;
if(head == PCP_ASYM_CIPHER_ANON_SIG) {
anon = 1;
verify = 1;
}
}
else {
@@ -135,6 +139,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
else {
dlen = pcp_decrypt_stream(ptx, pin, pout, NULL, symkey, verify, 0);
sfree(symkey);
symkey = NULL;
}
ps_close(pin);
@@ -151,20 +156,22 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
errde3:
if(symkey != NULL)
free(symkey);
sfree(symkey);
return 1;
}
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor, int anon) {
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd,
plist_t *recipient, int signcrypt, int armor, int anon) {
FILE *in = NULL;
FILE *out = NULL;
pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */
pcp_pubkey_t *tmp = NULL;
pcp_pubkey_t *pub = NULL;
pcp_key_t *secret = NULL;
pcp_key_t *signsecret = NULL;
byte *symkey = NULL;
int symmode = 0;
@@ -173,7 +180,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
symmode = 1;
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
pcp_readpass(ptx, &passphrase,
"Enter passphrase for symetric encryption", "Repeat passphrase", 1, NULL);
}
else {
@@ -194,15 +201,15 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
/* self-encryption: look if its a secret one */
pcp_key_t *s = pcphash_keyexists(ptx, id);
if(s != NULL) {
tmp = pcpkey_pub_from_secret(s);
pub = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(pub, tmp, sizeof(pcp_pubkey_t));
HASH_ADD_STR( pubhash, id, pub);
tmp = pcpkey_pub_from_secret(s);
pub = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(pub, tmp, sizeof(pcp_pubkey_t));
HASH_ADD_STR( pubhash, id, pub);
}
else {
fatal(ptx, "Could not find a public key with id 0x%s in vault %s!\n",
id, vault->filename);
goto erren3;
fatal(ptx, "Could not find a public key with id 0x%s in vault %s!\n",
id, vault->filename);
goto erren3;
}
}
else {
@@ -220,15 +227,15 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
pcphash_iteratepub(ptx, tmp) {
rec = recipient->first;
while (rec != 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, pub);
/* fprintf(stderr, " => found a matching key %s\n", tmp->id); */
}
rec = rec->next;
_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, pub);
/* fprintf(stderr, " => found a matching key %s\n", tmp->id); */
}
rec = rec->next;
}
}
@@ -236,10 +243,10 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
rec = recipient->first;
while (rec != NULL) {
if(strnstr("__self__", rec->value, 13) != NULL) {
pcp_key_t *s = pcp_find_primary_secret();
pcp_pubkey_t *p = pcpkey_pub_from_secret(s);
HASH_ADD_STR( pubhash, id, p);
break;
pcp_key_t *s = pcp_find_primary_secret();
pcp_pubkey_t *p = pcpkey_pub_from_secret(s);
HASH_ADD_STR( pubhash, id, p);
break;
}
rec = rec->next;
}
@@ -253,33 +260,31 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
if(symmode != 1) {
/* we're using a random secret keypair on our side */
if(anon) {
secret = pcpkey_new();
}
else {
if(signcrypt || !anon) {
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
goto erren2;
goto erren2;
}
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto erren2;
char *passphrase;
if(passwd == NULL) {
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto erren2;
signsecret = secret;
}
if(anon)
secret = pcpkey_new();
}
if(infile == NULL)
@@ -315,7 +320,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
sfree(symkey);
}
else {
clen = pcp_encrypt_stream(ptx, pin, pout, secret, pubhash, signcrypt, anon);
clen = pcp_encrypt_stream(ptx, pin, pout, secret, signsecret, pubhash, signcrypt, anon);
}
if(armor == 1) {
@@ -336,7 +341,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
fprintf(stderr, "Encrypted %"FMT_SIZE_T" bytes for:\n", (SIZE_T_CAST)clen);
pcp_pubkey_t *cur, *t;
HASH_ITER(hh, pubhash, cur, t) {
fprintf(stderr, " 0x%s - %s <%s>\n", cur->id, cur->owner, cur->mail);
fprintf(stderr, " 0x%s - %s <%s>\n", cur->id, cur->owner, cur->mail);
}
}
if(signcrypt)
@@ -363,16 +368,10 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
void pcpchecksum(char **files, int filenum, char *key) {
int i;
byte *checksum = ucmalloc(crypto_generichash_BYTES_MAX);
byte *keyhash = NULL;
size_t hashlen = 0;
size_t keylen = 0;
if(key != NULL) {
keyhash = ucmalloc(crypto_generichash_BYTES);
crypto_generichash(keyhash, crypto_generichash_BYTES,
(byte *)key, strlen(key),
NULL, crypto_generichash_BYTES);
hashlen = crypto_generichash_BYTES;
}
if(key != NULL)
keylen = strlen(key);
for(i=0; i<filenum; i++) {
FILE *in;
@@ -382,12 +381,12 @@ void pcpchecksum(char **files, int filenum, char *key) {
}
else {
if((in = fopen(files[i], "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", files[i]);
break;
fatal(ptx, "Could not open input file %s\n", files[i]);
break;
}
}
Pcpstream *pin = ps_new_file(in);
if(pcp_checksum(ptx, pin, checksum, keyhash, hashlen) > 0) {
if(pcp_checksum(ptx, pin, checksum, (byte *)key, keylen) > 0) {
char *hex = _bin2hex(checksum, crypto_generichash_BYTES_MAX);
fprintf(stdout, "BLAKE2b (%s) = %s\n", files[i], hex);
free(hex);
@@ -397,7 +396,4 @@ void pcpchecksum(char **files, int filenum, char *key) {
}
free(checksum);
if(keyhash != NULL)
free(keyhash);
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 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
@@ -25,7 +25,7 @@
char *pcp_getstdin(const char *prompt) {
char line[255];
char *out;
char *out = NULL;
fprintf(stderr, "%s: ", prompt);
@@ -67,36 +67,42 @@ void pcp_keygen(char *passwd) {
pcp_key_t *key = NULL;
char *owner = pcp_getstdin("Enter the name of the key owner");
memcpy(k->owner, owner, strlen(owner) + 1);
if(owner != NULL)
memcpy(k->owner, owner, strlen(owner) + 1);
char *mail = pcp_getstdin("Enter the email address of the key owner");
memcpy(k->mail, _lc(mail), strlen(mail) + 1);
if(mail != NULL)
memcpy(k->mail, _lc(mail), strlen(mail) + 1);
if(debug)
pcp_dumpkey(k);
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
}
else {
passphrase = ucmalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
passphrase = passwd;
}
if(strnlen(passphrase, 1024) > 0)
key = pcpkey_encrypt(ptx, k, passphrase);
else {
char *yes = pcp_getstdin("WARNING: secret key will be stored unencrypted. Are you sure [yes|NO]?");
if(strncmp(yes, "yes", 1024) == 0)
key = k;
else {
memset(key, 0, sizeof(pcp_key_t));
free(key);
goto errkg1;
if(strnlen(passphrase, 1024) > 0) {
double ent = pcp_getentropy(passphrase);
if(ent < 3.32) {
fprintf(stderr, "WARNING: you are using a weak passphrase (entropy: %lf)!\n", ent);
char *yes = pcp_getstdin("Are you sure to use it [yes|NO]?");
if(strncmp(yes, "yes", 1024) != 0) {
goto errkg1;
}
}
key = pcpkey_encrypt(ptx, k, passphrase);
}
else {
/* No unencrypted secret key allowed anymore [19.08.2015, tom] */
memset(k, 0, sizeof(pcp_key_t));
free(k);
goto errkg1;
}
if(key != NULL) {
@@ -108,6 +114,11 @@ void pcp_keygen(char *passwd) {
}
}
if(passwd == NULL) {
/* if passwd is set, it'll be free'd in main() */
sfree(passphrase);
}
errkg1:
free(mail);
free(owner);
@@ -158,7 +169,7 @@ char *pcp_normalize_id(char *keyid) {
if(keyid[0] == '0' && keyid[1] == 'x' && len == 18) {
int i;
for(i=0; i<16; ++i) {
id[i] = keyid[i+2];
id[i] = keyid[i+2];
}
id[16] = 0;
}
@@ -226,24 +237,21 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *pa
if(debug)
pcp_dumpkey(key);
if(key->secret[0] == 0) {
/* decrypt the secret key */
if(passwd == NULL) {
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
key = pcpkey_decrypt(ptx, key, passphrase);
if(key == NULL) {
sfree(passphrase);
goto errexpse1;
}
sfree(passphrase);
if(passwd == NULL) {
char *passphrase;
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
key = pcpkey_decrypt(ptx, key, passphrase);
if(key == NULL) {
sfree(passphrase);
goto errexpse1;
}
else {
key = pcpkey_decrypt(ptx, key, passwd);
if(key == NULL) {
goto errexpse1;
}
sfree(passphrase);
}
else {
key = pcpkey_decrypt(ptx, key, passwd);
if(key == NULL) {
goto errexpse1;
}
}
@@ -254,22 +262,22 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *pa
}
else {
char *passphrase;
pcp_readpass(&passphrase,
pcp_readpass(ptx, &passphrase,
"Enter passphrase to encrypt the exported secret key",
"Repeat passphrase", 1, NULL);
"Repeat passphrase", 1, NULL);
exported_sk = pcp_export_secret(ptx, key, passphrase);
sfree(passphrase);
}
if(exported_sk != NULL) {
if(armor == 1) {
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen, 1);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_SK_HEADER, z85, EXP_SK_FOOTER);
free(z85);
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen, 1);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_SK_HEADER, z85, EXP_SK_FOOTER);
free(z85);
}
else {
fwrite(buffer_get(exported_sk), 1, buffer_size(exported_sk), out);
fwrite(buffer_get(exported_sk), 1, buffer_size(exported_sk), out);
}
buffer_free(exported_sk);
fprintf(stderr, "secret key exported.\n");
@@ -312,13 +320,13 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
/* ok, so, then look for a secret key with that id */
sk = pcphash_keyexists(ptx, keyid);
if(sk == NULL) {
fatal(ptx, "Could not find a key with id 0x%s in vault %s!\n",
keyid, vault->filename);
goto errpcpexpu1;
fatal(ptx, "Could not find a key with id 0x%s in vault %s!\n",
keyid, vault->filename);
goto errpcpexpu1;
}
else {
/* ok, so it's our own key */
is_foreign = 0;
/* ok, so it's our own key */
is_foreign = 0;
}
}
else {
@@ -344,8 +352,8 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
}
else {
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
sk = pcpkey_decrypt(ptx, sk, passphrase);
sfree(passphrase);
}
@@ -359,16 +367,16 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
if(is_foreign == 0) {
exported_pk = pcp_export_rfc_pub(ptx, sk);
if(exported_pk != NULL) {
if(armor == 1) {
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
free(z85);
}
else
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), out);
buffer_free(exported_pk);
fprintf(stderr, "public key exported.\n");
if(armor == 1) {
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
free(z85);
}
else
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), out);
buffer_free(exported_pk);
fprintf(stderr, "public key exported.\n");
}
}
else {
@@ -381,13 +389,13 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
if(is_foreign == 0) {
exported_pk = pcp_export_pbp_pub(sk);
if(exported_pk != NULL) {
/* PBP format requires armoring always */
size_t zlen;
char *z85pbp = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1);
fprintf(out, "%s", z85pbp);
free(z85pbp);
buffer_free(exported_pk);
fprintf(stderr, "public key exported in PBP format.\n");
/* PBP format requires armoring always */
size_t zlen;
char *z85pbp = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1);
fprintf(out, "%s", z85pbp);
free(z85pbp);
buffer_free(exported_pk);
fprintf(stderr, "public key exported in PBP format.\n");
}
}
else {
@@ -407,6 +415,11 @@ void pcpdelete_key(char *keyid) {
if(p != NULL) {
/* delete public */
pcp_keysig_t *sig = pcphash_keysigexists(ptx, keyid);
if(sig != NULL) {
/* also delete associted sig, if any */
pcphash_del(ptx, sig, sig->type);
}
pcphash_del(ptx, p, p->type);
vault->unsafed = 1;
fprintf(stderr, "Public key deleted.\n");
@@ -431,7 +444,7 @@ void pcpedit_key(char *keyid) {
if(key != NULL) {
if(key->secret[0] == 0) {
char *passphrase;
pcp_readpass(&passphrase, "Enter passphrase to decrypt the key", NULL, 1, NULL);
pcp_readpass(ptx, &passphrase, "Enter passphrase to decrypt the key", NULL, 1, NULL);
key = pcpkey_decrypt(ptx, key, passphrase);
sfree(passphrase);
}
@@ -440,63 +453,63 @@ void pcpedit_key(char *keyid) {
fprintf(stderr, "Current owner: %s\n", key->owner);
char *owner = pcp_getstdin(" enter new name or press enter to keep current");
if(strlen(owner) > 0)
memcpy(key->owner, owner, strlen(owner) + 1);
memcpy(key->owner, owner, strlen(owner) + 1);
fprintf(stderr, "Current mail: %s\n", key->mail);
char *mail = pcp_getstdin(" enter new email or press enter to keep current");
if(strlen(mail) > 0)
memcpy(key->mail, mail, strlen(mail) + 1);
memcpy(key->mail, mail, strlen(mail) + 1);
free(owner);
free(mail);
if(key->type != PCP_KEY_TYPE_MAINSECRET) {
pcp_key_t *other = NULL;
uint8_t haveprimary = 0;
pcphash_iterate(ptx, other) {
if(other->type == PCP_KEY_TYPE_MAINSECRET) {
haveprimary = 1;
break;
}
}
pcp_key_t *other = NULL;
uint8_t haveprimary = 0;
pcphash_iterate(ptx, other) {
if(other->type == PCP_KEY_TYPE_MAINSECRET) {
haveprimary = 1;
break;
}
}
char *yes = NULL;
char *yes = NULL;
if(! haveprimary) {
fprintf(stderr, "There is currently no primary secret in your vault,\n");
yes = pcp_getstdin("want to make this one the primary [yes|NO]?");
}
else {
fprintf(stderr, "The key %s is currently the primary secret,\n", other->id);
yes = pcp_getstdin("want to make this one the primary instead [yes|NO]?");
}
fprintf(stderr, "There is currently no primary secret in your vault,\n");
yes = pcp_getstdin("want to make this one the primary [yes|NO]?");
}
else {
fprintf(stderr, "The key %s is currently the primary secret,\n", other->id);
yes = pcp_getstdin("want to make this one the primary instead [yes|NO]?");
}
if(strncmp(yes, "yes", 1024) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET;
if(haveprimary) {
fprintf(stderr, "other type: %d\n", other->type);
other->type = PCP_KEY_TYPE_SECRET;
fprintf(stderr, " new type: %d\n", other->type);
}
}
free(yes);
if(strncmp(yes, "yes", 1024) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET;
if(haveprimary) {
fprintf(stderr, "other type: %d\n", other->type);
other->type = PCP_KEY_TYPE_SECRET;
fprintf(stderr, " new type: %d\n", other->type);
}
}
free(yes);
}
char *passphrase;
pcp_readpass(&passphrase,
"Enter new passphrase for key encryption (press enter to keep current)",
"Enter the passphrase again", 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter new passphrase for key encryption (press enter to keep current)",
"Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) {
key = pcpkey_encrypt(ptx, key, passphrase);
sfree(passphrase);
key = pcpkey_encrypt(ptx, key, passphrase);
sfree(passphrase);
}
if(key != NULL) {
if(debug)
pcp_dumpkey(key);
if(debug)
pcp_dumpkey(key);
vault->unsafed = 1; /* will be safed automatically */
fprintf(stderr, "Key %s changed.\n", key->id);
vault->unsafed = 1; /* will be safed automatically */
fprintf(stderr, "Key %s changed.\n", key->id);
}
}
}
@@ -558,26 +571,26 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
fatals_ifany(ptx);
char *yes = pcp_getstdin("WARNING: signature doesn't verify, import anyway [yes|NO]?");
if(strncmp(yes, "yes", 1024) != 0) {
free(yes);
goto errimp2;
free(yes);
goto errimp2;
}
free(yes);
}
if(pcp_sanitycheck_pub(ptx, pub) == 0) {
if(pcpvault_addkey(ptx, vault, (void *)pub, PCP_KEY_TYPE_PUBLIC) == 0) {
fprintf(stderr, "key 0x%s added to %s.\n", pub->id, vault->filename);
/* avoid double free */
success = 0;
fprintf(stderr, "key 0x%s added to %s.\n", pub->id, vault->filename);
/* avoid double free */
success = 0;
}
else
goto errimp2;
goto errimp2;
if(keysig != NULL) {
if(pcpvault_addkey(ptx, vault, keysig, keysig->type) != 0) {
/* FIXME: remove pubkey if storing the keysig failed */
goto errimp2;
}
if(pcpvault_addkey(ptx, vault, keysig, keysig->type) != 0) {
/* FIXME: remove pubkey if storing the keysig failed */
goto errimp2;
}
}
}
else
@@ -592,8 +605,8 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
}
else {
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase to decrypt the secret key file", NULL, 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt the secret key file", NULL, 1, NULL);
sk = pcp_import_secret(ptx, buf, bufsize, passphrase);
sfree(passphrase);
}
@@ -617,34 +630,34 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
}
else {
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
pcp_readpass(ptx, &passphrase,
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) {
/* encrypt the key */
sk = pcpkey_encrypt(ptx, sk, passphrase);
sfree(passphrase);
/* encrypt the key */
sk = pcpkey_encrypt(ptx, sk, passphrase);
sfree(passphrase);
}
else {
/* ask for confirmation if we shall store it in the clear */
char *yes = pcp_getstdin(
"WARNING: secret key will be stored unencrypted. Are you sure [yes|NO]?");
if(strncmp(yes, "yes", 1024) != 0) {
free(yes);
goto errimp1;
}
free(yes);
/* ask for confirmation if we shall store it in the clear */
char *yes = pcp_getstdin(
"WARNING: secret key will be stored unencrypted. Are you sure [yes|NO]?");
if(strncmp(yes, "yes", 1024) != 0) {
free(yes);
goto errimp1;
}
free(yes);
}
}
if(sk != NULL) {
/* store it to the vault if we got it til here */
if(pcp_sanitycheck_key(ptx, sk) == 0) {
if(pcp_storekey(sk) == 0) {
pcpkey_printshortinfo(sk);
success = 0;
}
if(pcp_storekey(sk) == 0) {
pcpkey_printshortinfo(sk);
success = 0;
}
}
}
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 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
@@ -92,13 +92,13 @@ void pcptext_key(char *keyid) {
pcp_pubkey_t *p = pcphash_pubkeyexists(ptx, keyid);
if(p != NULL) {
if(debug) {
pcp_dumppubkey(p);
pcp_keysig_t *s = pcphash_keysigexists(ptx, keyid);
if(s != NULL) {
printf("\n");
pcp_dumpkeysig(s);
}
printf("\n");
pcp_dumppubkey(p);
pcp_keysig_t *s = pcphash_keysigexists(ptx, keyid);
if(s != NULL) {
printf("\n");
pcp_dumpkeysig(s);
}
printf("\n");
}
pcppubkey_print(p, stdout);
}
@@ -109,64 +109,66 @@ void pcptext_key(char *keyid) {
}
void pcptext_vault(vault_t *vault) {
if(vault != NULL) {
#ifdef HAVE_JSON
if(ptx->json) {
json_t *jout, *jkeys, *jtmp;
char *checksum, *jdump;
pcp_key_t *k;
pcp_pubkey_t *p;
if(ptx->json) {
json_t *jout, *jkeys, *jtmp;
char *checksum, *jdump;
pcp_key_t *k;
pcp_pubkey_t *p;
checksum = _bin2hex(vault->checksum, 32);
jout = json_pack("{sssisssisi}",
"keyvaultfile", vault->filename,
"version", vault->version,
"checksum", checksum,
"secretkeys", pcphash_count(ptx),
"publickey", pcphash_countpub(ptx));
checksum = _bin2hex(vault->checksum, LSHA);
jout = json_pack("{sssisssisi}",
"keyvaultfile" , vault->filename,
"version" , vault->version,
"checksum" , checksum,
"secretkeys" , pcphash_count(ptx),
"publickey" , pcphash_countpub(ptx));
jkeys = json_array();
jkeys = json_array();
pcphash_iterate(ptx, k) {
jtmp = pcp_sk2json(k, NULL, 0);
json_object_set(jtmp, "type", json_string("secret"));
json_array_append(jkeys, jtmp);
pcphash_iterate(ptx, k) {
jtmp = pcp_sk2json(k, NULL, 0);
json_object_set(jtmp, "type", json_string("secret"));
json_array_append(jkeys, jtmp);
}
pcphash_iteratepub(ptx, p) {
jtmp = pcp_pk2json(p);
json_array_append(jkeys, jtmp);
}
json_object_set(jout, "keys", jkeys);
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
printf("%s\n", jdump);
json_decref(jout);
free(jdump);
}
pcphash_iteratepub(ptx, p) {
jtmp = pcp_pk2json(p);
json_array_append(jkeys, jtmp);
}
json_object_set(jout, "keys", jkeys);
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
printf("%s\n", jdump);
json_decref(jout);
free(jdump);
}
else {
else {
#endif
printf(" Key vault: %s\n", vault->filename);
printf("Vault version: %08X\n", vault->version);
printf(" Checksum: ");
printf(" Key vault: %s\n", vault->filename);
printf("Vault version: %08X\n", vault->version);
printf(" Checksum: ");
int i;
for ( i = 0;i <15 ;++i) printf("%02X:",(unsigned int) vault->checksum[i]);
printf("%02X", vault->checksum[15]);
printf("\n ");
for ( i = 16;i <31 ;++i) printf("%02X:",(unsigned int) vault->checksum[i]);
printf("%02X", vault->checksum[31]);
printf("\n");
int i;
for ( i = 0;i <15 ;++i) printf("%02X:",(unsigned int) vault->checksum[i]);
printf("%02X", vault->checksum[15]);
printf("\n ");
for ( i = 16;i <31 ;++i) printf("%02X:",(unsigned int) vault->checksum[i]);
printf("%02X", vault->checksum[31]);
printf("\n");
printf(" Secret keys: %d\n", pcphash_count(ptx));
printf(" Public keys: %d\n", pcphash_countpub(ptx) );
printf(" Secret keys: %d\n", pcphash_count(ptx));
printf(" Public keys: %d\n", pcphash_countpub(ptx) );
#ifdef HAVE_JSON
}
}
#endif
}
}
void pcpkey_printlineinfo(pcp_key_t *key) {
@@ -174,26 +176,26 @@ void pcpkey_printlineinfo(pcp_key_t *key) {
time_t t = (time_t)key->ctime;
c = localtime(&t);
printf("0x%s %s %04d-%02d-%02dT%02d:%02d:%02d %s <%s>\n",
key->id,
(key->type == PCP_KEY_TYPE_MAINSECRET) ? "primary secret" : "secret ",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec,
key->owner, key->mail);
key->id,
(key->type == PCP_KEY_TYPE_MAINSECRET) ? "primary secret" : "secret ",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec,
key->owner, key->mail);
if(ptx->verbose) {
printf(" ");
byte *hash = pcpkey_getchecksum(key);
int i, y;
for(i=0; i<32; i+=4) {
for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) {
printf("%02x", hash[i+y]);
printf("%02x", hash[i+y]);
}
printf(" ");
}
free(hash);
printf("\n encrypted: %s, serial: %08x, version: %d\n",
(key->secret[0] == '\0') ? "yes" : " no",
key->serial, (int)key->version);
(key->secret[0] == '\0') ? "yes" : " no",
key->serial, (int)key->version);
printf("\n");
}
}
@@ -203,35 +205,35 @@ void pcppubkey_printlineinfo(pcp_pubkey_t *key) {
time_t t = (time_t)key->ctime;
c = localtime(&t);
printf("0x%s %s %04d-%02d-%02dT%02d:%02d:%02d %s <%s>\n",
key->id,
(key->valid == 1) ? "valid public " : "public ",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec,
key->owner, key->mail);
key->id,
(key->valid == 1) ? "valid public " : "public ",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec,
key->owner, key->mail);
if(ptx->verbose) {
printf(" ");
byte *hash = pcppubkey_getchecksum(key);
int i, y;
for(i=0; i<32; i+=4) {
for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) {
printf("%02x", hash[i+y]);
printf("%02x", hash[i+y]);
}
printf(" ");
}
free(hash);
printf("\n signed: %s, serial: %08x, version: %d, ",
(key->valid == 1) ? "yes" : " no",
key->serial, (int)key->version);
(key->valid == 1) ? "yes" : " no",
key->serial, (int)key->version);
pcp_keysig_t *sig = pcphash_keysigexists(ptx, key->id);
if(sig != NULL) {
printf("signature fingerprint:\n ");
byte *checksum = sig->checksum;
for(i=0; i<32; i+=4) {
for(y=0; y<4; y++) {
printf("%02x", checksum[i+y]);
}
printf(" ");
for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) {
printf("%02x", checksum[i+y]);
}
printf(" ");
}
printf("\n");
}
@@ -253,7 +255,7 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
jout = pcp_pk2json(key);
json_object_set(jout, "random-art-id", json_string(r));
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
fprintf(out, "%s\n", jdump);
json_decref(jout);
@@ -274,12 +276,12 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
fprintf(out, " Mail: %s\n", key->mail);
fprintf(out, " Key-ID: 0x%s\n", key->id);
fprintf(out, " Public-Key: %s\n", pcp_z85_encode(key->pub, 32, &zlen, 1));
fprintf(out, " Public-Key: %s\n", pcp_z85_encode(key->pub, LBOXPUB, &zlen, 1));
/* 2004-06-14T23:34:30. */
fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec);
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec);
byte *hash = pcppubkey_getchecksum(key);
fprintf(out, " Checksum: ");
@@ -298,10 +300,10 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
size_t rlen = strlen(r);
for (i=0; i<rlen; ++i) {
if(r[i] == '\n') {
fprintf(out, "\n ");
fprintf(out, "\n ");
}
else {
fprintf(out, "%c", r[i]);
fprintf(out, "%c", r[i]);
}
}
fprintf(out, "\n");
@@ -327,7 +329,7 @@ void pcpkey_print(pcp_key_t *key, FILE* out) {
jout = pcp_sk2json(key, NULL, 0);
json_object_set(jout, "type", json_string("secret"));
json_object_set(jout, "random-art-id", json_string(r));
jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER);
fprintf(out, "%s\n", jdump);
json_decref(jout);
@@ -349,8 +351,8 @@ void pcpkey_print(pcp_key_t *key, FILE* out) {
/* 2004-06-14T23:34:30. */
fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n",
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec);
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
c->tm_hour, c->tm_min, c->tm_sec);
fprintf(out, " Serial Number: 0x%08X\n", key->serial);
fprintf(out, " Key Version: 0x%08X\n", key->version);
@@ -359,10 +361,10 @@ void pcpkey_print(pcp_key_t *key, FILE* out) {
size_t rlen = strlen(r);
for (i=0; i<rlen; ++i) {
if(r[i] == '\n') {
fprintf(out, "\n ");
fprintf(out, "\n ");
}
else {
fprintf(out, "%c", r[i]);
fprintf(out, "%c", r[i]);
}
}
fprintf(out, "\n");

545
src/pcp.c
View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
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
@@ -34,7 +34,7 @@ void usage(int error) {
void version() {
fprintf(stderr, "pcp version %d.%d.%d, use --help to learn how to use.\n",
PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
exit(0);
}
@@ -66,6 +66,7 @@ int main (int argc, char **argv) {
char *xpassfile = NULL;
char *extra = NULL;
plist_t *recipient = NULL;
char *askpass = NULL;
FILE *in;
errno = 0;
@@ -93,6 +94,7 @@ int main (int argc, char **argv) {
{ "text", required_argument, NULL, 't' },
{ "xpass", required_argument, NULL, 'x' },
{ "password-file", required_argument, NULL, 'X' },
{ "extpass", required_argument, NULL, LONG_EXTPASS },
{ "recipient", required_argument, NULL, 'r' },
/* key management */
@@ -114,7 +116,7 @@ int main (int argc, char **argv) {
{ "decrypt", no_argument, NULL, 'd' },
{ "anonymous", no_argument, NULL, 'A' },
{ "add-myself", no_argument, NULL, 'M' },
{ "checksum", optional_argument, NULL, 'C' },
{ "checksum", no_argument, NULL, 'C' },
/* encoding */
{ "z85-encode", no_argument, NULL, 'z' },
@@ -136,166 +138,163 @@ int main (int argc, char **argv) {
{ NULL, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcmf:b1F:0KAMX:jC:",
longopts, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcmf:b1F:0KAMX:jC",
longopts, NULL)) != -1) {
switch (opt) {
case 0:
switch(lo) {
case 's':
printf("sign\n");
break;
}
break;
switch(lo) {
case 's':
printf("sign\n");
break;
}
break;
case 'k':
mode += PCP_MODE_KEYGEN;
usevault = 1;
usevault = 1;
break;
case 'L':
ptx->verbose = 1; /* no break by purpose, turn on -l */
case 'l':
mode += PCP_MODE_LISTKEYS;
usevault = 1;
break;
mode += PCP_MODE_LISTKEYS;
usevault = 1;
break;
case 's':
mode += PCP_MODE_EXPORT_SECRET;
usevault = 1;
break;
mode += PCP_MODE_EXPORT_SECRET;
usevault = 1;
break;
case 'p':
mode += PCP_MODE_EXPORT_PUBLIC;
usevault = 1;
break;
mode += PCP_MODE_EXPORT_PUBLIC;
usevault = 1;
break;
case 'K':
mode += PCP_MODE_IMPORT;
usevault = 1;
break;
mode += PCP_MODE_IMPORT;
usevault = 1;
break;
case 'R':
mode += PCP_MODE_DELETE_KEY;
usevault = 1;
break;
mode += PCP_MODE_DELETE_KEY;
usevault = 1;
break;
case 't':
mode += PCP_MODE_TEXT;
usevault = 0;
break;
mode += PCP_MODE_TEXT;
usevault = 0;
break;
case 'E':
mode += PCP_MODE_EDIT;
usevault = 1;
break;
mode += PCP_MODE_EDIT;
usevault = 1;
break;
case 'e':
mode += PCP_MODE_ENCRYPT;
usevault = 1;
break;
mode += PCP_MODE_ENCRYPT;
usevault = 1;
break;
case 'm':
mode += PCP_MODE_ENCRYPT_ME;
break;
mode += PCP_MODE_ENCRYPT_ME;
break;
case 'd':
mode += PCP_MODE_DECRYPT;
usevault = 1;
break;
mode += PCP_MODE_DECRYPT;
usevault = 1;
break;
case 'z':
case 'a':
armor = 1;
break;
armor = 1;
break;
case 'Z':
armor = 2;
break;
armor = 2;
break;
case 'A':
anon = 1;
break;
anon = 1;
break;
case 'F':
if(strncmp(optarg, "pbp", 3) == 0) {
exportformat = EXP_FORMAT_PBP;
}
else if(strncmp(optarg, "pcp", 3) == 0) {
exportformat = EXP_FORMAT_NATIVE;
}
else {
warn("Unknown export format specified, using native\n");
exportformat = EXP_FORMAT_NATIVE;
}
break;
if(strncmp(optarg, "pbp", 3) == 0) {
exportformat = EXP_FORMAT_PBP;
}
else if(strncmp(optarg, "pcp", 3) == 0) {
exportformat = EXP_FORMAT_NATIVE;
}
else {
fprintf(stderr, "WARN: Unknown export format specified, using native\n");
exportformat = EXP_FORMAT_NATIVE;
}
break;
case 'j':
#ifdef HAVE_JSON
ptx->json = 1;
ptx->json = 1;
#else
fprintf(stderr, "WARN: -j set, but no JSON support compiled in. Recompile with --with-json\n");
fprintf(stderr, "WARN: -j set, but no JSON support compiled in. Recompile with --with-json\n");
#endif
break;
break;
case 'g':
mode += PCP_MODE_SIGN;
usevault = 1;
break;
mode += PCP_MODE_SIGN;
usevault = 1;
break;
case 'c':
mode += PCP_MODE_VERIFY;
usevault = 1;
break;
mode += PCP_MODE_VERIFY;
usevault = 1;
break;
case 'C':
mode += PCP_MODE_CHECKSUM;
if(strlen(optarg) > 0 && strncmp(optarg, "--", 3) > 0) {
xpass = smalloc(strlen(optarg)+1);
strncpy(xpass, optarg, strlen(optarg)+1);
}
break;
mode += PCP_MODE_CHECKSUM;
break;
case 'f':
sigfile = ucmalloc(strlen(optarg)+1);
strncpy(sigfile, optarg, strlen(optarg)+1);
detach = 1;
break;
sigfile = ucmalloc(strlen(optarg)+1);
strncpy(sigfile, optarg, strlen(optarg)+1);
detach = 1;
break;
case 'V':
strncpy(vaultfile, optarg, 1024);
break;
strncpy(vaultfile, optarg, 1024);
break;
case 'O':
if(strncmp(optarg, "-", 2) > 0) {
outfile = ucmalloc(strlen(optarg)+1);
strncpy(outfile, optarg, strlen(optarg)+1);
}
break;
if(strncmp(optarg, "-", 2) > 0) {
outfile = ucmalloc(strlen(optarg)+1);
strncpy(outfile, optarg, strlen(optarg)+1);
}
break;
case 'I':
if(strncmp(optarg, "-", 2) > 0) {
infile = ucmalloc(strlen(optarg)+1);
strncpy(infile, optarg, strlen(optarg)+1);
}
break;
if(strncmp(optarg, "-", 2) > 0) {
infile = ucmalloc(strlen(optarg)+1);
strncpy(infile, optarg, strlen(optarg)+1);
}
break;
case 'X':
xpassfile = ucmalloc(strlen(optarg)+1);
strncpy(xpassfile, optarg, strlen(optarg)+1);
xpf = 1;
break;
xpassfile = ucmalloc(strlen(optarg)+1);
strncpy(xpassfile, optarg, strlen(optarg)+1);
xpf = 1;
break;
case 'i':
keyid = ucmalloc(19);
strncpy(keyid, optarg, 19);
useid = 1;
break;
keyid = ucmalloc(19);
strncpy(keyid, optarg, 19);
useid = 1;
break;
case 'x':
xpass = smalloc(strlen(optarg)+1);
strncpy(xpass, optarg, strlen(optarg)+1);
if(strncmp(xpass, "n/a", 3) == 0)
xpass[0] = '\0';
break;
xpass = smalloc(strlen(optarg)+1);
strncpy(xpass, optarg, strlen(optarg)+1);
break;
case LONG_EXTPASS:
askpass = malloc(strlen(optarg)+1);
strncpy(askpass, optarg, strlen(optarg)+1);
break;
case 'r':
p_add(&recipient, optarg);
userec = 1;
break;
p_add(&recipient, optarg);
userec = 1;
break;
case 'M':
p_add_me(&recipient);
userec = 1;
break;
p_add_me(&recipient);
userec = 1;
break;
case 'D':
debug = 1;
break;
debug = 1;
break;
case '0':
version();
version();
case 'v':
ptx->verbose = 1;
break;
ptx->verbose = 1;
break;
case 'h':
usage(0);
usage(0);
default:
usage(1);
usage(1);
}
}
@@ -326,8 +325,6 @@ int main (int argc, char **argv) {
}
sodium_init(); /* FIXME: better called from the lib? */
#ifndef DEBUG
# ifdef HAVE_SETRLIMIT
setrlimit(RLIMIT_CORE, &(struct rlimit) {0, 0});
@@ -352,79 +349,86 @@ int main (int argc, char **argv) {
switch (mode) {
case PCP_MODE_DECRYPT:
if(infile == NULL) {
infile = extra;
useex = 1;
infile = extra;
useex = 1;
}
break;
case PCP_MODE_ENCRYPT:
if(infile == NULL) {
infile = extra;
useex = 1;
infile = extra;
useex = 1;
}
else if(userec == 0 && useid == 0) {
userec = 1;
int i;
for (i=0; i<argc; i++) {
p_add(&recipient, argv[i]);
}
userec = 1;
int i;
for (i=0; i<argc; i++) {
p_add(&recipient, argv[i]);
}
}
break;
case PCP_MODE_IMPORT:
if(infile == NULL) {
infile = extra;
useex = 1;
infile = extra;
useex = 1;
}
break;
case PCP_MODE_EXPORT_SECRET:
case PCP_MODE_EXPORT_PUBLIC:
if(outfile == NULL) {
outfile = extra;
useex = 1;
outfile = extra;
useex = 1;
}
else if(useid == 0 && userec == 0) {
p_add(&recipient, extra);
useex = 1;
userec = 1;
p_add(&recipient, extra);
useex = 1;
userec = 1;
}
break;
case PCP_MODE_VERIFY:
if(infile == NULL) {
infile = extra;
useex = 1;
infile = extra;
useex = 1;
}
else if (useid == 0) {
id = extra;
useid = 1;
useex = 1;
id = extra;
useid = 1;
useex = 1;
}
break;
case PCP_MODE_SIGN:
if(infile == NULL) {
infile = extra;
useex = 1;
infile = extra;
useex = 1;
}
else if(outfile == NULL && detach == 0) {
outfile = extra;
useex = 1;
outfile = extra;
useex = 1;
}
break;
}
if(useex)
if(! useex)
free(extra);
}
if(xpassfile != NULL) {
pcp_readpass(&xpass, "passphrase", NULL, 0, xpassfile);
if(pcp_readpass(ptx, &xpass, "passphrase", NULL, 0, xpassfile) != 0)
goto perr1;
if(xpassfile[0] != '-')
xpf = 0;
free(xpassfile);
}
if(askpass != NULL) {
if(pcp_readpass_fromprog(ptx, &xpass, askpass) != 0)
goto perr1;
}
/* check if there's some enviroment we could use */
if(usevault == 1) {
char *_vaultfile = getenv("PCP_VAULT");
@@ -452,128 +456,128 @@ int main (int argc, char **argv) {
if(vault != NULL) {
switch (mode) {
case PCP_MODE_KEYGEN:
pcp_keygen(xpass);
break;
pcp_keygen(xpass);
break;
case PCP_MODE_LISTKEYS:
pcp_listkeys();
break;
pcp_listkeys();
break;
case PCP_MODE_EXPORT_SECRET:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcp_exportsecret(id, useid, outfile, armor, xpass);
}
}
else {
pcp_exportsecret(NULL, useid, outfile, armor, xpass);
}
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcp_exportsecret(id, useid, outfile, armor, xpass);
}
}
else {
pcp_exportsecret(NULL, useid, outfile, armor, xpass);
}
break;
case PCP_MODE_EXPORT_PUBLIC:
if(useid) {
id = pcp_normalize_id(keyid);
if(id == NULL)
break;
}
pcp_exportpublic(id, xpass, outfile, exportformat, armor);
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id == NULL)
break;
}
pcp_exportpublic(id, xpass, outfile, exportformat, armor);
break;
case PCP_MODE_IMPORT:
if(infile == NULL) {
altin(NULL, xpf);
in = stdin;
}
else {
if((in = fopen(infile, "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", infile);
break;
}
}
pcp_import(vault, in, xpass);
break;
if(infile == NULL) {
altin(NULL, xpf);
in = stdin;
}
else {
if((in = fopen(infile, "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", infile);
break;
}
}
pcp_import(vault, in, xpass);
break;
case PCP_MODE_DELETE_KEY:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpdelete_key(id);
}
}
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n");
}
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpdelete_key(id);
}
}
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n");
}
break;
case PCP_MODE_EDIT:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpedit_key(id);
}
}
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n");
}
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpedit_key(id);
}
}
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n");
}
break;
case PCP_MODE_ENCRYPT:
if(useid == 1 && userec == 0) {
/* one dst, FIXME: make id a list as well */
id = pcp_normalize_id(keyid);
pcpencrypt(id, altin(infile, xpf), outfile, xpass, NULL, signcrypt, armor, anon);
}
else if(useid == 0 && userec == 1) {
/* multiple dst */
pcpencrypt(NULL, altin(infile, xpf), outfile, xpass, recipient, signcrypt, armor, anon);
}
else {
/* -i and -r specified */
fatal(ptx, "You can't specify both -i and -r, use either -i or -r!\n");
}
if(useid == 1 && userec == 0) {
/* one dst, FIXME: make id a list as well */
id = pcp_normalize_id(keyid);
pcpencrypt(id, altin(infile, xpf), outfile, xpass, NULL, signcrypt, armor, anon);
}
else if(useid == 0 && userec == 1) {
/* multiple dst */
pcpencrypt(NULL, altin(infile, xpf), outfile, xpass, recipient, signcrypt, armor, anon);
}
else {
/* -i and -r specified */
fatal(ptx, "You can't specify both -i and -r, use either -i or -r!\n");
}
break;
break;
case PCP_MODE_DECRYPT:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpdecrypt(id, useid, altin(infile, xpf), outfile, xpass, signcrypt);
}
}
else {
pcpdecrypt(NULL, useid, altin(infile, xpf), outfile, xpass, signcrypt);
}
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpdecrypt(id, useid, altin(infile, xpf), outfile, xpass, signcrypt);
}
}
else {
pcpdecrypt(NULL, useid, altin(infile, xpf), outfile, xpass, signcrypt);
}
break;
case PCP_MODE_SIGN:
if(detach) {
if(outfile != NULL && sigfile != NULL)
fatal(ptx, "You can't both specify -O and -f, use -O for std signatures and -f for detached ones\n");
else
pcpsign(altin(infile, xpf), sigfile, xpass, armor, detach);
}
else
pcpsign(altin(infile, xpf), outfile, xpass, armor, detach);
break;
if(detach) {
if(outfile != NULL && sigfile != NULL)
fatal(ptx, "You can't both specify -O and -f, use -O for std signatures and -f for detached ones\n");
else
pcpsign(altin(infile, xpf), sigfile, xpass, armor, detach);
}
else
pcpsign(altin(infile, xpf), outfile, xpass, armor, detach);
break;
case PCP_MODE_VERIFY:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpverify(altin(infile, xpf), sigfile, id, detach);
}
}
else {
pcpverify(altin(infile, xpf), sigfile, NULL, detach);
}
break;
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpverify(altin(infile, xpf), sigfile, id, detach);
}
}
else {
pcpverify(altin(infile, xpf), sigfile, NULL, detach);
}
break;
default:
/* */
goto ELSEMODE;
break;
/* */
goto ELSEMODE;
break;
}
pcpvault_close(ptx, vault);
}
@@ -595,37 +599,37 @@ int main (int argc, char **argv) {
case PCP_MODE_TEXT:
if(infile != NULL) {
pcptext_infile(infile);
pcptext_infile(infile);
}
else {
vault = pcpvault_init(ptx, vaultfile);
if(! useid && infile == NULL) {
pcptext_vault(vault);
}
else {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcptext_key(id);
}
}
pcpvault_close(ptx, vault);
vault = pcpvault_init(ptx, vaultfile);
if(! useid && infile == NULL) {
pcptext_vault(vault);
}
else {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcptext_key(id);
}
}
pcpvault_close(ptx, vault);
}
break;
case PCP_MODE_CHECKSUM:
if(infile == NULL) {
if(argc == 0) {
char *list[1];
list[0] = NULL;
pcpchecksum(list, 1, xpass);
}
else {
pcpchecksum(argv, argc, xpass);
}
if(argc == 0) {
char *list[1];
list[0] = NULL;
pcpchecksum(list, 1, xpass);
}
else {
pcpchecksum(argv, argc, xpass);
}
}
else {
char *list[1];
list[0] = infile;
pcpchecksum(list, 1, xpass);
char *list[1];
list[0] = infile;
pcpchecksum(list, 1, xpass);
}
break;
@@ -635,7 +639,8 @@ int main (int argc, char **argv) {
break;
}
}
perr1:
fatals_ifany(ptx);
int e = ptx->pcp_exit;
ptx_clean(ptx);
@@ -650,6 +655,10 @@ int main (int argc, char **argv) {
free(sigfile);
if(xpass != NULL)
sfree(xpass);
if(askpass != NULL)
free(askpass);
if(xpassfile != NULL)
free(xpassfile);
if(recipient != NULL)
p_clean(recipient);
if(id != NULL)

View File

@@ -85,6 +85,8 @@
#define PCP_HELP_INTRO "This is Pretty Curved Privacy. Licensed under the GPLv3. This is\n" \
"BETA software. Use with care. NOT intended for production use.\n"
#define LONG_EXTPASS 515
/* some globals */
vault_t *vault;
PCPCTX *ptx;

View File

@@ -1,156 +0,0 @@
/*-
* Copyright 2009 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "readpass.h"
/**
* tarsnap_getpass(passwd, prompt, confirmprompt, devtty)
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
* not, read from stdin. If reading from a tty (either /dev/tty or stdin),
* disable echo and prompt the user by printing ${prompt} to stderr. If
* ${confirmprompt} is non-NULL, read a second password (prompting if a
* terminal is being used) and repeat until the user enters the same password
* twice. Return the password as a malloced NUL-terminated string via
* ${passwd}. The obscure name is to avoid namespace collisions due to the
* getpass / readpass / readpassphrase / etc. functions in various libraries.
*/
int
pcp_readpass(char ** passwd, const char * prompt,
const char * confirmprompt, int devtty, char *readfromfile)
{
FILE * readfrom;
char passbuf[MAXPASSLEN];
char confpassbuf[MAXPASSLEN];
struct termios term, term_old;
int usingtty;
/*
* If devtty != 0, try to open /dev/tty; if that fails, or if devtty
* is zero, we'll read the password from stdin instead.
*
* Added by tlinden: however, if readfromfile is defined, we'll
* read the password from there, but if it is '-' we'll use stdin
* as well.
*/
if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) {
if(readfromfile != NULL) {
if(readfromfile[0] == '-') {
readfrom = stdin;
}
else {
if((readfrom = fopen(readfromfile, "r")) == NULL) {
fatal(ptx, "Could not open password file '%s'\n", readfromfile);
goto err1;
}
}
}
else {
readfrom = stdin;
}
}
/* If we're reading from a terminal, try to disable echo. */
if ((usingtty = isatty(fileno(readfrom))) != 0) {
if (tcgetattr(fileno(readfrom), &term_old)) {
fatal(ptx, "Cannot read terminal settings\n");
goto err1;
}
memcpy(&term, &term_old, sizeof(struct termios));
term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
fatal(ptx, "Cannot set terminal settings\n");
goto err1;
}
}
retry:
/* If we have a terminal, prompt the user to enter the password. */
if (usingtty)
fprintf(stderr, "%s: ", prompt);
/* Read the password. */
if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
fatal(ptx, "Cannot read password\n");
goto err2;
}
/* Confirm the password if necessary. */
if (confirmprompt != NULL) {
if (usingtty)
fprintf(stderr, "%s: ", confirmprompt);
if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
fatal(ptx, "Cannot read password\n");
goto err2;
}
if (strcmp(passbuf, confpassbuf)) {
fprintf(stderr,
"Passwords mismatch, please try again\n");
goto retry;
}
}
/* Terminate the string at the first "\r" or "\n" (if any). */
passbuf[strcspn(passbuf, "\r\n")] = '\0';
/* If we changed terminal settings, reset them. */
if (usingtty)
tcsetattr(fileno(readfrom), TCSANOW, &term_old);
/* Close /dev/tty if we opened it.
if readfromfile is defined and set to -, disable stdin */
if (readfrom != stdin) {
fclose(readfrom);
}
else {
if(readfromfile != NULL)
stdin = NULL;
}
/* Copy the password out. */
char *p = smalloc(strlen(passbuf) + 1);
memcpy(p, passbuf, strlen(passbuf) + 1 );
*passwd = p;
/* Zero any stored passwords. */
memset(passbuf, 0, MAXPASSLEN);
memset(confpassbuf, 0, MAXPASSLEN);
/* Success! */
return (0);
err2:
/* Reset terminal settings if necessary. */
if (usingtty)
tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
err1:
/* Close /dev/tty if we opened it. */
if (readfrom != stdin)
fclose(readfrom);
/* Failure! */
return (-1);
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
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
@@ -54,23 +54,20 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach) {
}
}
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errs1;
char *passphrase;
if(passwd == NULL) {
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errs1;
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);

View File

@@ -16,7 +16,10 @@
"-V --vault <vaultfile> Specify an alternate vault file.\n" \
"-O --outfile <file> Output file. STDOUT if unspecified.\n" \
"-I --infile <file> Input file. STDIN if unspecified.\n" \
"-x --xpass <passwd> Provide password. INSECURE! Use for testing\n" \
" or debugging only!\n" \
"-X --password-file <file> Read passphrase from <file>.\n" \
" --extpass <program> Use external program for password prompt.\n" \
"-i --keyid <id> Specify a key id for various operations.\n" \
"-r --recipient <string> Specify a recpipient, multiple allowed.\n" \
"-t --text Print textual representation of ojects.\n" \
@@ -51,7 +54,8 @@
"-a --armor --textmode same as -z\n" \
"\n" \
"Misc Options:\n" \
"-C --checksum [<key>] calculate a Blake2 checksum of one or more files.\n" \
"-C --checksum calculate a Blake2 checksum of one or more files.\n" \
" add -x <key> to compute an authenticated hash.\n" \
"\n" \
"Arguments:\n" \
"Extra arguments after options are treated as filenames or\n" \

View File

@@ -14,7 +14,10 @@ General Options:
-V --vault <vaultfile> Specify an alternate vault file.
-O --outfile <file> Output file. STDOUT if unspecified.
-I --infile <file> Input file. STDIN if unspecified.
-x --xpass <passwd> Provide password. INSECURE! Use for testing
or debugging only!
-X --password-file <file> Read passphrase from <file>.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id for various operations.
-r --recipient <string> Specify a recpipient, multiple allowed.
-t --text Print textual representation of ojects.
@@ -49,7 +52,8 @@ Encoding Options:
-a --armor --textmode same as -z
Misc Options:
-C --checksum [<key>] calculate a Blake2 checksum of one or more files.
-C --checksum calculate a Blake2 checksum of one or more files.
add -x <key> to compute an authenticated hash.
Arguments:
Extra arguments after options are treated as filenames or

View File

@@ -28,7 +28,7 @@ if BUILDJSON
MAYJSON=jsontest
endif
AM_CFLAGS = -I../include/pcp -I../src -I../libpcp/scrypt/crypto
AM_CFLAGS = -I../include/pcp -I../src
check_PROGRAMS = invalidkeys gencheader statictest $(CPPTEST) \
buffertest sample streamtest pipetest decodertest mangle
@@ -68,7 +68,7 @@ mangle_LDADD =
mangle_SOURCES = mangle.c
invalidkeys_LDADD = ../libpcp/.libs/libpcp1.a \
../src/keyprint.o ../src/keymgmt.o ../src/readpass.o
../src/keyprint.o ../src/keymgmt.o
invalidkeys_SOURCES = invalidkeys.c
if BUILDCPP
@@ -94,21 +94,21 @@ test: check ctest $(MAYPY) $(MAYCPP) $(MAYJSON)
ctest:
rm -f test* v* stresstest/*
./unittests.pl unittests.cfg $(CHECK)
./unittests.sh unittests.cfg $(CHECK)
@echo "To run a single test only, type: 'make test CHECK=testname'"
pytest:
./unittests.pl pyunittests.cfg $(CHECK)
./unittests.sh pyunittests.cfg $(CHECK)
docpptest:
./unittests.pl cppunittests.cfg $(CHECK)
./unittests.sh cppunittests.cfg $(CHECK)
jsontest:
./unittests.pl jsonunittests.cfg $(CHECK)
./unittests.sh jsonunittests.cfg $(CHECK)
stresstest: check
./unittests.pl stresstests.cfg
./unittests.sh stresstests.cfg
iotest: check
./unittests.pl iotests.cfg
./unittests.sh iotests.cfg
sudo umount -f env

View File

@@ -1,9 +1,9 @@
----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----
1][S6097-%&#]c=V(%sWNt}-r6LMx$@@an<T6mz>3&K8{65fN}tfPsN+9oKbfm9/=PXA{S^
la=*sAv38NRiJO0aJS4rmx?mypA$TROMAp>vnWxqulxBM?Zyz@u[Noobvdm/Jwj%bo^9)00
0080SSi2097-%&@x5V2M>5b0037krBV1e00&(h000125(&Aw000Gy00SAaB7GxavqGsKG}e
hz01xRx1POWzCwZ#jlsB[R0000i6Awmo3t<i=y*{*[Bu<UXv{%fN0003s0dgX9k.t1Y4]E.
wJqps<VO=l+TY?Cn*FU72QK@@o*Qy]-cSK>[B}O^{C#D)!/>X^8XOnk&j2YmXVJ.{X2bXp[
YQ(E[Fgaa2UFf>x&j1=9e.nNOhhE13iI2CiHS=PRD.0YP2c$wabl3.ATFlqe8Zriz*trfz8
+%^.mf0q/ek(&S
1][S609x+qRxIc%9DnX1G9dD]Jg]@^u9pUFfzF>xqfpgkuQ}++S$?MWJTUdh(q+bJ>M3a9A
7Px8mj54K:64SP+]cM6&/GjCnK8m/eFPwybe:L=}co-}W>sKdCquHXZPlmg{5$Esbo^9)00
0080SSi209x+qRt{O@2M>5b003f>KTp5d00&(h00014[r23$000Gy00SAaB7GxavqLB5nRc
{x01xRx1POWzCwZ#jlsB[R0000i6Awmo3t<i=y*{*[Bu<UXv{%fN0003s0c)0/=73jW2XhD
:x71TdA*:km]lgxS/]u()mP[i%sbr90kLxIiD%hmTRPQXwVn+E-(Zu6MHkO+hfoC$i3aG=:
uP)YsgY/hv/{HE*w)Qsh0r=j-WLGtZrQZ+[}Ih#c}>>&iM!Wk=*K^mMI4ZBtM^MBnIM^uU9
k.ZF6951jUlqJv
----- END ED25519-CURVE29915 PUBLIC KEY -----

View File

@@ -65,10 +65,10 @@ void test0() {
DECRYPTED = _openrd("testcppdecrypted", CA);
char *got = (char *)ucmalloc(10);
if(fread(got, 1, 6, DECRYPTED) < 6) {
throw pcp::exception(CA, "read error, could not read decrypted content");
throw pcp::exception(CA, "read error, could not read decrypted content");
}
if(strncmp(got, "HALLO", 5) != 0) {
throw pcp::exception(CA);
throw pcp::exception(CA);
}
free(got);
}
@@ -173,7 +173,6 @@ void test4() {
}
int main(int argc, char **argv) {
sodium_init();
PcpContext *ptx = new PcpContext();
try {

View File

@@ -1,26 +1,37 @@
# -*-sh-*-
#
# test the c++ api
<test check-cpp-crypto>
cmd = ./cpptest 0
expect = /ok/
</test>
<test check-cpp-vault>
cmd = ./cpptest 1
expect = /ok/
</test>
check_cpp_crypto () {
cmd="./cpptest 0"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test check-cpp-import-pub>
cmd = ./cpptest 2
expect = /ok/
</test>
check_cpp_vault () {
cmd="./cpptest 1"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test check-cpp-signature>
cmd = ./cpptest 3
expect = /ok/
</test>
check_cpp_import_pub () {
cmd="./cpptest 2"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test check-buffer>
cmd = ./cpptest 4
expect = /ok/
</test>
check_cpp_signature () {
cmd="./cpptest 3"
expect=/ok/
check "$cmd" "$expect" "$input"
}
check_buffer () {
cmd="./cpptest 4"
expect=/ok/
check "$cmd" "$expect" "$input"
}
prepare () {
:
}

View File

@@ -118,22 +118,22 @@ int main(int argc, char **argv) {
back = pcp_z85_decode(ptx, raw, &zlen);
if(back == NULL) {
if(mode > 3) {
/* expected fail */
ret = TRUE;
/* expected fail */
ret = TRUE;
}
else {
/* expected ok */
ret = FALSE;
/* expected ok */
ret = FALSE;
}
}
else {
if(mode > 3) {
/* expected fail */
ret = FALSE;
/* expected fail */
ret = FALSE;
}
else {
/* expected ok */
ret = TRUE;
/* expected ok */
ret = TRUE;
}
}
}
@@ -143,7 +143,7 @@ int main(int argc, char **argv) {
if(mode <= 3 && memcmp(back, clear, 256) != 0) {
ret = FALSE;
if(ptx->pcp_errset == 0) {
fatal(ptx, "decoded content doesn't match\n");
fatal(ptx, "decoded content doesn't match\n");
}
}
}

View File

@@ -12,7 +12,7 @@ void pr(char *var, unsigned char *d, size_t len) {
}
int main() {
sodium_init();
if(sodium_init() == -1) return 1;
pcp_key_t *a = pcpkey_new();
pcp_key_t *b = pcpkey_new();

View File

@@ -12,7 +12,7 @@ gen() {
pub=$5
sec=$6
(echo $owner; echo $mail) | $pcp -V vxxx$owner -k -x $pass > /dev/null 2>&1
(echo $owner; echo $mail; echo yes) | $pcp -V vxxx$owner -k -x $pass > /dev/null 2>&1
id=`$pcp -V vxxx$owner -l | grep $owner | awk '{print $1}'`
@@ -41,14 +41,14 @@ ser=`$pcp -V vxxxBart -t -i $ids | grep Serial | awk '{print $3}'`
gen Niemand niemand@local n y unknown1 unknown2
$pcp1 -V unknown3 -l
echo hallo | $pcp -e -x a -z | egrep -v "^ " | egrep -v -- "----" | grep . > unknown4
echo blah | $pcp -g -x a | egrep -v "^ " | egrep -v -- "----" | grep . > unknown5
echo blah | $pcp -V vxxxBart -g -x a | egrep -v "^ " | egrep -v -- "----" | grep . > unknown5
echo "bartid = $ids
bartserial = $ser
idbobby = $idb
idalicia = $ida
mailbobby = bobby@local
mailalicia = alicia@local" > keys.cfg
echo "bartid=$ids
bartserial=$ser
idbobby=$idb
idalicia=$ida
mailbobby=bobby@local
mailalicia=alicia@local" > keys.cfg
./gencheader > static.h

View File

@@ -10,7 +10,7 @@ int main() {
strcpy(o, "xxxx");
strcpy(m, "xxxx");
sodium_init();
if(sodium_init() == -1) return 1;
PCPCTX *ptx = ptx_new();
pcp_key_t *k = pcpkey_new ();

View File

@@ -1,8 +1,8 @@
# -*-html-*-
# -*-sh-*-
#
# This file is part of Pretty Curved Privacy (pcp1).
#
# Copyright (C) 2013 T.Linden.
# Copyright (C) 2013-2016 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
@@ -20,27 +20,29 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
pcp = ../src/pcp1
vault = v1
passwd = xxx
md5msg = 66b8c4ca9e5d2a7e3c0559c3cdea3d50
pcp=../src/pcp1
vault=v1
passwd=xxx
md5msg=66b8c4ca9e5d2a7e3c0559c3cdea3d50
include keys.cfg
. ./keys.cfg
<test check-dependencies>
<test check-dependencies-shell>
cmd = which mdmfs
expect = /mdmfs/
</test>
<test check-dependencies-pcp>
cmd = ls $pcp
expect = /pcp/
</test>
</test>
check_dependencies_shell () {
cmd="which mdmfs"
expect="/mdmfs/"
check "$cmd" "$expect" "$input"
}
check_dependencies_pcp () {
cmd="ls $pcp"
expect="/pcp/"
check "$cmd" "$expect" "$input"
}
# this one only works on freebsd for my user. sorrry
<test check-vault-disk-full>
prepare = sudo mdmfs -s 1M -w 1001:1001 md env && dd if=/dev/zero of=env/b bs=1024 count=700
cmd = ./jot 100 | while read N; do if ! (echo a; echo b) | $pcp -V env/v1 -k -x x; then break; fi; done
expect = /Failed to copy/
</test>
check_vault_disk_full () {
sudo mdmfs -s 1M -w 1001:1001 md env && dd if=/dev/zero of=env/b bs=1024 count=700
cmd="./jot 100 | while read N; do if ! (echo a; echo b) | $pcp -V env/v1 -k -x x; then break; fi; done"
expect="/Failed to copy/"
check "$cmd" "$expect" "$input"
}

View File

@@ -1,4 +1,4 @@
# -*-html-*-
# -*-sh-*-
#
# This file is part of Pretty Curved Privacy (pcp1).
#
@@ -20,66 +20,82 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
pcp = ../src/pcp1
passwd = xxx
verbose = 1
include keys.cfg
pcp=../src/pcp1
passwd=xxx
verbose=1
<test vja>
prepare = rm -f vja; $pcp -V vja -K -I key-alicia-sec -x a
<test check-json-export-public>
cmd = $pcp -V vja -p -j -x a -O testkeyvjapub.json
expect-file testkeyvjapub.json
</test>
<test check-json-export-public-isjson>
cmd = cat testkeyvjapub.json
expect = /"Alicia"/
</test>
<test check-json-export-secret>
cmd = $pcp -V vja -s -j -x a -O testkeyvjasec.json
expect-file testkeyvjasec.json
</test>
<test check-json-export-secret-isjson>
cmd = cat testkeyvjasec.json
expect = /"Alicia"/
</test>
</test>
. ./keys.cfg
<test vjb>
prepare = rm -f vjb; $pcp -V vjb -K -I key-bobby-sec -x b
<test check-json-import-public>
cmd = $pcp -V vjb -K -I testkeyvjapub.json -j
expect /added/
</test>
<test check-json-import-public-open>
cmd = $pcp -V vjb -l
expect = /Alicia/
</test>
</test>
check_json_support () {
cmd="$pcp -V vja -t -j"
expect="\"keyvaultfile\""
check "$cmd" "$expect"
}
<test vjc>
prepare = rm -f vjc
<test check-json-import-secret>
cmd = $pcp -V vjc -K -I testkeyvjasec.json -x a -j
expect = /added/
</test>
<test check-json-import-secret-open>
cmd = $pcp -V vjc -l
expect = /Alicia/
</test>
</test>
check_json_export_public () {
cmd="$pcp -V vja -p -j -x a -O testkeyvjapub.json"
expectfile="testkeyvjapub.json"
expect="/\"Alicia\"/"
check "$cmd" "$expect" "$input" "$expectfile"
}
<test vjtxt>
<test check-json-text-vault>
cmd = $pcp -V vjb -t -j
expect = /"Alicia"/
</test>
<test check-json-text-public>
cmd = $pcp -V vjb -t -j -i ${idalicia}
expect = /"Alicia"/
</test>
<test check-json-text-secret>
cmd = $pcp -V vjb -t -j -i ${idbobby}
expect = /"Bobby"/
</test>
</test>
check_json_export_secret () {
cmd="$pcp -V vja -s -j -x a -O testkeyvjasec.json"
expectfile="testkeyvjasec.json"
check "$cmd" "$expect" "$input" "$expectfile"
}
check_json_export_secret_isjson () {
cmd="cat testkeyvjasec.json"
expect="/\"Alicia\"/"
check "$cmd" "$expect" "$input" ""
}
check_json_import_public () {
cmd="$pcp -V vjb -K -I testkeyvjapub.json -j"
expect="/added/"
check "$cmd" "$expect" "$input" ""
}
check_json_import_public_open () {
cmd="$pcp -V vjb -l"
expect="/Alicia/"
check "$cmd" "$expect" "$input" ""
}
check_json_import_secret () {
cmd="$pcp -V vjc -K -I testkeyvjasec.json -x a -j"
expect="/added/"
check "$cmd" "$expect" "$input" ""
}
check_json_import_secret_open () {
cmd="$pcp -V vjc -l"
expect="/Alicia/"
check "$cmd" "$expect" "$input" ""
}
check_json_text_vault () {
cmd="$pcp -V vjb -t -j"
expect="/\"Alicia\"/"
check "$cmd" "$expect" "$input" ""
}
check_json_text_public () {
cmd="$pcp -V vjb -t -j -i ${idalicia}"
expect="/\"Alicia\"/"
check "$cmd" "$expect" "$input" ""
}
check_json_text_secret () {
cmd="$pcp -V vjb -t -j -i ${idbobby}"
expect="/\"Bobby\"/"
check "$cmd" "$expect" "$input" ""
}
prepare () {
rm -f vja; $pcp -V vja -K -I key-alicia-sec -x a
rm -f vjb; $pcp -V vjb -K -I key-bobby-sec -x b
rm -f vjc
}

View File

@@ -1,9 +1,9 @@
----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----
1][S6097-%&#$gM?n.Qw]CtmmZ)(d5)^&#x)F*^2UDWe3ojbSby>gHT?EUjk&pI3cxE*gE*
R=K^->HL{Y*A**S:A($8dtQsZI:TI01m@D6l3U^%1sZjSCbM+IT[.CVMalMW*&AXbo^9)00
0080SSi2097-%&@x5V2M>5b0037krBV1e00&(h000125(&Aw000Gy00SAaB7GxavqK5azs^
/d01P+z1PO:BCwZ#jl2pmBx<*#w02caE1on<EvqfK^y?Wx[vl!TEv{%fN0003s0kNeq4oyJ
%r{ezyIoB(@YnLW$d64oZtgGiBE]1c[{@U#ssHEGm6wh7=sO1&PM?Gs%%mD4([^xGwyWQF]
4nC!>Hp>0=^)$.G5d:Ls***6SV1E(Zp1iSY59=}{.(N)q6gTYN33<i!*f]vWzFhl9n0KzZe
*B.6=&Q.Puh%%9[uTkt
1][S609x+qQ-(kd8DED3XEIrP&J96/y99g&c^p0l][]}UA%YiLE:OPOGh?71^bvw8w*87p]
3L)VPMa^#./nM(f<>&Pj8PzOKTstm)aqb$?ew82dt(&$OzHBSo5uT#oi5=O+RYzybo^9)00
0080SSi209x+qQYpw{2M>5b003f>KT6]b00&(h00014[r1%@000Gy00SAaB7GxavqDG?u:{
7o01P+z1PO:BCwZ#jl2pmBx<*#w02caE1on<EvqfK^y?Wx[vl!TEv{%fN0003s0iA)Wt$e1
=?mR07>8Mju*T#GhLDD)lQXO56z96SjccXzrP90/n^t-BkO!84sa=Lua?^umsV!NB&5FnDN
0rwgV7J(4$9Vz.tBkR955h6!P7Ho4FV(21)jCI:a(jc6%MaMdArLsFy6Gp0.&(cwLePK</7
yXS-z]Ao8li3#=cncUE
----- END ED25519-CURVE29915 PUBLIC KEY -----

View File

@@ -1,8 +1,8 @@
----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----
&xDEz1XK>dFo{10qP!ibe28hORn6ZEi1qc=oPF4<7Ci>Cd^eLqL42nhv/H:Yv<hu#5:x(a1
Ykg20+K2s]!!^W^0@^6J0)a!/<Lx@duF8]sU*S?[(ZdExqiPYco0xzgt/[Fs&)rJV#ySF%d
NHTbN@GPI1GZkX<I)(iCBe{5XSF.4b+&5vdLDmTh]j=>6#%e3fe?#*LLl6yt%n7CIdVR1a!
h/]p%UYSHekL{T/^S:<(0Kpie=oBQED#M1gpf0O7l}e6au!sk<DZd*@}Ndvp^H{symo{4@I
lqhs&Qvhg(YTR6!p^bti)Kq=)pR%Pqz9Pys}h(S3gj8#&piWQ@)x8/[HaB$9-AO<R1Feo@C
Mn9e2WSi$?lFHkb:tpwn7F6UUjmg9pUJ9Y.U4:aV^=!?jdu<:b%9esKvk]b.CKtChXPQpv
e-4xmz*C3SQoFQBCCJ:.T4Ia9H+oNREO@o^5ThnA2vTdQ{j+^7EGNWHfUY9A)=dN)PYq2}H
C>nwkbzSPB^Hgp?q+]dCG+I$1oGx9zH^.hY!y?LF^x=n/OML7D{5:D?JG<msxt/NrgWcuW+
s$PLGu3dI[806vQSH>%d:eEtg?)%C<I1.o9LU%(zU[=YP=@Wq[{adQ$hX[r%*R%f+o+@>pu
P:t@oPeFjI[i:u6/xa)nOHQp5yO+Rc5{rT7)[W1NY(qO+[:Q5b>f?mM:2V1qvWg*5}HlE7#
-O&snMqV=5Am5G*qR3>$A(n@<IZ.7jM-/pgbYCaagsOt!G5%JUB-x=r+LmbpFfk=6d&gUS8
dw@uCornt5D%)H(po)^YI:z{Jk#^/KL(gXUvJT%rNt%F@Q(EbqP(0s@ZWV[Yy-9iM@lsya
----- END ED25519-CURVE29915 PRIVATE KEY -----

View File

@@ -1,9 +1,9 @@
----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----
1][S6097-%&#}QgWB7(bso^-@]H&)M*?I88J7z<M7bxi$[Y8KjKTwRx]^D>wQhA%%EbhlBZ
LmNh1=03<0>3Sor8?vo2poRSNJukSM*v2^mDWoW:(!Q+/2:3p7i>^Gt$yR7L4$7ubo^9)00
0080SSi2097-%&@x5V2M>5b0037krBV1e00&(h000125(&Aw000Gy00SAaB7GxavqDv=Fk3
1z01GXy1POZACwZ#jlt{sxC(N*A6bgAH01iTLx(4l%vQ:QFy&r/(yYBCn0uh3]inVjYs)@0
geL6aUo^iV<eszj.BK:#y]:?&t@-!s^vEun#B>}S}[7Nd23jb9v.*Bd:IEStfX4QUzFrf>*
CIXx@Y(Xt.j+.q$WkU1(&h4<.@-tC0iNYZBwUH^^Bl{Jr1LV<c^zh[C+FO7LUy7SGZ4oKK+
9ebp]03EvZ{CG<
1][S609x+qR6dE.IeI(!Rduv(e9)NwJdQqu=aCB:gDwXwSmOf7vJd$@f0/Xs*F$8itnVT{I
JBeXzrN{{PlHJ9}yoTRTCmi?7L2*>JdvvU.OvbC</=p7HC#.mpLz>UeFSJitTwDkbo^9)00
0080SSi209x+qR2QF}2M>5b003f>KTf#c00&(h00014[r20%000Gy00SAaB7GxavqEgb^wl
*y01GXy1POZACwZ#jlt{sxC(N*A6bgAH01iTLx(4l%vQ:QFy&r/(yYBCn0uh3ltC%F5sw[U
Cnbd.0=Io(LFZrVB(X9{w799o#[1#/<S-(Ex?RJfbSM7H+0^bj%R5&DGFeiF@oWojQmjnND
f.B[WGUh9PiGIp.v[vi8rGwM<)Ukcw{(wz1(mr./[L:f&&2v*&tgssbZi==rbWHI!+jH:{Q
{rDf0cT}l(sC[P
----- END ED25519-CURVE29915 PUBLIC KEY -----

View File

@@ -1,8 +1,8 @@
----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----
sR$x!+Q+gdp>NvV]$zhGa)Wol.+mx1slD]$5Z&En}WJ.x+R2=^HzEhD0Z0Qk0$tH7BXo00b
[w}x6>)nWlm7zG1U]hUt<L030+A/Sc/-SvT53<MkRYgYu(JG:8G(z#-yoIb5n4$t7K=SGq-
KGlV[gV#4![&u0GDS%JE>h-k7dJ71e3G#pOPZruZJx}0$&It<=h*o8}i:^C7[$rP-<yDkVm
NiNVb<AEym]8U8dkycAfiaCVlIUtsQTnd2%yZil57mrjk:G]F(-V/NvfeYoaiQAxXpSnB<4
L)x9XygJu!(R0T!2HYv<$QE%P+F7pw-/{F])[HdUAnQS-.sh.QGpZZDR>DlWBNj3Iey28l%
A<rn0djBxIOfMb01{!8pg^E@sI+1}G+tEaMAx$1wt(LcuV%Ox1<a[CD5S&@e{k$<B
LVl&7.k8{]0<rQNtI$hG8]eJu&f#*hRbs6W+6(%NY#^O*]3Fkd13.*WY:kf0G]#D%}0ZY9{
5E=R2SFi#UQ(A/dI6:xnZ$D:ryCT18C)WLTpqJ=em):q-J@x<G[5GF(-)xt3uW#d?5![2ag
F>i&6+OSsB.*}1AABfG!G]4[{a*qjiPU.X]cxq2i^Ug(R)H8<l}TuIU1-?!kQU#>^>/R)sH
OEsLh1T-?-sf.6/e<WpD+Bc)*NqMHT}4Db(Ijn+Bqf<CjRpfVTEJw-rQuGx{a/<-[Iw^fh0
bKI5lp8a#m2]-sn6[[^>mb2ImGPK}$8v-k62a75nHd6X7FUtFJNQ1zG{HFiWKq=wu(Uu@V$
!#lX[(i.9WVjP{O2Vd^E-t7:3jh?e(H1TcnfoKGMrtkqDrhae>.1x3}<&q%Rr@or9
----- END ED25519-CURVE29915 PRIVATE KEY -----

View File

@@ -1,6 +1,6 @@
bartid = 0xF1F82C95B113F29D
bartserial = 0x6055859D
idbobby = 0x616BDDA58845987B
idalicia = 0x16F7B3374FE25F40
mailbobby = bobby@local
mailalicia = alicia@local
bartid=0xFFDF4449F875F4DA
bartserial=0xF0464982
idbobby=0x055BAC622090B2E8
idalicia=0x72FC1A3D01724A26
mailbobby=bobby@local
mailalicia=alicia@local

View File

@@ -1,7 +1,5 @@
#!/bin/sh
file=$1
if type md5 > /dev/null 2>&1; then
md5 -q $*
else
md5sum $* | awk '{print $1}'
fi
../src/pcp1 -C $file | awk '{print $4}'

View File

@@ -25,7 +25,7 @@ int main() {
pw *have = NULL;
unsigned char nonce[32] = {1};
sodium_init();
if(sodium_init() == -1) return 1;
for(i=97; i<126; ++i) {
pass[0] = i;

View File

@@ -1,3 +1,4 @@
# -*-sh-*-
#
# This file is part of Pretty Curved Privacy (pcp1).
#
@@ -19,40 +20,49 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
py = ./pytest.py
py=./pytest.py
<test py-import-keys>
cmd = $py impkeys
expect = /ok/
</test>
py_import_keys () {
cmd="$py impkeys"
expect=/ok/
}
py_encrypt_asym_armor () {
cmd="$py asymarmor"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-asym-armor>
cmd = $py asymarmor
expect = /ok/
</test>
py_encrypt_asym_raw () {
cmd="$py asymraw"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-asym-raw>
cmd = $py asymraw
expect = /ok/
</test>
py_encrypt_asym_sign () {
cmd="$py asymsign"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-asym-sign>
cmd = $py asymsign
expect = /ok/
</test>
py_encrypt_asym_anon () {
cmd="$py asymanon"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-asym-anon>
cmd = $py asymanon
expect = /ok/
</test>
py_encrypt_sym_armor () {
cmd="$py symarmor"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-sym-armor>
cmd = $py symarmor
expect = /ok/
</test>
py_encrypt_sym_raw () {
cmd="$py symraw"
expect=/ok/
check "$cmd" "$expect" "$input"
}
<test py-encrypt-sym-raw>
cmd = $py symraw
expect = /ok/
</test>
prepare () {
:
}

View File

@@ -4,10 +4,10 @@ int main() {
Buffer *inbuf;
pcp_key_t *alice, *bob;
pcp_pubkey_t *alicepub, *bobpub, *pubhash;
Pcpstream *clear_in, *crypt_out, *clear_out;
Pcpstream *clear_in, *crypt_out, *clear_out, *crypt_in;
PCPCTX *ptx;
char message[] = "hello world";
printf("hh: %ld\n", sizeof(UT_hash_handle));
/* we always need a context */
ptx = ptx_new();
@@ -36,24 +36,29 @@ int main() {
/* actually encrypt the message, don't sign it
Alice is the sender, Bob is the recipient */
pcp_encrypt_stream(ptx, clear_in, crypt_out, alice, pubhash, 0, 0);
pcp_encrypt_stream(ptx, clear_in, crypt_out, alice, alice, pubhash, 0, 0);
/* now, print the encrypted result */
fprintf(stderr, "Alice encrypted %"FMT_SIZE_T" bytes for Bob:\n", (SIZE_T_CAST)strlen(message));
buffer_dump(ps_buffer(crypt_out));
/* ---- encryption don, now decrypt ---- */
/* ---- encryption done, now decrypt ---- */
/* prepare the output buffer stream */
clear_out = ps_new_outbuffer();
/* input buffer stream from crypto output */
crypt_in = ps_new_inbuffer(ps_buffer(crypt_out));
/* in order for the decryptor find the senders public key,
we need to put it into the context hash. this step can be
omitted when using a Vault. */
pcphash_add(ptx, alicepub, alicepub->type);
buffer_info(crypt_in->b);
/* try to decrypt the message */
if(pcp_decrypt_stream(ptx, crypt_out, clear_out, bob, NULL, 0, 0) == 0)
if(pcp_decrypt_stream(ptx, crypt_in, clear_out, bob, NULL, 0, 0) == 0)
fatals_ifany(ptx);
else {
/* and finally print out the decrypted message */
@@ -62,15 +67,17 @@ int main() {
}
ps_close(clear_in);
ps_close(crypt_in);
ps_close(crypt_out);
ps_close(clear_out);
ptx_clean(ptx);
free(alice);
free(alicepub);
free(bob);
free(bobpub);
return 0;
}

View File

@@ -1,33 +1,33 @@
size_t secret_a_len = 32;
unsigned char secret_a[32] = {
0x58, 0x92, 0x0b, 0xc3, 0xb6, 0xc9, 0x84, 0xcc,
0x9f, 0x7f, 0x9a, 0xc7, 0x12, 0xc9, 0x90, 0xf2,
0xb3, 0x6a, 0xa6, 0x41, 0xf4, 0x34, 0x93, 0x95,
0xfe, 0xbf, 0xfa, 0xda, 0xab, 0x0d, 0x36, 0x76
0x78, 0xc0, 0x9f, 0x85, 0x1e, 0xd9, 0x86, 0xe8,
0xaa, 0x12, 0xed, 0xea, 0x7e, 0x75, 0x82, 0x4d,
0x57, 0x70, 0xab, 0x58, 0x2c, 0xb7, 0x89, 0xb0,
0x9f, 0x02, 0x85, 0xbd, 0x9e, 0xfc, 0xcb, 0x4b
};
size_t public_a_len = 32;
unsigned char public_a[32] = {
0x22, 0x07, 0xf0, 0xf7, 0x22, 0x37, 0xb3, 0x87,
0x6d, 0xed, 0xa6, 0xf4, 0xcc, 0x60, 0xb0, 0x12,
0xc3, 0xca, 0x0c, 0x24, 0x90, 0x71, 0xdf, 0x4d,
0xef, 0x44, 0x85, 0x9c, 0x54, 0x0b, 0xda, 0x4b
0x78, 0x65, 0x7b, 0xc9, 0x51, 0xeb, 0x47, 0xac,
0x44, 0xed, 0x12, 0xdf, 0x5f, 0x7a, 0x5d, 0x41,
0x1e, 0x52, 0x98, 0xa4, 0x9b, 0x4e, 0xcc, 0x9c,
0x30, 0x36, 0xb6, 0xec, 0xa3, 0x3c, 0xc8, 0x55
};
size_t secret_b_len = 32;
unsigned char secret_b[32] = {
0x78, 0x2c, 0xbf, 0x98, 0x20, 0x9e, 0x8a, 0xab,
0x7b, 0x26, 0x71, 0x4d, 0x06, 0x70, 0x27, 0x0b,
0x18, 0xd9, 0x4a, 0x5d, 0x1c, 0x12, 0xb3, 0xc1,
0x5c, 0x43, 0x69, 0x6a, 0xd1, 0x40, 0x6a, 0x41
0x28, 0x51, 0xed, 0x3d, 0x89, 0x9e, 0xbc, 0xc6,
0xf4, 0xf9, 0x15, 0x75, 0x75, 0xb9, 0xaf, 0xe7,
0xde, 0xa4, 0x69, 0x85, 0xfa, 0x65, 0xd2, 0x47,
0x5d, 0x64, 0x6a, 0x94, 0xf0, 0x8d, 0xe5, 0x6f
};
size_t public_b_len = 32;
unsigned char public_b[32] = {
0xa3, 0x24, 0x7a, 0x84, 0x38, 0x90, 0xbe, 0x91,
0xee, 0x5f, 0x6b, 0xe6, 0x04, 0x08, 0xa6, 0xba,
0x9e, 0x16, 0x3b, 0x66, 0x92, 0x3c, 0xf6, 0xc1,
0x10, 0xa8, 0xaa, 0x7e, 0x30, 0x4f, 0x2b, 0x3b
0x9b, 0x1b, 0x0e, 0xcf, 0x54, 0x55, 0x24, 0x8d,
0x07, 0x39, 0xbe, 0x7e, 0x85, 0x66, 0x5c, 0x6d,
0x1b, 0x2e, 0x77, 0xf9, 0x35, 0x12, 0x8f, 0xc0,
0x61, 0xa1, 0x9e, 0x7f, 0x0e, 0xbd, 0x4c, 0x2a
};
size_t message_len = 12;
@@ -38,16 +38,16 @@ unsigned char message[12] = {
size_t nonce_len = 24;
unsigned char nonce[24] = {
0x68, 0x0f, 0x5f, 0x72, 0x33, 0xbb, 0x24, 0x29,
0xab, 0x06, 0xd5, 0x70, 0xea, 0x27, 0x74, 0x0e,
0x91, 0xf9, 0x0b, 0xda, 0x2f, 0x50, 0xc3, 0xd9
0x36, 0x39, 0x31, 0xd4, 0xb1, 0x64, 0x4b, 0x49,
0xe1, 0x4c, 0x67, 0x0a, 0xfe, 0x52, 0xd1, 0x06,
0x76, 0xa4, 0x3b, 0x7d, 0x7e, 0xf2, 0x9f, 0xf6
};
size_t cipher_len = 28;
unsigned char cipher[28] = {
0x36, 0xb9, 0x2c, 0xc4, 0x02, 0x38, 0xae, 0xbc,
0x6a, 0xb8, 0x21, 0x4c, 0x30, 0x1d, 0xac, 0x6c,
0x14, 0x2d, 0xfc, 0x2a, 0xb6, 0x9b, 0x6c, 0x20,
0x95, 0x3e, 0xe3, 0x73
0x65, 0x7b, 0x60, 0xca, 0xa1, 0x26, 0xdd, 0xdb,
0x3d, 0xf5, 0xc2, 0x4e, 0xdd, 0x48, 0xa9, 0x7d,
0x70, 0xe9, 0xe3, 0xc4, 0xff, 0x28, 0x0f, 0x3a,
0x10, 0xaa, 0x5d, 0xb1
};

View File

@@ -2,7 +2,7 @@
#include "static.h"
int main() {
sodium_init();
if(sodium_init() == -1) return 1;
unsigned char *t = ucmalloc(12);
if(crypto_box_open_easy(t, cipher, cipher_len, nonce, public_a, secret_b) == 0) {
if(memcmp(t, message, message_len) == 0) {

View File

@@ -1,7 +1,8 @@
# -*-sh-*-
#
# This file is part of Pretty Curved Privacy (pcp1).
#
# Copyright (C) 2013 T.Linden.
# Copyright (C) 2013-2016 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
@@ -22,31 +23,33 @@
#
# stress tests
confirm = Stress tests will take some time, continue?
pcp = ../src/pcp1
outdir = stresstest
vault = $outdir/stresstestin
pvault = $outdir/stresstestout
numkeys = 100
verbose = 1
confirm=Stress tests will take some time, continue?
pcp=../src/pcp1
outdir =stresstest
vault=$outdir/stresstestin
pvault=$outdir/stresstestout
numkeys=100
verbose=1
<test check-bulk-tests>
prepare = ./genmasskeys.sh $outdir $numkeys $pcp $vault
prepare () {
./genmasskeys.sh $outdir $numkeys $pcp $vault
}
<test check-bulk-generate-keys>
cmd = $pcp -V $vault -l | grep 0x | wc -l
expect = $numkeys
</test>
check_bulk_generate_keys () {
cmd=$pcp -V $vault -l | grep 0x | wc -l
expect=$numkeys
}
<test check-bulk-vault-export-publics>
prepare = ./exportmasspubs.sh $outdir $pcp $vault
cmd = ls -1 $outdir/0x* | wc -l
expect = $numkeys
</test>
check_bulk_vault_export_publics () {
./exportmasspubs.sh $outdir $pcp $vault
cmd="ls -1 $outdir/0x* | wc -l"
expect="$numkeys"
check "$cmd" "$expect" "$input"
}
<test check-bulk-import-publics>
prepare = ./importmasspubs.sh $outdir $pcp $pvault
cmd = $pcp -V $pvault -l | grep 0x | wc -l
expect $numkeys
</test>
</test>
check_bulk_import_publics () {
./importmasspubs.sh $outdir $pcp $pvault
cmd="$pcp -V $pvault -l | grep 0x | wc -l"
expect="$numkeys"
check "$cmd" "$expect" "$input"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,357 +0,0 @@
#!/usr/bin/perl
#
# This file is part of Pretty Curved Privacy (pcp1).
#
# Copyright (C) 2013 T.Linden.
#
# 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>.
#
use lib qw(lib);
BEGIN {
eval {
require IPC::Run; # on win32
};
}
use IPC::Open3; # unix et al use this
use Test::More;
use IO::Select;
use FileHandle;
use Data::Dumper;
use Config::General qw(ParseConfig);
sub run3;
sub execute;
sub final;
my $output;
my ($config, $check) = @ARGV;
if (! $config) {
die "usage: $0 <config>\n";
}
my %cfg = Config::General::ParseConfig(-ConfigFile => $config,
-InterPolateVars => 1,
-UseApacheInclude => 1,
-Tie => "Tie::IxHash" );
my $verbose = $cfg{verbose};
if (exists $cfg{confirm}) {
print "$cfg{confirm} [CTRL-C to abort, <ENTER> to continue] ";
my $cont = <STDIN>;
}
if ($check) {
if (exists $cfg{test}->{$check}) {
&runtest($cfg{test}->{$check}, $check);
}
}
else {
my $continue = 1;
foreach my $test (keys %{$cfg{test}}) {
if ($continue) {
$continue = &runtest($cfg{test}->{$test}, $test);
if (!$continue) {
print "Last failed check: $test\n";
last;
}
}
}
}
sub runtest {
my($cfg, $name) = @_;
my($in, $out, $error, $timeout);
if (exists $cfg->{loop}) {
my $loop = delete $cfg->{loop};
foreach my $n (0 .. $loop) {
if (&runtest($cfg, "${name}-loop-${n}") == 0) {
return 0;
}
}
return 1;
}
foreach my $key (keys %{$cfg}) {
$cfg->{$key} =~ s/\`([^\`]*)\`/my $result = `$1`; chomp $result; $result/ge;
}
if (exists $cfg->{prepare}) {
print STDERR " executing prepare command: $cfg->{prepare}\n" if ($verbose);
if ($cfg->{prepare} =~ />/) {
system("$cfg->{prepare}");
}
else {
system("$cfg->{prepare} > /dev/null 2>&1");
}
}
if (exists $cfg->{test}) {
foreach my $test (keys %{$cfg->{test}}) {
if (&runtest($cfg->{test}->{$test}, $test) == 0) {
return 0;
}
}
return 1;
}
$cfg->{cmd} =~ s/%\{([^\}]*)\}/
my $N = $1; my $o;
if (exists $cfg->{$N}) {
$o = `$cfg->{$N}`;
chomp $o;
}
$o;
/gex;
print STDERR "\n$cfg->{cmd}\n ";
my $ret = run3($cfg->{cmd},
$cfg->{input},
\$out, \$error, 10, 0, undef);
$output = $out . $error;
$output =~ s/^\s*//;
$output =~ s/\s*$//;
printf "$output\n" if $verbose > 1;
if (exists $cfg->{expect}) {
if ($cfg->{expect} =~ /^!(\/.*)/) {
unlike($output, $1, "$name") or return final 0;
}
elsif ($cfg->{expect} =~ /^\//) {
like($output, $cfg->{expect}, "$name") or return final 0;
}
else {
is($output, $cfg->{expect}, "$name") or return final 0;
}
}
elsif (exists $cfg->{"expect-file"}) {
my $e = 0;
if (-s $cfg->{"expect-file"}) {
$e = 1;
}
is($e, 1, "$name") or return final 0;
}
elsif (exists $cfg->{"expect-file-contains"}) {
my($file, $expext) = split /\s\s*/, $cfg->{"expect-file-contains"};
my $e = 0;
if (-s $file) {
$e = 1;
}
is($e, 1, "$name") or return final 0;
if (open F, "<$file") {
my $content = join '', <F>;
close F;
like($content, qr/$expect/s, "$name") or return final 0;
}
else {
fail($test);
return final 0;
}
}
elsif (exists $cfg->{exit}) {
is($ret, $cfg->{exit}, "$name") or return final 0;
}
else {
diag("invalid test spec for $test");
fail($test);
return final 0;
}
return final 1;
}
done_testing;
sub final {
my $ret = shift;
system("stty echo"); # turn echo on, just in case a prompt timed out
if ($output =~ /(segmentation fault|bus error)/i || -s "pcp1.core") {
# override $ret
$ret = 0;
diag("Abnormal program termination");
# if there is a coredump, extract a backtrace
if (-s "pcp1.core") {
# print a backtrace
system("gdb -x .gdb -batch $cfg{pcp} pcp1.core");
unlink "pcp1.core";
}
}
return $ret;
}
sub run3 {
# open3 wrapper. catch stderr, stdout, errno; add timeout and kill
my($cmd, $input, $output, $error, $timeout, $debug, $monitorfile) = @_;
if ($^O =~ /win/i) {
my ($o, $e, @c);
if ($cmd =~ /\|/) {
@c = ("sh", "-c", $cmd);
}
else {
@c = split /\s\s*/, $cmd;
}
my $ret = IPC::Run::run( \@c, \$input, \$o, \$e, IPC::Run::timeout( $timeout ));
$$output = $o;
$$error = $e;
return $ret;
}
my ($stdin, $stderr, $stdout) = ('', '', '');
my $child = 0;
my $cmdline = join " ", @{$cmd};
$timeout = $timeout ? $timeout : 10;
$SIG{CHLD} = &reaper;
REENTRY:
eval {
local $SIG{ALRM} = sub { die "timeout" };
alarm $timeout;
if ($child && kill 0, $child) {
;
}
else {
$child = open3($stdin, $stdout, $stderr, $cmd);
$childs++;
if ($input) {
print $stdin $input;
}
$stdin->close();
}
my $sel = new IO::Select;
$sel->add($stdout, $stderr);
while(my @ready = $sel->can_read) {
foreach my $fh (@ready) {
my $line;
my $len = sysread $fh, $line, 4096;
if(not defined $len){
die "Error from child: $!\n";
}
elsif ($len == 0){
$sel->remove($fh);
next;
}
else {
if(fileno($fh) == fileno($stdout)) {
$$output .= $line;
}
elsif(fileno($fh) == fileno($stderr)) {
$$error .= $line;
}
else {
die "Unknown filehandle returned!\n";
}
}
}
}
alarm 0;
close $stderr;
close $stdout;
};
TRY:
my($exitcode, $killsignal, $coredumped);
if ($@ !~ /timeout at/) {
my ($alert);
while ($childs > 0 || kill(0, $child)) {
if ((time - $alert) >= 60) {
$alert = time;
}
}
$childs = 0;
$CHILD_ERROR = $childerror{$child};
$killsignal = $CHILD_ERROR & 127;
$coredumped = $CHILD_ERROR & 127;
}
$exitcode = $CHILD_ERROR >> 8;
if ($@ || ($exitcode != 0)) {
chomp $@;
if ($@ =~ /timeout/) {
if (kill 0, $child) {
# whoe it's still running
if ($monitorfile) {
my $size = -s $monitorfile;
sleep $timeout;
my $nsize = -s $monitorfile;
if ($size != $nsize and kill 0, $child) {
# well, file still growing, so the process seems still to work
# go back to the eval{} block and enter select() again
goto REENTRY;
}
else {
# process no more running
# reset $@ and go back to returncode check
$@ = "";
goto TRY;
}
}
else {
# get rid of it
$$error .= "Timed out after $timeout seconds!\n";
kill TERM => $child;
}
}
}
else {
$$error .= $@;
}
return $exitcode;
}
else {
return $exitcode;
}
}
sub reaper {
my $pid;
while (1) {
my $pid = waitpid(-1,WNOHANG);
if ($pid) {
$childs-- if $pid > 0;
$childerror{$pid} = $CHILD_ERROR;
last;
}
}
$SIG{CHLD} = \&reaper;
}

133
tests/unittests.sh Executable file
View File

@@ -0,0 +1,133 @@
#!/bin/sh
errout () {
logout="$1"
expect="$2"
echo " EXPECTED: $expect"
echo -n " GOT: "
cat $logout | head -1
cat $logout | tail -n +2 | sed 's/^/ /'
}
lookup () {
logfile="$1"
expect="$2"
if echo "$expect" | grep '!' > /dev/null 2>&2; then
# negate
expect=`echo "$expect" | sed -e 's/^\!//' -e 's#^/##' -e 's#/$##'`
if cat $logfile | grep -i "$expect" > /dev/null 2>&1; then
errout "$logfile" "NOT $expect"
return 1
else
echo " OK"
return 0
fi
else
expect=`echo "$expect" | sed -e 's#^/##' -e 's#/$##'`
if cat $logfile | grep -i "$expect" > /dev/null 2>&1; then
echo " OK"
return 0
else
errout "$logfile" "$expect"
return 1
fi
fi
}
check() {
cmd="$1"
expect="$2"
input="$3"
file="$4"
log=".log-$$"
fail=''
echo " executing $cmd"
echo "$input" | eval "$cmd" > $log 2>&1
if test -n "$file"; then
# ignore result, check output file
if test -n "$expect"; then
# look for string in output
if ! lookup "$file" "$expect"; then
fail=y
fi
else
# just check for existence
if test -e "$file"; then
echo " OK"
else
echo " Failed: $file doesnt exist"
fail=y
fi
fi
else
# check output
if ! lookup "$log" "$expect"; then
fail=y
fi
fi
rm -f $log
if test -n "$fail"; then
return 1
else
return 0
fi
}
checkdump () {
F="$1"
if test -e "pcp1.core"; then
echo "Test $F dumped core!"
gdb -x .gdb -batch $pcp pcp1.core
exit 1
fi
}
callcheck () {
F="$1"
rm -f pcp1.core
echo "--- test $F result:"
if ! $F; then
echo
echo "Test $F failed!"
checkdump $F
exit 1
else
checkdump $F
fi
}
cfg="$1"
check="$2"
if test -z "$cfg"; then
echo "Usage: $0 <config> [check]"
exit 1
fi
if ! test -e "$cfg"; then
echo "$cfg doesn't exist!"
exit 1
fi
. ./$cfg
count=`grep -E -- "^check_" "$cfg" | wc -l`
callcheck prepare
if test -n "$check"; then
callcheck $check
else
for F in `grep -E -- "^check_" "$cfg" | cut -d' ' -f1`; do
callcheck $F
done
echo "All Tests OK"
fi

View File

@@ -1,9 +1,9 @@
----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----
1][S6097-%&#%s9D*[RVp:%rAl!evYxQ7<h9yTfqgG!sj=&3GmsrH]at9-x2nn2^O@G{1u&
<$hyGP4mePZaZ[?1CxLQi$fUHo>I4C5*B00^e2rhV/-XKN+Aw4F0PT6t8qS[b@+lbo^9)00
0080SSi2097-%<nYeW2M>5b0037krB=7f00&(h000125(&Aw000Gy00SAaB7GxavqD5e/R5
oB01Y?A1PO^CCwZ#jphaoRvqYPQ000-F00Aohzddc{zFrW0vqYQvy&r/(yYBCn0uh2!.O?*
XJ$:1%==@=R7{:wD{CzQ[1]-2k5P:K5=@EM@h1?[9Yigq3Bsr=:O?Cjw!1gq=%i..Tf4Xk<
X7.mYD{R1[lTkTa2qc^xu1&6z8ECuigL@C!mT&vgD1TCgf9/)(6En?^OCZhRKw&<mLTPBc>
pI3zkiaG>bsHt/@d%.v
1][S609x+qRxL(=Ps)r^qoB5H>X!{Kh65+pUy*ssWF6FO<MNu$=w2=+^RO.bYYcG3d[wdz-
Vope(@lHILY:(ytC/yyXd6)8n]@N%Y7:hOB[z$EJ]&>#cr27]Ra<1uQQ^)n0.JFnbo^9)00
0080SSi209x+qRt{O@2M>5b003f>KTp5d00&(h00014[r23$000Gy00SAaB7GxavqG*=}%s
v-01Y?A1PO^CCwZ#jphaoRvqYPQ000-F00Aohzddc{zFrW0vqYQvy&r/(yYBCn0uh3Tt7H0
ly4YcV/X:m1ifK-4J#K@6/@GZ^T}M^)iTFH3?*9F+xKvF$=46HBJ-X7>j=!Zl=@ww@SA*tK
7>-r(y:U&DGB6DP+EEE&b4.h>cv?EIF}sd#vW(9+D]G4VGhU#dIK$T..Xs{cB&lg0T!!*yy
xDUmPjljR.(Lx?Tfr0k
----- END ED25519-CURVE29915 PUBLIC KEY -----

View File

@@ -1,8 +1,8 @@
----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----
k?.94xGjnQjK&1E]du2^aqzGt00=MS(BW^@1sWBErpH0CmaP1L1f//1Yl01v&li$iv>G06I
74-AC2C5u>x]c4T5g[yPhUs?SaHMW9f{LNrsr@n^db?cJt(L(TFzeV{p}Nv5?R*6mo/TC)0
@PBItOguyj6YTKBRLdsuaUxfYk.*LGcH(1gf&#}j--1n(ewi!$izcClGTuKt1tRWXiuYYE7
6o@hV%?y{{:3j5It%N+]B8w*P#C.*N^*S0Z2p)vszkF3hyE*1(Fj5bDheH/KnTDCKqoLs.2
3!=^SFytRDMEfJDH.n:&sPoQW?E<g9t?69uo4+Lw[dpQ4PL$LAnnokWOKoX*HdHkvW1WqoH
Sj*09.eu*oPr4&%Cd7WodrgX(%9g6W^s*l-96y5P.?8yUCj>iJ({-eP+aSRq2dB&>T*O9c
-y]P8A.u]@0B..69iG{NTHV#oC(-r2.r2gTeM/HA0D}Eq:ev7c+B:zcH9xC4W}?HN&ME0>5
59wS%kiAW3?wd*8QXm)]q0p?Ohz}&Lo5N3Y7UPBQ&{<%)^Ya-Jrj?s4zOrdbC:h:38w8f98
jAE8k?Tr<lHfR-F59TZ!bn!mc$A7h>s*g+7+3KHvjxSujgQ<+4qd9s7d7R5/Rez/=r*<d=M
Pc[4YCApdofklI22T4y6.YnZ[zsziltQq^ZvagB14BX8UMwDOJ*H7UX21Axmx2V^g1=2&c1
zoE$7peZ8KQzprOCgeq%<%0%RRGS7(Go)+}RfecaF[3O*k/nm5y)5z&Zo8Kn%38})Ajwq6m
gRa9!:tsA3T<WW0sLA19uH0$tPZii6.6VLG}L3ed2MQJgL&(9VNt>OjFczUvX#zrK!aV/w
----- END ED25519-CURVE29915 PRIVATE KEY -----

View File

@@ -1 +1 @@
7xBKNd@2v[N-5aot3DW1)P}.#QtXBYNqN5F]/#IQ6^9lJZ?zHM^l5}rTJ:ckwO&1W
7xBL-tR)BHRoB)ZhG+oVTa}Fx<oUfNxvUV@M*Nia:sjp95<h-%V62=xaj$Yoj}*9X

View File

@@ -0,0 +1,2 @@
blah
nacl-<2D> k̓ȋX<C88B>><3E>{<12>D5s<35><73>/<2F><>Lon<6F><16><>m<EFBFBD>,l<><04>zM!<21><>p<EFBFBD><01>.<2E><><EFBFBD><EFBFBD>E<EFBFBD><05><><EFBFBD>:'<27>n(hg<68><67><EFBFBD><EFBFBD>k<EFBFBD>nnjj<6A>DF<44><06><><EFBFBD><EFBFBD>x+`4>Q<><51>PA<1C>%<25>`<60><> <20><>]W<>PK<50><14><><EFBFBD><05>X