101 Commits

Author SHA1 Message Date
T. von Dein
913f584b76 migrate to codeberg (#21) 2025-11-24 23:02:13 +01:00
Thomas von Dein
48e87fd605 merge z85 bugfix#903 from https://github.com/zeromq/libzmq/pull/2322 2017-08-23 13:01:35 +02:00
Thomas von Dein
7e54d27011 version bump to 0.4.1 2017-08-23 13:00:12 +02:00
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
122 changed files with 5825 additions and 5736 deletions

View File

@@ -1,34 +1,26 @@
sudo: false
language: c language: c
os: os:
- linux - linux
addons:
apt:
packages:
- python-pip
- texinfo
compiler:
- clang
- gcc
before_install: before_install:
# runtime dependency # runtime dependency
- git clone https://github.com/jedisct1/libsodium - git clone https://github.com/jedisct1/libsodium
- cd libsodium - cd libsodium
- ./autogen.sh - ./autogen.sh
- ./configure --prefix=/usr - ./configure --prefix=$HOME/usr
- make - make
- sudo make install - 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
- cd .. - cd ..
# #
# for debugging - just in case, uncomment this and the next if needed # for debugging - just in case, uncomment this and the next if needed
@@ -45,24 +37,21 @@ before_install:
#- sudo apt-get install libc6-dbg #- sudo apt-get install libc6-dbg
# #
# python bindings runtime dependencies # python bindings runtime dependencies
- sudo apt-get update -qq #- git clone https://github.com/atgreen/libffi
- sudo apt-get install python-pip texinfo #- cd libffi
- git clone https://github.com/atgreen/libffi #- ./autogen.sh
- cd libffi #- ./configure --prefix=/usr
- ./autogen.sh #- make
- ./configure --prefix=/usr #- sudo make install
- make #- cd ..
- sudo make install #- sudo pip install cffi
- cd ..
- sudo pip install cffi
# #
# finally prepare autoconf stuff # finally prepare autoconf stuff
- ./autogen.sh - ./autogen.sh
compiler:
- clang
- gcc
script: script:
- ./configure --enable-python-binding #- ./configure --enable-python-binding
- LD_LIBRARY_PATH=$HOME/usr/lib ./configure --with-libsodium=$HOME/usr
- make - make
- make check - make check
- make test - make test

29
.woodpecker/build.yaml Normal file
View File

@@ -0,0 +1,29 @@
matrix:
platform:
- linux/amd64
labels:
platform: ${platform}
steps:
build:
when:
event: [push]
image: alpine:latest
commands:
- apk update
- apk add --no-cache bash build-base gdb perl libsodium libsodium-dev libbsd libbsd-dev jansson jansson-dev db db-dev pkgconfig meson ninja
- meson setup --reconfigure build
- ninja -C build
test:
when:
event: [push]
image: alpine:latest
commands:
- apk update
- apk add --no-cache bash build-base gdb perl libsodium libsodium-dev libbsd libbsd-dev jansson jansson-dev db db-dev pkgconfig meson ninja
- meson setup --reconfigure build
- ninja -C build test

54
.woodpecker/release.sh Executable file
View File

@@ -0,0 +1,54 @@
#!/bin/bash
# This is my own simple codeberg generic releaser. It takes to
# binaries to be uploaded as arguments and takes every other args from
# env. Works on tags or normal commits (push), tags must start with v.
set -e
die() {
echo $*
exit 1
}
if test -z "$DEPLOY_TOKEN"; then
die "token DEPLOY_TOKEN not set"
fi
git fetch --all
# determine current tag or commit hash
version="$CI_COMMIT_TAG"
previous=""
log=""
if test -z "$version"; then
version="${CI_COMMIT_SHA:0:6}"
log=$(git log -1 --oneline)
else
previous=$(git tag -l | grep -E "^v" | tac | grep -A1 "$version" | tail -1)
log=$(git log -1 --oneline "${previous}..${version}" | sed 's|^|- |g')
fi
# release body
printf "# Changes\n\n %s\n" "$log" > body.txt
# create the release
https --ignore-stdin --check-status -b -A bearer -a "$DEPLOY_TOKEN" POST \
"https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases" \
tag_name="$version" name="Release $version" body=@body.txt > release.json
# we need the id to upload files
ID=$(jq -r .id < release.json)
if test -z "$ID"; then
cat release.json
die "failed to create release"
fi
# actually upload
for file in "$@"; do
https --ignore-stdin --check-status -A bearer -a "$DEPLOY_TOKEN" -f POST \
"https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases/$ID/assets" \
"name=${file}" "attachment@${file}"
done

28
.woodpecker/release.yaml Normal file
View File

@@ -0,0 +1,28 @@
# build release
labels:
platform: linux/amd64
steps:
dist:
when:
event: [tag,manual]
image: alpine:latest
commands:
- apk update
- apk add --no-cache bash build-base gdb perl libsodium libsodium-dev libbsd libbsd-dev jansson jansson-dev db db-dev pkgconfig meson ninja git
- meson setup --reconfigure --buildtype=release build
- meson dist -C build --formats xztar,gztar,zip --no-tests
- mv build/meson-dist/* .
release:
image: alpine:latest
when:
event: [tag,manual]
environment:
DEPLOY_TOKEN:
from_secret: DEPLOY_TOKEN
commands:
- apk update
- apk add --no-cache bash httpie jq git
- .woodpecker/release.sh pcp-*

19
.woodpecker/test.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
yq '.steps.test-gdbm.commands' < .woodpecker/build.yaml \
| grep -- - | grep -v apk | sed 's/^\- //' \
| while read COMMAND; do
echo "$COMMAND" | bash -e > debug.log 2>&1
if test $? -ne 0; then
echo "fail - $COMMAND"
if test -s debug.log; then
cat debug.log
else
echo exit 1
fi
else
echo "ok - $COMMAND"
fi
done
rm -f debug.log

View File

@@ -1,3 +1,46 @@
0.4.1
Merged upstream patch:
https://github.com/zeromq/libzmq/pull/2322,
which fixes:
https://github.com/zeromq/libzmq/issues/903:
Problem: zmq_z85_decode does not validate its
input. Solution: added checks for invalid
characters and overflows.
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 0.3.0
Changed publuc key signature storage, previously Changed publuc key signature storage, previously
I didn't add the actual signature, therefore a 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 A passphrase like Ahc<e3% is not really secure. First
it's difficult to memorize, second it's easy for a computer it's difficult to memorize, second it's easy for a computer
to compute. The better aproach is to use a passphrase 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. to compute (i.e. to guess) like: Phantom orchestra boredom popcorn.
Read [1] to learn more. Read [1] to learn more.

168
README
View File

@@ -1,168 +0,0 @@
DESCRIPTION
Pretty Curved Privacy (pcp1) is a commandline utility which can be used
to encrypt files. pcp1 uses eliptc curve cryptography for encryption
(CURVE25519 by Dan J. Bernstein). While CURVE25519 is no worldwide
accepted standard it hasn't been compromised by the NSA - which might be
better, depending on your point of view.
Caution: since CURVE25519 is no accepted standard, pcp1 has to be
considered as experimental software. In fact, I wrote it just to learn
about the curve and see how it works.
Beside some differences it works like GNUPG. So, if you already know how
to use gpg, you'll feel almost home.
QUICKSTART
Lets say, Alicia and Bobby want to exchange encrypted messages. Here's
what the've got to do.
First, both have create a secret key:
Alicia Bobby
pcp1 -k pcp1 -k
After entering their name, email address and a passphrase to protect the
key, it will be stored in their vault file (by default ~/.pcpvault).
Now, both of them have to export the public key, which has to be
imported by the other one. With pcp you can export the public part of
your primary key, but the better solution is to export a derived public
key especially for the recipient:
Alicia Bobby
pcp1 -p -r Bobby -O alicia.pub pcp1 -p -r Alicia -O bobby.pub
They've to exchange the public key somehow (which is not my problem at
the moment, use ssh, encrypted mail, whatever). Once exchanged, they
have to import it:
Alicia Bobby
pcp1 -K -I bobby.pub pcp1 -K -I alicia.pub
They will see a response as this when done:
key 0x29A323A2C295D391 added to .pcpvault.
Now, Alicia finally writes the secret message, encrypts it and sends it
to Bobby, who in turn decrypts it:
Alicia Bobby
echo "Love you, honey" > letter
pcp1 -e -r Bobby -I letter -O letter.asc
cat letter.asc | mail bobby@foo.bar
pcp1 -d -I letter.asc | less
And that's it.
Please note the big difference to GPG though: both Alicia AND Bobby have
to enter the passphrase for their secret key! That's the way CURVE25519
works: you encrypt a message using your secret key and the recipients
public key and the recipient does the opposite, he uses his secret key
and your public key to actually decrypt the message.
Oh - and if you're wondering why I named them Alicia and Bobby: I was
just sick of Alice and Bob. We're running NSA-free, so we're using other
sample names as well.
FILES AND PIPES
Pcp behaves like any other unix tool. If not otherwise specified it will
read input from standard input (STDIN) and print output to standard
output (STDOUT). For instance:
pcp1 -e -O output
will read the text to be encrypted from standard input, because -I has
not been specified. It works the same with -O:
pcp1 -e -I myfile
In this case the encrypted result will be written to standard output.
Therefore it is possible to use pcp within pipes. Another more realistic
example:
ssh remote cat file | pcp1 -ez | mailx -s 'as requested' bob@somewhere
here we encrypt a file symmetrically without downloading it from a
remote ssh server and sending the encrypted result via email to someone.
The behavior is the same with any other functionality where files are
involved like importing or exporting keys. However, there's one
exception: If the option -X (--password-file) has been used and is set
to -, then this will take precedence over any other possible use of
standard input. So if you want to encrypt something and don't specify an
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
There are currently no packages available, so pcp has to be compiled
from source. Follow these steps:
First, you will need libsodium:
git clone git://github.com/jedisct1/libsodium.git
cd libsodium
./autogen.sh
./configure && make check
sudo make install
sudo ldconfig
cd ..
Next, pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp
./configure
sudo make install
cd ..
Optionally, you might run the unit tests:
make test
DOCUMENTATION
To learn how to use pcp, read the manpage:
man pcp1
COPYRIGHT
Copyright (c) 2013-2015 by T.v.Dein <tom AT vondein DOT org>
ADDITIONAL COPYRIGHTS
ZeroMQ Z85 encoding routine
Copyright (c) 2007-2013 iMatix Corporation
Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2010-2011 Miru Limited
Copyright (c) 2011 VMware, Inc.
Copyright (c) 2012 Spotify AB
Tarsnap readpass helpers
Copyright 2009 Colin Percival
jen_hash() hash algorithm
Bob Jenkins, Public Domain.
UTHASH hashing macros
Copyright (c) 2003-2013, Troy D. Hanson
Random art image from OpenSSH keygen
Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Comitted by Alexander von Gernler in rev 1.7.
Every incorporated source code is opensource and licensed under the GPL
as well.
AUTHORS
*T.v.Dein <tom AT vondein DOT org*>
LICENSE
Licensed under the GNU GENERAL PUBLIC LICENSE version 3.
HOME
The homepage of Pretty Curved Privacy can be found on
http://www.daemon.de/PrettyCurvedPrivacy. The source is on Github:
https://github.com/TLINDEN/pcp

187
README.md Normal file
View File

@@ -0,0 +1,187 @@
# Pretty Curved Privacy
Pretty Curved Privacy (pcp1) is a commandline utility which can be used
to encrypt files. pcp1 uses eliptc curve cryptography for encryption
(CURVE25519 by Dan J. Bernstein). While CURVE25519 is no worldwide
accepted standard it hasn't been compromised by the NSA - which might be
better, depending on your point of view.
Caution: since CURVE25519 is no accepted standard, pcp1 has to be
considered as experimental software. In fact, I wrote it just to learn
about the curve and see how it works.
Beside some differences it works like GNUPG. So, if you already know how
to use gpg, you'll feel almost home.
# QUICKSTART
Lets say, Alicia and Bobby want to exchange encrypted messages. Here's
what the've got to do.
First, both have create a secret key:
Alicia Bobby
pcp1 -k pcp1 -k
After entering their name, email address and a passphrase to protect the
key, it will be stored in their vault file (by default ~/.pcpvault).
Now, both of them have to export the public key, which has to be
imported by the other one. With pcp you can export the public part of
your primary key, but the better solution is to export a derived public
key especially for the recipient:
Alicia Bobby
pcp1 -p -r Bobby -O alicia.pub pcp1 -p -r Alicia -O bobby.pub
They've to exchange the public key somehow (which is not my problem at
the moment, use ssh, encrypted mail, whatever). Once exchanged, they
have to import it:
Alicia Bobby
pcp1 -K -I bobby.pub pcp1 -K -I alicia.pub
They will see a response as this when done:
key 0x29A323A2C295D391 added to .pcpvault.
Now, Alicia finally writes the secret message, encrypts it and sends it
to Bobby, who in turn decrypts it:
Alicia Bobby
echo "Love you, honey" > letter
pcp1 -e -r Bobby -I letter -O letter.asc
cat letter.asc | mail bobby@foo.bar
pcp1 -d -I letter.asc | less
And that's it.
Please note the big difference to GPG though: both Alicia AND Bobby have
to enter the passphrase for their secret key! That's the way CURVE25519
works: you encrypt a message using your secret key and the recipients
public key and the recipient does the opposite, he uses his secret key
and your public key to actually decrypt the message.
Oh - and if you're wondering why I named them Alicia and Bobby: I was
just sick of Alice and Bob. We're running NSA-free, so we're using other
sample names as well.
# FILES AND PIPES
Pcp behaves like any other unix tool. If not otherwise specified it will
read input from standard input (STDIN) and print output to standard
output (STDOUT). For instance:
pcp1 -e -O output
will read the text to be encrypted from standard input, because -I has
not been specified. It works the same with -O:
pcp1 -e -I myfile
In this case the encrypted result will be written to standard output.
Therefore it is possible to use pcp within pipes. Another more realistic
example:
ssh remote cat file | pcp1 -ez | mailx -s 'as requested' bob@somewhere
here we encrypt a file symmetrically without downloading it from a
remote ssh server and sending the encrypted result via email to someone.
The behavior is the same with any other functionality where files are
involved like importing or exporting keys. However, there's one
exception: If the option -X (--password-file) has been used and is set
to -, then this will take precedence over any other possible use of
standard input. So if you want to encrypt something and don't specify an
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.
# INSTALLATION
here are currently no packages available, so pcp has to be compiled
from source. Follow these steps:
First, you will need libsodium:
git clone git://github.com/jedisct1/libsodium.git
cd libsodium
./autogen.sh
./configure && make check
sudo make install
sudo ldconfig
cd ..
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://codeberg.org/scip/pcp.git
cd pcp
meson setup build
ninja -C build
sudo ninja -C install
Optionally, you might run the unit tests:
make test
DOCUMENTATION
To learn how to use pcp, read the manpage:
man pcp1
# COPYRIGHT
Copyright (c) 2013-2015 by T.v.Dein <tom AT vondein DOT org>
## ZeroMQ Z85 encoding routine:
- Copyright (c) 2007-2013 iMatix Corporation
- Copyright (c) 2009-2011 250bpm s.r.o.
- Copyright (c) 2010-2011 Miru Limited
- Copyright (c) 2011 VMware, Inc.
- Copyright (c) 2012 Spotify AB
## Tarsnap readpass helpers
Copyright 2009 Colin Percival
## jen_hash() hash algorithm
Bob Jenkins, Public Domain.
## UTHASH hashing macros
Copyright (c) 2003-2013, Troy D. Hanson
# Random art image from OpenSSH keygen
Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Comitted by Alexander von Gernler in rev 1.7.
# AUTHORS
*T.v.Dein <tom AT vondein DOT org*>
# LICENSE
Licensed under the GNU GENERAL PUBLIC LICENSE version 3.

View File

@@ -1,203 +0,0 @@
=begin html
<a href="https://travis-ci.org/TLINDEN/pcp"><img
src="https://travis-ci.org/TLINDEN/pcp.svg?branch=master"
alt="build status"/></a>
<a href="https://ci.appveyor.com/project/TLINDEN/pcp"><img
src="https://ci.appveyor.com/api/projects/status/7e833vup5pqhse83?svg=true"
alt="build status"/></a>
=end html
=head1 DESCRIPTION
B<Pretty Curved Privacy> (pcp1) is a commandline utility which can
be used to encrypt files. B<pcp1> uses eliptc curve cryptography
for encryption (CURVE25519 by Dan J. Bernstein). While CURVE25519
is no worldwide accepted standard it hasn't been compromised by
the NSA - which might be better, depending on your point of view.
B<Caution>: since CURVE25519 is no accepted standard, B<pcp1> has
to be considered as experimental software. In fact, I wrote it just
to learn about the curve and see how it works.
Beside some differences it works like B<GNUPG>. So, if you already
know how to use gpg, you'll feel almost home.
=head1 QUICKSTART
Lets say, Alicia and Bobby want to exchange encrypted messages.
Here's what the've got to do.
First, both have create a secret key:
Alicia Bobby
pcp1 -k pcp1 -k
After entering their name, email address and a passphrase to protect
the key, it will be stored in their B<vault file> (by default ~/.pcpvault).
Now, both of them have to export the public key, which has to be
imported by the other one. With B<pcp> you can export the public
part of your primary key, but the better solution is to export
a derived public key especially for the recipient:
Alicia Bobby
pcp1 -p -r Bobby -O alicia.pub pcp1 -p -r Alicia -O bobby.pub
They've to exchange the public key somehow (which is not my
problem at the moment, use ssh, encrypted mail, whatever). Once exchanged,
they have to import it:
Alicia Bobby
pcp1 -K -I bobby.pub pcp1 -K -I alicia.pub
They will see a response as this when done:
key 0x29A323A2C295D391 added to .pcpvault.
Now, Alicia finally writes the secret message, encrypts it and
sends it to Bobby, who in turn decrypts it:
Alicia Bobby
echo "Love you, honey" > letter
pcp1 -e -r Bobby -I letter -O letter.asc
cat letter.asc | mail bobby@foo.bar
pcp1 -d -I letter.asc | less
And that's it.
Please note the big difference to B<GPG> though: both Alicia
AND Bobby have to enter the passphrase for their secret key!
That's the way CURVE25519 works: you encrypt a message using
your secret key and the recipients public key and the recipient
does the opposite, he uses his secret key and your public key
to actually decrypt the message.
Oh - and if you're wondering why I named them Alicia and Bobby:
I was just sick of Alice and Bob. We're running NSA-free, so we're
using other sample names as well.
=head1 FILES AND PIPES
Pcp behaves like any other unix tool. If not otherwise specified
it will read input from standard input (STDIN) and print output
to standard output (STDOUT). For instance:
pcp1 -e -O output
will read the text to be encrypted from standard input, because B<-I>
has not been specified. It works the same with B<-O>:
pcp1 -e -I myfile
In this case the encrypted result will be written to standard output.
Therefore it is possible to use pcp within pipes. Another more
realistic example:
ssh remote cat file | pcp1 -ez | mailx -s 'as requested' bob@somewhere
here we encrypt a file symmetrically without downloading it from a
remote ssh server and sending the encrypted result via email to
someone.
The behavior is the same with any other functionality where files are involved
like importing or exporting keys. However, there's one exception:
If the option B<-X> (B<--password-file>) has been used and is set
to B<->, then this will take precedence over any other possible use
of standard input. So if you want to encrypt something and don't
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
compiled from source. Follow these steps:
First, you will need libsodium:
git clone git://github.com/jedisct1/libsodium.git
cd libsodium
./autogen.sh
./configure && make check
sudo make install
sudo ldconfig
cd ..
Next, pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp
./configure
sudo make install
cd ..
Optionally, you might run the unit tests:
make test
=head1 DOCUMENTATION
To learn how to use B<pcp>, read the manpage:
man pcp1
=head1 COPYRIGHT
Copyright (c) 2013-2015 by T.v.Dein <tom AT vondein DOT org>
=head1 ADDITIONAL COPYRIGHTS
=over
=item B<ZeroMQ Z85 encoding routine>
Copyright (c) 2007-2013 iMatix Corporation
Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2010-2011 Miru Limited
Copyright (c) 2011 VMware, Inc.
Copyright (c) 2012 Spotify AB
=item B<Tarsnap readpass helpers>
Copyright 2009 Colin Percival
=item B<jen_hash() hash algorithm>
Bob Jenkins, Public Domain.
=item B<UTHASH hashing macros>
Copyright (c) 2003-2013, Troy D. Hanson
=item B<Random art image from OpenSSH keygen>
Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Comitted by Alexander von Gernler in rev 1.7.
=back
Every incorporated source code is opensource and licensed
under the B<GPL> as well.
=head1 AUTHORS
I<T.v.Dein <tom AT vondein DOT org>>
=head1 LICENSE
Licensed under the GNU GENERAL PUBLIC LICENSE version 3.
=head1 HOME
The homepage of Pretty Curved Privacy can be found on
http://www.daemon.de/PrettyCurvedPrivacy. The source is
on Github: https://github.com/TLINDEN/pcp
=cut

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 detach keysig generation from pub key export, so that an existing
keysig can be verified later. 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 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. 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 c++ destructor double free mess

View File

@@ -1 +1 @@
0.3.0 0.4.1

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; ./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; 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"'
- '%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

@@ -1,116 +0,0 @@
#!/bin/sh
mode=config
case $1 in
clean)
mode=clean
;;
gen)
mode=gen
;;
-h|--help|help|\?)
echo "Usage: $0 [clean|gen]"
exit 1
;;
esac
if test "$mode" = "gen"; then
# generate the install include file
(echo "#ifndef _HAVE_PCP"; echo "#define _HAVE_PCP"; echo) > include/pcp.h
(echo "#ifdef __cplusplus"; echo "extern \"C\" {"; echo "#endif"; echo) >> include/pcp.h
echo "#include \"pcp/config.h\"" >> include/pcp.h
ls include/pcp/*.h | sed 's#include/##' | while read include; do
echo "#include \"$include\"" >> include/pcp.h
done
(echo "#ifdef __cplusplus"; echo "}"; echo "#endif"; echo) >> include/pcp.h
(echo; echo "#endif") >> include/pcp.h
# generate the version file
maj=`egrep "#define PCP_VERSION_MAJOR" include/pcp/version.h | awk '{print $3}'`
min=`egrep "#define PCP_VERSION_MINOR" include/pcp/version.h | awk '{print $3}'`
pat=`egrep "#define PCP_VERSION_PATCH" include/pcp/version.h | awk '{print $3}'`
echo -n "$maj.$min.$pat" > VERSION
# generate the manpage
echo "=head1 NAME
Pretty Curved Privacy - File encryption using eliptic curve cryptography.
=head1 SYNOPSIS
" > man/pcp1.pod
cat src/usage.txt | sed "s/^/ /g" >> man/pcp1.pod
cat man/options.pod >> man/pcp1.pod
cat man/pcp.pod >> man/pcp1.pod
cat man/details.pod >> man/pcp1.pod
cat man/footer.pod >> man/pcp1.pod
pod2man -r "PCP `cat VERSION`" -c "USER CONTRIBUTED DOCUMENTATION" man/pcp1.pod > man/pcp1.1
pod2html man/pcp1.pod > man/pcp1.html
# generate the top level readme
cat man/badges man/pcp.pod man/install.pod man/footer.pod > README.pod
pod2text README.pod > README
# generate usage.h
(cd src && ./usage.sh)
# generate pypcp types
cd bindings/py
./gencffi.pl ../../include/pcp/*.h > pypcp/raw.py
cd -
exit
fi
if test "$mode" = "config"; then
mkdir -p ./config
if ! command -v libtoolize >/dev/null 2>&1; then
echo "could not find libtool." 1>&2
exit 1
fi
if ! command -v autoreconf >/dev/null 2>&1; then
echo "could not find autoreconf." 1>&2
exit 1
fi
autoreconf --install --force --verbose -I config
fi
#
# normal autogen stuff
cat <<EOF > clean.sh
#!/bin/sh
find . -name Makefile -exec rm {} \; > /dev/null 2>&1
find . -name Makefile.in -exec rm {} \; > /dev/null 2>&1
find . -name "*~" -exec rm {} \; > /dev/null 2>&1
find . -name config.h -exec rm {} \; > /dev/null 2>&1
find . -name "stamp*" -exec rm {} \; > /dev/null 2>&1
find . -name .deps -exec rm -rf {} \; > /dev/null 2>&1
find . -name .libs -exec rm -rf {} \; > /dev/null 2>&1
find . -name .o -exec rm -rf {} \; > /dev/null 2>&1
find . -name .lo -exec rm -rf {} \; > /dev/null 2>&1
find . -name .pyc -exec rm -rf {} \; > /dev/null 2>&1
find . -name .dirstamp -exec rm -rf {} \; > /dev/null 2>&1
rm -rf aclocal.m4 libtool configure config.* config autom4te.cache tests/test* tests/v* tests/stresstest/* libpcp/libpcp1.pc
rm clean.sh
EOF
chmod 700 clean.sh
rm -rf include/pcp/config.h.in~ libpcp/stamp-h1 autom4te.cache
sleep 1
touch Makefile.in configure */Makefile.in

View File

@@ -54,7 +54,7 @@ bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
Pcpstream *pin = ps_new_file(in); Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out); 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) if(clen <= 0)
throw exception(PTX); throw exception(PTX);
ps_close(pin); ps_close(pin);

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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). 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 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 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). 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 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 it under the terms of the GNU General Public License as published by

View File

