migrate to codeberg (#21)

This commit is contained in:
T. von Dein
2025-11-24 23:02:13 +01:00
parent 48e87fd605
commit 913f584b76
59 changed files with 1702 additions and 2072 deletions

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

182
README
View File

@@ -1,182 +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.
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 ..
If you want to have JSON support, you'll need to install the Jansson
library (optional):
git clone git://github.com/akheron/jansson.git
cd jansson
autoreconf -i
./configure && make
sudo make install
cd ..
In order to use the python binding, you need to install the cffi python
package.
Next, build pcp:
git clone git://github.com/tlinden/pcp.git
cd pcp
./configure
sudo make install
cd ..
Optionally, you might run the unit tests:
make test
DOCUMENTATION
To learn how to use pcp, read the manpage:
man pcp1
COPYRIGHT
Copyright (c) 2013-2015 by T.v.Dein <tom AT vondein DOT org>
ADDITIONAL COPYRIGHTS
ZeroMQ Z85 encoding routine
Copyright (c) 2007-2013 iMatix Corporation
Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2010-2011 Miru Limited
Copyright (c) 2011 VMware, Inc.
Copyright (c) 2012 Spotify AB
Tarsnap readpass helpers
Copyright 2009 Colin Percival
jen_hash() hash algorithm
Bob Jenkins, Public Domain.
UTHASH hashing macros
Copyright (c) 2003-2013, Troy D. Hanson
Random art image from OpenSSH keygen
Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Comitted by Alexander von Gernler in rev 1.7.
Every incorporated source code is opensource and licensed under the GPL
as well.
AUTHORS
*T.v.Dein <tom AT vondein DOT org*>
LICENSE
Licensed under the GNU GENERAL PUBLIC LICENSE version 3.
HOME
The homepage of Pretty Curved Privacy can be found on
http://www.daemon.de/PrettyCurvedPrivacy. The source is on Github:
https://github.com/TLINDEN/pcp

187
README.md Normal file
View File

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

View File

@@ -1,217 +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 ..
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
./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

View File

@@ -1 +1 @@
0.4.0
0.4.1

View File

@@ -1,119 +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
lt=libtoolize
case `uname` in Darwin*) lt=glibtoolize;; esac
if ! command -v $lt >/dev/null 2>&1 ; then
echo "could not find $lt." 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

@@ -1,383 +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 \
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
)
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
# 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"
# FIXME: check for libm
LIBS="$LIBS -lm"
# 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}
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
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 readpass.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 $@

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

