103 Commits

Author SHA1 Message Date
8ecfe531a3 rm unneeded files 2025-11-24 23:16:54 +01:00
de2e1f3f22 add badges 2025-11-24 23:11:25 +01:00
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
126 changed files with 5799 additions and 6941 deletions

View File

@@ -1,73 +0,0 @@
language: c
os:
- linux
before_install:
# runtime dependency
- git clone https://github.com/jedisct1/libsodium
- cd libsodium
- ./autogen.sh
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
#
# unittest dependencies, perl modules
- wget http://search.cpan.org/CPAN/authors/id/T/TL/TLINDEN/Config-General-2.56.tar.gz
- tar xvzf Config-General-2.56.tar.gz
- cd Config-General-2.56
- perl Makefile.PL && make
- sudo make install
- cd ..
- wget http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/Tie-IxHash-1.23.tar.gz
- tar xvzf Tie-IxHash-1.23.tar.gz
- cd Tie-IxHash-1.23
- perl Makefile.PL && make
- sudo make install
- cd ..
- wget http://search.cpan.org/CPAN/authors/id/I/IN/INGY/YAML-1.14.tar.gz
- tar xvfz YAML-1.14.tar.gz
- cd YAML-1.14
- perl Makefile.PL && make
- sudo make install
- cd ..
#
# for debugging - just in case, uncomment this and the next if needed
#- wget http://valgrind.org/downloads/valgrind-3.10.1.tar.bz2
#- tar xvjf valgrind-3.10.1.tar.bz2
#- cd valgrind-3.10.1
#- ./configure --prefix=/usr
#- make
#- sudo make install
#- cd ..
#
# valgrind runtime dependency
#- sudo apt-get update
#- sudo apt-get install libc6-dbg
#
# python bindings runtime dependencies
- sudo apt-get update -qq
- sudo apt-get install python-pip texinfo
- git clone https://github.com/atgreen/libffi
- cd libffi
- ./autogen.sh
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
- sudo pip install cffi
#
# finally prepare autoconf stuff
- ./autogen.sh
compiler:
- clang
- gcc
script:
- ./configure --enable-python-binding
- make
- make check
- make test
#
# upload last fuzzy testfiles in case one of them failed
- cd tests
- cat testfuzzP.pub | openssl base64 | curl -F 'sprunge=<-' http://sprunge.us
- cat testfuzzS.sec | openssl base64 | curl -F 'sprunge=<-' http://sprunge.us

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

674
COPYING
View File

@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

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
Changed publuc key signature storage, previously
I didn't add the actual signature, therefore a

60
FAQ
View File

@@ -1,60 +0,0 @@
= build a static binary =
./configure --disable-debug
make LDFLAGS="-all-static -s"
= choosing a strong passphrase =
A passphrase like Ahc<e3% is not really secure. First
it's difficult to memorize, second it's easy for a computer
to compute. The better aproach is to use a passphrase
you can easily momorize and which is hard for a computer
to compute (i.e. to guess) like: Phantom orchestra boredom popcorn.
Read [1] to learn more.
Pcp doesn't enforce a password policy nor does it check
the password quality. Use something like pwqcheck [2].
= supply password non-interactively without blocking stdin =
Sometimes (e.g. for tests) there's no controlling terminal from
which pcp could request a passphrase if needed. In such cases
you can use the option -X <file> so that it reads the passphrase
from that file.
However if you call -X - then it will read the passphrase from
stdin. But what if the data to be processed shall be read from
stdin as well?
Use a pipe:
mkfifo /tmp/pwpipe
chmod 600 /tmp/pwpipe
export HISTIGNORE=printf
printf "%s\n", "password" > /tmp/pwpipe &
cat cleartext | pcp1 -e -O output -X /tmp/pwpipe
rm -f /tmp/pwpipe
So, what happens here? We create a named pipe in /tmp/pwpipe and
print the passphrase into it. We use printf, because this is a
shell built-in and does not appear in any process listing or
process accounting. But note the '&' after the printf command:
we're sending it into the background. Why? Because a named pipe
is a real simple device. It blocks writing if there's no reader
and it blocks reading if there's no writer. So in our case we
put the passphrase into it, but the printf command will be blocked
until some other process reads it from the pipe, which is precisely
what happens in the next line. Pcp uses the pipe (because of -X),
reads the passphrase from there and proceeds with it's normal
business. Meanwhile the printf command exits.
[1]
https://firstlook.org/theintercept/2015/03/26/passphrases-can-memorize-attackers-cant-guess/
[2]
http://www.openwall.com/passwdqc/

370
INSTALL
View File

@@ -1,370 +0,0 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@@ -1,37 +0,0 @@
#
# 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>.
#
if BUILDPY
MAYPY=bindings/py
endif
if BUILDCPP
MAYCPP=bindings/cpp
endif
SUBDIRS = include libpcp src man tests $(MAYCPP) $(MAYPY)
ACLOCAL_AMFLAGS = -I config
test:
cd tests && make test $(CHECK)
stresstest:
cd tests && make stresstest

0
NEWS
View File

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

190
README.md Normal file
View File