@@ -87,19 +87,19 @@ foreach my $head (@ARGV) {
print "PCP_RAW_CODE = '''\n"; print "PCP_RAW_CODE = '''\n";
print qq( print qq(
typedef enum { typedef enum {
JSON_OBJECT, JSON_OBJECT,
JSON_ARRAY, JSON_ARRAY,
JSON_STRING, JSON_STRING,
JSON_INTEGER, JSON_INTEGER,
JSON_REAL, JSON_REAL,
JSON_TRUE, JSON_TRUE,
JSON_FALSE, JSON_FALSE,
JSON_NULL JSON_NULL
} json_type; } json_type;
typedef struct json_t { typedef struct json_t {
json_type type; json_type type;
size_t refcount; size_t refcount;
} json_t; } json_t;
); );
print join "\n", @typedefs; print join "\n", @typedefs;

View File

@@ -1,28 +1,28 @@
PCP_RAW_CODE = ''' PCP_RAW_CODE = '''
typedef enum { typedef enum {
JSON_OBJECT, JSON_OBJECT,
JSON_ARRAY, JSON_ARRAY,
JSON_STRING, JSON_STRING,
JSON_INTEGER, JSON_INTEGER,
JSON_REAL, JSON_REAL,
JSON_TRUE, JSON_TRUE,
JSON_FALSE, JSON_FALSE,
JSON_NULL JSON_NULL
} json_type; } json_type;
typedef struct json_t { typedef struct json_t {
json_type type; json_type type;
size_t refcount; size_t refcount;
} json_t; } json_t;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */ /*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned char byte; typedef unsigned char byte;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */ /*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned short dbyte; typedef unsigned short dbyte;
/*** ./gencffi.pl: from ../../include/pcp/defines.h:172 */ /*** ./gencffi.pl: from ../../include/pcp/defines.h:185 */
typedef unsigned int qbyte; typedef unsigned int qbyte;
/*** ./gencffi.pl: from ../../include/pcp/plist.h:83 */ /*** ./gencffi.pl: from ../../include/pcp/plist.h:83 */
@@ -84,14 +84,14 @@ struct _plist_t {
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */ /*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pcp_key_t { struct _pcp_key_t {
byte masterpub[32]; /**< ED25519 master public key signing key */ byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte mastersecret[64]; /**< ED25519 master secret key signing key */ byte mastersecret[LEDSEC]; /**< ED25519 master secret key signing key */
byte pub[32]; /**< Curve25519 encryption public key */ byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte secret[32]; /**< Curve25519 encryption secret key */ byte secret[LBOXSEC]; /**< Curve25519 encryption secret key */
byte edpub[32]; /**< ED25519 public signing key */ byte edpub[LEDPUB]; /**< ED25519 public signing key */
byte edsecret[64]; /**< ED25519 secret signing key */ byte edsecret[LEDSEC]; /**< ED25519 secret signing key */
byte nonce[24]; /**< random nonce used to encrypt secret keys */ byte nonce[LNONCE]; /**< random nonce used to encrypt secret keys */
byte encrypted[176]; /**< concatenated and encrypted secret keys */ byte encrypted[LSEC]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */ char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */ char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */ char id[17]; /**< key-id, used internally only, jenhash of public keys */
@@ -104,10 +104,9 @@ struct _pcp_key_t {
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */ /*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pcp_pubkey_t { struct _pcp_pubkey_t {
byte masterpub[32]; /**< ED25519 master public key signing key */ byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte sigpub[32]; /**< ED25519 public signing key */ byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte pub[32]; /**< Curve25519 encryption public key */ byte edpub[LEDPUB]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
byte edpub[32]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */ char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */ char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */ char id[17]; /**< key-id, used internally only, jenhash of public keys */
@@ -122,7 +121,7 @@ struct _pcp_pubkey_t {
/*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */ /*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _pbp_pubkey_t { struct _pbp_pubkey_t {
byte sigpub[32]; byte masterpub[32];
byte edpub[32]; byte edpub[32];
byte pub[32]; byte pub[32];
char iso_ctime[32]; char iso_ctime[32];
@@ -143,7 +142,7 @@ struct _pcp_keysig_t {
uint8_t type; uint8_t type;
uint32_t size; uint32_t size;
char id[17]; char id[17];
byte checksum[32]; byte checksum[LSHA];
byte *blob; byte *blob;
byte hh[56]; byte hh[56];
}; };
@@ -170,14 +169,14 @@ struct _vault_t {
time_t modified; /**< mtime */ time_t modified; /**< mtime */
mode_t mode; /**< File mode */ mode_t mode; /**< File mode */
uint32_t version; /**< Vault version */ 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 */ /*** ./gencffi.pl: from ../../include/pcp/structs.h:380 */
struct _vault_header_t { struct _vault_header_t {
uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */ uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */
uint32_t version; /**< File version */ 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 */ /*** ./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 */ uint8_t type; /**< Item type (secret key, public, key, keysig, \see _PCP_KEY_TYPES */
uint32_t size; /**< Size of the item */ uint32_t size; /**< Size of the item */
uint32_t version; /**< Version 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 */ /*** ./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 *cache; /**< The caching Buffer object (for look ahead read) */
Buffer *next; /**< The caching Next-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 */ 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 is_buffer; /**< Set to 1 if the backend is a Buffer */
uint8_t eof; /**< Set to 1 if EOF reached */ uint8_t eof; /**< Set to 1 if EOF reached */
uint8_t err; /**< Set to 1 if an error occured */ 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 */ /*** ./gencffi.pl: from ../../include/pcp/context.h:96 */
void ptx_dump(PCPCTX *ptx); void ptx_dump(PCPCTX *ptx);
/*** ./gencffi.pl: from ../../include/pcp/crypto.h:351 */ /*** ./gencffi.pl: from ../../include/pcp/crypto.h:354 */
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 */
size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, int havehead, pcp_rec_t *recsign); 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); 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); 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); 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); 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); 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); 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); uint64_t _get_nonce_ctr(byte *nonce);
/*** ./gencffi.pl: from ../../include/pcp/ed.h:202 */ /*** ./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 */ /*** ./gencffi.pl: from ../../include/pcp/jenhash.h:25 */
unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval ); 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 (); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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(); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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 */ /*** ./gencffi.pl: from ../../include/pcp/keyhash.h:153 */
void pcphash_del(PCPCTX *ptx, void *key, int type); 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 */ /*** ./gencffi.pl: from ../../include/pcp/keyhash.h:153 */
pcp_keysig_t *pcphash_keysigexists(PCPCTX *ptx, char *id); pcp_keysig_t *pcphash_keysigexists(PCPCTX *ptx, char *id);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */ /*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
pcp_keysig_t *keysig2be(pcp_keysig_t *s); void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */ /*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
pcp_keysig_t *keysig2native(pcp_keysig_t *s); Buffer *pcp_keysigblob(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */ /*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
Buffer *pcp_keysig2blob(pcp_keysig_t *s); pcp_keysig_t *pcp_blob2keysig(Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */ /*** ./gencffi.pl: from ../../include/pcp/keysig.h:50 */
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
/*** ./gencffi.pl: from ../../include/pcp/keysig.h:52 */
void pcp_dumpkeysig(pcp_keysig_t *s); void pcp_dumpkeysig(pcp_keysig_t *s);
/*** ./gencffi.pl: from ../../include/pcp/mem.h:58 */ /*** ./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 */ /*** ./gencffi.pl: from ../../include/pcp/mem.h:58 */
void sfree(void *d); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader);
/*** ./gencffi.pl: from ../../include/pcp/pcpstream.h:291 */ /*** ./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 */ /*** ./gencffi.pl: from ../../include/pcp/randomart.h:54 */
char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len); 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 */ /*** ./gencffi.pl: from ../../include/pcp/scrypt.h:42 */
byte * pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_t noncelen); 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); 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); 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); 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); 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); 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); 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 */ /*** ./gencffi.pl: from ../../include/pcp/vault.h:230 */
vault_t *pcpvault_init(PCPCTX *ptx, char *filename); 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 */ /*** ./gencffi.pl: from ../../include/pcp/zmq_z85.h:31 */
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);''' char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);'''
# ./gencffi.pl: from ../../include/pcp/defines.h:172 # ./gencffi.pl: from ../../include/pcp/defines.h:185
EXP_FORMAT_PBP = 2
# ./gencffi.pl: from ../../include/pcp/defines.h:172
PCP_ASYM_CIPHER = 5 PCP_ASYM_CIPHER = 5
# ./gencffi.pl: from ../../include/pcp/defines.h:172 # ./gencffi.pl: from ../../include/pcp/defines.h:185
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
PCP_BLOCK_SIZE = 32 * 1024 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 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

@@ -1,435 +0,0 @@
# -*-sh-*-
#
# This file is part of Pretty Curved Privacy (pcp1).
#
# Copyright (C) 2013-2015 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>.
#
AC_PREREQ(2.61)
define([pcpversion], esyscmd([sh -c "cat VERSION"]))dnl
AC_INIT([pcp], [pcpversion], [pcp@daemon.de])
#AC_INIT(pcp, `cat VERSION`)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR(config)
AC_CONFIG_HEADER(include/pcp/config.h)
AM_INIT_AUTOMAKE([subdir-objects])
LT_INIT
ORIG_CFLAGS="${CFLAGS:-none}"
# Checks for programs
AC_PROG_CXX
AC_PROG_CXXCPP
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
AC_PROG_SED
AC_PROG_AWK
AC_PROG_INSTALL
# remove flags set by AC_PROG_CC (duplicates and/or invalid for clang)
# FIXME: why did I do this?!
#CFLAGS=""
#CXXFLAGS=""
# Host speciffic checks
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)
AC_TYPE_SIZE_T
# Checks for library functions.
AC_CHECK_FUNCS( \
arc4random_buf \
arc4random \
fread \
fopen \
free \
fwrite \
fseek \
ftruncate \
fprintf \
isatty \
malloc \
memset \
memcpy \
mmap \
perror \
posix_memalign \
setrlimit \
strnlen \
strnstr \
strlen \
strtol \
sizeof \
tcgetattr \
umask \
towlower \
getopt_long \
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); ]])],
[ AC_MSG_RESULT([yes]) ],
[
AC_MSG_RESULT([no])
AC_MSG_ERROR([*** compiler cannot create working executables, check config.log ***])
],
[
AC_MSG_WARN([cross compiling: not checking compiler sanity])
[cross_compile="yes"]
]
)
_havenacl=no
_ldlib=""
_have_json=no
AC_ARG_WITH([libsodium],
[AS_HELP_STRING([--with-libsodium],
[Specify libsodium prefix])],
[search_libsodium="yes"],
[])
if test "x$search_libsodium" = "xyes"; then
if test -r "${with_libsodium}/include/sodium.h"; then
CFLAGS="-I${with_libsodium}/include ${CFLAGS}"
LDFLAGS="-L${with_libsodium}/lib ${LDFLAGS}"
_havenacl=yes
_ldlib="${with_libsodium}/lib"
fi
fi
AC_ARG_WITH([libsodium-include-dir],
[AS_HELP_STRING([--with-libsodium-include-dir],
[Specify libsodium include prefix])],
[search_libsodium_include="yes"],
[])
if test "x$search_libsodium_include" = "xyes"; then
if test -r "${with_libsodium_include_dir}/sodium.h"; then
CFLAGS="-I${with_libsodium_include_dir} ${CFLAGS}"
_havenacl=yes
fi
fi
AC_ARG_WITH([libsodium_lib_dir],
[AS_HELP_STRING([--with-libsodium-lib-dir],
[Specify libsodium library prefix])],
[search_libsodium_lib="yes"],
[])
if test "x$search_libsodium_lib" = "xyes"; then
if test -r "${with_libsodium_lib_dir}/libsodium.dylib" -o -r "${with_libsodium_lib_dir}/libsodium.so" -o -r "${with_libsodium_lib_dir}/libsodium.a"; then
LDFLAGS="-L${with_libsodium_lib_dir} ${LDFLAGS}"
_havenacl=yes
_ldlib="${with_libsodium_lib_dir}"
fi
fi
if test "x${_havenacl}" = "xno"; then
AC_MSG_CHECKING([pkg-config for libsodium])
if pkg-config --exists libsodium; then
# found it
LDFLAGS="`pkg-config --libs libsodium` ${LDFLAGS}"
CFLAGS="`pkg-config --cflags libsodium` ${CFLAGS}"
_ldlib=`pkg-config --libs libsodium | cut -d ' ' -f 1 | cut -d L -f 2`
_havenacl=yes
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
if test "x${_havenacl}" != "xno" -a "x$cross_compile" = "xno"; then
LIBS="-lsodium" # gcc
export LDFLAGS="$LDFLAGS"
export CFLAGS="$CFLAGS"
export LIBS="$LIBS"
AC_MSG_CHECKING([libsodium version compatible])
AC_RUN_IFELSE([
AC_LANG_PROGRAM([[
#include <sodium.h>
]],[[
if (sodium_library_version_major() >= 7) { exit(0); }
else { exit(1); }
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_ERROR([no, libsodium too old. please update your libsodium installation. or maybe the path in "$LDFLAGS" is not in LD_LIBRARY_PATH?])
]
)
fi
AC_ARG_WITH([json],
[AS_HELP_STRING([--with-json],
[enable JSON support])],
[search_json="yes"],
[])
if test "x$search_json" = "xyes"; then
# use pkg only
# FIXME: search
_have_json="yes"
LDFLAGS="$LDFLAGS -ljansson"
CFLAGS="$CFLAGS -DHAVE_JSON=1"
fi
AM_CONDITIONAL([BUILDJSON], [test "x$_have_json" = "xyes"])
# Check for some target-specific stuff
case "$host" in
*aix*)
# libm is required as well
CFLAGS="$CFLAGS -D_AIX_SOURCE=1"
LDFLAGS="$LDFLAGS -lm"
;;
*-*-android*) ;;
*-*-cygwin*) ;;
*-*-dgux*) ;;
*-*-darwin*) ;;
*-*-dragonfly*) ;;
*-*-haiku*) ;;
*-*-hpux*) ;;
*-*-irix5*) ;;
*-*-irix6*) ;;
*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) ;;
*-*-linux*) ;;
*-*-netbsd*) ;;
*-*-freebsd*)
# ports install to /usr/local by default, check
if test -d "/usr/local/lib" -a -d "/usr/local/include"; then
CFLAGS="$CFLAGS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
fi
;;
*-*-bsdi*) ;;
*-next-*) ;;
*-*-openbsd*) ;;
*-*-solaris*) ;;
*-*-sunos4*) ;;
*-ncr-sysv*) ;;
*-sni-sysv*) ;;
*-*-sysv4.2*) ;;
*-*-sysv5*) ;;
*-*-sysv*) ;;
*-*-sco*) ;;
*-*-unicos*) ;;
*-dec-osf*) ;;
*-*-nto-qnx*) ;;
*-*-ultrix*) ;;
*-*-lynxos) ;;
esac
AC_CHECK_LIB(sodium, sodium_init, , [AC_MSG_ERROR([cannot link with -lsodium, install libsodium.])])
if test -n "$_ldlib"; then
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${_ldlib}"
fi
if test "$cross_compile" = "no"; then
AC_MSG_CHECKING([is libsodium compiled correctly])
AC_RUN_IFELSE([
AC_LANG_PROGRAM([[
#include <sodium.h>
#include <stdlib.h>
#if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32 || crypto_sign_PUBLICKEYBYTES != 32 || crypto_sign_PUBLICKEYBYTES != 32
# error "libsodium not built correctly"
#endif
]],[[exit(0);]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_ERROR([no. please check your libsodium installation, consider re-installing])
]
)
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"
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--disable-debug], [Disable debugging]))
AS_IF([test "x$enable_debug" != "xno"], [
CFLAGS="$CFLAGS -g -DDEBUG"
enable_debug="yes"
])
AC_ARG_ENABLE([optimize],
AS_HELP_STRING([--disable-optimize], [Disable optimization]))
AS_IF([test "x$enable_optimize" != "xno"], [
case $enable_optimize in
-O*)
CFLAGS="$CFLAGS $enable_optimize"
enable_optimize="$enable_optimize"
;;
*)
CFLAGS="$CFLAGS -O2"
enable_optimize="-O2"
;;
esac
])
CXXFLAGS="$CFLAGS"
# conditionals for bindings and stuff
# c++
AC_ARG_ENABLE([cpp-binding],
[AS_HELP_STRING([--disable-cpp-binding],
[Disable C++ binding])],
)
AS_IF([test "x$enable_cpp_binding" != "xno"], [
enable_cpp_binding=yes
])
AM_CONDITIONAL([BUILDCPP], [test "x$enable_cpp_binding" != "xno"])
# py
AC_ARG_ENABLE([python-binding],
[AS_HELP_STRING([--enable-python-binding],
[Enable python binding])
],
[python="yes"],
[])
if test "x$python" = "xyes"; then
if ! python -c "import cffi" > /dev/null 2>&1; then
python="no"
AC_MSG_ERROR([python or cffi is not installed])
fi
else
python="no"
fi
AM_CONDITIONAL([BUILDPY], [test "x$python" = "xyes"])
AC_SUBST(PACKAGE_VERSION)
# Specify output files
AC_CONFIG_FILES([Makefile include/Makefile libpcp/Makefile src/Makefile man/Makefile \
tests/Makefile libpcp/libpcp1.pc bindings/cpp/Makefile bindings/py/Makefile])
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'.
])

View File

