summaryrefslogtreecommitdiffstats
path: root/kbx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--kbx/Makefile.am67
-rw-r--r--kbx/Makefile.in1309
-rw-r--r--kbx/kbxutil.c644
-rw-r--r--kbx/keybox-blob.c1057
-rw-r--r--kbx/keybox-defs.h210
-rw-r--r--kbx/keybox-dump.c915
-rw-r--r--kbx/keybox-file.c190
-rw-r--r--kbx/keybox-init.c352
-rw-r--r--kbx/keybox-openpgp.c643
-rw-r--r--kbx/keybox-search-desc.h86
-rw-r--r--kbx/keybox-search.c1322
-rw-r--r--kbx/keybox-update.c788
-rw-r--r--kbx/keybox-util.c102
-rw-r--r--kbx/keybox.h137
-rwxr-xr-xkbx/mkerrors70
15 files changed, 7892 insertions, 0 deletions
diff --git a/kbx/Makefile.am b/kbx/Makefile.am
new file mode 100644
index 0000000..7b0a8a8
--- /dev/null
+++ b/kbx/Makefile.am
@@ -0,0 +1,67 @@
+# Keybox Makefile
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = mkerrors
+
+AM_CPPFLAGS =
+
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS)
+
+noinst_LIBRARIES = libkeybox.a libkeybox509.a
+bin_PROGRAMS = kbxutil
+
+if HAVE_W32CE_SYSTEM
+extra_libs = $(LIBASSUAN_LIBS)
+else
+extra_libs =
+endif
+
+common_sources = \
+ keybox.h keybox-defs.h keybox-search-desc.h \
+ keybox-util.c \
+ keybox-init.c \
+ keybox-blob.c \
+ keybox-file.c \
+ keybox-search.c \
+ keybox-update.c \
+ keybox-openpgp.c \
+ keybox-dump.c
+
+
+libkeybox_a_SOURCES = $(common_sources)
+libkeybox509_a_SOURCES = $(common_sources)
+
+libkeybox_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
+libkeybox509_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) \
+ -DKEYBOX_WITH_X509=1
+
+# We need W32SOCKLIBS because the init subsystem code in libcommon
+# requires it - although we don't actually need it. It is easier
+# to do it this way.
+kbxutil_SOURCES = kbxutil.c $(common_sources)
+kbxutil_CFLAGS = $(AM_CFLAGS) -DKEYBOX_WITH_X509=1
+kbxutil_LDADD = ../common/libcommon.a \
+ $(KSBA_LIBS) $(LIBGCRYPT_LIBS) $(extra_libs) \
+ $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS) \
+ $(NETLIBS)
+
+$(PROGRAMS) : ../common/libcommon.a
diff --git a/kbx/Makefile.in b/kbx/Makefile.in
new file mode 100644
index 0000000..c3a58cb
--- /dev/null
+++ b/kbx/Makefile.in
@@ -0,0 +1,1309 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 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@
+
+# Keybox Makefile
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+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@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+bin_PROGRAMS = kbxutil$(EXEEXT)
+subdir = kbx
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libkeybox_a_AR = $(AR) $(ARFLAGS)
+libkeybox_a_LIBADD =
+am__objects_1 = libkeybox_a-keybox-util.$(OBJEXT) \
+ libkeybox_a-keybox-init.$(OBJEXT) \
+ libkeybox_a-keybox-blob.$(OBJEXT) \
+ libkeybox_a-keybox-file.$(OBJEXT) \
+ libkeybox_a-keybox-search.$(OBJEXT) \
+ libkeybox_a-keybox-update.$(OBJEXT) \
+ libkeybox_a-keybox-openpgp.$(OBJEXT) \
+ libkeybox_a-keybox-dump.$(OBJEXT)
+am_libkeybox_a_OBJECTS = $(am__objects_1)
+libkeybox_a_OBJECTS = $(am_libkeybox_a_OBJECTS)
+libkeybox509_a_AR = $(AR) $(ARFLAGS)
+libkeybox509_a_LIBADD =
+am__objects_2 = libkeybox509_a-keybox-util.$(OBJEXT) \
+ libkeybox509_a-keybox-init.$(OBJEXT) \
+ libkeybox509_a-keybox-blob.$(OBJEXT) \
+ libkeybox509_a-keybox-file.$(OBJEXT) \
+ libkeybox509_a-keybox-search.$(OBJEXT) \
+ libkeybox509_a-keybox-update.$(OBJEXT) \
+ libkeybox509_a-keybox-openpgp.$(OBJEXT) \
+ libkeybox509_a-keybox-dump.$(OBJEXT)
+am_libkeybox509_a_OBJECTS = $(am__objects_2)
+libkeybox509_a_OBJECTS = $(am_libkeybox509_a_OBJECTS)
+am__objects_3 = kbxutil-keybox-util.$(OBJEXT) \
+ kbxutil-keybox-init.$(OBJEXT) kbxutil-keybox-blob.$(OBJEXT) \
+ kbxutil-keybox-file.$(OBJEXT) kbxutil-keybox-search.$(OBJEXT) \
+ kbxutil-keybox-update.$(OBJEXT) \
+ kbxutil-keybox-openpgp.$(OBJEXT) kbxutil-keybox-dump.$(OBJEXT)
+am_kbxutil_OBJECTS = kbxutil-kbxutil.$(OBJEXT) $(am__objects_3)
+kbxutil_OBJECTS = $(am_kbxutil_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_W32CE_SYSTEM_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+kbxutil_DEPENDENCIES = ../common/libcommon.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+kbxutil_LINK = $(CCLD) $(kbxutil_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/kbxutil-kbxutil.Po \
+ ./$(DEPDIR)/kbxutil-keybox-blob.Po \
+ ./$(DEPDIR)/kbxutil-keybox-dump.Po \
+ ./$(DEPDIR)/kbxutil-keybox-file.Po \
+ ./$(DEPDIR)/kbxutil-keybox-init.Po \
+ ./$(DEPDIR)/kbxutil-keybox-openpgp.Po \
+ ./$(DEPDIR)/kbxutil-keybox-search.Po \
+ ./$(DEPDIR)/kbxutil-keybox-update.Po \
+ ./$(DEPDIR)/kbxutil-keybox-util.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-blob.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-dump.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-file.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-init.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-openpgp.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-search.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-update.Po \
+ ./$(DEPDIR)/libkeybox509_a-keybox-util.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-blob.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-dump.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-file.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-init.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-openpgp.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-search.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-update.Po \
+ ./$(DEPDIR)/libkeybox_a-keybox-util.Po
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libkeybox_a_SOURCES) $(libkeybox509_a_SOURCES) \
+ $(kbxutil_SOURCES)
+DIST_SOURCES = $(libkeybox_a_SOURCES) $(libkeybox509_a_SOURCES) \
+ $(kbxutil_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+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 = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+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@
+EXTRA_DIST = mkerrors
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(am__append_1) \
+ $(am__append_2) $(am__append_3) $(am__append_4) \
+ $(am__append_5) $(am__append_6) $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS)
+noinst_LIBRARIES = libkeybox.a libkeybox509.a
+@HAVE_W32CE_SYSTEM_FALSE@extra_libs =
+@HAVE_W32CE_SYSTEM_TRUE@extra_libs = $(LIBASSUAN_LIBS)
+common_sources = \
+ keybox.h keybox-defs.h keybox-search-desc.h \
+ keybox-util.c \
+ keybox-init.c \
+ keybox-blob.c \
+ keybox-file.c \
+ keybox-search.c \
+ keybox-update.c \
+ keybox-openpgp.c \
+ keybox-dump.c
+
+libkeybox_a_SOURCES = $(common_sources)
+libkeybox509_a_SOURCES = $(common_sources)
+libkeybox_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
+libkeybox509_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) \
+ -DKEYBOX_WITH_X509=1
+
+
+# We need W32SOCKLIBS because the init subsystem code in libcommon
+# requires it - although we don't actually need it. It is easier
+# to do it this way.
+kbxutil_SOURCES = kbxutil.c $(common_sources)
+kbxutil_CFLAGS = $(AM_CFLAGS) -DKEYBOX_WITH_X509=1
+kbxutil_LDADD = ../common/libcommon.a \
+ $(KSBA_LIBS) $(LIBGCRYPT_LIBS) $(extra_libs) \
+ $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS) \
+ $(NETLIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.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 kbx/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu kbx/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libkeybox.a: $(libkeybox_a_OBJECTS) $(libkeybox_a_DEPENDENCIES) $(EXTRA_libkeybox_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libkeybox.a
+ $(AM_V_AR)$(libkeybox_a_AR) libkeybox.a $(libkeybox_a_OBJECTS) $(libkeybox_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libkeybox.a
+
+libkeybox509.a: $(libkeybox509_a_OBJECTS) $(libkeybox509_a_DEPENDENCIES) $(EXTRA_libkeybox509_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libkeybox509.a
+ $(AM_V_AR)$(libkeybox509_a_AR) libkeybox509.a $(libkeybox509_a_OBJECTS) $(libkeybox509_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libkeybox509.a
+
+kbxutil$(EXEEXT): $(kbxutil_OBJECTS) $(kbxutil_DEPENDENCIES) $(EXTRA_kbxutil_DEPENDENCIES)
+ @rm -f kbxutil$(EXEEXT)
+ $(AM_V_CCLD)$(kbxutil_LINK) $(kbxutil_OBJECTS) $(kbxutil_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-kbxutil.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-blob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-dump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-file.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-init.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-openpgp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-search.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-update.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbxutil-keybox-util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-blob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-dump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-file.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-init.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-openpgp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-search.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-update.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox509_a-keybox-util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-blob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-dump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-file.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-init.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-openpgp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-search.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-update.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkeybox_a-keybox-util.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libkeybox_a-keybox-util.o: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-util.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-util.Tpo -c -o libkeybox_a-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-util.Tpo $(DEPDIR)/libkeybox_a-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='libkeybox_a-keybox-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+
+libkeybox_a-keybox-util.obj: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-util.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-util.Tpo -c -o libkeybox_a-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-util.Tpo $(DEPDIR)/libkeybox_a-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='libkeybox_a-keybox-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+
+libkeybox_a-keybox-init.o: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-init.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-init.Tpo -c -o libkeybox_a-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-init.Tpo $(DEPDIR)/libkeybox_a-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='libkeybox_a-keybox-init.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+
+libkeybox_a-keybox-init.obj: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-init.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-init.Tpo -c -o libkeybox_a-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-init.Tpo $(DEPDIR)/libkeybox_a-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='libkeybox_a-keybox-init.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+
+libkeybox_a-keybox-blob.o: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-blob.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-blob.Tpo -c -o libkeybox_a-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-blob.Tpo $(DEPDIR)/libkeybox_a-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='libkeybox_a-keybox-blob.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+
+libkeybox_a-keybox-blob.obj: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-blob.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-blob.Tpo -c -o libkeybox_a-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-blob.Tpo $(DEPDIR)/libkeybox_a-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='libkeybox_a-keybox-blob.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+
+libkeybox_a-keybox-file.o: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-file.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-file.Tpo -c -o libkeybox_a-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-file.Tpo $(DEPDIR)/libkeybox_a-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='libkeybox_a-keybox-file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+
+libkeybox_a-keybox-file.obj: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-file.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-file.Tpo -c -o libkeybox_a-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-file.Tpo $(DEPDIR)/libkeybox_a-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='libkeybox_a-keybox-file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+
+libkeybox_a-keybox-search.o: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-search.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-search.Tpo -c -o libkeybox_a-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-search.Tpo $(DEPDIR)/libkeybox_a-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='libkeybox_a-keybox-search.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+
+libkeybox_a-keybox-search.obj: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-search.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-search.Tpo -c -o libkeybox_a-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-search.Tpo $(DEPDIR)/libkeybox_a-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='libkeybox_a-keybox-search.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+
+libkeybox_a-keybox-update.o: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-update.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-update.Tpo -c -o libkeybox_a-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-update.Tpo $(DEPDIR)/libkeybox_a-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='libkeybox_a-keybox-update.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+
+libkeybox_a-keybox-update.obj: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-update.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-update.Tpo -c -o libkeybox_a-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-update.Tpo $(DEPDIR)/libkeybox_a-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='libkeybox_a-keybox-update.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+
+libkeybox_a-keybox-openpgp.o: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-openpgp.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-openpgp.Tpo -c -o libkeybox_a-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-openpgp.Tpo $(DEPDIR)/libkeybox_a-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='libkeybox_a-keybox-openpgp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+
+libkeybox_a-keybox-openpgp.obj: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-openpgp.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-openpgp.Tpo -c -o libkeybox_a-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-openpgp.Tpo $(DEPDIR)/libkeybox_a-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='libkeybox_a-keybox-openpgp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+
+libkeybox_a-keybox-dump.o: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-dump.o -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-dump.Tpo -c -o libkeybox_a-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-dump.Tpo $(DEPDIR)/libkeybox_a-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='libkeybox_a-keybox-dump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+
+libkeybox_a-keybox-dump.obj: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -MT libkeybox_a-keybox-dump.obj -MD -MP -MF $(DEPDIR)/libkeybox_a-keybox-dump.Tpo -c -o libkeybox_a-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox_a-keybox-dump.Tpo $(DEPDIR)/libkeybox_a-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='libkeybox_a-keybox-dump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox_a_CFLAGS) $(CFLAGS) -c -o libkeybox_a-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+
+libkeybox509_a-keybox-util.o: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-util.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-util.Tpo -c -o libkeybox509_a-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-util.Tpo $(DEPDIR)/libkeybox509_a-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='libkeybox509_a-keybox-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+
+libkeybox509_a-keybox-util.obj: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-util.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-util.Tpo -c -o libkeybox509_a-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-util.Tpo $(DEPDIR)/libkeybox509_a-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='libkeybox509_a-keybox-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+
+libkeybox509_a-keybox-init.o: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-init.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-init.Tpo -c -o libkeybox509_a-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-init.Tpo $(DEPDIR)/libkeybox509_a-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='libkeybox509_a-keybox-init.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+
+libkeybox509_a-keybox-init.obj: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-init.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-init.Tpo -c -o libkeybox509_a-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-init.Tpo $(DEPDIR)/libkeybox509_a-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='libkeybox509_a-keybox-init.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+
+libkeybox509_a-keybox-blob.o: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-blob.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-blob.Tpo -c -o libkeybox509_a-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-blob.Tpo $(DEPDIR)/libkeybox509_a-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='libkeybox509_a-keybox-blob.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+
+libkeybox509_a-keybox-blob.obj: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-blob.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-blob.Tpo -c -o libkeybox509_a-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-blob.Tpo $(DEPDIR)/libkeybox509_a-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='libkeybox509_a-keybox-blob.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+
+libkeybox509_a-keybox-file.o: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-file.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-file.Tpo -c -o libkeybox509_a-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-file.Tpo $(DEPDIR)/libkeybox509_a-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='libkeybox509_a-keybox-file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+
+libkeybox509_a-keybox-file.obj: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-file.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-file.Tpo -c -o libkeybox509_a-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-file.Tpo $(DEPDIR)/libkeybox509_a-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='libkeybox509_a-keybox-file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+
+libkeybox509_a-keybox-search.o: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-search.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-search.Tpo -c -o libkeybox509_a-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-search.Tpo $(DEPDIR)/libkeybox509_a-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='libkeybox509_a-keybox-search.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+
+libkeybox509_a-keybox-search.obj: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-search.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-search.Tpo -c -o libkeybox509_a-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-search.Tpo $(DEPDIR)/libkeybox509_a-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='libkeybox509_a-keybox-search.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+
+libkeybox509_a-keybox-update.o: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-update.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-update.Tpo -c -o libkeybox509_a-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-update.Tpo $(DEPDIR)/libkeybox509_a-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='libkeybox509_a-keybox-update.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+
+libkeybox509_a-keybox-update.obj: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-update.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-update.Tpo -c -o libkeybox509_a-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-update.Tpo $(DEPDIR)/libkeybox509_a-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='libkeybox509_a-keybox-update.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+
+libkeybox509_a-keybox-openpgp.o: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-openpgp.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-openpgp.Tpo -c -o libkeybox509_a-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-openpgp.Tpo $(DEPDIR)/libkeybox509_a-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='libkeybox509_a-keybox-openpgp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+
+libkeybox509_a-keybox-openpgp.obj: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-openpgp.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-openpgp.Tpo -c -o libkeybox509_a-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-openpgp.Tpo $(DEPDIR)/libkeybox509_a-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='libkeybox509_a-keybox-openpgp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+
+libkeybox509_a-keybox-dump.o: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-dump.o -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-dump.Tpo -c -o libkeybox509_a-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-dump.Tpo $(DEPDIR)/libkeybox509_a-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='libkeybox509_a-keybox-dump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+
+libkeybox509_a-keybox-dump.obj: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -MT libkeybox509_a-keybox-dump.obj -MD -MP -MF $(DEPDIR)/libkeybox509_a-keybox-dump.Tpo -c -o libkeybox509_a-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkeybox509_a-keybox-dump.Tpo $(DEPDIR)/libkeybox509_a-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='libkeybox509_a-keybox-dump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libkeybox509_a_CFLAGS) $(CFLAGS) -c -o libkeybox509_a-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+
+kbxutil-kbxutil.o: kbxutil.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-kbxutil.o -MD -MP -MF $(DEPDIR)/kbxutil-kbxutil.Tpo -c -o kbxutil-kbxutil.o `test -f 'kbxutil.c' || echo '$(srcdir)/'`kbxutil.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-kbxutil.Tpo $(DEPDIR)/kbxutil-kbxutil.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kbxutil.c' object='kbxutil-kbxutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-kbxutil.o `test -f 'kbxutil.c' || echo '$(srcdir)/'`kbxutil.c
+
+kbxutil-kbxutil.obj: kbxutil.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-kbxutil.obj -MD -MP -MF $(DEPDIR)/kbxutil-kbxutil.Tpo -c -o kbxutil-kbxutil.obj `if test -f 'kbxutil.c'; then $(CYGPATH_W) 'kbxutil.c'; else $(CYGPATH_W) '$(srcdir)/kbxutil.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-kbxutil.Tpo $(DEPDIR)/kbxutil-kbxutil.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kbxutil.c' object='kbxutil-kbxutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-kbxutil.obj `if test -f 'kbxutil.c'; then $(CYGPATH_W) 'kbxutil.c'; else $(CYGPATH_W) '$(srcdir)/kbxutil.c'; fi`
+
+kbxutil-keybox-util.o: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-util.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-util.Tpo -c -o kbxutil-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-util.Tpo $(DEPDIR)/kbxutil-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='kbxutil-keybox-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-util.o `test -f 'keybox-util.c' || echo '$(srcdir)/'`keybox-util.c
+
+kbxutil-keybox-util.obj: keybox-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-util.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-util.Tpo -c -o kbxutil-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-util.Tpo $(DEPDIR)/kbxutil-keybox-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-util.c' object='kbxutil-keybox-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-util.obj `if test -f 'keybox-util.c'; then $(CYGPATH_W) 'keybox-util.c'; else $(CYGPATH_W) '$(srcdir)/keybox-util.c'; fi`
+
+kbxutil-keybox-init.o: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-init.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-init.Tpo -c -o kbxutil-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-init.Tpo $(DEPDIR)/kbxutil-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='kbxutil-keybox-init.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-init.o `test -f 'keybox-init.c' || echo '$(srcdir)/'`keybox-init.c
+
+kbxutil-keybox-init.obj: keybox-init.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-init.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-init.Tpo -c -o kbxutil-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-init.Tpo $(DEPDIR)/kbxutil-keybox-init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-init.c' object='kbxutil-keybox-init.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-init.obj `if test -f 'keybox-init.c'; then $(CYGPATH_W) 'keybox-init.c'; else $(CYGPATH_W) '$(srcdir)/keybox-init.c'; fi`
+
+kbxutil-keybox-blob.o: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-blob.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-blob.Tpo -c -o kbxutil-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-blob.Tpo $(DEPDIR)/kbxutil-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='kbxutil-keybox-blob.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-blob.o `test -f 'keybox-blob.c' || echo '$(srcdir)/'`keybox-blob.c
+
+kbxutil-keybox-blob.obj: keybox-blob.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-blob.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-blob.Tpo -c -o kbxutil-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-blob.Tpo $(DEPDIR)/kbxutil-keybox-blob.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-blob.c' object='kbxutil-keybox-blob.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-blob.obj `if test -f 'keybox-blob.c'; then $(CYGPATH_W) 'keybox-blob.c'; else $(CYGPATH_W) '$(srcdir)/keybox-blob.c'; fi`
+
+kbxutil-keybox-file.o: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-file.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-file.Tpo -c -o kbxutil-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-file.Tpo $(DEPDIR)/kbxutil-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='kbxutil-keybox-file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-file.o `test -f 'keybox-file.c' || echo '$(srcdir)/'`keybox-file.c
+
+kbxutil-keybox-file.obj: keybox-file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-file.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-file.Tpo -c -o kbxutil-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-file.Tpo $(DEPDIR)/kbxutil-keybox-file.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-file.c' object='kbxutil-keybox-file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-file.obj `if test -f 'keybox-file.c'; then $(CYGPATH_W) 'keybox-file.c'; else $(CYGPATH_W) '$(srcdir)/keybox-file.c'; fi`
+
+kbxutil-keybox-search.o: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-search.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-search.Tpo -c -o kbxutil-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-search.Tpo $(DEPDIR)/kbxutil-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='kbxutil-keybox-search.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-search.o `test -f 'keybox-search.c' || echo '$(srcdir)/'`keybox-search.c
+
+kbxutil-keybox-search.obj: keybox-search.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-search.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-search.Tpo -c -o kbxutil-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-search.Tpo $(DEPDIR)/kbxutil-keybox-search.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-search.c' object='kbxutil-keybox-search.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-search.obj `if test -f 'keybox-search.c'; then $(CYGPATH_W) 'keybox-search.c'; else $(CYGPATH_W) '$(srcdir)/keybox-search.c'; fi`
+
+kbxutil-keybox-update.o: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-update.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-update.Tpo -c -o kbxutil-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-update.Tpo $(DEPDIR)/kbxutil-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='kbxutil-keybox-update.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-update.o `test -f 'keybox-update.c' || echo '$(srcdir)/'`keybox-update.c
+
+kbxutil-keybox-update.obj: keybox-update.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-update.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-update.Tpo -c -o kbxutil-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-update.Tpo $(DEPDIR)/kbxutil-keybox-update.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-update.c' object='kbxutil-keybox-update.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-update.obj `if test -f 'keybox-update.c'; then $(CYGPATH_W) 'keybox-update.c'; else $(CYGPATH_W) '$(srcdir)/keybox-update.c'; fi`
+
+kbxutil-keybox-openpgp.o: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-openpgp.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-openpgp.Tpo -c -o kbxutil-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-openpgp.Tpo $(DEPDIR)/kbxutil-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='kbxutil-keybox-openpgp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-openpgp.o `test -f 'keybox-openpgp.c' || echo '$(srcdir)/'`keybox-openpgp.c
+
+kbxutil-keybox-openpgp.obj: keybox-openpgp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-openpgp.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-openpgp.Tpo -c -o kbxutil-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-openpgp.Tpo $(DEPDIR)/kbxutil-keybox-openpgp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-openpgp.c' object='kbxutil-keybox-openpgp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-openpgp.obj `if test -f 'keybox-openpgp.c'; then $(CYGPATH_W) 'keybox-openpgp.c'; else $(CYGPATH_W) '$(srcdir)/keybox-openpgp.c'; fi`
+
+kbxutil-keybox-dump.o: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-dump.o -MD -MP -MF $(DEPDIR)/kbxutil-keybox-dump.Tpo -c -o kbxutil-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-dump.Tpo $(DEPDIR)/kbxutil-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='kbxutil-keybox-dump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-dump.o `test -f 'keybox-dump.c' || echo '$(srcdir)/'`keybox-dump.c
+
+kbxutil-keybox-dump.obj: keybox-dump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -MT kbxutil-keybox-dump.obj -MD -MP -MF $(DEPDIR)/kbxutil-keybox-dump.Tpo -c -o kbxutil-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kbxutil-keybox-dump.Tpo $(DEPDIR)/kbxutil-keybox-dump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keybox-dump.c' object='kbxutil-keybox-dump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kbxutil_CFLAGS) $(CFLAGS) -c -o kbxutil-keybox-dump.obj `if test -f 'keybox-dump.c'; then $(CYGPATH_W) 'keybox-dump.c'; else $(CYGPATH_W) '$(srcdir)/keybox-dump.c'; fi`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ 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-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ 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: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ 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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(PROGRAMS) $(LIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; 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-binPROGRAMS clean-generic clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/kbxutil-kbxutil.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-file.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-init.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-search.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-update.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-util.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-file.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-init.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-search.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-update.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-util.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-file.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-init.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-search.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-update.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-util.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+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 -f ./$(DEPDIR)/kbxutil-kbxutil.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-file.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-init.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-search.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-update.Po
+ -rm -f ./$(DEPDIR)/kbxutil-keybox-util.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-file.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-init.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-search.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-update.Po
+ -rm -f ./$(DEPDIR)/libkeybox509_a-keybox-util.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-blob.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-dump.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-file.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-init.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-openpgp.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-search.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-update.Po
+ -rm -f ./$(DEPDIR)/libkeybox_a-keybox-util.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am 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 pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-binPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+$(PROGRAMS) : ../common/libcommon.a
+
+# 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:
diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c
new file mode 100644
index 0000000..9e05de4
--- /dev/null
+++ b/kbx/kbxutil.c
@@ -0,0 +1,644 @@
+/* kbxutil.c - The Keybox utility
+ * Copyright (C) 2000, 2001, 2004, 2007, 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+
+#include <gpg-error.h>
+#include "../common/logging.h"
+#include "../common/argparse.h"
+#include "../common/stringhelp.h"
+#include "../common/utf8conv.h"
+#include "../common/i18n.h"
+#include "keybox-defs.h"
+#include "../common/init.h"
+#include <gcrypt.h>
+
+
+enum cmd_and_opt_values {
+ aNull = 0,
+ oArmor = 'a',
+ oDryRun = 'n',
+ oOutput = 'o',
+ oQuiet = 'q',
+ oVerbose = 'v',
+
+ aNoSuchCmd = 500, /* force other values not to be a letter */
+ aFindByFpr,
+ aFindByKid,
+ aFindByUid,
+ aStats,
+ aImportOpenPGP,
+ aFindDups,
+ aCut,
+
+ oDebug,
+ oDebugAll,
+
+ oNoArmor,
+ oFrom,
+ oTo,
+
+ aTest
+};
+
+
+static ARGPARSE_OPTS opts[] = {
+ { 300, NULL, 0, N_("@Commands:\n ") },
+
+/* { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */
+/* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */
+/* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */
+ { aStats, "stats", 0, "show key statistics" },
+ { aImportOpenPGP, "import-openpgp", 0, "import OpenPGP keyblocks"},
+ { aFindDups, "find-dups", 0, "find duplicates" },
+ { aCut, "cut", 0, "export records" },
+
+ { 301, NULL, 0, N_("@\nOptions:\n ") },
+
+ { oFrom, "from", 4, "|N|first record to export" },
+ { oTo, "to", 4, "|N|last record to export" },
+/* { oArmor, "armor", 0, N_("create ascii armored output")}, */
+/* { oArmor, "armour", 0, "@" }, */
+/* { oOutput, "output", 2, N_("use as output file")}, */
+ { oVerbose, "verbose", 0, N_("verbose") },
+ { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
+ { oDryRun, "dry-run", 0, N_("do not make any changes") },
+
+ { oDebug, "debug" ,4|16, N_("set debugging flags")},
+ { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
+
+ ARGPARSE_end () /* end of list */
+};
+
+
+void myexit (int rc);
+
+int keybox_errors_seen = 0;
+
+
+static const char *
+my_strusage( int level )
+{
+ const char *p;
+ switch( level ) {
+ case 11: p = "kbxutil (@GNUPG@)";
+ break;
+ case 13: p = VERSION; break;
+ case 17: p = PRINTABLE_OS_NAME; break;
+ case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
+
+ case 1:
+ case 40: p =
+ _("Usage: kbxutil [options] [files] (-h for help)");
+ break;
+ case 41: p =
+ _("Syntax: kbxutil [options] [files]\n"
+ "List, export, import Keybox data\n");
+ break;
+
+
+ default: p = NULL;
+ }
+ return p;
+}
+
+
+/* Used by gcry for logging */
+static void
+my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
+{
+ (void)dummy;
+
+ /* Map the log levels. */
+ switch (level)
+ {
+ case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
+ case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
+ case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
+ case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
+ case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
+ case GCRY_LOG_BUG: level = GPGRT_LOG_BUG; break;
+ case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
+ default: level = GPGRT_LOG_ERROR; break;
+ }
+ log_logv (level, fmt, arg_ptr);
+}
+
+
+
+/* static void */
+/* wrong_args( const char *text ) */
+/* { */
+/* log_error("usage: kbxutil %s\n", text); */
+/* myexit ( 1 ); */
+/* } */
+
+
+#if 0
+static int
+hextobyte( const byte *s )
+{
+ int c;
+
+ if( *s >= '0' && *s <= '9' )
+ c = 16 * (*s - '0');
+ else if( *s >= 'A' && *s <= 'F' )
+ c = 16 * (10 + *s - 'A');
+ else if( *s >= 'a' && *s <= 'f' )
+ c = 16 * (10 + *s - 'a');
+ else
+ return -1;
+ s++;
+ if( *s >= '0' && *s <= '9' )
+ c += *s - '0';
+ else if( *s >= 'A' && *s <= 'F' )
+ c += 10 + *s - 'A';
+ else if( *s >= 'a' && *s <= 'f' )
+ c += 10 + *s - 'a';
+ else
+ return -1;
+ return c;
+}
+#endif
+
+#if 0
+static char *
+format_fingerprint ( const char *s )
+{
+ int i, c;
+ byte fpr[20];
+
+ for (i=0; i < 20 && *s; ) {
+ if ( *s == ' ' || *s == '\t' ) {
+ s++;
+ continue;
+ }
+ c = hextobyte(s);
+ if (c == -1) {
+ return NULL;
+ }
+ fpr[i++] = c;
+ s += 2;
+ }
+ return gcry_xstrdup ( fpr );
+}
+#endif
+
+#if 0
+static int
+format_keyid ( const char *s, u32 *kid )
+{
+ char helpbuf[9];
+ switch ( strlen ( s ) ) {
+ case 8:
+ kid[0] = 0;
+ kid[1] = strtoul( s, NULL, 16 );
+ return 10;
+
+ case 16:
+ mem2str( helpbuf, s, 9 );
+ kid[0] = strtoul( helpbuf, NULL, 16 );
+ kid[1] = strtoul( s+8, NULL, 16 );
+ return 11;
+ }
+ return 0; /* error */
+}
+#endif
+
+static char *
+read_file (const char *fname, size_t *r_length)
+{
+ FILE *fp;
+ char *buf;
+ size_t buflen;
+
+ if (!strcmp (fname, "-"))
+ {
+ size_t nread, bufsize = 0;
+
+ fp = stdin;
+ buf = NULL;
+ buflen = 0;
+#define NCHUNK 8192
+ do
+ {
+ bufsize += NCHUNK;
+ if (!buf)
+ buf = xtrymalloc (bufsize);
+ else
+ buf = xtryrealloc (buf, bufsize);
+ if (!buf)
+ log_fatal ("can't allocate buffer: %s\n", strerror (errno));
+
+ nread = fread (buf+buflen, 1, NCHUNK, fp);
+ if (nread < NCHUNK && ferror (fp))
+ {
+ log_error ("error reading '[stdin]': %s\n", strerror (errno));
+ xfree (buf);
+ return NULL;
+ }
+ buflen += nread;
+ }
+ while (nread == NCHUNK);
+#undef NCHUNK
+
+ }
+ else
+ {
+ struct stat st;
+
+ fp = gnupg_fopen (fname, "rb");
+ if (!fp)
+ {
+ log_error ("can't open '%s': %s\n", fname, strerror (errno));
+ return NULL;
+ }
+
+ if (fstat (fileno(fp), &st))
+ {
+ log_error ("can't stat '%s': %s\n", fname, strerror (errno));
+ fclose (fp);
+ return NULL;
+ }
+
+ buflen = st.st_size;
+ buf = xtrymalloc (buflen+1);
+ if (!buf)
+ log_fatal ("can't allocate buffer: %s\n", strerror (errno));
+ if (fread (buf, buflen, 1, fp) != 1)
+ {
+ log_error ("error reading '%s': %s\n", fname, strerror (errno));
+ fclose (fp);
+ xfree (buf);
+ return NULL;
+ }
+ fclose (fp);
+ }
+
+ *r_length = buflen;
+ return buf;
+}
+
+
+static void
+dump_fpr (const unsigned char *buffer, size_t len)
+{
+ int i;
+
+ for (i=0; i < len; i++, buffer++)
+ {
+ if (len == 20)
+ {
+ if (i == 10)
+ putchar (' ');
+ printf (" %02X%02X", buffer[0], buffer[1]);
+ i++; buffer++;
+ }
+ else
+ {
+ if (i && !(i % 8))
+ putchar (' ');
+ printf (" %02X", buffer[0]);
+ }
+ }
+}
+
+
+static void
+dump_grip (const unsigned char *buffer, size_t len)
+{
+ int i;
+
+ for (i=0; i < len; i++, buffer++)
+ {
+ printf ("%02X", buffer[0]);
+ }
+}
+
+
+static void
+dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
+{
+ printf ("pub %2d %02X%02X%02X%02X",
+ info->primary.algo,
+ info->primary.keyid[4], info->primary.keyid[5],
+ info->primary.keyid[6], info->primary.keyid[7] );
+ dump_fpr (info->primary.fpr, info->primary.fprlen);
+ putchar ('\n');
+ fputs ("grp ", stdout);
+ dump_grip (info->primary.grip, 20);
+ putchar ('\n');
+ if (info->nsubkeys)
+ {
+ struct _keybox_openpgp_key_info *k;
+
+ k = &info->subkeys;
+ do
+ {
+ printf ("sub %2d %02X%02X%02X%02X",
+ k->algo,
+ k->keyid[4], k->keyid[5],
+ k->keyid[6], k->keyid[7] );
+ dump_fpr (k->fpr, k->fprlen);
+ putchar ('\n');
+ fputs ("grp ", stdout);
+ dump_grip (k->grip, 20);
+ putchar ('\n');
+ k = k->next;
+ }
+ while (k);
+ }
+ if (info->nuids)
+ {
+ struct _keybox_openpgp_uid_info *u;
+
+ u = &info->uids;
+ do
+ {
+ printf ("uid\t\t%.*s\n", (int)u->len, image + u->off);
+ u = u->next;
+ }
+ while (u);
+ }
+}
+
+
+static void
+import_openpgp (const char *filename, int dryrun)
+{
+ gpg_error_t err;
+ char *buffer;
+ size_t buflen, nparsed;
+ unsigned char *p;
+ struct _keybox_openpgp_info info;
+ KEYBOXBLOB blob;
+
+ buffer = read_file (filename, &buflen);
+ if (!buffer)
+ return;
+ p = (unsigned char *)buffer;
+ for (;;)
+ {
+ err = _keybox_parse_openpgp (p, buflen, &nparsed, &info);
+ assert (nparsed <= buflen);
+ if (err)
+ {
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ break;
+ if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
+ {
+ /* This is likely a v3 key packet with a non-RSA
+ algorithm. These are keys from very early versions
+ of GnuPG (pre-OpenPGP). */
+ }
+ else
+ {
+ es_fflush (es_stdout);
+ log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
+ filename, gpg_strerror (err));
+ }
+ }
+ else
+ {
+ if (dryrun)
+ dump_openpgp_key (&info, p);
+ else
+ {
+ err = _keybox_create_openpgp_blob (&blob, &info, p, nparsed, 0);
+ if (err)
+ {
+ es_fflush (es_stdout);
+ log_error ("%s: failed to create OpenPGP keyblock: %s\n",
+ filename, gpg_strerror (err));
+ }
+ else
+ {
+ err = _keybox_write_blob (blob, es_stdout, NULL);
+ _keybox_release_blob (blob);
+ if (err)
+ {
+ es_fflush (es_stdout);
+ log_error ("%s: failed to write OpenPGP keyblock: %s\n",
+ filename, gpg_strerror (err));
+ }
+ }
+ }
+
+ _keybox_destroy_openpgp_info (&info);
+ }
+ p += nparsed;
+ buflen -= nparsed;
+ }
+ xfree (buffer);
+}
+
+
+
+
+int
+main( int argc, char **argv )
+{
+ ARGPARSE_ARGS pargs;
+ enum cmd_and_opt_values cmd = 0;
+ unsigned long from = 0;
+ unsigned long to = ULONG_MAX;
+ int dry_run = 0;
+
+ early_system_init ();
+ set_strusage( my_strusage );
+ gcry_control (GCRYCTL_DISABLE_SECMEM);
+ log_set_prefix ("kbxutil", GPGRT_LOG_WITH_PREFIX);
+
+ /* Make sure that our subsystems are ready. */
+ i18n_init ();
+ init_common_subsystems (&argc, &argv);
+
+ gcry_set_log_handler (my_gcry_logger, NULL);
+
+ /*create_dotlock(NULL); register locking cleanup */
+
+ /* We need to use the gcry malloc function because jnlib uses them. */
+ ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
+
+
+ pargs.argc = &argc;
+ pargs.argv = &argv;
+ pargs.flags= ARGPARSE_FLAG_KEEP;
+ while (gnupg_argparse (NULL, &pargs, opts))
+ {
+ switch (pargs.r_opt)
+ {
+ case oVerbose:
+ /*opt.verbose++;*/
+ /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
+ break;
+ case oDebug:
+ /*opt.debug |= pargs.r.ret_ulong; */
+ break;
+ case oDebugAll:
+ /*opt.debug = ~0;*/
+ break;
+
+ case aFindByFpr:
+ case aFindByKid:
+ case aFindByUid:
+ case aStats:
+ case aImportOpenPGP:
+ case aFindDups:
+ case aCut:
+ cmd = pargs.r_opt;
+ break;
+
+ case oFrom: from = pargs.r.ret_ulong; break;
+ case oTo: to = pargs.r.ret_ulong; break;
+
+ case oDryRun: dry_run = 1; break;
+
+ default:
+ pargs.err = 2;
+ break;
+ }
+ }
+
+ gnupg_argparse (NULL, &pargs, NULL);
+
+ if (to < from)
+ log_error ("record number of \"--to\" is lower than \"--from\" one\n");
+
+
+ if (log_get_errorcount(0) )
+ myexit(2);
+
+ if (!cmd)
+ { /* Default is to list a KBX file */
+ if (!argc)
+ _keybox_dump_file (NULL, 0, stdout);
+ else
+ {
+ for (; argc; argc--, argv++)
+ _keybox_dump_file (*argv, 0, stdout);
+ }
+ }
+ else if (cmd == aStats )
+ {
+ if (!argc)
+ _keybox_dump_file (NULL, 1, stdout);
+ else
+ {
+ for (; argc; argc--, argv++)
+ _keybox_dump_file (*argv, 1, stdout);
+ }
+ }
+ else if (cmd == aFindDups )
+ {
+ if (!argc)
+ _keybox_dump_find_dups (NULL, 0, stdout);
+ else
+ {
+ for (; argc; argc--, argv++)
+ _keybox_dump_find_dups (*argv, 0, stdout);
+ }
+ }
+ else if (cmd == aCut )
+ {
+ if (!argc)
+ _keybox_dump_cut_records (NULL, from, to, stdout);
+ else
+ {
+ for (; argc; argc--, argv++)
+ _keybox_dump_cut_records (*argv, from, to, stdout);
+ }
+ }
+ else if (cmd == aImportOpenPGP)
+ {
+ if (!argc)
+ import_openpgp ("-", dry_run);
+ else
+ {
+ for (; argc; argc--, argv++)
+ import_openpgp (*argv, dry_run);
+ }
+ }
+#if 0
+ else if ( cmd == aFindByFpr )
+ {
+ char *fpr;
+ if ( argc != 2 )
+ wrong_args ("kbxfile foingerprint");
+ fpr = format_fingerprint ( argv[1] );
+ if ( !fpr )
+ log_error ("invalid formatted fingerprint\n");
+ else
+ {
+ kbxfile_search_by_fpr ( argv[0], fpr );
+ gcry_free ( fpr );
+ }
+ }
+ else if ( cmd == aFindByKid )
+ {
+ u32 kid[2];
+ int mode;
+
+ if ( argc != 2 )
+ wrong_args ("kbxfile short-or-long-keyid");
+ mode = format_keyid ( argv[1], kid );
+ if ( !mode )
+ log_error ("invalid formatted keyID\n");
+ else
+ {
+ kbxfile_search_by_kid ( argv[0], kid, mode );
+ }
+ }
+ else if ( cmd == aFindByUid )
+ {
+ if ( argc != 2 )
+ wrong_args ("kbxfile userID");
+ kbxfile_search_by_uid ( argv[0], argv[1] );
+ }
+#endif
+ else
+ log_error ("unsupported action\n");
+
+ myexit(0);
+ return 8; /*NEVER REACHED*/
+}
+
+
+void
+myexit( int rc )
+{
+ /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/
+/* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */
+/* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */
+ /* }*/
+/* if( opt.debug ) */
+/* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */
+ rc = rc? rc : log_get_errorcount(0)? 2 :
+ keybox_errors_seen? 1 : 0;
+ exit(rc );
+}
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
new file mode 100644
index 0000000..ac259ea
--- /dev/null
+++ b/kbx/keybox-blob.c
@@ -0,0 +1,1057 @@
+/* keybox-blob.c - KBX Blob handling
+ * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+* The keybox data format
+
+ The KeyBox uses an augmented OpenPGP/X.509 key format. This makes
+ random access to a keyblock/certificate easier and also gives the
+ opportunity to store additional information (e.g. the fingerprint)
+ along with the key. All integers are stored in network byte order,
+ offsets are counted from the beginning of the Blob.
+
+** Overview of blob types
+
+ | Byte 4 | Blob type |
+ |--------+--------------|
+ | 0 | Empty blob |
+ | 1 | First blob |
+ | 2 | OpenPGP blob |
+ | 3 | X.509 blob |
+
+** The First blob
+
+ The first blob of a plain KBX file has a special format:
+
+ - u32 Length of this blob
+ - byte Blob type (1)
+ - byte Version number (1)
+ - u16 Header flags
+ bit 0 - RFU
+ bit 1 - Is being or has been used for OpenPGP blobs
+ - b4 Magic 'KBXf'
+ - u32 RFU
+ - u32 file_created_at
+ - u32 last_maintenance_run
+ - u32 RFU
+ - u32 RFU
+
+** The OpenPGP and X.509 blobs
+
+ The OpenPGP and X.509 blobs are very similar, things which are
+ X.509 specific are noted like [X.509: xxx]
+
+ - u32 Length of this blob (including these 4 bytes)
+ - byte Blob type
+ 2 = OpenPGP
+ 3 = X509
+ - byte Version number of this blob type
+ 1 = The only defined value
+ - u16 Blob flags
+ bit 0 = contains secret key material (not used)
+ bit 1 = ephemeral blob (e.g. used while querying external resources)
+ - u32 Offset to the OpenPGP keyblock or the X.509 DER encoded
+ certificate
+ - u32 The length of the keyblock or certificate
+ - u16 [NKEYS] Number of keys (at least 1!) [X509: always 1]
+ - u16 Size of the key information structure (at least 28).
+ - NKEYS times:
+ - b20 The fingerprint of the key.
+ Fingerprints are always 20 bytes, MD5 left padded with zeroes.
+ - u32 Offset to the n-th key's keyID (a keyID is always 8 byte)
+ or 0 if not known which is the case only for X.509.
+ - u16 Key flags
+ bit 0 = qualified signature (not yet implemented}
+ - u16 RFU
+ - bN Optional filler up to the specified length of this
+ structure.
+ - u16 Size of the serial number (may be zero)
+ - bN The serial number. N as giiven above.
+ - u16 Number of user IDs
+ - u16 [NUIDS] Size of user ID information structure
+ - NUIDS times:
+
+ For X509, the first user ID is the Issuer, the second the
+ Subject and the others are subjectAltNames. For OpenPGP we only
+ store the information from UserID packets here.
+
+ - u32 Blob offset to the n-th user ID
+ - u32 Length of this user ID.
+ - u16 User ID flags.
+ (not yet used)
+ - byte Validity
+ - byte RFU
+
+ - u16 [NSIGS] Number of signatures
+ - u16 Size of signature information (4)
+ - NSIGS times:
+ - u32 Expiration time of signature with some special values.
+ Since version 2.1.20 these special valuesare not anymore
+ used for OpenPGP:
+ - 0x00000000 = not checked
+ - 0x00000001 = missing key
+ - 0x00000002 = bad signature
+ - 0x10000000 = valid and expires at some date in 1978.
+ - 0xffffffff = valid and does not expire
+ - u8 Assigned ownertrust [X509: not used]
+ - u8 All_Validity
+ OpenPGP: See ../g10/trustdb/TRUST_* [not yet used]
+ X509: Bit 4 set := key has been revoked.
+ Note that this value matches TRUST_FLAG_REVOKED
+ - u16 RFU
+ - u32 Recheck_after
+ - u32 Latest timestamp in the keyblock (useful for KS synchronization?)
+ - u32 Blob created at
+ - u32 [NRES] Size of reserved space (not including this field)
+ - bN Reserved space of size NRES for future use.
+ - bN Arbitrary space for example used to store data which is not
+ part of the keyblock or certificate. For example the v3 key
+ IDs go here.
+ - bN Space for the keyblock or certificate.
+ - bN RFU. This is the remaining space after keyblock and before
+ the checksum. It is not covered by the checksum.
+ - b20 SHA-1 checksum (useful for KS synchronization?)
+ Note, that KBX versions before GnuPG 2.1 used an MD5
+ checksum. However it was only created but never checked.
+ Thus we do not expect problems if we switch to SHA-1. If
+ the checksum fails and the first 4 bytes are zero, we can
+ try again with MD5. SHA-1 has the advantage that it is
+ faster on CPUs with dedicated SHA-1 support.
+
+
+*/
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <time.h>
+
+#include "keybox-defs.h"
+#include <gcrypt.h>
+
+#ifdef KEYBOX_WITH_X509
+#include <ksba.h>
+#endif
+
+
+#include "../common/gettime.h"
+
+
+/* special values of the signature status */
+#define SF_NONE(a) ( !(a) )
+#define SF_NOKEY(a) ((a) & (1<<0))
+#define SF_BAD(a) ((a) & (1<<1))
+#define SF_VALID(a) ((a) & (1<<29))
+
+
+struct membuf {
+ size_t len;
+ size_t size;
+ char *buf;
+ int out_of_core;
+};
+
+
+/* #if MAX_FINGERPRINT_LEN < 20 */
+/* #error fingerprints are 20 bytes */
+/* #endif */
+
+struct keyboxblob_key {
+ char fpr[20];
+ u32 off_kid;
+ ulong off_kid_addr;
+ u16 flags;
+};
+struct keyboxblob_uid {
+ u32 off;
+ ulong off_addr;
+ char *name; /* used only with x509 */
+ u32 len;
+ u16 flags;
+ byte validity;
+};
+
+struct keyid_list {
+ struct keyid_list *next;
+ int seqno;
+ byte kid[8];
+};
+
+struct fixup_list {
+ struct fixup_list *next;
+ u32 off;
+ u32 val;
+};
+
+
+struct keyboxblob {
+ byte *blob;
+ size_t bloblen;
+ off_t fileoffset;
+
+ /* stuff used only by keybox_create_blob */
+ unsigned char *serialbuf;
+ const unsigned char *serial;
+ size_t seriallen;
+ int nkeys;
+ struct keyboxblob_key *keys;
+ int nuids;
+ struct keyboxblob_uid *uids;
+ int nsigs;
+ u32 *sigs;
+ struct fixup_list *fixups;
+ int fixup_out_of_core;
+
+ struct keyid_list *temp_kids;
+ struct membuf bufbuf; /* temporary store for the blob */
+ struct membuf *buf;
+};
+
+
+
+/* A simple implementation of a dynamic buffer. Use init_membuf() to
+ create a buffer, put_membuf to append bytes and get_membuf to
+ release and return the buffer. Allocation errors are detected but
+ only returned at the final get_membuf(), this helps not to clutter
+ the code with out of core checks. */
+
+static void
+init_membuf (struct membuf *mb, int initiallen)
+{
+ mb->len = 0;
+ mb->size = initiallen;
+ mb->out_of_core = 0;
+ mb->buf = xtrymalloc (initiallen);
+ if (!mb->buf)
+ mb->out_of_core = 1;
+}
+
+static void
+put_membuf (struct membuf *mb, const void *buf, size_t len)
+{
+ if (mb->out_of_core)
+ return;
+
+ if (mb->len + len >= mb->size)
+ {
+ char *p;
+
+ mb->size += len + 1024;
+ p = xtryrealloc (mb->buf, mb->size);
+ if (!p)
+ {
+ mb->out_of_core = 1;
+ return;
+ }
+ mb->buf = p;
+ }
+ if (buf)
+ memcpy (mb->buf + mb->len, buf, len);
+ else
+ memset (mb->buf + mb->len, 0, len);
+ mb->len += len;
+}
+
+static void *
+get_membuf (struct membuf *mb, size_t *len)
+{
+ char *p;
+
+ if (mb->out_of_core)
+ {
+ xfree (mb->buf);
+ mb->buf = NULL;
+ return NULL;
+ }
+
+ p = mb->buf;
+ *len = mb->len;
+ mb->buf = NULL;
+ mb->out_of_core = 1; /* don't allow a reuse */
+ return p;
+}
+
+
+static void
+put8 (struct membuf *mb, byte a )
+{
+ put_membuf (mb, &a, 1);
+}
+
+static void
+put16 (struct membuf *mb, u16 a )
+{
+ unsigned char tmp[2];
+ tmp[0] = a>>8;
+ tmp[1] = a;
+ put_membuf (mb, tmp, 2);
+}
+
+static void
+put32 (struct membuf *mb, u32 a )
+{
+ unsigned char tmp[4];
+ tmp[0] = a>>24;
+ tmp[1] = a>>16;
+ tmp[2] = a>>8;
+ tmp[3] = a;
+ put_membuf (mb, tmp, 4);
+}
+
+
+
+/* Store a value in the fixup list */
+static void
+add_fixup (KEYBOXBLOB blob, u32 off, u32 val)
+{
+ struct fixup_list *fl;
+
+ if (blob->fixup_out_of_core)
+ return;
+
+ fl = xtrycalloc(1, sizeof *fl);
+ if (!fl)
+ blob->fixup_out_of_core = 1;
+ else
+ {
+ fl->off = off;
+ fl->val = val;
+ fl->next = blob->fixups;
+ blob->fixups = fl;
+ }
+}
+
+
+
+/*
+ OpenPGP specific stuff
+*/
+
+
+/* We must store the keyid at some place because we can't calculate
+ the offset yet. This is only used for v3 keyIDs. Function returns
+ an index value for later fixup or -1 for out of core. The value
+ must be a non-zero value. */
+static int
+pgp_temp_store_kid (KEYBOXBLOB blob, struct _keybox_openpgp_key_info *kinfo)
+{
+ struct keyid_list *k, *r;
+
+ k = xtrymalloc (sizeof *k);
+ if (!k)
+ return -1;
+ memcpy (k->kid, kinfo->keyid, 8);
+ k->seqno = 0;
+ k->next = blob->temp_kids;
+ blob->temp_kids = k;
+ for (r=k; r; r = r->next)
+ k->seqno++;
+
+ return k->seqno;
+}
+
+
+/* Helper for pgp_create_key_part. */
+static gpg_error_t
+pgp_create_key_part_single (KEYBOXBLOB blob, int n,
+ struct _keybox_openpgp_key_info *kinfo)
+{
+ size_t fprlen;
+ int off;
+
+ fprlen = kinfo->fprlen;
+ if (fprlen > 20)
+ fprlen = 20;
+ memcpy (blob->keys[n].fpr, kinfo->fpr, fprlen);
+ if (fprlen != 20) /* v3 fpr - shift right and fill with zeroes. */
+ {
+ memmove (blob->keys[n].fpr + 20 - fprlen, blob->keys[n].fpr, fprlen);
+ memset (blob->keys[n].fpr, 0, 20 - fprlen);
+ off = pgp_temp_store_kid (blob, kinfo);
+ if (off == -1)
+ return gpg_error_from_syserror ();
+ blob->keys[n].off_kid = off;
+ }
+ else
+ blob->keys[n].off_kid = 0; /* Will be fixed up later */
+ blob->keys[n].flags = 0;
+ return 0;
+}
+
+
+static gpg_error_t
+pgp_create_key_part (KEYBOXBLOB blob, keybox_openpgp_info_t info)
+{
+ gpg_error_t err;
+ int n = 0;
+ struct _keybox_openpgp_key_info *kinfo;
+
+ err = pgp_create_key_part_single (blob, n++, &info->primary);
+ if (err)
+ return err;
+ if (info->nsubkeys)
+ for (kinfo = &info->subkeys; kinfo; kinfo = kinfo->next)
+ if ((err=pgp_create_key_part_single (blob, n++, kinfo)))
+ return err;
+
+ assert (n == blob->nkeys);
+ return 0;
+}
+
+
+static void
+pgp_create_uid_part (KEYBOXBLOB blob, keybox_openpgp_info_t info)
+{
+ int n = 0;
+ struct _keybox_openpgp_uid_info *u;
+
+ if (info->nuids)
+ {
+ for (u = &info->uids; u; u = u->next)
+ {
+ blob->uids[n].off = u->off;
+ blob->uids[n].len = u->len;
+ blob->uids[n].flags = 0;
+ blob->uids[n].validity = 0;
+ n++;
+ }
+ }
+
+ assert (n == blob->nuids);
+}
+
+
+static void
+pgp_create_sig_part (KEYBOXBLOB blob, u32 *sigstatus)
+{
+ int n;
+
+ for (n=0; n < blob->nsigs; n++)
+ {
+ blob->sigs[n] = sigstatus? sigstatus[n+1] : 0;
+ }
+}
+
+
+static int
+pgp_create_blob_keyblock (KEYBOXBLOB blob,
+ const unsigned char *image, size_t imagelen)
+{
+ struct membuf *a = blob->buf;
+ int n;
+ u32 kbstart = a->len;
+
+ add_fixup (blob, 8, kbstart);
+
+ for (n = 0; n < blob->nuids; n++)
+ add_fixup (blob, blob->uids[n].off_addr, kbstart + blob->uids[n].off);
+
+ put_membuf (a, image, imagelen);
+
+ add_fixup (blob, 12, a->len - kbstart);
+ return 0;
+}
+
+
+
+#ifdef KEYBOX_WITH_X509
+/*
+ X.509 specific stuff
+ */
+
+/* Write the raw certificate out */
+static int
+x509_create_blob_cert (KEYBOXBLOB blob, ksba_cert_t cert)
+{
+ struct membuf *a = blob->buf;
+ const unsigned char *image;
+ size_t length;
+ u32 kbstart = a->len;
+
+ /* Store our offset for later fixup */
+ add_fixup (blob, 8, kbstart);
+
+ image = ksba_cert_get_image (cert, &length);
+ if (!image)
+ return gpg_error (GPG_ERR_GENERAL);
+ put_membuf (a, image, length);
+
+ add_fixup (blob, 12, a->len - kbstart);
+ return 0;
+}
+
+#endif /*KEYBOX_WITH_X509*/
+
+/* Write a stored keyID out to the buffer */
+static void
+write_stored_kid (KEYBOXBLOB blob, int seqno)
+{
+ struct keyid_list *r;
+
+ for ( r = blob->temp_kids; r; r = r->next )
+ {
+ if (r->seqno == seqno )
+ {
+ put_membuf (blob->buf, r->kid, 8);
+ return;
+ }
+ }
+ never_reached ();
+}
+
+/* Release a list of key IDs */
+static void
+release_kid_list (struct keyid_list *kl)
+{
+ struct keyid_list *r, *r2;
+
+ for ( r = kl; r; r = r2 )
+ {
+ r2 = r->next;
+ xfree (r);
+ }
+}
+
+
+
+static int
+create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
+{
+ struct membuf *a = blob->buf;
+ int i;
+
+ put32 ( a, 0 ); /* blob length, needs fixup */
+ put8 ( a, blobtype);
+ put8 ( a, 1 ); /* blob type version */
+ put16 ( a, as_ephemeral? 2:0 ); /* blob flags */
+
+ put32 ( a, 0 ); /* offset to the raw data, needs fixup */
+ put32 ( a, 0 ); /* length of the raw data, needs fixup */
+
+ put16 ( a, blob->nkeys );
+ put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
+ for ( i=0; i < blob->nkeys; i++ )
+ {
+ put_membuf (a, blob->keys[i].fpr, 20);
+ blob->keys[i].off_kid_addr = a->len;
+ put32 ( a, 0 ); /* offset to keyid, fixed up later */
+ put16 ( a, blob->keys[i].flags );
+ put16 ( a, 0 ); /* reserved */
+ }
+
+ put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/
+ if (blob->serial)
+ put_membuf (a, blob->serial, blob->seriallen);
+
+ put16 ( a, blob->nuids );
+ put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
+ for (i=0; i < blob->nuids; i++)
+ {
+ blob->uids[i].off_addr = a->len;
+ put32 ( a, 0 ); /* offset to userid, fixed up later */
+ put32 ( a, blob->uids[i].len );
+ put16 ( a, blob->uids[i].flags );
+ put8 ( a, 0 ); /* validity */
+ put8 ( a, 0 ); /* reserved */
+ }
+
+ put16 ( a, blob->nsigs );
+ put16 ( a, 4 ); /* size of sig info */
+ for (i=0; i < blob->nsigs; i++)
+ {
+ put32 ( a, blob->sigs[i]);
+ }
+
+ put8 ( a, 0 ); /* assigned ownertrust */
+ put8 ( a, 0 ); /* validity of all user IDs */
+ put16 ( a, 0 ); /* reserved */
+ put32 ( a, 0 ); /* time of next recheck */
+ put32 ( a, 0 ); /* newest timestamp (none) */
+ put32 ( a, make_timestamp() ); /* creation time */
+ put32 ( a, 0 ); /* size of reserved space */
+ /* reserved space (which is currently of size 0) */
+
+ /* space where we write keyIDs and other stuff so that the
+ pointers can actually point to somewhere */
+ if (blobtype == KEYBOX_BLOBTYPE_PGP)
+ {
+ /* We need to store the keyids for all pgp v3 keys because those key
+ IDs are not part of the fingerprint. While we are doing that, we
+ fixup all the keyID offsets */
+ for (i=0; i < blob->nkeys; i++ )
+ {
+ if (blob->keys[i].off_kid)
+ { /* this is a v3 one */
+ add_fixup (blob, blob->keys[i].off_kid_addr, a->len);
+ write_stored_kid (blob, blob->keys[i].off_kid);
+ }
+ else
+ { /* the better v4 key IDs - just store an offset 8 bytes back */
+ add_fixup (blob, blob->keys[i].off_kid_addr,
+ blob->keys[i].off_kid_addr - 8);
+ }
+ }
+ }
+
+ if (blobtype == KEYBOX_BLOBTYPE_X509)
+ {
+ /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
+ the utf-8 string represenation of them */
+ for (i=0; i < blob->nuids; i++ )
+ {
+ if (blob->uids[i].name)
+ { /* this is a v3 one */
+ add_fixup (blob, blob->uids[i].off_addr, a->len);
+ put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+static int
+create_blob_trailer (KEYBOXBLOB blob)
+{
+ (void)blob;
+ return 0;
+}
+
+
+static int
+create_blob_finish (KEYBOXBLOB blob)
+{
+ struct membuf *a = blob->buf;
+ unsigned char *p;
+ unsigned char *pp;
+ size_t n;
+
+ /* Write a placeholder for the checksum */
+ put_membuf (a, NULL, 20);
+
+ /* get the memory area */
+ n = 0; /* (Just to avoid compiler warning.) */
+ p = get_membuf (a, &n);
+ if (!p)
+ return gpg_error (GPG_ERR_ENOMEM);
+ assert (n >= 20);
+
+ /* fixup the length */
+ add_fixup (blob, 0, n);
+
+ /* do the fixups */
+ if (blob->fixup_out_of_core)
+ {
+ xfree (p);
+ return gpg_error (GPG_ERR_ENOMEM);
+ }
+
+ {
+ struct fixup_list *fl, *next;
+ for (fl = blob->fixups; fl; fl = next)
+ {
+ assert (fl->off+4 <= n);
+ p[fl->off+0] = fl->val >> 24;
+ p[fl->off+1] = fl->val >> 16;
+ p[fl->off+2] = fl->val >> 8;
+ p[fl->off+3] = fl->val;
+ next = fl->next;
+ xfree (fl);
+ }
+ blob->fixups = NULL;
+ }
+
+ /* Compute and store the SHA-1 checksum. */
+ gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 20, p, n - 20);
+
+ pp = xtrymalloc (n);
+ if ( !pp )
+ {
+ xfree (p);
+ return gpg_error_from_syserror ();
+ }
+ memcpy (pp , p, n);
+ xfree (p);
+ blob->blob = pp;
+ blob->bloblen = n;
+
+ return 0;
+}
+
+
+
+gpg_error_t
+_keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
+ keybox_openpgp_info_t info,
+ const unsigned char *image,
+ size_t imagelen,
+ int as_ephemeral)
+{
+ gpg_error_t err;
+ KEYBOXBLOB blob;
+
+ *r_blob = NULL;
+
+ blob = xtrycalloc (1, sizeof *blob);
+ if (!blob)
+ return gpg_error_from_syserror ();
+
+ blob->nkeys = 1 + info->nsubkeys;
+ blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
+ if (!blob->keys)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ blob->nuids = info->nuids;
+ if (blob->nuids)
+ {
+ blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
+ if (!blob->uids)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+
+ blob->nsigs = info->nsigs;
+ if (blob->nsigs)
+ {
+ blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
+ if (!blob->sigs)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+
+ err = pgp_create_key_part (blob, info);
+ if (err)
+ goto leave;
+ pgp_create_uid_part (blob, info);
+ pgp_create_sig_part (blob, NULL);
+
+ init_membuf (&blob->bufbuf, 1024);
+ blob->buf = &blob->bufbuf;
+ err = create_blob_header (blob, KEYBOX_BLOBTYPE_PGP, as_ephemeral);
+ if (err)
+ goto leave;
+ err = pgp_create_blob_keyblock (blob, image, imagelen);
+ if (err)
+ goto leave;
+ err = create_blob_trailer (blob);
+ if (err)
+ goto leave;
+ err = create_blob_finish (blob);
+ if (err)
+ goto leave;
+
+ leave:
+ release_kid_list (blob->temp_kids);
+ blob->temp_kids = NULL;
+ if (err)
+ _keybox_release_blob (blob);
+ else
+ *r_blob = blob;
+ return err;
+}
+
+
+#ifdef KEYBOX_WITH_X509
+
+/* Return an allocated string with the email address extracted from a
+ DN. Note hat we use this code also in ../sm/keylist.c. */
+static char *
+x509_email_kludge (const char *name)
+{
+ const char *p, *string;
+ unsigned char *buf;
+ int n;
+
+ string = name;
+ for (;;)
+ {
+ p = strstr (string, "1.2.840.113549.1.9.1=#");
+ if (!p)
+ return NULL;
+ if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
+ {
+ name = p + 22;
+ break;
+ }
+ string = p + 22;
+ }
+
+
+ /* This looks pretty much like an email address in the subject's DN
+ we use this to add an additional user ID entry. This way,
+ OpenSSL generated keys get a nicer and usable listing. */
+ for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
+ ;
+ if (!n)
+ return NULL;
+ buf = xtrymalloc (n+3);
+ if (!buf)
+ return NULL; /* oops, out of core */
+ *buf = '<';
+ for (n=1, p=name; hexdigitp (p); p +=2, n++)
+ buf[n] = xtoi_2 (p);
+ buf[n++] = '>';
+ buf[n] = 0;
+ return (char*)buf;
+}
+
+
+
+/* Note: We should move calculation of the digest into libksba and
+ remove that parameter */
+int
+_keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
+ unsigned char *sha1_digest, int as_ephemeral)
+{
+ int i, rc = 0;
+ KEYBOXBLOB blob;
+ unsigned char *sn;
+ char *p;
+ char **names = NULL;
+ size_t max_names;
+
+ *r_blob = NULL;
+ blob = xtrycalloc (1, sizeof *blob);
+ if( !blob )
+ return gpg_error_from_syserror ();
+
+ sn = ksba_cert_get_serial (cert);
+ if (sn)
+ {
+ size_t n, len;
+ n = gcry_sexp_canon_len (sn, 0, NULL, NULL);
+ if (n < 2)
+ {
+ xfree (sn);
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ blob->serialbuf = sn;
+ sn++; n--; /* skip '(' */
+ for (len=0; n && *sn && *sn != ':' && digitp (sn); n--, sn++)
+ len = len*10 + atoi_1 (sn);
+ if (*sn != ':')
+ {
+ xfree (blob->serialbuf);
+ blob->serialbuf = NULL;
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ sn++;
+ blob->serial = sn;
+ blob->seriallen = len;
+ }
+
+ blob->nkeys = 1;
+
+ /* create list of names */
+ blob->nuids = 0;
+ max_names = 100;
+ names = xtrymalloc (max_names * sizeof *names);
+ if (!names)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ p = ksba_cert_get_issuer (cert, 0);
+ if (!p)
+ {
+ rc = gpg_error (GPG_ERR_MISSING_VALUE);
+ goto leave;
+ }
+ names[blob->nuids++] = p;
+ for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
+ {
+ if (blob->nuids >= max_names)
+ {
+ char **tmp;
+
+ max_names += 100;
+ tmp = xtryrealloc (names, max_names * sizeof *names);
+ if (!tmp)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ names = tmp;
+ }
+ names[blob->nuids++] = p;
+ if (!i && (p=x509_email_kludge (p)))
+ names[blob->nuids++] = p; /* due to !i we don't need to check bounds*/
+ }
+
+ /* space for signature information */
+ blob->nsigs = 1;
+
+ blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
+ blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
+ blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
+ if (!blob->keys || !blob->uids || !blob->sigs)
+ {
+ rc = gpg_error (GPG_ERR_ENOMEM);
+ goto leave;
+ }
+
+ memcpy (blob->keys[0].fpr, sha1_digest, 20);
+ blob->keys[0].off_kid = 0; /* We don't have keyids */
+ blob->keys[0].flags = 0;
+
+ /* issuer and subject names */
+ for (i=0; i < blob->nuids; i++)
+ {
+ blob->uids[i].name = names[i];
+ blob->uids[i].len = strlen(names[i]);
+ names[i] = NULL;
+ blob->uids[i].flags = 0;
+ blob->uids[i].validity = 0;
+ }
+ xfree (names);
+ names = NULL;
+
+ /* signatures */
+ blob->sigs[0] = 0; /* not yet checked */
+
+ /* Create a temporary buffer for further processing */
+ init_membuf (&blob->bufbuf, 1024);
+ blob->buf = &blob->bufbuf;
+ /* write out what we already have */
+ rc = create_blob_header (blob, KEYBOX_BLOBTYPE_X509, as_ephemeral);
+ if (rc)
+ goto leave;
+ rc = x509_create_blob_cert (blob, cert);
+ if (rc)
+ goto leave;
+ rc = create_blob_trailer (blob);
+ if (rc)
+ goto leave;
+ rc = create_blob_finish ( blob );
+ if (rc)
+ goto leave;
+
+
+ leave:
+ release_kid_list (blob->temp_kids);
+ blob->temp_kids = NULL;
+ if (names)
+ {
+ for (i=0; i < blob->nuids; i++)
+ xfree (names[i]);
+ xfree (names);
+ }
+ if (rc)
+ {
+ _keybox_release_blob (blob);
+ *r_blob = NULL;
+ }
+ else
+ {
+ *r_blob = blob;
+ }
+ return rc;
+}
+#endif /*KEYBOX_WITH_X509*/
+
+
+
+int
+_keybox_new_blob (KEYBOXBLOB *r_blob,
+ unsigned char *image, size_t imagelen, off_t off)
+{
+ KEYBOXBLOB blob;
+
+ *r_blob = NULL;
+ blob = xtrycalloc (1, sizeof *blob);
+ if (!blob)
+ return gpg_error_from_syserror ();
+
+ blob->blob = image;
+ blob->bloblen = imagelen;
+ blob->fileoffset = off;
+ *r_blob = blob;
+ return 0;
+}
+
+
+void
+_keybox_release_blob (KEYBOXBLOB blob)
+{
+ int i;
+ if (!blob)
+ return;
+ if (blob->buf)
+ {
+ size_t len;
+ xfree (get_membuf (blob->buf, &len));
+ }
+ xfree (blob->keys );
+ xfree (blob->serialbuf);
+ for (i=0; i < blob->nuids; i++)
+ xfree (blob->uids[i].name);
+ xfree (blob->uids );
+ xfree (blob->sigs );
+ xfree (blob->blob );
+ xfree (blob );
+}
+
+
+
+const unsigned char *
+_keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
+{
+ *n = blob->bloblen;
+ return blob->blob;
+}
+
+off_t
+_keybox_get_blob_fileoffset (KEYBOXBLOB blob)
+{
+ return blob->fileoffset;
+}
+
+
+
+void
+_keybox_update_header_blob (KEYBOXBLOB blob, int for_openpgp)
+{
+ if (blob->bloblen >= 32 && blob->blob[4] == KEYBOX_BLOBTYPE_HEADER)
+ {
+ u32 val = make_timestamp ();
+
+ /* Update the last maintenance run times tamp. */
+ blob->blob[20] = (val >> 24);
+ blob->blob[20+1] = (val >> 16);
+ blob->blob[20+2] = (val >> 8);
+ blob->blob[20+3] = (val );
+
+ if (for_openpgp)
+ blob->blob[7] |= 0x02; /* OpenPGP data may be available. */
+ }
+}
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
new file mode 100644
index 0000000..2751b4b
--- /dev/null
+++ b/kbx/keybox-defs.h
@@ -0,0 +1,210 @@
+/* keybox-defs.h - internal Keybox definitions
+ * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEYBOX_DEFS_H
+#define KEYBOX_DEFS_H 1
+
+#ifdef GPG_ERR_SOURCE_DEFAULT
+# if GPG_ERR_SOURCE_DEFAULT != GPG_ERR_SOURCE_KEYBOX
+# error GPG_ERR_SOURCE_DEFAULT already defined
+# endif
+#else
+# define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_KEYBOX
+#endif
+#include <gpg-error.h>
+#define map_assuan_err(a) \
+ map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a))
+
+#include <sys/types.h> /* off_t */
+
+#include "../common/util.h"
+#include "keybox.h"
+
+
+typedef struct keyboxblob *KEYBOXBLOB;
+
+
+typedef struct keybox_name *KB_NAME;
+struct keybox_name
+{
+ /* Link to the next resources, so that we can walk all
+ resources. */
+ KB_NAME next;
+
+ /* True if this is a keybox with secret keys. */
+ int secret;
+
+ /* A table with all the handles accessing this resources.
+ HANDLE_TABLE_SIZE gives the allocated length of this table unused
+ entrues are set to NULL. HANDLE_TABLE may be NULL. */
+ KEYBOX_HANDLE *handle_table;
+ size_t handle_table_size;
+
+ /* The lock handle or NULL it not yet initialized. */
+ dotlock_t lockhd;
+
+ /* Not yet used. */
+ int is_locked;
+
+ /* Not yet used. */
+ int did_full_scan;
+
+ /* The name of the resource file. */
+ char fname[1];
+};
+
+
+struct keybox_found_s
+{
+ KEYBOXBLOB blob;
+ size_t pk_no;
+ size_t uid_no;
+};
+
+struct keybox_handle {
+ KB_NAME kb;
+ int secret; /* this is for a secret keybox */
+ estream_t fp;
+ int eof;
+ int error;
+ int ephemeral;
+ int for_openpgp; /* Used by gpg. */
+ struct keybox_found_s found;
+ struct keybox_found_s saved_found;
+ struct {
+ char *name;
+ char *pattern;
+ } word_match;
+};
+
+
+/* OpenPGP helper structures. */
+struct _keybox_openpgp_key_info
+{
+ struct _keybox_openpgp_key_info *next;
+ int algo;
+ unsigned char grip[20];
+ unsigned char keyid[8];
+ int fprlen; /* Either 16 or 20 */
+ unsigned char fpr[20];
+};
+
+struct _keybox_openpgp_uid_info
+{
+ struct _keybox_openpgp_uid_info *next;
+ size_t off;
+ size_t len;
+};
+
+struct _keybox_openpgp_info
+{
+ int is_secret; /* True if this is a secret key. */
+ unsigned int nsubkeys;/* Total number of subkeys. */
+ unsigned int nuids; /* Total number of user IDs in the keyblock. */
+ unsigned int nsigs; /* Total number of signatures in the keyblock. */
+
+ /* Note, we use 2 structs here to better cope with the most common
+ use of having one primary and one subkey - this allows us to
+ statically allocate this structure and only malloc stuff for more
+ than one subkey. */
+ struct _keybox_openpgp_key_info primary;
+ struct _keybox_openpgp_key_info subkeys;
+ struct _keybox_openpgp_uid_info uids;
+};
+typedef struct _keybox_openpgp_info *keybox_openpgp_info_t;
+
+
+/* Don't know whether this is needed: */
+/* static struct { */
+/* int dry_run; */
+/* int quiet; */
+/* int verbose; */
+/* int preserve_permissions; */
+/* } keybox_opt; */
+
+/*-- keybox-init.c --*/
+void _keybox_close_file (KEYBOX_HANDLE hd);
+
+
+/*-- keybox-blob.c --*/
+gpg_error_t _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
+ keybox_openpgp_info_t info,
+ const unsigned char *image,
+ size_t imagelen,
+ int as_ephemeral);
+#ifdef KEYBOX_WITH_X509
+int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
+ unsigned char *sha1_digest, int as_ephemeral);
+#endif /*KEYBOX_WITH_X509*/
+
+int _keybox_new_blob (KEYBOXBLOB *r_blob,
+ unsigned char *image, size_t imagelen,
+ off_t off);
+void _keybox_release_blob (KEYBOXBLOB blob);
+const unsigned char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n);
+off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob);
+void _keybox_update_header_blob (KEYBOXBLOB blob, int for_openpgp);
+
+/*-- keybox-openpgp.c --*/
+gpg_error_t _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
+ size_t *nparsed,
+ keybox_openpgp_info_t info);
+void _keybox_destroy_openpgp_info (keybox_openpgp_info_t info);
+
+
+/*-- keybox-file.c --*/
+int _keybox_read_blob (KEYBOXBLOB *r_blob, estream_t fp, int *skipped_deleted);
+int _keybox_write_blob (KEYBOXBLOB blob, estream_t fp, FILE *outfp);
+
+/*-- keybox-search.c --*/
+gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer,
+ size_t length,
+ int what,
+ size_t *flag_off, size_t *flag_size);
+
+static inline int
+blob_get_type (KEYBOXBLOB blob)
+{
+ const unsigned char *buffer;
+ size_t length;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 32)
+ return -1; /* blob too short */
+
+ return buffer[4];
+}
+
+
+/*-- keybox-dump.c --*/
+int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
+int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp);
+int _keybox_dump_find_dups (const char *filename, int print_them, FILE *outfp);
+int _keybox_dump_cut_records (const char *filename, unsigned long from,
+ unsigned long to, FILE *outfp);
+
+
+/*-- keybox-util.c --*/
+
+/*
+ * A couple of handy macros
+ */
+
+
+#endif /*KEYBOX_DEFS_H*/
diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c
new file mode 100644
index 0000000..3e66b72
--- /dev/null
+++ b/kbx/keybox-dump.c
@@ -0,0 +1,915 @@
+/* keybox-dump.c - Debug helpers
+ * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "keybox-defs.h"
+#include <gcrypt.h>
+#include "../common/host2net.h"
+
+/* Argg, we can't include ../common/util.h */
+char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf);
+
+#define get32(a) buf32_to_ulong ((a))
+#define get16(a) buf16_to_ulong ((a))
+
+
+void
+print_string (FILE *fp, const byte *p, size_t n, int delim)
+{
+ for ( ; n; n--, p++ )
+ {
+ if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
+ {
+ putc('\\', fp);
+ if( *p == '\n' )
+ putc('n', fp);
+ else if( *p == '\r' )
+ putc('r', fp);
+ else if( *p == '\f' )
+ putc('f', fp);
+ else if( *p == '\v' )
+ putc('v', fp);
+ else if( *p == '\b' )
+ putc('b', fp);
+ else if( !*p )
+ putc('0', fp);
+ else
+ fprintf(fp, "x%02x", *p );
+ }
+ else
+ putc(*p, fp);
+ }
+}
+
+
+static int
+print_checksum (const byte *buffer, size_t length, size_t unhashed, FILE *fp)
+{
+ const byte *p;
+ int i;
+ int hashlen;
+ unsigned char digest[20];
+
+ fprintf (fp, "Checksum: ");
+ if (unhashed && unhashed < 20)
+ {
+ fputs ("[specified unhashed sized too short]\n", fp);
+ return 0;
+ }
+ if (!unhashed)
+ {
+ unhashed = 16;
+ hashlen = 16;
+ }
+ else
+ hashlen = 20;
+
+ if (length < 5+unhashed)
+ {
+ fputs ("[blob too short for a checksum]\n", fp);
+ return 0;
+ }
+
+ p = buffer + length - hashlen;
+ for (i=0; i < hashlen; p++, i++)
+ fprintf (fp, "%02x", *p);
+
+ if (hashlen == 16) /* Compatibility method. */
+ {
+ gcry_md_hash_buffer (GCRY_MD_MD5, digest, buffer, length - 16);
+ if (!memcmp (buffer + length - 16, digest, 16))
+ fputs (" [valid]\n", fp);
+ else
+ fputs (" [bad]\n", fp);
+ }
+ else
+ {
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer, length - unhashed);
+ if (!memcmp (buffer + length - hashlen, digest, hashlen))
+ fputs (" [valid]\n", fp);
+ else
+ fputs (" [bad]\n", fp);
+ }
+ return 0;
+}
+
+
+static int
+dump_header_blob (const byte *buffer, size_t length, FILE *fp)
+{
+ unsigned long n;
+
+ if (length < 32)
+ {
+ fprintf (fp, "[blob too short]\n");
+ return -1;
+ }
+ fprintf (fp, "Version: %d\n", buffer[5]);
+
+ n = get16 (buffer + 6);
+ fprintf( fp, "Flags: %04lX", n);
+ if (n)
+ {
+ int any = 0;
+
+ fputs (" (", fp);
+ if ((n & 2))
+ {
+ if (any)
+ putc (',', fp);
+ fputs ("openpgp", fp);
+ any++;
+ }
+ putc (')', fp);
+ }
+ putc ('\n', fp);
+
+ if ( memcmp (buffer+8, "KBXf", 4))
+ fprintf (fp, "[Error: invalid magic number]\n");
+
+ n = get32 (buffer+16);
+ fprintf( fp, "created-at: %lu\n", n );
+ n = get32 (buffer+20);
+ fprintf( fp, "last-maint: %lu\n", n );
+
+ return 0;
+}
+
+
+/* Dump one block to FP */
+int
+_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
+{
+ const byte *buffer;
+ size_t length;
+ int type, i;
+ ulong n, nkeys, keyinfolen;
+ ulong nuids, uidinfolen;
+ ulong nsigs, siginfolen;
+ ulong rawdata_off, rawdata_len;
+ ulong nserial;
+ ulong unhashed;
+ const byte *p;
+ const byte *pend;
+ int is_fpr32; /* blob version 2 */
+
+ buffer = _keybox_get_blob_image (blob, &length);
+
+ if (length < 32)
+ {
+ fprintf (fp, "[blob too short]\n");
+ return -1;
+ }
+
+ n = get32( buffer );
+ if (n > length)
+ fprintf (fp, "[blob larger than length - output truncated]\n");
+ else
+ length = n; /* ignore the rest */
+
+ fprintf (fp, "Length: %lu\n", n );
+ type = buffer[4];
+ switch (type)
+ {
+ case KEYBOX_BLOBTYPE_EMPTY:
+ fprintf (fp, "Type: Empty\n");
+ return 0;
+
+ case KEYBOX_BLOBTYPE_HEADER:
+ fprintf (fp, "Type: Header\n");
+ return dump_header_blob (buffer, length, fp);
+ case KEYBOX_BLOBTYPE_PGP:
+ fprintf (fp, "Type: OpenPGP\n");
+ break;
+ case KEYBOX_BLOBTYPE_X509:
+ fprintf (fp, "Type: X.509\n");
+ break;
+ default:
+ fprintf (fp, "Type: %d\n", type);
+ fprintf (fp, "[can't dump this blob type]\n");
+ return 0;
+ }
+ /* Here we have either BLOGTYPE_X509 or BLOBTYPE_OPENPGP */
+ fprintf (fp, "Version: %d\n", buffer[5]);
+ is_fpr32 = buffer[5] == 2;
+
+ if (length < 40)
+ {
+ fprintf (fp, "[blob too short]\n");
+ return -1;
+ }
+
+ n = get16 (buffer + 6);
+ fprintf( fp, "Blob-Flags: %04lX", n);
+ if (n)
+ {
+ int any = 0;
+
+ fputs (" (", fp);
+ if ((n & 1))
+ {
+ fputs ("secret", fp);
+ any++;
+ }
+ if ((n & 2))
+ {
+ if (any)
+ putc (',', fp);
+ fputs ("ephemeral", fp);
+ any++;
+ }
+ putc (')', fp);
+ }
+ putc ('\n', fp);
+
+ rawdata_off = get32 (buffer + 8);
+ rawdata_len = get32 (buffer + 12);
+
+ fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
+ fprintf( fp, "Data-Length: %lu\n", rawdata_len );
+ if (rawdata_off > length || rawdata_len > length
+ || rawdata_off+rawdata_len > length
+ || rawdata_len + 4 > length
+ || rawdata_off+rawdata_len + 4 > length)
+ {
+ fprintf (fp, "[Error: raw data larger than blob]\n");
+ return -1;
+ }
+
+ if (rawdata_off > length
+ || rawdata_len > length
+ || rawdata_off + rawdata_len > length)
+ {
+ fprintf (fp, "[Error: unhashed data larger than blob]\n");
+ return -1;
+ }
+ unhashed = length - rawdata_off - rawdata_len;
+ fprintf (fp, "Unhashed: %lu\n", unhashed);
+
+ nkeys = get16 (buffer + 16);
+ fprintf (fp, "Key-Count: %lu\n", nkeys );
+ if (!nkeys)
+ fprintf (fp, "[Error: no keys]\n");
+ if (nkeys > 1 && type == KEYBOX_BLOBTYPE_X509)
+ fprintf (fp, "[Error: only one key allowed for X509]\n");
+
+ keyinfolen = get16 (buffer + 18 );
+ fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
+ p = buffer + 20;
+ pend = buffer + length;
+ for (n=0; n < nkeys; n++, p += keyinfolen)
+ {
+ ulong kidoff, kflags;
+
+ if (p + keyinfolen >= pend)
+ {
+ fprintf (fp, "[Error: key data larger than blob]\n");
+ return -1;
+ }
+
+ fprintf (fp, "Key-Fpr[%lu]: ", n );
+ if (is_fpr32)
+ {
+ if (p + 32 + 2 >= pend)
+ {
+ fprintf (fp, "[Error: fingerprint data larger than blob]\n");
+ return -1;
+ }
+ kflags = get16 (p + 32 );
+ for (i=0; i < ((kflags & 0x80)?32:20); i++ )
+ fprintf (fp, "%02X", p[i]);
+ }
+ else
+ {
+ if (p + 20 + 4 >= pend)
+ {
+ fprintf (fp, "[Error: fingerprint data larger than blob]\n");
+ return -1;
+ }
+ for (i=0; i < 20; i++ )
+ fprintf (fp, "%02X", p[i]);
+ kidoff = get32 (p + 20);
+ fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
+ fprintf (fp, "Key-Kid[%lu]: ", n );
+
+ if (p + kidoff + 8 >= pend)
+ {
+ fprintf (fp, "[Error: fingerprint data larger than blob]\n");
+ return -1;
+ }
+ for (i=0; i < 8; i++ )
+ fprintf (fp, "%02X", buffer[kidoff+i] );
+ if (p + 24 >= pend)
+ {
+ fprintf (fp, "[Error: fingerprint data larger than blob]\n");
+ return -1;
+ }
+ kflags = get16 (p + 24);
+ }
+ fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
+ }
+
+ /* serial number */
+ if (p + 2 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ fputs ("Serial-No: ", fp);
+ nserial = get16 (p);
+ p += 2;
+ if (!nserial)
+ fputs ("none", fp);
+ else
+ {
+ if (p + nserial >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ for (; nserial; nserial--, p++)
+ fprintf (fp, "%02X", *p);
+ }
+ putc ('\n', fp);
+
+ /* user IDs */
+ if (p + 4 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ nuids = get16 (p);
+ fprintf (fp, "Uid-Count: %lu\n", nuids );
+ uidinfolen = get16 (p + 2);
+ fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
+ p += 4;
+ for (n=0; n < nuids; n++, p += uidinfolen)
+ {
+ ulong uidoff, uidlen, uflags;
+
+ if (p + uidinfolen >= pend || uidinfolen < 8)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+
+ uidoff = get32( p );
+ uidlen = get32( p+4 );
+ if (type == KEYBOX_BLOBTYPE_X509 && !n)
+ {
+ fprintf (fp, "Issuer-Off: %lu\n", uidoff );
+ fprintf (fp, "Issuer-Len: %lu\n", uidlen );
+ fprintf (fp, "Issuer: \"");
+ }
+ else if (type == KEYBOX_BLOBTYPE_X509 && n == 1)
+ {
+ fprintf (fp, "Subject-Off: %lu\n", uidoff );
+ fprintf (fp, "Subject-Len: %lu\n", uidlen );
+ fprintf (fp, "Subject: \"");
+ }
+ else
+ {
+ fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff );
+ fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
+ fprintf (fp, "Uid[%lu]: \"", n );
+ }
+
+ if (uidoff + uidlen > length
+ || uidoff + uidlen < uidoff
+ || uidoff + uidlen < uidlen)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ print_string (fp, buffer+uidoff, uidlen, '\"');
+ fputs ("\"\n", fp);
+ if (p + 8 + 2 + 1 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ uflags = get16 (p + 8);
+ if (type == KEYBOX_BLOBTYPE_X509 && !n)
+ {
+ fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
+ fprintf (fp, "Issuer-Validity: %d\n", p[10] );
+ }
+ else if (type == KEYBOX_BLOBTYPE_X509 && n == 1)
+ {
+ fprintf (fp, "Subject-Flags: %04lX\n", uflags );
+ fprintf (fp, "Subject-Validity: %d\n", p[10] );
+ }
+ else
+ {
+ fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags );
+ fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] );
+ }
+ }
+
+ if (p + 2 + 2 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ nsigs = get16 (p);
+ fprintf (fp, "Sig-Count: %lu\n", nsigs );
+ siginfolen = get16 (p + 2);
+ fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
+ p += 4;
+ {
+ int in_range = 0;
+ ulong first = 0;
+
+ for (n=0; n < nsigs; n++, p += siginfolen)
+ {
+ ulong sflags;
+
+ if (p + siginfolen >= pend || siginfolen < 4)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ sflags = get32 (p);
+ if (!in_range && !sflags)
+ {
+ in_range = 1;
+ first = n;
+ continue;
+ }
+ if (in_range && !sflags)
+ continue;
+ if (in_range)
+ {
+ fprintf (fp, "Sig-Expire[%lu-%lu]: [not checked]\n", first, n-1);
+ in_range = 0;
+ }
+
+ fprintf (fp, "Sig-Expire[%lu]: ", n );
+ if (!sflags)
+ fputs ("[not checked]", fp);
+ else if (sflags == 1 )
+ fputs ("[missing key]", fp);
+ else if (sflags == 2 )
+ fputs ("[bad signature]", fp);
+ else if (sflags < 0x10000000)
+ fprintf (fp, "[bad flag %0lx]", sflags);
+ else if (sflags == (ulong)(-1))
+ fputs ("[good - does not expire]", fp );
+ else
+ fprintf (fp, "[good - expires at %lu]", sflags);
+ putc ('\n', fp );
+ }
+ if (in_range)
+ fprintf (fp, "Sig-Expire[%lu-%lu]: [not checked]\n", first, n-1);
+ }
+
+ if (p + 16 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ fprintf (fp, "Ownertrust: %d\n", p[0] );
+ fprintf (fp, "All-Validity: %d\n", p[1] );
+ p += 4;
+ n = get32 (p);
+ p += 4;
+ fprintf (fp, "Recheck-After: %lu\n", n );
+ n = get32 (p );
+ p += 4;
+ fprintf( fp, "Latest-Timestamp: %lu\n", n );
+ n = get32 (p );
+ p += 4;
+ fprintf (fp, "Created-At: %lu\n", n );
+
+ if (p + 4 >= pend)
+ {
+ fprintf (fp, "[Error: data larger than blob]\n");
+ return -1;
+ }
+ n = get32 (p );
+ fprintf (fp, "Reserved-Space: %lu\n", n );
+
+ if (n >= 4 && unhashed >= 24)
+ {
+ n = get32 ( buffer + length - unhashed);
+ fprintf (fp, "Storage-Flags: %08lx\n", n );
+ }
+ print_checksum (buffer, length, unhashed, fp);
+ return 0;
+}
+
+
+/* Compute the SHA-1 checksum of the rawdata in BLOB and put it into
+ DIGEST. */
+static int
+hash_blob_rawdata (KEYBOXBLOB blob, unsigned char *digest)
+{
+ const unsigned char *buffer;
+ size_t n, length;
+ int type;
+ ulong rawdata_off, rawdata_len;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+
+ if (length < 32)
+ return -1;
+ n = get32 (buffer);
+ if (n < length)
+ length = n; /* Blob larger than length in header - ignore the rest. */
+
+ type = buffer[4];
+ switch (type)
+ {
+ case KEYBOX_BLOBTYPE_PGP:
+ case KEYBOX_BLOBTYPE_X509:
+ break;
+
+ case KEYBOX_BLOBTYPE_EMPTY:
+ case KEYBOX_BLOBTYPE_HEADER:
+ default:
+ memset (digest, 0, 20);
+ return 0;
+ }
+
+ if (length < 40)
+ return -1;
+
+ rawdata_off = get32 (buffer + 8);
+ rawdata_len = get32 (buffer + 12);
+
+ if (rawdata_off > length || rawdata_len > length
+ || rawdata_off+rawdata_off > length)
+ return -1; /* Out of bounds. */
+
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer+rawdata_off, rawdata_len);
+ return 0;
+}
+
+
+struct file_stats_s
+{
+ unsigned long too_short_blobs;
+ unsigned long too_large_blobs;
+ unsigned long total_blob_count;
+ unsigned long empty_blob_count;
+ unsigned long header_blob_count;
+ unsigned long pgp_blob_count;
+ unsigned long x509_blob_count;
+ unsigned long unknown_blob_count;
+ unsigned long non_flagged;
+ unsigned long secret_flagged;
+ unsigned long ephemeral_flagged;
+ unsigned long skipped_long_blobs;
+};
+
+static int
+update_stats (KEYBOXBLOB blob, struct file_stats_s *s)
+{
+ const unsigned char *buffer;
+ size_t length;
+ int type;
+ unsigned long n;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 32)
+ {
+ s->too_short_blobs++;
+ return -1;
+ }
+
+ n = get32( buffer );
+ if (n > length)
+ s->too_large_blobs++;
+ else
+ length = n; /* ignore the rest */
+
+ s->total_blob_count++;
+ type = buffer[4];
+ switch (type)
+ {
+ case KEYBOX_BLOBTYPE_EMPTY:
+ s->empty_blob_count++;
+ return 0;
+ case KEYBOX_BLOBTYPE_HEADER:
+ s->header_blob_count++;
+ return 0;
+ case KEYBOX_BLOBTYPE_PGP:
+ s->pgp_blob_count++;
+ break;
+ case KEYBOX_BLOBTYPE_X509:
+ s->x509_blob_count++;
+ break;
+ default:
+ s->unknown_blob_count++;
+ return 0;
+ }
+
+ if (length < 40)
+ {
+ s->too_short_blobs++;
+ return -1;
+ }
+
+ n = get16 (buffer + 6);
+ if (n)
+ {
+ if ((n & 1))
+ s->secret_flagged++;
+ if ((n & 2))
+ s->ephemeral_flagged++;
+ }
+ else
+ s->non_flagged++;
+
+ return 0;
+}
+
+
+
+static estream_t
+open_file (const char **filename, FILE *outfp)
+{
+ estream_t fp;
+
+ if (!*filename)
+ {
+ *filename = "-";
+ fp = es_stdin;
+ }
+ else
+ fp = es_fopen (*filename, "rb");
+ if (!fp)
+ {
+ int save_errno = errno;
+ fprintf (outfp, "can't open '%s': %s\n", *filename, strerror(errno));
+ gpg_err_set_errno (save_errno);
+ }
+ return fp;
+}
+
+
+
+int
+_keybox_dump_file (const char *filename, int stats_only, FILE *outfp)
+{
+ estream_t fp;
+ KEYBOXBLOB blob;
+ int rc;
+ unsigned long count = 0;
+ struct file_stats_s stats;
+ int skipped_deleted;
+
+ memset (&stats, 0, sizeof stats);
+
+ if (!(fp = open_file (&filename, outfp)))
+ return gpg_error_from_syserror ();
+
+ for (;;)
+ {
+ rc = _keybox_read_blob (&blob, fp, &skipped_deleted);
+ if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
+ && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
+ {
+ if (stats_only)
+ stats.skipped_long_blobs++;
+ else
+ {
+ fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
+ fprintf (outfp, "# Record too large\nEND-RECORD\n");
+ }
+ count++;
+ continue;
+ }
+ if (rc)
+ break;
+
+ count += skipped_deleted;
+
+ if (stats_only)
+ {
+ stats.total_blob_count += skipped_deleted;
+ stats.empty_blob_count += skipped_deleted;
+ update_stats (blob, &stats);
+ }
+ else
+ {
+ fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
+ _keybox_dump_blob (blob, outfp);
+ fprintf (outfp, "END-RECORD\n");
+ }
+ _keybox_release_blob (blob);
+ count++;
+ }
+ if (rc == -1)
+ rc = 0;
+ if (rc)
+ fprintf (outfp, "# error reading '%s': %s\n", filename, gpg_strerror (rc));
+
+ if (fp != es_stdin)
+ es_fclose (fp);
+
+ if (stats_only)
+ {
+ fprintf (outfp,
+ "Total number of blobs: %8lu\n"
+ " header: %8lu\n"
+ " empty: %8lu\n"
+ " openpgp: %8lu\n"
+ " x509: %8lu\n"
+ " non flagged: %8lu\n"
+ " secret flagged: %8lu\n"
+ " ephemeral flagged: %8lu\n",
+ stats.total_blob_count,
+ stats.header_blob_count,
+ stats.empty_blob_count,
+ stats.pgp_blob_count,
+ stats.x509_blob_count,
+ stats.non_flagged,
+ stats.secret_flagged,
+ stats.ephemeral_flagged);
+ if (stats.skipped_long_blobs)
+ fprintf (outfp, " skipped long blobs: %8lu\n",
+ stats.skipped_long_blobs);
+ if (stats.unknown_blob_count)
+ fprintf (outfp, " unknown blob types: %8lu\n",
+ stats.unknown_blob_count);
+ if (stats.too_short_blobs)
+ fprintf (outfp, " too short blobs: %8lu (error)\n",
+ stats.too_short_blobs);
+ if (stats.too_large_blobs)
+ fprintf (outfp, " too large blobs: %8lu (error)\n",
+ stats.too_large_blobs);
+ }
+
+ return rc;
+}
+
+
+
+struct dupitem_s
+{
+ unsigned long recno;
+ unsigned char digest[20];
+};
+
+
+static int
+cmp_dupitems (const void *arg_a, const void *arg_b)
+{
+ struct dupitem_s *a = (struct dupitem_s *)arg_a;
+ struct dupitem_s *b = (struct dupitem_s *)arg_b;
+
+ return memcmp (a->digest, b->digest, 20);
+}
+
+
+int
+_keybox_dump_find_dups (const char *filename, int print_them, FILE *outfp)
+{
+ estream_t fp;
+ KEYBOXBLOB blob;
+ int rc;
+ unsigned long recno = 0;
+ unsigned char zerodigest[20];
+ struct dupitem_s *dupitems;
+ size_t dupitems_size, dupitems_count, lastn, n;
+ char fprbuf[3*20+1];
+
+ (void)print_them;
+
+ memset (zerodigest, 0, sizeof zerodigest);
+
+ if (!(fp = open_file (&filename, outfp)))
+ return gpg_error_from_syserror ();
+
+ dupitems_size = 1000;
+ dupitems = malloc (dupitems_size * sizeof *dupitems);
+ if (!dupitems)
+ {
+ gpg_error_t tmperr = gpg_error_from_syserror ();
+ fprintf (outfp, "error allocating array for '%s': %s\n",
+ filename, strerror(errno));
+ return tmperr;
+ }
+ dupitems_count = 0;
+
+ while ( !(rc = _keybox_read_blob (&blob, fp, NULL)) )
+ {
+ unsigned char digest[20];
+
+ if (hash_blob_rawdata (blob, digest))
+ fprintf (outfp, "error in blob %ld of '%s'\n", recno, filename);
+ else if (memcmp (digest, zerodigest, 20))
+ {
+ if (dupitems_count >= dupitems_size)
+ {
+ struct dupitem_s *tmp;
+
+ dupitems_size += 1000;
+ tmp = realloc (dupitems, dupitems_size * sizeof *dupitems);
+ if (!tmp)
+ {
+ gpg_error_t tmperr = gpg_error_from_syserror ();
+ fprintf (outfp, "error reallocating array for '%s': %s\n",
+ filename, strerror(errno));
+ free (dupitems);
+ return tmperr;
+ }
+ dupitems = tmp;
+ }
+ dupitems[dupitems_count].recno = recno;
+ memcpy (dupitems[dupitems_count].digest, digest, 20);
+ dupitems_count++;
+ }
+ _keybox_release_blob (blob);
+ recno++;
+ }
+ if (rc == -1)
+ rc = 0;
+ if (rc)
+ fprintf (outfp, "error reading '%s': %s\n", filename, gpg_strerror (rc));
+ if (fp != es_stdin)
+ es_fclose (fp);
+
+ qsort (dupitems, dupitems_count, sizeof *dupitems, cmp_dupitems);
+
+ for (lastn=0, n=1; n < dupitems_count; lastn=n, n++)
+ {
+ if (!memcmp (dupitems[lastn].digest, dupitems[n].digest, 20))
+ {
+ bin2hexcolon (dupitems[lastn].digest, 20, fprbuf);
+ fprintf (outfp, "fpr=%s recno=%lu", fprbuf, dupitems[lastn].recno);
+ do
+ fprintf (outfp, " %lu", dupitems[n].recno);
+ while (++n < dupitems_count
+ && !memcmp (dupitems[lastn].digest, dupitems[n].digest, 20));
+ putc ('\n', outfp);
+ n--;
+ }
+ }
+
+ free (dupitems);
+
+ return rc;
+}
+
+
+/* Print records with record numbers FROM to TO to OUTFP. */
+int
+_keybox_dump_cut_records (const char *filename, unsigned long from,
+ unsigned long to, FILE *outfp)
+{
+ estream_t fp;
+ KEYBOXBLOB blob;
+ int rc;
+ unsigned long recno = 0;
+
+ if (!(fp = open_file (&filename, stderr)))
+ return gpg_error_from_syserror ();
+
+ while ( !(rc = _keybox_read_blob (&blob, fp, NULL)) )
+ {
+ if (recno > to)
+ break; /* Ready. */
+ if (recno >= from)
+ {
+ if ((rc = _keybox_write_blob (blob, NULL, outfp)))
+ {
+ fprintf (stderr, "error writing output: %s\n",
+ gpg_strerror (rc));
+ goto leave;
+ }
+ }
+ _keybox_release_blob (blob);
+ recno++;
+ }
+ if (rc == -1)
+ rc = 0;
+ if (rc)
+ fprintf (stderr, "error reading '%s': %s\n", filename, gpg_strerror (rc));
+ leave:
+ if (fp != es_stdin)
+ es_fclose (fp);
+ return rc;
+}
diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c
new file mode 100644
index 0000000..c36f5be
--- /dev/null
+++ b/kbx/keybox-file.c
@@ -0,0 +1,190 @@
+/* keybox-file.c - File operations
+ * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "keybox-defs.h"
+
+
+#define IMAGELEN_LIMIT (5*1024*1024)
+
+
+#if !defined(HAVE_FTELLO) && !defined(ftello)
+static off_t
+ftello (FILE *stream)
+{
+ long int off;
+
+ off = ftell (stream);
+ if (off == -1)
+ return (off_t)-1;
+ return off;
+}
+#endif /* !defined(HAVE_FTELLO) && !defined(ftello) */
+
+
+
+/* Read a block at the current position and return it in R_BLOB.
+ R_BLOB may be NULL to simply skip the current block. */
+int
+_keybox_read_blob (KEYBOXBLOB *r_blob, estream_t fp, int *skipped_deleted)
+{
+ unsigned char *image;
+ size_t imagelen = 0;
+ int c1, c2, c3, c4, type;
+ int rc;
+ off_t off;
+
+ if (skipped_deleted)
+ *skipped_deleted = 0;
+ again:
+ if (r_blob)
+ *r_blob = NULL;
+ off = es_ftello (fp);
+ if (off == (off_t)-1)
+ return gpg_error_from_syserror ();
+
+ if ((c1 = es_getc (fp)) == EOF
+ || (c2 = es_getc (fp)) == EOF
+ || (c3 = es_getc (fp)) == EOF
+ || (c4 = es_getc (fp)) == EOF
+ || (type = es_getc (fp)) == EOF)
+ {
+ if ( c1 == EOF && !es_ferror (fp) )
+ return -1; /* eof */
+ if (!es_ferror (fp))
+ return gpg_error (GPG_ERR_TOO_SHORT);
+ return gpg_error_from_syserror ();
+ }
+
+ imagelen = ((unsigned int) c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
+ if (imagelen < 5)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+
+ if (!type)
+ {
+ /* Special treatment for empty blobs. */
+ if (es_fseek (fp, imagelen-5, SEEK_CUR))
+ return gpg_error_from_syserror ();
+ if (skipped_deleted)
+ *skipped_deleted = 1;
+ goto again;
+ }
+
+ if (imagelen > IMAGELEN_LIMIT) /* Sanity check. */
+ {
+ /* Seek forward so that the caller may choose to ignore this
+ record. */
+ if (es_fseek (fp, imagelen-5, SEEK_CUR))
+ return gpg_error_from_syserror ();
+ return gpg_error (GPG_ERR_TOO_LARGE);
+ }
+
+ if (!r_blob)
+ {
+ /* This blob shall be skipped. */
+ if (es_fseek (fp, imagelen-5, SEEK_CUR))
+ return gpg_error_from_syserror ();
+ return 0;
+ }
+
+ image = xtrymalloc (imagelen);
+ if (!image)
+ return gpg_error_from_syserror ();
+
+ image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type;
+ if (es_fread (image+5, imagelen-5, 1, fp) != 1)
+ {
+ gpg_error_t tmperr = gpg_error_from_syserror ();
+ xfree (image);
+ return tmperr;
+ }
+
+ rc = _keybox_new_blob (r_blob, image, imagelen, off);
+ if (rc)
+ xfree (image);
+ return rc;
+}
+
+
+/* Write the block to the current file position */
+int
+_keybox_write_blob (KEYBOXBLOB blob, estream_t fp, FILE *outfp)
+{
+ const unsigned char *image;
+ size_t length;
+
+ image = _keybox_get_blob_image (blob, &length);
+
+ if (length > IMAGELEN_LIMIT)
+ return gpg_error (GPG_ERR_TOO_LARGE);
+
+ if (fp)
+ {
+ if (es_fwrite (image, length, 1, fp) != 1)
+ return gpg_error_from_syserror ();
+ }
+ else
+ {
+ if (fwrite (image, length, 1, outfp) != 1)
+ return gpg_error_from_syserror ();
+ }
+
+ return 0;
+}
+
+
+/* Write a fresh header type blob. */
+int
+_keybox_write_header_blob (estream_t fp, int for_openpgp)
+{
+ unsigned char image[32];
+ u32 val;
+
+ memset (image, 0, sizeof image);
+ /* Length of this blob. */
+ image[3] = 32;
+
+ image[4] = KEYBOX_BLOBTYPE_HEADER;
+ image[5] = 1; /* Version */
+ if (for_openpgp)
+ image[7] = 0x02; /* OpenPGP data may be available. */
+
+ memcpy (image+8, "KBXf", 4);
+ val = time (NULL);
+ /* created_at and last maintenance run. */
+ image[16] = (val >> 24);
+ image[16+1] = (val >> 16);
+ image[16+2] = (val >> 8);
+ image[16+3] = (val );
+ image[20] = (val >> 24);
+ image[20+1] = (val >> 16);
+ image[20+2] = (val >> 8);
+ image[20+3] = (val );
+
+ if (es_fwrite (image, 32, 1, fp) != 1)
+ return gpg_error_from_syserror ();
+
+ return 0;
+}
diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c
new file mode 100644
index 0000000..f07ba8d
--- /dev/null
+++ b/kbx/keybox-init.c
@@ -0,0 +1,352 @@
+/* keybox-init.c - Initialization of the library
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "keybox-defs.h"
+#include "../common/sysutils.h"
+#include "../common/mischelp.h"
+
+static KB_NAME kb_names;
+
+
+/* Register a filename for plain keybox files. Returns 0 on success,
+ * GPG_ERR_EEXIST if it has already been registered, or another error
+ * code. On success or with error code GPG_ERR_EEXIST a token usable
+ * to access the keybox handle is stored at R_TOKEN, NULL is stored
+ * for all other errors. */
+gpg_error_t
+keybox_register_file (const char *fname, int secret, void **r_token)
+{
+ KB_NAME kr;
+
+ *r_token = NULL;
+
+ for (kr=kb_names; kr; kr = kr->next)
+ {
+ if (same_file_p (kr->fname, fname) )
+ {
+ *r_token = kr;
+ return gpg_error (GPG_ERR_EEXIST); /* Already registered. */
+ }
+ }
+
+ kr = xtrymalloc (sizeof *kr + strlen (fname));
+ if (!kr)
+ return gpg_error_from_syserror ();
+ strcpy (kr->fname, fname);
+ kr->secret = !!secret;
+
+ kr->handle_table = NULL;
+ kr->handle_table_size = 0;
+
+ kr->lockhd = NULL;
+ kr->is_locked = 0;
+ kr->did_full_scan = 0;
+ /* keep a list of all issued pointers */
+ kr->next = kb_names;
+ kb_names = kr;
+
+ /* create the offset table the first time a function here is used */
+/* if (!kb_offtbl) */
+/* kb_offtbl = new_offset_hash_table (); */
+
+ *r_token = kr;
+ return 0;
+}
+
+int
+keybox_is_writable (void *token)
+{
+ KB_NAME r = token;
+
+ return r? !gnupg_access (r->fname, W_OK) : 0;
+}
+
+
+
+static KEYBOX_HANDLE
+do_keybox_new (KB_NAME resource, int secret, int for_openpgp)
+{
+ KEYBOX_HANDLE hd;
+ int idx;
+
+ assert (resource && !resource->secret == !secret);
+ hd = xtrycalloc (1, sizeof *hd);
+ if (hd)
+ {
+ hd->kb = resource;
+ hd->secret = !!secret;
+ hd->for_openpgp = for_openpgp;
+ if (!resource->handle_table)
+ {
+ resource->handle_table_size = 3;
+ resource->handle_table = xtrycalloc (resource->handle_table_size,
+ sizeof *resource->handle_table);
+ if (!resource->handle_table)
+ {
+ resource->handle_table_size = 0;
+ xfree (hd);
+ return NULL;
+ }
+ }
+ for (idx=0; idx < resource->handle_table_size; idx++)
+ if (!resource->handle_table[idx])
+ {
+ resource->handle_table[idx] = hd;
+ break;
+ }
+ if (!(idx < resource->handle_table_size))
+ {
+ KEYBOX_HANDLE *tmptbl;
+ size_t newsize;
+
+ newsize = resource->handle_table_size + 5;
+ tmptbl = xtryrealloc (resource->handle_table,
+ newsize * sizeof (*tmptbl));
+ if (!tmptbl)
+ {
+ xfree (hd);
+ return NULL;
+ }
+ resource->handle_table = tmptbl;
+ resource->handle_table_size = newsize;
+ resource->handle_table[idx] = hd;
+ for (idx++; idx < resource->handle_table_size; idx++)
+ resource->handle_table[idx] = NULL;
+ }
+ }
+ return hd;
+}
+
+
+/* Create a new handle for the resource associated with TOKEN. SECRET
+ is just a cross-check. This is the OpenPGP version. The returned
+ handle must be released using keybox_release. */
+KEYBOX_HANDLE
+keybox_new_openpgp (void *token, int secret)
+{
+ KB_NAME resource = token;
+
+ return do_keybox_new (resource, secret, 1);
+}
+
+/* Create a new handle for the resource associated with TOKEN. SECRET
+ is just a cross-check. This is the X.509 version. The returned
+ handle must be released using keybox_release. */
+KEYBOX_HANDLE
+keybox_new_x509 (void *token, int secret)
+{
+ KB_NAME resource = token;
+
+ return do_keybox_new (resource, secret, 0);
+}
+
+
+void
+keybox_release (KEYBOX_HANDLE hd)
+{
+ if (!hd)
+ return;
+ if (hd->kb->handle_table)
+ {
+ int idx;
+ for (idx=0; idx < hd->kb->handle_table_size; idx++)
+ if (hd->kb->handle_table[idx] == hd)
+ hd->kb->handle_table[idx] = NULL;
+ }
+ _keybox_release_blob (hd->found.blob);
+ _keybox_release_blob (hd->saved_found.blob);
+ if (hd->fp)
+ {
+ es_fclose (hd->fp);
+ hd->fp = NULL;
+ }
+ xfree (hd->word_match.name);
+ xfree (hd->word_match.pattern);
+ xfree (hd);
+}
+
+
+/* Save the current found state in HD for later retrieval by
+ keybox_restore_found_state. Only one state may be saved. */
+void
+keybox_push_found_state (KEYBOX_HANDLE hd)
+{
+ if (hd->saved_found.blob)
+ {
+ _keybox_release_blob (hd->saved_found.blob);
+ hd->saved_found.blob = NULL;
+ }
+ hd->saved_found = hd->found;
+ hd->found.blob = NULL;
+}
+
+
+/* Restore the saved found state in HD. */
+void
+keybox_pop_found_state (KEYBOX_HANDLE hd)
+{
+ if (hd->found.blob)
+ {
+ _keybox_release_blob (hd->found.blob);
+ hd->found.blob = NULL;
+ }
+ hd->found = hd->saved_found;
+ hd->saved_found.blob = NULL;
+}
+
+
+const char *
+keybox_get_resource_name (KEYBOX_HANDLE hd)
+{
+ if (!hd || !hd->kb)
+ return NULL;
+ return hd->kb->fname;
+}
+
+int
+keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes)
+{
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ hd->ephemeral = yes;
+ return 0;
+}
+
+
+/* Close the file of the resource identified by HD. For consistent
+ results this function closes the files of all handles pointing to
+ the resource identified by HD. */
+void
+_keybox_close_file (KEYBOX_HANDLE hd)
+{
+ int idx;
+ KEYBOX_HANDLE roverhd;
+
+ if (!hd || !hd->kb || !hd->kb->handle_table)
+ return;
+
+ for (idx=0; idx < hd->kb->handle_table_size; idx++)
+ if ((roverhd = hd->kb->handle_table[idx]))
+ {
+ if (roverhd->fp)
+ {
+ es_fclose (roverhd->fp);
+ roverhd->fp = NULL;
+ }
+ }
+ log_assert (!hd->fp);
+}
+
+
+/* Close all the files associated with the resource identified by TOKEN. */
+void
+keybox_close_all_files (void *token)
+{
+ KB_NAME resource = token;
+ KEYBOX_HANDLE roverhd;
+ int idx;
+
+ if (!resource)
+ return;
+
+ for (idx=0; idx < resource->handle_table_size; idx++)
+ if ((roverhd = resource->handle_table[idx]) && roverhd->fp)
+ {
+ es_fclose (roverhd->fp);
+ roverhd->fp = NULL;
+ }
+}
+
+
+/*
+ * Lock the keybox at handle HD, or unlock if YES is false.
+ * Lock the keybox at handle HD, or unlock if YES is false. TIMEOUT
+ * is the value used for dotlock_take. In general -1 should be used
+ * when taking a lock; use 0 when releasing a lock.
+ */
+gpg_error_t
+keybox_lock (KEYBOX_HANDLE hd, int yes, long timeout)
+{
+ gpg_error_t err = 0;
+ KB_NAME kb = hd->kb;
+
+ if (!keybox_is_writable (kb))
+ return 0;
+
+ /* Make sure the lock handle has been created. */
+ if (!kb->lockhd)
+ {
+ kb->lockhd = dotlock_create (kb->fname, 0);
+ if (!kb->lockhd)
+ {
+ err = gpg_error_from_syserror ();
+ log_info ("can't allocate lock for '%s'\n", kb->fname );
+ return err;
+ }
+ }
+
+ if (yes) /* Take the lock. */
+ {
+ if (!kb->is_locked)
+ {
+#ifdef HAVE_W32_SYSTEM
+ /* Under Windows we need to close the file before we try
+ * to lock it. This is because another process might have
+ * taken the lock and is using keybox_file_rename to
+ * rename the base file. Now if our dotlock_take below is
+ * waiting for the lock but we have the base file still
+ * open, keybox_file_rename will never succeed as we are
+ * in a deadlock. */
+ _keybox_close_file (hd);
+#endif /*HAVE_W32_SYSTEM*/
+ if (dotlock_take (kb->lockhd, timeout))
+ {
+ err = gpg_error_from_syserror ();
+ if (!timeout && gpg_err_code (err) == GPG_ERR_EACCES)
+ ; /* No diagnostic if we only tried to lock. */
+ else
+ log_info ("can't lock '%s'\n", kb->fname );
+ }
+ else
+ kb->is_locked = 1;
+ }
+ }
+ else /* Release the lock. */
+ {
+ if (kb->is_locked)
+ {
+ if (dotlock_release (kb->lockhd))
+ {
+ err = gpg_error_from_syserror ();
+ log_info ("can't unlock '%s'\n", kb->fname );
+ }
+ else
+ kb->is_locked = 0;
+ }
+ }
+
+ return err;
+}
diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c
new file mode 100644
index 0000000..8ded683
--- /dev/null
+++ b/kbx/keybox-openpgp.c
@@ -0,0 +1,643 @@
+/* keybox-openpgp.c - OpenPGP key parsing
+ * Copyright (C) 2001, 2003, 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+/* This is a simple OpenPGP parser suitable for all OpenPGP key
+ material. It just provides the functionality required to build and
+ parse an KBX OpenPGP key blob. Thus it is not a complete parser.
+ However it is self-contained and optimized for fast in-memory
+ parsing. Note that we don't support old ElGamal v3 keys
+ anymore. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "keybox-defs.h"
+
+#include <gcrypt.h>
+
+#include "../common/openpgpdefs.h"
+#include "../common/host2net.h"
+
+struct keyparm_s
+{
+ const char *mpi;
+ int len; /* int to avoid a cast in gcry_sexp_build. */
+};
+
+
+/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
+ which has a maximum length as stored at BUFLEN. Return the header
+ information of that packet and advance the pointer stored at BUFPTR
+ to the next packet; also adjust the length stored at BUFLEN to
+ match the remaining bytes. If there are no more packets, store NULL
+ at BUFPTR. Return an non-zero error code on failure or the
+ following data on success:
+
+ R_DATAPKT = Pointer to the begin of the packet data.
+ R_DATALEN = Length of this data. This has already been checked to fit
+ into the buffer.
+ R_PKTTYPE = The packet type.
+ R_NTOTAL = The total number of bytes of this packet
+
+ Note that these values are only updated on success.
+*/
+static gpg_error_t
+next_packet (unsigned char const **bufptr, size_t *buflen,
+ unsigned char const **r_data, size_t *r_datalen, int *r_pkttype,
+ size_t *r_ntotal)
+{
+ const unsigned char *buf = *bufptr;
+ size_t len = *buflen;
+ int c, ctb, pkttype;
+ unsigned long pktlen;
+
+ if (!len)
+ return gpg_error (GPG_ERR_NO_DATA);
+
+ ctb = *buf++; len--;
+ if ( !(ctb & 0x80) )
+ return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */
+
+ if ((ctb & 0x40)) /* New style (OpenPGP) CTB. */
+ {
+ pkttype = (ctb & 0x3f);
+ if (!len)
+ return gpg_error (GPG_ERR_INV_PACKET); /* No 1st length byte. */
+ c = *buf++; len--;
+ if (pkttype == PKT_COMPRESSED)
+ return gpg_error (GPG_ERR_UNEXPECTED); /* ... packet in a keyblock. */
+ if ( c < 192 )
+ pktlen = c;
+ else if ( c < 224 )
+ {
+ pktlen = (c - 192) * 256;
+ if (!len)
+ return gpg_error (GPG_ERR_INV_PACKET); /* No 2nd length byte. */
+ c = *buf++; len--;
+ pktlen += c + 192;
+ }
+ else if (c == 255)
+ {
+ if (len <4 )
+ return gpg_error (GPG_ERR_INV_PACKET); /* No length bytes. */
+ pktlen = buf32_to_ulong (buf);
+ buf += 4;
+ len -= 4;
+ }
+ else /* Partial length encoding is not allowed for key packets. */
+ return gpg_error (GPG_ERR_UNEXPECTED);
+ }
+ else /* Old style CTB. */
+ {
+ int lenbytes;
+
+ pktlen = 0;
+ pkttype = (ctb>>2)&0xf;
+ lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
+ if (!lenbytes) /* Not allowed in key packets. */
+ return gpg_error (GPG_ERR_UNEXPECTED);
+ if (len < lenbytes)
+ return gpg_error (GPG_ERR_INV_PACKET); /* Not enough length bytes. */
+ for (; lenbytes; lenbytes--)
+ {
+ pktlen <<= 8;
+ pktlen |= *buf++; len--;
+ }
+ }
+
+ /* Do some basic sanity check. */
+ switch (pkttype)
+ {
+ case PKT_SIGNATURE:
+ case PKT_SECRET_KEY:
+ case PKT_PUBLIC_KEY:
+ case PKT_SECRET_SUBKEY:
+ case PKT_MARKER:
+ case PKT_RING_TRUST:
+ case PKT_USER_ID:
+ case PKT_PUBLIC_SUBKEY:
+ case PKT_OLD_COMMENT:
+ case PKT_ATTRIBUTE:
+ case PKT_COMMENT:
+ case PKT_GPG_CONTROL:
+ break; /* Okay these are allowed packets. */
+ default:
+ return gpg_error (GPG_ERR_UNEXPECTED);
+ }
+
+ if (pkttype == 63 && pktlen == 0xFFFFFFFF)
+ /* Sometimes the decompressing layer enters an error state in
+ which it simply outputs 0xff for every byte read. If we have a
+ stream of 0xff bytes, then it will be detected as a new format
+ packet with type 63 and a 4-byte encoded length that is 4G-1.
+ Since packets with type 63 are private and we use them as a
+ control packet, which won't be 4 GB, we reject such packets as
+ invalid. */
+ return gpg_error (GPG_ERR_INV_PACKET);
+
+ if (pktlen > len)
+ return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */
+
+ *r_data = buf;
+ *r_datalen = pktlen;
+ *r_pkttype = pkttype;
+ *r_ntotal = (buf - *bufptr) + pktlen;
+
+ *bufptr = buf + pktlen;
+ *buflen = len - pktlen;
+ if (!*buflen)
+ *bufptr = NULL;
+
+ return 0;
+}
+
+
+/* Take a list of key parameters KP for the OpenPGP ALGO and compute
+ * the keygrip which will be stored at GRIP. GRIP needs to be a
+ * buffer of 20 bytes. */
+static gpg_error_t
+keygrip_from_keyparm (int algo, struct keyparm_s *kp, unsigned char *grip)
+{
+ gpg_error_t err;
+ gcry_sexp_t s_pkey = NULL;
+
+ switch (algo)
+ {
+ case PUBKEY_ALGO_DSA:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi,
+ kp[2].len, kp[2].mpi,
+ kp[3].len, kp[3].mpi);
+ break;
+
+ case PUBKEY_ALGO_ELGAMAL:
+ case PUBKEY_ALGO_ELGAMAL_E:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(elg(p%b)(g%b)(y%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi,
+ kp[2].len, kp[2].mpi);
+ break;
+
+ case PUBKEY_ALGO_RSA:
+ case PUBKEY_ALGO_RSA_S:
+ case PUBKEY_ALGO_RSA_E:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(rsa(n%b)(e%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi);
+ break;
+
+ case PUBKEY_ALGO_EDDSA:
+ case PUBKEY_ALGO_ECDSA:
+ case PUBKEY_ALGO_ECDH:
+ {
+ char *curve = openpgp_oidbuf_to_str (kp[0].mpi, kp[0].len);
+ if (!curve)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ err = gcry_sexp_build
+ (&s_pkey, NULL,
+ (algo == PUBKEY_ALGO_EDDSA)?
+ "(public-key(ecc(curve%s)(flags eddsa)(q%b)))":
+ (algo == PUBKEY_ALGO_ECDH
+ && openpgp_oidbuf_is_cv25519 (kp[0].mpi, kp[0].len))?
+ "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))":
+ "(public-key(ecc(curve%s)(q%b)))",
+ curve, kp[1].len, kp[1].mpi);
+ xfree (curve);
+ }
+ }
+ break;
+
+ default:
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ break;
+ }
+
+ if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
+ {
+ /* Some Linux distributions remove certain curves from Libgcrypt
+ * but not from GnuPG and thus the keygrip can't be computed.
+ * Emit a better error message for this case. */
+ if (!gcry_pk_get_curve (s_pkey, 0, NULL))
+ err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
+ else
+ {
+ log_info ("kbx: error computing keygrip\n");
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+ }
+
+ gcry_sexp_release (s_pkey);
+
+ if (err)
+ memset (grip, 0, 20);
+ return err;
+}
+
+
+/* Parse a key packet and store the information in KI. */
+static gpg_error_t
+parse_key (const unsigned char *data, size_t datalen,
+ struct _keybox_openpgp_key_info *ki)
+{
+ gpg_error_t err;
+ const unsigned char *data_start = data;
+ int i, version, algorithm;
+ size_t n;
+ int npkey;
+ unsigned char hashbuffer[768];
+ gcry_md_hd_t md;
+ int is_ecc = 0;
+ struct keyparm_s keyparm[OPENPGP_MAX_NPKEY];
+ unsigned char *helpmpibuf[OPENPGP_MAX_NPKEY] = { NULL };
+
+ if (datalen < 5)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ version = *data++; datalen--;
+ if (version < 2 || version > 4 )
+ return gpg_error (GPG_ERR_INV_PACKET); /* Invalid version. */
+
+ /*timestamp = ((data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]));*/
+ data +=4; datalen -=4;
+
+ if (version < 4)
+ {
+ if (datalen < 2)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ data +=2; datalen -= 2;
+ }
+
+ if (!datalen)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ algorithm = *data++; datalen--;
+
+ switch (algorithm)
+ {
+ case PUBKEY_ALGO_RSA:
+ case PUBKEY_ALGO_RSA_E:
+ case PUBKEY_ALGO_RSA_S:
+ npkey = 2;
+ break;
+ case PUBKEY_ALGO_ELGAMAL_E:
+ case PUBKEY_ALGO_ELGAMAL:
+ npkey = 3;
+ break;
+ case PUBKEY_ALGO_DSA:
+ npkey = 4;
+ break;
+ case PUBKEY_ALGO_ECDH:
+ npkey = 3;
+ is_ecc = 1;
+ break;
+ case PUBKEY_ALGO_ECDSA:
+ case PUBKEY_ALGO_EDDSA:
+ npkey = 2;
+ is_ecc = 1;
+ break;
+ default: /* Unknown algorithm. */
+ return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
+ }
+
+ ki->algo = algorithm;
+
+ for (i=0; i < npkey; i++ )
+ {
+ unsigned int nbits, nbytes;
+
+ if (datalen < 2)
+ return gpg_error (GPG_ERR_INV_PACKET);
+
+ if (is_ecc && (i == 0 || i == 2))
+ {
+ nbytes = data[0];
+ if (nbytes < 2 || nbytes > 254)
+ return gpg_error (GPG_ERR_INV_PACKET);
+ nbytes++; /* The size byte itself. */
+ if (datalen < nbytes)
+ return gpg_error (GPG_ERR_INV_PACKET);
+
+ keyparm[i].mpi = data;
+ keyparm[i].len = nbytes;
+ }
+ else
+ {
+ nbits = ((data[0]<<8)|(data[1]));
+ data += 2;
+ datalen -= 2;
+ nbytes = (nbits+7) / 8;
+ if (datalen < nbytes)
+ return gpg_error (GPG_ERR_INV_PACKET);
+
+ keyparm[i].mpi = data;
+ keyparm[i].len = nbytes;
+ }
+
+ data += nbytes; datalen -= nbytes;
+ }
+ n = data - data_start;
+
+
+ /* Note: Starting here we need to jump to leave on error. */
+
+ /* Make sure the MPIs are unsigned. */
+ for (i=0; i < npkey; i++)
+ {
+ if (!keyparm[i].len || (keyparm[i].mpi[0] & 0x80))
+ {
+ helpmpibuf[i] = xtrymalloc (1+keyparm[i].len);
+ if (!helpmpibuf[i])
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ helpmpibuf[i][0] = 0;
+ memcpy (helpmpibuf[i]+1, keyparm[i].mpi, keyparm[i].len);
+ keyparm[i].mpi = helpmpibuf[i];
+ keyparm[i].len++;
+ }
+ }
+
+ err = keygrip_from_keyparm (algorithm, keyparm, ki->grip);
+ if (err)
+ goto leave;
+
+ if (version < 4)
+ {
+ /* We do not support any other algorithm than RSA in v3
+ packets. */
+ if (algorithm < 1 || algorithm > 3)
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+
+ err = gcry_md_open (&md, GCRY_MD_MD5, 0);
+ if (err)
+ return err; /* Oops */
+ gcry_md_write (md, keyparm[0].mpi, keyparm[0].len);
+ gcry_md_write (md, keyparm[1].mpi, keyparm[1].len);
+ memcpy (ki->fpr, gcry_md_read (md, 0), 16);
+ gcry_md_close (md);
+ ki->fprlen = 16;
+
+ if (keyparm[0].len < 8)
+ {
+ /* Moduli less than 64 bit are out of the specs scope. Zero
+ them out because this is what gpg does too. */
+ memset (ki->keyid, 0, 8);
+ }
+ else
+ memcpy (ki->keyid, keyparm[0].mpi + keyparm[0].len - 8, 8);
+ }
+ else
+ {
+ /* Its a pity that we need to prefix the buffer with the tag
+ and a length header: We can't simply pass it to the fast
+ hashing function for that reason. It might be a good idea to
+ have a scatter-gather enabled hash function. What we do here
+ is to use a static buffer if this one is large enough and
+ only use the regular hash functions if this buffer is not
+ large enough. */
+ if ( 3 + n < sizeof hashbuffer )
+ {
+ hashbuffer[0] = 0x99; /* CTB */
+ hashbuffer[1] = (n >> 8); /* 2 byte length header. */
+ hashbuffer[2] = n;
+ memcpy (hashbuffer + 3, data_start, n);
+ gcry_md_hash_buffer (GCRY_MD_SHA1, ki->fpr, hashbuffer, 3 + n);
+ }
+ else
+ {
+ err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
+ if (err)
+ return err; /* Oops */
+ gcry_md_putc (md, 0x99 ); /* CTB */
+ gcry_md_putc (md, (n >> 8) ); /* 2 byte length header. */
+ gcry_md_putc (md, n );
+ gcry_md_write (md, data_start, n);
+ memcpy (ki->fpr, gcry_md_read (md, 0), 20);
+ gcry_md_close (md);
+ }
+ ki->fprlen = 20;
+ memcpy (ki->keyid, ki->fpr+12, 8);
+ }
+
+ leave:
+ for (i=0; i < npkey; i++)
+ xfree (helpmpibuf[i]);
+
+ return err;
+}
+
+
+
+/* The caller must pass the address of an INFO structure which will
+ get filled on success with information pertaining to the OpenPGP
+ keyblock IMAGE of length IMAGELEN. Note that a caller does only
+ need to release this INFO structure if the function returns
+ success. If NPARSED is not NULL the actual number of bytes parsed
+ will be stored at this address. */
+gpg_error_t
+_keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
+ size_t *nparsed, keybox_openpgp_info_t info)
+{
+ gpg_error_t err = 0;
+ const unsigned char *image_start, *data;
+ size_t n, datalen;
+ int pkttype;
+ int first = 1;
+ int read_error = 0;
+ struct _keybox_openpgp_key_info *k, **ktail = NULL;
+ struct _keybox_openpgp_uid_info *u, **utail = NULL;
+
+ memset (info, 0, sizeof *info);
+ if (nparsed)
+ *nparsed = 0;
+
+ image_start = image;
+ while (image)
+ {
+ err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n);
+ if (err)
+ {
+ read_error = 1;
+ break;
+ }
+
+ if (first)
+ {
+ if (pkttype == PKT_PUBLIC_KEY)
+ ;
+ else if (pkttype == PKT_SECRET_KEY)
+ info->is_secret = 1;
+ else
+ {
+ err = gpg_error (GPG_ERR_UNEXPECTED);
+ if (nparsed)
+ *nparsed += n;
+ break;
+ }
+ first = 0;
+ }
+ else if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY)
+ break; /* Next keyblock encountered - ready. */
+
+ if (nparsed)
+ *nparsed += n;
+
+ if (pkttype == PKT_SIGNATURE)
+ {
+ /* For now we only count the total number of signatures. */
+ info->nsigs++;
+ }
+ else if (pkttype == PKT_USER_ID)
+ {
+ info->nuids++;
+ if (info->nuids == 1)
+ {
+ info->uids.off = data - image_start;
+ info->uids.len = datalen;
+ utail = &info->uids.next;
+ }
+ else
+ {
+ u = xtrycalloc (1, sizeof *u);
+ if (!u)
+ {
+ err = gpg_error_from_syserror ();
+ break;
+ }
+ u->off = data - image_start;
+ u->len = datalen;
+ *utail = u;
+ utail = &u->next;
+ }
+ }
+ else if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY)
+ {
+ err = parse_key (data, datalen, &info->primary);
+ if (err)
+ break;
+ }
+ else if( pkttype == PKT_PUBLIC_SUBKEY && datalen && *data == '#' )
+ {
+ /* Early versions of GnuPG used old PGP comment packets;
+ * luckily all those comments are prefixed by a hash
+ * sign - ignore these packets. */
+ }
+ else if (pkttype == PKT_PUBLIC_SUBKEY || pkttype == PKT_SECRET_SUBKEY)
+ {
+ info->nsubkeys++;
+ if (info->nsubkeys == 1)
+ {
+ err = parse_key (data, datalen, &info->subkeys);
+ if (err)
+ {
+ info->nsubkeys--;
+ /* We ignore subkeys with unknown algorithms. */
+ if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
+ || gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
+ err = 0;
+ if (err)
+ break;
+ }
+ else
+ ktail = &info->subkeys.next;
+ }
+ else
+ {
+ k = xtrycalloc (1, sizeof *k);
+ if (!k)
+ {
+ err = gpg_error_from_syserror ();
+ break;
+ }
+ err = parse_key (data, datalen, k);
+ if (err)
+ {
+ xfree (k);
+ info->nsubkeys--;
+ /* We ignore subkeys with unknown algorithms. */
+ if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
+ || gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
+ err = 0;
+ if (err)
+ break;
+ }
+ else
+ {
+ *ktail = k;
+ ktail = &k->next;
+ }
+ }
+ }
+ }
+
+ if (err)
+ {
+ _keybox_destroy_openpgp_info (info);
+ if (!read_error)
+ {
+ /* Packet parsing worked, thus we should be able to skip the
+ rest of the keyblock. */
+ while (image)
+ {
+ if (next_packet (&image, &imagelen,
+ &data, &datalen, &pkttype, &n) )
+ break; /* Another error - stop here. */
+
+ if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY)
+ break; /* Next keyblock encountered - ready. */
+
+ if (nparsed)
+ *nparsed += n;
+ }
+ }
+ }
+
+ return err;
+}
+
+
+/* Release any malloced data in INFO but not INFO itself! */
+void
+_keybox_destroy_openpgp_info (keybox_openpgp_info_t info)
+{
+ struct _keybox_openpgp_key_info *k, *k2;
+ struct _keybox_openpgp_uid_info *u, *u2;
+
+ assert (!info->primary.next);
+ for (k=info->subkeys.next; k; k = k2)
+ {
+ k2 = k->next;
+ xfree (k);
+ }
+
+ for (u=info->uids.next; u; u = u2)
+ {
+ u2 = u->next;
+ xfree (u);
+ }
+}
diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h
new file mode 100644
index 0000000..6298994
--- /dev/null
+++ b/kbx/keybox-search-desc.h
@@ -0,0 +1,86 @@
+/* keybox-search-desc.h - Keybox serch description
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ This file is a temporary kludge until we can come up with solution
+ to share this description between keybox and the application
+ specific keydb
+*/
+
+#ifndef KEYBOX_SEARCH_DESC_H
+#define KEYBOX_SEARCH_DESC_H 1
+
+typedef enum {
+ KEYDB_SEARCH_MODE_NONE,
+ KEYDB_SEARCH_MODE_EXACT,
+ KEYDB_SEARCH_MODE_SUBSTR,
+ KEYDB_SEARCH_MODE_MAIL,
+ KEYDB_SEARCH_MODE_MAILSUB,
+ KEYDB_SEARCH_MODE_MAILEND,
+ KEYDB_SEARCH_MODE_WORDS,
+ KEYDB_SEARCH_MODE_SHORT_KID,
+ KEYDB_SEARCH_MODE_LONG_KID,
+ KEYDB_SEARCH_MODE_FPR16,
+ KEYDB_SEARCH_MODE_FPR20,
+ KEYDB_SEARCH_MODE_FPR,
+ KEYDB_SEARCH_MODE_ISSUER,
+ KEYDB_SEARCH_MODE_ISSUER_SN,
+ KEYDB_SEARCH_MODE_SN,
+ KEYDB_SEARCH_MODE_SUBJECT,
+ KEYDB_SEARCH_MODE_KEYGRIP,
+ KEYDB_SEARCH_MODE_FIRST,
+ KEYDB_SEARCH_MODE_NEXT
+} KeydbSearchMode;
+
+
+/* Forwward declaration. See g10/packet.h. */
+struct gpg_pkt_user_id_s;
+typedef struct gpg_pkt_user_id_s *gpg_pkt_user_id_t;
+
+/* A search descriptor. */
+struct keydb_search_desc
+{
+ KeydbSearchMode mode;
+ /* Callback used to filter results. The first parameter is
+ SKIPFUNCVALUE. The second is the keyid. The third is the
+ 1-based index of the UID packet that matched the search criteria
+ (or 0, if none).
+
+ Return non-zero if the result should be skipped. */
+ int (*skipfnc)(void *, u32 *, int);
+ void *skipfncvalue;
+ const unsigned char *sn;
+ int snlen; /* -1 := sn is a hex string */
+ union {
+ const char *name;
+ unsigned char fpr[24];
+ u32 kid[2]; /* Note that this is in native endianness. */
+ unsigned char grip[20];
+ } u;
+ int exact; /* Use exactly this key ('!' suffix in gpg). */
+};
+
+
+struct keydb_search_desc;
+typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
+typedef struct keydb_search_desc KEYBOX_SEARCH_DESC;
+
+
+
+#endif /*KEYBOX_SEARCH_DESC_H*/
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
new file mode 100644
index 0000000..263a166
--- /dev/null
+++ b/kbx/keybox-search.c
@@ -0,0 +1,1322 @@
+/* keybox-search.c - Search operations
+ * Copyright (C) 2001, 2002, 2003, 2004, 2012,
+ * 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "keybox-defs.h"
+#include <gcrypt.h>
+#include "../common/host2net.h"
+#include "../common/mbox-util.h"
+
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+struct sn_array_s {
+ int snlen;
+ unsigned char *sn;
+};
+
+
+#define get32(a) buf32_to_ulong ((a))
+#define get16(a) buf16_to_ulong ((a))
+
+
+static inline unsigned int
+blob_get_blob_flags (KEYBOXBLOB blob)
+{
+ const unsigned char *buffer;
+ size_t length;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 8)
+ return 0; /* oops */
+
+ return get16 (buffer + 6);
+}
+
+
+/* Return the first keyid from the blob. Returns true if
+ available. */
+static int
+blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
+{
+ const unsigned char *buffer;
+ size_t length, nkeys, keyinfolen;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 48)
+ return 0; /* blob too short */
+
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18);
+ if (!nkeys || keyinfolen < 28)
+ return 0; /* invalid blob */
+
+ kid[0] = get32 (buffer + 32);
+ kid[1] = get32 (buffer + 36);
+
+ return 1;
+}
+
+
+/* Return information on the flag WHAT within the blob BUFFER,LENGTH.
+ Return the offset and the length (in bytes) of the flag in
+ FLAGOFF,FLAG_SIZE. */
+gpg_err_code_t
+_keybox_get_flag_location (const unsigned char *buffer, size_t length,
+ int what, size_t *flag_off, size_t *flag_size)
+{
+ size_t pos;
+ size_t nkeys, keyinfolen;
+ size_t nuids, uidinfolen;
+ size_t nserial;
+ size_t nsigs, siginfolen, siginfooff;
+
+ switch (what)
+ {
+ case KEYBOX_FLAG_BLOB:
+ if (length < 8)
+ return GPG_ERR_INV_OBJ;
+ *flag_off = 6;
+ *flag_size = 2;
+ break;
+
+ case KEYBOX_FLAG_OWNERTRUST:
+ case KEYBOX_FLAG_VALIDITY:
+ case KEYBOX_FLAG_CREATED_AT:
+ case KEYBOX_FLAG_SIG_INFO:
+ if (length < 20)
+ return GPG_ERR_INV_OBJ;
+ /* Key info. */
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return GPG_ERR_INV_OBJ;
+ pos = 20 + keyinfolen*nkeys;
+ if (pos+2 > length)
+ return GPG_ERR_INV_OBJ; /* Out of bounds. */
+ /* Serial number. */
+ nserial = get16 (buffer+pos);
+ pos += 2 + nserial;
+ if (pos+4 > length)
+ return GPG_ERR_INV_OBJ; /* Out of bounds. */
+ /* User IDs. */
+ nuids = get16 (buffer + pos); pos += 2;
+ uidinfolen = get16 (buffer + pos); pos += 2;
+ if (uidinfolen < 12 )
+ return GPG_ERR_INV_OBJ;
+ pos += uidinfolen*nuids;
+ if (pos+4 > length)
+ return GPG_ERR_INV_OBJ ; /* Out of bounds. */
+ /* Signature info. */
+ siginfooff = pos;
+ nsigs = get16 (buffer + pos); pos += 2;
+ siginfolen = get16 (buffer + pos); pos += 2;
+ if (siginfolen < 4 )
+ return GPG_ERR_INV_OBJ;
+ pos += siginfolen*nsigs;
+ if (pos+1+1+2+4+4+4+4 > length)
+ return GPG_ERR_INV_OBJ ; /* Out of bounds. */
+ *flag_size = 1;
+ *flag_off = pos;
+ switch (what)
+ {
+ case KEYBOX_FLAG_VALIDITY:
+ *flag_off += 1;
+ break;
+ case KEYBOX_FLAG_CREATED_AT:
+ *flag_size = 4;
+ *flag_off += 1+2+4+4+4;
+ break;
+ case KEYBOX_FLAG_SIG_INFO:
+ *flag_size = siginfolen * nsigs;
+ *flag_off = siginfooff;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ return GPG_ERR_INV_FLAG;
+ }
+ return 0;
+}
+
+
+
+/* Return one of the flags WHAT in VALUE from the blob BUFFER of
+ LENGTH bytes. Return 0 on success or an raw error code. */
+static gpg_err_code_t
+get_flag_from_image (const unsigned char *buffer, size_t length,
+ int what, unsigned int *value)
+{
+ gpg_err_code_t ec;
+ size_t pos, size;
+
+ *value = 0;
+ ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
+ if (!ec)
+ switch (size)
+ {
+ case 1: *value = buffer[pos]; break;
+ case 2: *value = get16 (buffer + pos); break;
+ case 4: *value = get32 (buffer + pos); break;
+ default: ec = GPG_ERR_BUG; break;
+ }
+
+ return ec;
+}
+
+
+static int
+blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos, off;
+ size_t nkeys, keyinfolen;
+ size_t nserial;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return 0; /* invalid blob */
+ pos = 20 + keyinfolen*nkeys;
+ if (pos+2 > length)
+ return 0; /* out of bounds */
+
+ /*serial*/
+ nserial = get16 (buffer+pos);
+ off = pos + 2;
+ if (off+nserial > length)
+ return 0; /* out of bounds */
+
+ return nserial == snlen && !memcmp (buffer+off, sn, snlen);
+}
+
+
+/* Returns 0 if not found or the number of the key which was found.
+ For X.509 this is always 1, for OpenPGP this is 1 for the primary
+ key and 2 and more for the subkeys. */
+static int
+blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos, off;
+ size_t nkeys, keyinfolen;
+ int idx;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return 0; /* invalid blob */
+ pos = 20;
+ if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
+ return 0; /* out of bounds */
+
+ for (idx=0; idx < nkeys; idx++)
+ {
+ off = pos + idx*keyinfolen;
+ if (!memcmp (buffer + off, fpr, 20))
+ return idx+1; /* found */
+ }
+ return 0; /* not found */
+}
+
+static int
+blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
+ int fproff, int fprlen)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos, off;
+ size_t nkeys, keyinfolen;
+ int idx;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return 0; /* invalid blob */
+ pos = 20;
+ if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
+ return 0; /* out of bounds */
+
+ for (idx=0; idx < nkeys; idx++)
+ {
+ off = pos + idx*keyinfolen;
+ if (!memcmp (buffer + off + fproff, fpr, fprlen))
+ return idx+1; /* found */
+ }
+ return 0; /* not found */
+}
+
+
+static int
+blob_cmp_name (KEYBOXBLOB blob, int idx,
+ const char *name, size_t namelen, int substr, int x509)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos, off, len;
+ size_t nkeys, keyinfolen;
+ size_t nuids, uidinfolen;
+ size_t nserial;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return 0; /* invalid blob */
+ pos = 20 + keyinfolen*nkeys;
+ if ((uint64_t)pos+2 > (uint64_t)length)
+ return 0; /* out of bounds */
+
+ /*serial*/
+ nserial = get16 (buffer+pos);
+ pos += 2 + nserial;
+ if (pos+4 > length)
+ return 0; /* out of bounds */
+
+ /* user ids*/
+ nuids = get16 (buffer + pos); pos += 2;
+ uidinfolen = get16 (buffer + pos); pos += 2;
+ if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
+ return 0; /* invalid blob */
+ if (pos + uidinfolen*nuids > length)
+ return 0; /* out of bounds */
+
+ if (idx < 0)
+ { /* Compare all names. Note that for X.509 we start with index 1
+ so to skip the issuer at index 0. */
+ for (idx = !!x509; idx < nuids; idx++)
+ {
+ size_t mypos = pos;
+
+ mypos += idx*uidinfolen;
+ off = get32 (buffer+mypos);
+ len = get32 (buffer+mypos+4);
+ if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
+ return 0; /* error: better stop here out of bounds */
+ if (len < 1)
+ continue; /* empty name */
+ if (substr)
+ {
+ if (ascii_memcasemem (buffer+off, len, name, namelen))
+ return idx+1; /* found */
+ }
+ else
+ {
+ if (len == namelen && !memcmp (buffer+off, name, len))
+ return idx+1; /* found */
+ }
+ }
+ }
+ else
+ {
+ if (idx > nuids)
+ return 0; /* no user ID with that idx */
+ pos += idx*uidinfolen;
+ off = get32 (buffer+pos);
+ len = get32 (buffer+pos+4);
+ if (off+len > length)
+ return 0; /* out of bounds */
+ if (len < 1)
+ return 0; /* empty name */
+
+ if (substr)
+ {
+ if (ascii_memcasemem (buffer+off, len, name, namelen))
+ return idx+1; /* found */
+ }
+ else
+ {
+ if (len == namelen && !memcmp (buffer+off, name, len))
+ return idx+1; /* found */
+ }
+ }
+ return 0; /* not found */
+}
+
+
+/* Compare all email addresses of the subject. With SUBSTR given as
+ True a substring search is done in the mail address. The X509 flag
+ indicated whether the search is done on an X.509 blob. */
+static int
+blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
+ int x509)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos, off, len;
+ size_t nkeys, keyinfolen;
+ size_t nuids, uidinfolen;
+ size_t nserial;
+ int idx;
+
+ /* fixme: this code is common to blob_cmp_mail */
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (keyinfolen < 28)
+ return 0; /* invalid blob */
+ pos = 20 + keyinfolen*nkeys;
+ if (pos+2 > length)
+ return 0; /* out of bounds */
+
+ /*serial*/
+ nserial = get16 (buffer+pos);
+ pos += 2 + nserial;
+ if (pos+4 > length)
+ return 0; /* out of bounds */
+
+ /* user ids*/
+ nuids = get16 (buffer + pos); pos += 2;
+ uidinfolen = get16 (buffer + pos); pos += 2;
+ if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
+ return 0; /* invalid blob */
+ if (pos + uidinfolen*nuids > length)
+ return 0; /* out of bounds */
+
+ if (namelen < 1)
+ return 0;
+
+ /* Note that for X.509 we start at index 1 because index 0 is used
+ for the issuer name. */
+ for (idx=!!x509 ;idx < nuids; idx++)
+ {
+ size_t mypos = pos;
+ size_t mylen;
+
+ mypos += idx*uidinfolen;
+ off = get32 (buffer+mypos);
+ len = get32 (buffer+mypos+4);
+ if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
+ return 0; /* error: better stop here - out of bounds */
+ if (x509)
+ {
+ if (len < 2 || buffer[off] != '<')
+ continue; /* empty name or trailing 0 not stored */
+ len--; /* one back */
+ if ( len < 3 || buffer[off+len] != '>')
+ continue; /* not a proper email address */
+ off++;
+ len--;
+ }
+ else /* OpenPGP. */
+ {
+ /* We need to forward to the mailbox part. */
+ mypos = off;
+ mylen = len;
+ for ( ; len && buffer[off] != '<'; len--, off++)
+ ;
+ if (len < 2 || buffer[off] != '<')
+ {
+ /* Mailbox not explicitly given or too short. Restore
+ OFF and LEN and check whether the entire string
+ resembles a mailbox without the angle brackets. */
+ off = mypos;
+ len = mylen;
+ if (!is_valid_mailbox_mem (buffer+off, len))
+ continue; /* Not a mail address. */
+ }
+ else /* Seems to be standard user id with mail address. */
+ {
+ off++; /* Point to first char of the mail address. */
+ len--;
+ /* Search closing '>'. */
+ for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
+ ;
+ if (!len || buffer[mypos] != '>' || off == mypos)
+ continue; /* Not a proper mail address. */
+ len = mypos - off;
+ }
+
+ }
+
+ if (substr)
+ {
+ if (ascii_memcasemem (buffer+off, len, name, namelen))
+ return idx+1; /* found */
+ }
+ else
+ {
+ if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
+ return idx+1; /* found */
+ }
+ }
+ return 0; /* not found */
+}
+
+
+/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
+ * We don't have the keygrips as meta data, thus we need to parse the
+ * certificate. Fixme: We might want to return proper error codes
+ * instead of failing a search for invalid certificates etc. */
+static int
+blob_openpgp_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
+{
+ int rc = 0;
+ const unsigned char *buffer;
+ size_t length;
+ size_t cert_off, cert_len;
+ struct _keybox_openpgp_info info;
+ struct _keybox_openpgp_key_info *k;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* Too short. */
+ cert_off = get32 (buffer+8);
+ cert_len = get32 (buffer+12);
+ if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
+ return 0; /* Too short. */
+
+ if (_keybox_parse_openpgp (buffer + cert_off, cert_len, NULL, &info))
+ return 0; /* Parse error. */
+
+ if (!memcmp (info.primary.grip, grip, 20))
+ {
+ rc = 1;
+ goto leave;
+ }
+
+ if (info.nsubkeys)
+ {
+ k = &info.subkeys;
+ do
+ {
+ if (!memcmp (k->grip, grip, 20))
+ {
+ rc = 1;
+ goto leave;
+ }
+ k = k->next;
+ }
+ while (k);
+ }
+
+ leave:
+ _keybox_destroy_openpgp_info (&info);
+ return rc;
+}
+
+
+#ifdef KEYBOX_WITH_X509
+/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
+ We don't have the keygrips as meta data, thus we need to parse the
+ certificate. Fixme: We might want to return proper error codes
+ instead of failing a search for invalid certificates etc. */
+static int
+blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
+{
+ int rc;
+ const unsigned char *buffer;
+ size_t length;
+ size_t cert_off, cert_len;
+ ksba_reader_t reader = NULL;
+ ksba_cert_t cert = NULL;
+ ksba_sexp_t p = NULL;
+ gcry_sexp_t s_pkey;
+ unsigned char array[20];
+ unsigned char *rcp;
+ size_t n;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* Too short. */
+ cert_off = get32 (buffer+8);
+ cert_len = get32 (buffer+12);
+ if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
+ return 0; /* Too short. */
+
+ rc = ksba_reader_new (&reader);
+ if (rc)
+ return 0; /* Problem with ksba. */
+ rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
+ if (rc)
+ goto failed;
+ rc = ksba_cert_new (&cert);
+ if (rc)
+ goto failed;
+ rc = ksba_cert_read_der (cert, reader);
+ if (rc)
+ goto failed;
+ p = ksba_cert_get_public_key (cert);
+ if (!p)
+ goto failed;
+ n = gcry_sexp_canon_len (p, 0, NULL, NULL);
+ if (!n)
+ goto failed;
+ rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
+ if (rc)
+ {
+ gcry_sexp_release (s_pkey);
+ goto failed;
+ }
+ rcp = gcry_pk_get_keygrip (s_pkey, array);
+ gcry_sexp_release (s_pkey);
+ if (!rcp)
+ goto failed; /* Can't calculate keygrip. */
+
+ xfree (p);
+ ksba_cert_release (cert);
+ ksba_reader_release (reader);
+ return !memcmp (array, grip, 20);
+ failed:
+ xfree (p);
+ ksba_cert_release (cert);
+ ksba_reader_release (reader);
+ return 0;
+}
+#endif /*KEYBOX_WITH_X509*/
+
+
+
+/*
+ The has_foo functions are used as helpers for search
+*/
+static inline int
+has_short_kid (KEYBOXBLOB blob, u32 lkid)
+{
+ unsigned char buf[4];
+ buf[0] = lkid >> 24;
+ buf[1] = lkid >> 16;
+ buf[2] = lkid >> 8;
+ buf[3] = lkid;
+ return blob_cmp_fpr_part (blob, buf, 16, 4);
+}
+
+static inline int
+has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
+{
+ unsigned char buf[8];
+ buf[0] = mkid >> 24;
+ buf[1] = mkid >> 16;
+ buf[2] = mkid >> 8;
+ buf[3] = mkid;
+ buf[4] = lkid >> 24;
+ buf[5] = lkid >> 16;
+ buf[6] = lkid >> 8;
+ buf[7] = lkid;
+ return blob_cmp_fpr_part (blob, buf, 12, 8);
+}
+
+static inline int
+has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
+{
+ return blob_cmp_fpr (blob, fpr);
+}
+
+static inline int
+has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
+{
+ if (blob_get_type (blob) == KEYBOX_BLOBTYPE_PGP)
+ return blob_openpgp_has_grip (blob, grip);
+#ifdef KEYBOX_WITH_X509
+ if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
+ return blob_x509_has_grip (blob, grip);
+#endif
+ return 0;
+}
+
+
+static inline int
+has_issuer (KEYBOXBLOB blob, const char *name)
+{
+ size_t namelen;
+
+ return_val_if_fail (name, 0);
+
+ if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
+ return 0;
+
+ namelen = strlen (name);
+ return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
+}
+
+static inline int
+has_issuer_sn (KEYBOXBLOB blob, const char *name,
+ const unsigned char *sn, int snlen)
+{
+ size_t namelen;
+
+ return_val_if_fail (name, 0);
+ return_val_if_fail (sn, 0);
+
+ if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
+ return 0;
+
+ namelen = strlen (name);
+
+ return (blob_cmp_sn (blob, sn, snlen)
+ && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
+}
+
+static inline int
+has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
+{
+ return_val_if_fail (sn, 0);
+
+ if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
+ return 0;
+ return blob_cmp_sn (blob, sn, snlen);
+}
+
+static inline int
+has_subject (KEYBOXBLOB blob, const char *name)
+{
+ size_t namelen;
+
+ return_val_if_fail (name, 0);
+
+ if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
+ return 0;
+
+ namelen = strlen (name);
+ return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
+}
+
+
+static inline int
+has_username (KEYBOXBLOB blob, const char *name, int substr)
+{
+ size_t namelen;
+ int btype;
+
+ return_val_if_fail (name, 0);
+
+ btype = blob_get_type (blob);
+ if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
+ return 0;
+
+ namelen = strlen (name);
+ return blob_cmp_name (blob, -1 /* all subject/user names */, name,
+ namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
+}
+
+
+static inline int
+has_mail (KEYBOXBLOB blob, const char *name, int substr)
+{
+ size_t namelen;
+ int btype;
+
+ return_val_if_fail (name, 0);
+
+ btype = blob_get_type (blob);
+ if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
+ return 0;
+
+ if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
+ name++; /* Hack to remove the leading '<' for gpg. */
+
+ namelen = strlen (name);
+ if (namelen && name[namelen-1] == '>')
+ namelen--;
+ return blob_cmp_mail (blob, name, namelen, substr,
+ (btype == KEYBOX_BLOBTYPE_X509));
+}
+
+
+static void
+release_sn_array (struct sn_array_s *array, size_t size)
+{
+ size_t n;
+
+ for (n=0; n < size; n++)
+ xfree (array[n].sn);
+ xfree (array);
+}
+
+
+/* Helper to open the file. */
+static gpg_error_t
+open_file (KEYBOX_HANDLE hd)
+{
+
+ hd->fp = es_fopen (hd->kb->fname, "rb");
+ if (!hd->fp)
+ {
+ hd->error = gpg_error_from_syserror ();
+ return hd->error;
+ }
+
+ return 0;
+}
+
+
+
+/*
+
+ The search API
+
+*/
+
+gpg_error_t
+keybox_search_reset (KEYBOX_HANDLE hd)
+{
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (hd->found.blob)
+ {
+ _keybox_release_blob (hd->found.blob);
+ hd->found.blob = NULL;
+ }
+
+ if (hd->fp)
+ {
+#if HAVE_W32_SYSTEM
+ es_fclose (hd->fp);
+ hd->fp = NULL;
+#else
+ if (es_fseeko (hd->fp, 0, SEEK_SET))
+ {
+ /* Ooops. Seek did not work. Close so that the search will
+ * open the file again. */
+ es_fclose (hd->fp);
+ hd->fp = NULL;
+ }
+#endif
+ }
+ hd->error = 0;
+ hd->eof = 0;
+ return 0;
+}
+
+
+/* Note: When in ephemeral mode the search function does visit all
+ blobs but in standard mode, blobs flagged as ephemeral are ignored.
+ If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
+ The value at R_SKIPPED is updated by the number of skipped long
+ records (counts PGP and X.509). */
+gpg_error_t
+keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
+ keybox_blobtype_t want_blobtype,
+ size_t *r_descindex, unsigned long *r_skipped)
+{
+ gpg_error_t rc;
+ size_t n;
+ int need_words, any_skip;
+ KEYBOXBLOB blob = NULL;
+ struct sn_array_s *sn_array = NULL;
+ int pk_no, uid_no;
+ off_t lastfoundoff;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* Clear last found result but reord the offset of the last found
+ * blob which we may need later. */
+ if (hd->found.blob)
+ {
+ lastfoundoff = _keybox_get_blob_fileoffset (hd->found.blob);
+ _keybox_release_blob (hd->found.blob);
+ hd->found.blob = NULL;
+ }
+ else
+ lastfoundoff = 0;
+
+ if (hd->error)
+ return hd->error; /* still in error state */
+ if (hd->eof)
+ return -1; /* still EOF */
+
+ /* figure out what information we need */
+ need_words = any_skip = 0;
+ for (n=0; n < ndesc; n++)
+ {
+ switch (desc[n].mode)
+ {
+ case KEYDB_SEARCH_MODE_WORDS:
+ need_words = 1;
+ break;
+ case KEYDB_SEARCH_MODE_FIRST:
+ /* always restart the search in this mode */
+ keybox_search_reset (hd);
+ lastfoundoff = 0;
+ break;
+ default:
+ break;
+ }
+ if (desc[n].skipfnc)
+ any_skip = 1;
+ if (desc[n].snlen == -1 && !sn_array)
+ {
+ sn_array = xtrycalloc (ndesc, sizeof *sn_array);
+ if (!sn_array)
+ return (hd->error = gpg_error_from_syserror ());
+ }
+ }
+
+ (void)need_words; /* Not yet implemented. */
+
+ if (!hd->fp)
+ {
+ rc = open_file (hd);
+ if (rc)
+ {
+ xfree (sn_array);
+ return rc;
+ }
+ /* log_debug ("%s: re-opened file\n", __func__); */
+ if (ndesc && desc[0].mode != KEYDB_SEARCH_MODE_FIRST && lastfoundoff)
+ {
+ /* Search mode is not first and the last search operation
+ * returned a blob which also was not the first one. We now
+ * need to skip over that blob and hope that the file has
+ * not changed. */
+ if (es_fseeko (hd->fp, lastfoundoff, SEEK_SET))
+ {
+ rc = gpg_error_from_syserror ();
+ log_debug ("%s: seeking to last found offset failed: %s\n",
+ __func__, gpg_strerror (rc));
+ xfree (sn_array);
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ }
+ /* log_debug ("%s: re-opened file and sought to last offset\n", */
+ /* __func__); */
+ rc = _keybox_read_blob (NULL, hd->fp, NULL);
+ if (rc)
+ {
+ log_debug ("%s: skipping last found blob failed: %s\n",
+ __func__, gpg_strerror (rc));
+ xfree (sn_array);
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ }
+ }
+ }
+
+ /* Kludge: We need to convert an SN given as hexstring to its binary
+ representation - in some cases we are not able to store it in the
+ search descriptor, because due to the way we use it, it is not
+ possible to free allocated memory. */
+ if (sn_array)
+ {
+ const unsigned char *s;
+ int i, odd;
+ size_t snlen;
+
+ for (n=0; n < ndesc; n++)
+ {
+ if (!desc[n].sn)
+ ;
+ else if (desc[n].snlen == -1)
+ {
+ unsigned char *sn;
+
+ s = desc[n].sn;
+ for (i=0; *s && *s != '/'; s++, i++)
+ ;
+ odd = (i & 1);
+ snlen = (i+1)/2;
+ sn_array[n].sn = xtrymalloc (snlen);
+ if (!sn_array[n].sn)
+ {
+ hd->error = gpg_error_from_syserror ();
+ release_sn_array (sn_array, n);
+ return hd->error;
+ }
+ sn_array[n].snlen = snlen;
+ sn = sn_array[n].sn;
+ s = desc[n].sn;
+ if (odd)
+ {
+ *sn++ = xtoi_1 (s);
+ s++;
+ }
+ for (; *s && *s != '/'; s += 2)
+ *sn++ = xtoi_2 (s);
+ }
+ else
+ {
+ const unsigned char *sn;
+
+ sn = desc[n].sn;
+ snlen = desc[n].snlen;
+ sn_array[n].sn = xtrymalloc (snlen);
+ if (!sn_array[n].sn)
+ {
+ hd->error = gpg_error_from_syserror ();
+ release_sn_array (sn_array, n);
+ return hd->error;
+ }
+ sn_array[n].snlen = snlen;
+ memcpy (sn_array[n].sn, sn, snlen);
+ }
+ }
+ }
+
+
+ pk_no = uid_no = 0;
+ for (;;)
+ {
+ unsigned int blobflags;
+ int blobtype;
+
+ _keybox_release_blob (blob); blob = NULL;
+ rc = _keybox_read_blob (&blob, hd->fp, NULL);
+ if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
+ && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
+ {
+ ++*r_skipped;
+ continue; /* Skip too large records. */
+ }
+
+ if (rc)
+ break;
+
+ blobtype = blob_get_type (blob);
+ if (blobtype == KEYBOX_BLOBTYPE_HEADER)
+ continue;
+ if (want_blobtype && blobtype != want_blobtype)
+ continue;
+
+ blobflags = blob_get_blob_flags (blob);
+ if (!hd->ephemeral && (blobflags & 2))
+ continue; /* Not in ephemeral mode but blob is flagged ephemeral. */
+
+ for (n=0; n < ndesc; n++)
+ {
+ switch (desc[n].mode)
+ {
+ case KEYDB_SEARCH_MODE_NONE:
+ never_reached ();
+ break;
+ case KEYDB_SEARCH_MODE_EXACT:
+ uid_no = has_username (blob, desc[n].u.name, 0);
+ if (uid_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_MAIL:
+ uid_no = has_mail (blob, desc[n].u.name, 0);
+ if (uid_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_MAILSUB:
+ uid_no = has_mail (blob, desc[n].u.name, 1);
+ if (uid_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_SUBSTR:
+ uid_no = has_username (blob, desc[n].u.name, 1);
+ if (uid_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_MAILEND:
+ case KEYDB_SEARCH_MODE_WORDS:
+ /* not yet implemented */
+ break;
+ case KEYDB_SEARCH_MODE_ISSUER:
+ if (has_issuer (blob, desc[n].u.name))
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_ISSUER_SN:
+ if (has_issuer_sn (blob, desc[n].u.name,
+ sn_array? sn_array[n].sn : desc[n].sn,
+ sn_array? sn_array[n].snlen : desc[n].snlen))
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_SN:
+ if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
+ sn_array? sn_array[n].snlen : desc[n].snlen))
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_SUBJECT:
+ if (has_subject (blob, desc[n].u.name))
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_SHORT_KID:
+ pk_no = has_short_kid (blob, desc[n].u.kid[1]);
+ if (pk_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_LONG_KID:
+ pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
+ if (pk_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_FPR:
+ case KEYDB_SEARCH_MODE_FPR20:
+ pk_no = has_fingerprint (blob, desc[n].u.fpr);
+ if (pk_no)
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_KEYGRIP:
+ if (has_keygrip (blob, desc[n].u.grip))
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_FIRST:
+ goto found;
+ break;
+ case KEYDB_SEARCH_MODE_NEXT:
+ goto found;
+ break;
+ default:
+ rc = gpg_error (GPG_ERR_INV_VALUE);
+ goto found;
+ }
+ }
+ continue;
+ found:
+ /* Record which DESC we matched on. Note this value is only
+ meaningful if this function returns with no errors. */
+ if(r_descindex)
+ *r_descindex = n;
+ for (n=any_skip?0:ndesc; n < ndesc; n++)
+ {
+ u32 kid[2];
+
+ if (desc[n].skipfnc
+ && blob_get_first_keyid (blob, kid)
+ && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
+ break;
+ }
+ if (n == ndesc)
+ break; /* got it */
+ }
+
+ if (!rc)
+ {
+ hd->found.blob = blob;
+ hd->found.pk_no = pk_no;
+ hd->found.uid_no = uid_no;
+ }
+ else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
+ {
+ _keybox_release_blob (blob);
+ hd->eof = 1;
+ }
+ else
+ {
+ _keybox_release_blob (blob);
+ hd->error = rc;
+ }
+
+ if (sn_array)
+ release_sn_array (sn_array, ndesc);
+
+ return rc;
+}
+
+
+
+
+/*
+ Functions to return a certificate or a keyblock. To be used after
+ a successful search operation.
+*/
+
+
+/* Return the last found keyblock. Returns 0 on success and stores a
+ * new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to retun the
+ * number of the key or user id which was matched the search criteria;
+ * if not known they are set to 0. */
+gpg_error_t
+keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
+ int *r_pk_no, int *r_uid_no)
+{
+ gpg_error_t err;
+ const unsigned char *buffer;
+ size_t length;
+ size_t image_off, image_len;
+ size_t siginfo_off, siginfo_len;
+
+ *r_iobuf = NULL;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+
+ if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
+ return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
+
+ buffer = _keybox_get_blob_image (hd->found.blob, &length);
+ if (length < 40)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+ image_off = get32 (buffer+8);
+ image_len = get32 (buffer+12);
+ if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+
+ err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
+ &siginfo_off, &siginfo_len);
+ if (err)
+ return err;
+
+ *r_pk_no = hd->found.pk_no;
+ *r_uid_no = hd->found.uid_no;
+ *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
+ return 0;
+}
+
+
+#ifdef KEYBOX_WITH_X509
+/*
+ Return the last found cert. Caller must free it.
+ */
+int
+keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t cert_off, cert_len;
+ ksba_reader_t reader = NULL;
+ ksba_cert_t cert = NULL;
+ int rc;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+
+ if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
+ return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
+
+ buffer = _keybox_get_blob_image (hd->found.blob, &length);
+ if (length < 40)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+ cert_off = get32 (buffer+8);
+ cert_len = get32 (buffer+12);
+ if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+
+ rc = ksba_reader_new (&reader);
+ if (rc)
+ return rc;
+ rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
+ if (rc)
+ {
+ ksba_reader_release (reader);
+ /* fixme: need to map the error codes */
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+
+ rc = ksba_cert_new (&cert);
+ if (rc)
+ {
+ ksba_reader_release (reader);
+ return rc;
+ }
+
+ rc = ksba_cert_read_der (cert, reader);
+ if (rc)
+ {
+ ksba_cert_release (cert);
+ ksba_reader_release (reader);
+ /* fixme: need to map the error codes */
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+
+ *r_cert = cert;
+ ksba_reader_release (reader);
+ return 0;
+}
+
+#endif /*KEYBOX_WITH_X509*/
+
+/* Return the flags named WHAT at the address of VALUE. IDX is used
+ only for certain flags and should be 0 if not required. */
+int
+keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
+{
+ const unsigned char *buffer;
+ size_t length;
+ gpg_err_code_t ec;
+
+ (void)idx; /* Not yet used. */
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+
+ buffer = _keybox_get_blob_image (hd->found.blob, &length);
+ ec = get_flag_from_image (buffer, length, what, value);
+ return ec? gpg_error (ec):0;
+}
+
+off_t
+keybox_offset (KEYBOX_HANDLE hd)
+{
+ if (!hd->fp)
+ return 0;
+ return es_ftello (hd->fp);
+}
+
+gpg_error_t
+keybox_seek (KEYBOX_HANDLE hd, off_t offset)
+{
+ gpg_error_t err;
+
+ if (hd->error)
+ return hd->error; /* still in error state */
+
+ if (! hd->fp)
+ {
+ if (!offset)
+ {
+ /* No need to open the file. An unopened file is effectively at
+ offset 0. */
+ return 0;
+ }
+
+ err = open_file (hd);
+ if (err)
+ return err;
+ }
+
+ err = es_fseeko (hd->fp, offset, SEEK_SET);
+ hd->error = gpg_error_from_errno (err);
+
+ return hd->error;
+}
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c
new file mode 100644
index 0000000..6e45f3d
--- /dev/null
+++ b/kbx/keybox-update.c
@@ -0,0 +1,788 @@
+/* keybox-update.c - keybox update operations
+ * Copyright (C) 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "keybox-defs.h"
+#include "../common/sysutils.h"
+#include "../common/host2net.h"
+#include "../common/utilproto.h"
+
+#define EXTSEP_S "."
+
+#define FILECOPY_INSERT 1
+#define FILECOPY_DELETE 2
+#define FILECOPY_UPDATE 3
+
+
+#if !defined(HAVE_FSEEKO) && !defined(fseeko)
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef LONG_MAX
+# define LONG_MAX ((long) ((unsigned long) -1 >> 1))
+#endif
+#ifndef LONG_MIN
+# define LONG_MIN (-1 - LONG_MAX)
+#endif
+
+/****************
+ * A substitute for fseeko, for hosts that don't have it.
+ */
+static int
+fseeko (FILE * stream, off_t newpos, int whence)
+{
+ while (newpos != (long) newpos)
+ {
+ long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
+ if (fseek (stream, pos, whence) != 0)
+ return -1;
+ newpos -= pos;
+ whence = SEEK_CUR;
+ }
+ return fseek (stream, (long) newpos, whence);
+}
+#endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
+
+
+static int
+create_tmp_file (const char *template,
+ char **r_bakfname, char **r_tmpfname, estream_t *r_fp)
+{
+ gpg_error_t err;
+
+ err = keybox_tmp_names (template, 0, r_bakfname, r_tmpfname);
+ if (!err)
+ {
+ *r_fp = es_fopen (*r_tmpfname, "wb");
+ if (!*r_fp)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (*r_tmpfname);
+ *r_tmpfname = NULL;
+ xfree (*r_bakfname);
+ *r_bakfname = NULL;
+ }
+ }
+
+ return err;
+}
+
+
+static int
+rename_tmp_file (const char *bakfname, const char *tmpfname,
+ const char *fname, int secret )
+{
+ int rc=0;
+ int block = 0;
+
+ /* restrict the permissions for secret keyboxs */
+#ifndef HAVE_DOSISH_SYSTEM
+/* if (secret && !opt.preserve_permissions) */
+/* { */
+/* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */
+/* { */
+/* log_debug ("chmod of '%s' failed: %s\n", */
+/* tmpfname, strerror(errno) ); */
+/* return KEYBOX_Write_File; */
+/* } */
+/* } */
+#endif
+
+ /* fixme: invalidate close caches (not used with stdio)*/
+/* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ); */
+/* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname ); */
+/* iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname ); */
+
+ /* First make a backup file except for secret keyboxes. */
+ if (!secret)
+ {
+ block = 1;
+ rc = gnupg_rename_file (fname, bakfname, &block);
+ if (rc)
+ goto leave;
+ }
+
+ /* Then rename the file. */
+ rc = gnupg_rename_file (tmpfname, fname, NULL);
+ if (block)
+ {
+ gnupg_unblock_all_signals ();
+ block = 0;
+ }
+ /* if (rc) */
+ /* { */
+ /* if (secret) */
+ /* { */
+ /* log_info ("WARNING: 2 files with confidential" */
+ /* " information exists.\n"); */
+ /* log_info ("%s is the unchanged one\n", fname ); */
+ /* log_info ("%s is the new one\n", tmpfname ); */
+ /* log_info ("Please fix this possible security flaw\n"); */
+ /* } */
+ /* } */
+
+ leave:
+ if (block)
+ gnupg_unblock_all_signals ();
+ return rc;
+}
+
+
+
+/* Perform insert/delete/update operation. MODE is one of
+ FILECOPY_INSERT, FILECOPY_DELETE, FILECOPY_UPDATE. FOR_OPENPGP
+ indicates that this is called due to an OpenPGP keyblock change. */
+static int
+blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
+ int secret, int for_openpgp, off_t start_offset)
+{
+ gpg_err_code_t ec;
+ estream_t fp, newfp;
+ int rc = 0;
+ char *bakfname = NULL;
+ char *tmpfname = NULL;
+ char buffer[4096]; /* (Must be at least 32 bytes) */
+ int nread, nbytes;
+
+ /* Open the source file. Because we do a rename, we have to check the
+ permissions of the file */
+ if ((ec = gnupg_access (fname, W_OK)))
+ return gpg_error (ec);
+
+ fp = es_fopen (fname, "rb");
+ if (mode == FILECOPY_INSERT && !fp && errno == ENOENT)
+ {
+ /* Insert mode but file does not exist:
+ Create a new keybox file. */
+ newfp = es_fopen (fname, "wb");
+ if (!newfp )
+ return gpg_error_from_syserror ();
+
+ rc = _keybox_write_header_blob (newfp, for_openpgp);
+ if (rc)
+ {
+ es_fclose (newfp);
+ return rc;
+ }
+
+ rc = _keybox_write_blob (blob, newfp, NULL);
+ if (rc)
+ {
+ es_fclose (newfp);
+ return rc;
+ }
+
+ if ( es_fclose (newfp) )
+ return gpg_error_from_syserror ();
+
+/* if (chmod( fname, S_IRUSR | S_IWUSR )) */
+/* { */
+/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */
+/* return KEYBOX_File_Error; */
+/* } */
+ return 0; /* Ready. */
+ }
+
+ if (!fp)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ /* Create the new file. On success NEWFP is initialized. */
+ rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
+ if (rc)
+ {
+ es_fclose (fp);
+ goto leave;
+ }
+
+ /* prepare for insert */
+ if (mode == FILECOPY_INSERT)
+ {
+ int first_record = 1;
+
+ /* Copy everything to the new file. If this is for OpenPGP, we
+ make sure that the openpgp flag is set in the header. (We
+ failsafe the blob type.) */
+ while ( (nread = es_fread (buffer, 1, DIM(buffer), fp)) > 0 )
+ {
+ if (first_record && for_openpgp
+ && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+ {
+ first_record = 0;
+ buffer[7] |= 0x02; /* OpenPGP data may be available. */
+ }
+
+ if (es_fwrite (buffer, nread, 1, newfp) != 1)
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+ }
+ if (es_ferror (fp))
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+ }
+
+ /* Prepare for delete or update. */
+ if ( mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE )
+ {
+ off_t current = 0;
+
+ /* Copy first part to the new file. */
+ while ( current < start_offset )
+ {
+ nbytes = DIM(buffer);
+ if (current + nbytes > start_offset)
+ nbytes = start_offset - current;
+ nread = es_fread (buffer, 1, nbytes, fp);
+ if (!nread)
+ break;
+ current += nread;
+
+ if (es_fwrite (buffer, nread, 1, newfp) != 1)
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+ }
+ if (es_ferror (fp))
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+
+ /* Skip this blob. */
+ rc = _keybox_read_blob (NULL, fp, NULL);
+ if (rc)
+ {
+ es_fclose (fp);
+ es_fclose (newfp);
+ return rc;
+ }
+ }
+
+ /* Do an insert or update. */
+ if ( mode == FILECOPY_INSERT || mode == FILECOPY_UPDATE )
+ {
+ rc = _keybox_write_blob (blob, newfp, NULL);
+ if (rc)
+ {
+ es_fclose (fp);
+ es_fclose (newfp);
+ return rc;
+ }
+ }
+
+ /* Copy the rest of the packet for an delete or update. */
+ if (mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE)
+ {
+ while ( (nread = es_fread (buffer, 1, DIM(buffer), fp)) > 0 )
+ {
+ if (es_fwrite (buffer, nread, 1, newfp) != 1)
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+ }
+ if (es_ferror (fp))
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (fp);
+ es_fclose (newfp);
+ goto leave;
+ }
+ }
+
+ /* Close both files. */
+ if (es_fclose(fp))
+ {
+ rc = gpg_error_from_syserror ();
+ es_fclose (newfp);
+ goto leave;
+ }
+ if (es_fclose(newfp))
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
+
+ leave:
+ xfree(bakfname);
+ xfree(tmpfname);
+ return rc;
+}
+
+
+/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD. */
+gpg_error_t
+keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
+{
+ gpg_error_t err;
+ const char *fname;
+ KEYBOXBLOB blob;
+ size_t nparsed;
+ struct _keybox_openpgp_info info;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ if (!hd->kb)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+
+ /* Close this one otherwise we will mess up the position for a next
+ search. Fixme: it would be better to adjust the position after
+ the write operation. */
+ _keybox_close_file (hd);
+
+ err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
+ if (err)
+ return err;
+ assert (nparsed <= imagelen);
+ err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
+ hd->ephemeral);
+ _keybox_destroy_openpgp_info (&info);
+ if (!err)
+ {
+ err = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 1, 0);
+ _keybox_release_blob (blob);
+ /* if (!rc && !hd->secret && kb_offtbl) */
+ /* { */
+ /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
+ /* } */
+ }
+ return err;
+}
+
+
+/* Update the current key at HD with the given OpenPGP keyblock in
+ {IMAGE,IMAGELEN}. */
+gpg_error_t
+keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
+{
+ gpg_error_t err;
+ const char *fname;
+ off_t off;
+ KEYBOXBLOB blob;
+ size_t nparsed;
+ struct _keybox_openpgp_info info;
+
+ if (!hd || !image || !imagelen)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
+ return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+ off = _keybox_get_blob_fileoffset (hd->found.blob);
+ if (off == (off_t)-1)
+ return gpg_error (GPG_ERR_GENERAL);
+
+ /* Close the file so that we do no mess up the position for a
+ next search. */
+ _keybox_close_file (hd);
+
+ /* Build a new blob. */
+ err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
+ if (err)
+ return err;
+ assert (nparsed <= imagelen);
+ err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
+ hd->ephemeral);
+ _keybox_destroy_openpgp_info (&info);
+
+ /* Update the keyblock. */
+ if (!err)
+ {
+ err = blob_filecopy (FILECOPY_UPDATE, fname, blob, hd->secret, 1, off);
+ _keybox_release_blob (blob);
+ }
+ return err;
+}
+
+
+
+#ifdef KEYBOX_WITH_X509
+int
+keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
+ unsigned char *sha1_digest)
+{
+ int rc;
+ const char *fname;
+ KEYBOXBLOB blob;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ if (!hd->kb)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+ /* Close this one otherwise we will mess up the position for a next
+ search. Fixme: it would be better to adjust the position after
+ the write operation. */
+ _keybox_close_file (hd);
+
+ rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
+ if (!rc)
+ {
+ rc = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0, 0);
+ _keybox_release_blob (blob);
+ /* if (!rc && !hd->secret && kb_offtbl) */
+ /* { */
+ /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
+ /* } */
+ }
+ return rc;
+}
+
+#endif /*KEYBOX_WITH_X509*/
+
+/* Note: We assume that the keybox has been locked before the current
+ search was executed. This is needed so that we can depend on the
+ offset information of the flags. */
+int
+keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
+{
+ off_t off;
+ const char *fname;
+ estream_t fp;
+ gpg_err_code_t ec;
+ size_t flag_pos, flag_size;
+ const unsigned char *buffer;
+ size_t length;
+
+ (void)idx; /* Not yet used. */
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ if (!hd->kb)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+ off = _keybox_get_blob_fileoffset (hd->found.blob);
+ if (off == (off_t)-1)
+ return gpg_error (GPG_ERR_GENERAL);
+
+ buffer = _keybox_get_blob_image (hd->found.blob, &length);
+ ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
+ if (ec)
+ return gpg_error (ec);
+
+ off += flag_pos;
+
+ _keybox_close_file (hd);
+ fp = es_fopen (hd->kb->fname, "r+b");
+ if (!fp)
+ return gpg_error_from_syserror ();
+
+ ec = 0;
+ if (es_fseeko (fp, off, SEEK_SET))
+ ec = gpg_err_code_from_syserror ();
+ else
+ {
+ unsigned char tmp[4];
+
+ tmp[0] = value >> 24;
+ tmp[1] = value >> 16;
+ tmp[2] = value >> 8;
+ tmp[3] = value;
+
+ switch (flag_size)
+ {
+ case 1:
+ case 2:
+ case 4:
+ if (es_fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
+ ec = gpg_err_code_from_syserror ();
+ break;
+ default:
+ ec = GPG_ERR_BUG;
+ break;
+ }
+ }
+
+ if (es_fclose (fp))
+ {
+ if (!ec)
+ ec = gpg_err_code_from_syserror ();
+ }
+
+ return gpg_error (ec);
+}
+
+
+
+int
+keybox_delete (KEYBOX_HANDLE hd)
+{
+ off_t off;
+ const char *fname;
+ estream_t fp;
+ int rc;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+ if (!hd->kb)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+ off = _keybox_get_blob_fileoffset (hd->found.blob);
+ if (off == (off_t)-1)
+ return gpg_error (GPG_ERR_GENERAL);
+ off += 4;
+
+ _keybox_close_file (hd);
+ fp = es_fopen (hd->kb->fname, "r+b");
+ if (!fp)
+ return gpg_error_from_syserror ();
+
+ if (es_fseeko (fp, off, SEEK_SET))
+ rc = gpg_error_from_syserror ();
+ else if (es_fputc (0, fp) == EOF)
+ rc = gpg_error_from_syserror ();
+ else
+ rc = 0;
+
+ if (es_fclose (fp))
+ {
+ if (!rc)
+ rc = gpg_error_from_syserror ();
+ }
+
+ return rc;
+}
+
+
+/* Compress the keybox file. This should be run with the file
+ locked. */
+int
+keybox_compress (KEYBOX_HANDLE hd)
+{
+ gpg_err_code_t ec;
+ int read_rc, rc;
+ const char *fname;
+ estream_t fp, newfp;
+ char *bakfname = NULL;
+ char *tmpfname = NULL;
+ int first_blob;
+ KEYBOXBLOB blob = NULL;
+ u32 cut_time;
+ int any_changes = 0;
+ int skipped_deleted;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ if (!hd->kb)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+ if (hd->secret)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ fname = hd->kb->fname;
+ if (!fname)
+ return gpg_error (GPG_ERR_INV_HANDLE);
+
+ _keybox_close_file (hd);
+
+ /* Open the source file. Because we do a rename, we have to check the
+ permissions of the file */
+ if ((ec = gnupg_access (fname, W_OK)))
+ return gpg_error (ec);
+
+ fp = es_fopen (fname, "rb");
+ if (!fp && errno == ENOENT)
+ return 0; /* Ready. File has been deleted right after the access above. */
+ if (!fp)
+ {
+ rc = gpg_error_from_syserror ();
+ return rc;
+ }
+
+ /* A quick test to see if we need to compress the file at all. We
+ schedule a compress run after 3 hours. */
+ if ( !_keybox_read_blob (&blob, fp, NULL) )
+ {
+ const unsigned char *buffer;
+ size_t length;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+ {
+ u32 last_maint = buf32_to_u32 (buffer+20);
+
+ if ( (last_maint + 3*3600) > make_timestamp () )
+ {
+ es_fclose (fp);
+ _keybox_release_blob (blob);
+ return 0; /* Compress run not yet needed. */
+ }
+ }
+ _keybox_release_blob (blob);
+ es_fseek (fp, 0, SEEK_SET);
+ es_clearerr (fp);
+ }
+
+ /* Create the new file. */
+ rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
+ if (rc)
+ {
+ es_fclose (fp);
+ return rc;;
+ }
+
+
+ /* Processing loop. By reading using _keybox_read_blob we
+ automagically skip any blobs flagged as deleted. Thus what we
+ only have to do is to check all ephemeral flagged blocks whether
+ their time has come and write out all other blobs. */
+ cut_time = make_timestamp () - 86400;
+ first_blob = 1;
+ skipped_deleted = 0;
+ for (rc=0; !(read_rc = _keybox_read_blob (&blob, fp, &skipped_deleted));
+ _keybox_release_blob (blob), blob = NULL )
+ {
+ unsigned int blobflags;
+ const unsigned char *buffer;
+ size_t length, pos, size;
+ u32 created_at;
+
+ if (skipped_deleted)
+ any_changes = 1;
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (first_blob)
+ {
+ first_blob = 0;
+ if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+ {
+ /* Write out the blob with an updated maintenance time
+ stamp and if needed (ie. used by gpg) set the openpgp
+ flag. */
+ _keybox_update_header_blob (blob, hd->for_openpgp);
+ rc = _keybox_write_blob (blob, newfp, NULL);
+ if (rc)
+ break;
+ continue;
+ }
+
+ /* The header blob is missing. Insert it. */
+ rc = _keybox_write_header_blob (newfp, hd->for_openpgp);
+ if (rc)
+ break;
+ any_changes = 1;
+ }
+ else if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+ {
+ /* Oops: There is another header record - remove it. */
+ any_changes = 1;
+ continue;
+ }
+
+ if (_keybox_get_flag_location (buffer, length,
+ KEYBOX_FLAG_BLOB, &pos, &size)
+ || size != 2)
+ {
+ rc = gpg_error (GPG_ERR_BUG);
+ break;
+ }
+ blobflags = buf16_to_uint (buffer+pos);
+ if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
+ {
+ /* This is an ephemeral blob. */
+ if (_keybox_get_flag_location (buffer, length,
+ KEYBOX_FLAG_CREATED_AT, &pos, &size)
+ || size != 4)
+ created_at = 0; /* oops. */
+ else
+ created_at = buf32_to_u32 (buffer+pos);
+
+ if (created_at && created_at < cut_time)
+ {
+ any_changes = 1;
+ continue; /* Skip this blob. */
+ }
+ }
+
+ rc = _keybox_write_blob (blob, newfp, NULL);
+ if (rc)
+ break;
+ }
+ if (skipped_deleted)
+ any_changes = 1;
+ _keybox_release_blob (blob); blob = NULL;
+ if (!rc && read_rc == -1)
+ rc = 0;
+ else if (!rc)
+ rc = read_rc;
+
+ /* Close both files. */
+ if (es_fclose(fp) && !rc)
+ rc = gpg_error_from_syserror ();
+ if (es_fclose(newfp) && !rc)
+ rc = gpg_error_from_syserror ();
+
+ /* Rename or remove the temporary file. */
+ if (rc || !any_changes)
+ gnupg_remove (tmpfname);
+ else
+ rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);
+
+ xfree(bakfname);
+ xfree(tmpfname);
+ return rc;
+}
diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c
new file mode 100644
index 0000000..3ce5162
--- /dev/null
+++ b/kbx/keybox-util.c
@@ -0,0 +1,102 @@
+/* keybox-util.c - Utility functions for Keybox
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_DOSISH_SYSTEM
+# define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */
+# include <windows.h>
+#endif
+
+#include "keybox-defs.h"
+
+
+/* Store the two malloced temporary file names used for keybox updates
+ of file FILENAME at R_BAKNAME and R_TMPNAME. On error an error
+ code is returned and NULL stored at R_BAKNAME and R_TMPNAME. If
+ FOR_KEYRING is true the returned names match those used by GnuPG's
+ keyring code. */
+gpg_error_t
+keybox_tmp_names (const char *filename, int for_keyring,
+ char **r_bakname, char **r_tmpname)
+{
+ gpg_error_t err;
+ char *bak_name, *tmp_name;
+
+ *r_bakname = NULL;
+ *r_tmpname = NULL;
+
+# ifdef USE_ONLY_8DOT3
+ /* Here is another Windoze bug?:
+ * you can't rename("pubring.kbx.tmp", "pubring.kbx");
+ * but rename("pubring.kbx.tmp", "pubring.aaa");
+ * works. So we replace ".kbx" by ".kb_" or ".k__". Note that we
+ * can't use ".bak" and ".tmp", because these suffixes are used by
+ * gpg's keyrings and would lead to a sharing violation or data
+ * corruption. If the name does not end in ".kbx" we assume working
+ * on a modern file system and append the suffix. */
+ {
+ const char *ext = for_keyring? EXTSEP_S GPGEXT_GPG : EXTSEP_S "kbx";
+ const char *b_ext = for_keyring? EXTSEP_S "bak" : EXTSEP_S "kb_";
+ const char *t_ext = for_keyring? EXTSEP_S "tmp" : EXTSEP_S "k__";
+ int repl;
+
+ if (strlen (ext) != 4 || strlen (b_ext) != 4)
+ BUG ();
+ repl = (strlen (filename) > 4
+ && !strcmp (filename + strlen (filename) - 4, ext));
+ bak_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1);
+ if (!bak_name)
+ return gpg_error_from_syserror ();
+ strcpy (bak_name, filename);
+ strcpy (bak_name + strlen (filename) - (repl?4:0), b_ext);
+
+ tmp_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1);
+ if (!tmp_name)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (bak_name);
+ return err;
+ }
+ strcpy (tmp_name, filename);
+ strcpy (tmp_name + strlen (filename) - (repl?4:0), t_ext);
+ }
+# else /* Posix file names */
+ (void)for_keyring;
+ bak_name = xtrymalloc (strlen (filename) + 2);
+ if (!bak_name)
+ return gpg_error_from_syserror ();
+ strcpy (stpcpy (bak_name, filename), "~");
+
+ tmp_name = xtrymalloc (strlen (filename) + 5);
+ if (!tmp_name)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (bak_name);
+ return err;
+ }
+ strcpy (stpcpy (tmp_name,filename), EXTSEP_S "tmp");
+# endif /* Posix filename */
+
+ *r_bakname = bak_name;
+ *r_tmpname = tmp_name;
+ return 0;
+}
diff --git a/kbx/keybox.h b/kbx/keybox.h
new file mode 100644
index 0000000..f90ea1c
--- /dev/null
+++ b/kbx/keybox.h
@@ -0,0 +1,137 @@
+/* keybox.h - Keybox operations
+ * Copyright (C) 2001, 2003, 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEYBOX_H
+#define KEYBOX_H 1
+#ifdef __cplusplus
+extern "C" {
+#if 0
+ }
+#endif
+#endif
+
+#include "../common/iobuf.h"
+#include "keybox-search-desc.h"
+
+#ifdef KEYBOX_WITH_X509
+# include <ksba.h>
+#endif
+
+typedef struct keybox_handle *KEYBOX_HANDLE;
+
+
+typedef enum
+ {
+ KEYBOX_FLAG_BLOB, /* The blob flags. */
+ KEYBOX_FLAG_VALIDITY, /* The validity of the entire key. */
+ KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */
+ KEYBOX_FLAG_KEY, /* The key flags; requires a key index. */
+ KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */
+ KEYBOX_FLAG_UID_VALIDITY,/* The validity of a specific uid, requires
+ an uid index. */
+ KEYBOX_FLAG_CREATED_AT, /* The date the block was created. */
+ KEYBOX_FLAG_SIG_INFO, /* The signature info block. */
+ } keybox_flag_t;
+
+/* Flag values used with KEYBOX_FLAG_BLOB. */
+#define KEYBOX_FLAG_BLOB_SECRET 1
+#define KEYBOX_FLAG_BLOB_EPHEMERAL 2
+
+/* The keybox blob types. */
+typedef enum
+ {
+ KEYBOX_BLOBTYPE_EMPTY = 0,
+ KEYBOX_BLOBTYPE_HEADER = 1,
+ KEYBOX_BLOBTYPE_PGP = 2,
+ KEYBOX_BLOBTYPE_X509 = 3
+ } keybox_blobtype_t;
+
+
+/*-- keybox-init.c --*/
+gpg_error_t keybox_register_file (const char *fname, int secret,
+ void **r_token);
+int keybox_is_writable (void *token);
+
+KEYBOX_HANDLE keybox_new_openpgp (void *token, int secret);
+KEYBOX_HANDLE keybox_new_x509 (void *token, int secret);
+void keybox_close_all_files (void *token);
+
+void keybox_release (KEYBOX_HANDLE hd);
+void keybox_push_found_state (KEYBOX_HANDLE hd);
+void keybox_pop_found_state (KEYBOX_HANDLE hd);
+const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
+int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes);
+
+gpg_error_t keybox_lock (KEYBOX_HANDLE hd, int yes, long timeout);
+
+/*-- keybox-file.c --*/
+/* Fixme: This function does not belong here: Provide a better
+ interface to create a new keybox file. */
+int _keybox_write_header_blob (estream_t fp, int openpgp_flag);
+
+/*-- keybox-search.c --*/
+gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
+ int *r_uid_no, int *r_pk_no);
+#ifdef KEYBOX_WITH_X509
+int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert);
+#endif /*KEYBOX_WITH_X509*/
+int keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value);
+
+gpg_error_t keybox_search_reset (KEYBOX_HANDLE hd);
+gpg_error_t keybox_search (KEYBOX_HANDLE hd,
+ KEYBOX_SEARCH_DESC *desc, size_t ndesc,
+ keybox_blobtype_t want_blobtype,
+ size_t *r_descindex, unsigned long *r_skipped);
+
+off_t keybox_offset (KEYBOX_HANDLE hd);
+gpg_error_t keybox_seek (KEYBOX_HANDLE hd, off_t offset);
+
+/*-- keybox-update.c --*/
+gpg_error_t keybox_insert_keyblock (KEYBOX_HANDLE hd,
+ const void *image, size_t imagelen);
+gpg_error_t keybox_update_keyblock (KEYBOX_HANDLE hd,
+ const void *image, size_t imagelen);
+
+#ifdef KEYBOX_WITH_X509
+int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
+ unsigned char *sha1_digest);
+#endif /*KEYBOX_WITH_X509*/
+int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value);
+
+int keybox_delete (KEYBOX_HANDLE hd);
+int keybox_compress (KEYBOX_HANDLE hd);
+
+
+/*-- --*/
+
+#if 0
+int keybox_locate_writable (KEYBOX_HANDLE hd);
+int keybox_rebuild_cache (void *);
+#endif
+
+
+/*-- keybox-util.c --*/
+gpg_error_t keybox_tmp_names (const char *filename, int for_keyring,
+ char **r_bakname, char **r_tmpname);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*KEYBOX_H*/
diff --git a/kbx/mkerrors b/kbx/mkerrors
new file mode 100755
index 0000000..629485a
--- /dev/null
+++ b/kbx/mkerrors
@@ -0,0 +1,70 @@
+#!/bin/sh
+# mkerrors - Extract error strings from assuan.h
+# and create C source for assuan_strerror
+# Copyright (C) 2001 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+cat <<EOF
+/* Generated automatically by mkerrors */
+/* Do not edit! */
+
+#include <stdio.h>
+#include "keybox-defs.h"
+
+/**
+ * keybox_strerror:
+ * @err: Error code
+ *
+ * This function returns a textual representaion of the given
+ * errorcode. If this is an unknown value, a string with the value
+ * is returned (Beware: it is hold in a static buffer).
+ *
+ * Return value: String with the error description.
+ **/
+const char *
+keybox_strerror (KeyboxError err)
+{
+ const char *s;
+ static char buf[25];
+
+ switch (err)
+ {
+EOF
+
+awk '
+/KEYBOX_No_Error/ { okay=1 }
+!okay {next}
+/}/ { exit 0 }
+/KEYBOX_[A-Za-z_]*/ { print_code($1) }
+
+
+function print_code( s )
+{
+printf " case %s: s=\"", s ;
+gsub(/_/, " ", s );
+printf "%s\"; break;\n", tolower(substr(s,8));
+}
+'
+
+cat <<EOF
+ default: sprintf (buf, "ec=%d", err ); s=buf; break;
+ }
+
+ return s;
+}
+
+EOF