@@ -27,49 +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 _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#
# ifndef __USE_XOPEN
# define __USE_XOPEN 1
# endif
#ifndef __USE_XOPEN
#define __USE_XOPEN 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
* @{
@@ -77,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.
@@ -92,9 +88,7 @@
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
@@ -110,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.
@@ -135,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
@@ -148,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
@@ -157,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
@@ -179,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

@@ -19,7 +19,6 @@
You can contact me by mail: <tom AT vondein DOT org>.
*/
#include "key.h"
#include "context.h"
@@ -36,7 +35,7 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
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;
@@ -48,7 +47,6 @@ 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, LBOXPUB, JEN_PSALT);
@@ -68,7 +66,8 @@ char *pcp_getpubkeyid(pcp_pubkey_t *k) {
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);
@@ -94,7 +93,7 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
ucfree(cs, 32);
}
pcp_key_t * pcpkey_new () {
pcp_key_t *pcpkey_new() {
byte *mp = ucmalloc(LEDPUB);
byte *ms = ucmalloc(LEDSEC);
byte *sp = ucmalloc(LEDPUB);
@@ -107,15 +106,15 @@ pcp_key_t * pcpkey_new () {
/* fill in our struct */
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
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);
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);
@@ -138,7 +137,7 @@ pcp_key_t * pcpkey_new () {
return key;
}
byte * pcp_gennonce() {
byte *pcp_gennonce() {
byte *nonce = ucmalloc(LNONCE);
arc4random_buf(nonce, LNONCE);
return nonce;
@@ -150,9 +149,9 @@ 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, LNONCE);
memcpy(key->nonce, nonce, LNONCE);
ucfree(nonce, LNONCE);
}
@@ -166,20 +165,20 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
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 == LSEC) {
if (es == LSEC) {
/* success */
memcpy(key->encrypted, encrypted, LSEC);
ucfree(encrypted, es);
memset(key->secret, 0, LBOXSEC);
memset(key->edsecret, 0, LEDSEC);
memset(key->mastersecret, 0, LEDSEC);
}
else {
} else {
fatal(ptx, "failed to encrypt the secret key!\n");
ucfree(encrypted, es);
ucfree(key, sizeof(pcp_key_t));
@@ -195,18 +194,18 @@ pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
byte *decrypted = ucmalloc(LSEC - crypto_secretbox_MACBYTES);
size_t es;
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, LSEC, 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, LEDSEC);
memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
memcpy(key->secret, decrypted + LEDSEC + LEDSEC, LBOXSEC);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
}
else {
} else {
fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es);
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
return NULL;
@@ -216,7 +215,7 @@ 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));
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);
@@ -252,7 +251,6 @@ byte *pcpkey_getchecksum(pcp_key_t *k) {
return hash;
}
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) {
buffer_add(b, k->masterpub, LEDPUB);
buffer_add(b, k->pub, LBOXPUB);
@@ -327,47 +325,53 @@ pcp_pubkey_t *pcp_blob2pubkey(Buffer *b) {
}
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",
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",
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->serial <= 0) {
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1;
}
if(key->id[16] != '\0') {
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;
}
@@ -375,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",
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",
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->serial <= 0) {
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n",
key->serial);
return 1;
}
if(key->id[16] != '\0') {
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;
}
@@ -426,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;
}
@@ -447,35 +470,43 @@ void pcp_dumpkey(pcp_key_t *k) {
printf("Dumping pcp_key_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < LEDPUB;++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 < LBOXPUB;++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 < LEDPUB;++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 < LEDSEC;++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 < LBOXPUB;++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 < LEDSEC;++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 < LNONCE;++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 < LSEC;++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);
@@ -493,21 +524,23 @@ void pcp_dumpkey(pcp_key_t *k) {
printf(" type: 0x%02X\n", k->type);
}
void pcp_dumppubkey(pcp_pubkey_t *k) {
unsigned int i;
printf("Dumping pcp_pubkey_t raw values:\n");
printf("masterpub: ");
for ( i = 0;i < LEDPUB;++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 < LBOXPUB;++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 < LEDPUB;++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);
@@ -525,7 +558,6 @@ void pcp_dumppubkey(pcp_pubkey_t *k) {
printf(" type: 0x%02X\n", k->type);
}
/*
via
http://rosettacode.org/wiki/Entropy#C
@@ -535,25 +567,25 @@ double pcp_getentropy(char *source) {
int *hist;
double H;
int wherechar[256];
int i,histlen;
int i, histlen;
histlen = 0;
H = 0;
len = (int)strlen(source);
hist = (int*)calloc(len, sizeof(int));
hist = (int *)calloc(len, sizeof(int));
for(i=0; i<256; i++)
for (i = 0; i < 256; i++)
wherechar[i] = -1;
for(i=0; i<len; i++){
if(wherechar[(int)source[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++) {
for (i = 0; i < histlen; i++) {
H -= (double)hist[i] / len * log2((double)hist[i] / len);
}

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

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

@@ -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,13 +70,13 @@ struct option {
#define optional_argument 2
/* GNU-style long-argument parsers */
extern int my_getopt_long(int argc, char * argv[], const char *shortopts,
extern int my_getopt_long(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int my_getopt_long_only(int argc, char * argv[], const char *shortopts,
extern int my_getopt_long_only(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind);
extern int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
extern int _my_getopt_internal(int argc, char *argv[], const char *shortopts,
const struct option *longopts, int *longind,
int long_only);

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

@@ -19,10 +19,8 @@
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 = NULL;
@@ -43,17 +41,17 @@ 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;
@@ -63,117 +61,107 @@ int pcp_storekey (pcp_key_t *key) {
}
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");
if(owner != NULL)
if (owner != NULL)
memcpy(k->owner, owner, strlen(owner) + 1);
char *mail = pcp_getstdin("Enter the email address of the key owner");
if(mail != NULL)
if (mail != NULL)
memcpy(k->mail, _lc(mail), strlen(mail) + 1);
if(debug)
if (debug)
pcp_dumpkey(k);
char *passphrase;
if(passwd == NULL) {
pcp_readpass(ptx, &passphrase,
"Enter passphrase for key encryption",
if (passwd == NULL) {
pcp_readpass(ptx, &passphrase, "Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
}
else {
} else {
passphrase = passwd;
}
if(strnlen(passphrase, 1024) > 0) {
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);
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) {
if (strncmp(yes, "yes", 1024) != 0) {
goto errkg1;
}
}
key = pcpkey_encrypt(ptx, k, passphrase);
}
else {
} 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);
}
}
if(passwd == NULL) {
if (passwd == NULL) {
/* if passwd is set, it'll be free'd in main() */
sfree(passphrase);
}
errkg1:
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;
@@ -186,81 +174,79 @@ 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;
}
}
if(out != NULL) {
if(debug)
if (out != NULL) {
if (debug)
pcp_dumpkey(key);
if(passwd == NULL) {
if (passwd == NULL) {
char *passphrase;
pcp_readpass(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
"Enter passphrase to decrypt your secret key", NULL, 1,
NULL);
key = pcpkey_decrypt(ptx, key, passphrase);
if(key == NULL) {
if (key == NULL) {
sfree(passphrase);
goto errexpse1;
}
sfree(passphrase);
}
else {
} else {
key = pcpkey_decrypt(ptx, key, passwd);
if(key == NULL) {
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(ptx, &passphrase,
"Enter passphrase to encrypt the exported secret key",
@@ -269,170 +255,158 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor, char *pa
sfree(passphrase);
}
if(exported_sk != NULL) {
if(armor == 1) {
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);
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 {
} 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);
if (sk == NULL) {
fatal(ptx, "Could not find a key with id 0x%s in vault %s!\n", keyid,
vault->filename);
goto errpcpexpu1;
}
else {
} 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(ptx, &passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1, NULL);
"Enter passphrase to decrypt your secret key", NULL, 1,
NULL);
sk = pcpkey_decrypt(ptx, sk, passphrase);
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) {
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);
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
} 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) {
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);
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) {
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);
}
}
@@ -441,51 +415,56 @@ 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(ptx, &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)
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)
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) {
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) {
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");
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]?");
} 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) {
if (strncmp(yes, "yes", 1024) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET;
if(haveprimary) {
if (haveprimary) {
fprintf(stderr, "other type: %d\n", other->type);
other->type = PCP_KEY_TYPE_SECRET;
fprintf(stderr, " new type: %d\n", other->type);
@@ -496,40 +475,39 @@ void pcpedit_key(char *keyid) {
char *passphrase;
pcp_readpass(ptx, &passphrase,
"Enter new passphrase for key encryption (press enter to keep current)",
"Enter new passphrase for key encryption (press enter to "
"keep current)",
"Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) {
if (strnlen(passphrase, 1024) > 0) {
key = pcpkey_encrypt(ptx, key, passphrase);
sfree(passphrase);
}
if(key != NULL) {
if(debug)
if (key != NULL) {
if (debug)
pcp_dumpkey(key);
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;
@@ -538,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;
@@ -553,97 +530,95 @@ 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) {
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) {
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
} else
goto errimp2;
if(keysig != NULL) {
if(pcpvault_addkey(ptx, vault, keysig, keysig->type) != 0) {
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(ptx, &passphrase,
"Enter passphrase to decrypt the secret key file", NULL, 1, NULL);
"Enter passphrase to decrypt the secret key file", NULL, 1,
NULL);
sk = pcp_import_secret(ptx, buf, bufsize, passphrase);
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(ptx, &passphrase,
"Enter passphrase for key encryption",
pcp_readpass(ptx, &passphrase, "Enter passphrase for key encryption",
"Enter the passphrase again", 1, NULL);
if(strnlen(passphrase, 1024) > 0) {
if (strnlen(passphrase, 1024) > 0) {
/* encrypt the key */
sk = pcpkey_encrypt(ptx, sk, passphrase);
sfree(passphrase);
}
else {
} 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) {
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;
}
@@ -651,10 +626,10 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
}
}
if(sk != NULL) {
if (sk != NULL) {
/* store it to the vault if we got it til here */
if(pcp_sanitycheck_key(ptx, sk) == 0) {
if(pcp_storekey(sk) == 0) {
if (pcp_sanitycheck_key(ptx, sk) == 0) {
if (pcp_storekey(sk) == 0) {
pcpkey_printshortinfo(sk);
success = 0;
}
@@ -662,28 +637,27 @@ int pcp_import (vault_t *vault, FILE *in, char *passwd) {
}
}
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);

363
src/pcp.c
View File

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

View File

@@ -19,42 +19,42 @@
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 }' */
/* 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
@@ -82,15 +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

@@ -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;
}
@@ -48,17 +47,17 @@ int pcpz85_encode(char *infile, char *outfile) {
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

@@ -20,17 +20,20 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
pcp=../src/pcp1
pcp=../pcp
vault=v1
passwd=xxx
md5msg=66b8c4ca9e5d2a7e3c0559c3cdea3d50
os=$(uname)
. ./keys.cfg
check_dependencies_shell () {
if test "$os" = "FreeBSD"; then
cmd="which mdmfs"
expect="/mdmfs/"
check "$cmd" "$expect" "$input"
fi
}
check_dependencies_pcp () {
@@ -39,10 +42,16 @@ check_dependencies_pcp () {
check "$cmd" "$expect" "$input"
}
# this one only works on freebsd for my user. sorrry
# this one only works on freebsd for my user. sorry
check_vault_disk_full () {
if test "$os" = "FreeBSD"; then
sudo mdmfs -s 1M -w 1001:1001 md env && dd if=/dev/zero of=env/b bs=1024 count=700
cmd="./jot 100 | while read N; do if ! (echo a; echo b) | $pcp -V env/v1 -k -x x; then break; fi; done"
expect="/Failed to copy/"
check "$cmd" "$expect" "$input"
fi
}
prepare() {
:
}

View File

@@ -20,7 +20,7 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
pcp=../src/pcp1
pcp=../pcp
passwd=xxx
verbose=1

View File

@@ -1,5 +1,5 @@
#!/bin/sh
file=$1
../src/pcp1 -C $file | awk '{print $4}'
../pcp -C $file | awk '{print $4}'

54
tests/meson.build Normal file
View File

@@ -0,0 +1,54 @@
# -*-python-*-
# genheader statictest buffertest sample pipetest decodertest
fs = import('fs')
binaries = [
'gencheader',
'statictest',
'buffertest',
'sample',
'pipetest',
'decodertest',
'mangle',
'invalidkeys',
'pwhashes',
'streamtest',
]
configs = [
'cppunittests.cfg',
'iotests.cfg',
'jsonunittests.cfg',
'keys.cfg',
'pyunittests.cfg',
'stresstests.cfg',
'unittests.cfg',
'md5',
'jot',
'bart.pub',
'key-alicia-pub',
'key-alicia-sec',
'key-bobby-pub',
'key-bobby-sec'
]
foreach binary: binaries
executable(
binary,
binary + '.c',
include_directories: [pcp_inc],
dependencies: [libpcp_dep, pcp_deps],
)
endforeach
foreach config: configs
cp = fs.copyfile(config)
endforeach
unittest = find_program('unittests.sh', '.')
test('C tests', unittest, args : ['unittests.cfg'])
test('IO tests', unittest, args : ['iotests.cfg'])
test('JSON tests', unittest, args : ['jsonunittests.cfg'])

View File

@@ -1,13 +1,13 @@
#include <unistd.h>
#include <limits.h>
#include <sodium.h>
#include <stdio.h>
#include <stdlib.h>
#include <sodium.h>
#include <limits.h>
#include <unistd.h>
#include "mem.h"
#include "defines.h"
#include "keyprint.h"
#include "key.h"
#include "keyprint.h"
#include "mem.h"
struct _pw_t {
char hash[65];
@@ -24,28 +24,29 @@ int main() {
pw *list = NULL;
pw *have = NULL;
unsigned char nonce[32] = {1};
PCPCTX *ptx = ptx_new();
if(sodium_init() == -1) return 1;
if (sodium_init() == -1)
return 1;
for(i=97; i<126; ++i) {
for (i = 97; i < 126; ++i) {
pass[0] = i;
pass[1] = 0;
h = pcp_derivekey(pass, nonce);
h = pcp_derivekey(ptx, pass, nonce);
p =0;
for(t=0; t<32; ++t) {
p = 0;
for (t = 0; t < 32; ++t) {
sprintf(&tmp[p], "%02x", h[t]);
p += 2;
}
have = NULL;
HASH_FIND_STR(list, tmp, have);
if(have == NULL) {
if (have == NULL) {
item = ucmalloc(sizeof(pw));
memcpy(item->hash, tmp, 65);
HASH_ADD_STR( list, hash, item );
}
else {
HASH_ADD_STR(list, hash, item);
} else {
fprintf(stderr, "Error: collision found: %s!\n", have->hash);
return 1;
}

View File

@@ -20,7 +20,7 @@
# You can contact me by mail: <tlinden AT cpan DOT org>.
#
pcp=../src/pcp1
pcp=../pcp
vault=v1
passwd=ech9xeiT%CuxuH1ch-is2ies1R
md5msg=66b8c4ca9e5d2a7e3c0559c3cdea3d50
@@ -40,29 +40,29 @@ check_dependencies_pcp () {
}
check_streams_8 () {
md5=`./md5 ../COPYING`
cmd="./pipetest 8 e < ../COPYING | ./pipetest 8 d | ./md5"
md5=`./md5 ../../COPYING`
cmd="./pipetest 8 e < ../../COPYING | ./pipetest 8 d | ./md5"
expect="/$md5/"
check "$cmd" "$expect" "$input"
}
check_streams_16 () {
md5=`./md5 ../COPYING`
cmd="./pipetest 16 e < ../COPYING | ./pipetest 16 d | ./md5"
md5=`./md5 ../../COPYING`
cmd="./pipetest 16 e < ../../COPYING | ./pipetest 16 d | ./md5"
expect="/$md5/"
check "$cmd" "$expect" "$input"
}
check_streams_32 () {
md5=`./md5 ../COPYING`
cmd="./pipetest 32 e < ../COPYING | ./pipetest 32 d | ./md5"
md5=`./md5 ../../COPYING`
cmd="./pipetest 32 e < ../../COPYING | ./pipetest 32 d | ./md5"
expect="/$md5/"
check "$cmd" "$expect" "$input"
}
check_streams_64 () {
md5=`./md5 ../COPYING`
cmd="./pipetest 64 e < ../COPYING | ./pipetest 64 d | ./md5"
md5=`./md5 ../../COPYING`
cmd="./pipetest 64 e < ../../COPYING | ./pipetest 64 d | ./md5"
expect="/$md5/"
check "$cmd" "$expect" "$input"
}
@@ -284,27 +284,27 @@ check_sym_decrypt () {
#
# signature tests
check_sign_detached_to_bobby () {
cmd="$pcp -V va -g -I README -f testsig -x a"
cmd="$pcp -V va -g -I ../../COPYING -f testsig -x a"
expectfile="testsig"
expect=""
check "$cmd" "$expect" "$input" "$expectfile"
}
check_verify_detached_signature () {
cmd="$pcp -V vb -c -f testsig -I README -i $idalicia"
cmd="$pcp -V vb -c -f testsig -I ../../COPYING -i $idalicia"
expect="/verified/"
check "$cmd" "$expect" "$input"
}
check_verify_detached_signature_self () {
cmd="$pcp -V va -c -f testsig -I README"
cmd="$pcp -V va -c -f testsig -I ../../COPYING"
expect="/verified/"
check "$cmd" "$expect" "$input"
}
check_sign_armored_to_bobby () {
rm -f testsig
cmd="$pcp -V va -g -I README -O testsig -x a -z"
cmd="$pcp -V va -g -I ../../COPYING -O testsig -x a -z"
expectfile="testsig"
expect=""
check "$cmd" "$expect" "$input" "$expectfile"
@@ -324,7 +324,7 @@ check_verify_armored_signature_self () {
check_sign_bin_to_bobby () {
rm -f testsig
cmd="$pcp -V va -g -I README -O testsig -x a"
cmd="$pcp -V va -g -I ../../COPYING -O testsig -x a"
expectfile="testsig"
expect=""
check "$cmd" "$expect" "$input" "$expectfile"
@@ -345,7 +345,7 @@ check_verify_bin_signature_self () {
#
# sign+encrypt tests
check_sign_crypt_to_bobby () {
cmd="$pcp -V va -g -e -I README -O testsig -r Bobby -x a"
cmd="$pcp -V va -g -e -I ../../COPYING -O testsig -r Bobby -x a"
expect="/Encrypted/"
check "$cmd" "$expect" "$input"
}
@@ -572,26 +572,26 @@ check_fuzz_binary_seckey () {
# checksum tests
check_checksum_copying () {
cmd="$pcp -C ../COPYING"
cmd="$pcp -C ../../COPYING"
expect="/$blake2/"
check "$cmd" "$expect" "$input"
}
check_checksum_authenticated_copying () {
cmd="$pcp -x $key -C ../COPYING"
cmd="$pcp -x $key -C ../../COPYING"
expect="/$blake2auth/"
check "$cmd" "$expect" "$input"
}
check_checksum_copying_stdin () {
cmd="$pcp -C < ../COPYING"
cmd="$pcp -C < ../../COPYING"
expect="/$blake2/"
check "$cmd" "$expect" "$input"
}
check_checksum_multiple () {
cmd="$pcp -C ../COPYING ../README"
expect="/README/"
cmd="$pcp -C ../../COPYING ../../../COPYING"
expect="/../../COPYING/"
check "$cmd" "$expect" "$input"
}

View File

@@ -106,13 +106,23 @@ callcheck () {
cfg="$1"
check="$2"
pwd=$(pwd)
base=$(basename "$pwd")
if test "$base" != "test"; then
cd tests
fi
echo "PWD: $(pwd)"
if test -z "$cfg"; then
echo "Usage: $0 <config> [check]"
exit 1
fi
if ! test -e "$cfg"; then
echo "$cfg doesn't exist!"
echo "$cfg doesn't exist ($(pwd))!"
exit 1
fi