mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 03:50:57 +01:00
initial commit
This commit is contained in:
10
libpcp/Makefile.am
Normal file
10
libpcp/Makefile.am
Normal file
@@ -0,0 +1,10 @@
|
||||
AM_CFLAGS = -I../libpcp -Wall -g
|
||||
|
||||
lib_LTLIBRARIES = libpcp1.la
|
||||
|
||||
libpcp1_la_SOURCES = mac.c mem.c pad.c version.c warn.c \
|
||||
z85.c zmq_z85.c key.c randomart.c \
|
||||
vault.c fatal.c jenhash.c digital_crc32.c \
|
||||
crypto.c
|
||||
|
||||
include_HEADERS = ../include/pcp.h
|
||||
630
libpcp/Makefile.in
Normal file
630
libpcp/Makefile.in
Normal file
@@ -0,0 +1,630 @@
|
||||
# Makefile.in generated by automake 1.12.4 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2012 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__make_dryrun = \
|
||||
{ \
|
||||
am__dry=no; \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
|
||||
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
|
||||
*) \
|
||||
for am__flg in $$MAKEFLAGS; do \
|
||||
case $$am__flg in \
|
||||
*=*|--*) ;; \
|
||||
*n*) am__dry=yes; break;; \
|
||||
esac; \
|
||||
done;; \
|
||||
esac; \
|
||||
test $$am__dry = yes; \
|
||||
}
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = libpcp
|
||||
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/config/depcomp
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
|
||||
$(top_srcdir)/config/ltoptions.m4 \
|
||||
$(top_srcdir)/config/ltsugar.m4 \
|
||||
$(top_srcdir)/config/ltversion.m4 \
|
||||
$(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libpcp1_la_LIBADD =
|
||||
am_libpcp1_la_OBJECTS = mac.lo mem.lo pad.lo version.lo warn.lo z85.lo \
|
||||
zmq_z85.lo key.lo randomart.lo vault.lo fatal.lo jenhash.lo \
|
||||
digital_crc32.lo crypto.lo
|
||||
libpcp1_la_OBJECTS = $(am_libpcp1_la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(libpcp1_la_SOURCES)
|
||||
DIST_SOURCES = $(libpcp1_la_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
HEADERS = $(include_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AM_CFLAGS = -I../libpcp -Wall -g
|
||||
lib_LTLIBRARIES = libpcp1.la
|
||||
libpcp1_la_SOURCES = mac.c mem.c pad.c version.c warn.c \
|
||||
z85.c zmq_z85.c key.c randomart.c \
|
||||
vault.c fatal.c jenhash.c digital_crc32.c \
|
||||
crypto.c
|
||||
|
||||
include_HEADERS = ../include/pcp.h
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpcp/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu libpcp/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
config.h: stamp-h1
|
||||
@if test ! -f $@; then rm -f stamp-h1; else :; fi
|
||||
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
|
||||
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status libpcp/config.h
|
||||
$(srcdir)/config.h.in: $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||
list2=; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
list2="$$list2 $$p"; \
|
||||
else :; fi; \
|
||||
done; \
|
||||
test -z "$$list2" || { \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
|
||||
}
|
||||
|
||||
uninstall-libLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-libLTLIBRARIES:
|
||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||
@list='$(lib_LTLIBRARIES)'; \
|
||||
locs=`for p in $$list; do echo $$p; done | \
|
||||
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||
sort -u`; \
|
||||
test -z "$$locs" || { \
|
||||
echo rm -f $${locs}; \
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
libpcp1.la: $(libpcp1_la_OBJECTS) $(libpcp1_la_DEPENDENCIES) $(EXTRA_libpcp1_la_DEPENDENCIES)
|
||||
$(LINK) -rpath $(libdir) $(libpcp1_la_OBJECTS) $(libpcp1_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digital_crc32.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatal.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jenhash.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pad.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/randomart.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vault.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/warn.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/z85.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmq_z85.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-includeHEADERS: $(include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
|
||||
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
cscopelist: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-libLTLIBRARIES
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
|
||||
|
||||
.MAKE: all install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libLTLIBRARIES clean-libtool cscopelist ctags distclean \
|
||||
distclean-compile distclean-generic distclean-hdr \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am \
|
||||
install-includeHEADERS install-info install-info-am \
|
||||
install-libLTLIBRARIES install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags uninstall uninstall-am uninstall-includeHEADERS \
|
||||
uninstall-libLTLIBRARIES
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
149
libpcp/config.h.in
Normal file
149
libpcp/config.h.in
Normal file
@@ -0,0 +1,149 @@
|
||||
/* libpcp/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define to 1 if you have the <err.h> header file. */
|
||||
#undef HAVE_ERR_H
|
||||
|
||||
/* Define to 1 if you have the `fopen' function. */
|
||||
#undef HAVE_FOPEN
|
||||
|
||||
/* Define to 1 if you have the `fprintf' function. */
|
||||
#undef HAVE_FPRINTF
|
||||
|
||||
/* Define to 1 if you have the `fread' function. */
|
||||
#undef HAVE_FREAD
|
||||
|
||||
/* Define to 1 if you have the `free' function. */
|
||||
#undef HAVE_FREE
|
||||
|
||||
/* Define to 1 if you have the `fseek' function. */
|
||||
#undef HAVE_FSEEK
|
||||
|
||||
/* Define to 1 if you have the `ftruncate' function. */
|
||||
#undef HAVE_FTRUNCATE
|
||||
|
||||
/* Define to 1 if you have the `fwrite' function. */
|
||||
#undef HAVE_FWRITE
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `isatty' function. */
|
||||
#undef HAVE_ISATTY
|
||||
|
||||
/* Define to 1 if you have the `sodium' library (-lsodium). */
|
||||
#undef HAVE_LIBSODIUM
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the `malloc' function. */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the `perror' function. */
|
||||
#undef HAVE_PERROR
|
||||
|
||||
/* Define to 1 if you have the `sizeof' function. */
|
||||
#undef HAVE_SIZEOF
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlen' function. */
|
||||
#undef HAVE_STRLEN
|
||||
|
||||
/* Define to 1 if you have the `strnlen' function. */
|
||||
#undef HAVE_STRNLEN
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#undef HAVE_STRTOL
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the `tcgetattr' function. */
|
||||
#undef HAVE_TCGETATTR
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the `umask' function. */
|
||||
#undef HAVE_UMASK
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
133
libpcp/crypto.c
Normal file
133
libpcp/crypto.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "crypto.h"
|
||||
|
||||
size_t pcp_sodium_box(unsigned char **cipher,
|
||||
unsigned char *cleartext,
|
||||
size_t clearsize,
|
||||
unsigned char *nonce,
|
||||
unsigned char *secret,
|
||||
unsigned char *public) {
|
||||
|
||||
unsigned char *pad_clear;
|
||||
unsigned char *pad_cipher;
|
||||
|
||||
size_t ciphersize = (clearsize + crypto_box_ZEROBYTES) - crypto_box_BOXZEROBYTES; // $s + 32 -16
|
||||
|
||||
pad_cipher = ucmalloc(crypto_box_ZEROBYTES + clearsize);
|
||||
pcp_pad_prepend(&pad_clear, cleartext, crypto_box_ZEROBYTES, clearsize);
|
||||
|
||||
// crypto_box(c,m,mlen,n,pk,sk);
|
||||
crypto_box(pad_cipher, pad_clear,
|
||||
clearsize + crypto_box_ZEROBYTES, nonce, public, secret);
|
||||
|
||||
pcp_pad_remove(cipher, pad_cipher, crypto_secretbox_BOXZEROBYTES, ciphersize);
|
||||
|
||||
free(pad_clear);
|
||||
free(pad_cipher);
|
||||
|
||||
return ciphersize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pcp_sodium_verify_box(unsigned char **cleartext, unsigned char* message,
|
||||
size_t messagesize, unsigned char *nonce,
|
||||
unsigned char *secret, unsigned char *public) {
|
||||
// verify/decrypt the box
|
||||
unsigned char *pad_cipher;
|
||||
unsigned char *pad_clear;
|
||||
int success = -1;
|
||||
|
||||
pcp_pad_prepend(&pad_cipher, message, crypto_box_BOXZEROBYTES, messagesize);
|
||||
pad_clear = (unsigned char *)ucmalloc((crypto_box_ZEROBYTES+ messagesize));
|
||||
|
||||
// crypto_box_open(m,c,clen,n,pk,sk);
|
||||
if (crypto_box_open(pad_clear, pad_cipher,
|
||||
messagesize + crypto_box_BOXZEROBYTES,
|
||||
nonce, public, secret) == 0) {
|
||||
success = 0;
|
||||
}
|
||||
|
||||
pcp_pad_remove(cleartext, pad_clear, crypto_box_ZEROBYTES, messagesize);
|
||||
|
||||
free(pad_clear);
|
||||
free(pad_cipher);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned char *pcp_box_encrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
||||
unsigned char *message, size_t messagesize,
|
||||
size_t *csize) {
|
||||
|
||||
unsigned char *nonce = pcp_gennonce();
|
||||
unsigned char *cipher;
|
||||
|
||||
size_t es = pcp_sodium_box(&cipher, message, messagesize, nonce,
|
||||
secret->secret, public->public);
|
||||
|
||||
if(es <= messagesize) {
|
||||
fatal("failed to encrypt message!\n");
|
||||
goto errbec;
|
||||
}
|
||||
|
||||
// put nonce and cipher together
|
||||
unsigned char *combined = ucmalloc(es + crypto_secretbox_NONCEBYTES);
|
||||
memcpy(combined, nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(&combined[crypto_secretbox_NONCEBYTES], cipher, es);
|
||||
|
||||
free(cipher);
|
||||
free(nonce);
|
||||
|
||||
*csize = es + crypto_secretbox_NONCEBYTES;
|
||||
|
||||
return combined;
|
||||
|
||||
errbec:
|
||||
if(cipher != NULL)
|
||||
free(cipher);
|
||||
free(nonce);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
unsigned char *pcp_box_decrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
||||
unsigned char *cipher, size_t ciphersize,
|
||||
size_t *dsize) {
|
||||
|
||||
unsigned char *message = NULL;
|
||||
|
||||
unsigned char *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
|
||||
unsigned char *cipheronly = ucmalloc(ciphersize - crypto_secretbox_NONCEBYTES);
|
||||
|
||||
memcpy(nonce, cipher, crypto_secretbox_NONCEBYTES);
|
||||
memcpy(cipheronly, &cipher[crypto_secretbox_NONCEBYTES],
|
||||
ciphersize - crypto_secretbox_NONCEBYTES);
|
||||
|
||||
if(pcp_sodium_verify_box(&message, cipheronly,
|
||||
ciphersize - crypto_secretbox_NONCEBYTES,
|
||||
nonce, secret->secret, public->public) != 0){
|
||||
fatal("failed to decrypt message!\n");
|
||||
goto errbed;
|
||||
}
|
||||
|
||||
free(nonce);
|
||||
free(cipheronly);
|
||||
|
||||
// resulting size:
|
||||
// ciphersize - crypto_secretbox_ZEROBYTES
|
||||
*dsize = ciphersize - crypto_secretbox_ZEROBYTES;
|
||||
return message;
|
||||
|
||||
errbed:
|
||||
free(nonce);
|
||||
free(cipheronly);
|
||||
if(message != NULL)
|
||||
free(message);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
33
libpcp/crypto.h
Normal file
33
libpcp/crypto.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _HAVE_PCP_CRYPTO_H
|
||||
#define _HAVE_PCP_CRYPTO_H
|
||||
|
||||
#include <sodium.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sodium.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "mem.h"
|
||||
#include "key.h"
|
||||
|
||||
size_t pcp_sodium_box(unsigned char **cipher,
|
||||
unsigned char *cleartext,
|
||||
size_t clearsize,
|
||||
unsigned char *nonce,
|
||||
unsigned char *secret,
|
||||
unsigned char *public);
|
||||
|
||||
int pcp_sodium_verify_box(unsigned char **cleartext, unsigned char* message,
|
||||
size_t messagesize, unsigned char *nonce,
|
||||
unsigned char *secret, unsigned char *public);
|
||||
|
||||
unsigned char *pcp_box_encrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
||||
unsigned char *message, size_t messagesize,
|
||||
size_t *csize);
|
||||
|
||||
unsigned char *pcp_box_decrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
||||
unsigned char *cipher, size_t ciphersize,
|
||||
size_t *dsize);
|
||||
|
||||
#endif // _HAVE_PCP_CRYPTO_H
|
||||
50
libpcp/defines.h
Normal file
50
libpcp/defines.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef _DEFINES_H
|
||||
#define _DEFINES_H
|
||||
|
||||
typedef unsigned char byte; // Single unsigned byte = 8 bits
|
||||
typedef unsigned short dbyte; // Double byte = 16 bits
|
||||
typedef unsigned int qbyte; // Quad byte = 32 bits
|
||||
|
||||
// key stuff
|
||||
#define PCP_KEY_HEADER "----- BEGIN PCP SECRET KEY -----"
|
||||
#define PCP_KEY_FOOTER "------ END PCP SECRET KEY ------"
|
||||
|
||||
#define PCP_PUBKEY_HEADER "----- BEGIN PCP PUBLIC KEY -----"
|
||||
#define PCP_PUBKEY_FOOTER "------ END PCP PUBLICKEY ------"
|
||||
|
||||
#define PCP_ENFILE_HEADER "----- BEGIN PCP ENCRYPTED FILE -----"
|
||||
#define PCP_ENFILE_FOOTER "------ END PCP ENCRYPTED FILE ------"
|
||||
|
||||
#define PCP_ZFILE_HEADER "----- BEGIN Z85 ENCODED FILE -----"
|
||||
#define PCP_ZFILE_FOOTER "------ END Z85 ENCODED FILE ------"
|
||||
|
||||
#define PCP_ME "Pretty Curved Privacy"
|
||||
|
||||
#define PCP_KEY_VERSION 0x00000001U
|
||||
#define PCP_KEY_PRIMITIVE "CURVE25519-ED25519-SALSA20-POLY1305"
|
||||
|
||||
#define PCP_KEY_TYPE_MAINSECRET 0x01
|
||||
#define PCP_KEY_TYPE_SECRET 0x02
|
||||
#define PCP_KEY_TYPE_PUBLIC 0x03
|
||||
|
||||
// how many times do we hash a passphrase
|
||||
#define HCYCLES 128000
|
||||
|
||||
// save typing, dammit
|
||||
#define PCP_ENCRYPT_PAD crypto_secretbox_ZEROBYTES + crypto_secretbox_NONCEBYTES
|
||||
|
||||
// vault id
|
||||
#define PCP_VAULT_ID 0xC4
|
||||
#define PCP_VAULT_VERSION 0x01
|
||||
|
||||
char *PCP_ERR;
|
||||
byte PCP_ERRSET;
|
||||
int PCP_EXIT;
|
||||
|
||||
//set error
|
||||
void fatal(const char * fmt, ...);
|
||||
|
||||
// fetch error
|
||||
void fatals_ifany();
|
||||
|
||||
#endif // _DEFINES_H
|
||||
119
libpcp/digital_crc32.c
Normal file
119
libpcp/digital_crc32.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2005,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See also ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-V42] for a formal specification.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <digital_crc32.h>
|
||||
|
||||
|
||||
// Automatically generated CRC function
|
||||
// polynomial: 0x104C11DB7
|
||||
unsigned int
|
||||
digital_update_crc32(unsigned int crc, const unsigned char *data, size_t len)
|
||||
{
|
||||
static const unsigned int table[256] = {
|
||||
0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U,
|
||||
0x130476DCU,0x17C56B6BU,0x1A864DB2U,0x1E475005U,
|
||||
0x2608EDB8U,0x22C9F00FU,0x2F8AD6D6U,0x2B4BCB61U,
|
||||
0x350C9B64U,0x31CD86D3U,0x3C8EA00AU,0x384FBDBDU,
|
||||
0x4C11DB70U,0x48D0C6C7U,0x4593E01EU,0x4152FDA9U,
|
||||
0x5F15ADACU,0x5BD4B01BU,0x569796C2U,0x52568B75U,
|
||||
0x6A1936C8U,0x6ED82B7FU,0x639B0DA6U,0x675A1011U,
|
||||
0x791D4014U,0x7DDC5DA3U,0x709F7B7AU,0x745E66CDU,
|
||||
0x9823B6E0U,0x9CE2AB57U,0x91A18D8EU,0x95609039U,
|
||||
0x8B27C03CU,0x8FE6DD8BU,0x82A5FB52U,0x8664E6E5U,
|
||||
0xBE2B5B58U,0xBAEA46EFU,0xB7A96036U,0xB3687D81U,
|
||||
0xAD2F2D84U,0xA9EE3033U,0xA4AD16EAU,0xA06C0B5DU,
|
||||
0xD4326D90U,0xD0F37027U,0xDDB056FEU,0xD9714B49U,
|
||||
0xC7361B4CU,0xC3F706FBU,0xCEB42022U,0xCA753D95U,
|
||||
0xF23A8028U,0xF6FB9D9FU,0xFBB8BB46U,0xFF79A6F1U,
|
||||
0xE13EF6F4U,0xE5FFEB43U,0xE8BCCD9AU,0xEC7DD02DU,
|
||||
0x34867077U,0x30476DC0U,0x3D044B19U,0x39C556AEU,
|
||||
0x278206ABU,0x23431B1CU,0x2E003DC5U,0x2AC12072U,
|
||||
0x128E9DCFU,0x164F8078U,0x1B0CA6A1U,0x1FCDBB16U,
|
||||
0x018AEB13U,0x054BF6A4U,0x0808D07DU,0x0CC9CDCAU,
|
||||
0x7897AB07U,0x7C56B6B0U,0x71159069U,0x75D48DDEU,
|
||||
0x6B93DDDBU,0x6F52C06CU,0x6211E6B5U,0x66D0FB02U,
|
||||
0x5E9F46BFU,0x5A5E5B08U,0x571D7DD1U,0x53DC6066U,
|
||||
0x4D9B3063U,0x495A2DD4U,0x44190B0DU,0x40D816BAU,
|
||||
0xACA5C697U,0xA864DB20U,0xA527FDF9U,0xA1E6E04EU,
|
||||
0xBFA1B04BU,0xBB60ADFCU,0xB6238B25U,0xB2E29692U,
|
||||
0x8AAD2B2FU,0x8E6C3698U,0x832F1041U,0x87EE0DF6U,
|
||||
0x99A95DF3U,0x9D684044U,0x902B669DU,0x94EA7B2AU,
|
||||
0xE0B41DE7U,0xE4750050U,0xE9362689U,0xEDF73B3EU,
|
||||
0xF3B06B3BU,0xF771768CU,0xFA325055U,0xFEF34DE2U,
|
||||
0xC6BCF05FU,0xC27DEDE8U,0xCF3ECB31U,0xCBFFD686U,
|
||||
0xD5B88683U,0xD1799B34U,0xDC3ABDEDU,0xD8FBA05AU,
|
||||
0x690CE0EEU,0x6DCDFD59U,0x608EDB80U,0x644FC637U,
|
||||
0x7A089632U,0x7EC98B85U,0x738AAD5CU,0x774BB0EBU,
|
||||
0x4F040D56U,0x4BC510E1U,0x46863638U,0x42472B8FU,
|
||||
0x5C007B8AU,0x58C1663DU,0x558240E4U,0x51435D53U,
|
||||
0x251D3B9EU,0x21DC2629U,0x2C9F00F0U,0x285E1D47U,
|
||||
0x36194D42U,0x32D850F5U,0x3F9B762CU,0x3B5A6B9BU,
|
||||
0x0315D626U,0x07D4CB91U,0x0A97ED48U,0x0E56F0FFU,
|
||||
0x1011A0FAU,0x14D0BD4DU,0x19939B94U,0x1D528623U,
|
||||
0xF12F560EU,0xF5EE4BB9U,0xF8AD6D60U,0xFC6C70D7U,
|
||||
0xE22B20D2U,0xE6EA3D65U,0xEBA91BBCU,0xEF68060BU,
|
||||
0xD727BBB6U,0xD3E6A601U,0xDEA580D8U,0xDA649D6FU,
|
||||
0xC423CD6AU,0xC0E2D0DDU,0xCDA1F604U,0xC960EBB3U,
|
||||
0xBD3E8D7EU,0xB9FF90C9U,0xB4BCB610U,0xB07DABA7U,
|
||||
0xAE3AFBA2U,0xAAFBE615U,0xA7B8C0CCU,0xA379DD7BU,
|
||||
0x9B3660C6U,0x9FF77D71U,0x92B45BA8U,0x9675461FU,
|
||||
0x8832161AU,0x8CF30BADU,0x81B02D74U,0x857130C3U,
|
||||
0x5D8A9099U,0x594B8D2EU,0x5408ABF7U,0x50C9B640U,
|
||||
0x4E8EE645U,0x4A4FFBF2U,0x470CDD2BU,0x43CDC09CU,
|
||||
0x7B827D21U,0x7F436096U,0x7200464FU,0x76C15BF8U,
|
||||
0x68860BFDU,0x6C47164AU,0x61043093U,0x65C52D24U,
|
||||
0x119B4BE9U,0x155A565EU,0x18197087U,0x1CD86D30U,
|
||||
0x029F3D35U,0x065E2082U,0x0B1D065BU,0x0FDC1BECU,
|
||||
0x3793A651U,0x3352BBE6U,0x3E119D3FU,0x3AD08088U,
|
||||
0x2497D08DU,0x2056CD3AU,0x2D15EBE3U,0x29D4F654U,
|
||||
0xC5A92679U,0xC1683BCEU,0xCC2B1D17U,0xC8EA00A0U,
|
||||
0xD6AD50A5U,0xD26C4D12U,0xDF2F6BCBU,0xDBEE767CU,
|
||||
0xE3A1CBC1U,0xE760D676U,0xEA23F0AFU,0xEEE2ED18U,
|
||||
0xF0A5BD1DU,0xF464A0AAU,0xF9278673U,0xFDE69BC4U,
|
||||
0x89B8FD09U,0x8D79E0BEU,0x803AC667U,0x84FBDBD0U,
|
||||
0x9ABC8BD5U,0x9E7D9662U,0x933EB0BBU,0x97FFAD0CU,
|
||||
0xAFB010B1U,0xAB710D06U,0xA6322BDFU,0xA2F33668U,
|
||||
0xBCB4666DU,0xB8757BDAU,0xB5365D03U,0xB1F740B4U,
|
||||
};
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
digital_crc32(const unsigned char *buf, size_t len)
|
||||
{
|
||||
return digital_update_crc32(0xffffffff, buf, len) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
43
libpcp/digital_crc32.h
Normal file
43
libpcp/digital_crc32.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2005,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_DIGITAL_CRC32_H
|
||||
#define INCLUDED_DIGITAL_CRC32_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*!
|
||||
* \brief update running CRC-32
|
||||
* \ingroup misc
|
||||
*
|
||||
* Update a running CRC with the bytes buf[0..len-1] The CRC should be
|
||||
* initialized to all 1's, and the transmitted value is the 1's
|
||||
* complement of the final running CRC. The resulting CRC should be
|
||||
* transmitted in big endian order.
|
||||
*/
|
||||
unsigned int
|
||||
digital_update_crc32(unsigned int crc, const unsigned char *buf, size_t len);
|
||||
|
||||
unsigned int
|
||||
digital_crc32(const unsigned char *buf, size_t len);
|
||||
|
||||
#endif /* INCLUDED_CRC32_H */
|
||||
29
libpcp/fatal.c
Normal file
29
libpcp/fatal.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "defines.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void fatal(const char * fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vasprintf(&PCP_ERR, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
PCP_ERRSET = 1;
|
||||
}
|
||||
|
||||
void fatals_ifany() {
|
||||
if(PCP_ERRSET == 1) {
|
||||
fprintf(stderr, PCP_ERR);
|
||||
if(errno) {
|
||||
fprintf(stderr, "Error: %s\n", strerror(errno));
|
||||
}
|
||||
free(PCP_ERR);
|
||||
PCP_EXIT = 1;
|
||||
}
|
||||
}
|
||||
57
libpcp/getpass.c
Normal file
57
libpcp/getpass.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "getpass.h"
|
||||
|
||||
|
||||
/*
|
||||
* (unportable) functions to turn on/off terminal echo
|
||||
* using termios functions. might compile however on
|
||||
* most unices, tested on FreeBSD only.
|
||||
*/
|
||||
|
||||
static struct termios stored_settings;
|
||||
|
||||
void pcp_echo_off() {
|
||||
struct termios new_settings;
|
||||
tcgetattr(0,&stored_settings);
|
||||
new_settings = stored_settings;
|
||||
new_settings.c_lflag &= (~ECHO);
|
||||
tcsetattr(0,TCSANOW,&new_settings);
|
||||
}
|
||||
|
||||
void pcp_echo_on() {
|
||||
tcsetattr(0,TCSANOW,&stored_settings);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* read a line from stdin, return without
|
||||
* trailing \n or NULL if something went
|
||||
* wrong
|
||||
*/
|
||||
char *pcp_get_stdin() {
|
||||
char *line = NULL;
|
||||
size_t linecap = 0;
|
||||
ssize_t linelen;
|
||||
linelen = getline(&line, &linecap, stdin);
|
||||
|
||||
if (linelen < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
line[linelen - 1] = '\0'; // remove newline at end
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn off terminal echo, ask for a passphrase
|
||||
* and turn it on again
|
||||
*/
|
||||
char * pcp_get_passphrase(char *prompt) {
|
||||
printf("%s: ", prompt);
|
||||
pcp_echo_off();
|
||||
char *line = pcp_get_stdin();
|
||||
pcp_echo_on();
|
||||
printf("\n");
|
||||
return line;
|
||||
}
|
||||
|
||||
22
libpcp/getpass.h
Normal file
22
libpcp/getpass.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _HAVE_PCP_GETPASS
|
||||
#define _HAVE_PCP_GETPASS
|
||||
|
||||
/*
|
||||
* (unportable) functions to turn on/off terminal echo
|
||||
* using termios functions. might compile however on
|
||||
* most unices, tested on FreeBSD only.
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
|
||||
void pcp_echo_off();
|
||||
void pcp_echo_on();
|
||||
char *pcp_get_stdin();
|
||||
char *pcp_get_passphrase(char *prompt);
|
||||
|
||||
#endif // _HAVE_PCP_GETPASS
|
||||
48
libpcp/jenhash.c
Normal file
48
libpcp/jenhash.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "jenhash.h"
|
||||
|
||||
unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval ) {
|
||||
unsigned a, b;
|
||||
unsigned c = initval;
|
||||
unsigned len = length;
|
||||
|
||||
a = b = 0x9e3779b9;
|
||||
|
||||
while ( len >= 12 ) {
|
||||
a += ( k[0] + ( (unsigned)k[1] << 8 )
|
||||
+ ( (unsigned)k[2] << 16 )
|
||||
+ ( (unsigned)k[3] << 24 ) );
|
||||
b += ( k[4] + ( (unsigned)k[5] << 8 )
|
||||
+ ( (unsigned)k[6] << 16 )
|
||||
+ ( (unsigned)k[7] << 24 ) );
|
||||
c += ( k[8] + ( (unsigned)k[9] << 8 )
|
||||
+ ( (unsigned)k[10] << 16 )
|
||||
+ ( (unsigned)k[11] << 24 ) );
|
||||
|
||||
jen_mix ( a, b, c );
|
||||
|
||||
k += 12;
|
||||
len -= 12;
|
||||
}
|
||||
|
||||
c += length;
|
||||
|
||||
switch ( len ) {
|
||||
case 11: c += ( (unsigned)k[10] << 24 );
|
||||
case 10: c += ( (unsigned)k[9] << 16 );
|
||||
case 9 : c += ( (unsigned)k[8] << 8 );
|
||||
/* First byte of c reserved for length */
|
||||
case 8 : b += ( (unsigned)k[7] << 24 );
|
||||
case 7 : b += ( (unsigned)k[6] << 16 );
|
||||
case 6 : b += ( (unsigned)k[5] << 8 );
|
||||
case 5 : b += k[4];
|
||||
case 4 : a += ( (unsigned)k[3] << 24 );
|
||||
case 3 : a += ( (unsigned)k[2] << 16 );
|
||||
case 2 : a += ( (unsigned)k[1] << 8 );
|
||||
case 1 : a += k[0];
|
||||
}
|
||||
|
||||
jen_mix ( a, b, c );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
25
libpcp/jenhash.h
Normal file
25
libpcp/jenhash.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _HAVE_JENHASH_H
|
||||
#define _HAVE_JENHASH_H
|
||||
|
||||
// Bob Jenkins 32bit hash function
|
||||
// via: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||
|
||||
#define jen_mix(a,b,c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
}
|
||||
|
||||
#define JEN_PSALT 0xD9A03
|
||||
#define JEN_SSALT 0xC503B
|
||||
|
||||
unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval );
|
||||
|
||||
#endif // _HAVE_JENHASH_H
|
||||
199
libpcp/key.c
Normal file
199
libpcp/key.c
Normal file
@@ -0,0 +1,199 @@
|
||||
#include "key.h"
|
||||
|
||||
char *pcp_getkeyid(pcp_key_t *k) {
|
||||
uint32_t s, p;
|
||||
p = jen_hash(k->public, 32, JEN_PSALT);
|
||||
s = jen_hash(k->secret, 32, JEN_SSALT);
|
||||
char *id = ucmalloc(17);
|
||||
snprintf(id, 17, "%08X%08X", p, s);
|
||||
return id;
|
||||
}
|
||||
|
||||
pcp_key_t * pcpkey_new () {
|
||||
byte public[32] = { 0 };
|
||||
byte secret[32] = { 0 };
|
||||
|
||||
// generate curve 25519 keypair
|
||||
if(crypto_box_keypair (public, secret) != 0) {
|
||||
fatal("Failed to generate a CURVE25519 keypair!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fill in our struct
|
||||
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
|
||||
memcpy (key->public, public, 32);
|
||||
memcpy (key->secret, secret, 32);
|
||||
memcpy (key->id, pcp_getkeyid(key), 17);
|
||||
|
||||
key->ctime = (long)time(0);
|
||||
|
||||
key->version = PCP_KEY_VERSION;
|
||||
key->serial = arc4random();
|
||||
key->type = PCP_KEY_TYPE_SECRET;
|
||||
return key;
|
||||
}
|
||||
|
||||
unsigned char * pcp_gennonce() {
|
||||
unsigned char *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
|
||||
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
pcp_key_t *pcpkey_encrypt(pcp_key_t *key, char *passphrase) {
|
||||
if(key->nonce[0] == 0) {
|
||||
unsigned char *nonce = pcp_gennonce();
|
||||
memcpy (key->nonce, nonce, crypto_secretbox_NONCEBYTES);
|
||||
}
|
||||
|
||||
unsigned char *encryptkey = pcp_derivekey(passphrase);
|
||||
|
||||
unsigned char *encrypted;
|
||||
size_t es;
|
||||
|
||||
es = pcp_sodium_mac(&encrypted, key->secret, 32, key->nonce, encryptkey);
|
||||
|
||||
bzero(encryptkey, 32);
|
||||
free(encryptkey);
|
||||
|
||||
if(es == 48) {
|
||||
// success
|
||||
memcpy(key->encrypted, encrypted, 48);
|
||||
arc4random_buf(key->secret, 32);
|
||||
key->secret[0] = 0;
|
||||
}
|
||||
else {
|
||||
fatal("failed to encrypt the secret key!\n");
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
pcp_key_t *pcpkey_decrypt(pcp_key_t *key, char *passphrase) {
|
||||
unsigned char *encryptkey = pcp_derivekey(passphrase);
|
||||
unsigned char *decrypted;
|
||||
size_t es;
|
||||
|
||||
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, 48, key->nonce, encryptkey);
|
||||
|
||||
bzero(encryptkey, 32);
|
||||
free(encryptkey);
|
||||
|
||||
if(es == 0) {
|
||||
// success
|
||||
memcpy(key->secret, decrypted, 32);
|
||||
}
|
||||
else {
|
||||
fatal("failed to decrypt the secret key (got %d, expected 32)!\n", es);
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key) {
|
||||
//pcp_dumpkey(key);
|
||||
pcp_pubkey_t *pub = urmalloc(sizeof (pcp_pubkey_t));
|
||||
memcpy(pub->public, key->public, 32);
|
||||
memcpy(pub->owner, key->owner, 255);
|
||||
memcpy(pub->mail, key->mail, 255);
|
||||
memcpy(pub->id, key->id, 17);
|
||||
pub->version = key->version;
|
||||
pub->type = PCP_KEY_TYPE_PUBLIC;
|
||||
pub->ctime = key->ctime;
|
||||
return pub;
|
||||
}
|
||||
|
||||
char *pcppubkey_get_art(pcp_pubkey_t *k) {
|
||||
char *r = key_fingerprint_randomart(k->public, sizeof(k));
|
||||
return r;
|
||||
}
|
||||
|
||||
char *pcpkey_get_art(pcp_key_t *k) {
|
||||
char *r = key_fingerprint_randomart(k->public, sizeof(k));
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned char *pcppubkey_getchecksum(pcp_pubkey_t *k) {
|
||||
unsigned char *hash = ucmalloc(32);
|
||||
crypto_hash_sha256(hash, k->public, 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
unsigned char *pcpkey_getchecksum(pcp_key_t *k) {
|
||||
unsigned char *hash = ucmalloc(32);
|
||||
crypto_hash_sha256(hash, k->public, 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcp_inithashes() {
|
||||
pcpkey_hash = NULL;
|
||||
pcppubkey_hash = NULL;
|
||||
}
|
||||
|
||||
void pcp_cleanhashes() {
|
||||
if(pcpkey_hash != NULL) {
|
||||
pcp_key_t *current_key, *tmp;
|
||||
HASH_ITER(hh, pcpkey_hash, current_key, tmp) {
|
||||
HASH_DEL(pcpkey_hash,current_key);
|
||||
bzero(current_key, sizeof(pcp_key_t));
|
||||
free(current_key); // FIXME: coredumps here after n-th secret keys has been added
|
||||
}
|
||||
}
|
||||
|
||||
if(pcppubkey_hash != NULL) {
|
||||
pcp_pubkey_t *current_pub, *ptmp;
|
||||
HASH_ITER(hh, pcppubkey_hash, current_pub, ptmp) {
|
||||
HASH_DEL(pcppubkey_hash,current_pub);
|
||||
bzero(current_pub, sizeof(pcp_pubkey_t));
|
||||
free(current_pub);
|
||||
}
|
||||
}
|
||||
pcp_inithashes();
|
||||
}
|
||||
|
||||
pcp_key_t *pcpkey_exists(char *id) {
|
||||
pcp_key_t *key = NULL;
|
||||
HASH_FIND_STR(pcpkey_hash, id, key);
|
||||
return key; // maybe NULL!
|
||||
}
|
||||
|
||||
pcp_pubkey_t *pcppubkey_exists(char *id) {
|
||||
pcp_pubkey_t *key = NULL;
|
||||
HASH_FIND_STR(pcppubkey_hash, id, key);
|
||||
return key; // maybe NULL!
|
||||
}
|
||||
|
||||
pcp_key_t * key2be(pcp_key_t *k) {
|
||||
k->version = htobe32(k->version);
|
||||
k->serial = htobe32(k->serial);
|
||||
k->ctime = htobe64(k->ctime);
|
||||
return k;
|
||||
}
|
||||
|
||||
pcp_key_t *key2native(pcp_key_t *k) {
|
||||
k->version = be32toh(k->version);
|
||||
k->serial = be32toh(k->serial);
|
||||
k->ctime = be64toh(k->ctime);
|
||||
return k;
|
||||
}
|
||||
|
||||
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k) {
|
||||
k->version = htobe32(k->version);
|
||||
k->serial = htobe32(k->serial);
|
||||
k->ctime = htobe64(k->ctime);
|
||||
return k;
|
||||
}
|
||||
|
||||
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k) {
|
||||
k->version = be32toh(k->version);
|
||||
k->serial = be32toh(k->serial);
|
||||
k->ctime = be64toh(k->ctime);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
120
libpcp/key.h
Normal file
120
libpcp/key.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef _HAVE_PCP_KEYPAIR_H
|
||||
#define _HAVE_PCP_KEYPAIR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sodium.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/endian.h> // FIXME: put portable thing from scrypt here
|
||||
|
||||
#include "defines.h"
|
||||
#include "mem.h"
|
||||
#include "mac.h"
|
||||
#include "randomart.h"
|
||||
#include "version.h"
|
||||
#include "z85.h"
|
||||
#include "uthash.h"
|
||||
#include "jenhash.h"
|
||||
|
||||
/*
|
||||
PCP private key structure. Most fields are self explanatory.
|
||||
Some notes:
|
||||
|
||||
'encrypted' contains the encrypted secret key. If it's set,
|
||||
the field 'secret' which contains the clear secret key will
|
||||
be zeroed with random values, the first byte will be 0.
|
||||
|
||||
'nonce' contains the nonce required to decrypt the encrypted
|
||||
secret, if set.
|
||||
|
||||
'serial' is a random number.
|
||||
|
||||
'id' is a string containing the hex values of the CRC32 checksum
|
||||
of the public and secret key.
|
||||
|
||||
Upon creation everything will be filled with random bytes.
|
||||
String fields will contain a string followed by 0 followed
|
||||
by the rest of the pre-filled random bytes. To denote a string
|
||||
field as empty, the first byte will be set to 0.
|
||||
|
||||
There are dynamically calculated attributes as well:
|
||||
|
||||
'checksum' is a 256 bit SHA hash of the public key returned
|
||||
by pcpkey_getchecksum() or pcppubkey_getchecksum().
|
||||
|
||||
'random id' is a random art ascii image returned by
|
||||
pcppubkey_get_art() or pcpkey_get_art(), calculated from
|
||||
the public key.
|
||||
|
||||
If exported to a single file or printed, the structure will
|
||||
be encoded using Z85 encoding.
|
||||
|
||||
*/
|
||||
struct _pcp_key_t {
|
||||
byte public[32];
|
||||
byte secret[32];
|
||||
byte nonce[24];
|
||||
byte encrypted[48];
|
||||
char owner[255];
|
||||
char mail[255];
|
||||
char id[17];
|
||||
long ctime;
|
||||
uint32_t version;
|
||||
uint32_t serial;
|
||||
uint8_t type;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct _pcp_pubkey_t {
|
||||
byte public[32];
|
||||
char owner[255];
|
||||
char mail[255];
|
||||
char id[17];
|
||||
long ctime;
|
||||
uint32_t version;
|
||||
uint32_t serial;
|
||||
uint8_t type;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
typedef struct _pcp_key_t pcp_key_t;
|
||||
typedef struct _pcp_pubkey_t pcp_pubkey_t;
|
||||
|
||||
pcp_key_t *pcpkey_hash;
|
||||
pcp_pubkey_t *pcppubkey_hash;
|
||||
|
||||
void pcp_cleanhashes();
|
||||
pcp_key_t *pcpkey_new ();
|
||||
|
||||
char *pcppubkey_get_art(pcp_pubkey_t *k);
|
||||
char *pcpkey_get_art(pcp_key_t *k);
|
||||
|
||||
pcp_key_t *pcpkey_encrypt(pcp_key_t *key, char *passphrase);
|
||||
pcp_key_t *pcpkey_decrypt(pcp_key_t *key, char *passphrase);
|
||||
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key);
|
||||
char *pcp_getkeyid(pcp_key_t *k);
|
||||
unsigned char *pcppubkey_getchecksum(pcp_pubkey_t *k);
|
||||
unsigned char *pcpkey_getchecksum(pcp_key_t *k);
|
||||
void pcp_inithashes();
|
||||
|
||||
pcp_key_t *pcpkey_exists(char *id);
|
||||
pcp_pubkey_t *pcppubkey_exists(char *id);
|
||||
|
||||
pcp_key_t * key2be(pcp_key_t *k);
|
||||
pcp_key_t *key2native(pcp_key_t *k);
|
||||
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
|
||||
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
|
||||
|
||||
unsigned char * pcp_gennonce();
|
||||
|
||||
void pcpedit_key(char *keyid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _HAVE_PCP_KEYPAIR_H
|
||||
97
libpcp/mac.c
Normal file
97
libpcp/mac.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "mac.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned char *pcp_derivekey(char *passphrase) {
|
||||
unsigned char *hash64 = ucmalloc(crypto_hash_BYTES);
|
||||
unsigned char *xor = ucmalloc(crypto_secretbox_KEYBYTES);
|
||||
unsigned char *key = ucmalloc(crypto_secretbox_KEYBYTES);
|
||||
|
||||
size_t plen = strnlen(passphrase, 255);
|
||||
unsigned char *temp = ucmalloc(crypto_hash_BYTES);
|
||||
int i;
|
||||
|
||||
// make a hash from the passphrase and then HCYCLES times from the result
|
||||
memcpy(temp, passphrase, plen);
|
||||
for(i=0; i<HCYCLES; ++i) {
|
||||
if(crypto_hash(hash64, temp, plen) == 0) {
|
||||
memcpy(temp, hash64, crypto_hash_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
// xor the first half of the hash with the latter to get
|
||||
// a 32 byte array
|
||||
for(i=0; i<crypto_secretbox_KEYBYTES; ++i) {
|
||||
xor[i] = hash64[i] ^ hash64[i + crypto_secretbox_KEYBYTES];
|
||||
}
|
||||
|
||||
// turn the 32byte hash into a secret key
|
||||
xor[0] &= 248;
|
||||
xor[31] &= 127;
|
||||
xor[31] |= 64;
|
||||
|
||||
memcpy(key, xor, crypto_secretbox_KEYBYTES);
|
||||
|
||||
bzero(passphrase, plen);
|
||||
bzero(temp, crypto_hash_BYTES);
|
||||
free(passphrase);
|
||||
free(temp);
|
||||
free(xor);
|
||||
free(hash64);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
size_t pcp_sodium_mac(unsigned char **cipher,
|
||||
unsigned char *cleartext,
|
||||
size_t clearsize,
|
||||
unsigned char *nonce,
|
||||
unsigned char *key) {
|
||||
unsigned char *pad_clear;
|
||||
unsigned char *pad_cipher;
|
||||
|
||||
pad_cipher = ucmalloc(crypto_secretbox_ZEROBYTES + clearsize);
|
||||
|
||||
pcp_pad_prepend(&pad_clear, cleartext, crypto_secretbox_ZEROBYTES, clearsize);
|
||||
|
||||
crypto_secretbox(pad_cipher, pad_clear,
|
||||
clearsize + crypto_secretbox_ZEROBYTES, nonce, key);
|
||||
|
||||
pcp_pad_remove(cipher, pad_cipher, crypto_secretbox_BOXZEROBYTES,
|
||||
(clearsize + crypto_secretbox_ZEROBYTES) - crypto_secretbox_BOXZEROBYTES);
|
||||
|
||||
free(pad_clear);
|
||||
free(pad_cipher);
|
||||
|
||||
return (clearsize + crypto_secretbox_ZEROBYTES) - crypto_secretbox_BOXZEROBYTES;
|
||||
}
|
||||
|
||||
int pcp_sodium_verify_mac(unsigned char **cleartext, unsigned char* message,
|
||||
size_t messagesize, unsigned char *nonce,
|
||||
unsigned char *key) {
|
||||
// verify the mac
|
||||
unsigned char *pad_cipher;
|
||||
unsigned char *pad_clear;
|
||||
int success = -1;
|
||||
|
||||
pcp_pad_prepend(&pad_cipher, message, crypto_secretbox_BOXZEROBYTES, messagesize);
|
||||
|
||||
pad_clear = (unsigned char *)ucmalloc((crypto_secretbox_BOXZEROBYTES + messagesize));
|
||||
|
||||
if (crypto_secretbox_open(pad_clear,
|
||||
pad_cipher,
|
||||
messagesize + crypto_secretbox_BOXZEROBYTES,
|
||||
nonce, key) == 0) {
|
||||
success = 0;
|
||||
}
|
||||
|
||||
pcp_pad_remove(cleartext, pad_clear, crypto_secretbox_ZEROBYTES, messagesize);
|
||||
|
||||
free(pad_clear);
|
||||
free(pad_cipher);
|
||||
|
||||
return success;
|
||||
}
|
||||
70
libpcp/mac.h
Normal file
70
libpcp/mac.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef _HAVE_PCP_MAC
|
||||
#define _HAVE_PCP_MAC
|
||||
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sodium.h>
|
||||
#include "pad.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
// how many times do we hash the passphrase
|
||||
#define HCYCLES 128000
|
||||
|
||||
// encrypt some arbitrary cleartext using
|
||||
// a curve25519 secret key and a given nonce.
|
||||
//
|
||||
// expects a pointer to the target binary
|
||||
// stream containing the encrypted data,
|
||||
// the cleartext string, its size, the nonce
|
||||
// (24 bytes) and the secret key (32 bytes).
|
||||
//
|
||||
// allocates memory for the returned cipher
|
||||
// and it is up to the user to free it after use.
|
||||
//
|
||||
// returns the size of the returned cipherstream.
|
||||
// in case of an error, the cipher will be set
|
||||
// to NULL.
|
||||
size_t pcp_sodium_mac(unsigned char **cipher,
|
||||
unsigned char *cleartext,
|
||||
size_t clearsize,
|
||||
unsigned char *nonce,
|
||||
unsigned char *key);
|
||||
|
||||
// does the opposite of pcp_sodium_mac and decrypts
|
||||
// a given encrypted binary stream using a nonce and
|
||||
// a secret key (sizes: see above).
|
||||
//
|
||||
// allocates memory for the returned cleartext and
|
||||
// it is up to the user to free it after use.
|
||||
//
|
||||
// returns 0 if decryption and verification were
|
||||
// successful, otherwise -1.
|
||||
int pcp_sodium_verify_mac(unsigned char **cleartext,
|
||||
unsigned char* message,
|
||||
size_t messagesize,
|
||||
unsigned char *nonce,
|
||||
unsigned char *key);
|
||||
|
||||
// generate a nonce from random source arc4random().
|
||||
// allocates memory for the returned nonce and
|
||||
// it is up to the user to free it after use.
|
||||
void pcp_makenonce(unsigned char **nonce);
|
||||
|
||||
// proprietary key derivation function. derives an
|
||||
// secure encryption key from the given passphrase by
|
||||
// calculating a SALSA20 hash from it HCYCLES times.
|
||||
//
|
||||
// turns the result into a proper CURVE25519 secret
|
||||
// key. allocates memory for key and it is up to the
|
||||
// user to free it after use.
|
||||
//
|
||||
// deprecation warning: maybe removed once the libsodium
|
||||
// developers incorporated some key derivation function
|
||||
// into libsodium. so far, there's none but word goes
|
||||
// that perhaps something like scrypt() from the star
|
||||
// distribution may be added in the future.
|
||||
unsigned char *pcp_derivekey(char *passphrase);
|
||||
|
||||
#endif // _HAVE_PCP_MAC
|
||||
33
libpcp/mem.c
Normal file
33
libpcp/mem.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "mem.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void *ucmalloc(size_t s) {
|
||||
size_t size = s * sizeof(unsigned char);
|
||||
void *value = malloc (size);
|
||||
|
||||
if (value == NULL) {
|
||||
err(errno, "Cannot allocate memory");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bzero (value, size);
|
||||
|
||||
//printf("allocated %d bytes at %p\n", (int)size, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void *urmalloc(size_t s) {
|
||||
void *value = ucmalloc (s);
|
||||
|
||||
arc4random_buf(value, s);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void *ucfree(void *ptr) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
24
libpcp/mem.h
Normal file
24
libpcp/mem.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _HAVE_PCP_MEM
|
||||
#define _HAVE_PCP_MEM
|
||||
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
|
||||
// simple malloc() wrapper
|
||||
// behaves like calloc(), which
|
||||
// I don't have here.
|
||||
//
|
||||
// exits if there's no more memory
|
||||
// available.
|
||||
void *ucmalloc(size_t s);
|
||||
|
||||
// the same but it fills the pointer with random values
|
||||
void *urmalloc(size_t s);
|
||||
|
||||
// dito.
|
||||
void *ucfree(void *ptr);
|
||||
|
||||
|
||||
#endif // _HAVE_PCP_MEM
|
||||
53
libpcp/pad.c
Normal file
53
libpcp/pad.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "pad.h"
|
||||
|
||||
void pcp_pad_prepend(unsigned char **padded, unsigned char *unpadded,
|
||||
size_t padlen, size_t unpadlen) {
|
||||
*padded = ucmalloc(unpadlen + padlen);
|
||||
unsigned char *tmp = ucmalloc(unpadlen + padlen);
|
||||
|
||||
// pcp_append orig
|
||||
int i;
|
||||
for(i=0; i<unpadlen; ++i) {
|
||||
tmp[i + padlen] = unpadded[i];
|
||||
}
|
||||
|
||||
memcpy(*padded, tmp, unpadlen + padlen);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
void pcp_pad_remove(unsigned char **unpadded, unsigned char *padded,
|
||||
size_t padlen, size_t unpadlen) {
|
||||
*unpadded = ucmalloc(unpadlen * sizeof(unsigned char));
|
||||
unsigned char *tmp = ucmalloc(unpadlen);
|
||||
|
||||
int i;
|
||||
for(i=0; i<unpadlen; ++i) {
|
||||
tmp[i] = padded[padlen + i];
|
||||
}
|
||||
|
||||
memcpy(*unpadded, tmp, unpadlen);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
#ifdef _MK_ZPAD_MAIN
|
||||
int main(int argc, char **argv) {
|
||||
if(argc >= 2) {
|
||||
size_t unpadlen;
|
||||
int padlen = strtol(argv[2], NULL, 0);
|
||||
unpadlen = strlen(argv[1]);
|
||||
unsigned char *dst;
|
||||
|
||||
pcp_pad_prepend(&dst, argv[1], padlen, unpadlen);
|
||||
//printf(" prev: %s\n after: %s\n", argv[1], dst);
|
||||
|
||||
unsigned char *reverse;
|
||||
pcp_pad_remove(&reverse, dst, padlen, unpadlen);
|
||||
//printf("reverse: %s\n", reverse);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//fprintf(stderr, "Usage: pad <string> <padlen>\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
76
libpcp/pad.h
Normal file
76
libpcp/pad.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef _HAVE_PCP_ZPADDING
|
||||
#define _HAVE_PCP_ZPADDING
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ZPADCHAR 48
|
||||
#else
|
||||
#define ZPADCHAR 0
|
||||
#endif
|
||||
|
||||
// prepends a binary stream with a number of
|
||||
// \0's as required by the secret_box and
|
||||
// secret_box_open functions of libsodium.
|
||||
//
|
||||
// parameters:
|
||||
//
|
||||
// padded: destination array (ref)
|
||||
// unpadded: source array without padding
|
||||
// padlen: length of padding
|
||||
// unpadlen: length of source array
|
||||
//
|
||||
// turns "efa5" into "00000000efa5" with padlen 8
|
||||
//
|
||||
// if DEBUG is set, destination will be padded with
|
||||
// the character '0', NOT the integer 0.
|
||||
//
|
||||
// allocates memory for padded and it is up to the
|
||||
// user to free it after use.
|
||||
//
|
||||
// sample call:
|
||||
//
|
||||
// char unpadded[] = {0xef, 0xa5};
|
||||
// unsigned char *padded;
|
||||
// pcp_pad_prepend(&padded, unpadded, 8, 2);
|
||||
//
|
||||
// the result, padded, would be 10 bytes long, 8
|
||||
// bytes for the leading zeros and 2 for the content
|
||||
// of the original unpadded.
|
||||
void pcp_pad_prepend(unsigned char **padded, unsigned char *unpadded,
|
||||
size_t padlen, size_t unpadlen);
|
||||
|
||||
// removes zero's of a binary stream, which is
|
||||
// the reverse of pcp_pad_prepend().
|
||||
//
|
||||
// parameters:
|
||||
//
|
||||
// unpadded: destination array (ref), with padding removed
|
||||
// padded: source array with padding
|
||||
// padlen: length of padding
|
||||
// unpadlen: length of source array
|
||||
//
|
||||
// turns "00000000efa5" into "efa5" with padlen 8
|
||||
//
|
||||
// allocates memory for unpadded and it is up to the
|
||||
// user to free it after use.
|
||||
//
|
||||
// sample call:
|
||||
//
|
||||
// char padded[] = {0x0, 0x0, 0x0, 0x0, 0xef, 0xa5};
|
||||
// unsigned char *unpadded;
|
||||
// pcp_pad_remove(unpadded, padded, 4, 2);
|
||||
//
|
||||
// the result, unpadded would be 2 bytes long containing
|
||||
// only the 2 bytes we want to have with zeros removed.
|
||||
void pcp_pad_remove(unsigned char **unpadded, unsigned char *padded,
|
||||
size_t padlen, size_t unpadlen);
|
||||
|
||||
|
||||
#endif // _HAVE_PCP_ZPADDING
|
||||
13
libpcp/platform.h
Normal file
13
libpcp/platform.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _HAVE_PCP_PLATFORM_H
|
||||
#define _HAVE_PCP_PLATFORM_H
|
||||
|
||||
#if defined(CONFIG_H_FILE)
|
||||
#include CONFIG_H_FILE
|
||||
#elif defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#else
|
||||
#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
|
||||
#endif
|
||||
|
||||
#endif /* !_HAVE_PCP_PLATFORM_H */
|
||||
|
||||
101
libpcp/randomart.c
Normal file
101
libpcp/randomart.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Draw an ASCII-Art representing the fingerprint so human brain can
|
||||
* profit from its built-in pattern recognition ability.
|
||||
* This technique is called "random art" and can be found in some
|
||||
* scientific publications like this original paper:
|
||||
*
|
||||
* "Hash Visualization: a New Technique to improve Real-World Security",
|
||||
* Perrig A. and Song D., 1999, International Workshop on Cryptographic
|
||||
* Techniques and E-Commerce (CrypTEC '99)
|
||||
* sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
|
||||
*
|
||||
* The subject came up in a talk by Dan Kaminsky, too.
|
||||
*
|
||||
* If you see the picture is different, the key is different.
|
||||
* If the picture looks the same, you still know nothing.
|
||||
*
|
||||
* The algorithm used here is a worm crawling over a discrete plane,
|
||||
* leaving a trace (augmenting the field) everywhere it goes.
|
||||
* Movement is taken from dgst_raw 2bit-wise. Bumping into walls
|
||||
* makes the respective movement vector be ignored for this turn.
|
||||
* Graphs are not unambiguous, because circles in graphs can be
|
||||
* walked in either direction.
|
||||
*/
|
||||
|
||||
#include "randomart.h"
|
||||
|
||||
#define FLDSIZE_Y 8
|
||||
#define FLDSIZE_X FLDSIZE_Y * 2
|
||||
|
||||
char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len)
|
||||
{
|
||||
/*
|
||||
* Chars to be used after each other every time the worm
|
||||
* intersects with itself. Matter of taste.
|
||||
*/
|
||||
char *augmentation_string = " .o+=*BOX@%&#/^";
|
||||
char *retval, *p;
|
||||
char field[FLDSIZE_X][FLDSIZE_Y];
|
||||
unsigned int i, b;
|
||||
int x, y;
|
||||
|
||||
retval = ucmalloc((FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
|
||||
|
||||
/* initialize field */
|
||||
memset(field, ' ', FLDSIZE_X * FLDSIZE_Y * sizeof(char));
|
||||
x = FLDSIZE_X / 2;
|
||||
y = FLDSIZE_Y / 2;
|
||||
field[x][y] = '.';
|
||||
|
||||
/* process raw key */
|
||||
for (i = 0; i < dgst_raw_len; i++) {
|
||||
int input;
|
||||
/* each byte conveys four 2-bit move commands */
|
||||
input = dgst_raw[i];
|
||||
for (b = 0; b < 4; b++) {
|
||||
/* evaluate 2 bit, rest is shifted later */
|
||||
x += (input & 0x1) ? 1 : -1;
|
||||
y += (input & 0x2) ? 1 : -1;
|
||||
|
||||
/* assure we are still in bounds */
|
||||
x = MAX(x, 0);
|
||||
y = MAX(y, 0);
|
||||
x = MIN(x, FLDSIZE_X - 1);
|
||||
y = MIN(y, FLDSIZE_Y - 1);
|
||||
|
||||
/* augment the field */
|
||||
p = strchr(augmentation_string, field[x][y]);
|
||||
if (*++p != '\0')
|
||||
field[x][y] = *p;
|
||||
|
||||
input = input >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill in retval */
|
||||
p = retval;
|
||||
|
||||
/* output upper border */
|
||||
*p++ = '+';
|
||||
for (i = 0; i < FLDSIZE_X; i++)
|
||||
*p++ = '-';
|
||||
*p++ = '+';
|
||||
*p++ = '\n';
|
||||
|
||||
/* output content */
|
||||
for (y = 0; y < FLDSIZE_Y; y++) {
|
||||
*p++ = '|';
|
||||
for (x = 0; x < FLDSIZE_X; x++)
|
||||
*p++ = field[x][y];
|
||||
*p++ = '|';
|
||||
*p++ = '\n';
|
||||
}
|
||||
|
||||
/* output lower border */
|
||||
*p++ = '+';
|
||||
for (i = 0; i < FLDSIZE_X; i++)
|
||||
*p++ = '-';
|
||||
*p++ = '+';
|
||||
|
||||
return retval;
|
||||
}
|
||||
54
libpcp/randomart.h
Normal file
54
libpcp/randomart.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* $OpenBSD: key.c,v 1.70 2008/06/11 21:01:35 grunk Exp $ */
|
||||
/*
|
||||
* read_bignum():
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// key_fingerprint_randomart comitted by Alexander von Gernler in rev 1.70
|
||||
|
||||
#ifndef _HAVE_PCP_RANDOMART_H
|
||||
#define _HAVE_PCP_RANDOMART_H
|
||||
|
||||
#include "mem.h"
|
||||
#include <string.h>
|
||||
|
||||
// from openssh key.c
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
|
||||
char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len);
|
||||
|
||||
#endif // _HAVE_PCP_RANDOMART_H
|
||||
140
libpcp/sysendian.h
Normal file
140
libpcp/sysendian.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*-
|
||||
* Copyright 2007-2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _SYSENDIAN_H_
|
||||
#define _SYSENDIAN_H_
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
|
||||
#if !HAVE_DECL_BE64ENC
|
||||
#undef HAVE_SYS_ENDIAN_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
be64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
|
||||
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
|
||||
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
|
||||
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[7] = x & 0xff;
|
||||
p[6] = (x >> 8) & 0xff;
|
||||
p[5] = (x >> 16) & 0xff;
|
||||
p[4] = (x >> 24) & 0xff;
|
||||
p[3] = (x >> 32) & 0xff;
|
||||
p[2] = (x >> 40) & 0xff;
|
||||
p[1] = (x >> 48) & 0xff;
|
||||
p[0] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
le32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
le64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
|
||||
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
|
||||
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
|
||||
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
p[4] = (x >> 32) & 0xff;
|
||||
p[5] = (x >> 40) & 0xff;
|
||||
p[6] = (x >> 48) & 0xff;
|
||||
p[7] = (x >> 56) & 0xff;
|
||||
}
|
||||
#endif /* !HAVE_SYS_ENDIAN_H */
|
||||
|
||||
#endif /* !_SYSENDIAN_H_ */
|
||||
948
libpcp/uthash.h
Executable file
948
libpcp/uthash.h
Executable file
@@ -0,0 +1,948 @@
|
||||
/*
|
||||
Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#include <string.h> /* memcmp,strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit() */
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ source) this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#ifdef _MSC_VER /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define DECLTYPE(x) (decltype(x))
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#endif
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#endif
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
char **_da_dst = (char**)(&(dst)); \
|
||||
*_da_dst = (char*)(src); \
|
||||
} while(0)
|
||||
#else
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
(dst) = DECLTYPE(dst)(src); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* a number of the hash function use uint32_t which isn't defined on win32 */
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#else
|
||||
#include <inttypes.h> /* uint32_t */
|
||||
#endif
|
||||
|
||||
#define UTHASH_VERSION 1.9.8
|
||||
|
||||
#ifndef uthash_fatal
|
||||
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
|
||||
#endif
|
||||
#ifndef uthash_malloc
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#endif
|
||||
#ifndef uthash_free
|
||||
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
|
||||
#endif
|
||||
|
||||
#ifndef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
|
||||
#endif
|
||||
#ifndef uthash_expand_fyi
|
||||
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
||||
#endif
|
||||
|
||||
/* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
|
||||
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
|
||||
|
||||
/* calculate the element whose hash handle address is hhe */
|
||||
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
||||
|
||||
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
||||
do { \
|
||||
unsigned _hf_bkt,_hf_hashv; \
|
||||
out=NULL; \
|
||||
if (head) { \
|
||||
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
|
||||
keyptr,keylen,out); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef HASH_BLOOM
|
||||
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
|
||||
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
|
||||
#define HASH_BLOOM_MAKE(tbl) \
|
||||
do { \
|
||||
(tbl)->bloom_nbits = HASH_BLOOM; \
|
||||
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
||||
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
|
||||
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
|
||||
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_FREE(tbl) \
|
||||
do { \
|
||||
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) \
|
||||
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#else
|
||||
#define HASH_BLOOM_MAKE(tbl)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_BYTELEN 0
|
||||
#endif
|
||||
|
||||
#define HASH_MAKE_TABLE(hh,head) \
|
||||
do { \
|
||||
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
|
||||
sizeof(UT_hash_table)); \
|
||||
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
|
||||
(head)->hh.tbl->tail = &((head)->hh); \
|
||||
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
||||
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
||||
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
||||
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl->buckets, 0, \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_MAKE((head)->hh.tbl); \
|
||||
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
||||
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
|
||||
|
||||
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
||||
do { \
|
||||
replaced=NULL; \
|
||||
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
|
||||
if (replaced!=NULL) { \
|
||||
HASH_DELETE(hh,head,replaced); \
|
||||
}; \
|
||||
HASH_ADD(hh,head,fieldname,keylen_in,add); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
||||
do { \
|
||||
unsigned _ha_bkt; \
|
||||
(add)->hh.next = NULL; \
|
||||
(add)->hh.key = (char*)(keyptr); \
|
||||
(add)->hh.keylen = (unsigned)(keylen_in); \
|
||||
if (!(head)) { \
|
||||
head = (add); \
|
||||
(head)->hh.prev = NULL; \
|
||||
HASH_MAKE_TABLE(hh,head); \
|
||||
} else { \
|
||||
(head)->hh.tbl->tail->next = (add); \
|
||||
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
||||
(head)->hh.tbl->tail = &((add)->hh); \
|
||||
} \
|
||||
(head)->hh.tbl->num_items++; \
|
||||
(add)->hh.tbl = (head)->hh.tbl; \
|
||||
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
|
||||
(add)->hh.hashv, _ha_bkt); \
|
||||
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
||||
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
||||
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
||||
do { \
|
||||
bkt = ((hashv) & ((num_bkts) - 1)); \
|
||||
} while(0)
|
||||
|
||||
/* delete "delptr" from the hash table.
|
||||
* "the usual" patch-up process for the app-order doubly-linked-list.
|
||||
* The use of _hd_hh_del below deserves special explanation.
|
||||
* These used to be expressed using (delptr) but that led to a bug
|
||||
* if someone used the same symbol for the head and deletee, like
|
||||
* HASH_DELETE(hh,users,users);
|
||||
* We want that to work, but by changing the head (users) below
|
||||
* we were forfeiting our ability to further refer to the deletee (users)
|
||||
* in the patch-up process. Solution: use scratch space to
|
||||
* copy the deletee pointer, then the latter references are via that
|
||||
* scratch pointer rather than through the repointed (users) symbol.
|
||||
*/
|
||||
#define HASH_DELETE(hh,head,delptr) \
|
||||
do { \
|
||||
unsigned _hd_bkt; \
|
||||
struct UT_hash_handle *_hd_hh_del; \
|
||||
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
head = NULL; \
|
||||
} else { \
|
||||
_hd_hh_del = &((delptr)->hh); \
|
||||
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
|
||||
(head)->hh.tbl->tail = \
|
||||
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho); \
|
||||
} \
|
||||
if ((delptr)->hh.prev) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
|
||||
} else { \
|
||||
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
|
||||
} \
|
||||
if (_hd_hh_del->next) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
|
||||
(head)->hh.tbl->hho))->prev = \
|
||||
_hd_hh_del->prev; \
|
||||
} \
|
||||
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
||||
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
||||
(head)->hh.tbl->num_items--; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
||||
#define HASH_FIND_STR(head,findstr,out) \
|
||||
HASH_FIND(hh,head,findstr,strlen(findstr),out)
|
||||
#define HASH_ADD_STR(head,strfield,add) \
|
||||
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
|
||||
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
|
||||
#define HASH_FIND_INT(head,findint,out) \
|
||||
HASH_FIND(hh,head,findint,sizeof(int),out)
|
||||
#define HASH_ADD_INT(head,intfield,add) \
|
||||
HASH_ADD(hh,head,intfield,sizeof(int),add)
|
||||
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
|
||||
#define HASH_FIND_PTR(head,findptr,out) \
|
||||
HASH_FIND(hh,head,findptr,sizeof(void *),out)
|
||||
#define HASH_ADD_PTR(head,ptrfield,add) \
|
||||
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
|
||||
#define HASH_REPLACE_PTR(head,ptrfield,add) \
|
||||
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
|
||||
#define HASH_DEL(head,delptr) \
|
||||
HASH_DELETE(hh,head,delptr)
|
||||
|
||||
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
|
||||
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
||||
*/
|
||||
#ifdef HASH_DEBUG
|
||||
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
|
||||
#define HASH_FSCK(hh,head) \
|
||||
do { \
|
||||
unsigned _bkt_i; \
|
||||
unsigned _count, _bkt_count; \
|
||||
char *_prev; \
|
||||
struct UT_hash_handle *_thh; \
|
||||
if (head) { \
|
||||
_count = 0; \
|
||||
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
|
||||
_bkt_count = 0; \
|
||||
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
||||
_prev = NULL; \
|
||||
while (_thh) { \
|
||||
if (_prev != (char*)(_thh->hh_prev)) { \
|
||||
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
|
||||
_thh->hh_prev, _prev ); \
|
||||
} \
|
||||
_bkt_count++; \
|
||||
_prev = (char*)(_thh); \
|
||||
_thh = _thh->hh_next; \
|
||||
} \
|
||||
_count += _bkt_count; \
|
||||
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
||||
HASH_OOPS("invalid bucket count %d, actual %d\n", \
|
||||
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
||||
} \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid hh item count %d, actual %d\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
/* traverse hh in app order; check next/prev integrity, count */ \
|
||||
_count = 0; \
|
||||
_prev = NULL; \
|
||||
_thh = &(head)->hh; \
|
||||
while (_thh) { \
|
||||
_count++; \
|
||||
if (_prev !=(char*)(_thh->prev)) { \
|
||||
HASH_OOPS("invalid prev %p, actual %p\n", \
|
||||
_thh->prev, _prev ); \
|
||||
} \
|
||||
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
||||
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
|
||||
(head)->hh.tbl->hho) : NULL ); \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid app item count %d, actual %d\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_FSCK(hh,head)
|
||||
#endif
|
||||
|
||||
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
||||
* the descriptor to which this macro is defined for tuning the hash function.
|
||||
* The app can #include <unistd.h> to get the prototype for write(2). */
|
||||
#ifdef HASH_EMIT_KEYS
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
||||
do { \
|
||||
unsigned _klen = fieldlen; \
|
||||
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
||||
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#ifdef HASH_FUNCTION
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6 */
|
||||
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hb_keylen=keylen; \
|
||||
char *_hb_key=(char*)(key); \
|
||||
(hashv) = 0; \
|
||||
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
|
||||
bkt = (hashv) & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
char *_hs_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
|
||||
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _fn_i; \
|
||||
char *_hf_key=(char*)(key); \
|
||||
hashv = 2166136261UL; \
|
||||
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
|
||||
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _ho_i; \
|
||||
char *_ho_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
|
||||
hashv += _ho_key[_ho_i]; \
|
||||
hashv += (hashv << 10); \
|
||||
hashv ^= (hashv >> 6); \
|
||||
} \
|
||||
hashv += (hashv << 3); \
|
||||
hashv ^= (hashv >> 11); \
|
||||
hashv += (hashv << 15); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_JEN_MIX(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hj_i,_hj_j,_hj_k; \
|
||||
unsigned char *_hj_key=(unsigned char*)(key); \
|
||||
hashv = 0xfeedbeef; \
|
||||
_hj_i = _hj_j = 0x9e3779b9; \
|
||||
_hj_k = (unsigned)(keylen); \
|
||||
while (_hj_k >= 12) { \
|
||||
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[2] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[3] << 24 ) ); \
|
||||
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[6] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[7] << 24 ) ); \
|
||||
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[10] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[11] << 24 ) ); \
|
||||
\
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
\
|
||||
_hj_key += 12; \
|
||||
_hj_k -= 12; \
|
||||
} \
|
||||
hashv += keylen; \
|
||||
switch ( _hj_k ) { \
|
||||
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
|
||||
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
|
||||
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
|
||||
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
|
||||
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
|
||||
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
|
||||
case 5: _hj_j += _hj_key[4]; \
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
/* The Paul Hsieh hash function */
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned char *_sfh_key=(unsigned char*)(key); \
|
||||
uint32_t _sfh_tmp, _sfh_len = keylen; \
|
||||
\
|
||||
int _sfh_rem = _sfh_len & 3; \
|
||||
_sfh_len >>= 2; \
|
||||
hashv = 0xcafebabe; \
|
||||
\
|
||||
/* Main loop */ \
|
||||
for (;_sfh_len > 0; _sfh_len--) { \
|
||||
hashv += get16bits (_sfh_key); \
|
||||
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
|
||||
hashv = (hashv << 16) ^ _sfh_tmp; \
|
||||
_sfh_key += 2*sizeof (uint16_t); \
|
||||
hashv += hashv >> 11; \
|
||||
} \
|
||||
\
|
||||
/* Handle end cases */ \
|
||||
switch (_sfh_rem) { \
|
||||
case 3: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 16; \
|
||||
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
|
||||
hashv += hashv >> 11; \
|
||||
break; \
|
||||
case 2: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 11; \
|
||||
hashv += hashv >> 17; \
|
||||
break; \
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
hashv ^= hashv << 3; \
|
||||
hashv += hashv >> 5; \
|
||||
hashv ^= hashv << 4; \
|
||||
hashv += hashv >> 17; \
|
||||
hashv ^= hashv << 25; \
|
||||
hashv += hashv >> 6; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#ifdef HASH_USING_NO_STRICT_ALIASING
|
||||
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
|
||||
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
|
||||
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
|
||||
*
|
||||
* Note the preprocessor built-in defines can be emitted using:
|
||||
*
|
||||
* gcc -m64 -dM -E - < /dev/null (on gcc)
|
||||
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
|
||||
*/
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
|
||||
#define MUR_GETBLOCK(p,i) p[i]
|
||||
#else /* non intel */
|
||||
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
|
||||
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
|
||||
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
|
||||
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
|
||||
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
|
||||
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
|
||||
#else /* assume little endian non-intel */
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
|
||||
#endif
|
||||
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
|
||||
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
|
||||
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
|
||||
MUR_ONE_THREE(p))))
|
||||
#endif
|
||||
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
#define MUR_FMIX(_h) \
|
||||
do { \
|
||||
_h ^= _h >> 16; \
|
||||
_h *= 0x85ebca6b; \
|
||||
_h ^= _h >> 13; \
|
||||
_h *= 0xc2b2ae35l; \
|
||||
_h ^= _h >> 16; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const uint8_t *_mur_data = (const uint8_t*)(key); \
|
||||
const int _mur_nblocks = (keylen) / 4; \
|
||||
uint32_t _mur_h1 = 0xf88D5353; \
|
||||
uint32_t _mur_c1 = 0xcc9e2d51; \
|
||||
uint32_t _mur_c2 = 0x1b873593; \
|
||||
uint32_t _mur_k1 = 0; \
|
||||
const uint8_t *_mur_tail; \
|
||||
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
|
||||
int _mur_i; \
|
||||
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
|
||||
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
\
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
|
||||
_mur_h1 = _mur_h1*5+0xe6546b64; \
|
||||
} \
|
||||
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
|
||||
_mur_k1=0; \
|
||||
switch((keylen) & 3) { \
|
||||
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
|
||||
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
|
||||
case 1: _mur_k1 ^= _mur_tail[0]; \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
} \
|
||||
_mur_h1 ^= (keylen); \
|
||||
MUR_FMIX(_mur_h1); \
|
||||
hashv = _mur_h1; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
#endif /* HASH_USING_NO_STRICT_ALIASING */
|
||||
|
||||
/* key comparison function; return 0 if keys equal */
|
||||
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
|
||||
|
||||
/* iterate over items in a known bucket to find desired item */
|
||||
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
|
||||
do { \
|
||||
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
|
||||
else out=NULL; \
|
||||
while (out) { \
|
||||
if ((out)->hh.keylen == keylen_in) { \
|
||||
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
|
||||
} \
|
||||
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
|
||||
else out = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* add an item to a bucket */
|
||||
#define HASH_ADD_TO_BKT(head,addhh) \
|
||||
do { \
|
||||
head.count++; \
|
||||
(addhh)->hh_next = head.hh_head; \
|
||||
(addhh)->hh_prev = NULL; \
|
||||
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
|
||||
(head).hh_head=addhh; \
|
||||
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
|
||||
&& (addhh)->tbl->noexpand != 1) { \
|
||||
HASH_EXPAND_BUCKETS((addhh)->tbl); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* remove an item from a given bucket */
|
||||
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
|
||||
(head).count--; \
|
||||
if ((head).hh_head == hh_del) { \
|
||||
(head).hh_head = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_prev) { \
|
||||
hh_del->hh_prev->hh_next = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_next) { \
|
||||
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
|
||||
}
|
||||
|
||||
/* Bucket expansion has the effect of doubling the number of buckets
|
||||
* and redistributing the items into the new buckets. Ideally the
|
||||
* items will distribute more or less evenly into the new buckets
|
||||
* (the extent to which this is true is a measure of the quality of
|
||||
* the hash function as it applies to the key domain).
|
||||
*
|
||||
* With the items distributed into more buckets, the chain length
|
||||
* (item count) in each bucket is reduced. Thus by expanding buckets
|
||||
* the hash keeps a bound on the chain length. This bounded chain
|
||||
* length is the essence of how a hash provides constant time lookup.
|
||||
*
|
||||
* The calculation of tbl->ideal_chain_maxlen below deserves some
|
||||
* explanation. First, keep in mind that we're calculating the ideal
|
||||
* maximum chain length based on the *new* (doubled) bucket count.
|
||||
* In fractions this is just n/b (n=number of items,b=new num buckets).
|
||||
* Since the ideal chain length is an integer, we want to calculate
|
||||
* ceil(n/b). We don't depend on floating point arithmetic in this
|
||||
* hash, so to calculate ceil(n/b) with integers we could write
|
||||
*
|
||||
* ceil(n/b) = (n/b) + ((n%b)?1:0)
|
||||
*
|
||||
* and in fact a previous version of this hash did just that.
|
||||
* But now we have improved things a bit by recognizing that b is
|
||||
* always a power of two. We keep its base 2 log handy (call it lb),
|
||||
* so now we can write this with a bit shift and logical AND:
|
||||
*
|
||||
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
||||
*
|
||||
*/
|
||||
#define HASH_EXPAND_BUCKETS(tbl) \
|
||||
do { \
|
||||
unsigned _he_bkt; \
|
||||
unsigned _he_bkt_i; \
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset(_he_new_buckets, 0, \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
tbl->ideal_chain_maxlen = \
|
||||
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
|
||||
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
|
||||
tbl->nonideal_items = 0; \
|
||||
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
|
||||
{ \
|
||||
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
|
||||
while (_he_thh) { \
|
||||
_he_hh_nxt = _he_thh->hh_next; \
|
||||
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
|
||||
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
|
||||
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
|
||||
tbl->nonideal_items++; \
|
||||
_he_newbkt->expand_mult = _he_newbkt->count / \
|
||||
tbl->ideal_chain_maxlen; \
|
||||
} \
|
||||
_he_thh->hh_prev = NULL; \
|
||||
_he_thh->hh_next = _he_newbkt->hh_head; \
|
||||
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
|
||||
_he_thh; \
|
||||
_he_newbkt->hh_head = _he_thh; \
|
||||
_he_thh = _he_hh_nxt; \
|
||||
} \
|
||||
} \
|
||||
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
tbl->num_buckets *= 2; \
|
||||
tbl->log2_num_buckets++; \
|
||||
tbl->buckets = _he_new_buckets; \
|
||||
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
|
||||
(tbl->ineff_expands+1) : 0; \
|
||||
if (tbl->ineff_expands > 1) { \
|
||||
tbl->noexpand=1; \
|
||||
uthash_noexpand_fyi(tbl); \
|
||||
} \
|
||||
uthash_expand_fyi(tbl); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
|
||||
/* Note that HASH_SORT assumes the hash handle name to be hh.
|
||||
* HASH_SRT was added to allow the hash handle name to be passed in. */
|
||||
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
|
||||
#define HASH_SRT(hh,head,cmpfcn) \
|
||||
do { \
|
||||
unsigned _hs_i; \
|
||||
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
||||
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
||||
if (head) { \
|
||||
_hs_insize = 1; \
|
||||
_hs_looping = 1; \
|
||||
_hs_list = &((head)->hh); \
|
||||
while (_hs_looping) { \
|
||||
_hs_p = _hs_list; \
|
||||
_hs_list = NULL; \
|
||||
_hs_tail = NULL; \
|
||||
_hs_nmerges = 0; \
|
||||
while (_hs_p) { \
|
||||
_hs_nmerges++; \
|
||||
_hs_q = _hs_p; \
|
||||
_hs_psize = 0; \
|
||||
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
|
||||
_hs_psize++; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
if (! (_hs_q) ) break; \
|
||||
} \
|
||||
_hs_qsize = _hs_insize; \
|
||||
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
|
||||
if (_hs_psize == 0) { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else if (( \
|
||||
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
|
||||
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
|
||||
) <= 0) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} \
|
||||
if ( _hs_tail ) { \
|
||||
_hs_tail->next = ((_hs_e) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
|
||||
} else { \
|
||||
_hs_list = _hs_e; \
|
||||
} \
|
||||
if (_hs_e) { \
|
||||
_hs_e->prev = ((_hs_tail) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
|
||||
} \
|
||||
_hs_tail = _hs_e; \
|
||||
} \
|
||||
_hs_p = _hs_q; \
|
||||
} \
|
||||
if (_hs_tail){ \
|
||||
_hs_tail->next = NULL; \
|
||||
} \
|
||||
if ( _hs_nmerges <= 1 ) { \
|
||||
_hs_looping=0; \
|
||||
(head)->hh.tbl->tail = _hs_tail; \
|
||||
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
||||
} \
|
||||
_hs_insize *= 2; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This function selects items from one hash into another hash.
|
||||
* The end result is that the selected items have dual presence
|
||||
* in both hashes. There is no copy of the items made; rather
|
||||
* they are added into the new hash through a secondary hash
|
||||
* hash handle that must be present in the structure. */
|
||||
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
||||
do { \
|
||||
unsigned _src_bkt, _dst_bkt; \
|
||||
void *_last_elt=NULL, *_elt; \
|
||||
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
||||
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
|
||||
if (src) { \
|
||||
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
||||
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
||||
_src_hh; \
|
||||
_src_hh = _src_hh->hh_next) { \
|
||||
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
||||
if (cond(_elt)) { \
|
||||
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
|
||||
_dst_hh->key = _src_hh->key; \
|
||||
_dst_hh->keylen = _src_hh->keylen; \
|
||||
_dst_hh->hashv = _src_hh->hashv; \
|
||||
_dst_hh->prev = _last_elt; \
|
||||
_dst_hh->next = NULL; \
|
||||
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
|
||||
if (!dst) { \
|
||||
DECLTYPE_ASSIGN(dst,_elt); \
|
||||
HASH_MAKE_TABLE(hh_dst,dst); \
|
||||
} else { \
|
||||
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
||||
} \
|
||||
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
||||
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
|
||||
(dst)->hh_dst.tbl->num_items++; \
|
||||
_last_elt = _elt; \
|
||||
_last_elt_hh = _dst_hh; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
HASH_FSCK(hh_dst,dst); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_CLEAR(hh,head) \
|
||||
do { \
|
||||
if (head) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
(head)=NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OVERHEAD(hh,head) \
|
||||
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
|
||||
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
|
||||
(sizeof(UT_hash_table)) + \
|
||||
(HASH_BLOOM_BYTELEN)))
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
|
||||
#else
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
|
||||
#endif
|
||||
|
||||
/* obtain a count of items in the hash */
|
||||
#define HASH_COUNT(head) HASH_CNT(hh,head)
|
||||
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
|
||||
|
||||
typedef struct UT_hash_bucket {
|
||||
struct UT_hash_handle *hh_head;
|
||||
unsigned count;
|
||||
|
||||
/* expand_mult is normally set to 0. In this situation, the max chain length
|
||||
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
|
||||
* the bucket's chain exceeds this length, bucket expansion is triggered).
|
||||
* However, setting expand_mult to a non-zero value delays bucket expansion
|
||||
* (that would be triggered by additions to this particular bucket)
|
||||
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
|
||||
* (The multiplier is simply expand_mult+1). The whole idea of this
|
||||
* multiplier is to reduce bucket expansions, since they are expensive, in
|
||||
* situations where we know that a particular bucket tends to be overused.
|
||||
* It is better to let its chain length grow to a longer yet-still-bounded
|
||||
* value, than to do an O(n) bucket expansion too often.
|
||||
*/
|
||||
unsigned expand_mult;
|
||||
|
||||
} UT_hash_bucket;
|
||||
|
||||
/* random signature used only to find hash tables in external analysis */
|
||||
#define HASH_SIGNATURE 0xa0111fe1
|
||||
#define HASH_BLOOM_SIGNATURE 0xb12220f2
|
||||
|
||||
typedef struct UT_hash_table {
|
||||
UT_hash_bucket *buckets;
|
||||
unsigned num_buckets, log2_num_buckets;
|
||||
unsigned num_items;
|
||||
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
|
||||
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
|
||||
|
||||
/* in an ideal situation (all buckets used equally), no bucket would have
|
||||
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
|
||||
unsigned ideal_chain_maxlen;
|
||||
|
||||
/* nonideal_items is the number of items in the hash whose chain position
|
||||
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
|
||||
* hash distribution; reaching them in a chain traversal takes >ideal steps */
|
||||
unsigned nonideal_items;
|
||||
|
||||
/* ineffective expands occur when a bucket doubling was performed, but
|
||||
* afterward, more than half the items in the hash had nonideal chain
|
||||
* positions. If this happens on two consecutive expansions we inhibit any
|
||||
* further expansion, as it's not helping; this happens when the hash
|
||||
* function isn't a good fit for the key domain. When expansion is inhibited
|
||||
* the hash will still work, albeit no longer in constant time. */
|
||||
unsigned ineff_expands, noexpand;
|
||||
|
||||
uint32_t signature; /* used only to find hash tables in external analysis */
|
||||
#ifdef HASH_BLOOM
|
||||
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
|
||||
uint8_t *bloom_bv;
|
||||
char bloom_nbits;
|
||||
#endif
|
||||
|
||||
} UT_hash_table;
|
||||
|
||||
typedef struct UT_hash_handle {
|
||||
struct UT_hash_table *tbl;
|
||||
void *prev; /* prev element in app order */
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
#endif /* UTHASH_H */
|
||||
397
libpcp/vault.c
Normal file
397
libpcp/vault.c
Normal file
@@ -0,0 +1,397 @@
|
||||
#include "vault.h"
|
||||
|
||||
vault_t *pcpvault_init(char *filename) {
|
||||
vault_t *vault = pcpvault_new(filename, 0);
|
||||
if(vault != NULL) {
|
||||
if(vault->isnew == 1) {
|
||||
if(pcpvault_create(vault) != 0) {
|
||||
pcpvault_close(vault);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(pcpvault_fetchall(vault) != 0) {
|
||||
errno = 0; // weird, something sets it to ENOENT and it's not me
|
||||
pcpvault_close(vault);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vault;
|
||||
}
|
||||
|
||||
vault_t *pcpvault_new(char *filename, int is_tmp) {
|
||||
vault_t *vault = ucmalloc(sizeof(vault_t));
|
||||
FILE *fd;
|
||||
struct stat stat_buf;
|
||||
|
||||
if(is_tmp) {
|
||||
filename = ucmalloc(1024);
|
||||
uint32_t a,b;
|
||||
while (1) {
|
||||
a = arc4random();
|
||||
b = arc4random();
|
||||
snprintf(filename, 1024, "%s/.pcpvault-%08x%08x", getenv("HOME"), a, b);
|
||||
if (stat (filename, &stat_buf) != 0)
|
||||
break;
|
||||
}
|
||||
unlink(filename);
|
||||
vault->size = 0;
|
||||
vault->modified = 0;
|
||||
vault->mode = 0;
|
||||
}
|
||||
else {
|
||||
if (stat (filename, &stat_buf) == 0) {
|
||||
vault->size = stat_buf.st_size;
|
||||
vault->modified = stat_buf.st_mtime;
|
||||
vault->mode = stat_buf.st_mode;
|
||||
}
|
||||
else {
|
||||
vault->size = 0;
|
||||
vault->modified = 0;
|
||||
vault->mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(vault->size == 0) {
|
||||
vault->isnew = 1;
|
||||
mode_t old_mask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
|
||||
if((fd = fopen(filename, "wb+")) == NULL) {
|
||||
fatal("Could not create vault file %s", filename);
|
||||
umask (old_mask);
|
||||
goto errn;
|
||||
}
|
||||
umask (old_mask);
|
||||
}
|
||||
else {
|
||||
if((fd = fopen(filename, "rb+")) == NULL) {
|
||||
fatal("Could not open vault file %s", filename);
|
||||
goto errn;
|
||||
}
|
||||
}
|
||||
|
||||
vault->fd = fd;
|
||||
vault->filename = filename;
|
||||
vault->unsafed = 0;
|
||||
|
||||
return vault;
|
||||
|
||||
errn:
|
||||
free(vault);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pcpvault_create(vault_t *vault) {
|
||||
vault_header_t *header = ucmalloc(sizeof(vault_header_t));
|
||||
header->fileid = PCP_VAULT_ID;
|
||||
header->version = PCP_VAULT_VERSION;
|
||||
|
||||
vault->version = header->version;
|
||||
memcpy(vault->checksum, header->checksum, 32);
|
||||
|
||||
vh2be(header);
|
||||
|
||||
fseek(vault->fd, 0, SEEK_SET);
|
||||
|
||||
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
||||
|
||||
if(ferror(vault->fd) != 0) {
|
||||
fatal("Failed to write fileheader to vault %s!\n", vault->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
vault->unsafed = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcpvault_additem(vault_t *vault, void *item, size_t itemsize, uint8_t type, uint8_t do_hash) {
|
||||
vault_item_header_t *header = ucmalloc(sizeof(vault_item_header_t));
|
||||
header->type = type;
|
||||
header->size = itemsize;
|
||||
|
||||
crypto_hash_sha256((unsigned char*)header->checksum, item, itemsize);
|
||||
ih2be(header);
|
||||
|
||||
void *saveitem = ucmalloc(itemsize);
|
||||
memcpy(saveitem, item, itemsize);
|
||||
|
||||
if(type == PCP_KEY_TYPE_PUBLIC)
|
||||
pubkey2be((pcp_pubkey_t *)saveitem);
|
||||
else
|
||||
key2be((pcp_key_t *)saveitem);
|
||||
|
||||
fwrite(header, sizeof(vault_item_header_t), 1, vault->fd);
|
||||
fwrite(saveitem, itemsize, 1, vault->fd);
|
||||
|
||||
bzero(saveitem, itemsize);
|
||||
free(saveitem);
|
||||
|
||||
if(do_hash == 1) {
|
||||
// we don't re-hash if it's a full update
|
||||
if(type == PCP_KEY_TYPE_PUBLIC) {
|
||||
pcp_pubkey_t *p = (pcp_pubkey_t *)item;
|
||||
HASH_ADD_STR( pcppubkey_hash, id, p );
|
||||
}
|
||||
else {
|
||||
pcp_key_t *s = (pcp_key_t *)item;
|
||||
HASH_ADD_STR( pcpkey_hash, id, s );
|
||||
}
|
||||
pcpvault_update_checksum(vault);
|
||||
}
|
||||
|
||||
if(ferror(vault->fd) != 0) {
|
||||
fatal("Failed to add an item to vault %s!\n", vault->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
vault->unsafed = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcpvault_writeall(vault_t *vault) {
|
||||
vault_t *tmp = pcpvault_new(NULL, 1); // FIXME
|
||||
if(tmp != NULL) {
|
||||
if(pcpvault_create(tmp) == 0) {
|
||||
pcp_key_t *k, *kt = NULL;
|
||||
HASH_ITER(hh, pcpkey_hash, k, kt) {
|
||||
if(pcpvault_additem(tmp, (void *)k, sizeof(pcp_key_t), PCP_KEY_TYPE_SECRET, 0) != 0)
|
||||
goto errwa;
|
||||
}
|
||||
pcp_pubkey_t *p, *pt = NULL;
|
||||
HASH_ITER(hh, pcppubkey_hash, p, pt) {
|
||||
if(pcpvault_additem(tmp, (void *)p, sizeof(pcp_pubkey_t), PCP_KEY_TYPE_PUBLIC, 0) != 0)
|
||||
goto errwa;
|
||||
}
|
||||
pcpvault_update_checksum(tmp);
|
||||
pcpvault_copy(tmp, vault);
|
||||
}
|
||||
}
|
||||
|
||||
errwa:
|
||||
if(tmp != NULL) {
|
||||
pcpvault_unlink(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pcpvault_update_checksum(vault_t *vault) {
|
||||
unsigned char *checksum = pcpvault_create_checksum(vault);
|
||||
|
||||
vault_header_t *header = ucmalloc(sizeof(vault_header_t));
|
||||
header->fileid = PCP_VAULT_ID;
|
||||
header->version = PCP_VAULT_VERSION;
|
||||
memcpy(header->checksum, checksum, 32);
|
||||
memcpy(vault->checksum, checksum, 32);
|
||||
|
||||
vh2be(header);
|
||||
|
||||
fseek(vault->fd, 0, SEEK_SET);
|
||||
fwrite(header, sizeof(vault_header_t), 1, vault->fd);
|
||||
fseek(vault->fd, 0, SEEK_END);
|
||||
}
|
||||
|
||||
unsigned char *pcpvault_create_checksum(vault_t *vault) {
|
||||
size_t skeysize = sizeof(pcp_key_t) - sizeof(UT_hash_handle);
|
||||
size_t pkeysize = sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle);
|
||||
|
||||
int numskeys = HASH_COUNT(pcpkey_hash);
|
||||
int numpkeys = HASH_COUNT(pcppubkey_hash);
|
||||
|
||||
size_t datasize = (skeysize * numskeys) + (pkeysize * numpkeys);
|
||||
unsigned char *data = ucmalloc(datasize);
|
||||
unsigned char *checksum = ucmalloc(32);
|
||||
size_t datapos = 0;
|
||||
|
||||
pcp_key_t *k, *kt = NULL;
|
||||
HASH_ITER(hh, pcpkey_hash, k, kt) {
|
||||
key2be(k);
|
||||
memcpy(&data[datapos], k, skeysize);
|
||||
key2native(k);
|
||||
datapos += skeysize;
|
||||
}
|
||||
|
||||
pcp_pubkey_t *p, *pt = NULL;
|
||||
HASH_ITER(hh, pcppubkey_hash, p, pt) {
|
||||
pubkey2be(p);
|
||||
memcpy(&data[datapos], p, pkeysize);
|
||||
pubkey2native(p);
|
||||
datapos += pkeysize;
|
||||
}
|
||||
|
||||
crypto_hash_sha256(checksum, data, datasize);
|
||||
|
||||
bzero(data, datasize);
|
||||
free(data);
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
void pcpvault_copy(vault_t *tmp, vault_t *vault) {
|
||||
// fetch tmp content
|
||||
fseek(tmp->fd, 0, SEEK_END);
|
||||
int tmpsize = ftell(tmp->fd);
|
||||
fseek(tmp->fd, 0, SEEK_SET);
|
||||
unsigned char *in = ucmalloc(tmpsize);
|
||||
fread(in, tmpsize, 1, tmp->fd);
|
||||
|
||||
// and put it into the old file
|
||||
vault->fd = freopen(vault->filename, "wb+", vault->fd);
|
||||
fwrite(in, tmpsize, 1, vault->fd);
|
||||
}
|
||||
|
||||
void pcpvault_unlink(vault_t *tmp) {
|
||||
int i, tmpsize;
|
||||
unsigned char *r;
|
||||
fseek(tmp->fd, 0, SEEK_END);
|
||||
tmpsize = ftell(tmp->fd);
|
||||
r = ucmalloc(tmpsize);
|
||||
for (i=0; i<16; ++i) {
|
||||
fseek(tmp->fd, 0, SEEK_SET);
|
||||
arc4random_buf(r, tmpsize);
|
||||
fwrite(r, tmpsize, 1, tmp->fd);
|
||||
}
|
||||
fclose(tmp->fd);
|
||||
unlink(tmp->filename);
|
||||
free(r);
|
||||
}
|
||||
|
||||
int pcpvault_close(vault_t *vault) {
|
||||
if(vault != NULL) {
|
||||
if(vault->fd) {
|
||||
if(vault->unsafed == 1) {
|
||||
pcpvault_writeall(vault);
|
||||
}
|
||||
fclose(vault->fd);
|
||||
}
|
||||
free(vault);
|
||||
vault = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
vault_header_t * vh2be(vault_header_t *h) {
|
||||
h->version = htobe32(h->version);
|
||||
return h;
|
||||
}
|
||||
|
||||
vault_header_t * vh2native(vault_header_t *h) {
|
||||
h->version = be32toh(h->version);
|
||||
return h;
|
||||
}
|
||||
|
||||
vault_item_header_t * ih2be(vault_item_header_t *h) {
|
||||
h->version = htobe32(h->version);
|
||||
h->size = htobe32(h->size);
|
||||
return h;
|
||||
}
|
||||
|
||||
vault_item_header_t * ih2native(vault_item_header_t *h) {
|
||||
h->version = be32toh(h->version);
|
||||
h->size = be32toh(h->size);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
int pcpvault_fetchall(vault_t *vault) {
|
||||
fseek(vault->fd, 0, SEEK_SET);
|
||||
|
||||
vault_header_t *header = ucmalloc(sizeof(vault_header_t));
|
||||
vault_item_header_t *item = ucmalloc(sizeof(vault_item_header_t));
|
||||
fread(header, sizeof(vault_header_t), 1, vault->fd);
|
||||
vh2native(header);
|
||||
|
||||
if(header->fileid == PCP_VAULT_ID && header->version == PCP_VAULT_VERSION) {
|
||||
// loop over the file and slurp everything in
|
||||
pcpkey_hash = NULL;
|
||||
pcppubkey_hash = NULL;
|
||||
int readpos = 0;
|
||||
pcp_key_t *key;
|
||||
pcp_pubkey_t *pubkey;
|
||||
int bytesleft = 0;
|
||||
int ksize = sizeof(pcp_pubkey_t); // smallest possbile item
|
||||
|
||||
vault->version = header->version;
|
||||
memcpy(vault->checksum, header->checksum, 32);
|
||||
|
||||
for(;;) {
|
||||
readpos = ftell(vault->fd);
|
||||
if(vault->size - readpos >= sizeof(vault_item_header_t)) {
|
||||
// an item header follows
|
||||
fread(item, sizeof(vault_item_header_t), 1, vault->fd);
|
||||
ih2native(item);
|
||||
|
||||
if(item->size > 0) {
|
||||
// item is valid
|
||||
readpos = ftell(vault->fd);
|
||||
bytesleft = vault->size - readpos;
|
||||
if(bytesleft >= ksize) {
|
||||
// a key follows
|
||||
if(item->type == PCP_KEY_TYPE_MAINSECRET ||
|
||||
item->type == PCP_KEY_TYPE_SECRET) {
|
||||
// read a secret key
|
||||
key = ucmalloc(sizeof(pcp_key_t));
|
||||
fread(key, sizeof(pcp_key_t), 1, vault->fd);
|
||||
key2native(key);
|
||||
//pcp_dumpkey(key);
|
||||
HASH_ADD_STR( pcpkey_hash, id, key );
|
||||
}
|
||||
else if(item->type == PCP_KEY_TYPE_PUBLIC) {
|
||||
// read a public key
|
||||
pubkey = ucmalloc(sizeof(pcp_pubkey_t));
|
||||
fread(pubkey, sizeof(pcp_pubkey_t), 1, vault->fd);
|
||||
pubkey2native(pubkey);
|
||||
HASH_ADD_STR( pcppubkey_hash, id, pubkey );
|
||||
}
|
||||
else {
|
||||
fatal("Failed to read vault - invalid key type: %02X! at %d\n", item->type, readpos);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fatal("Failed to read vault - that's no pcp key at %d!\n", readpos);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fatal("Failed to read vault - invalid key item header size at %d!\n",
|
||||
readpos);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no more items
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
fatal("Unexpected vault file format!\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned char *checksum = NULL;
|
||||
checksum = pcpvault_create_checksum(vault);
|
||||
if(HASH_COUNT(pcpkey_hash) + HASH_COUNT(pcppubkey_hash) > 0) {
|
||||
// only validate the checksum if there are keys
|
||||
if(memcmp(checksum, vault->checksum, 32) != 0) {
|
||||
fatal("Error: the checksum of the key vault doesn't match its contents!\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
free(checksum);
|
||||
free(item);
|
||||
free(header);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(item);
|
||||
free(header);
|
||||
pcp_cleanhashes();
|
||||
|
||||
return -1;
|
||||
}
|
||||
62
libpcp/vault.h
Normal file
62
libpcp/vault.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef _HAVE_PCP_VAULT
|
||||
#define _HAVE_PCP_VAULT
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <sodium.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "mem.h"
|
||||
#include "key.h"
|
||||
#include "uthash.h"
|
||||
|
||||
|
||||
struct _vault_t {
|
||||
char *filename;
|
||||
FILE *fd;
|
||||
uint8_t unsafed;
|
||||
uint8_t isnew;
|
||||
uint32_t size;
|
||||
time_t modified;
|
||||
mode_t mode;
|
||||
uint32_t version;
|
||||
byte checksum[32];
|
||||
};
|
||||
|
||||
struct _vault_header_t {
|
||||
byte fileid;
|
||||
uint32_t version;
|
||||
byte checksum[32];
|
||||
};
|
||||
|
||||
struct _vault_item_header_t {
|
||||
byte type;
|
||||
uint32_t size;
|
||||
uint32_t version;
|
||||
byte checksum[32];
|
||||
};
|
||||
|
||||
typedef struct _vault_t vault_t;
|
||||
typedef struct _vault_header_t vault_header_t;
|
||||
typedef struct _vault_item_header_t vault_item_header_t;
|
||||
|
||||
vault_t *pcpvault_init(char *filename);
|
||||
vault_t *pcpvault_new(char *filename, int is_tmp);
|
||||
int pcpvault_create(vault_t *vault);
|
||||
int pcpvault_additem(vault_t *vault, void *item, size_t itemsize, uint8_t type, uint8_t do_hash);
|
||||
int pcpvault_close(vault_t *vault);
|
||||
int pcpvault_fetchall(vault_t *vault);
|
||||
int pcpvault_writeall(vault_t *vault);
|
||||
void pcpvault_copy(vault_t *tmp, vault_t *vault);
|
||||
void pcpvault_unlink(vault_t *tmp);
|
||||
unsigned char *pcpvault_create_checksum(vault_t *vault);
|
||||
void pcpvault_update_checksum(vault_t *vault);
|
||||
|
||||
vault_header_t * vh2be(vault_header_t *h);
|
||||
vault_header_t * vh2native(vault_header_t *h);
|
||||
vault_item_header_t * ih2be(vault_item_header_t *h);
|
||||
vault_item_header_t * ih2native(vault_item_header_t *h);
|
||||
|
||||
#endif // _HAVE_PCP_VAULT
|
||||
5
libpcp/version.c
Normal file
5
libpcp/version.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "version.h"
|
||||
|
||||
int pcp_version() {
|
||||
return PCP_VERSION;
|
||||
}
|
||||
15
libpcp/version.h
Normal file
15
libpcp/version.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _HAVE_PCP_VERSION
|
||||
#define _HAVE_PCP_VERSION
|
||||
|
||||
#define PCP_VERSION_MAJOR 0
|
||||
#define PCP_VERSION_MINOR 0
|
||||
#define PCP_VERSION_PATCH 1
|
||||
|
||||
#define PCP_MAKE_VERSION(major, minor, patch) \
|
||||
((major) * 10000 + (minor) * 100 + (patch))
|
||||
#define PCP_VERSION \
|
||||
PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH)
|
||||
|
||||
int pcp_version();
|
||||
|
||||
#endif // _HAVE_PCP_VERSION
|
||||
75
libpcp/warn.c
Normal file
75
libpcp/warn.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef HAVE_ERR_H
|
||||
/*
|
||||
* Everything is provided through err.h and the associated library, so we
|
||||
* don't need to do anything here.
|
||||
*/
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "warn.h"
|
||||
|
||||
const char * warn_progname = "(null)";
|
||||
|
||||
void
|
||||
warn(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s", warn_progname);
|
||||
if (fmt != NULL) {
|
||||
fprintf(stderr, ": ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
fprintf(stderr, ": %s\n", strerror(errno));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
warnx(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s", warn_progname);
|
||||
if (fmt != NULL) {
|
||||
fprintf(stderr, ": ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
13
libpcp/warn.h
Normal file
13
libpcp/warn.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _HAVE_PCP_WARN_H
|
||||
#define _HAVE_PCP_WARN_H
|
||||
|
||||
#ifdef HAVE_ERR_H
|
||||
#include <err.h>
|
||||
#else
|
||||
#define NEED_WARN_PROGNAME
|
||||
const char * warn_progname;
|
||||
void warn(const char *, ...);
|
||||
void warnx(const char *, ...);
|
||||
#endif
|
||||
|
||||
#endif /* !_HAVE_WARN_H */
|
||||
178
libpcp/z85.c
Normal file
178
libpcp/z85.c
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "z85.h"
|
||||
|
||||
unsigned char *pcp_padfour(unsigned char *src, size_t srclen, size_t *dstlen) {
|
||||
size_t outlen, zerolen;
|
||||
unsigned char *dst;
|
||||
|
||||
outlen = srclen + 1; // 1 for the pad flag
|
||||
while (outlen % 4 != 0) outlen++;
|
||||
zerolen = outlen - (srclen + 1);
|
||||
|
||||
dst = (unsigned char*)ucmalloc(outlen);
|
||||
dst[0] = zerolen; // add the number of zeros we add
|
||||
memcpy(&dst[1], src, srclen); // add the original
|
||||
bzero(&dst[srclen+1], zerolen); // pad with zeroes
|
||||
|
||||
*dstlen = outlen;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
unsigned char *pcp_unpadfour(unsigned char *src, size_t srclen, size_t *dstlen) {
|
||||
size_t outlen;
|
||||
size_t numzeroes;
|
||||
unsigned char *dst;
|
||||
|
||||
numzeroes = src[0]; // first byte tells us how many zeroes we've got
|
||||
outlen = srclen - 1 - numzeroes;
|
||||
|
||||
dst = malloc(outlen);
|
||||
|
||||
memcpy(dst, &src[1], outlen);
|
||||
|
||||
*dstlen = outlen;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
unsigned char *pcp_z85_decode(char *z85block, size_t *dstlen) {
|
||||
unsigned char *bin;
|
||||
int i, pos;
|
||||
size_t zlen, binlen, outlen;
|
||||
|
||||
zlen = strlen(z85block);
|
||||
char *z85 = ucmalloc(zlen);
|
||||
|
||||
// remove newlines
|
||||
pos = 0;
|
||||
for(i=0; i<zlen+1; ++i) {
|
||||
if(z85block[i] != '\r' && z85block[i] != '\n') {
|
||||
z85[pos] = z85block[i];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
binlen = strlen (z85) * 4 / 5;
|
||||
bin = ucmalloc(binlen);
|
||||
bin = zmq_z85_decode(bin, z85);
|
||||
|
||||
unsigned char *raw = NULL;
|
||||
if(bin != NULL) {
|
||||
raw = pcp_unpadfour(bin, binlen, &outlen);
|
||||
}
|
||||
|
||||
free(z85);
|
||||
free(bin);
|
||||
|
||||
*dstlen = outlen;
|
||||
return raw;
|
||||
}
|
||||
|
||||
char *pcp_z85_encode(unsigned char *raw, size_t srclen, size_t *dstlen) {
|
||||
int i, pos, b;
|
||||
size_t outlen, blocklen, zlen;
|
||||
|
||||
// make z85 happy (size % 4)
|
||||
unsigned char *padded = pcp_padfour(raw, srclen, &outlen);
|
||||
|
||||
// encode to z85
|
||||
zlen = (outlen * 5 / 4) + 1;
|
||||
char *z85 = ucmalloc(zlen);
|
||||
z85 = zmq_z85_encode(z85, padded, outlen);
|
||||
|
||||
// make it a 72 chars wide block
|
||||
blocklen = strlen(z85) + ((strlen(z85) / 72) * 2) + 1;
|
||||
char *z85block = ucmalloc(blocklen);
|
||||
|
||||
pos = b = 0;
|
||||
for(i=0; i<zlen; ++i) {
|
||||
if(pos >= 71) {
|
||||
z85block[b++] = '\r';
|
||||
z85block[b++] = '\n';
|
||||
pos = 1;
|
||||
}
|
||||
else {
|
||||
pos++;
|
||||
}
|
||||
z85block[b++] = z85[i];
|
||||
}
|
||||
|
||||
*dstlen = blocklen;
|
||||
free(z85);
|
||||
free(padded);
|
||||
|
||||
return z85block;
|
||||
}
|
||||
|
||||
|
||||
char *pcp_readz85file(FILE *infile) {
|
||||
unsigned char *input = NULL;
|
||||
unsigned char *out = NULL;
|
||||
unsigned char *tmp = NULL;
|
||||
char *ret;
|
||||
char *line;
|
||||
unsigned char byte[1];
|
||||
int i, outsize, lpos, x;
|
||||
size_t bufsize = 0;
|
||||
lpos = outsize = 0;
|
||||
size_t MAXLINE = 1024;
|
||||
|
||||
while(!feof(infile)) {
|
||||
if(!fread(&byte, 1, 1, infile))
|
||||
break;
|
||||
tmp = realloc(input, bufsize + 1);
|
||||
input = tmp;
|
||||
memmove(&input[bufsize], byte, 1);
|
||||
bufsize ++;
|
||||
}
|
||||
|
||||
if(bufsize == 0) {
|
||||
fatal("Input file is empty!\n");
|
||||
goto rferrx;
|
||||
}
|
||||
|
||||
out = ucmalloc(bufsize);
|
||||
line = ucmalloc(MAXLINE);
|
||||
|
||||
for(i=0; i<bufsize; ++i) {
|
||||
if(lpos > MAXLINE) {
|
||||
// huh, now that's suspicious
|
||||
fatal("Invalid input, line is too long (%d bytes so far)!\n", lpos);
|
||||
goto rferr;
|
||||
}
|
||||
if(input[i] != '\n' && input[i] != '\r') {
|
||||
line[lpos++] = input[i];
|
||||
}
|
||||
else {
|
||||
if(line[0] != ' ' && strncmp(line, "-----", 5) != 0) {
|
||||
if(lpos > 0) {
|
||||
for(x=0;x<lpos;++x)
|
||||
out[outsize+x] = line[x];
|
||||
outsize += lpos;
|
||||
lpos = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lpos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out[outsize+1] = '\0';
|
||||
|
||||
ret = ucmalloc(outsize+1);
|
||||
memcpy(ret, out, outsize+1);
|
||||
|
||||
free(tmp);
|
||||
free(out);
|
||||
free(line);
|
||||
|
||||
return ret;
|
||||
|
||||
rferr:
|
||||
free(out);
|
||||
free(line);
|
||||
rferrx:
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
23
libpcp/z85.h
Normal file
23
libpcp/z85.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// from https://github.com/tlinden/curve-keygen/
|
||||
#ifndef _HAVE_PCP_Z85_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "zmq_z85.h"
|
||||
#include "mem.h"
|
||||
|
||||
// convert a binary stream to one which gets accepted by zmq_z85_encode
|
||||
// we pad it with zeroes and put the number of zerores in front of it
|
||||
unsigned char *pcp_unpadfour(unsigned char *src, size_t srclen, size_t *dstlen);
|
||||
|
||||
// the reverse of the above
|
||||
unsigned char *pcp_unpadfour(unsigned char *src, size_t srclen, size_t *dstlen);
|
||||
|
||||
// wrapper around zmq Z85 encoding function
|
||||
unsigned char *pcp_z85_decode(char *z85block, size_t *dstlen);
|
||||
|
||||
// the reverse of the above
|
||||
char *pcp_z85_encode(unsigned char *raw, size_t srclen, size_t *dstlen);
|
||||
|
||||
char *pcp_readz85file(FILE *infile);
|
||||
|
||||
#endif // _HAVE_PCP_Z85_H
|
||||
110
libpcp/zmq_z85.c
Normal file
110
libpcp/zmq_z85.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of 0MQ.
|
||||
|
||||
0MQ is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
0MQ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "zmq_z85.h"
|
||||
|
||||
// Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding
|
||||
|
||||
// Maps base 256 to base 85
|
||||
static char encoder [85 + 1] = {
|
||||
"0123456789" "abcdefghij" "klmnopqrst" "uvwxyzABCD"
|
||||
"EFGHIJKLMN" "OPQRSTUVWX" "YZ.-:+=^!/" "*?&<>()[]{"
|
||||
"}@%$#"
|
||||
};
|
||||
|
||||
// Maps base 85 to base 256
|
||||
// We chop off lower 32 and higher 128 ranges
|
||||
static uint8_t decoder [96] = {
|
||||
0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
|
||||
0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
|
||||
0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
|
||||
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
|
||||
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
|
||||
0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
|
||||
0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
|
||||
0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Encode a binary frame as a string; destination string MUST be at least
|
||||
// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
|
||||
// dest. Size must be a multiple of 4.
|
||||
|
||||
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
|
||||
{
|
||||
if (size % 4 != 0)
|
||||
return NULL; // !assert
|
||||
|
||||
unsigned int char_nbr = 0;
|
||||
unsigned int byte_nbr = 0;
|
||||
uint32_t value = 0;
|
||||
while (byte_nbr < size) {
|
||||
// Accumulate value in base 256 (binary)
|
||||
value = value * 256 + data [byte_nbr++];
|
||||
if (byte_nbr % 4 == 0) {
|
||||
// Output value in base 85
|
||||
unsigned int divisor = 85 * 85 * 85 * 85;
|
||||
while (divisor) {
|
||||
dest [char_nbr++] = encoder [value / divisor % 85];
|
||||
divisor /= 85;
|
||||
}
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if (char_nbr != size * 5 / 4)
|
||||
return NULL; // !assert
|
||||
|
||||
dest [char_nbr] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Decode an encoded string into a binary frame; dest must be at least
|
||||
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
|
||||
// must be a multiple of 5.
|
||||
|
||||
uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
|
||||
{
|
||||
if (strlen (string) % 5 != 0)
|
||||
return NULL; // !assert
|
||||
unsigned int byte_nbr = 0;
|
||||
unsigned int char_nbr = 0;
|
||||
uint32_t value = 0;
|
||||
while (char_nbr < strlen (string)) {
|
||||
// Accumulate value in base 85
|
||||
value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32];
|
||||
if (char_nbr % 5 == 0) {
|
||||
// Output value in base 256
|
||||
unsigned int divisor = 256 * 256 * 256;
|
||||
while (divisor) {
|
||||
dest [byte_nbr++] = value / divisor % 256;
|
||||
divisor /= 256;
|
||||
}
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if (byte_nbr != strlen (string) * 4 / 5)
|
||||
return NULL; //!assert
|
||||
return dest;
|
||||
}
|
||||
39
libpcp/zmq_z85.h
Normal file
39
libpcp/zmq_z85.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of 0MQ.
|
||||
|
||||
0MQ is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
0MQ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_Z85_H_INCLUDED__
|
||||
#define __ZMQ_Z85_H_INCLUDED__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
|
||||
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user