@@ -0,0 +1,190 @@
[![status-badge](https://ci.codeberg.org/api/badges/15605/status.svg)](https://ci.codeberg.org/repos/15605)
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/pcp/blob/master/LICENSE)
# 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
keysig can be verified later.
@@ -10,12 +13,7 @@ malloc() new pointers in functions only if not NULL, e.g. pcp_gennonce()
check pub key count in pcp.c before calling verify signature, croak if count==0
vault checksum: add keysigs as well
Add newlines to headers in define.h, so strlen() later catches the whole length.
Check is_utf8 license.
also found in https://gd.meizo.com/_files/lpc/ext/utf8.c
c++ destructor double free mess

View File

@@ -1 +0,0 @@
0.3.0

View File

@@ -1,28 +0,0 @@
environment:
global:
CYG_ROOT: C:\cygwin
CYG_BASH: C:\cygwin\bin\bash
os: unstable
platform:
- Win32
test: off
init:
- git config --global core.autocrlf input
install:
- '%CYG_ROOT%/bin/bash -lc "git clone https://github.com/jedisct1/libsodium /tmp/libsodium"'
- '%CYG_ROOT%/bin/bash -lc "cd /tmp/libsodium; exec 0</dev/null; ./autogen.sh"'
- '%CYG_ROOT%/bin/bash -lc "cd /tmp/libsodium; exec 0</dev/null; ./configure --prefix=/usr"'
- '%CYG_ROOT%/bin/bash -lc "cd /tmp/libsodium; exec 0</dev/null; make"'
- '%CYG_ROOT%/bin/bash -lc "cd /tmp/libsodium; exec 0</dev/null; make install"'
build_script:
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./autogen.sh"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; cat config.log"'
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'

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 *pout = ps_new_file(out);
size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, pubhash, sign, 0); // FIXME: add anon support
size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, S.K, pubhash, sign, 0); // FIXME: add anon support
if(clen <= 0)
throw exception(PTX);
ps_close(pin);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -41,12 +41,12 @@ namespace pcp {
std::string msg;
PCPCTX *ptx = P->ptx;
if(ptx->pcp_errset == 1) {
msg = ptx->pcp_err;
msg = ptx->pcp_err;
}
if(errno) {
msg += std::string("\nError: ")
+ std::string(strerror(errno))
+ std::string("\n");
msg += std::string("\nError: ")
+ std::string(strerror(errno))
+ std::string("\n");
}
return msg;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,8 +83,8 @@ namespace pcp {
Key(PcpContext *P, bool generate);
Key(PcpContext *P, const std::string& passphrase);
Key(PcpContext *P, const std::string& passphrase,
const std::string& owner,
const std::string& mail);
const std::string& owner,
const std::string& mail);
Key(PcpContext *P, pcp_key_t *k);
Key(PcpContext *P, pcp_key_t *k, bool store);
Key(PcpContext *P, std::string &z85encoded, std::string& passphrase);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -53,8 +53,8 @@ Key::Key(PcpContext *P, const string& passphrase) {
}
Key::Key(PcpContext *P, const string& passphrase,
const string& owner,
const string& mail) {
const string& owner,
const string& mail) {
stored = false;
pcp_key_t *_K = pcpkey_new();
K = pcpkey_encrypt(P->ptx, _K, (char *)passphrase.c_str());

View File

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

View File

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

View File

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

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).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -43,7 +43,10 @@ PCPCTX *ptx_new() {
p->pcppubkey_hash = NULL;
p->pcpkeysig_hash = NULL;
sodium_init();
if(sodium_init() == -1) {
perror("failed to initialize libsodium");
exit(1);
}
return p;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iterate(ptx, key) \
#define pcphash_iterate(ptx, key) \
pcp_key_t *__k = NULL; \
HASH_ITER(hh, ptx->pcpkey_hash, key, __k)
@@ -73,7 +73,7 @@
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iteratepub(ptx, key) \
#define pcphash_iteratepub(ptx, key) \
pcp_pubkey_t *__p = NULL; \
HASH_ITER(hh, ptx->pcppubkey_hash, key, __p)
@@ -142,7 +142,7 @@ int pcphash_countpub(PCPCTX *ptx);
#define pcphash_iteratekeysig(ptx, key) \
#define pcphash_iteratekeysig(ptx, key) \
pcp_keysig_t *__s = NULL; \
HASH_ITER(hh, ptx->pcpkeysig_hash, key, __s)

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,16 +35,14 @@
#define PCP_RAW_KEYSIGSIZE sizeof(pcp_keysig_t) - sizeof(UT_hash_handle)
pcp_keysig_t *keysig2be(pcp_keysig_t *s);
pcp_keysig_t *keysig2native(pcp_keysig_t *s);
/* put a keysig into a buffer, convert to big endian while at it */
Buffer *pcp_keysig2blob(pcp_keysig_t *s);
void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s);
/* same, but allocs buffer */
Buffer *pcp_keysigblob(pcp_keysig_t *s);
/* fetch a keysig from a buffer, usually loaded from vault */
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
pcp_keysig_t *pcp_blob2keysig(Buffer *blob);
/* debug print a keysig */
void pcp_dumpkeysig(pcp_keysig_t *s);

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2014 T.v.Dein.
Copyright (C) 2014-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,44 +27,49 @@
#define _HAVE_PCP_MGMT_H
#if defined __linux__ || defined __GNU__ || defined __GLIBC__
# ifndef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE 1
# endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#endif
#
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 1
# endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 1
#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
# define _BSD_SOURCE 1
#define _BSD_SOURCE 1
#endif
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_JSON
// #ifdef HAVE_JSON
#ifndef JANSSON_H
#include <jansson.h>
#endif
#include "buffer.h"
#include "context.h"
#include "defines.h"
#include "platform.h"
#include "structs.h"
#include "mem.h"
#include "ed.h"
#include "key.h"
#include "keysig.h"
#include "buffer.h"
#include "mem.h"
#include "platform.h"
#include "scrypt.h"
#include "context.h"
#include "structs.h"
/* key management api, export, import, and stuff */
/**
* \defgroup PubKeyExport KEYEXPORT
* @{
@@ -72,10 +77,6 @@
Functions to export and import keys in various formats.
*/
/** RFC4880 alike public key export with some modifications.
(Refer to the INTERNALS section of the pcp(1) manual page for details.
@@ -85,11 +86,9 @@
\return the function returns a Buffer object containing the binary
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 the format described at
@@ -105,7 +104,8 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
/** 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.
@@ -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
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
@@ -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
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
@@ -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)
*/
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
@@ -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);
/* import secret key */
pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize, 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);
pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize,
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 */
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_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader);
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p,
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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,47 +25,6 @@
#include "config.h"
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#else /* no endian.h */
# ifdef HAVE_SYS_ENDIAN_H
# include <sys/types.h>
# include <sys/endian.h>
# ifndef HAVE_BE32TOH
# /* openbsd, use aliases */
# define be16toh betoh16
# define be32toh betoh32
# define be64toh betoh64
# endif
# else /* no sys/endian.h */
# ifdef __CPU_IS_BIG_ENDIAN
# define be16toh(x) (x)
# define htobe16(x) (x)
# define be32toh(x) (x)
# define htobe32(x) (x)
# define be64toh(x) (x)
# define htobe64(x) (x)
# else
# ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
# else
# ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
# else
# error Need either netinet/in.h or arpa/inet.h for ntohl() and htonl()
# endif
# endif
# define be16toh(x) ((uint16_t)ntohl((uint16_t)(x)))
# define htobe16(x) ((uint16_t)htonl((uint16_t)(x)))
# define be32toh(x) ((uint32_t)ntohl((uint32_t)(x)))
# define htobe32(x) ((uint32_t)htonl((uint32_t)(x)))
# define be64toh(x) ((uint64_t)ntohl((uint64_t)(x)))
# define htobe64(x) ((uint64_t)htonl((uint64_t)(x)))
# endif
# endif /* HAVE_SYS_ENDIAN_H */
#endif /* HAVE_ENDIAN_H */
#ifndef HAVE_ARC4RANDOM
#include <sodium.h>
#define arc4random() randombytes_random()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
You can contact me by mail: <tom AT vondein DOT org>.
*/
#include "key.h"
#include "context.h"
@@ -33,13 +32,13 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
size_t plen = strnlen(passphrase, 255);
/* create the scrypt hash */
byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, crypto_secretbox_NONCEBYTES);
byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, LNONCE);
/* make a hash from the scrypt() result */
crypto_hash_sha256(key, (byte*)scrypted, 64);
crypto_hash_sha256(key, (byte *)scrypted, 64);
/* turn the 32byte hash into a secret key */
key[0] &= 248;
key[0] &= 248;
key[31] &= 127;
key[31] |= 64;
@@ -48,11 +47,10 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
return key;
}
char *pcp_getkeyid(pcp_key_t *k) {
uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT);
p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s);
return id;
@@ -61,14 +59,15 @@ char *pcp_getkeyid(pcp_key_t *k) {
/* same as above but for imported pbp keys */
char *pcp_getpubkeyid(pcp_pubkey_t *k) {
uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT);
p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
s = jen_hash(k->edpub, LEDPUB, JEN_SSALT);
char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s);
return id;
}
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 */
byte *ms = urmalloc(32);
byte *ss = urmalloc(32);
@@ -82,7 +81,7 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
/* curve25519 secret key */
memcpy(csk, cs, 32);
csk[0] &= 248;
csk[0] &= 248;
csk[31] &= 63;
csk[31] |= 64;
@@ -94,53 +93,53 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
ucfree(cs, 32);
}
pcp_key_t * pcpkey_new () {
byte *mp = ucmalloc(32);
byte *ms = ucmalloc(64);
byte *sp = ucmalloc(32);
byte *ss = ucmalloc(64);
byte *cp = ucmalloc(32);
byte *cs = ucmalloc(32);
pcp_key_t *pcpkey_new() {
byte *mp = ucmalloc(LEDPUB);
byte *ms = ucmalloc(LEDSEC);
byte *sp = ucmalloc(LEDPUB);
byte *ss = ucmalloc(LEDSEC);
byte *cp = ucmalloc(LBOXPUB);
byte *cs = ucmalloc(LBOXSEC);
/* generate key material */
pcp_keypairs(ms, mp, cs, cp, ss, sp);
/* fill in our struct */
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
memcpy (key->masterpub, mp, 32);
memcpy (key->mastersecret, ms, 64);
memcpy (key->pub, cp, 32);
memcpy (key->secret, cs, 32);
memcpy (key->edpub, sp, 32);
memcpy (key->edsecret, ss, 64);
memcpy(key->masterpub, mp, LEDPUB);
memcpy(key->mastersecret, ms, LEDSEC);
memcpy(key->pub, cp, LBOXPUB);
memcpy(key->secret, cs, LBOXSEC);
memcpy(key->edpub, sp, LEDPUB);
memcpy(key->edsecret, ss, LEDSEC);
char *id = pcp_getkeyid(key);
memcpy (key->id, id, 17);
memcpy(key->id, id, 17);
free(id);
key->ctime = (long)time(0);
key->version = PCP_KEY_VERSION;
key->serial = arc4random();
key->type = PCP_KEY_TYPE_SECRET;
key->serial = arc4random();
key->type = PCP_KEY_TYPE_SECRET;
key->owner[0] = '\0';
key->mail[0] = '\0';
/* clean up */
ucfree(ms, 64);
ucfree(ss, 64);
ucfree(mp, 32);
ucfree(sp, 32);
ucfree(cs, 32);
ucfree(cp, 32);
ucfree(ms, LEDSEC);
ucfree(ss, LEDSEC);
ucfree(mp, LEDPUB);
ucfree(sp, LEDPUB);
ucfree(cs, LBOXSEC);
ucfree(cp, LBOXPUB);
return key;
}
byte * pcp_gennonce() {
byte *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
byte *pcp_gennonce() {
byte *nonce = ucmalloc(LNONCE);
arc4random_buf(nonce, LNONCE);
return nonce;
}
@@ -150,39 +149,36 @@ void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail) {
}
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
if(key->nonce[0] == 0) {
if (key->nonce[0] == 0) {
byte *nonce = pcp_gennonce();
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
memcpy(key->nonce, nonce, LNONCE);
ucfree(nonce, LNONCE);
}
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *encrypted;
size_t es;
Buffer *both = buffer_new(128, "keypack");
buffer_add(both, key->mastersecret, 64);
buffer_add(both, key->edsecret, 64);
buffer_add(both, key->secret, 32);
buffer_add(both, key->mastersecret, LEDSEC);
buffer_add(both, key->edsecret, LEDSEC);
buffer_add(both, key->secret, LBOXSEC);
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both), key->nonce, encryptkey);
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both),
key->nonce, encryptkey);
buffer_free(both);
sfree(encryptkey);
if(es == 176) { /* FIXME: calc! */
if (es == LSEC) {
/* success */
memcpy(key->encrypted, encrypted, 176);
memcpy(key->encrypted, encrypted, LSEC);
ucfree(encrypted, es);
arc4random_buf(key->secret, 32);
arc4random_buf(key->edsecret, 64);
arc4random_buf(key->mastersecret, 64);
key->secret[0] = 0;
key->edsecret[0] = 0;
key->mastersecret[0] = 0;
}
else {
memset(key->secret, 0, LBOXSEC);
memset(key->edsecret, 0, LEDSEC);
memset(key->mastersecret, 0, LEDSEC);
} else {
fatal(ptx, "failed to encrypt the secret key!\n");
ucfree(encrypted, es);
ucfree(key, sizeof(pcp_key_t));
@@ -193,25 +189,25 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
}
pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
byte *decrypted;
byte *decrypted = ucmalloc(LSEC - crypto_secretbox_MACBYTES);
size_t es;
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, 176, key->nonce, encryptkey);
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, LSEC, key->nonce,
encryptkey);
sfree(encryptkey);
if(es == 0) {
if (es == 0) {
/* success */
memcpy(key->mastersecret, decrypted, 64);
memcpy(key->edsecret, decrypted + 64, 64);
memcpy(key->secret, decrypted +128, 32);
ucfree(decrypted, 160);
}
else {
memcpy(key->mastersecret, decrypted, LEDSEC);
memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
memcpy(key->secret, decrypted + LEDSEC + LEDSEC, LBOXSEC);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
} else {
fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es);
ucfree(decrypted, 160);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
return NULL;
}
@@ -219,17 +215,17 @@ pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
}
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key) {
pcp_pubkey_t *pub = urmalloc(sizeof (pcp_pubkey_t));
memcpy(pub->masterpub, key->masterpub, 32);
memcpy(pub->pub, key->pub, 32);
memcpy(pub->edpub, key->edpub, 32);
pcp_pubkey_t *pub = urmalloc(sizeof(pcp_pubkey_t));
memcpy(pub->masterpub, key->masterpub, LEDPUB);
memcpy(pub->pub, key->pub, LBOXPUB);
memcpy(pub->edpub, key->edpub, LEDSEC);
memcpy(pub->owner, key->owner, 255);
memcpy(pub->mail, key->mail, 255);
memcpy(pub->id, key->id, 17);
pub->version = key->version;
pub->type = PCP_KEY_TYPE_PUBLIC;
pub->ctime = key->ctime;
pub->serial = key->serial;
pub->type = PCP_KEY_TYPE_PUBLIC;
pub->ctime = key->ctime;
pub->serial = key->serial;
return pub;
}
@@ -245,152 +241,137 @@ char *pcpkey_get_art(pcp_key_t *k) {
byte *pcppubkey_getchecksum(pcp_pubkey_t *k) {
byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32);
crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash;
}
byte *pcpkey_getchecksum(pcp_key_t *k) {
byte *hash = ucmalloc(32);
crypto_hash_sha256(hash, k->pub, 32);
crypto_hash_sha256(hash, k->pub, LBOXPUB);
return hash;
}
pcp_key_t * key2be(pcp_key_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
uint32_t version = k->version;
byte* p = (byte*)&version;
if(p[0] != 0) {
k->version = htobe32(k->version);
k->serial = htobe32(k->serial);
k->ctime = htobe64(k->ctime);
}
return k;
#endif
}
pcp_key_t *key2native(pcp_key_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
k->version = be32toh(k->version);
k->serial = be32toh(k->serial);
k->ctime = be64toh(k->ctime);
return k;
#endif
}
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
uint32_t version = k->version;
byte* p = (byte*)&version;
if(p[0] != 0) {
k->version = htobe32(k->version);
k->serial = htobe32(k->serial);
k->ctime = htobe64(k->ctime);
}
return k;
#endif
}
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k) {
#ifdef __CPU_IS_BIG_ENDIAN
return k;
#else
k->version = be32toh(k->version);
k->serial = be32toh(k->serial);
k->ctime = be64toh(k->ctime);
return k;
#endif
}
void pcp_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) {
buffer_add(b, k->masterpub, 32);
buffer_add(b, k->sigpub, 32);
buffer_add(b, k->pub, 32);
buffer_add(b, k->edpub, 32);
buffer_add(b, k->masterpub, LEDPUB);
buffer_add(b, k->pub, LBOXPUB);
buffer_add(b, k->edpub, LEDPUB);
buffer_add(b, k->owner, 255);
buffer_add(b, k->mail, 255);
buffer_add(b, k->id, 17);
buffer_add8(b, k->type);
buffer_add64(b, k->ctime);
buffer_add32(b, k->version);
buffer_add32(b, k->serial);
buffer_add64be(b, k->ctime);
buffer_add32be(b, k->version);
buffer_add32be(b, k->serial);
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) {
if(type == PCP_KEY_TYPE_PUBLIC) {
if (type == PCP_KEY_TYPE_PUBLIC) {
Buffer *b = buffer_new(PCP_RAW_PUBKEYSIZE, "bp");
pcp_pubkeyblob(b, (pcp_pubkey_t *)k);
return b;
}
else {
} else {
Buffer *b = buffer_new(PCP_RAW_KEYSIZE, "bs");
pcp_seckeyblob(b, (pcp_key_t *)k);
return b;
}
}
int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
if(key->pub[0] == 0) {
fatal(ptx, "Pubkey sanity check: public key contained in key seems to be empty!\n");
if (key->pub[0] == 0) {
fatal(ptx, "Pubkey sanity check: public key contained in key seems to be "
"empty!\n");
return 1;
}
if(key->type != PCP_KEY_TYPE_PUBLIC) {
fatal(ptx, "Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: %02x)!\n",
PCP_KEY_TYPE_PUBLIC, key->type);
if (key->type != PCP_KEY_TYPE_PUBLIC) {
fatal(ptx,
"Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: "
"%02x)!\n",
PCP_KEY_TYPE_PUBLIC, key->type);
return 1;
}
if(key->version != PCP_KEY_VERSION) {
fatal(ptx, "Pubkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
PCP_KEY_VERSION, key->version);
return 1;
}
if(key->serial <= 0) {
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n", key->serial);
if (key->version != PCP_KEY_VERSION) {
fatal(ptx,
"Pubkey sanity check: unknown key version (expected: %08X, got: "
"%08X)!\n",
PCP_KEY_VERSION, key->version);
return 1;
}
if(key->id[16] != '\0') {
if (key->serial <= 0) {
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1;
}
if (key->id[16] != '\0') {
char *got = ucmalloc(17);
memcpy(got, key->id, 17);
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);
return 1;
}
@@ -398,50 +379,63 @@ int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
struct tm *c;
time_t t = (time_t)key->ctime;
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 :) */
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;
}
pcp_pubkey_t *maybe = pcphash_pubkeyexists(ptx, key->id);
if(maybe != NULL) {
fatal(ptx, "Pubkey sanity check: there already exists a key with the id 0x%s\n", key->id);
if (maybe != NULL) {
fatal(ptx,
"Pubkey sanity check: there already exists a key with the id 0x%s\n",
key->id);
return 1;
}
return 0;
}
int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
if(key->encrypted[0] == 0) {
fatal(ptx, "Secretkey sanity check: secret key contained in key seems to be empty!\n");
if (key->encrypted[0] == 0) {
fatal(ptx, "Secretkey sanity check: secret key contained in key seems to "
"be empty!\n");
return 1;
}
if(key->type != PCP_KEY_TYPE_SECRET && key->type != PCP_KEY_TYPE_MAINSECRET) {
fatal(ptx, "Secretkey sanity check: key type is not SECRET (expected: %02x, got: %02x)!\n",
PCP_KEY_TYPE_SECRET, key->type);
if (key->type != PCP_KEY_TYPE_SECRET &&
key->type != PCP_KEY_TYPE_MAINSECRET) {
fatal(ptx,
"Secretkey sanity check: key type is not SECRET (expected: %02x, "
"got: %02x)!\n",
PCP_KEY_TYPE_SECRET, key->type);
return 1;
}
if(key->version != PCP_KEY_VERSION) {
fatal(ptx, "Secretkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
PCP_KEY_VERSION, key->version);
return 1;
}
if(key->serial <= 0) {
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n", key->serial);
if (key->version != PCP_KEY_VERSION) {
fatal(ptx,
"Secretkey sanity check: unknown key version (expected: %08X, got: "
"%08X)!\n",
PCP_KEY_VERSION, key->version);
return 1;
}
if(key->id[16] != '\0') {
if (key->serial <= 0) {
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1;
}
if (key->id[16] != '\0') {
char *got = ucmalloc(17);
memcpy(got, key->id, 17);
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);
return 1;
}
@@ -449,15 +443,21 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
struct tm *c;
time_t t = (time_t)key->ctime;
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 :) */
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;
}
pcp_key_t *maybe = pcphash_keyexists(ptx, key->id);
if(maybe != NULL) {
fatal(ptx, "Secretkey sanity check: there already exists a key with the id 0x%s\n", key->id);
if (maybe != NULL) {
fatal(
ptx,
"Secretkey sanity check: there already exists a key with the id 0x%s\n",
key->id);
return 1;
}
@@ -465,40 +465,48 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
}
void pcp_dumpkey(pcp_key_t *k) {
int i;
unsigned int i;
printf("Dumping pcp_key_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->masterpub[i]);
for (i = 0; i < LEDPUB; ++i)
printf("%02x", (unsigned int)k->masterpub[i]);
printf("\n");
printf(" public: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->pub[i]);
for (i = 0; i < LBOXPUB; ++i)
printf("%02x", (unsigned int)k->pub[i]);
printf("\n");
printf(" edpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->edpub[i]);
for (i = 0; i < LEDPUB; ++i)
printf("%02x", (unsigned int)k->edpub[i]);
printf("\n");
printf("mastersec: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->mastersecret[i]);
for (i = 0; i < LEDSEC; ++i)
printf("%02x", (unsigned int)k->mastersecret[i]);
printf("\n");
printf(" secret: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->secret[i]);
for (i = 0; i < LBOXPUB; ++i)
printf("%02x", (unsigned int)k->secret[i]);
printf("\n");
printf(" edsecret: ");
for ( i = 0;i < 64;++i) printf("%02x",(unsigned int) k->edsecret[i]);
for (i = 0; i < LEDSEC; ++i)
printf("%02x", (unsigned int)k->edsecret[i]);
printf("\n");
printf(" nonce: ");
for ( i = 0;i < 24;++i) printf("%02x",(unsigned int) k->nonce[i]);
for (i = 0; i < LNONCE; ++i)
printf("%02x", (unsigned int)k->nonce[i]);
printf("\n");
printf("encrypted: ");
for ( i = 0;i < 80;++i) printf("%02x",(unsigned int) k->encrypted[i]);
for (i = 0; i < LSEC; ++i)
printf("%02x", (unsigned int)k->encrypted[i]);
printf("\n");
printf(" owner: %s\n", k->owner);
@@ -516,21 +524,23 @@ void pcp_dumpkey(pcp_key_t *k) {
printf(" type: 0x%02X\n", k->type);
}
void pcp_dumppubkey(pcp_pubkey_t *k) {
int i;
unsigned int i;
printf("Dumping pcp_pubkey_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->masterpub[i]);
for (i = 0; i < LEDPUB; ++i)
printf("%02x", (unsigned int)k->masterpub[i]);
printf("\n");
printf(" public: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->pub[i]);
for (i = 0; i < LBOXPUB; ++i)
printf("%02x", (unsigned int)k->pub[i]);
printf("\n");
printf(" edpub: ");
for ( i = 0;i < 32;++i) printf("%02x",(unsigned int) k->edpub[i]);
for (i = 0; i < LEDPUB; ++i)
printf("%02x", (unsigned int)k->edpub[i]);
printf("\n");
printf(" owner: %s\n", k->owner);
@@ -547,3 +557,37 @@ void pcp_dumppubkey(pcp_pubkey_t *k) {
printf(" type: 0x%02X\n", k->type);
}
/*
via
http://rosettacode.org/wiki/Entropy#C
*/
double pcp_getentropy(char *source) {
int len;
int *hist;
double H;
int wherechar[256];
int i, histlen;
histlen = 0;
H = 0;
len = (int)strlen(source);
hist = (int *)calloc(len, sizeof(int));
for (i = 0; i < 256; i++)
wherechar[i] = -1;
for (i = 0; i < len; i++) {
if (wherechar[(int)source[i]] == -1) {
wherechar[(int)source[i]] = histlen;
histlen++;
}
hist[wherechar[(int)source[i]]]++;
}
for (i = 0; i < histlen; i++) {
H -= (double)hist[i] / len * log2((double)hist[i] / len);
}
return H;
}

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,7 +83,7 @@ void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
byte *value = realloc (d, newlen);
if (value == NULL) {
err(errno, "Cannot reallocate %ld bytes of memory", newlen);
err(errno, "Cannot reallocate %"FMT_SIZE_T" bytes of memory", (SIZE_T_CAST)newlen);
exit(-1);
}

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

View File

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

278
libpcp/readpass.c Normal file
View File

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

View File

@@ -1,7 +1,7 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,8 +30,8 @@ byte* pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_
nonce, noncelen, NULL, 0);
int status = crypto_pwhash_scryptsalsa208sha256(dk, 64, passwd, passwdlen, salt,
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
ucfree(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
if (status == 0) {

View File

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

View File

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

View File

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

View File

@@ -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.
@@ -28,21 +28,22 @@ static char encoder [85 + 1] = {
"}@%$#"
};
/* Maps base 85 to base 256 */
/* We chop off lower 32 and higher 128 ranges */
/* Maps base 85 to base 256
We chop off lower 32 and higher 128 ranges
0xFF denotes invalid characters within this range */
static uint8_t decoder [96] = {
0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
0xFF, 0x44, 0xFF, 0x54, 0x53, 0x52, 0x48, 0xFF,
0x4B, 0x4C, 0x46, 0x41, 0xFF, 0x3F, 0x3E, 0x45,
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,
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x3B, 0x3C, 0x3D, 0x4D, 0xFF, 0x4E, 0x43, 0xFF,
0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
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 */
/* dest. Size must be a multiple of 4. */
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
{
if (size % 4 != 0)
return NULL; /* !assert */
/* --------------------------------------------------------------------------
Encode a binary frame as a string; destination string MUST be at least
size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
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 byte_nbr = 0;
uint32_t value = 0;
while (byte_nbr < size) {
/* Accumulate value in base 256 (binary) */
// Accumulate value in base 256 (binary)
value = value * 256 + data [byte_nbr++];
if (byte_nbr % 4 == 0) {
/* Output value in base 85 */
// Output value in base 85
unsigned int divisor = 85 * 85 * 85 * 85;
while (divisor) {
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;
}
}
if (char_nbr != size * 5 / 4)
return NULL; /* !assert */
if (char_nbr != size * 5 / 4) {
return NULL; /* !assert */
}
dest [char_nbr] = 0;
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. */
// --------------------------------------------------------------------------
// 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, char *string)
uint8_t *zmq_z85_decode (uint8_t *dest, const char *string)
{
if (strlen (string) % 5 != 0)
return NULL; /* !assert */
unsigned int byte_nbr = 0;
unsigned int char_nbr = 0;
uint32_t value = 0;
size_t string_len = strlen (string);
while (char_nbr < string_len) {
/* Accumulate value in base 85 */
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
while (string[char_nbr]) {
// Accumulate value in base 85
if (UINT32_MAX / 85 < value) {
// 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) {
/* Output value in base 256 */
// Output value in base 256
unsigned int divisor = 256 * 256 * 256;
while (divisor) {
dest [byte_nbr++] = value / divisor % 256;
@@ -105,7 +125,15 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
value = 0;
}
}
if (byte_nbr != strlen (string) * 4 / 5)
return NULL; /* !assert */
if (char_nbr % 5 != 0) {
goto error_inval;
}
if (byte_nbr != strlen (string) * 4 / 5) {
goto error_inval;
}
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
=head2 PASSPHRASES
Passphrases are used to protect secret data at rest on various instances
by pcp, like secret keys or symmetric encrypted data.
Pcp doesn't use the passphrase directly but uses a key derivation function
to calculate a secure key from the passphrase: libsodium's
B<crypto_pwhash_scryptsalsa208sha256()> function.
In order to properly protect secret keys, pcp measures the entropy
of a given passphrase and warns the user about the possible weak
passphrase. This measurement is calculated using the Claude E. Shannon
method, where a value of 8.0 means maximum available entropy (e.g.
truly random 256 chars in no comprehensible order) and 0.0 stands
for the worst like passphrases like "aaa" or "x".
Pcp considers passphrases with an entropy measurement of 3.32 or higher
as acceptable. This may change in the future.
=head2 VAULT FORMAT
The vault file contains all public and secret keys. It's a portable

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

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
bin_PROGRAMS = pcp1
pcp1_LDADD = ../libpcp/.libs/libpcp1.a
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c \
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c \
encryption.c z85util.c signature.c \
compat_getopt.c

View File

@@ -26,11 +26,9 @@
#ifndef MY_GETOPT_H_INCLUDED
#define MY_GETOPT_H_INCLUDED
#ifdef HAVE_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>
#else
@@ -51,7 +49,7 @@ extern "C" {
#define optarg my_optarg
/* 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 char *my_optarg;
@@ -72,15 +70,15 @@ struct option {
#define optional_argument 2
/* GNU-style long-argument parsers */
extern int my_getopt_long(int argc, char * argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int my_getopt_long(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int my_getopt_long_only(int argc, char * argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int my_getopt_long_only(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
extern int _my_getopt_internal(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#ifdef __cplusplus
}

View File

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

View File

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

View File

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

View File

@@ -19,44 +19,44 @@
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_KEYMGMT_H
#define _HAVE_KEYMGMT_H
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.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 "mgmt.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
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_listkeys();
void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *passwd);
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor);
void pcp_exportsecret(char *keyid, int useid, char *outfile, 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);
char *pcp_normalize_id(char *keyid);
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);
char *pcp_find_id_byrec(char *recipient);

View File

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

858
src/pcp.c

File diff suppressed because it is too large Load Diff

View File

@@ -19,58 +19,58 @@
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCP_H
#define _HAVE_PCP_H
#include <unistd.h>
#include <compat_getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <compat_getopt.h>
#include <unistd.h>
#ifndef DEBUG
# ifdef HAVE_SETRLIMIT
# include <sys/types.h>
# include <sys/time.h>
# include <sys/resource.h>
# endif
#ifdef HAVE_SETRLIMIT
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#endif
/* lib */
#include "mem.h"
#include "z85.h"
#include "zmq_z85.h"
#include "z85util.h"
#include "version.h"
#include "vault.h"
#include "context.h"
#include "mem.h"
#include "vault.h"
#include "version.h"
#include "z85.h"
#include "z85util.h"
#include "zmq_z85.h"
/* subs */
#include "keymgmt.h"
#include "usage.h"
#include "encryption.h"
#include "signature.h"
#include "keyhash.h"
#include "keymgmt.h"
#include "plist.h"
#include "signature.h"
#include "usage.h"
/* operation modi */
/* 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_LISTKEYS 0x00000004
/* 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_LISTKEYS 0x00000004
#define PCP_MODE_EXPORT_SECRET 0x00000009
#define PCP_MODE_EXPORT_PUBLIC 0x00000011
#define PCP_MODE_IMPORT 0x00000020
#define PCP_MODE_ENCRYPT_ME 0x00000038
#define PCP_MODE_DELETE_KEY 0x00000061
#define PCP_MODE_TEXT 0x000000A6
#define PCP_MODE_EDIT 0x0000011D
#define PCP_MODE_ENCRYPT 0x000001E7
#define PCP_MODE_DECRYPT 0x0000033D
#define PCP_MODE_ZENCODE 0x00000584
#define PCP_MODE_ZDECODE 0x00000962
#define PCP_MODE_SIGN 0x00000FF6
#define PCP_MODE_VERIFY 0x00001B25
#define PCP_MODE_CHECKSUM 0x00002E27
#define PCP_MODE_IMPORT 0x00000020
#define PCP_MODE_ENCRYPT_ME 0x00000038
#define PCP_MODE_DELETE_KEY 0x00000061
#define PCP_MODE_TEXT 0x000000A6
#define PCP_MODE_EDIT 0x0000011D
#define PCP_MODE_ENCRYPT 0x000001E7
#define PCP_MODE_DECRYPT 0x0000033D
#define PCP_MODE_ZENCODE 0x00000584
#define PCP_MODE_ZDECODE 0x00000962
#define PCP_MODE_SIGN 0x00000FF6
#define PCP_MODE_VERIFY 0x00001B25
#define PCP_MODE_CHECKSUM 0x00002E27
/*
0x00001B25
@@ -82,13 +82,16 @@
0x00028F70
*/
#define PCP_HELP_INTRO "This is Pretty Curved Privacy. Licensed under the GPLv3. This is\n" \
"BETA software. Use with care. NOT intended for production use.\n"
#define PCP_HELP_INTRO \
"This is Pretty Curved Privacy. Licensed under the GPLv3. This is\n" \
"BETA software. Use with care. NOT intended for production use.\n"
#define LONG_EXTPASS 515
/* some globals */
vault_t *vault;
PCPCTX *ptx;
int debug;
extern vault_t *vault;
extern PCPCTX *ptx;
extern int debug;
void version();
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).
Copyright (C) 2013-2015 T.Linden.
Copyright (C) 2013-2016 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,23 +54,20 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach) {
}
}
if(secret->secret[0] == 0) {
/* encrypted, decrypt it */
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errs1;
char *passphrase;
if(passwd == NULL) {
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
}
else {
passphrase = smalloc(strlen(passwd)+1);
memcpy(passphrase, passwd, strlen(passwd)+1);
}
secret = pcpkey_decrypt(ptx, secret, passphrase);
sfree(passphrase);
if(secret == NULL)
goto errs1;
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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