@@ -1,38 +0,0 @@
#
# 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>.
#
AM_CFLAGS = -I../include/pcp -Iscrypt/util
lib_LTLIBRARIES = libpcp1.la
pkgconfigdir = $(libdir)/pkgconfig
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 \
crypto.c ed.c keyhash.c scrypt.c \
util.c buffer.c mgmt.c keysig.c pcpstream.c
include_HEADERS = ../include/pcp.h
libpcp1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -95,7 +95,7 @@ void buffer_add_str(Buffer *b, const char * fmt, ...) {
if(vasprintf(&dst, fmt, ap) >= 0) { if(vasprintf(&dst, fmt, ap) >= 0) {
if(b->end > 0) if(b->end > 0)
b->end--; b->end--;
buffer_add(b, dst, strlen(dst)+1); buffer_add(b, dst, strlen(dst));
} }
va_end(ap); va_end(ap);
free(dst); free(dst);
@@ -221,30 +221,27 @@ uint64_t buffer_get64(Buffer *b) {
} }
uint16_t buffer_get16na(Buffer *b) { uint16_t buffer_get16na(Buffer *b) {
uint16_t i; uint8_t bin[2];
if(buffer_get_chunk(b, &i, 2) > 0) { if(buffer_get_chunk(b, bin, 2) > 0) {
i = be16toh(i); return _wireto16(bin);
return i;
} }
else else
return 0; return 0;
} }
uint32_t buffer_get32na(Buffer *b) { uint32_t buffer_get32na(Buffer *b) {
uint32_t i; uint8_t bin[4];
if(buffer_get_chunk(b, &i, 4) > 0) { if(buffer_get_chunk(b, bin, 4) > 0) {
i = be32toh(i); return _wireto32(bin);
return i;
} }
else else
return 0; return 0;
} }
uint64_t buffer_get64na(Buffer *b) { uint64_t buffer_get64na(Buffer *b) {
uint64_t i; uint8_t bin[8];
if(buffer_get_chunk(b, &i, 8) > 0) { if(buffer_get_chunk(b, bin, 8) > 0) {
i = be64toh(i); return _wireto64(bin);
return i;
} }
else else
return 0; return 0;
@@ -362,19 +359,19 @@ void buffer_add64(Buffer *b, uint64_t v) {
} }
void buffer_add16be(Buffer *b, uint16_t v) { void buffer_add16be(Buffer *b, uint16_t v) {
uint16_t e = v; uint8_t bin[2];
e = htobe16(e); _16towire(v, bin);
buffer_add(b, &e, 2); buffer_add(b, bin, 2);
} }
void buffer_add32be(Buffer *b, uint32_t v) { void buffer_add32be(Buffer *b, uint32_t v) {
uint32_t e = v; uint8_t bin[4];
e = htobe32(e); _32towire(v, bin);
buffer_add(b, &e, 4); buffer_add(b, bin, 4);
} }
void buffer_add64be(Buffer *b, uint64_t v) { void buffer_add64be(Buffer *b, uint64_t v) {
uint64_t e = v; uint8_t bin[8];
e = htobe64(e); _64towire(v, bin);
buffer_add(b, &e, 8); buffer_add(b, bin, 8);
} }

17
libpcp/config.h.in Normal file
View File

@@ -0,0 +1,17 @@
/* platform.h.in. Generated from configure.ac by autoheader. */
#mesondefine HAVE_SODIUM
#mesondefine HAVE_JSON
#mesondefine HAVE_GETOPT
#mesondefine HAVE_GETOPT_LONG
#mesondefine HAVE_SETRLIMIT
#mesondefine HAVE_VASPRINTF
#mesondefine HAVE_STRNLEN
#define PACKAGE "pcp"
#define VERSION "@VERSION@"
/* Define to empty if `const' does not conform to ANSI C. */
#undef const

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@
/* asym encr */ /* asym encr */
byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub, byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *message, size_t messagesize, byte *message, size_t messagesize,
@@ -44,14 +43,14 @@ byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
} }
/* put nonce and cipher together */ /* put nonce and cipher together */
byte *combined = ucmalloc(es + crypto_secretbox_NONCEBYTES); byte *combined = ucmalloc(es + LNONCE);
memcpy(combined, nonce, crypto_secretbox_NONCEBYTES); memcpy(combined, nonce, LNONCE);
memcpy(&combined[crypto_secretbox_NONCEBYTES], cipher, es); memcpy(&combined[LNONCE], cipher, es);
free(cipher); free(cipher);
free(nonce); free(nonce);
*csize = es + crypto_secretbox_NONCEBYTES; *csize = es + LNONCE;
return combined; return combined;
@@ -71,15 +70,15 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *message = NULL; byte *message = NULL;
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES); byte *nonce = ucmalloc(LNONCE);
byte *cipheronly = ucmalloc(ciphersize - crypto_secretbox_NONCEBYTES); byte *cipheronly = ucmalloc(ciphersize - LNONCE);
memcpy(nonce, cipher, crypto_secretbox_NONCEBYTES); memcpy(nonce, cipher, LNONCE);
memcpy(cipheronly, &cipher[crypto_secretbox_NONCEBYTES], memcpy(cipheronly, &cipher[LNONCE],
ciphersize - crypto_secretbox_NONCEBYTES); ciphersize - LNONCE);
message = ucmalloc(ciphersize - crypto_secretbox_NONCEBYTES - crypto_box_MACBYTES); message = ucmalloc(ciphersize - LNONCE - crypto_box_MACBYTES);
if(crypto_box_open_easy(message, cipheronly, ciphersize - crypto_secretbox_NONCEBYTES, if(crypto_box_open_easy(message, cipheronly, ciphersize - LNONCE,
nonce, pub->pub, secret->secret) != 0) { nonce, pub->pub, secret->secret) != 0) {
fatal(ptx, "failed to decrypt message!\n"); fatal(ptx, "failed to decrypt message!\n");
goto errbed; goto errbed;
@@ -90,7 +89,7 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
/* resulting size: */ /* resulting size: */
/* ciphersize - crypto_secretbox_ZEROBYTES */ /* ciphersize - crypto_secretbox_ZEROBYTES */
*dsize = ciphersize - crypto_secretbox_NONCEBYTES - PCP_CRYPTO_ADD; *dsize = ciphersize - LNONCE - LMAC;
return message; return message;
errbed: errbed:
@@ -109,10 +108,10 @@ size_t pcp_sodium_mac(byte **cipher,
byte *nonce, byte *nonce,
byte *key) { byte *key) {
*cipher = ucmalloc(clearsize + crypto_secretbox_MACBYTES); *cipher = ucmalloc(clearsize + LMAC);
crypto_secretbox_easy(*cipher, cleartext, clearsize, nonce, key); crypto_secretbox_easy(*cipher, cleartext, clearsize, nonce, key);
return clearsize + crypto_secretbox_MACBYTES; return clearsize + LMAC;
} }
/* sym decr */ /* sym decr */
@@ -120,13 +119,12 @@ int pcp_sodium_verify_mac(byte **cleartext, byte* message,
size_t messagesize, byte *nonce, size_t messagesize, byte *nonce,
byte *key) { byte *key) {
*cleartext = ucmalloc(messagesize - crypto_secretbox_MACBYTES);
return crypto_secretbox_open_easy(*cleartext, message, messagesize, nonce, key); 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) { 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; byte *reccipher = NULL;
int recmatch, self; int recmatch, self;
uint32_t lenrec; uint32_t lenrec;
@@ -158,6 +156,11 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
self = 0; self = 0;
anon = 1; anon = 1;
} }
else if(head[0] == PCP_ASYM_CIPHER_ANON_SIG) {
self = 0;
anon = 1;
verify = 1;
}
else if(head[0] == PCP_ASYM_CIPHER) { else if(head[0] == PCP_ASYM_CIPHER) {
self = 0; self = 0;
} }
@@ -172,6 +175,11 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
} }
} }
if(ptx->verbose) {
fprintf(stderr, "crypto.c: header <= self: %d, anon: %d, verify:%d\n",
self, anon, verify);
}
if(self) { if(self) {
/* just decrypt symetrically and go outa here */ /* just decrypt symetrically and go outa here */
return pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL); return pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
@@ -185,22 +193,31 @@ 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"); fatal(ptx, "Error: input file doesn't contain senders public key\n");
goto errdef1; goto errdef1;
} }
if(ptx->verbose) {
fprintf(stderr, "crypto.c: <= sender anon pub key:\n");
pcp_dumppubkey(senderpub);
}
} }
/* step 3, check len recipients */ /* 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)) { if(cur_bufsize != 4 && !ps_end(in) && !ps_err(in)) {
fatal(ptx, "Error: input file doesn't contain recipient count\n"); fatal(ptx, "Error: input file doesn't contain recipient count\n");
goto errdef1; 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) { if(verify) {
reccipher = ucmalloc(lenrec * PCP_ASYM_RECIPIENT_SIZE); reccipher = ucmalloc(lenrec * PCP_ASYM_RECIPIENT_SIZE);
} }
/* step 4, fetch recipient list and try to decrypt it for us */ /* step 4, fetch recipient list and try to decrypt it for us */
rec_buf = ucmalloc(PCP_ASYM_RECIPIENT_SIZE); rec_buf = ucmalloc(PCP_ASYM_RECIPIENT_SIZE);
for(nrec=0; nrec<lenrec; nrec++) { for(nrec=0; nrec<lenrec; nrec++) {
@@ -213,6 +230,10 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
} }
recmatch = 0; recmatch = 0;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: <= rec_cipher:\n");
_dump("crypto.c: encrypted rec cipher", rec_buf, cur_bufsize);
}
if(anon) { if(anon) {
/* anonymous sender */ /* anonymous sender */
byte *recipient; byte *recipient;
@@ -224,6 +245,15 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES); memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient); free(recipient);
ucfree(senderpub, sizeof(pcp_pubkey_t)); 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; break;
} }
free(recipient); free(recipient);
@@ -239,6 +269,13 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
symkey = smalloc(crypto_secretbox_KEYBYTES); symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES); memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient); 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; break;
} }
free(recipient); free(recipient);
@@ -248,15 +285,24 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
if(recmatch == 0) { if(recmatch == 0) {
pcp_key_t *k; pcp_key_t *k;
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) {
cur = pcpkey_pub_from_secret(k); if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t)); /* avoid overwrite of used mem */
fromsec = pcpkey_pub_from_secret(k);
byte *recipient; byte *recipient;
recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size); recipient = pcp_box_decrypt(ptx, s, fromsec, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) { if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */ /* found a match */
recmatch = 1; recmatch = 1;
symkey = smalloc(crypto_secretbox_KEYBYTES); symkey = smalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES); memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient); free(recipient);
cur = fromsec;
if(ptx->verbose) {
_dump("crypto.c: got my own sec symkey", symkey, crypto_secretbox_KEYBYTES);
}
break; break;
} }
} }
@@ -278,34 +324,39 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
/* step 5, actually decrypt the file, finally */ /* step 5, actually decrypt the file, finally */
if(verify) { if(verify) {
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur); 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); nrec = pcp_decrypt_stream_sym(ptx, in, out, symkey, rec);
pcp_rec_free(rec); pcp_rec_free(rec);
ucfree(reccipher, lenrec * PCP_ASYM_RECIPIENT_SIZE); ucfree(reccipher, lenrec * PCP_ASYM_RECIPIENT_SIZE);
sfree(symkey);
return s;
} }
else { else {
size_t s = pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL); nrec = pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
sfree(symkey);
return s;
} }
if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t));
sfree(symkey);
return nrec;
errdef1: errdef1:
if(fromsec != NULL)
ucfree(fromsec, sizeof(pcp_pubkey_t));
sfree(symkey); sfree(symkey);
return 0; 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; byte *symkey;
int recipient_count; int recipient_count;
byte *recipients_cipher; byte *recipients_cipher;
pcp_pubkey_t *cur, *t; pcp_pubkey_t *cur, *t;
size_t es; size_t es;
int nrec; int nrec;
uint32_t lenrec;
size_t rec_size, out_size; size_t rec_size, out_size;
byte head[1]; byte head[1];
byte bo[4];
/* /*
6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...) 6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...)
@@ -317,15 +368,23 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
/* A, generate sym key */ /* A, generate sym key */
symkey = srmalloc(crypto_secretbox_KEYBYTES); symkey = srmalloc(crypto_secretbox_KEYBYTES);
if(ptx->verbose) {
_dump("crypto.c: new symkey", symkey, crypto_secretbox_KEYBYTES);
}
/* B, encrypt it asymetrically for each recipient */ /* B, encrypt it asymetrically for each recipient */
recipient_count = HASH_COUNT(p); recipient_count = HASH_COUNT(p);
rec_size = PCP_ASYM_RECIPIENT_SIZE; rec_size = PCP_ASYM_RECIPIENT_SIZE;
recipients_cipher = ucmalloc(rec_size * recipient_count); recipients_cipher = ucmalloc(rec_size * recipient_count);
nrec = 0; nrec = 0;
if(ptx->verbose) {
fprintf(stderr, "crypto.c: async recipients: %d\n", recipient_count);
}
HASH_ITER(hh, p, cur, t) { HASH_ITER(hh, p, cur, t) {
byte *rec_cipher; 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) { if(es != rec_size) {
fatal(ptx, "invalid rec_size, expected %dl, got %dl\n", rec_size, es); fatal(ptx, "invalid rec_size, expected %dl, got %dl\n", rec_size, es);
if(rec_cipher != NULL) if(rec_cipher != NULL)
@@ -333,6 +392,12 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
goto errec1; 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 */ /* put it into the recipient list, already includes the nonce */
memcpy(&recipients_cipher[nrec * rec_size], rec_cipher, rec_size); memcpy(&recipients_cipher[nrec * rec_size], rec_cipher, rec_size);
nrec++; nrec++;
@@ -340,7 +405,14 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
} }
/* step 1, file header */ /* step 1, file header */
if(sign) 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; head[0] = PCP_ASYM_CIPHER_SIG;
else if(anon) else if(anon)
head[0] = PCP_ASYM_CIPHER_ANON; head[0] = PCP_ASYM_CIPHER_ANON;
@@ -355,26 +427,25 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
if(anon) { if(anon) {
/* step 2, sender's pubkey */ /* step 2, sender's pubkey */
ps_write(out, s->pub, crypto_box_PUBLICKEYBYTES); ps_write(out, secret->pub, crypto_box_PUBLICKEYBYTES);
/*fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out); */
/* fprintf(stderr, "D: sender pub - %d\n", crypto_box_PUBLICKEYBYTES); */
if(ps_err(out) != 0) if(ps_err(out) != 0)
goto errec1; 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 */ /* step 3, len recipients, big endian */
lenrec = recipient_count;
lenrec = htobe32(lenrec); _32towire(recipient_count, bo);
ps_write(out, &lenrec, 4); ps_write(out, bo, 4);
/* fwrite(&lenrec, 4, 1, out); */
/* fprintf(stderr, "D: %d recipients - 4\n", recipient_count); */
if(ps_err(out) != 0) if(ps_err(out) != 0)
goto errec1; goto errec1;
/* step 4, recipient list */ /* step 4, recipient list */
ps_write(out, recipients_cipher, rec_size * recipient_count); 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) if(ps_err(out) != 0)
goto errec1; 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 */ /* step 5, actual encrypted data */
size_t sym_size = 0; size_t sym_size = 0;
if(sign) { 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); sym_size = pcp_encrypt_stream_sym(ptx, in, out, symkey, 1, rec);
pcp_rec_free(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) { if(havehead == 0) {
head[0] = PCP_SYM_CIPHER; head[0] = PCP_SYM_CIPHER;
es = ps_write(out, head, 1); es = ps_write(out, head, 1);
/* es = fwrite(head, 1, 1, out); */
if(ps_err(out) != 0) { if(ps_err(out) != 0) {
fatal(ptx, "Failed to write encrypted output!\n"); fatal(ptx, "Failed to write encrypted output!\n");
return 0; return 0;
} }
if(ptx->verbose) {
fprintf(stderr, "crypto.c: => header: self: 1\n");
}
} }
/* 32k-Block-mode. */ /* 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++); buf_nonce = _gen_ctr_nonce(ctr++);
es = pcp_sodium_mac(&buf_cipher, in_buf, cur_bufsize, buf_nonce, symkey); 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); ps_write(out, buf_cipher, es);
out_size += crypto_secretbox_NONCEBYTES + es; out_size += LNONCE + es;
if(recsign != NULL) if(recsign != NULL)
crypto_generichash_update(st, buf_cipher, es); crypto_generichash_update(st, buf_cipher, es);
ucfree(buf_nonce, crypto_secretbox_NONCEBYTES); ucfree(buf_nonce, LNONCE);
free(buf_cipher); free(buf_cipher);
} }
@@ -479,22 +552,28 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
if(recsign != NULL) { if(recsign != NULL) {
/* add encrypted recipient list to the hash */ /* add encrypted recipient list to the hash */
crypto_generichash_update(st, recsign->cipher, recsign->ciphersize); 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 */ /* generate the actual signature */
byte *signature = pcp_ed_sign(hash, crypto_generichash_BYTES_MAX, recsign->secret); byte *signature = pcp_ed_sign(hash, LHASH, recsign->secret);
size_t siglen = crypto_sign_BYTES + crypto_generichash_BYTES_MAX; size_t siglen = LSIG + LHASH;
/* encrypt it as well */ /* encrypt it as well */
buf_nonce = pcp_gennonce(); buf_nonce = pcp_gennonce();
es = pcp_sodium_mac(&buf_cipher, signature, siglen, buf_nonce, symkey); 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); 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(st);
free(hash); free(hash);
ucfree(buf_nonce, crypto_secretbox_NONCEBYTES); ucfree(buf_nonce, LNONCE);
free(buf_cipher); free(buf_cipher);
ucfree(signature, siglen); ucfree(signature, siglen);
} }
@@ -512,17 +591,18 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte *
return 0; 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_nonce;
byte *buf_cipher; byte *buf_cipher;
byte *buf_clear; byte *buf_clear;
size_t out_size, cur_bufsize, es; 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; byte *in_buf = NULL;
uint64_t ctr, pastctr; uint64_t ctr, pastctr;
pastctr = 0; pastctr = 0;
buf_nonce = ucmalloc(crypto_secretbox_NONCEBYTES); buf_nonce = ucmalloc(LNONCE);
buf_cipher = ucmalloc(ciphersize); buf_cipher = ucmalloc(ciphersize);
buf_clear = ucmalloc(ciphersize); buf_clear = ucmalloc(ciphersize);
out_size = 0; 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 = NULL;
byte *signature_cr = NULL; byte *signature_cr = NULL;
size_t siglen = crypto_sign_BYTES + crypto_generichash_BYTES_MAX; 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; crypto_generichash_state *st = NULL;
byte *hash = NULL; byte *hash = NULL;
@@ -539,13 +619,14 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
hash = ucmalloc(crypto_generichash_BYTES_MAX); hash = ucmalloc(crypto_generichash_BYTES_MAX);
crypto_generichash_init(st, NULL, 0, 0); crypto_generichash_init(st, NULL, 0, 0);
signature_cr = ucmalloc(siglen_cr); signature_cr = ucmalloc(siglen_cr);
signature = ucmalloc(siglen);
} }
in_buf = ucmalloc(PCP_BLOCK_SIZE_IN); in_buf = ucmalloc(PCP_BLOCK_SIZE_IN);
while(!ps_end(in)) { while(!ps_end(in)) {
cur_bufsize = ps_read(in, in_buf, PCP_BLOCK_SIZE_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 */ break; /* no valid cipher block */
if(recverify != NULL) { if(recverify != NULL) {
@@ -556,9 +637,9 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
} }
} }
ciphersize = cur_bufsize - crypto_secretbox_NONCEBYTES; ciphersize = cur_bufsize - LNONCE;
memcpy(buf_nonce, in_buf, crypto_secretbox_NONCEBYTES); memcpy(buf_nonce, in_buf, LNONCE);
memcpy(buf_cipher, &in_buf[crypto_secretbox_NONCEBYTES], ciphersize); memcpy(buf_cipher, &in_buf[LNONCE], ciphersize);
/* extract counter from nonce and check if it is in line with previous one /* 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 TODO: save unordered buffers to disk and continue writing to out if
@@ -573,10 +654,10 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
pastctr = ctr; pastctr = ctr;
es = pcp_sodium_verify_mac(&buf_clear, buf_cipher, ciphersize, buf_nonce, symkey); 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) { if(es == 0) {
ps_write(out, buf_clear, ciphersize - PCP_CRYPTO_ADD); ps_write(out, buf_clear, ciphersize - LMAC);
if(recverify != NULL) if(recverify != NULL)
crypto_generichash_update(st, buf_cipher, ciphersize); crypto_generichash_update(st, buf_cipher, ciphersize);
@@ -596,31 +677,51 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
ucfree(in_buf, PCP_BLOCK_SIZE_IN); ucfree(in_buf, PCP_BLOCK_SIZE_IN);
ucfree(buf_cipher, ciphersize); ucfree(buf_cipher, ciphersize);
ucfree(buf_clear, ciphersize - PCP_CRYPTO_ADD); ucfree(buf_clear, ciphersize - LMAC);
if(recverify != NULL) { if(recverify != NULL) {
/* decrypt the signature */ /* 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], es = pcp_sodium_verify_mac(&signature, &signature_cr[LNONCE],
siglen_cr - crypto_secretbox_NONCEBYTES, buf_nonce, symkey); siglen_cr - LNONCE, buf_nonce, symkey);
if(es == 0) { if(es == 0) {
/* add encrypted recipient list to the hash */ /* add encrypted recipient list to the hash */
crypto_generichash_update(st, recverify->cipher, recverify->ciphersize); crypto_generichash_update(st, recverify->cipher, recverify->ciphersize);
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX); crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
byte *verifiedhash = NULL; byte *verifiedhash = NULL;
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 {
verifiedhash = pcp_ed_verify(ptx, signature, siglen, recverify->pub); verifiedhash = pcp_ed_verify(ptx, signature, siglen, recverify->pub);
}
if(verifiedhash == NULL) if(verifiedhash == NULL)
out_size = 0; out_size = 0;
else { else {
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 match */ /* sig verified, but the hash doesn't match */
fatal(ptx, "signed hash doesn't match actual hash of signed decrypted file content\n"); fatal(ptx, "signed hash doesn't match actual hash of signed decrypted file content\n");
out_size = 0; out_size = 0;
} }
free(verifiedhash); 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 { else {
fatal(ptx, "Failed to decrypt signature!\n"); fatal(ptx, "Failed to decrypt signature!\n");
@@ -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); r->cipher = ucmalloc(clen);
memcpy(r->cipher, cipher, clen); memcpy(r->cipher, cipher, clen);
r->ciphersize = clen; r->ciphersize = clen;
if(secret != NULL) { if(secret != NULL) {
r->secret = ucmalloc(sizeof(pcp_key_t)); r->secret = ucmalloc(sizeof(pcp_key_t));
memcpy(r->secret, secret, sizeof(pcp_key_t)); memcpy(r->secret, secret, sizeof(pcp_key_t));
@@ -690,8 +790,6 @@ void pcp_rec_free(pcp_rec_t *r) {
uint64_t _get_nonce_ctr(byte *nonce) { uint64_t _get_nonce_ctr(byte *nonce) {
uint64_t ctr = 0; uint64_t ctr = 0;
uint8_t i = nonce[0]; uint8_t i = nonce[0];
uint16_t m16 = 0;
uint32_t m32 = 0;
if(i > 16) { if(i > 16) {
/* counter bigger than max allowed by protocol, could lead to overflow, therefore die hard here */ /* counter bigger than max allowed by protocol, could lead to overflow, therefore die hard here */
@@ -704,16 +802,13 @@ uint64_t _get_nonce_ctr(byte *nonce) {
ctr = nonce[1]; ctr = nonce[1];
break; break;
case 2: case 2:
memcpy(&m16, &nonce[1], 2); ctr = _wireto16(&nonce[1]);
ctr = be16toh(m16);
break; break;
case 4: case 4:
memcpy(&m32, &nonce[1], 4); ctr = _wireto32(&nonce[1]);
ctr = be32toh(m32);
break; break;
case 8: case 8:
memcpy(&ctr, &nonce[1], 8); ctr = _wireto64(&nonce[1]);
ctr = be64toh(ctr);
break; break;
} }
@@ -777,25 +872,21 @@ byte *_gen_ctr_nonce(uint64_t ctr) {
uint8_t m8 = -1; uint8_t m8 = -1;
uint16_t m16 = -1; uint16_t m16 = -1;
uint32_t m32 = -1; uint32_t m32 = -1;
uint64_t m64 = -1;
uint8_t i = 1; uint8_t i = 1;
byte *nonce = pcp_gennonce(); byte *nonce = pcp_gennonce();
if(ctr > m32) { if(ctr > m32) {
i = 8; i = 8;
m64 = htobe64(ctr); _64towire(ctr, &nonce[1]);
memcpy(&nonce[1], &m64, 8);
} }
else if(ctr < m32 && ctr > m16) { else if(ctr <= m32 && ctr > m16) {
i = 4; i = 4;
m32 = htobe32(ctr); _32towire(ctr, &nonce[1]);
memcpy(&nonce[1], &m32, 4);
} }
else if(ctr < m16 && ctr > m8) { else if(ctr <= m16 && ctr > m8) {
i = 2; i = 2;
m16 = htobe16(ctr); _16towire(ctr, &nonce[1]);
memcpy(&nonce[1], &m16, 2);
} }
else { else {
i = 1; i = 1;

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -301,7 +301,7 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
if(verifiedhash == NULL) if(verifiedhash == NULL)
goto errvb1; 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 */ /* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n"); fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
free(verifiedhash); free(verifiedhash);
@@ -441,7 +441,7 @@ pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream
if(verifiedhash == NULL) if(verifiedhash == NULL)
goto errdea4; 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 */ /* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n"); fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
goto errdea5; goto errdea5;

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -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[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. \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. \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. /** Symmetrically encrypt a file or a buffer stream.

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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 short dbyte; /* Double byte = 16 bits */
typedef unsigned int qbyte; /* Quad byte = 32 bits */ typedef unsigned int qbyte; /* Quad byte = 32 bits */
/* key stuff, deprecated. */ /* key stuff, deprecated. */
#define PCP_ENFILE_HEADER "----- BEGIN PCP ENCRYPTED FILE -----\r\n" #define PCP_ENFILE_HEADER "----- BEGIN PCP ENCRYPTED FILE -----\r\n"
#define PCP_ENFILE_FOOTER "\r\n----- END 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 */ /* vault id */
#define PCP_VAULT_ID 14 #define PCP_VAULT_ID 14
@@ -115,13 +127,14 @@ typedef enum _PCP_KEY_TYPES {
/* crypto file format stuff */ /* crypto file format stuff */
#define PCP_ASYM_CIPHER 5 #define PCP_ASYM_CIPHER 5
#define PCP_ASYM_CIPHER_ANON 6 #define PCP_ASYM_CIPHER_ANON 6
#define PCP_ASYM_CIPHER_ANON_SIG 7
#define PCP_SYM_CIPHER 23 #define PCP_SYM_CIPHER 23
#define PCP_ASYM_CIPHER_SIG 24 #define PCP_ASYM_CIPHER_SIG 24
#define PCP_BLOCK_SIZE 32 * 1024 #define PCP_BLOCK_SIZE 32 * 1024
#define PCP_CRYPTO_ADD (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) //#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_BLOCK_SIZE_IN (PCP_BLOCK_SIZE) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
#define PCP_ASYM_RECIPIENT_SIZE crypto_secretbox_KEYBYTES + PCP_CRYPTO_ADD + crypto_secretbox_NONCEBYTES #define PCP_ASYM_RECIPIENT_SIZE crypto_secretbox_KEYBYTES + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
/* #define PCP_ASYM_ADD_SENDER_PUB */ /* #define PCP_ASYM_ADD_SENDER_PUB */

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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). 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 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 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) #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 */ /* 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 */ /* 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 */ /* debug print a keysig */
void pcp_dumpkeysig(pcp_keysig_t *s); void pcp_dumpkeysig(pcp_keysig_t *s);

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -27,44 +27,49 @@
#define _HAVE_PCP_MGMT_H #define _HAVE_PCP_MGMT_H
#if defined __linux__ || defined __GNU__ || defined __GLIBC__ #if defined __linux__ || defined __GNU__ || defined __GLIBC__
# ifndef _DEFAULT_SOURCE #ifndef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE 1 #define _DEFAULT_SOURCE 1
# endif #endif
# #
# ifndef _XOPEN_SOURCE #ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 1 #define _XOPEN_SOURCE 1
# endif #endif
#
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#
#ifndef __USE_XOPEN
#define __USE_XOPEN 1
#endif
# #
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif
#else #else
# define _BSD_SOURCE 1 #define _BSD_SOURCE 1
#endif #endif
#include <sodium.h> #include <sodium.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <time.h> #include <time.h>
#ifdef HAVE_JSON // #ifdef HAVE_JSON
#ifndef JANSSON_H
#include <jansson.h> #include <jansson.h>
#endif #endif
#include "buffer.h"
#include "context.h"
#include "defines.h" #include "defines.h"
#include "platform.h"
#include "structs.h"
#include "mem.h"
#include "ed.h" #include "ed.h"
#include "key.h" #include "key.h"
#include "keysig.h" #include "keysig.h"
#include "buffer.h" #include "mem.h"
#include "platform.h"
#include "scrypt.h" #include "scrypt.h"
#include "context.h" #include "structs.h"
/* key management api, export, import, and stuff */ /* key management api, export, import, and stuff */
/** /**
* \defgroup PubKeyExport KEYEXPORT * \defgroup PubKeyExport KEYEXPORT
* @{ * @{
@@ -72,10 +77,6 @@
Functions to export and import keys in various formats. Functions to export and import keys in various formats.
*/ */
/** RFC4880 alike public key export with some modifications. /** RFC4880 alike public key export with some modifications.
(Refer to the INTERNALS section of the pcp(1) manual page for details. (Refer to the INTERNALS section of the pcp(1) manual page for details.
@@ -87,9 +88,7 @@
blob in the format described above. blob in the format described above.
*/ */
Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk); Buffer *pcp_export_rfc_pub(PCPCTX *ptx, pcp_key_t *sk);
/** Export a public key in PBP format. /** Export a public key in PBP format.
Export a public key in the format described at Export a public key in the format described at
@@ -105,7 +104,8 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
/** Export secret key. /** Export secret key.
Export a secret key. (refer to the INTERNALS section of the pcp(1) manual page for details). Export a secret key. (refer to the INTERNALS section of the pcp(1) manual
page for details).
\param[in] ptx context. \param[in] ptx context.
@@ -130,7 +130,8 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase);
\return the function returns a Buffer object containing the binary \return the function returns a Buffer object containing the binary
blob containing a JSON string. blob containing a JSON string.
*/ */
Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen); Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig,
size_t siglen);
/** Export secret key in JSON format /** Export secret key in JSON format
@@ -143,7 +144,8 @@ Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen
\return the function returns a Buffer object containing the binary \return the function returns a Buffer object containing the binary
blob containing a JSON string. blob containing a JSON string.
*/ */
Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen); Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce,
byte *cipher, size_t clen);
/** Convert secret key struct into JSON struct /** Convert secret key struct into JSON struct
@@ -152,7 +154,7 @@ Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *ci
\return returns a json_t structure (see libjansson docs for details) \return returns a json_t structure (see libjansson docs for details)
*/ */
json_t *pcp_sk2json(pcp_key_t *sk, byte *sig,size_t siglen); json_t *pcp_sk2json(pcp_key_t *sk, byte *sig, size_t siglen);
/** Convert public key struct into JSON struct /** Convert public key struct into JSON struct
@@ -174,14 +176,19 @@ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob);
pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob); pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob);
/* import secret key */ /* import secret key */
pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize,
pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); char *passphrase);
pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase); pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize,
char *passphrase);
pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher,
char *passphrase);
/* helpers */ /* helpers */
int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h); int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h);
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk); int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p,
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader); pcp_keysig_t *sk);
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p,
rfc_pub_sig_s *subheader);
#endif // _HAVE_PCP_MGMT_H #endif // _HAVE_PCP_MGMT_H

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -25,47 +25,6 @@
#include "config.h" #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 #ifndef HAVE_ARC4RANDOM
#include <sodium.h> #include <sodium.h>
#define arc4random() randombytes_random() #define arc4random() randombytes_random()

View File

@@ -35,9 +35,14 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "defines.h" #include "defines.h"
#include "context.h" #include "context.h"
#include "pcp.h" #include "util.h"
#define MAXPASSLEN 2048 #define MAXPASSLEN 2048
@@ -52,6 +57,13 @@
* ${passwd}. The obscure name is to avoid namespace collisions due to the * ${passwd}. The obscure name is to avoid namespace collisions due to the
* getpass / readpass / readpassphrase / etc. functions in various libraries. * 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_ */ #endif /* !_READPASS_H_ */

View File

@@ -70,14 +70,14 @@
*/ */
struct _pcp_key_t { struct _pcp_key_t {
byte masterpub[32]; /**< ED25519 master public key signing key */ byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte mastersecret[64]; /**< ED25519 master secret key signing key */ byte mastersecret[LEDSEC]; /**< ED25519 master secret key signing key */
byte pub[32]; /**< Curve25519 encryption public key */ byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte secret[32]; /**< Curve25519 encryption secret key */ byte secret[LBOXSEC]; /**< Curve25519 encryption secret key */
byte edpub[32]; /**< ED25519 public signing key */ byte edpub[LEDPUB]; /**< ED25519 public signing key */
byte edsecret[64]; /**< ED25519 secret signing key */ byte edsecret[LEDSEC]; /**< ED25519 secret signing key */
byte nonce[24]; /**< random nonce used to encrypt secret keys */ byte nonce[LNONCE]; /**< random nonce used to encrypt secret keys */
byte encrypted[176]; /**< concatenated and encrypted secret keys */ byte encrypted[LSEC]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */ char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */ char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */ char id[17]; /**< key-id, used internally only, jenhash of public keys */
@@ -99,10 +99,9 @@ typedef struct _pcp_key_t pcp_key_t;
without the secret and nonce fields. without the secret and nonce fields.
*/ */
struct _pcp_pubkey_t { struct _pcp_pubkey_t {
byte masterpub[32]; /**< ED25519 master public key signing key */ byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte sigpub[32]; /**< ED25519 public signing key */ byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte pub[32]; /**< Curve25519 encryption public key */ byte edpub[LEDPUB]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
byte edpub[32]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */ char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */ char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */ char id[17]; /**< key-id, used internally only, jenhash of public keys */
@@ -122,7 +121,7 @@ typedef struct _pcp_pubkey_t pcp_pubkey_t;
/* the PBP public key format */ /* the PBP public key format */
/* keys.mp+keys.cp+keys.sp+keys.name */ /* keys.mp+keys.cp+keys.sp+keys.name */
struct _pbp_pubkey_t { struct _pbp_pubkey_t {
byte sigpub[crypto_sign_PUBLICKEYBYTES]; byte masterpub[crypto_sign_PUBLICKEYBYTES];
byte edpub[crypto_sign_PUBLICKEYBYTES]; byte edpub[crypto_sign_PUBLICKEYBYTES];
byte pub[crypto_box_PUBLICKEYBYTES]; byte pub[crypto_box_PUBLICKEYBYTES];
char iso_ctime[32]; char iso_ctime[32];
@@ -158,7 +157,7 @@ struct _pcp_keysig_t {
uint8_t type; uint8_t type;
uint32_t size; uint32_t size;
char id[17]; char id[17];
byte checksum[32]; byte checksum[LSHA];
byte *blob; byte *blob;
UT_hash_handle hh; UT_hash_handle hh;
}; };
@@ -229,7 +228,7 @@ struct _vault_t {
time_t modified; /**< mtime */ time_t modified; /**< mtime */
mode_t mode; /**< File mode */ mode_t mode; /**< File mode */
uint32_t version; /**< Vault version */ 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 */ /** Name of the struct */
@@ -240,7 +239,7 @@ typedef struct _vault_t vault_t;
struct _vault_header_t { struct _vault_header_t {
uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */ uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */
uint32_t version; /**< File version */ 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 */ /** 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 */ uint8_t type; /**< Item type (secret key, public, key, keysig, \see _PCP_KEY_TYPES */
uint32_t size; /**< Size of the item */ uint32_t size; /**< Size of the item */
uint32_t version; /**< Version 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 */ /** Name of the struct */
@@ -312,6 +311,7 @@ struct _pcp_stream_t {
Buffer *cache; /**< The caching Buffer object (for look ahead read) */ Buffer *cache; /**< The caching Buffer object (for look ahead read) */
Buffer *next; /**< The caching Next-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 */ 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 is_buffer; /**< Set to 1 if the backend is a Buffer */
uint8_t eof; /**< Set to 1 if EOF reached */ uint8_t eof; /**< Set to 1 if EOF reached */
uint8_t err; /**< Set to 1 if an error occured */ uint8_t err; /**< Set to 1 if an error occured */

View File

@@ -36,6 +36,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include "platform.h" #include "platform.h"
#include "defines.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); 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 */ #endif /* _HAVE_PCP_UTIL_H */
/**@}*/ /**@}*/

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein. Copyright (C) 2013-2017 T.v.Dein.
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -24,8 +24,8 @@
#define _HAVE_PCP_VERSION #define _HAVE_PCP_VERSION
#define PCP_VERSION_MAJOR 0 #define PCP_VERSION_MAJOR 0
#define PCP_VERSION_MINOR 3 #define PCP_VERSION_MINOR 4
#define PCP_VERSION_PATCH 0 #define PCP_VERSION_PATCH 1
#define PCP_VERSION PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH) #define PCP_VERSION PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH)
#define PCP_MAKE_VERSION(major, minor, patch) ((major * 10000) + (minor * 100) + (patch)) #define PCP_MAKE_VERSION(major, minor, patch) ((major * 10000) + (minor * 100) + (patch))

View File

@@ -20,12 +20,15 @@
#ifndef __ZMQ_Z85_H_INCLUDED__ #ifndef __ZMQ_Z85_H_INCLUDED__
#define __ZMQ_Z85_H_INCLUDED__ #define __ZMQ_Z85_H_INCLUDED__
#define __STDC_LIMIT_MACROS
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
uint8_t *zmq_z85_decode (uint8_t *dest, char *string); uint8_t *zmq_z85_decode (uint8_t *dest, const char *string);
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size); char *zmq_z85_encode (char *dest, const uint8_t *data, size_t size);
#endif #endif

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
You can contact me by mail: <tom AT vondein DOT org>. You can contact me by mail: <tom AT vondein DOT org>.
*/ */
#include "key.h" #include "key.h"
#include "context.h" #include "context.h"
@@ -33,10 +32,10 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
size_t plen = strnlen(passphrase, 255); size_t plen = strnlen(passphrase, 255);
/* create the scrypt hash */ /* 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 */ /* make a hash from the scrypt() result */
crypto_hash_sha256(key, (byte*)scrypted, 64); crypto_hash_sha256(key, (byte *)scrypted, 64);
/* turn the 32byte hash into a secret key */ /* turn the 32byte hash into a secret key */
key[0] &= 248; key[0] &= 248;
@@ -48,11 +47,10 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
return key; return key;
} }
char *pcp_getkeyid(pcp_key_t *k) { char *pcp_getkeyid(pcp_key_t *k) {
uint32_t s, p; uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT); p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT); s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17); char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s); snprintf(id, 17, "%08X%08X", p, s);
return id; return id;
@@ -61,14 +59,15 @@ char *pcp_getkeyid(pcp_key_t *k) {
/* same as above but for imported pbp keys */ /* same as above but for imported pbp keys */
char *pcp_getpubkeyid(pcp_pubkey_t *k) { char *pcp_getpubkeyid(pcp_pubkey_t *k) {
uint32_t s, p; uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT); p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT); s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17); char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s); snprintf(id, 17, "%08X%08X", p, s);
return id; return id;
} }
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk) { void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk,
byte *epk) {
/* generate keypairs from random seed */ /* generate keypairs from random seed */
byte *ms = urmalloc(32); byte *ms = urmalloc(32);
byte *ss = urmalloc(32); byte *ss = urmalloc(32);
@@ -94,28 +93,28 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
ucfree(cs, 32); ucfree(cs, 32);
} }
pcp_key_t * pcpkey_new () { pcp_key_t *pcpkey_new() {
byte *mp = ucmalloc(32); byte *mp = ucmalloc(LEDPUB);
byte *ms = ucmalloc(64); byte *ms = ucmalloc(LEDSEC);
byte *sp = ucmalloc(32); byte *sp = ucmalloc(LEDPUB);
byte *ss = ucmalloc(64); byte *ss = ucmalloc(LEDSEC);
byte *cp = ucmalloc(32); byte *cp = ucmalloc(LBOXPUB);
byte *cs = ucmalloc(32); byte *cs = ucmalloc(LBOXSEC);
/* generate key material */ /* generate key material */
pcp_keypairs(ms, mp, cs, cp, ss, sp); pcp_keypairs(ms, mp, cs, cp, ss, sp);
/* fill in our struct */ /* fill in our struct */
pcp_key_t *key = urmalloc(sizeof(pcp_key_t)); pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
memcpy (key->masterpub, mp, 32); memcpy(key->masterpub, mp, LEDPUB);
memcpy (key->mastersecret, ms, 64); memcpy(key->mastersecret, ms, LEDSEC);
memcpy (key->pub, cp, 32); memcpy(key->pub, cp, LBOXPUB);
memcpy (key->secret, cs, 32); memcpy(key->secret, cs, LBOXSEC);
memcpy (key->edpub, sp, 32); memcpy(key->edpub, sp, LEDPUB);
memcpy (key->edsecret, ss, 64); memcpy(key->edsecret, ss, LEDSEC);
char *id = pcp_getkeyid(key); char *id = pcp_getkeyid(key);
memcpy (key->id, id, 17); memcpy(key->id, id, 17);
free(id); free(id);
key->ctime = (long)time(0); key->ctime = (long)time(0);
@@ -128,19 +127,19 @@ pcp_key_t * pcpkey_new () {
key->mail[0] = '\0'; key->mail[0] = '\0';
/* clean up */ /* clean up */
ucfree(ms, 64); ucfree(ms, LEDSEC);
ucfree(ss, 64); ucfree(ss, LEDSEC);
ucfree(mp, 32); ucfree(mp, LEDPUB);
ucfree(sp, 32); ucfree(sp, LEDPUB);
ucfree(cs, 32); ucfree(cs, LBOXSEC);
ucfree(cp, 32); ucfree(cp, LBOXPUB);
return key; return key;
} }
byte * pcp_gennonce() { byte *pcp_gennonce() {
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES); byte *nonce = ucmalloc(LNONCE);
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES); arc4random_buf(nonce, LNONCE);
return nonce; return nonce;
} }
@@ -150,10 +149,10 @@ void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail) {
} }
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) { pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
if(key->nonce[0] == 0) { if (key->nonce[0] == 0) {
byte *nonce = pcp_gennonce(); byte *nonce = pcp_gennonce();
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES); memcpy(key->nonce, nonce, LNONCE);
ucfree(nonce, crypto_secretbox_NONCEBYTES); ucfree(nonce, LNONCE);
} }
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce); byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
@@ -162,27 +161,24 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
size_t es; size_t es;
Buffer *both = buffer_new(128, "keypack"); Buffer *both = buffer_new(128, "keypack");
buffer_add(both, key->mastersecret, 64); buffer_add(both, key->mastersecret, LEDSEC);
buffer_add(both, key->edsecret, 64); buffer_add(both, key->edsecret, LEDSEC);
buffer_add(both, key->secret, 32); buffer_add(both, key->secret, LBOXSEC);
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both), key->nonce, encryptkey); es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both),
key->nonce, encryptkey);
buffer_free(both); buffer_free(both);
sfree(encryptkey); sfree(encryptkey);
if(es == 176) { /* FIXME: calc! */ if (es == LSEC) {
/* success */ /* success */
memcpy(key->encrypted, encrypted, 176); memcpy(key->encrypted, encrypted, LSEC);
ucfree(encrypted, es); ucfree(encrypted, es);
arc4random_buf(key->secret, 32); memset(key->secret, 0, LBOXSEC);
arc4random_buf(key->edsecret, 64); memset(key->edsecret, 0, LEDSEC);
arc4random_buf(key->mastersecret, 64); memset(key->mastersecret, 0, LEDSEC);
key->secret[0] = 0; } else {
key->edsecret[0] = 0;
key->mastersecret[0] = 0;
}
else {
fatal(ptx, "failed to encrypt the secret key!\n"); fatal(ptx, "failed to encrypt the secret key!\n");
ucfree(encrypted, es); ucfree(encrypted, es);
ucfree(key, sizeof(pcp_key_t)); ucfree(key, sizeof(pcp_key_t));
@@ -195,23 +191,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) { pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce); byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *decrypted; byte *decrypted = ucmalloc(LSEC - crypto_secretbox_MACBYTES);
size_t es; 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); sfree(encryptkey);
if(es == 0) { if (es == 0) {
/* success */ /* success */
memcpy(key->mastersecret, decrypted, 64); memcpy(key->mastersecret, decrypted, LEDSEC);
memcpy(key->edsecret, decrypted + 64, 64); memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
memcpy(key->secret, decrypted +128, 32); memcpy(key->secret, decrypted + LEDSEC + LEDSEC, LBOXSEC);
ucfree(decrypted, 160); ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
} } else {
else {
fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es); fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es);
ucfree(decrypted, 160); ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
return NULL; return NULL;
} }
@@ -219,10 +215,10 @@ 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 *pcpkey_pub_from_secret(pcp_key_t *key) {
pcp_pubkey_t *pub = urmalloc(sizeof (pcp_pubkey_t)); pcp_pubkey_t *pub = urmalloc(sizeof(pcp_pubkey_t));
memcpy(pub->masterpub, key->masterpub, 32); memcpy(pub->masterpub, key->masterpub, LEDPUB);
memcpy(pub->pub, key->pub, 32); memcpy(pub->pub, key->pub, LBOXPUB);
memcpy(pub->edpub, key->edpub, 32); memcpy(pub->edpub, key->edpub, LEDSEC);
memcpy(pub->owner, key->owner, 255); memcpy(pub->owner, key->owner, 255);
memcpy(pub->mail, key->mail, 255); memcpy(pub->mail, key->mail, 255);
memcpy(pub->id, key->id, 17); memcpy(pub->id, key->id, 17);
@@ -245,152 +241,137 @@ char *pcpkey_get_art(pcp_key_t *k) {
byte *pcppubkey_getchecksum(pcp_pubkey_t *k) { byte *pcppubkey_getchecksum(pcp_pubkey_t *k) {
byte *hash = ucmalloc(32); byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32); crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash; return hash;
} }
byte *pcpkey_getchecksum(pcp_key_t *k) { byte *pcpkey_getchecksum(pcp_key_t *k) {
byte *hash = ucmalloc(32); byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32); crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash; 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_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->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);
}
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) { void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) {
buffer_add(b, k->masterpub, 32); buffer_add(b, k->masterpub, LEDPUB);
buffer_add(b, k->sigpub, 32); buffer_add(b, k->pub, LBOXPUB);
buffer_add(b, k->pub, 32); buffer_add(b, k->edpub, LEDPUB);
buffer_add(b, k->edpub, 32);
buffer_add(b, k->owner, 255); buffer_add(b, k->owner, 255);
buffer_add(b, k->mail, 255); buffer_add(b, k->mail, 255);
buffer_add(b, k->id, 17); buffer_add(b, k->id, 17);
buffer_add8(b, k->type); buffer_add8(b, k->type);
buffer_add64(b, k->ctime); buffer_add64be(b, k->ctime);
buffer_add32(b, k->version); buffer_add32be(b, k->version);
buffer_add32(b, k->serial); buffer_add32be(b, k->serial);
buffer_add8(b, k->valid); buffer_add8(b, k->valid);
} }
void pcp_seckeyblob(Buffer *b, pcp_key_t *k) {
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_add64be(b, k->ctime);
buffer_add32be(b, k->version);
buffer_add32be(b, k->serial);
}
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);
k->type = buffer_get8(b);
k->ctime = buffer_get64na(b);
k->version = buffer_get32na(b);
k->serial = buffer_get32na(b);
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) { Buffer *pcp_keyblob(void *k, int type) {
if(type == PCP_KEY_TYPE_PUBLIC) { if (type == PCP_KEY_TYPE_PUBLIC) {
Buffer *b = buffer_new(PCP_RAW_PUBKEYSIZE, "bp"); Buffer *b = buffer_new(PCP_RAW_PUBKEYSIZE, "bp");
pcp_pubkeyblob(b, (pcp_pubkey_t *)k); pcp_pubkeyblob(b, (pcp_pubkey_t *)k);
return b; return b;
} } else {
else {
Buffer *b = buffer_new(PCP_RAW_KEYSIZE, "bs"); Buffer *b = buffer_new(PCP_RAW_KEYSIZE, "bs");
pcp_seckeyblob(b, (pcp_key_t *)k); pcp_seckeyblob(b, (pcp_key_t *)k);
return b; return b;
} }
} }
int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) { int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
if(key->pub[0] == 0) { if (key->pub[0] == 0) {
fatal(ptx, "Pubkey sanity check: public key contained in key seems to be empty!\n"); fatal(ptx, "Pubkey sanity check: public key contained in key seems to be "
"empty!\n");
return 1; return 1;
} }
if(key->type != PCP_KEY_TYPE_PUBLIC) { if (key->type != PCP_KEY_TYPE_PUBLIC) {
fatal(ptx, "Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: %02x)!\n", 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; return 1;
} }
if(key->version != PCP_KEY_VERSION) { if (key->version != PCP_KEY_VERSION) {
fatal(ptx, "Pubkey sanity check: unknown key version (expected: %08X, got: %08X)!\n", 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; return 1;
} }
if(key->serial <= 0) { if (key->serial <= 0) {
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n", key->serial); fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1; return 1;
} }
if(key->id[16] != '\0') { if (key->id[16] != '\0') {
char *got = ucmalloc(17); char *got = ucmalloc(17);
memcpy(got, key->id, 17); memcpy(got, key->id, 17);
got[16] = '\0'; got[16] = '\0';
fatal(ptx, "Pubkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n", got); fatal(ptx,
"Pubkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n",
got);
free(got); free(got);
return 1; return 1;
} }
@@ -398,50 +379,63 @@ int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
struct tm *c; struct tm *c;
time_t t = (time_t)key->ctime; time_t t = (time_t)key->ctime;
c = localtime(&t); c = localtime(&t);
if(c->tm_year <= 0 || c->tm_year > 1100) { if (c->tm_year <= 0 || c->tm_year > 1100) {
/* well, I'm perhaps overacting here :) */ /* well, I'm perhaps overacting here :) */
fatal(ptx, "Pubkey sanity check: invalid creation timestamp (got year %04d)!\n", c->tm_year + 1900); fatal(ptx,
"Pubkey sanity check: invalid creation timestamp (got year %04d)!\n",
c->tm_year + 1900);
return 1; return 1;
} }
pcp_pubkey_t *maybe = pcphash_pubkeyexists(ptx, key->id); pcp_pubkey_t *maybe = pcphash_pubkeyexists(ptx, key->id);
if(maybe != NULL) { if (maybe != NULL) {
fatal(ptx, "Pubkey sanity check: there already exists a key with the id 0x%s\n", key->id); fatal(ptx,
"Pubkey sanity check: there already exists a key with the id 0x%s\n",
key->id);
return 1; return 1;
} }
return 0; return 0;
} }
int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) { int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
if(key->encrypted[0] == 0) { if (key->encrypted[0] == 0) {
fatal(ptx, "Secretkey sanity check: secret key contained in key seems to be empty!\n"); fatal(ptx, "Secretkey sanity check: secret key contained in key seems to "
"be empty!\n");
return 1; return 1;
} }
if(key->type != PCP_KEY_TYPE_SECRET && key->type != PCP_KEY_TYPE_MAINSECRET) { if (key->type != PCP_KEY_TYPE_SECRET &&
fatal(ptx, "Secretkey sanity check: key type is not SECRET (expected: %02x, got: %02x)!\n", 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; return 1;
} }
if(key->version != PCP_KEY_VERSION) { if (key->version != PCP_KEY_VERSION) {
fatal(ptx, "Secretkey sanity check: unknown key version (expected: %08X, got: %08X)!\n", 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; return 1;
} }
if(key->serial <= 0) { if (key->serial <= 0) {
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n", key->serial); fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1; return 1;
} }
if(key->id[16] != '\0') { if (key->id[16] != '\0') {
char *got = ucmalloc(17); char *got = ucmalloc(17);
memcpy(got, key->id, 17); memcpy(got, key->id, 17);
got[16] = '\0'; got[16] = '\0';
fatal(ptx, "Secretkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n", got); fatal(ptx,
"Secretkey sanity check: invalid key id (expected 16 bytes, got: "
"%s)!\n",
got);
free(got); free(got);
return 1; return 1;
} }
@@ -449,15 +443,21 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
struct tm *c; struct tm *c;
time_t t = (time_t)key->ctime; time_t t = (time_t)key->ctime;
c = localtime(&t); c = localtime(&t);
if(c->tm_year <= 70 || c->tm_year > 1100) { if (c->tm_year <= 70 || c->tm_year > 1100) {
/* well, I'm perhaps overacting here :) */ /* well, I'm perhaps overacting here :) */
fatal(ptx, "Secretkey sanity check: invalid creation timestamp (got year %04d)!\n", c->tm_year + 1900); fatal(
ptx,
"Secretkey sanity check: invalid creation timestamp (got year %04d)!\n",
c->tm_year + 1900);
return 1; return 1;
} }
pcp_key_t *maybe = pcphash_keyexists(ptx, key->id); pcp_key_t *maybe = pcphash_keyexists(ptx, key->id);
if(maybe != NULL) { if (maybe != NULL) {
fatal(ptx, "Secretkey sanity check: there already exists a key with the id 0x%s\n", key->id); fatal(
ptx,
"Secretkey sanity check: there already exists a key with the id 0x%s\n",
key->id);
return 1; return 1;
} }
@@ -465,40 +465,48 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
} }
void pcp_dumpkey(pcp_key_t *k) { void pcp_dumpkey(pcp_key_t *k) {
int i; unsigned int i;
printf("Dumping pcp_key_t raw values:\n"); printf("Dumping pcp_key_t raw values:\n");
printf("masterpub: "); 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("\n");
printf(" public: "); 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("\n");
printf(" edpub: "); 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("\n");
printf("mastersec: "); 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("\n");
printf(" secret: "); 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("\n");
printf(" edsecret: "); 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("\n");
printf(" nonce: "); 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("\n");
printf("encrypted: "); 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("\n");
printf(" owner: %s\n", k->owner); printf(" owner: %s\n", k->owner);
@@ -516,21 +524,23 @@ void pcp_dumpkey(pcp_key_t *k) {
printf(" type: 0x%02X\n", k->type); printf(" type: 0x%02X\n", k->type);
} }
void pcp_dumppubkey(pcp_pubkey_t *k) { void pcp_dumppubkey(pcp_pubkey_t *k) {
int i; unsigned int i;
printf("Dumping pcp_pubkey_t raw values:\n"); printf("Dumping pcp_pubkey_t raw values:\n");
printf("masterpub: "); 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("\n");
printf(" public: "); 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("\n");
printf(" edpub: "); 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("\n");
printf(" owner: %s\n", k->owner); printf(" owner: %s\n", k->owner);
@@ -547,3 +557,37 @@ void pcp_dumppubkey(pcp_pubkey_t *k) {
printf(" type: 0x%02X\n", k->type); 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). 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 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 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). 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 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 it under the terms of the GNU General Public License as published by
@@ -22,39 +22,21 @@
#include "keysig.h" #include "keysig.h"
pcp_keysig_t * keysig2be(pcp_keysig_t *s) { void pcp_keysig2blob(Buffer *b, 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");
buffer_add8(b, s->type); buffer_add8(b, s->type);
buffer_add32be(b, s->size); buffer_add32be(b, s->size);
buffer_add(b, s->id, 17); 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_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; 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)); pcp_keysig_t *sk = ucmalloc(sizeof(pcp_keysig_t));
uint8_t type = buffer_get8(blob); 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); buffer_get_chunk(blob, sk->id, 17);
byte *checksum = ucmalloc(32); byte *checksum = ucmalloc(LSHA);
buffer_get_chunk(blob, checksum, 32); buffer_get_chunk(blob, checksum, LSHA);
sk->blob = ucmalloc(size); sk->blob = ucmalloc(size);
buffer_get_chunk(blob, sk->blob, size); buffer_get_chunk(blob, sk->blob, size);
sk->size = size; sk->size = size;
sk->type = type; sk->type = type;
memcpy(sk->checksum, checksum, 32); memcpy(sk->checksum, checksum, LSHA);
ucfree(checksum, 32); ucfree(checksum, LSHA);
return sk; return sk;
} }
@@ -86,7 +68,7 @@ void pcp_dumpkeysig(pcp_keysig_t *s) {
printf(" size: %ld\n", (long int)s->size); printf(" size: %ld\n", (long int)s->size);
printf(" checksum: "); 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"); printf("\n");
_dump(" blob:", s->blob, s->size); _dump(" blob:", s->blob, s->size);

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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); byte *value = realloc (d, newlen);
if (value == NULL) { 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); exit(-1);
} }

64
libpcp/meson.build Normal file
View File

@@ -0,0 +1,64 @@
# -*-python-*-
libincludes = include_directories('include', 'include/pcp')
# check for libraries with CMAKE or pkg-config
sodium = dependency('libsodium')
# manually check for libraries
jansson = c.find_library('jansson', required: true,
dirs : ['/usr', '/usr/local'])
conf.set('HAVE_SODIUM', sodium.found())
conf.set('HAVE_JSON', jansson.found())
math = c.find_library('m')
# add dependencies, manual libs are added directly below
pcp_deps = [
sodium, jansson, math
]
libpcp = shared_library(
'pcp',
'buffer.c',
'context.c',
'crypto.c',
'ed.c',
'getpass.c',
'jenhash.c',
'key.c',
'keyhash.c',
'keysig.c',
'mem.c',
'mgmt.c',
'pcpstream.c',
'platform.c',
'randomart.c',
'readpass.c',
'scrypt.c',
'util.c',
'vault.c',
'version.c',
'z85.c',
'zmq_z85.c',
include_directories: libincludes,
install: true,
dependencies: pcp_deps
)
libpcp_dep = declare_dependency(
include_directories: libincludes,
link_with: libpcp,
)
# write out the config header
m = configure_file(
input : 'config.h.in',
output : 'config.h',
configuration : conf,
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -137,6 +137,7 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
} }
else { else {
size_t got = fread(buf+idx, 1, readbytes, stream->fd); size_t got = fread(buf+idx, 1, readbytes, stream->fd);
gotbytes += got; gotbytes += got;
if(feof(stream->fd) != 0) if(feof(stream->fd) != 0)
stream->eof = 1; stream->eof = 1;
@@ -146,7 +147,8 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
rawdone: 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; return gotbytes;
} }
@@ -174,6 +176,7 @@ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
else { else {
// fprintf(stderr, " fetch next\n"); // 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"); Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadchunktmp");
if( buffer_left(stream->cache) > 0) { if( buffer_left(stream->cache) > 0) {
@@ -257,6 +260,7 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
size_t got = 0; size_t got = 0;
if(stream->cache == NULL) { if(stream->cache == NULL) {
got = ps_read_raw(stream, buf, readbytes); 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) { else if(buffer_size(stream->cache) > 0) {
/* use cache */ /* use cache */
@@ -281,11 +285,12 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
else { else {
/* read directly from source */ /* read directly from source */
got = ps_read_raw(stream, buf, readbytes); got = ps_read_raw(stream, buf, readbytes);
// fprintf(stderr, "%ld = ps_read_raw(stream, buf, readbytes);\n", got);
} }
} }
stream->pos += got; stream->pos += got;
// fprintf(stderr, " ps_read(): %ld\n", got); //fprintf(stderr, " ps_read(): %ld\n", got);
return got; return got;
} }
@@ -293,7 +298,7 @@ int ps_readline(Pcpstream *stream, Buffer *line) {
int c = -1, max = 1; int c = -1, max = 1;
byte b[1]; byte b[1];
while(c<PSMAXLINE) { while(c<PSMAXLINE) { // && ps_end(stream) != 1
//fprintf(stderr, " ps_readline: call raw\n"); //fprintf(stderr, " ps_readline: call raw\n");
if(ps_read_raw(stream, b, 1) < 1) { if(ps_read_raw(stream, b, 1) < 1) {
//fprintf(stderr, " ps_readline: raw returned < 1\n"); //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"); //fprintf(stderr, " ps_readline: raw found CR\n");
continue; continue;
} }
else if(*b == '\n' || ps_end(stream) == 1) { else if(*b == '\n') {
//fprintf(stderr, " ps_readline: raw found NL\n"); //fprintf(stderr, " ps_readline: raw found NL\n");
c++; c++;
max = 0; max = 0;
@@ -326,7 +331,8 @@ int ps_readline(Pcpstream *stream, Buffer *line) {
return -1; 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; return c;
} }
@@ -436,14 +442,16 @@ size_t ps_read_decode(Pcpstream *stream) {
} }
} }
//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 */ /* finally, decode it and put into next */
size_t binlen, outlen; size_t binlen, outlen;
byte *bin = pcp_z85_decode(ptx, buffer_get_str(z), &binlen); 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); //fprintf(stderr, "ps_read_decode decoding z: %ld, got: %ld\n", buffer_size(z), binlen);
//_dump("bin", bin, binlen); //_dump("bin", bin, binlen);
//fatals_ifany(); fatals_ifany(ptx);
if(bin == NULL) { if(bin == NULL) {
/* it's not z85 encoded, so threat it as binary */ /* it's not z85 encoded, so threat it as binary */

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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)); fprintf(stderr, ": %s\n", strerror(errno));
va_end(ap); 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 #endif

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). 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 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 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). 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 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 it under the terms of the GNU General Public License as published by
@@ -119,3 +119,114 @@ size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_arra
return byte_array_size; 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). 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 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 it under the terms of the GNU General Public License as published by
@@ -111,7 +111,7 @@ int pcpvault_create(PCPCTX *ptx, vault_t *vault) {
header->version = PCP_VAULT_VERSION; header->version = PCP_VAULT_VERSION;
vault->version = header->version; vault->version = header->version;
memcpy(vault->checksum, header->checksum, 32); memcpy(vault->checksum, header->checksum, LSHA);
vh2be(header); vh2be(header);
@@ -164,9 +164,7 @@ int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type) {
itemsize = PCP_RAW_PUBKEYSIZE; itemsize = PCP_RAW_PUBKEYSIZE;
saveitem = ucmalloc(sizeof(pcp_pubkey_t)); saveitem = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(saveitem, item, sizeof(pcp_pubkey_t)); memcpy(saveitem, item, sizeof(pcp_pubkey_t));
pubkey2be((pcp_pubkey_t *)item); blob = pcp_keyblob(item, type);
blob = buffer_new(PCP_RAW_KEYSIZE, "bs");
pcp_pubkeyblob(blob, (pcp_pubkey_t *)item);
} }
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_PBP) { else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_PBP) {
saveitem = ucmalloc(sizeof(pcp_keysig_t)); 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)); memcpy(ksout, ksin, sizeof(pcp_keysig_t));
ksout->blob = ucmalloc(ksin->size); ksout->blob = ucmalloc(ksin->size);
memcpy(ksout->blob, ksin->blob, ksin->size); memcpy(ksout->blob, ksin->blob, ksin->size);
blob = pcp_keysig2blob(item); blob = pcp_keysigblob(ksin);
itemsize = buffer_size(blob); itemsize = buffer_size(blob);
} }
else { else {
itemsize = PCP_RAW_KEYSIZE; itemsize = PCP_RAW_KEYSIZE;
saveitem = ucmalloc(sizeof(pcp_key_t)); saveitem = ucmalloc(sizeof(pcp_key_t));
memcpy(saveitem, item, sizeof(pcp_key_t)); memcpy(saveitem, item, sizeof(pcp_key_t));
key2be((pcp_key_t *)item);
blob = pcp_keyblob(item, type); blob = pcp_keyblob(item, type);
pcp_seckeyblob(blob, (pcp_key_t *)item);
} }
if(tmp != NULL) { if(tmp != NULL) {
@@ -224,24 +220,40 @@ int pcpvault_writeall(PCPCTX *ptx, vault_t *vault) {
if(tmp != NULL) { if(tmp != NULL) {
if(pcpvault_create(ptx, tmp) == 0) { if(pcpvault_create(ptx, tmp) == 0) {
pcp_key_t *k = NULL; pcp_key_t *k = NULL;
pcp_pubkey_t *p = NULL;
pcp_keysig_t *s = NULL;
Buffer *blob = buffer_new(PCP_RAW_PUBKEYSIZE, "bs"); Buffer *blob = buffer_new(PCP_RAW_PUBKEYSIZE, "bs");
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) {
pcp_seckeyblob(blob, k); pcp_seckeyblob(blob, k);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_KEYSIZE, PCP_KEY_TYPE_SECRET) != 0) { if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_KEYSIZE,
PCP_KEY_TYPE_SECRET) != 0) {
buffer_free(blob); buffer_free(blob);
goto errwa; goto errwa;
} }
buffer_clear(blob); buffer_clear(blob);
} }
pcp_pubkey_t *p = NULL;
pcphash_iteratepub(ptx, p) { pcphash_iteratepub(ptx, p) {
pcp_pubkeyblob(blob, p); pcp_pubkeyblob(blob, p);
if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_PUBKEYSIZE, PCP_KEY_TYPE_PUBLIC) != 0) { if(pcpvault_additem(ptx, tmp, buffer_get(blob), PCP_RAW_PUBKEYSIZE,
PCP_KEY_TYPE_PUBLIC) != 0) {
buffer_free(blob); buffer_free(blob);
goto errwa; goto errwa;
} }
buffer_clear(blob); 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); pcpvault_update_checksum(ptx, tmp);
if(pcpvault_copy(ptx, tmp, vault) == 0) { if(pcpvault_copy(ptx, tmp, vault) == 0) {
pcpvault_unlink(tmp); pcpvault_unlink(tmp);
@@ -268,9 +280,9 @@ void pcpvault_update_checksum(PCPCTX *ptx, vault_t *vault) {
vault_header_t *header = ucmalloc(sizeof(vault_header_t)); vault_header_t *header = ucmalloc(sizeof(vault_header_t));
header->fileid = PCP_VAULT_ID; header->fileid = PCP_VAULT_ID;
header->version = PCP_VAULT_VERSION; header->version = PCP_VAULT_VERSION;
memcpy(header->checksum, checksum, 32); memcpy(header->checksum, checksum, LSHA);
memcpy(vault->checksum, checksum, 32); memcpy(vault->checksum, checksum, LSHA);
ucfree(checksum, 32); ucfree(checksum, LSHA);
vh2be(header); vh2be(header);
@@ -292,36 +304,33 @@ byte *pcpvault_create_checksum(PCPCTX *ptx) {
size_t datasize = ((PCP_RAW_KEYSIZE) * numskeys) + size_t datasize = ((PCP_RAW_KEYSIZE) * numskeys) +
((PCP_RAW_PUBKEYSIZE) * numpkeys); ((PCP_RAW_PUBKEYSIZE) * numpkeys);
byte *data = ucmalloc(datasize); byte *data = ucmalloc(datasize);
byte *checksum = ucmalloc(32); byte *checksum = ucmalloc(LSHA);
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) {
key2be(k);
pcp_seckeyblob(blob, (pcp_key_t *)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); buffer_clear(blob);
key2native(k); datapos += buffer_size(blob);
datapos += PCP_RAW_KEYSIZE;
} }
pcp_pubkey_t *p = NULL; pcp_pubkey_t *p = NULL;
pcphash_iteratepub(ptx, p) { pcphash_iteratepub(ptx, p) {
/* pcp_dumppubkey(p); */
pubkey2be(p);
pcp_pubkeyblob(blob, (pcp_pubkey_t *)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); buffer_clear(blob);
pubkey2native(p); datapos += buffer_size(blob);
datapos += PCP_RAW_PUBKEYSIZE; }
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); 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); crypto_hash_sha256(checksum, data, datasize);
memset(data, 0, datasize); memset(data, 0, datasize);
@@ -396,45 +405,30 @@ void pcpvault_free(vault_t *vault) {
} }
vault_header_t * vh2be(vault_header_t *h) { vault_header_t * vh2be(vault_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN _32towire(h->version, (byte *)&h->version);
return h; return h;
#else
h->version = htobe32(h->version);
return h;
#endif
} }
vault_header_t * vh2native(vault_header_t *h) { vault_header_t * vh2native(vault_header_t *h) {
#ifdef __CPU_IS_BIG_ENDIAN h->version = _wireto32((byte *)&h->version);
return h; return h;
#else
h->version = be32toh(h->version);
return h;
#endif
} }
vault_item_header_t * ih2be(vault_item_header_t *h) { 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; 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) { 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; return h;
#else
h->version = be32toh(h->version);
h->size = be32toh(h->size);
return h;
#endif
} }
int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) { int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
Buffer *raw = NULL;
size_t got = 0; size_t got = 0;
fseek(vault->fd, 0, SEEK_SET); fseek(vault->fd, 0, SEEK_SET);
@@ -455,9 +449,10 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
pcp_pubkey_t *pubkey; pcp_pubkey_t *pubkey;
int bytesleft = 0; int bytesleft = 0;
int ksize = PCP_RAW_KEYSIGSIZE; /* smallest possbile item */ int ksize = PCP_RAW_KEYSIGSIZE; /* smallest possbile item */
raw = buffer_new(256, "rawin");
vault->version = header->version; vault->version = header->version;
memcpy(vault->checksum, header->checksum, 32); memcpy(vault->checksum, header->checksum, LSHA);
for(;;) { for(;;) {
readpos = ftell(vault->fd); readpos = ftell(vault->fd);
@@ -475,24 +470,23 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
if(item->type == PCP_KEY_TYPE_MAINSECRET || if(item->type == PCP_KEY_TYPE_MAINSECRET ||
item->type == PCP_KEY_TYPE_SECRET) { item->type == PCP_KEY_TYPE_SECRET) {
/* read a secret key */ /* read a secret key */
key = ucmalloc(sizeof(pcp_key_t)); buffer_fd_read(raw, vault->fd, item->size);
got = fread(key, PCP_RAW_KEYSIZE, 1, vault->fd); key = pcp_blob2key(raw);
key2native(key);
pcphash_add(ptx, (void *)key, item->type); pcphash_add(ptx, (void *)key, item->type);
buffer_clear(raw);
} }
else if(item->type == PCP_KEY_TYPE_PUBLIC) { else if(item->type == PCP_KEY_TYPE_PUBLIC) {
/* read a public key */ /* read a public key */
pubkey = ucmalloc(sizeof(pcp_pubkey_t)); buffer_fd_read(raw, vault->fd, item->size);
got = fread(pubkey, PCP_RAW_PUBKEYSIZE, 1, vault->fd); pubkey = pcp_blob2pubkey(raw);
pubkey2native(pubkey);
pcphash_add(ptx, (void *)pubkey, item->type); pcphash_add(ptx, (void *)pubkey, item->type);
buffer_clear(raw);
} }
else if(item->type == PCP_KEYSIG_NATIVE || item->type == PCP_KEYSIG_PBP) { else if(item->type == PCP_KEYSIG_NATIVE || item->type == PCP_KEYSIG_PBP) {
Buffer *rawks = buffer_new(256, "keysig"); buffer_fd_read(raw, vault->fd, item->size);
buffer_fd_read(rawks, vault->fd, item->size); pcp_keysig_t *s = pcp_blob2keysig(raw);
pcp_keysig_t *s = pcp_keysig_new(rawks);
pcphash_add(ptx, (void *)s, item->type); pcphash_add(ptx, (void *)s, item->type);
buffer_free(rawks); buffer_clear(raw);
} }
else { else {
fatal(ptx, "Failed to read vault - invalid key type: %02X! at %d\n", fatal(ptx, "Failed to read vault - invalid key type: %02X! at %d\n",
@@ -526,14 +520,9 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
byte *checksum = NULL; byte *checksum = NULL;
checksum = pcpvault_create_checksum(ptx); checksum = pcpvault_create_checksum(ptx);
/*
_dump(" calc checksum", checksum, 32);
_dump("vault checksum", vault->checksum, 32);
*/
if(pcphash_count(ptx) + pcphash_countpub(ptx) > 0) { if(pcphash_count(ptx) + pcphash_countpub(ptx) > 0) {
/* only validate the checksum if there are keys */ /* 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"); fatal(ptx, "Error: the checksum of the key vault doesn't match its contents!\n");
goto err; goto err;
} }
@@ -542,11 +531,13 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
free(checksum); free(checksum);
free(item); free(item);
free(header); free(header);
buffer_free(raw);
return 0; return 0;
err: err:
free(item); free(item);
free(header); free(header);
buffer_free(raw);
/* pcphash_clean(); */ /* pcphash_clean(); */
return -1; return -1;

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 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) { uint8_t is_utf8(const byte *bytes) {
if( (// non-overlong 2-byte if( (// non-overlong 2-byte
(0xC2 <= bytes[0] && bytes[0] <= 0xDF) && (0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
@@ -173,7 +176,6 @@ byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen) {
byte padblob[4]; byte padblob[4];
srclen = strlen(z85block); srclen = strlen(z85block);
if(srclen == 0) { if(srclen == 0) {
/* FIXME: check how this happens, pcpstream decoder call */ /* FIXME: check how this happens, pcpstream decoder call */
*dstlen = 0; *dstlen = 0;
@@ -229,6 +231,9 @@ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock) {
zlen = (outlen * 5 / 4) + 1; zlen = (outlen * 5 / 4) + 1;
z85 = ucmalloc(zlen + 5); /* plus space for pad blob */ z85 = ucmalloc(zlen + 5); /* plus space for pad blob */
z85 = zmq_z85_encode(z85, padded, outlen); z85 = zmq_z85_encode(z85, padded, outlen);
if (z85 == NULL) {
perror("zmq_z85_encode *z85 failed!");
}
if(srclen %4 != 0) if(srclen %4 != 0)
free(padded); free(padded);
@@ -237,7 +242,9 @@ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock) {
padblob = ucmalloc(6); padblob = ucmalloc(6);
rpad = urmalloc(4); rpad = urmalloc(4);
rpad[3] = (int)padlen; rpad[3] = (int)padlen;
zmq_z85_encode(padblob, rpad, 4); if(zmq_z85_encode(padblob, rpad, 4) == NULL) {
perror("zmq_z85_encode *padblob failed!");
}
/* append pad blob to encoded output */ /* append pad blob to encoded output */
memcpy(&z85[zlen-1], padblob, 5); memcpy(&z85[zlen-1], padblob, 5);

View File

@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of 0MQ. This file is part of 0MQ.
@@ -28,21 +28,22 @@ static char encoder [85 + 1] = {
"}@%$#" "}@%$#"
}; };
/* Maps base 85 to base 256 */ /* Maps base 85 to base 256
/* We chop off lower 32 and higher 128 ranges */ We chop off lower 32 and higher 128 ranges
0xFF denotes invalid characters within this range */
static uint8_t decoder [96] = { static uint8_t decoder [96] = {
0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00, 0xFF, 0x44, 0xFF, 0x54, 0x53, 0x52, 0x48, 0xFF,
0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45, 0x4B, 0x4C, 0x46, 0x41, 0xFF, 0x3F, 0x3E, 0x45,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47, 0x08, 0x09, 0x40, 0xFF, 0x49, 0x42, 0x4A, 0x47,
0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00, 0x3B, 0x3C, 0x3D, 0x4D, 0xFF, 0x4E, 0x43, 0xFF,
0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 0x21, 0x22, 0x23, 0x4F, 0xFF, 0x50, 0xFF, 0xFF
}; };
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -50,19 +51,26 @@ static uint8_t decoder [96] = {
/* size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns */ /* size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns */
/* dest. Size must be a multiple of 4. */ /* dest. Size must be a multiple of 4. */
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size) /* --------------------------------------------------------------------------
{ Encode a binary frame as a string; destination string MUST be at least
if (size % 4 != 0) size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
return NULL; /* !assert */ dest. Size must be a multiple of 4.
Returns NULL and sets errno = EINVAL for invalid input. */
char *zmq_z85_encode (char *dest, const uint8_t *data, size_t size)
{
if (size % 4 != 0) {
errno = EINVAL;
return NULL;
}
unsigned int char_nbr = 0; unsigned int char_nbr = 0;
unsigned int byte_nbr = 0; unsigned int byte_nbr = 0;
uint32_t value = 0; uint32_t value = 0;
while (byte_nbr < size) { while (byte_nbr < size) {
/* Accumulate value in base 256 (binary) */ // Accumulate value in base 256 (binary)
value = value * 256 + data [byte_nbr++]; value = value * 256 + data [byte_nbr++];
if (byte_nbr % 4 == 0) { if (byte_nbr % 4 == 0) {
/* Output value in base 85 */ // Output value in base 85
unsigned int divisor = 85 * 85 * 85 * 85; unsigned int divisor = 85 * 85 * 85 * 85;
while (divisor) { while (divisor) {
dest [char_nbr++] = encoder [value / divisor % 85]; dest [char_nbr++] = encoder [value / divisor % 85];
@@ -71,32 +79,44 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
value = 0; value = 0;
} }
} }
if (char_nbr != size * 5 / 4) if (char_nbr != size * 5 / 4) {
return NULL; /* !assert */ return NULL; /* !assert */
}
dest [char_nbr] = 0; dest [char_nbr] = 0;
return dest; return dest;
} }
// --------------------------------------------------------------------------
// Decode an encoded string into a binary frame; dest must be at least
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
// must be a multiple of 5.
// Returns NULL and sets errno = EINVAL for invalid input.
/* -------------------------------------------------------------------------- */ uint8_t *zmq_z85_decode (uint8_t *dest, const char *string)
/* Decode an encoded string into a binary frame; dest must be at least */
/* strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string) */
/* must be a multiple of 5. */
uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
{ {
if (strlen (string) % 5 != 0)
return NULL; /* !assert */
unsigned int byte_nbr = 0; unsigned int byte_nbr = 0;
unsigned int char_nbr = 0; unsigned int char_nbr = 0;
uint32_t value = 0; uint32_t value = 0;
size_t string_len = strlen (string); while (string[char_nbr]) {
while (char_nbr < string_len) { // Accumulate value in base 85
/* Accumulate value in base 85 */ if (UINT32_MAX / 85 < value) {
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32]; // Invalid z85 encoding, represented value exceeds 0xffffffff
goto error_inval;
}
value *= 85;
uint8_t index = string [char_nbr++] - 32;
if (index >= sizeof(decoder)) {
// Invalid z85 encoding, character outside range
goto error_inval;
}
uint32_t summand = decoder [index];
if (summand == 0xFF || summand > (UINT32_MAX - value)) {
// Invalid z85 encoding, invalid character or represented value exceeds 0xffffffff
goto error_inval;
}
value += summand;
if (char_nbr % 5 == 0) { if (char_nbr % 5 == 0) {
/* Output value in base 256 */ // Output value in base 256
unsigned int divisor = 256 * 256 * 256; unsigned int divisor = 256 * 256 * 256;
while (divisor) { while (divisor) {
dest [byte_nbr++] = value / divisor % 256; dest [byte_nbr++] = value / divisor % 256;
@@ -105,7 +125,15 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
value = 0; value = 0;
} }
} }
if (byte_nbr != strlen (string) * 4 / 5) if (char_nbr % 5 != 0) {
return NULL; /* !assert */ goto error_inval;
}
if (byte_nbr != strlen (string) * 4 / 5) {
goto error_inval;
}
return dest; return dest;
error_inval:
errno = EINVAL;
return NULL;
} }

View File

@@ -286,6 +286,26 @@ B<In short: don NOT use this software for production purposes!>
=head1 INTERNALS =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 =head2 VAULT FORMAT
The vault file contains all public and secret keys. It's a portable The vault file contains all public and secret keys. It's a portable

View File

@@ -1,3 +1,4 @@
=head1 INSTALLATION =head1 INSTALLATION
There are currently no packages available, so B<pcp> has to be There are currently no packages available, so B<pcp> has to be
@@ -13,7 +14,20 @@ First, you will need libsodium:
sudo ldconfig sudo ldconfig
cd .. 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 git clone git://github.com/tlinden/pcp.git
cd pcp cd pcp

View File

@@ -1,3 +1,4 @@
=head1 OPTIONS =head1 OPTIONS
Usage: pcp1 [options] Usage: pcp1 [options]
@@ -9,10 +10,13 @@
will be used. will be used.
-I --infile <file> Input file. If not specified, stdin -I --infile <file> Input file. If not specified, stdin
will be used. 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> -X --password-file <file> Read passphrase from <file>. If <file>
is -, read from stdin. This takes is -, read from stdin. This takes
precedence over other uses of stdin precedence over other uses of stdin
elsewhere, see below for more details. elsewhere, see below for more details.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id to import/export. -i --keyid <id> Specify a key id to import/export.
-r --recipient <string> Specify a recpipient, used for public -r --recipient <string> Specify a recpipient, used for public
key export and encryption. key export and encryption.
@@ -35,9 +39,7 @@
been specified, don't store the generated been specified, don't store the generated
key to the vault but export it to the key to the vault but export it to the
file instead. You will be asked for file instead. You will be asked for
an owner, mail and a passphrase. If you an owner, mail and a passphrase.
leave the passphrase empty, the key will
be stored unencrypted.
-l --listkeys List all keys currently stored in your -l --listkeys List all keys currently stored in your
vault. Only the key id's and some info vault. Only the key id's and some info
about the keys will be printed, not the about the keys will be printed, not the
@@ -132,11 +134,9 @@
uses stdin/stdout uses stdin/stdout
Misc Options: Misc Options:
-C --checksum [<key>] Calculate a Blake2b checksum of one or more files. -C --checksum Calculate a Blake2b checksum of one or more files.
If <key> is provided, an authenticated hash will If -x is provided, an authenticated hash will
be calculated, otherwise a normal hash. If you don't be calculated, otherwise a normal hash.
want to generate an authenticated hash, specify
-- after -C.
Use -I to specify one file or put multiple file Use -I to specify one file or put multiple file
names after -C like "pcp1 -C -- file1 file2 file3". 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: .\" Standard preamble:
.\" ======================================================================== .\" ========================================================================
@@ -38,8 +38,6 @@
. ds PI \(*p . ds PI \(*p
. ds L" `` . ds L" ``
. ds R" '' . ds R" ''
. ds C`
. ds C'
'br\} 'br\}
.\" .\"
.\" Escape single quotes in literal strings from groff's Unicode transform. .\" 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 .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the .\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion. .\" output yourself in some meaningful fashion.
.\" .ie \nF \{\
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX . de IX
. tm Index:\\$1\t\\n%\t"\\$2" . tm Index:\\$1\t\\n%\t"\\$2"
.. ..
. if !\nF==2 \{
. nr % 0 . nr % 0
. nr F 2 . rr F
. \} .\}
. \} .el \{\
. de IX
..
.\} .\}
.rr rF
.\" .\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts. .\" Fear. Run. Save yourself. No user-serviceable parts.
@@ -133,7 +124,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "PCP1 1" .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 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .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. \& \-V \-\-vault <vaultfile> Specify an alternate vault file.
\& \-O \-\-outfile <file> Output file. STDOUT if unspecified. \& \-O \-\-outfile <file> Output file. STDOUT if unspecified.
\& \-I \-\-infile <file> Input file. STDIN 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>. \& \-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. \& \-i \-\-keyid <id> Specify a key id for various operations.
\& \-r \-\-recipient <string> Specify a recpipient, multiple allowed. \& \-r \-\-recipient <string> Specify a recpipient, multiple allowed.
\& \-t \-\-text Print textual representation of ojects. \& \-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 \& \-a \-\-armor \-\-textmode same as \-z
\& \&
\& Misc Options: \& 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: \& Arguments:
\& Extra arguments after options are treated as filenames or \& Extra arguments after options are treated as filenames or
\& recipients, depending on operation mode. \& recipients, depending on operation mode.
\&=head1 OPTIONS .Ve
\& .SH "OPTIONS"
.IX Header "OPTIONS"
.Vb 1
\& Usage: pcp1 [options] \& Usage: pcp1 [options]
\& \&
\& General Options: \& General Options:
@@ -209,10 +206,13 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& will be used. \& will be used.
\& \-I \-\-infile <file> Input file. If not specified, stdin \& \-I \-\-infile <file> Input file. If not specified, stdin
\& will be used. \& 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> \& \-X \-\-password\-file <file> Read passphrase from <file>. If <file>
\& is \-, read from stdin. This takes \& is \-, read from stdin. This takes
\& precedence over other uses of stdin \& precedence over other uses of stdin
\& elsewhere, see below for more details. \& elsewhere, see below for more details.
\& \-\-extpass <program> Use external program for password prompt.
\& \-i \-\-keyid <id> Specify a key id to import/export. \& \-i \-\-keyid <id> Specify a key id to import/export.
\& \-r \-\-recipient <string> Specify a recpipient, used for public \& \-r \-\-recipient <string> Specify a recpipient, used for public
\& key export and encryption. \& key export and encryption.
@@ -235,9 +235,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& been specified, don\*(Aqt store the generated \& been specified, don\*(Aqt store the generated
\& key to the vault but export it to the \& key to the vault but export it to the
\& file instead. You will be asked for \& file instead. You will be asked for
\& an owner, mail and a passphrase. If you \& an owner, mail and a passphrase.
\& leave the passphrase empty, the key will
\& be stored unencrypted.
\& \-l \-\-listkeys List all keys currently stored in your \& \-l \-\-listkeys List all keys currently stored in your
\& vault. Only the key id\*(Aqs and some info \& vault. Only the key id\*(Aqs and some info
\& about the keys will be printed, not the \& about the keys will be printed, not the
@@ -332,11 +330,9 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& uses stdin/stdout \& uses stdin/stdout
\& \&
\& Misc Options: \& Misc Options:
\& \-C \-\-checksum [<key>] Calculate a Blake2b checksum of one or more files. \& \-C \-\-checksum Calculate a Blake2b checksum of one or more files.
\& If <key> is provided, an authenticated hash will \& If \-x is provided, an authenticated hash will
\& be calculated, otherwise a normal hash. If you don\*(Aqt \& be calculated, otherwise a normal hash.
\& want to generate an authenticated hash, specify
\& \-\- after \-C.
\& Use \-I to specify one file or put multiple file \& Use \-I to specify one file or put multiple file
\& names after \-C like "pcp1 \-C \-\- file1 file2 file3". \& names after \-C like "pcp1 \-C \-\- file1 file2 file3".
.Ve .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 be used to encrypt files. \fBpcp1\fR uses eliptc curve cryptography
for encryption (\s-1CURVE25519\s0 by Dan J. Bernstein). While \s-1CURVE25519\s0 for encryption (\s-1CURVE25519\s0 by Dan J. Bernstein). While \s-1CURVE25519\s0
is no worldwide accepted standard it hasn't been compromised by 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 .PP
\&\fBCaution\fR: since \s-1CURVE25519\s0 is no accepted standard, \fBpcp1\fR has \&\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 to be considered as experimental software. In fact, I wrote it just
@@ -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 \&\fBIn short: don \s-1NOT\s0 use this software for production purposes!\fR
.SH "INTERNALS" .SH "INTERNALS"
.IX Header "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" .IX Subsection "VAULT FORMAT"
The vault file contains all public and secret keys. It's a portable The vault file contains all public and secret keys. It's a portable
binary file. binary file.
@@ -771,7 +785,7 @@ Type can be one of:
.Ve .Ve
.PP .PP
The key header is followed by the actual key, see below. 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" .IX Subsection "SECRET KEY FORMAT"
A secret key is a binary structure with the following format: A secret key is a binary structure with the following format:
.PP .PP
@@ -840,7 +854,7 @@ are otherwise unrelated. If one of them leaks, the other
cannot be recalculated from it. cannot be recalculated from it.
.PP .PP
Take a look at the function \fB\f(BIpcp_keypairs()\fB\fR for details. 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" .IX Subsection "PUBLIC KEY EXPORT FORMAT"
Exported public and secret keys will be written in a portable Exported public and secret keys will be written in a portable
way. Pcp uses \s-1RFC4880\s0 export format for public keys with some 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 \& hash
\& signature \& signature
.Ve .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" .IX Subsection "SECRET KEY EXPORT FORMAT"
Secret keys are exported in a proprietary format. Secret keys are exported in a proprietary format.
.PP .PP
@@ -976,7 +990,7 @@ to encrypt the data and looks after encryption as such:
.Vb 1 .Vb 1
\& Nonce | Cipher \& Nonce | Cipher
.Ve .Ve
.SS "\s-1ENCRYPTED OUTPUT FORMAT\s0" .SS "\s-1ENCRYPTED\s0 \s-1OUTPUT\s0 \s-1FORMAT\s0"
.IX Subsection "ENCRYPTED OUTPUT FORMAT" .IX Subsection "ENCRYPTED OUTPUT FORMAT"
The encryption protocol used by \s-1PCP\s0 uses mostly standard The encryption protocol used by \s-1PCP\s0 uses mostly standard
libsodium facilities with the exception that \s-1PCP\s0 uses counter 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 The encrypted output maybe Z85 encoded. In this case the Z85
encoding will be done blockwise with blocks of 16k bytes. The encoding will be done blockwise with blocks of 16k bytes. The
decoded content inside will be as described above. decoded content inside will be as described above.
.SS "\s-1SIGNATURE FORMAT\s0" .SS "\s-1SIGNATURE\s0 \s-1FORMAT\s0"
.IX Subsection "SIGNATURE FORMAT" .IX Subsection "SIGNATURE FORMAT"
There are different signature formats. Standard binary \s-1NACL\s0 There are different signature formats. Standard binary \s-1NACL\s0
signatures have the following format: signatures have the following format:
@@ -1121,15 +1135,15 @@ Armored signatures have the following format:
.PP .PP
The Z85 encoded signature at the end contains the same signature The Z85 encoded signature at the end contains the same signature
contents as the binary signature outlined above (hash+sig). 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" .IX Subsection "SIGNED ENCRYPTION FORMAT"
Signed encrypted files are in binary form only. The first part is 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 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 FORMAT\s0\fR followed by the binary encrypted signature described in \fB\s-1SIGNATURE\s0 \s-1FORMAT\s0\fR
without the offset separator. without the offset separator.
.PP .PP
However, not only the hash of the file content will be signed but the 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 valid recipient is therefore not able to re-encrypt the decrypted
message, append the original signature and send it to other recipients. message, append the original signature and send it to other recipients.
The signature would not match since the recipient list differs and The signature would not match since the recipient list differs and
@@ -1169,7 +1183,7 @@ Before encryption the signature format is:
\& +\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ \& +\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
.Ve .Ve
.PP .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 .PP
Pseudocode: Pseudocode:
.PP .PP
@@ -1236,9 +1250,9 @@ pcp1 \-z \-I file \-O file.z85
Reverse the process: Reverse the process:
.PP .PP
pcp1 \-Z \-I file.z85 \-O file pcp1 \-Z \-I file.z85 \-O file
.SS "\s-1PBP COMPATIBILITY\s0" .SS "\s-1PBP\s0 \s-1COMPATIBILITY\s0"
.IX Subsection "PBP COMPATIBILITY" .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, 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 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 no shared key format between pbp and pcp. However, it is possible to export and
@@ -1262,8 +1276,8 @@ functions:
.PD .PD
.PP .PP
\&\s-1JSON\s0 support can be used either with the commandline tool \fBpcp1\fR or programmatically \&\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 using the C, \*(C+ or Python \s-1API\s0.
.SS "\s-1USING JSON FROM THE C API\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" .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: In order to use \s-1JSON\s0 all you've got to do is to switch a context flag:
.PP .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 .Ve
.PP .PP
That all to it. Now any function normally used for key import and export works 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. 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" .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 In order to use \s-1JSON\s0 on the commandline, add \fB\-j\fR. This can be used in
conjunction with the following options: conjunction with the following options:
@@ -1293,9 +1307,9 @@ Public and secret key import.
Text view mode (aka inspect mode). Text view mode (aka inspect mode).
.PP .PP
The \fB\-z\fR and \fB\-Z\fR options are ignored in \s-1JSON\s0 mode. 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" .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)" .IX Subsection "JSON PUBLIC KEY (pcp1 -p -j)"
.PP .PP
The \s-1JSON\s0 object for a public key looks like this: The \s-1JSON\s0 object for a public key looks like this:
@@ -1324,7 +1338,7 @@ Fields containing byte arrays are hex encoded.
.PP .PP
Numbers are represented as literal integers. Numbers are represented as literal integers.
.PP .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)" .IX Subsection "JSON SECRET KEY (pcp1 -s -j)"
.PP .PP
The \s-1JSON\s0 object for a public key looks like this: 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 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. decoupled from \fBsecrets\fR. This may change in the future.
.PP .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)" .IX Subsection "JSON VAULT (pcp1 -t)"
.PP .PP
The \s-1JSON\s0 object for the vault looks like this: 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 The field \fBkeys\fR is an array containing one or more of the already
described key objects. described key objects.
.PP .PP
\fI\s-1JSON PROGRAM OUTPUT\s0\fR \fI\s-1JSON\s0 \s-1PROGRAM\s0 \s-1OUTPUT\s0\fR
.IX Subsection "JSON PROGRAM OUTPUT" .IX Subsection "JSON PROGRAM OUTPUT"
.PP .PP
Currently pcp does not support \s-1JSON\s0 program output, that is, success or 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> \&\fIT.v.Dein <tom \s-1AT\s0 vondein \s-1DOT\s0 org\fR>
.SH "LICENSE" .SH "LICENSE"
.IX Header "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" .SH "HOME"
.IX Header "HOME" .IX Header "HOME"
The homepage of Pretty Curved Privacy can be found on 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. -V --vault <vaultfile> Specify an alternate vault file.
-O --outfile <file> Output file. STDOUT if unspecified. -O --outfile <file> Output file. STDOUT if unspecified.
-I --infile <file> Input file. STDIN 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>. -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. -i --keyid <id> Specify a key id for various operations.
-r --recipient <string> Specify a recpipient, multiple allowed. -r --recipient <string> Specify a recpipient, multiple allowed.
-t --text Print textual representation of ojects. -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 -a --armor --textmode same as -z
Misc Options: 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: Arguments:
Extra arguments after options are treated as filenames or Extra arguments after options are treated as filenames or
recipients, depending on operation mode. recipients, depending on operation mode.
=head1 OPTIONS =head1 OPTIONS
Usage: pcp1 [options] Usage: pcp1 [options]
@@ -72,10 +77,13 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
will be used. will be used.
-I --infile <file> Input file. If not specified, stdin -I --infile <file> Input file. If not specified, stdin
will be used. 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> -X --password-file <file> Read passphrase from <file>. If <file>
is -, read from stdin. This takes is -, read from stdin. This takes
precedence over other uses of stdin precedence over other uses of stdin
elsewhere, see below for more details. elsewhere, see below for more details.
--extpass <program> Use external program for password prompt.
-i --keyid <id> Specify a key id to import/export. -i --keyid <id> Specify a key id to import/export.
-r --recipient <string> Specify a recpipient, used for public -r --recipient <string> Specify a recpipient, used for public
key export and encryption. key export and encryption.
@@ -98,9 +106,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
been specified, don't store the generated been specified, don't store the generated
key to the vault but export it to the key to the vault but export it to the
file instead. You will be asked for file instead. You will be asked for
an owner, mail and a passphrase. If you an owner, mail and a passphrase.
leave the passphrase empty, the key will
be stored unencrypted.
-l --listkeys List all keys currently stored in your -l --listkeys List all keys currently stored in your
vault. Only the key id's and some info vault. Only the key id's and some info
about the keys will be printed, not the about the keys will be printed, not the
@@ -195,11 +201,9 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
uses stdin/stdout uses stdin/stdout
Misc Options: Misc Options:
-C --checksum [<key>] Calculate a Blake2b checksum of one or more files. -C --checksum Calculate a Blake2b checksum of one or more files.
If <key> is provided, an authenticated hash will If -x is provided, an authenticated hash will
be calculated, otherwise a normal hash. If you don't be calculated, otherwise a normal hash.
want to generate an authenticated hash, specify
-- after -C.
Use -I to specify one file or put multiple file Use -I to specify one file or put multiple file
names after -C like "pcp1 -C -- file1 file2 file3". 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 =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 =head2 VAULT FORMAT
The vault file contains all public and secret keys. It's a portable The vault file contains all public and secret keys. It's a portable

120
meson.build Normal file
View File

@@ -0,0 +1,120 @@
# -*-python-*-
project(
'pcp',
'c',
license: 'GPL',
version: '0.4.1',
meson_version: '>=1.3',
default_options: [
'warning_level=2',
'werror=true',
],
)
add_project_arguments(
[
'-Wno-unused-parameter',
'-Wno-unused-result',
'-Wno-missing-braces',
'-Wno-format-zero-length',
'-Wno-implicit-fallthrough',
#'-Wvla',
'-Wno-sign-compare',
'-Wno-narrowing'
],
language: 'c',
)
c = meson.get_compiler('c')
conf = configuration_data()
pcp_inc = include_directories('src', 'libpcp')
if host_machine.system().startswith('freebsd')
pcp_inc = include_directories('.', '/usr/local/include')
add_project_link_arguments('LDFLAGS=/usr/local/lib')
endif
# check for funcs.
foreach func : ['getopt', 'fdopen', 'fgetc', 'getenv', 'getpass', 'arc4random', 'fopen', 'fread', 'fwrite', 'ftruncate', 'fprintf', 'isatty', 'malloc', 'memset', 'memcpy', 'perror', 'posix_memalign', 'setrlimit', 'strnlen', 'strlen', 'strtol', 'tcgetattr', 'umask', 'towlower', 'getopt', 'getopt_long', 'vasprintf',]
conf.set('HAVE_'+func.to_upper(),
c.has_function(
func,
prefix : '#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/resource.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <termios.h>\n#include <wctype.h>\n#include <getopt.h>',
)
)
endforeach
if host_machine.system().startswith('freebsd')
conf.set('HAVE_STRNSTR',
c.has_function(
'strnstr',
prefix: '#include <string.h>'
))
else
bsd = c.find_library('bsd')
conf.set('HAVE_STRNSTR',
c.has_function(
'strnstr',
prefix: '#include <bsd/string.h>',
dependencies: bsd,
))
add_project_dependencies(bsd, language: 'c')
endif
# check commandline options
prefix = get_option('prefix')
if get_option('buildtype') == 'debug'
conf.set('DEBUG', '1')
endif
# setup conf map
version = '@0@'.format(meson.project_version())
conf.set('prefix', prefix)
conf.set('VERSION', version)
subdir('libpcp')
# code
pcp_sources = files(
'src/compat_getopt.c',
'src/encryption.c',
'src/keymgmt.c',
'src/keyprint.c',
'src/pcp.c',
'src/signature.c',
'src/z85util.c'
)
executable(
'pcp',
[pcp_sources],
include_directories: [pcp_inc],
dependencies: [libpcp_dep, jansson],
install: true
)
# build manual page
pod2man = find_program('pod2man', native: true)
if pod2man.found()
res = run_command(pod2man.full_path(), 'man/pcp.pod', 'pcp.1', check:true)
if res.returncode() == 0
install_man('pcp.1')
endif
endif
subdir('tests')

1
meson_options.txt Normal file
View File

@@ -0,0 +1 @@
# custom build options

View File

@@ -20,14 +20,14 @@
# #
AM_CFLAGS = -I../include/pcp -I../libpcp/scrypt/crypto AM_CFLAGS = -I../include/pcp
EXTRA_DIST = *.h EXTRA_DIST = *.h
bin_PROGRAMS = pcp1 bin_PROGRAMS = pcp1
pcp1_LDADD = ../libpcp/.libs/libpcp1.a 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 \ encryption.c z85util.c signature.c \
compat_getopt.c compat_getopt.c

View File

@@ -26,11 +26,9 @@
#ifndef MY_GETOPT_H_INCLUDED #ifndef MY_GETOPT_H_INCLUDED
#define MY_GETOPT_H_INCLUDED #define MY_GETOPT_H_INCLUDED
#ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif
#if defined(HAVE_GETOPT_H) && defined(HAVE_GETOPT_LONG) #if defined(HAVE_GETOPT) && defined(HAVE_GETOPT_LONG)
#include <getopt.h> #include <getopt.h>
#else #else
@@ -51,7 +49,7 @@ extern "C" {
#define optarg my_optarg #define optarg my_optarg
/* UNIX-style short-argument parser */ /* UNIX-style short-argument parser */
extern int my_getopt(int argc, char * argv[], const char *opts); extern int my_getopt(int argc, char *argv[], const char *opts);
extern int my_optind, my_opterr, my_optopt; extern int my_optind, my_opterr, my_optopt;
extern char *my_optarg; extern char *my_optarg;
@@ -72,13 +70,13 @@ struct option {
#define optional_argument 2 #define optional_argument 2
/* GNU-style long-argument parsers */ /* GNU-style long-argument parsers */
extern int my_getopt_long(int argc, char * argv[], const char *shortopts, extern int my_getopt_long(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind); const struct option *longopts, int *longind);
extern int my_getopt_long_only(int argc, char * argv[], const char *shortopts, extern int my_getopt_long_only(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind); const struct option *longopts, int *longind);
extern int _my_getopt_internal(int argc, char * argv[], const char *shortopts, extern int _my_getopt_internal(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind, const struct option *longopts, int *longind,
int long_only); int long_only);

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -66,7 +66,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
char *passphrase; char *passphrase;
if(passwd == NULL) { if(passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase for symetric decryption", NULL, 1, NULL); "Enter passphrase for symetric decryption", NULL, 1, NULL);
} }
else { else {
@@ -78,7 +78,8 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
sfree(passphrase); sfree(passphrase);
free(salt); 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 */ /* asymetric mode */
if(useid) { if(useid) {
secret = pcphash_keyexists(ptx, id); secret = pcphash_keyexists(ptx, id);
@@ -95,11 +96,10 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
goto errde3; goto errde3;
} }
} }
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase; char *passphrase;
if(passwd == NULL) { if(passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL); "Enter passphrase to decrypt your secret key", NULL, 1, NULL);
} }
else { else {
@@ -117,6 +117,10 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
if(head == PCP_ASYM_CIPHER_SIG) if(head == PCP_ASYM_CIPHER_SIG)
verify = 1; verify = 1;
if(head == PCP_ASYM_CIPHER_ANON_SIG) {
anon = 1;
verify = 1;
} }
} }
else { else {
@@ -135,6 +139,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
else { else {
dlen = pcp_decrypt_stream(ptx, pin, pout, NULL, symkey, verify, 0); dlen = pcp_decrypt_stream(ptx, pin, pout, NULL, symkey, verify, 0);
sfree(symkey); sfree(symkey);
symkey = NULL;
} }
ps_close(pin); ps_close(pin);
@@ -151,20 +156,22 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
errde3: errde3:
if(symkey != NULL) if(symkey != NULL)
free(symkey); sfree(symkey);
return 1; 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 *in = NULL;
FILE *out = NULL; FILE *out = NULL;
pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */ pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */
pcp_pubkey_t *tmp = NULL; pcp_pubkey_t *tmp = NULL;
pcp_pubkey_t *pub = NULL; pcp_pubkey_t *pub = NULL;
pcp_key_t *secret = NULL; pcp_key_t *secret = NULL;
pcp_key_t *signsecret = NULL;
byte *symkey = NULL; byte *symkey = NULL;
int symmode = 0; int symmode = 0;
@@ -173,7 +180,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
symmode = 1; symmode = 1;
char *passphrase; char *passphrase;
if(passwd == NULL) { if(passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase for symetric encryption", "Repeat passphrase", 1, NULL); "Enter passphrase for symetric encryption", "Repeat passphrase", 1, NULL);
} }
else { else {
@@ -253,21 +260,16 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
if(symmode != 1) { if(symmode != 1) {
/* we're using a random secret keypair on our side */ /* we're using a random secret keypair on our side */
if(anon) { if(signcrypt || !anon) {
secret = pcpkey_new();
}
else {
secret = pcp_find_primary_secret(); secret = pcp_find_primary_secret();
if(secret == NULL) { if(secret == NULL) {
fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename); 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; char *passphrase;
if(passwd == NULL) { if(passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL); "Enter passphrase to decrypt your secret key", NULL, 1, NULL);
} }
else { else {
@@ -278,8 +280,11 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
sfree(passphrase); sfree(passphrase);
if(secret == NULL) if(secret == NULL)
goto erren2; goto erren2;
signsecret = secret;
} }
} if(anon)
secret = pcpkey_new();
} }
if(infile == NULL) if(infile == NULL)
@@ -315,7 +320,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
sfree(symkey); sfree(symkey);
} }
else { 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) { if(armor == 1) {
@@ -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) { void pcpchecksum(char **files, int filenum, char *key) {
int i; int i;
byte *checksum = ucmalloc(crypto_generichash_BYTES_MAX); byte *checksum = ucmalloc(crypto_generichash_BYTES_MAX);
byte *keyhash = NULL; size_t keylen = 0;
size_t hashlen = 0;
if(key != NULL) { if(key != NULL)
keyhash = ucmalloc(crypto_generichash_BYTES); keylen = strlen(key);
crypto_generichash(keyhash, crypto_generichash_BYTES,
(byte *)key, strlen(key),
NULL, crypto_generichash_BYTES);
hashlen = crypto_generichash_BYTES;
}
for(i=0; i<filenum; i++) { for(i=0; i<filenum; i++) {
FILE *in; FILE *in;
@@ -387,7 +386,7 @@ void pcpchecksum(char **files, int filenum, char *key) {
} }
} }
Pcpstream *pin = ps_new_file(in); 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); char *hex = _bin2hex(checksum, crypto_generichash_BYTES_MAX);
fprintf(stdout, "BLAKE2b (%s) = %s\n", files[i], hex); fprintf(stdout, "BLAKE2b (%s) = %s\n", files[i], hex);
free(hex); free(hex);
@@ -397,7 +396,4 @@ void pcpchecksum(char **files, int filenum, char *key) {
} }
free(checksum); free(checksum);
if(keyhash != NULL)
free(keyhash);
} }

View File

@@ -19,27 +19,28 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#ifndef _HAVE_ENCRYPTION_H #ifndef _HAVE_ENCRYPTION_H
#define _HAVE_ENCRYPTION_H #define _HAVE_ENCRYPTION_H
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "context.h"
#include "crypto.h"
#include "defines.h" #include "defines.h"
#include "key.h" #include "key.h"
#include "crypto.h" #include "keyhash.h"
#include "keyprint.h"
#include "pcp.h" #include "pcp.h"
#include "pcpstream.h"
#include "plist.h"
#include "uthash.h" #include "uthash.h"
#include "z85.h" #include "z85.h"
#include "keyprint.h"
#include "keyhash.h"
#include "plist.h"
#include "pcpstream.h"
#include "context.h"
int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, int verify); int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd,
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor, int anon); int verify);
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd,
plist_t *recipient, int signcrypt, int armor, int anon);
void pcpchecksum(char **files, int filenum, char *key); void pcpchecksum(char **files, int filenum, char *key);
#endif /* _HAVE_ENCRYPTION_H */ #endif /* _HAVE_ENCRYPTION_H */

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -19,13 +19,11 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#include "keymgmt.h" #include "keymgmt.h"
char *pcp_getstdin(const char *prompt) { char *pcp_getstdin(const char *prompt) {
char line[255]; char line[255];
char *out; char *out = NULL;
fprintf(stderr, "%s: ", prompt); fprintf(stderr, "%s: ", prompt);
@@ -43,17 +41,17 @@ char *pcp_getstdin(const char *prompt) {
return out; return out;
errgst: errgst:
return NULL; return NULL;
} }
int pcp_storekey (pcp_key_t *key) { int pcp_storekey(pcp_key_t *key) {
if(vault->isnew == 1 || pcphash_count(ptx) == 0) { if (vault->isnew == 1 || pcphash_count(ptx) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET; key->type = PCP_KEY_TYPE_MAINSECRET;
} }
if(pcpvault_addkey(ptx, vault, key, key->type) == 0) { if (pcpvault_addkey(ptx, vault, key, key->type) == 0) {
if(vault->isnew) if (vault->isnew)
fprintf(stderr, "new vault created, "); fprintf(stderr, "new vault created, ");
fprintf(stderr, "key 0x%s added to %s.\n", key->id, vault->filename); fprintf(stderr, "key 0x%s added to %s.\n", key->id, vault->filename);
return 0; return 0;
@@ -63,106 +61,107 @@ int pcp_storekey (pcp_key_t *key) {
} }
void pcp_keygen(char *passwd) { void pcp_keygen(char *passwd) {
pcp_key_t *k = pcpkey_new (); pcp_key_t *k = pcpkey_new();
pcp_key_t *key = NULL; pcp_key_t *key = NULL;
char *owner = pcp_getstdin("Enter the name of the key owner"); char *owner = pcp_getstdin("Enter the name of the key owner");
if (owner != NULL)
memcpy(k->owner, owner, strlen(owner) + 1); memcpy(k->owner, owner, strlen(owner) + 1);
char *mail = pcp_getstdin("Enter the email address of the key owner"); char *mail = pcp_getstdin("Enter the email address of the key owner");
if (mail != NULL)
memcpy(k->mail, _lc(mail), strlen(mail) + 1); memcpy(k->mail, _lc(mail), strlen(mail) + 1);
if(debug) if (debug)
pcp_dumpkey(k); pcp_dumpkey(k);
char *passphrase; char *passphrase;
if(passwd == NULL) { if (passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase, "Enter passphrase for key encryption",
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL); "Enter the passphrase again", 1, NULL);
} } else {
else { passphrase = passwd;
passphrase = ucmalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
} }
if(strnlen(passphrase, 1024) > 0) if (strnlen(passphrase, 1024) > 0) {
key = pcpkey_encrypt(ptx, k, passphrase); double ent = pcp_getentropy(passphrase);
else { if (ent < 3.32) {
char *yes = pcp_getstdin("WARNING: secret key will be stored unencrypted. Are you sure [yes|NO]?"); fprintf(stderr,
if(strncmp(yes, "yes", 1024) == 0) "WARNING: you are using a weak passphrase (entropy: %lf)!\n",
key = k; ent);
else { char *yes = pcp_getstdin("Are you sure to use it [yes|NO]?");
memset(key, 0, sizeof(pcp_key_t)); if (strncmp(yes, "yes", 1024) != 0) {
free(key);
goto errkg1; 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) { if (key != NULL) {
fprintf(stderr, "Generated new secret key:\n"); fprintf(stderr, "Generated new secret key:\n");
if(pcp_storekey(key) == 0) { if (pcp_storekey(key) == 0) {
pcpkey_printshortinfo(key); pcpkey_printshortinfo(key);
memset(key, 0, sizeof(pcp_key_t)); memset(key, 0, sizeof(pcp_key_t));
free(key); free(key);
} }
} }
errkg1: if (passwd == NULL) {
/* if passwd is set, it'll be free'd in main() */
sfree(passphrase);
}
errkg1:
free(mail); free(mail);
free(owner); free(owner);
} }
void pcp_listkeys() { void pcp_listkeys() {
pcp_key_t *k; pcp_key_t *k;
int nkeys = pcphash_count(ptx) + pcphash_countpub(ptx); int nkeys = pcphash_count(ptx) + pcphash_countpub(ptx);
if(nkeys > 0) { if (nkeys > 0) {
printf("Key ID Type Creation Time Owner\n"); printf(
"Key ID Type Creation Time Owner\n");
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) { pcpkey_printlineinfo(k); }
pcpkey_printlineinfo(k);
}
pcp_pubkey_t *p; pcp_pubkey_t *p;
pcphash_iteratepub(ptx, p) { pcphash_iteratepub(ptx, p) { pcppubkey_printlineinfo(p); }
pcppubkey_printlineinfo(p); } else {
} fatal(ptx, "The key vault file %s doesn't contain any keys so far.\n",
} vault->filename);
else {
fatal(ptx, "The key vault file %s doesn't contain any keys so far.\n", vault->filename);
} }
} }
char *pcp_normalize_id(char *keyid) { char *pcp_normalize_id(char *keyid) {
char *id = ucmalloc(17); char *id = ucmalloc(17);
int len = strnlen(keyid, 24); int len = strnlen(keyid, 24);
if(len == 16) { if (len == 16) {
memcpy(id, keyid, 17); memcpy(id, keyid, 17);
} } else if (len < 16) {
else if(len < 16) {
fatal(ptx, "Specified key id %s is too short!\n", keyid); fatal(ptx, "Specified key id %s is too short!\n", keyid);
free(id); free(id);
return NULL; return NULL;
} } else if (len > 18) {
else if(len > 18) {
fatal(ptx, "Specified key id %s is too long!\n", keyid); fatal(ptx, "Specified key id %s is too long!\n", keyid);
free(id); free(id);
return NULL; return NULL;
} } else {
else { if (keyid[0] == '0' && keyid[1] == 'x' && len == 18) {
if(keyid[0] == '0' && keyid[1] == 'x' && len == 18) {
int i; int i;
for(i=0; i<16; ++i) { for (i = 0; i < 16; ++i) {
id[i] = keyid[i+2]; id[i] = keyid[i + 2];
} }
id[16] = 0; id[16] = 0;
} } else {
else {
fatal(ptx, "Specified key id %s is too long!\n", keyid); fatal(ptx, "Specified key id %s is too long!\n", keyid);
free(id); free(id);
return NULL; return NULL;
@@ -175,251 +174,239 @@ char *pcp_normalize_id(char *keyid) {
pcp_key_t *pcp_find_primary_secret() { pcp_key_t *pcp_find_primary_secret() {
pcp_key_t *k; pcp_key_t *k;
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) {
if(k->type == PCP_KEY_TYPE_MAINSECRET) { if (k->type == PCP_KEY_TYPE_MAINSECRET) {
return k; return k;
} }
} }
/* no primary? whoops */ /* no primary? whoops */
int nkeys = pcphash_count(ptx); int nkeys = pcphash_count(ptx);
if(nkeys == 1) { if (nkeys == 1) {
pcphash_iterate(ptx, k) { pcphash_iterate(ptx, k) { return k; }
return k;
}
} }
return NULL; return NULL;
} }
void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *passwd) { void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor,
char *passwd) {
pcp_key_t *key = NULL; pcp_key_t *key = NULL;
if(useid == 1) { if (useid == 1) {
/* look if we've got that one */ /* look if we've got that one */
key = pcphash_keyexists(ptx, keyid); key = pcphash_keyexists(ptx, keyid);
if(key == NULL) { if (key == NULL) {
fatal(ptx, "Could not find a secret key with id 0x%s in vault %s!\n", keyid, vault->filename); fatal(ptx, "Could not find a secret key with id 0x%s in vault %s!\n",
keyid, vault->filename);
goto errexpse1; goto errexpse1;
} }
} } else {
else {
/* look for our primary key */ /* look for our primary key */
key = pcp_find_primary_secret(); key = pcp_find_primary_secret();
if(key == NULL) { if (key == NULL) {
fatal(ptx, "There's no primary secret key in the vault %s!\n", vault->filename); fatal(ptx, "There's no primary secret key in the vault %s!\n",
vault->filename);
goto errexpse1; goto errexpse1;
} }
} }
FILE *out; FILE *out;
if(outfile == NULL) { if (outfile == NULL) {
out = stdout; out = stdout;
} } else {
else { if ((out = fopen(outfile, "wb+")) == NULL) {
if((out = fopen(outfile, "wb+")) == NULL) {
fatal(ptx, "Could not create output file %s\n", outfile); fatal(ptx, "Could not create output file %s\n", outfile);
goto errexpse1; goto errexpse1;
} }
} }
if(out != NULL) { if (out != NULL) {
if(debug) if (debug)
pcp_dumpkey(key); pcp_dumpkey(key);
if(key->secret[0] == 0) { if (passwd == NULL) {
/* decrypt the secret key */
if(passwd == NULL) {
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL); "Enter passphrase to decrypt your secret key", NULL, 1,
NULL);
key = pcpkey_decrypt(ptx, key, passphrase); key = pcpkey_decrypt(ptx, key, passphrase);
if(key == NULL) { if (key == NULL) {
sfree(passphrase); sfree(passphrase);
goto errexpse1; goto errexpse1;
} }
sfree(passphrase); sfree(passphrase);
} } else {
else {
key = pcpkey_decrypt(ptx, key, passwd); key = pcpkey_decrypt(ptx, key, passwd);
if(key == NULL) { if (key == NULL) {
goto errexpse1; goto errexpse1;
} }
} }
}
Buffer *exported_sk; Buffer *exported_sk;
if(passwd != NULL) { if (passwd != NULL) {
exported_sk = pcp_export_secret(ptx, key, passwd); exported_sk = pcp_export_secret(ptx, key, passwd);
} } else {
else {
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to encrypt the exported secret key", "Enter passphrase to encrypt the exported secret key",
"Repeat passphrase", 1, NULL); "Repeat passphrase", 1, NULL);
exported_sk = pcp_export_secret(ptx, key, passphrase); exported_sk = pcp_export_secret(ptx, key, passphrase);
sfree(passphrase); sfree(passphrase);
} }
if(exported_sk != NULL) { if (exported_sk != NULL) {
if(armor == 1) { if (armor == 1) {
size_t zlen; size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen, 1); 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); fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_SK_HEADER, z85, EXP_SK_FOOTER);
free(z85); free(z85);
} } else {
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); buffer_free(exported_sk);
fprintf(stderr, "secret key exported.\n"); fprintf(stderr, "secret key exported.\n");
} }
} }
errexpse1: errexpse1:;
;
} }
/* /*
if id given, look if it is already a public and export this, if id given, look if it is already a public and export this,
else we look for a secret key with that id. without a given else we look for a secret key with that id. without a given
keyid we use the primary key. if no keyid has been given but keyid we use the primary key. if no keyid has been given but
a recipient instead, we try to look up the vault for a match. a recipient instead, we try to look up the vault for a match.
*/ */
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor) { void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format,
int armor) {
FILE *out; FILE *out;
int is_foreign = 0; int is_foreign = 0;
pcp_pubkey_t *pk = NULL; pcp_pubkey_t *pk = NULL;
pcp_key_t *sk = NULL; pcp_key_t *sk = NULL;
Buffer *exported_pk = NULL; Buffer *exported_pk = NULL;
if(outfile == NULL) { if (outfile == NULL) {
out = stdout; out = stdout;
} } else {
else { if ((out = fopen(outfile, "wb+")) == NULL) {
if((out = fopen(outfile, "wb+")) == NULL) {
fatal(ptx, "Could not create output file %s\n", outfile); fatal(ptx, "Could not create output file %s\n", outfile);
goto errpcpexpu1; goto errpcpexpu1;
} }
} }
if(keyid != NULL) { if (keyid != NULL) {
/* keyid specified, check if it exists and if yes, what type it is */ /* keyid specified, check if it exists and if yes, what type it is */
pk = pcphash_pubkeyexists(ptx, keyid); pk = pcphash_pubkeyexists(ptx, keyid);
if(pk == NULL) { if (pk == NULL) {
/* ok, so, then look for a secret key with that id */ /* ok, so, then look for a secret key with that id */
sk = pcphash_keyexists(ptx, keyid); sk = pcphash_keyexists(ptx, keyid);
if(sk == NULL) { if (sk == NULL) {
fatal(ptx, "Could not find a key with id 0x%s in vault %s!\n", fatal(ptx, "Could not find a key with id 0x%s in vault %s!\n", keyid,
keyid, vault->filename); vault->filename);
goto errpcpexpu1; goto errpcpexpu1;
} } else {
else {
/* ok, so it's our own key */ /* ok, so it's our own key */
is_foreign = 0; is_foreign = 0;
} }
} } else {
else {
/* it's a foreign public key, we cannot sign it ourselfes */ /* it's a foreign public key, we cannot sign it ourselfes */
is_foreign = 1; is_foreign = 1;
} }
} } else {
else {
/* we use our primary key anyway */ /* we use our primary key anyway */
sk = pcp_find_primary_secret(); sk = pcp_find_primary_secret();
if(sk == NULL) { if (sk == NULL) {
fatal(ptx, "There's no primary secret key in the vault %s!\n", vault->filename); fatal(ptx, "There's no primary secret key in the vault %s!\n",
vault->filename);
goto errpcpexpu1; goto errpcpexpu1;
} }
is_foreign = 0; is_foreign = 0;
} }
if (is_foreign == 0 && sk->secret[0] == 0 && format <= EXP_FORMAT_PBP) {
if(is_foreign == 0 && sk->secret[0] == 0 && format <= EXP_FORMAT_PBP) {
/* decrypt the secret key */ /* decrypt the secret key */
if(passwd != NULL) { if (passwd != NULL) {
sk = pcpkey_decrypt(ptx, sk, passwd); sk = pcpkey_decrypt(ptx, sk, passwd);
} } else {
else {
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL); "Enter passphrase to decrypt your secret key", NULL, 1,
NULL);
sk = pcpkey_decrypt(ptx, sk, passphrase); sk = pcpkey_decrypt(ptx, sk, passphrase);
sfree(passphrase); sfree(passphrase);
} }
if(sk == NULL) { if (sk == NULL) {
goto errpcpexpu1; goto errpcpexpu1;
} }
} }
/* now, we're ready for the actual export */ /* now, we're ready for the actual export */
if(format == EXP_FORMAT_NATIVE) { if (format == EXP_FORMAT_NATIVE) {
if(is_foreign == 0) { if (is_foreign == 0) {
exported_pk = pcp_export_rfc_pub(ptx, sk); exported_pk = pcp_export_rfc_pub(ptx, sk);
if(exported_pk != NULL) { if (exported_pk != NULL) {
if(armor == 1) { if (armor == 1) {
size_t zlen; size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1); 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); fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
free(z85); free(z85);
} } else
else
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), out); fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), out);
buffer_free(exported_pk); buffer_free(exported_pk);
fprintf(stderr, "public key exported.\n"); fprintf(stderr, "public key exported.\n");
} }
} } else {
else {
/* FIXME: export foreign keys unsupported yet */ /* FIXME: export foreign keys unsupported yet */
fatal(ptx, "Exporting foreign public keys in native format unsupported yet\n"); fatal(ptx,
"Exporting foreign public keys in native format unsupported yet\n");
goto errpcpexpu1; goto errpcpexpu1;
} }
} } else if (format == EXP_FORMAT_PBP) {
else if(format == EXP_FORMAT_PBP) { if (is_foreign == 0) {
if(is_foreign == 0) {
exported_pk = pcp_export_pbp_pub(sk); exported_pk = pcp_export_pbp_pub(sk);
if(exported_pk != NULL) { if (exported_pk != NULL) {
/* PBP format requires armoring always */ /* PBP format requires armoring always */
size_t zlen; size_t zlen;
char *z85pbp = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen, 1); char *z85pbp = pcp_z85_encode(buffer_get(exported_pk),
buffer_size(exported_pk), &zlen, 1);
fprintf(out, "%s", z85pbp); fprintf(out, "%s", z85pbp);
free(z85pbp); free(z85pbp);
buffer_free(exported_pk); buffer_free(exported_pk);
fprintf(stderr, "public key exported in PBP format.\n"); fprintf(stderr, "public key exported in PBP format.\n");
} }
} } else {
else {
fatal(ptx, "Exporting foreign public keys in PBP format not possible\n"); fatal(ptx, "Exporting foreign public keys in PBP format not possible\n");
goto errpcpexpu1; goto errpcpexpu1;
} }
} }
errpcpexpu1: errpcpexpu1:;
;
} }
void pcpdelete_key(char *keyid) { void pcpdelete_key(char *keyid) {
pcp_pubkey_t *p = pcphash_pubkeyexists(ptx, keyid); pcp_pubkey_t *p = pcphash_pubkeyexists(ptx, keyid);
if(p != NULL) { if (p != NULL) {
/* delete public */ /* 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); pcphash_del(ptx, p, p->type);
vault->unsafed = 1; vault->unsafed = 1;
fprintf(stderr, "Public key deleted.\n"); fprintf(stderr, "Public key deleted.\n");
} } else {
else {
pcp_key_t *s = pcphash_keyexists(ptx, keyid); pcp_key_t *s = pcphash_keyexists(ptx, keyid);
if(s != NULL) { if (s != NULL) {
/* delete secret */ /* delete secret */
pcphash_del(ptx, s, s->type); pcphash_del(ptx, s, s->type);
vault->unsafed = 1; vault->unsafed = 1;
fprintf(stderr, "Secret key deleted.\n"); fprintf(stderr, "Secret key deleted.\n");
} } else {
else {
fatal(ptx, "No key with id 0x%s found!\n", keyid); fatal(ptx, "No key with id 0x%s found!\n", keyid);
} }
} }
@@ -428,51 +415,56 @@ void pcpdelete_key(char *keyid) {
void pcpedit_key(char *keyid) { void pcpedit_key(char *keyid) {
pcp_key_t *key = pcphash_keyexists(ptx, keyid); pcp_key_t *key = pcphash_keyexists(ptx, keyid);
if(key != NULL) { if (key != NULL) {
if(key->secret[0] == 0) { if (key->secret[0] == 0) {
char *passphrase; 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); key = pcpkey_decrypt(ptx, key, passphrase);
sfree(passphrase); sfree(passphrase);
} }
if(key != NULL) { if (key != NULL) {
fprintf(stderr, "Current owner: %s\n", key->owner); fprintf(stderr, "Current owner: %s\n", key->owner);
char *owner = pcp_getstdin(" enter new name or press enter to keep current"); char *owner =
if(strlen(owner) > 0) 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); fprintf(stderr, "Current mail: %s\n", key->mail);
char *mail = pcp_getstdin(" enter new email or press enter to keep current"); char *mail =
if(strlen(mail) > 0) 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(owner);
free(mail); free(mail);
if(key->type != PCP_KEY_TYPE_MAINSECRET) { if (key->type != PCP_KEY_TYPE_MAINSECRET) {
pcp_key_t *other = NULL; pcp_key_t *other = NULL;
uint8_t haveprimary = 0; uint8_t haveprimary = 0;
pcphash_iterate(ptx, other) { pcphash_iterate(ptx, other) {
if(other->type == PCP_KEY_TYPE_MAINSECRET) { if (other->type == PCP_KEY_TYPE_MAINSECRET) {
haveprimary = 1; haveprimary = 1;
break; break;
} }
} }
char *yes = NULL; char *yes = NULL;
if(! haveprimary) { if (!haveprimary) {
fprintf(stderr, "There is currently no primary secret in your vault,\n"); fprintf(stderr,
"There is currently no primary secret in your vault,\n");
yes = pcp_getstdin("want to make this one the primary [yes|NO]?"); yes = pcp_getstdin("want to make this one the primary [yes|NO]?");
} } else {
else { fprintf(stderr, "The key %s is currently the primary secret,\n",
fprintf(stderr, "The key %s is currently the primary secret,\n", other->id); other->id);
yes = pcp_getstdin("want to make this one the primary instead [yes|NO]?"); yes = pcp_getstdin(
"want to make this one the primary instead [yes|NO]?");
} }
if(strncmp(yes, "yes", 1024) == 0) { if (strncmp(yes, "yes", 1024) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET; key->type = PCP_KEY_TYPE_MAINSECRET;
if(haveprimary) { if (haveprimary) {
fprintf(stderr, "other type: %d\n", other->type); fprintf(stderr, "other type: %d\n", other->type);
other->type = PCP_KEY_TYPE_SECRET; other->type = PCP_KEY_TYPE_SECRET;
fprintf(stderr, " new type: %d\n", other->type); fprintf(stderr, " new type: %d\n", other->type);
@@ -482,41 +474,40 @@ void pcpedit_key(char *keyid) {
} }
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter new passphrase for key encryption (press enter to keep current)", "Enter new passphrase for key encryption (press enter to "
"keep current)",
"Enter the passphrase again", 1, NULL); "Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) { if (strnlen(passphrase, 1024) > 0) {
key = pcpkey_encrypt(ptx, key, passphrase); key = pcpkey_encrypt(ptx, key, passphrase);
sfree(passphrase); sfree(passphrase);
} }
if(key != NULL) { if (key != NULL) {
if(debug) if (debug)
pcp_dumpkey(key); pcp_dumpkey(key);
vault->unsafed = 1; /* will be safed automatically */ vault->unsafed = 1; /* will be safed automatically */
fprintf(stderr, "Key %s changed.\n", key->id); fprintf(stderr, "Key %s changed.\n", key->id);
} }
} }
} } else {
else {
fatal(ptx, "No key with id 0x%s found!\n", keyid); fatal(ptx, "No key with id 0x%s found!\n", keyid);
} }
} }
char *pcp_find_id_byrec(char *recipient) { char *pcp_find_id_byrec(char *recipient) {
pcp_pubkey_t *p; pcp_pubkey_t *p;
char *id = NULL; char *id = NULL;
_lc(recipient); _lc(recipient);
pcphash_iteratepub(ptx, p) { pcphash_iteratepub(ptx, p) {
if(strncmp(p->owner, recipient, 255) == 0) { if (strncmp(p->owner, recipient, 255) == 0) {
id = ucmalloc(17); id = ucmalloc(17);
strncpy(id, p->id, 17); strncpy(id, p->id, 17);
break; break;
} }
if(strncmp(p->mail, recipient, 255) == 0) { if (strncmp(p->mail, recipient, 255) == 0) {
id = ucmalloc(17); id = ucmalloc(17);
strncpy(id, p->id, 17); strncpy(id, p->id, 17);
break; break;
@@ -525,8 +516,7 @@ char *pcp_find_id_byrec(char *recipient) {
return id; return id;
} }
int pcp_import(vault_t *vault, FILE *in, char *passwd) {
int pcp_import (vault_t *vault, FILE *in, char *passwd) {
byte *buf = ucmalloc(PCP_BLOCK_SIZE); byte *buf = ucmalloc(PCP_BLOCK_SIZE);
size_t bufsize; size_t bufsize;
pcp_pubkey_t *pub = NULL; pcp_pubkey_t *pub = NULL;
@@ -540,97 +530,95 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
bufsize = ps_read(pin, buf, PCP_BLOCK_SIZE); bufsize = ps_read(pin, buf, PCP_BLOCK_SIZE);
if(bufsize == 0) { if (bufsize == 0) {
fatal(ptx, "Input file is empty!\n"); fatal(ptx, "Input file is empty!\n");
goto errimp1; goto errimp1;
} }
/* first try as rfc pub key */ /* first try as rfc pub key */
bundle = pcp_import_binpub(ptx, buf, bufsize); bundle = pcp_import_binpub(ptx, buf, bufsize);
if(bundle != NULL) { if (bundle != NULL) {
keysig = bundle->s; keysig = bundle->s;
pub = bundle->p; pub = bundle->p;
if(debug) if (debug)
pcp_dumppubkey(pub); pcp_dumppubkey(pub);
if(keysig == NULL) { if (keysig == NULL) {
fatals_ifany(ptx); fatals_ifany(ptx);
char *yes = pcp_getstdin("WARNING: signature doesn't verify, import anyway [yes|NO]?"); char *yes = pcp_getstdin(
if(strncmp(yes, "yes", 1024) != 0) { "WARNING: signature doesn't verify, import anyway [yes|NO]?");
if (strncmp(yes, "yes", 1024) != 0) {
free(yes); free(yes);
goto errimp2; goto errimp2;
} }
free(yes); free(yes);
} }
if(pcp_sanitycheck_pub(ptx, pub) == 0) { if (pcp_sanitycheck_pub(ptx, pub) == 0) {
if(pcpvault_addkey(ptx, vault, (void *)pub, PCP_KEY_TYPE_PUBLIC) == 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); fprintf(stderr, "key 0x%s added to %s.\n", pub->id, vault->filename);
/* avoid double free */ /* avoid double free */
success = 0; success = 0;
} } else
else
goto errimp2; goto errimp2;
if(keysig != NULL) { if (keysig != NULL) {
if(pcpvault_addkey(ptx, vault, keysig, keysig->type) != 0) { if (pcpvault_addkey(ptx, vault, keysig, keysig->type) != 0) {
/* FIXME: remove pubkey if storing the keysig failed */ /* FIXME: remove pubkey if storing the keysig failed */
goto errimp2; goto errimp2;
} }
} }
} } else
else
goto errimp2; goto errimp2;
} } else {
else {
/* it's not public key, so let's try to interpret it as secret key */ /* it's not public key, so let's try to interpret it as secret key */
if(ptx->verbose) if (ptx->verbose)
fatals_ifany(ptx); fatals_ifany(ptx);
if(passwd != NULL) { if (passwd != NULL) {
sk = pcp_import_secret(ptx, buf, bufsize, passwd); sk = pcp_import_secret(ptx, buf, bufsize, passwd);
} } else {
else {
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt the secret key file", NULL, 1, NULL); "Enter passphrase to decrypt the secret key file", NULL, 1,
NULL);
sk = pcp_import_secret(ptx, buf, bufsize, passphrase); sk = pcp_import_secret(ptx, buf, bufsize, passphrase);
sfree(passphrase); sfree(passphrase);
} }
if(sk == NULL) { if (sk == NULL) {
goto errimp2; goto errimp2;
} }
if(debug) if (debug)
pcp_dumpkey(sk); pcp_dumpkey(sk);
pcp_key_t *maybe = pcphash_keyexists(ptx, sk->id); pcp_key_t *maybe = pcphash_keyexists(ptx, sk->id);
if(maybe != NULL) { if (maybe != NULL) {
fatal(ptx, "Secretkey sanity check: there already exists a key with the id 0x%s\n", sk->id); fatal(ptx,
"Secretkey sanity check: there already exists a key with the id "
"0x%s\n",
sk->id);
goto errimp2; goto errimp2;
} }
/* store it */ /* store it */
if(passwd != NULL) { if (passwd != NULL) {
sk = pcpkey_encrypt(ptx, sk, passwd); sk = pcpkey_encrypt(ptx, sk, passwd);
} } else {
else {
char *passphrase; char *passphrase;
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase, "Enter passphrase for key encryption",
"Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL); "Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) { if (strnlen(passphrase, 1024) > 0) {
/* encrypt the key */ /* encrypt the key */
sk = pcpkey_encrypt(ptx, sk, passphrase); sk = pcpkey_encrypt(ptx, sk, passphrase);
sfree(passphrase); sfree(passphrase);
} } else {
else {
/* ask for confirmation if we shall store it in the clear */ /* ask for confirmation if we shall store it in the clear */
char *yes = pcp_getstdin( char *yes = pcp_getstdin("WARNING: secret key will be stored "
"WARNING: secret key will be stored unencrypted. Are you sure [yes|NO]?"); "unencrypted. Are you sure [yes|NO]?");
if(strncmp(yes, "yes", 1024) != 0) { if (strncmp(yes, "yes", 1024) != 0) {
free(yes); free(yes);
goto errimp1; goto errimp1;
} }
@@ -638,10 +626,10 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
} }
} }
if(sk != NULL) { if (sk != NULL) {
/* store it to the vault if we got it til here */ /* store it to the vault if we got it til here */
if(pcp_sanitycheck_key(ptx, sk) == 0) { if (pcp_sanitycheck_key(ptx, sk) == 0) {
if(pcp_storekey(sk) == 0) { if (pcp_storekey(sk) == 0) {
pcpkey_printshortinfo(sk); pcpkey_printshortinfo(sk);
success = 0; success = 0;
} }
@@ -649,28 +637,27 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
} }
} }
errimp2: errimp2:
if(keysig != NULL) { if (keysig != NULL) {
ucfree(keysig->blob, keysig->size); ucfree(keysig->blob, keysig->size);
ucfree(keysig, sizeof(pcp_keysig_t)); ucfree(keysig, sizeof(pcp_keysig_t));
} }
if(bundle != NULL) { if (bundle != NULL) {
free(bundle); free(bundle);
} }
if(pub != NULL) { if (pub != NULL) {
ucfree(pub, sizeof(pcp_pubkey_t)); ucfree(pub, sizeof(pcp_pubkey_t));
} }
if(sk != NULL) { if (sk != NULL) {
ucfree(sk, sizeof(pcp_key_t)); ucfree(sk, sizeof(pcp_key_t));
} }
ucfree(buf, bufsize); ucfree(buf, bufsize);
errimp1: errimp1:
ps_close(pin); ps_close(pin);
return success; return success;

View File

@@ -19,44 +19,44 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#ifndef _HAVE_KEYMGMT_H #ifndef _HAVE_KEYMGMT_H
#define _HAVE_KEYMGMT_H #define _HAVE_KEYMGMT_H
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <wctype.h> #include <wctype.h>
#include "randomart.h"
#include "key.h"
#include "pcp.h"
#include "vault.h"
#include "defines.h"
#include "readpass.h"
#include "keyprint.h"
#include "keyhash.h"
#include "util.h"
#include "buffer.h" #include "buffer.h"
#include "mgmt.h"
#include "context.h" #include "context.h"
#include "defines.h"
#include "key.h"
#include "keyhash.h"
#include "keyprint.h"
#include "mgmt.h"
#include "randomart.h"
#include "readpass.h"
#include "util.h"
#include "vault.h"
#define _WITH_GETLINE #define _WITH_GETLINE
char *pcp_getstdin(const char *prompt); char *pcp_getstdin(const char *prompt);
int pcp_storekey (pcp_key_t *key); int pcp_storekey(pcp_key_t *key);
void pcp_keygen(char *passwd); void pcp_keygen(char *passwd);
void pcp_listkeys(); void pcp_listkeys();
void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *passwd); void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor,
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor); char *passwd);
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format,
int armor);
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd); pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd);
char *pcp_normalize_id(char *keyid); char *pcp_normalize_id(char *keyid);
pcp_key_t *pcp_find_primary_secret(); pcp_key_t *pcp_find_primary_secret();
int pcp_import (vault_t *vault, FILE *in, char *passwd); int pcp_import(vault_t *vault, FILE *in, char *passwd);
void pcpdelete_key(char *keyid); void pcpdelete_key(char *keyid);
char *pcp_find_id_byrec(char *recipient); char *pcp_find_id_byrec(char *recipient);

View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -109,6 +109,7 @@ void pcptext_key(char *keyid) {
} }
void pcptext_vault(vault_t *vault) { void pcptext_vault(vault_t *vault) {
if(vault != NULL) {
#ifdef HAVE_JSON #ifdef HAVE_JSON
if(ptx->json) { if(ptx->json) {
@@ -117,13 +118,13 @@ void pcptext_vault(vault_t *vault) {
pcp_key_t *k; pcp_key_t *k;
pcp_pubkey_t *p; pcp_pubkey_t *p;
checksum = _bin2hex(vault->checksum, 32); checksum = _bin2hex(vault->checksum, LSHA);
jout = json_pack("{sssisssisi}", jout = json_pack("{sssisssisi}",
"keyvaultfile", vault->filename, "keyvaultfile" , vault->filename,
"version", vault->version, "version" , vault->version,
"checksum", checksum, "checksum" , checksum,
"secretkeys", pcphash_count(ptx), "secretkeys" , pcphash_count(ptx),
"publickey", pcphash_countpub(ptx)); "publickey" , pcphash_countpub(ptx));
jkeys = json_array(); jkeys = json_array();
@@ -167,6 +168,7 @@ void pcptext_vault(vault_t *vault) {
#ifdef HAVE_JSON #ifdef HAVE_JSON
} }
#endif #endif
}
} }
void pcpkey_printlineinfo(pcp_key_t *key) { void pcpkey_printlineinfo(pcp_key_t *key) {
@@ -184,7 +186,7 @@ void pcpkey_printlineinfo(pcp_key_t *key) {
printf(" "); printf(" ");
byte *hash = pcpkey_getchecksum(key); byte *hash = pcpkey_getchecksum(key);
int i, y; int i, y;
for(i=0; i<32; i+=4) { for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) { for(y=0; y<4; y++) {
printf("%02x", hash[i+y]); printf("%02x", hash[i+y]);
} }
@@ -213,7 +215,7 @@ void pcppubkey_printlineinfo(pcp_pubkey_t *key) {
printf(" "); printf(" ");
byte *hash = pcppubkey_getchecksum(key); byte *hash = pcppubkey_getchecksum(key);
int i, y; int i, y;
for(i=0; i<32; i+=4) { for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) { for(y=0; y<4; y++) {
printf("%02x", hash[i+y]); printf("%02x", hash[i+y]);
} }
@@ -227,7 +229,7 @@ void pcppubkey_printlineinfo(pcp_pubkey_t *key) {
if(sig != NULL) { if(sig != NULL) {
printf("signature fingerprint:\n "); printf("signature fingerprint:\n ");
byte *checksum = sig->checksum; byte *checksum = sig->checksum;
for(i=0; i<32; i+=4) { for(i=0; i<LSHA; i+=4) {
for(y=0; y<4; y++) { for(y=0; y<4; y++) {
printf("%02x", checksum[i+y]); printf("%02x", checksum[i+y]);
} }
@@ -274,7 +276,7 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
fprintf(out, " Mail: %s\n", key->mail); fprintf(out, " Mail: %s\n", key->mail);
fprintf(out, " Key-ID: 0x%s\n", key->id); 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. */ /* 2004-06-14T23:34:30. */
fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n", fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n",

376
src/pcp.c
View File

@@ -1,7 +1,7 @@
/* /*
This file is part of Pretty Curved Privacy (pcp1). 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 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 it under the terms of the GNU General Public License as published by
@@ -19,43 +19,45 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#include "pcp.h" #include "pcp.h"
#include "defines.h" #include "defines.h"
vault_t *vault;
PCPCTX *ptx;
int debug;
void usage(int error) { void usage(int error) {
fprintf(stderr, PCP_HELP_INTRO); fprintf(stderr, PCP_HELP_INTRO);
if(error == 0) if (error == 0)
fprintf(stderr, PCP_HELP); fprintf(stderr, PCP_HELP);
version(); version();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void version() { void version() {
fprintf(stderr, "pcp version %d.%d.%d, use --help to learn how to use.\n", 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); exit(0);
} }
char *default_vault() { char *default_vault() {
char *path = ucmalloc(1024);; char *path = ucmalloc(1024);
;
snprintf(path, 1024, "%s/.pcpvault", getenv("HOME")); snprintf(path, 1024, "%s/.pcpvault", getenv("HOME"));
return path; return path;
} }
char *altin(char *infile, int stdinused) { char *altin(char *infile, int stdinused) {
if(infile == NULL && stdinused == 1) { if (infile == NULL && stdinused == 1) {
fprintf(stderr, "Error: cannot use <stdin> because -X had precedence!\n"); fprintf(stderr, "Error: cannot use <stdin> because -X had precedence!\n");
exit(1); exit(1);
} }
return infile; return infile;
} }
int main (int argc, char **argv) { int main(int argc, char **argv) {
int opt, mode, usevault, useid, userec, lo, armor, detach, \ int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt,
signcrypt, exportformat, anon, xpf; exportformat, anon, xpf;
char *vaultfile = default_vault(); char *vaultfile = default_vault();
char *outfile = NULL; char *outfile = NULL;
char *infile = NULL; char *infile = NULL;
@@ -66,6 +68,7 @@ int main (int argc, char **argv) {
char *xpassfile = NULL; char *xpassfile = NULL;
char *extra = NULL; char *extra = NULL;
plist_t *recipient = NULL; plist_t *recipient = NULL;
char *askpass = NULL;
FILE *in; FILE *in;
errno = 0; errno = 0;
@@ -86,62 +89,64 @@ int main (int argc, char **argv) {
static struct option longopts[] = { static struct option longopts[] = {
/* generics */ /* generics */
{ "vault", required_argument, NULL, 'V' }, {"vault", required_argument, NULL, 'V'},
{ "outfile", required_argument, NULL, 'O' }, {"outfile", required_argument, NULL, 'O'},
{ "infile", required_argument, NULL, 'I' }, {"infile", required_argument, NULL, 'I'},
{ "keyid", required_argument, NULL, 'i' }, {"keyid", required_argument, NULL, 'i'},
{ "text", required_argument, NULL, 't' }, {"text", required_argument, NULL, 't'},
{ "xpass", required_argument, NULL, 'x' }, {"xpass", required_argument, NULL, 'x'},
{ "password-file", required_argument, NULL, 'X' }, {"password-file", required_argument, NULL, 'X'},
{ "recipient", required_argument, NULL, 'r' }, {"extpass", required_argument, NULL, LONG_EXTPASS},
{"recipient", required_argument, NULL, 'r'},
/* key management */ /* key management */
{ "keygen", no_argument, NULL, 'k' }, {"keygen", no_argument, NULL, 'k'},
{ "listkeys", no_argument, NULL, 'l' }, {"listkeys", no_argument, NULL, 'l'},
{ "listkeys-verbose",no_argument, NULL, 'L' }, /* alias for -l -v */ {"listkeys-verbose", no_argument, NULL, 'L'}, /* alias for -l -v */
{ "export-secret", no_argument, NULL, 's' }, {"export-secret", no_argument, NULL, 's'},
{ "export-public", no_argument, NULL, 'p' }, {"export-public", no_argument, NULL, 'p'},
{ "export", no_argument, NULL, 'p' }, /* alias -p */ {"export", no_argument, NULL, 'p'}, /* alias -p */
{ "import", no_argument, NULL, 'K' }, /* alias -P */ {"import", no_argument, NULL, 'K'}, /* alias -P */
{ "import-key", no_argument, NULL, 'K' }, /* alias -K */ {"import-key", no_argument, NULL, 'K'}, /* alias -K */
{ "remove-key", no_argument, NULL, 'R' }, {"remove-key", no_argument, NULL, 'R'},
{ "edit-key", no_argument, NULL, 'E' }, {"edit-key", no_argument, NULL, 'E'},
{ "export-format", required_argument, NULL, 'F' }, {"export-format", required_argument, NULL, 'F'},
/* crypto */ /* crypto */
{ "encrypt", no_argument, NULL, 'e' }, {"encrypt", no_argument, NULL, 'e'},
{ "encrypt-sym", no_argument, NULL, 'm' }, {"encrypt-sym", no_argument, NULL, 'm'},
{ "decrypt", no_argument, NULL, 'd' }, {"decrypt", no_argument, NULL, 'd'},
{ "anonymous", no_argument, NULL, 'A' }, {"anonymous", no_argument, NULL, 'A'},
{ "add-myself", no_argument, NULL, 'M' }, {"add-myself", no_argument, NULL, 'M'},
{ "checksum", optional_argument, NULL, 'C' }, {"checksum", no_argument, NULL, 'C'},
/* encoding */ /* encoding */
{ "z85-encode", no_argument, NULL, 'z' }, {"z85-encode", no_argument, NULL, 'z'},
{ "armor", no_argument, NULL, 'a' }, /* alias -z */ {"armor", no_argument, NULL, 'a'}, /* alias -z */
{ "textmode", no_argument, NULL, 'a' }, /* alias -z */ {"textmode", no_argument, NULL, 'a'}, /* alias -z */
{ "z85-decode", no_argument, NULL, 'Z' }, {"z85-decode", no_argument, NULL, 'Z'},
{ "json-io", no_argument, NULL, 'j' }, {"json-io", no_argument, NULL, 'j'},
/* globals */ /* globals */
{ "help", no_argument, NULL, 'h' }, {"help", no_argument, NULL, 'h'},
{ "version", no_argument, NULL, '0' }, /* no short opt, FIXME: how to avoid? */ {"version", no_argument, NULL,
{ "verbose", no_argument, NULL, 'v' }, '0'}, /* no short opt, FIXME: how to avoid? */
{ "debug", no_argument, NULL, 'D' }, {"verbose", no_argument, NULL, 'v'},
{"debug", no_argument, NULL, 'D'},
/* signing */ /* signing */
{ "sign", no_argument, NULL, 'g' }, {"sign", no_argument, NULL, 'g'},
{ "check-signature", no_argument, NULL, 'c' }, {"check-signature", no_argument, NULL, 'c'},
{ "sigfile", required_argument, NULL, 'f' }, {"sigfile", required_argument, NULL, 'f'},
{ NULL, 0, NULL, 0 } {NULL, 0, NULL, 0}};
};
while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcmf:b1F:0KAMX:jC:", while ((opt = getopt_long(argc, argv,
"klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcmf:b1F:0KAMX:jC",
longopts, NULL)) != -1) { longopts, NULL)) != -1) {
switch (opt) { switch (opt) {
case 0: case 0:
switch(lo) { switch (lo) {
case 's': case 's':
printf("sign\n"); printf("sign\n");
break; break;
@@ -205,14 +210,13 @@ int main (int argc, char **argv) {
anon = 1; anon = 1;
break; break;
case 'F': case 'F':
if(strncmp(optarg, "pbp", 3) == 0) { if (strncmp(optarg, "pbp", 3) == 0) {
exportformat = EXP_FORMAT_PBP; exportformat = EXP_FORMAT_PBP;
} } else if (strncmp(optarg, "pcp", 3) == 0) {
else if(strncmp(optarg, "pcp", 3) == 0) {
exportformat = EXP_FORMAT_NATIVE; exportformat = EXP_FORMAT_NATIVE;
} } else {
else { fprintf(stderr,
warn("Unknown export format specified, using native\n"); "WARN: Unknown export format specified, using native\n");
exportformat = EXP_FORMAT_NATIVE; exportformat = EXP_FORMAT_NATIVE;
} }
break; break;
@@ -220,7 +224,8 @@ int main (int argc, char **argv) {
#ifdef HAVE_JSON #ifdef HAVE_JSON
ptx->json = 1; ptx->json = 1;
#else #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 #endif
break; break;
case 'g': case 'g':
@@ -233,14 +238,10 @@ int main (int argc, char **argv) {
break; break;
case 'C': case 'C':
mode += PCP_MODE_CHECKSUM; mode += PCP_MODE_CHECKSUM;
if(strlen(optarg) > 0 && strncmp(optarg, "--", 3) > 0) {
xpass = smalloc(strlen(optarg)+1);
strncpy(xpass, optarg, strlen(optarg)+1);
}
break; break;
case 'f': case 'f':
sigfile = ucmalloc(strlen(optarg)+1); sigfile = ucmalloc(strlen(optarg) + 1);
strncpy(sigfile, optarg, strlen(optarg)+1); strncpy(sigfile, optarg, strlen(optarg) + 1);
detach = 1; detach = 1;
break; break;
@@ -248,20 +249,20 @@ int main (int argc, char **argv) {
strncpy(vaultfile, optarg, 1024); strncpy(vaultfile, optarg, 1024);
break; break;
case 'O': case 'O':
if(strncmp(optarg, "-", 2) > 0) { if (strncmp(optarg, "-", 2) > 0) {
outfile = ucmalloc(strlen(optarg)+1); outfile = ucmalloc(strlen(optarg) + 1);
strncpy(outfile, optarg, strlen(optarg)+1); strncpy(outfile, optarg, strlen(optarg) + 1);
} }
break; break;
case 'I': case 'I':
if(strncmp(optarg, "-", 2) > 0) { if (strncmp(optarg, "-", 2) > 0) {
infile = ucmalloc(strlen(optarg)+1); infile = ucmalloc(strlen(optarg) + 1);
strncpy(infile, optarg, strlen(optarg)+1); strncpy(infile, optarg, strlen(optarg) + 1);
} }
break; break;
case 'X': case 'X':
xpassfile = ucmalloc(strlen(optarg)+1); xpassfile = ucmalloc(strlen(optarg) + 1);
strncpy(xpassfile, optarg, strlen(optarg)+1); strncpy(xpassfile, optarg, strlen(optarg) + 1);
xpf = 1; xpf = 1;
break; break;
case 'i': case 'i':
@@ -270,10 +271,12 @@ int main (int argc, char **argv) {
useid = 1; useid = 1;
break; break;
case 'x': case 'x':
xpass = smalloc(strlen(optarg)+1); xpass = smalloc(strlen(optarg) + 1);
strncpy(xpass, optarg, strlen(optarg)+1); strncpy(xpass, optarg, strlen(optarg) + 1);
if(strncmp(xpass, "n/a", 3) == 0) break;
xpass[0] = '\0'; case LONG_EXTPASS:
askpass = malloc(strlen(optarg) + 1);
strncpy(askpass, optarg, strlen(optarg) + 1);
break; break;
case 'r': case 'r':
p_add(&recipient, optarg); p_add(&recipient, optarg);
@@ -283,7 +286,6 @@ int main (int argc, char **argv) {
p_add_me(&recipient); p_add_me(&recipient);
userec = 1; userec = 1;
break; break;
case 'D': case 'D':
debug = 1; debug = 1;
break; break;
@@ -302,77 +304,72 @@ int main (int argc, char **argv) {
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if(mode == 0) { if (mode == 0) {
/* turn -z|-Z into a mode if there's nothing else specified */ /* turn -z|-Z into a mode if there's nothing else specified */
if(armor == 1) { if (armor == 1) {
mode = PCP_MODE_ZENCODE; mode = PCP_MODE_ZENCODE;
} } else if (armor == 2) {
else if(armor == 2) {
mode = PCP_MODE_ZDECODE; mode = PCP_MODE_ZDECODE;
} } else {
else {
version(); version();
return 1; return 1;
} }
} }
if(mode == PCP_MODE_ENCRYPT + PCP_MODE_SIGN) { if (mode == PCP_MODE_ENCRYPT + PCP_MODE_SIGN) {
mode = PCP_MODE_ENCRYPT; mode = PCP_MODE_ENCRYPT;
signcrypt = 1; signcrypt = 1;
} }
if(mode == PCP_MODE_DECRYPT + PCP_MODE_VERIFY) { if (mode == PCP_MODE_DECRYPT + PCP_MODE_VERIFY) {
mode = PCP_MODE_DECRYPT; mode = PCP_MODE_DECRYPT;
signcrypt = 1; signcrypt = 1;
} }
sodium_init(); /* FIXME: better called from the lib? */
#ifndef DEBUG #ifndef DEBUG
# ifdef HAVE_SETRLIMIT #ifdef HAVE_SETRLIMIT
setrlimit(RLIMIT_CORE, &(struct rlimit) {0, 0}); setrlimit(RLIMIT_CORE, &(struct rlimit){0, 0});
# endif #endif
#endif #endif
errno = 0; /* FIXME: workaround for https://github.com/jedisct1/libsodium/issues/114 */ errno = 0; /* FIXME: workaround for
https://github.com/jedisct1/libsodium/issues/114 */
if(mode == PCP_MODE_ENCRYPT && useid == 0 && userec == 0) { if (mode == PCP_MODE_ENCRYPT && useid == 0 && userec == 0) {
usevault = 0; usevault = 0;
mode = PCP_MODE_ENCRYPT_ME; mode = PCP_MODE_ENCRYPT_ME;
} }
if(argc >= 1) { if (argc >= 1) {
/* ok, there are arguments left on the commandline. /* ok, there are arguments left on the commandline.
treat it as filename or recipient, depending on treat it as filename or recipient, depending on
current mode and other given parameters */ current mode and other given parameters */
extra = ucmalloc(strlen(argv[0])+1); extra = ucmalloc(strlen(argv[0]) + 1);
strncpy(extra, argv[0], strlen(argv[0])+1); strncpy(extra, argv[0], strlen(argv[0]) + 1);
int useex = 0; int useex = 0;
switch (mode) { switch (mode) {
case PCP_MODE_DECRYPT: case PCP_MODE_DECRYPT:
if(infile == NULL) { if (infile == NULL) {
infile = extra; infile = extra;
useex = 1; useex = 1;
} }
break; break;
case PCP_MODE_ENCRYPT: case PCP_MODE_ENCRYPT:
if(infile == NULL) { if (infile == NULL) {
infile = extra; infile = extra;
useex = 1; useex = 1;
} } else if (userec == 0 && useid == 0) {
else if(userec == 0 && useid == 0) {
userec = 1; userec = 1;
int i; int i;
for (i=0; i<argc; i++) { for (i = 0; i < argc; i++) {
p_add(&recipient, argv[i]); p_add(&recipient, argv[i]);
} }
} }
break; break;
case PCP_MODE_IMPORT: case PCP_MODE_IMPORT:
if(infile == NULL) { if (infile == NULL) {
infile = extra; infile = extra;
useex = 1; useex = 1;
} }
@@ -380,11 +377,10 @@ int main (int argc, char **argv) {
case PCP_MODE_EXPORT_SECRET: case PCP_MODE_EXPORT_SECRET:
case PCP_MODE_EXPORT_PUBLIC: case PCP_MODE_EXPORT_PUBLIC:
if(outfile == NULL) { if (outfile == NULL) {
outfile = extra; outfile = extra;
useex = 1; useex = 1;
} } else if (useid == 0 && userec == 0) {
else if(useid == 0 && userec == 0) {
p_add(&recipient, extra); p_add(&recipient, extra);
useex = 1; useex = 1;
userec = 1; userec = 1;
@@ -392,11 +388,10 @@ int main (int argc, char **argv) {
break; break;
case PCP_MODE_VERIFY: case PCP_MODE_VERIFY:
if(infile == NULL) { if (infile == NULL) {
infile = extra; infile = extra;
useex = 1; useex = 1;
} } else if (useid == 0) {
else if (useid == 0) {
id = extra; id = extra;
useid = 1; useid = 1;
useex = 1; useex = 1;
@@ -404,52 +399,58 @@ int main (int argc, char **argv) {
break; break;
case PCP_MODE_SIGN: case PCP_MODE_SIGN:
if(infile == NULL) { if (infile == NULL) {
infile = extra; infile = extra;
useex = 1; useex = 1;
} } else if (outfile == NULL && detach == 0) {
else if(outfile == NULL && detach == 0) {
outfile = extra; outfile = extra;
useex = 1; useex = 1;
} }
break; break;
} }
if(useex)
if (!useex)
free(extra); free(extra);
} }
if(xpassfile != NULL) { if (xpassfile != NULL) {
pcp_readpass(&xpass, "passphrase", NULL, 0, xpassfile); if (pcp_readpass(ptx, &xpass, "passphrase", NULL, 0, xpassfile) != 0)
if(xpassfile[0] != '-') goto perr1;
if (xpassfile[0] != '-')
xpf = 0; xpf = 0;
free(xpassfile); free(xpassfile);
} }
if (askpass != NULL) {
if (pcp_readpass_fromprog(ptx, &xpass, askpass) != 0)
goto perr1;
}
/* check if there's some enviroment we could use */ /* check if there's some enviroment we could use */
if(usevault == 1) { if (usevault == 1) {
char *_vaultfile = getenv("PCP_VAULT"); char *_vaultfile = getenv("PCP_VAULT");
if(_vaultfile != NULL) { if (_vaultfile != NULL) {
strncpy(vaultfile, _vaultfile, strlen(_vaultfile)+1); strncpy(vaultfile, _vaultfile, strlen(_vaultfile) + 1);
} }
} }
if(debug == 0) { if (debug == 0) {
char *_debug = getenv("PCP_DEBUG"); char *_debug = getenv("PCP_DEBUG");
if(_debug != NULL) { if (_debug != NULL) {
debug = 1; debug = 1;
} }
} }
if(usevault == 1) { if (usevault == 1) {
vault = pcpvault_init(ptx, vaultfile); vault = pcpvault_init(ptx, vaultfile);
/* special case: ignore vault error in decrypt mode. sym decrypt doesn't /* special case: ignore vault error in decrypt mode. sym decrypt doesn't
need it and asym will just fail without keys. */ need it and asym will just fail without keys. */
if(vault == NULL && mode == PCP_MODE_DECRYPT) { if (vault == NULL && mode == PCP_MODE_DECRYPT) {
/* use an empty one */ /* use an empty one */
vault = pcpvault_init(ptx, "/dev/null"); vault = pcpvault_init(ptx, "/dev/null");
fatals_reset(ptx); fatals_reset(ptx);
} }
if(vault != NULL) { if (vault != NULL) {
switch (mode) { switch (mode) {
case PCP_MODE_KEYGEN: case PCP_MODE_KEYGEN:
pcp_keygen(xpass); pcp_keygen(xpass);
@@ -460,33 +461,31 @@ int main (int argc, char **argv) {
break; break;
case PCP_MODE_EXPORT_SECRET: case PCP_MODE_EXPORT_SECRET:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcp_exportsecret(id, useid, outfile, armor, xpass); pcp_exportsecret(id, useid, outfile, armor, xpass);
} }
} } else {
else {
pcp_exportsecret(NULL, useid, outfile, armor, xpass); pcp_exportsecret(NULL, useid, outfile, armor, xpass);
} }
break; break;
case PCP_MODE_EXPORT_PUBLIC: case PCP_MODE_EXPORT_PUBLIC:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id == NULL) if (id == NULL)
break; break;
} }
pcp_exportpublic(id, xpass, outfile, exportformat, armor); pcp_exportpublic(id, xpass, outfile, exportformat, armor);
break; break;
case PCP_MODE_IMPORT: case PCP_MODE_IMPORT:
if(infile == NULL) { if (infile == NULL) {
altin(NULL, xpf); altin(NULL, xpf);
in = stdin; in = stdin;
} } else {
else { if ((in = fopen(infile, "rb")) == NULL) {
if((in = fopen(infile, "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", infile); fatal(ptx, "Could not open input file %s\n", infile);
break; break;
} }
@@ -495,77 +494,76 @@ int main (int argc, char **argv) {
break; break;
case PCP_MODE_DELETE_KEY: case PCP_MODE_DELETE_KEY:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcpdelete_key(id); pcpdelete_key(id);
} }
} } else {
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n"); fatal(ptx, "You need to specify a key id (--keyid)!\n");
} }
break; break;
case PCP_MODE_EDIT: case PCP_MODE_EDIT:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcpedit_key(id); pcpedit_key(id);
} }
} } else {
else {
fatal(ptx, "You need to specify a key id (--keyid)!\n"); fatal(ptx, "You need to specify a key id (--keyid)!\n");
} }
break; break;
case PCP_MODE_ENCRYPT: case PCP_MODE_ENCRYPT:
if(useid == 1 && userec == 0) { if (useid == 1 && userec == 0) {
/* one dst, FIXME: make id a list as well */ /* one dst, FIXME: make id a list as well */
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
pcpencrypt(id, altin(infile, xpf), outfile, xpass, NULL, signcrypt, armor, anon); pcpencrypt(id, altin(infile, xpf), outfile, xpass, NULL, signcrypt,
} armor, anon);
else if(useid == 0 && userec == 1) { } else if (useid == 0 && userec == 1) {
/* multiple dst */ /* multiple dst */
pcpencrypt(NULL, altin(infile, xpf), outfile, xpass, recipient, signcrypt, armor, anon); pcpencrypt(NULL, altin(infile, xpf), outfile, xpass, recipient,
} signcrypt, armor, anon);
else { } else {
/* -i and -r specified */ /* -i and -r specified */
fatal(ptx, "You can't specify both -i and -r, use either -i or -r!\n"); fatal(ptx,
"You can't specify both -i and -r, use either -i or -r!\n");
} }
break; break;
case PCP_MODE_DECRYPT: case PCP_MODE_DECRYPT:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcpdecrypt(id, useid, altin(infile, xpf), outfile, xpass, signcrypt); pcpdecrypt(id, useid, altin(infile, xpf), outfile, xpass,
signcrypt);
} }
} } else {
else { pcpdecrypt(NULL, useid, altin(infile, xpf), outfile, xpass,
pcpdecrypt(NULL, useid, altin(infile, xpf), outfile, xpass, signcrypt); signcrypt);
} }
break; break;
case PCP_MODE_SIGN: case PCP_MODE_SIGN:
if(detach) { if (detach) {
if(outfile != NULL && sigfile != NULL) 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"); fatal(ptx, "You can't both specify -O and -f, use -O for std "
"signatures and -f for detached ones\n");
else else
pcpsign(altin(infile, xpf), sigfile, xpass, armor, detach); pcpsign(altin(infile, xpf), sigfile, xpass, armor, detach);
} } else
else
pcpsign(altin(infile, xpf), outfile, xpass, armor, detach); pcpsign(altin(infile, xpf), outfile, xpass, armor, detach);
break; break;
case PCP_MODE_VERIFY: case PCP_MODE_VERIFY:
if(useid) { if (useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcpverify(altin(infile, xpf), sigfile, id, detach); pcpverify(altin(infile, xpf), sigfile, id, detach);
} }
} } else {
else {
pcpverify(altin(infile, xpf), sigfile, NULL, detach); pcpverify(altin(infile, xpf), sigfile, NULL, detach);
} }
break; break;
@@ -577,8 +575,7 @@ int main (int argc, char **argv) {
} }
pcpvault_close(ptx, vault); pcpvault_close(ptx, vault);
} }
} } else {
else {
ELSEMODE: ELSEMODE:
switch (mode) { switch (mode) {
case PCP_MODE_ZENCODE: case PCP_MODE_ZENCODE:
@@ -594,17 +591,15 @@ int main (int argc, char **argv) {
break; break;
case PCP_MODE_TEXT: case PCP_MODE_TEXT:
if(infile != NULL) { if (infile != NULL) {
pcptext_infile(infile); pcptext_infile(infile);
} } else {
else {
vault = pcpvault_init(ptx, vaultfile); vault = pcpvault_init(ptx, vaultfile);
if(! useid && infile == NULL) { if (!useid && infile == NULL) {
pcptext_vault(vault); pcptext_vault(vault);
} } else {
else {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if (id != NULL) {
pcptext_key(id); pcptext_key(id);
} }
} }
@@ -612,17 +607,15 @@ int main (int argc, char **argv) {
} }
break; break;
case PCP_MODE_CHECKSUM: case PCP_MODE_CHECKSUM:
if(infile == NULL) { if (infile == NULL) {
if(argc == 0) { if (argc == 0) {
char *list[1]; char *list[1];
list[0] = NULL; list[0] = NULL;
pcpchecksum(list, 1, xpass); pcpchecksum(list, 1, xpass);
} } else {
else {
pcpchecksum(argv, argc, xpass); pcpchecksum(argv, argc, xpass);
} }
} } else {
else {
char *list[1]; char *list[1];
list[0] = infile; list[0] = infile;
pcpchecksum(list, 1, xpass); pcpchecksum(list, 1, xpass);
@@ -631,30 +624,37 @@ int main (int argc, char **argv) {
default: default:
/* mode params mixed */ /* mode params mixed */
fatal(ptx, "Sorry, invalid combination of commandline parameters (0x%04X)!\n", mode); fatal(ptx,
"Sorry, invalid combination of commandline parameters (0x%04X)!\n",
mode);
break; break;
} }
} }
perr1:
fatals_ifany(ptx); fatals_ifany(ptx);
int e = ptx->pcp_exit; int e = ptx->pcp_exit;
ptx_clean(ptx); ptx_clean(ptx);
if(infile != NULL) if (infile != NULL)
free(infile); free(infile);
if(outfile != NULL) if (outfile != NULL)
free(outfile); free(outfile);
if(vaultfile != NULL) if (vaultfile != NULL)
free(vaultfile); free(vaultfile);
if(sigfile != NULL) if (sigfile != NULL)
free(sigfile); free(sigfile);
if(xpass != NULL) if (xpass != NULL)
sfree(xpass); sfree(xpass);
if(recipient != NULL) if (askpass != NULL)
free(askpass);
if (xpassfile != NULL)
free(xpassfile);
if (recipient != NULL)
p_clean(recipient); p_clean(recipient);
if(id != NULL) if (id != NULL)
free(id); free(id);
if(keyid != NULL) if (keyid != NULL)
free(keyid); free(keyid);
return e; return e;
} }

View File

@@ -19,42 +19,42 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#ifndef _HAVE_PCP_H #ifndef _HAVE_PCP_H
#define _HAVE_PCP_H #define _HAVE_PCP_H
#include <unistd.h> #include <compat_getopt.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <compat_getopt.h> #include <unistd.h>
#ifndef DEBUG #ifndef DEBUG
# ifdef HAVE_SETRLIMIT #ifdef HAVE_SETRLIMIT
# include <sys/types.h> #include <sys/resource.h>
# include <sys/time.h> #include <sys/time.h>
# include <sys/resource.h> #include <sys/types.h>
# endif #endif
#endif #endif
/* lib */ /* lib */
#include "mem.h"
#include "z85.h"
#include "zmq_z85.h"
#include "z85util.h"
#include "version.h"
#include "vault.h"
#include "context.h" #include "context.h"
#include "mem.h"
#include "vault.h"
#include "version.h"
#include "z85.h"
#include "z85util.h"
#include "zmq_z85.h"
/* subs */ /* subs */
#include "keymgmt.h"
#include "usage.h"
#include "encryption.h" #include "encryption.h"
#include "signature.h"
#include "keyhash.h" #include "keyhash.h"
#include "keymgmt.h"
#include "plist.h" #include "plist.h"
#include "signature.h"
#include "usage.h"
/* operation modi */ /* operation modi */
/* perl -e '$x=0; while ($x<100000) { $x++; $x *= 1.7; printf "0x%08X: %d\n", $x, $x }' */ /* perl -e '$x=0; while ($x<100000) { $x++; $x *= 1.7; printf "0x%08X: %d\n",
* $x, $x }' */
#define PCP_MODE_KEYGEN 0x00000001 #define PCP_MODE_KEYGEN 0x00000001
#define PCP_MODE_LISTKEYS 0x00000004 #define PCP_MODE_LISTKEYS 0x00000004
#define PCP_MODE_EXPORT_SECRET 0x00000009 #define PCP_MODE_EXPORT_SECRET 0x00000009
@@ -82,13 +82,16 @@
0x00028F70 0x00028F70
*/ */
#define PCP_HELP_INTRO "This is Pretty Curved Privacy. Licensed under the GPLv3. This is\n" \ #define PCP_HELP_INTRO \
"BETA software. Use with care. NOT intended for production use.\n" "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 */ /* some globals */
vault_t *vault; extern vault_t *vault;
PCPCTX *ptx; extern PCPCTX *ptx;
int debug; extern int debug;
void version(); void version();
void usage(); void usage();

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). 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 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 it under the terms of the GNU General Public License as published by
@@ -54,11 +54,9 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach) {
} }
} }
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase; char *passphrase;
if(passwd == NULL) { if(passwd == NULL) {
pcp_readpass(&passphrase, pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL); "Enter passphrase to decrypt your secret key", NULL, 1, NULL);
} }
else { else {
@@ -70,7 +68,6 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach) {
sfree(passphrase); sfree(passphrase);
if(secret == NULL) if(secret == NULL)
goto errs1; goto errs1;
}
Pcpstream *pin = ps_new_file(in); Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out); Pcpstream *pout = ps_new_file(out);

View File

@@ -16,7 +16,10 @@
"-V --vault <vaultfile> Specify an alternate vault file.\n" \ "-V --vault <vaultfile> Specify an alternate vault file.\n" \
"-O --outfile <file> Output file. STDOUT if unspecified.\n" \ "-O --outfile <file> Output file. STDOUT if unspecified.\n" \
"-I --infile <file> Input file. STDIN 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" \ "-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" \ "-i --keyid <id> Specify a key id for various operations.\n" \
"-r --recipient <string> Specify a recpipient, multiple allowed.\n" \ "-r --recipient <string> Specify a recpipient, multiple allowed.\n" \
"-t --text Print textual representation of ojects.\n" \ "-t --text Print textual representation of ojects.\n" \
@@ -51,7 +54,8 @@
"-a --armor --textmode same as -z\n" \ "-a --armor --textmode same as -z\n" \
"\n" \ "\n" \
"Misc Options:\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" \ "\n" \
"Arguments:\n" \ "Arguments:\n" \
"Extra arguments after options are treated as filenames or\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. -V --vault <vaultfile> Specify an alternate vault file.
-O --outfile <file> Output file. STDOUT if unspecified. -O --outfile <file> Output file. STDOUT if unspecified.
-I --infile <file> Input file. STDIN 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>. -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. -i --keyid <id> Specify a key id for various operations.
-r --recipient <string> Specify a recpipient, multiple allowed. -r --recipient <string> Specify a recpipient, multiple allowed.
-t --text Print textual representation of ojects. -t --text Print textual representation of ojects.
@@ -49,7 +52,8 @@ Encoding Options:
-a --armor --textmode same as -z -a --armor --textmode same as -z
Misc Options: 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: Arguments:
Extra arguments after options are treated as filenames or Extra arguments after options are treated as filenames or

View File

@@ -19,26 +19,25 @@
You can contact me by mail: <tlinden AT cpan DOT org>. You can contact me by mail: <tlinden AT cpan DOT org>.
*/ */
#include "z85util.h" #include "z85util.h"
int pcpz85_encode(char *infile, char *outfile) { int pcpz85_encode(char *infile, char *outfile) {
FILE *in; FILE *in;
FILE *out; FILE *out;
if(infile == NULL) if (infile == NULL)
in = stdin; in = stdin;
else { else {
if((in = fopen(infile, "rb")) == NULL) { if ((in = fopen(infile, "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", infile); fatal(ptx, "Could not open input file %s\n", infile);
goto errz1; goto errz1;
} }
} }
if(outfile == NULL) if (outfile == NULL)
out = stdout; out = stdout;
else { else {
if((out = fopen(outfile, "wb+")) == NULL) { if ((out = fopen(outfile, "wb+")) == NULL) {
fatal(ptx, "Could not open output file %s\n", outfile); fatal(ptx, "Could not open output file %s\n", outfile);
goto errz1; goto errz1;
} }
@@ -48,17 +47,17 @@ int pcpz85_encode(char *infile, char *outfile) {
size_t inputBufSize = 0; size_t inputBufSize = 0;
byte onebyte[1]; byte onebyte[1];
while(!feof(in)) { while (!feof(in)) {
if(!fread(&onebyte, 1, 1, in)) if (!fread(&onebyte, 1, 1, in))
break; break;
byte *tmp = realloc(input, inputBufSize + 1); byte *tmp = realloc(input, inputBufSize + 1);
input = tmp; input = tmp;
memmove(&input[inputBufSize], onebyte, 1); memmove(&input[inputBufSize], onebyte, 1);
inputBufSize ++; inputBufSize++;
} }
fclose(in); fclose(in);
if(inputBufSize == 0) { if (inputBufSize == 0) {
fatal(ptx, "Input file is empty!\n"); fatal(ptx, "Input file is empty!\n");
goto errz2; goto errz2;
} }
@@ -66,9 +65,9 @@ int pcpz85_encode(char *infile, char *outfile) {
size_t zlen; size_t zlen;
char *encoded = pcp_z85_encode(input, inputBufSize, &zlen, 1); char *encoded = pcp_z85_encode(input, inputBufSize, &zlen, 1);
if(encoded != NULL) { if (encoded != NULL) {
fprintf(out, "%s\n%s\n%s\n", PCP_ZFILE_HEADER, encoded, PCP_ZFILE_FOOTER); fprintf(out, "%s\n%s\n%s\n", PCP_ZFILE_HEADER, encoded, PCP_ZFILE_FOOTER);
if(ferror(out) != 0) { if (ferror(out) != 0) {
fatal(ptx, "Failed to write z85 output!\n"); fatal(ptx, "Failed to write z85 output!\n");
} }
free(encoded); free(encoded);
@@ -77,33 +76,30 @@ int pcpz85_encode(char *infile, char *outfile) {
return 0; return 0;
errz2: errz2:
free(input); free(input);
errz1: errz1:
return 1; return 1;
} }
int pcpz85_decode(char *infile, char *outfile) { int pcpz85_decode(char *infile, char *outfile) {
FILE *in; FILE *in;
FILE *out; FILE *out;
if(infile == NULL) if (infile == NULL)
in = stdin; in = stdin;
else { else {
if((in = fopen(infile, "rb")) == NULL) { if ((in = fopen(infile, "rb")) == NULL) {
fatal(ptx, "Could not open input file %s\n", infile); fatal(ptx, "Could not open input file %s\n", infile);
goto errdz1; goto errdz1;
} }
} }
if(outfile == NULL) if (outfile == NULL)
out = stdout; out = stdout;
else { else {
if((out = fopen(outfile, "wb+")) == NULL) { if ((out = fopen(outfile, "wb+")) == NULL) {
fatal(ptx, "Could not open output file %s\n", outfile); fatal(ptx, "Could not open output file %s\n", outfile);
goto errdz1; goto errdz1;
} }
@@ -111,20 +107,17 @@ int pcpz85_decode(char *infile, char *outfile) {
char *encoded = pcp_readz85file(ptx, in); char *encoded = pcp_readz85file(ptx, in);
if(encoded == NULL) if (encoded == NULL)
goto errdz1; goto errdz1;
size_t clen; size_t clen;
byte *decoded = pcp_z85_decode(ptx, encoded, &clen); byte *decoded = pcp_z85_decode(ptx, encoded, &clen);
if (decoded == NULL)
if(decoded == NULL)
goto errdz2; goto errdz2;
fwrite(decoded, clen, 1, out); fwrite(decoded, clen, 1, out);
fclose(out); if (fclose(out) != 0) {
if(ferror(out) != 0) {
fatal(ptx, "Failed to write decoded output!\n"); fatal(ptx, "Failed to write decoded output!\n");
goto errdz3; goto errdz3;
} }
@@ -133,12 +126,12 @@ int pcpz85_decode(char *infile, char *outfile) {
free(decoded); free(decoded);
return 0; return 0;
errdz3: errdz3:
free(decoded); free(decoded);
errdz2: errdz2:
free(encoded); free(encoded);
errdz1: errdz1:
return 1; return 1;
} }

View File

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

View File

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

View File

@@ -173,7 +173,6 @@ void test4() {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
sodium_init();
PcpContext *ptx = new PcpContext(); PcpContext *ptx = new PcpContext();
try { try {

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ gen() {
pub=$5 pub=$5
sec=$6 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}'` 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 gen Niemand niemand@local n y unknown1 unknown2
$pcp1 -V unknown3 -l $pcp1 -V unknown3 -l
echo hallo | $pcp -e -x a -z | egrep -v "^ " | egrep -v -- "----" | grep . > unknown4 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 echo "bartid=$ids
bartserial = $ser bartserial=$ser
idbobby = $idb idbobby=$idb
idalicia = $ida idalicia=$ida
mailbobby = bobby@local mailbobby=bobby@local
mailalicia = alicia@local" > keys.cfg mailalicia=alicia@local" > keys.cfg
./gencheader > static.h ./gencheader > static.h

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More