mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
Signature checking tool based on GnuPG
The new 'verify' component facilitates the code of GnuPG to verify detached OpenPGP signatures against public keys. Since GnuPG depends on libgcrypt and libgpg-error, the patch adds these libraries to the libports repository. Fixes #2640
This commit is contained in:
parent
8fca8a9a04
commit
5b6bd8459f
1
repos/libports/lib/import/import-libgcrypt.mk
Normal file
1
repos/libports/lib/import/import-libgcrypt.mk
Normal file
@ -0,0 +1 @@
|
||||
INC_DIR += $(call select_from_ports,libgcrypt)/include/libgcrypt
|
34
repos/libports/lib/mk/libgcrypt.mk
Normal file
34
repos/libports/lib/mk/libgcrypt.mk
Normal file
@ -0,0 +1,34 @@
|
||||
LIBGCRYPT_DIR := $(call select_from_ports,libgcrypt)/src/lib/libgcrypt
|
||||
LIBGCRYPT_SRC_DIR := $(LIBGCRYPT_DIR)/src
|
||||
|
||||
LIBS := libc libgpg-error
|
||||
|
||||
SRC_C := global.c stdmem.c visibility.c fips.c misc.c secmem.c md.c cipher.c \
|
||||
random.c random-csprng.c poly1305.c rndjent.c pubkey.c random-drbg.c \
|
||||
primegen.c random-system.c sha1.c mac.c hmac-tests.c mac-poly1305.c \
|
||||
hwfeatures.c hmac256.c blake2.c rndhw.c hash-common.c sexp.c \
|
||||
mac-hmac.c rsa.c rsa-common.c pubkey-util.c sha256.c
|
||||
|
||||
SRC_C += $(notdir $(wildcard $(LIBGCRYPT_DIR)/mpi/mpi*.c))
|
||||
SRC_C += $(notdir $(wildcard $(LIBGCRYPT_DIR)/mpi/generic/*.c))
|
||||
SRC_C += $(notdir $(wildcard $(LIBGCRYPT_DIR)/cipher/cipher-*.c))
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/libgcrypt
|
||||
INC_DIR += $(REP_DIR)/src/lib/libgcrypt/mpi
|
||||
INC_DIR += $(LIBGCRYPT_SRC_DIR)
|
||||
INC_DIR += $(LIBGCRYPT_DIR)/mpi
|
||||
INC_DIR += $(call select_from_ports,libgcrypt)/include/libgcrypt
|
||||
|
||||
CC_OPT += -D_GCRYPT_IN_LIBGCRYPT
|
||||
CC_OPT += -DVERSION='"$(< $(LIBGCRYPT_DIR))"'
|
||||
CC_OPT += -DLIBGCRYPT_CIPHERS='"rsa"'
|
||||
CC_OPT += -DLIBGCRYPT_PUBKEY_CIPHERS='"rsa"'
|
||||
CC_OPT += -DLIBGCRYPT_DIGESTS='""'
|
||||
|
||||
CC_OPT_global += -Wno-switch
|
||||
|
||||
vpath %.c $(LIBGCRYPT_SRC_DIR)
|
||||
vpath %.c $(LIBGCRYPT_DIR)/cipher
|
||||
vpath %.c $(LIBGCRYPT_DIR)/random
|
||||
vpath %.c $(LIBGCRYPT_DIR)/mpi
|
||||
vpath %.c $(LIBGCRYPT_DIR)/mpi/generic
|
15
repos/libports/lib/mk/libgpg-error.mk
Normal file
15
repos/libports/lib/mk/libgpg-error.mk
Normal file
@ -0,0 +1,15 @@
|
||||
LIBGPG_ERROR_DIR := $(call select_from_ports,libgcrypt)/src/lib/libgpg-error
|
||||
LIBGPG_ERROR_SRC_DIR := $(LIBGPG_ERROR_DIR)/src
|
||||
|
||||
LIBS := libc
|
||||
|
||||
SRC_C := visibility.c code-from-errno.c init.c estream.c estream-printf.c \
|
||||
strerror.c code-to-errno.c posix-lock.c posix-thread.c
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/libgpg-error $(LIBGPG_ERROR_SRC_DIR)
|
||||
|
||||
CC_OPT += -DHAVE_CONFIG_H
|
||||
|
||||
include $(REP_DIR)/lib/import/import-libgcrypt.mk
|
||||
|
||||
vpath %.c $(LIBGPG_ERROR_SRC_DIR)
|
1
repos/libports/ports/libgcrypt.hash
Normal file
1
repos/libports/ports/libgcrypt.hash
Normal file
@ -0,0 +1 @@
|
||||
c9c155548be98de2f3fcf27400838caaee3db765
|
83
repos/libports/ports/libgcrypt.port
Normal file
83
repos/libports/ports/libgcrypt.port
Normal file
@ -0,0 +1,83 @@
|
||||
LICENSE := LGPLv2.1+
|
||||
VERSION := 1.8.2
|
||||
DOWNLOADS := libgcrypt.archive libgpg-error.archive
|
||||
|
||||
COMMON_URL := https://www.gnupg.org/ftp/gcrypt
|
||||
|
||||
URL(libgcrypt) := $(COMMON_URL)/libgcrypt/libgcrypt-$(VERSION).tar.bz2
|
||||
SHA(libgcrypt) := ab8aae5d7a68f8e0988f90e11e7f6a4805af5c8d
|
||||
DIR(libgcrypt) := src/lib/libgcrypt
|
||||
|
||||
LIBGPG_ERROR_VERSION := 1.27
|
||||
|
||||
URL(libgpg-error) := $(COMMON_URL)/libgpg-error/libgpg-error-$(LIBGPG_ERROR_VERSION).tar.bz2
|
||||
SHA(libgpg-error) := a428758999ff573e62d06892e3d2c0b0f335787c
|
||||
DIR(libgpg-error) := src/lib/libgpg-error
|
||||
|
||||
HASH_INPUT += $(REP_DIR)/src/lib/libgpg-error/config.h
|
||||
|
||||
$(call check_tool,mawk)
|
||||
|
||||
gen_files := include/libgcrypt/gcrypt.h \
|
||||
include/libgcrypt/gpg-error.h \
|
||||
src/lib/libgpg-error/src/code-from-errno.h \
|
||||
src/lib/libgpg-error/src/code-to-errno.h
|
||||
|
||||
default: $(gen_files)
|
||||
|
||||
$(gen_files): $(DOWNLOADS)
|
||||
|
||||
# obtain 'VERSION_NUMBER' definition from configure script
|
||||
version_number = $(shell sed -n "/VERSION_NUMBER=/s/.*=//p" $1/configure)
|
||||
|
||||
subst_gcrypt = \
|
||||
"@INSERT_SYS_SELECT_H@/include <sys\/select.h>" \
|
||||
"@FALLBACK_SOCKLEN_T@/" \
|
||||
"@VERSION@/\"$(VERSION)\"" \
|
||||
"@VERSION_NUMBER@/$(call version_number,src/lib/libgcrypt)"
|
||||
|
||||
apply_substitutions = $(VERBOSE)for i in $(1); do sed -i "s/$$i/g" $(2); done
|
||||
|
||||
include/libgcrypt/gcrypt.h:
|
||||
@$(MSG_GENERATE)$@
|
||||
$(VERBOSE)mkdir -p $(dir $@)
|
||||
$(VERBOSE)cp src/lib/libgcrypt/src/gcrypt.h.in $@
|
||||
$(call apply_substitutions,$(subst_gcrypt),$@)
|
||||
|
||||
include/libgcrypt/gpg-error.h: mkheader
|
||||
@$(MSG_GENERATE)$@
|
||||
$(VERBOSE)mkdir -p $(dir $@)
|
||||
$(VERBOSE)cp src/lib/libgpg-error/src/syscfg/lock-obj-pub.x86_64-pc-kfreebsd-gnu.h \
|
||||
lock-obj-pub.native.h
|
||||
$(VERBOSE)./mkheader unknown-host-os host-triplet-unknown \
|
||||
src/lib/libgpg-error/src/gpg-error.h.in \
|
||||
$(REP_DIR)/src/lib/libgpg-error/config.h \
|
||||
$(LIBGPG_ERROR_VERSION) $(call version_number,src/lib/libgpg-error) >$@
|
||||
$(VERBOSE)rm lock-obj-pub.native.h mkheader
|
||||
|
||||
src/lib/libgpg-error/src/code-from-errno.h: mkerrcodes
|
||||
@$(MSG_GENERATE)$@
|
||||
$(VERBOSE)mkdir -p $(dir $@)
|
||||
$(VERBOSE)./mkerrcodes | nawk -f src/lib/libgpg-error/src/mkerrcodes2.awk > $@
|
||||
$(VERBOSE)rm mkerrcodes
|
||||
|
||||
src/lib/libgpg-error/src/code-to-errno.h:
|
||||
@$(MSG_GENERATE)$@
|
||||
$(VERBOSE)nawk -f src/lib/libgpg-error/src/mkerrnos.awk src/lib/libgpg-error/src/errnos.in > $@
|
||||
|
||||
mkheader: $(DOWNLOADS)
|
||||
$(VERBOSE)$(CC) -g -Isrc/lib/libgpg-error/src \
|
||||
src/lib/libgpg-error/src/mkheader.c -o $@
|
||||
|
||||
mkerrcodes: $(DOWNLOADS) src/lib/libgpg-error/src/mkerrcodes.h
|
||||
$(VERBOSE)$(CC) -g -Isrc/lib/libgpg-error/src \
|
||||
src/lib/libgpg-error/src/mkerrcodes.c -o $@
|
||||
|
||||
src/lib/libgpg-error/src/mkerrcodes.h:
|
||||
@$(MSG_GENERATE)$@
|
||||
$(VERBOSE)nawk -f src/lib/libgpg-error/src/mkerrcodes1.awk \
|
||||
src/lib/libgpg-error/src/errnos.in |\
|
||||
$(CPP) -P - |\
|
||||
grep GPG_ERR_ |\
|
||||
nawk -f src/lib/libgpg-error/src/mkerrcodes.awk > $@
|
||||
|
31
repos/libports/recipes/api/libgcrypt/content.mk
Normal file
31
repos/libports/recipes/api/libgcrypt/content.mk
Normal file
@ -0,0 +1,31 @@
|
||||
content: src/lib/libgcrypt src/lib/libgpg-error include lib/mk lib/import LICENSE
|
||||
|
||||
LIBGCRYPT_DIR := $(call port_dir,$(REP_DIR)/ports/libgcrypt)
|
||||
LIBGCRYPT_SRC_DIR := $(LIBGCRYPT_DIR)/src/lib/libgcrypt
|
||||
|
||||
include:
|
||||
cp -r $(LIBGCRYPT_DIR)/include/libgcrypt $@
|
||||
|
||||
src/lib/libgcrypt:
|
||||
mkdir -p $@
|
||||
cp -r $(addprefix $(LIBGCRYPT_SRC_DIR)/,src mpi cipher random compat) $@
|
||||
cp $(REP_DIR)/src/lib/libgcrypt/config.h $@
|
||||
cp $(REP_DIR)/src/lib/libgcrypt/mod-source-info.h $@
|
||||
cp $(REP_DIR)/src/lib/libgcrypt/mpi/mpi-asm-defs.h $@/mpi
|
||||
|
||||
src/lib/libgpg-error:
|
||||
mkdir -p $@
|
||||
cp -r $(LIBGCRYPT_DIR)/src/lib/libgpg-error/src $@
|
||||
cp $(REP_DIR)/src/lib/libgpg-error/config.h $@
|
||||
|
||||
lib/mk:
|
||||
mkdir -p $@
|
||||
cp $(addprefix $(REP_DIR)/lib/mk/,libgpg-error.mk libgcrypt.mk) $@
|
||||
|
||||
lib/import:
|
||||
mkdir -p $@
|
||||
cp $(REP_DIR)/lib/import/import-libgcrypt.mk $@
|
||||
|
||||
LICENSE:
|
||||
cp $(LIBGCRYPT_SRC_DIR)/COPYING $@
|
||||
|
1
repos/libports/recipes/api/libgcrypt/hash
Normal file
1
repos/libports/recipes/api/libgcrypt/hash
Normal file
@ -0,0 +1 @@
|
||||
2018-01-11 5d8f799b6f0c03d4d1697da40c858d878b2e3664
|
21
repos/libports/src/lib/libgcrypt/config.h
Normal file
21
repos/libports/src/lib/libgcrypt/config.h
Normal file
@ -0,0 +1,21 @@
|
||||
#define _GCRYPT_CONFIG_H_INCLUDED 1
|
||||
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
#define HAVE_GETPID 1
|
||||
#define HAVE_CLOCK 1
|
||||
|
||||
#ifdef __LP64__
|
||||
#define SIZEOF_UNSIGNED_SHORT 2
|
||||
#define SIZEOF_UNSIGNED_INT 4
|
||||
#define SIZEOF_UNSIGNED_LONG 8
|
||||
#else
|
||||
#define SIZEOF_UNSIGNED_SHORT 2
|
||||
#define SIZEOF_UNSIGNED_INT 4
|
||||
#define SIZEOF_UNSIGNED_LONG 4
|
||||
#define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
#endif
|
||||
|
||||
#define USE_SHA1 1
|
||||
#define USE_SHA256 1
|
||||
#define USE_RSA 1
|
48
repos/libports/src/lib/libgcrypt/local_install.mk
Normal file
48
repos/libports/src/lib/libgcrypt/local_install.mk
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# This is a convenience helper for porting libgcrypt. It downloads and builds
|
||||
# libgcrypt and libgpg-error within the current working directory and thereby
|
||||
# makes generated files like config.h readily available.
|
||||
#
|
||||
|
||||
default: install_libgcrypt
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
LIBGRYPT := libgcrypt-1.8.2
|
||||
LIBGPG_ERROR := libgpg-error-1.27
|
||||
|
||||
INSTALL_DIR := $(PWD)/install
|
||||
|
||||
URL(${LIBGRYPT}) := https://www.gnupg.org/ftp/gcrypt/libgcrypt/$(LIBGRYPT).tar.bz2
|
||||
URL(${LIBGPG_ERROR}) := https://www.gnupg.org/ftp/gcrypt/libgpg-error/$(LIBGPG_ERROR).tar.bz2
|
||||
|
||||
install/include/gpg-error.h: build/$(LIBGPG_ERROR)/Makefile
|
||||
cd build/$(LIBGPG_ERROR); $(MAKE) install
|
||||
|
||||
install_libgcrypt: build/$(LIBGRYPT)/Makefile
|
||||
cd build/$(LIBGRYPT); $(MAKE) install
|
||||
|
||||
build/$(LIBGRYPT)/Makefile : src/$(LIBGRYPT) build/$(LIBGRYPT) install/include/gpg-error.h
|
||||
cd build/$(LIBGRYPT); \
|
||||
$(PWD)/src/$(LIBGRYPT)/configure --prefix=$(INSTALL_DIR) \
|
||||
--with-libgpg-error-prefix=$(INSTALL_DIR)
|
||||
|
||||
build/$(LIBGPG_ERROR)/Makefile : src/$(LIBGPG_ERROR) build/$(LIBGPG_ERROR)
|
||||
cd build/$(LIBGPG_ERROR); \
|
||||
$(PWD)/src/$(LIBGPG_ERROR)/configure --prefix=$(INSTALL_DIR)
|
||||
|
||||
build/%:
|
||||
mkdir -p $@
|
||||
|
||||
src/% : %.tar.bz2
|
||||
mkdir -p src
|
||||
cd src; tar xf $(PWD)/$<
|
||||
|
||||
%.tar.bz2:
|
||||
wget ${URL($*)}
|
||||
|
||||
clean:
|
||||
rm -rf install build src
|
||||
|
||||
cleanall: clean
|
||||
rm *.tar.bz2
|
1
repos/libports/src/lib/libgcrypt/mod-source-info.h
Normal file
1
repos/libports/src/lib/libgcrypt/mod-source-info.h
Normal file
@ -0,0 +1 @@
|
||||
static char mod_source_info[] = "";
|
7
repos/libports/src/lib/libgcrypt/mpi/mpi-asm-defs.h
Normal file
7
repos/libports/src/lib/libgcrypt/mpi/mpi-asm-defs.h
Normal file
@ -0,0 +1,7 @@
|
||||
/*
|
||||
* 'libgcrypt/src/mpi.h' unconditionally includes "../mpi/mpi-asm-defs.h"/
|
||||
* We need to direct it to one of the architecture-specific versions at
|
||||
* 'libgcrypt/mpi/<architecture>/'.
|
||||
*/
|
||||
|
||||
#include <../mpi/generic/mpi-asm-defs.h>
|
32
repos/libports/src/lib/libgpg-error/config.h
Normal file
32
repos/libports/src/lib/libgpg-error/config.h
Normal file
@ -0,0 +1,32 @@
|
||||
#define BUILD_REVISION "0"
|
||||
#define BUILD_TIMESTAMP "<none>"
|
||||
#define HAVE_DECL_STRERROR_R 1
|
||||
#define HAVE_DLFCN_H 1
|
||||
#define HAVE_GCC_ATTRIBUTE_ALIGNED 1
|
||||
#define HAVE_INTMAX_T 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_LONG_LONG_INT 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_MEMRCHR 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRERROR_R 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UINTMAX_T 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
||||
#define HOST_TRIPLET_STRING "unknown-host-triplet"
|
||||
#define PACKAGE "libgpg-error"
|
||||
#define PACKAGE_NAME "libgpg-error"
|
||||
#define PACKAGE_VERSION "1.27"
|
||||
#define REPLACEMENT_FOR_OFF_T "long"
|
||||
#define STDC_HEADERS 1
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
#define VERSION "1.27"
|
||||
#define GPGRT_ENABLE_ES_MACROS 1
|
||||
#define USE_POSIX_THREADS 1
|
1
repos/ports/ports/gnupg.hash
Normal file
1
repos/ports/ports/gnupg.hash
Normal file
@ -0,0 +1 @@
|
||||
8ce83fbaac6f49a07708219ec64a9a0ae12606c4
|
7
repos/ports/ports/gnupg.port
Normal file
7
repos/ports/ports/gnupg.port
Normal file
@ -0,0 +1,7 @@
|
||||
LICENSE := GPLv3
|
||||
VERSION := 2.2.4
|
||||
DOWNLOADS := gnupg.archive
|
||||
|
||||
URL(gnupg) := https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-$(VERSION).tar.bz2
|
||||
SHA(gnupg) := 732266e8888c6f41c084d043c7a0058332ff3580
|
||||
DIR(gnupg) := src/app/gnupg
|
14
repos/ports/recipes/src/verify/content.mk
Normal file
14
repos/ports/recipes/src/verify/content.mk
Normal file
@ -0,0 +1,14 @@
|
||||
content: src/app/verify src/app/gnupg LICENSE
|
||||
|
||||
GNUPG_SRC_DIR := $(call port_dir,$(REP_DIR)/ports/gnupg)/src/app/gnupg
|
||||
|
||||
src/app/verify:
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
src/app/gnupg:
|
||||
mkdir -p $@
|
||||
cp -r $(addprefix $(GNUPG_SRC_DIR)/,g10 common kbx) $@
|
||||
|
||||
LICENSE:
|
||||
cp $(GNUPG_SRC_DIR)/COPYING $@
|
||||
|
1
repos/ports/recipes/src/verify/hash
Normal file
1
repos/ports/recipes/src/verify/hash
Normal file
@ -0,0 +1 @@
|
||||
2018-01-11 a131bb0a9eb207d83c2ffbd63cd4cab42b7b2ce1
|
7
repos/ports/recipes/src/verify/used_apis
Normal file
7
repos/ports/recipes/src/verify/used_apis
Normal file
@ -0,0 +1,7 @@
|
||||
base
|
||||
os
|
||||
vfs
|
||||
libc
|
||||
timer_session
|
||||
report_session
|
||||
libgcrypt
|
66
repos/ports/run/verify.run
Normal file
66
repos/ports/run/verify.run
Normal file
@ -0,0 +1,66 @@
|
||||
create_boot_directory
|
||||
|
||||
import_from_depot genodelabs/src/[base_src] \
|
||||
genodelabs/src/init \
|
||||
genodelabs/src/report_rom \
|
||||
genodelabs/src/libc
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="RAM"/>
|
||||
<service name="ROM"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route> <any-service> <parent/> <any-child/> </any-service> </default-route>
|
||||
|
||||
<start name="report_rom" caps="100">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Report"/> <service name="ROM"/> </provides>
|
||||
<config verbose="yes"/>
|
||||
</start>
|
||||
|
||||
<start name="verify" caps="200">
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<config verbose="yes">
|
||||
<libc stdout="/dev/log" stderr="/dev/null" rtc="/dev/null"/>
|
||||
<vfs>
|
||||
<rom name="pubkey"/>
|
||||
<tar name="test.tar"/>
|
||||
<dir name="dev"> <log/> <null/> </dir>
|
||||
</vfs>
|
||||
<verify path="expect_valid.txt" pubkey="/nonexistent_pubkey"/>
|
||||
<verify path="expect_valid.txt" pubkey="/dev/null"/>
|
||||
<verify path="expect_valid.txt" pubkey="/pubkey"/>
|
||||
<verify path="expect_invalid.txt" pubkey="/pubkey"/>
|
||||
</config>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build { app/verify }
|
||||
|
||||
exec tar cf [run_dir]/genode/test.tar -C [genode_dir]/repos/ports/src/app/verify/test .
|
||||
|
||||
file copy [genode_dir]/depot/nfeske/pubkey [run_dir]/genode/pubkey
|
||||
|
||||
build_boot_image { verify libc.lib.so pthread.lib.so }
|
||||
|
||||
append qemu_args " -nographic "
|
||||
|
||||
run_genode_until {</result>.*\n} 30
|
||||
|
||||
grep_output {\[init \-\> report_rom\]}
|
||||
|
||||
compare_output_to {
|
||||
[init -> report_rom] report 'verify -> result'
|
||||
[init -> report_rom] <result>
|
||||
[init -> report_rom] <bad path="expect_valid.txt" reason="public key unavailable"/>
|
||||
[init -> report_rom] <bad path="expect_valid.txt" reason="malformed public key"/>
|
||||
[init -> report_rom] <good path="expect_valid.txt"/>
|
||||
[init -> report_rom] <bad path="expect_invalid.txt" reason="bad signature"/>
|
||||
[init -> report_rom] </result>
|
||||
}
|
19
repos/ports/src/app/verify/README
Normal file
19
repos/ports/src/app/verify/README
Normal file
@ -0,0 +1,19 @@
|
||||
The 'verify' component verifies detached OpenPGP signatures. Its configuration
|
||||
accepts any number of '<verify>' nodes of the following form:
|
||||
|
||||
! <verify path="/path/to/data" pubkey="/pubkey"/>
|
||||
|
||||
The detached signature file is expected to be named after the data file with
|
||||
the additional suffix '.sig'. The 'path' and 'pubkey' attributes refer to
|
||||
paths within the component's local VFS.
|
||||
|
||||
The results of the signature checks are provided in the form of a report
|
||||
with the label "result". For each '<verify>' node of the configuration, this
|
||||
report contains a node of type '<good>' or '<bad>'. In either case, the node
|
||||
contains the corresponding 'path' as attribute. Furthermore, '<bad>' nodes
|
||||
feature diagnostic information as a 'reason' attribute.
|
||||
|
||||
For an example scenario, refer to the _ports/run/verify.run_ script.
|
||||
|
||||
Disclaimer: The component does not perform time-related plausibility checks
|
||||
such as scrutinizing the creation date of the public key.
|
0
repos/ports/src/app/verify/assuan.h
Normal file
0
repos/ports/src/app/verify/assuan.h
Normal file
0
repos/ports/src/app/verify/config.h
Normal file
0
repos/ports/src/app/verify/config.h
Normal file
120
repos/ports/src/app/verify/dummies.c
Normal file
120
repos/ports/src/app/verify/dummies.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* \brief Dummies needed to link the parts of GnuPG that we need
|
||||
* \author Norman Feske
|
||||
* \date 2018-01-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* libc includes */
|
||||
#include <ctype.h> /* isascii, needed by gnupg headers */
|
||||
|
||||
/* GnuPG headers */
|
||||
#include <gpg.h>
|
||||
#include <main.h>
|
||||
|
||||
|
||||
/********************
|
||||
** Silent dummies **
|
||||
********************/
|
||||
|
||||
int check_special_filename(char const *fname, int for_write, int notranslate)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void show_notation(PKT_signature *sig,int indent,int mode,int which) { }
|
||||
void show_keyserver_url(PKT_signature *sig,int indent,int mode) { }
|
||||
void show_policy_url(PKT_signature *sig,int indent,int mode) { }
|
||||
void register_mem_cleanup_func() { }
|
||||
int check_signatures_trust(ctrl_t ctrl, PKT_signature *sig) { return 0; }
|
||||
|
||||
const char *asctimestamp(u32 stamp) { return "<sometime>"; }
|
||||
|
||||
u32 make_timestamp() { return ~0; /* disarm key-creation time check */ }
|
||||
|
||||
|
||||
/***********************************************************
|
||||
** Dummies that print a message when unexpectedly called **
|
||||
***********************************************************/
|
||||
|
||||
#define DUMMY(ret_type, ret_val, name, args) \
|
||||
ret_type name args \
|
||||
{ \
|
||||
printf("%s: not implemented\n", __func__); \
|
||||
return ret_val; \
|
||||
}
|
||||
|
||||
#define DUMMY_NORETURN(name, args) \
|
||||
void name args \
|
||||
{ \
|
||||
printf("%s: not implemented\n", __func__); \
|
||||
for (;;); \
|
||||
}
|
||||
|
||||
DUMMY(byte const *, NULL, get_session_marker, (size_t *rlen));
|
||||
DUMMY(char const *, NULL, print_fname_stdin, (char const *s));
|
||||
|
||||
DUMMY_NORETURN(g10_exit, (int code));
|
||||
|
||||
|
||||
/*
|
||||
* The following dummies are solely needed by mainproc.c
|
||||
*/
|
||||
|
||||
DUMMY(char *, NULL, bin2hex, (const void *buffer, size_t length, char *stringbuf));
|
||||
DUMMY(int, 0, decrypt_data, (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek));
|
||||
DUMMY(void, , dump_attribs, (const PKT_user_id *uid, PKT_public_key *pk));
|
||||
DUMMY(void, , free_keyserver_spec, ());
|
||||
DUMMY(void, , free_notation, (struct notation *notation));
|
||||
DUMMY(char *, NULL, get_matching_datafile, (const char *sigfilename));
|
||||
DUMMY(gpg_error_t, 0, get_override_session_key, (DEK *dek, const char *string));
|
||||
DUMMY(void, , get_ownertrust_info, ());
|
||||
DUMMY(gpg_error_t, 0, get_session_key, (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek));
|
||||
DUMMY(char*, NULL, get_user_id, (ctrl_t ctrl, u32 *keyid, size_t *rn));
|
||||
DUMMY(char*, NULL, get_user_id_native, (ctrl_t ctrl, u32 *keyid));
|
||||
DUMMY(void, , get_validity, ());
|
||||
DUMMY(void, , get_validity_info, ());
|
||||
DUMMY(void, , gpg_dirmngr_get_pka, ());
|
||||
DUMMY(int, 0, handle_compressed, (ctrl_t ctrl, void *ctx, PKT_compressed *cd, int (*callback)(iobuf_t, void *), void *passthru));
|
||||
DUMMY(int, 0, have_secret_key_with_kid, (u32 *keyid));
|
||||
DUMMY(void, , is_valid_mailbox, ());
|
||||
DUMMY(void, , keyserver_any_configured, ());
|
||||
DUMMY(void, , keyserver_import_fprint, ());
|
||||
DUMMY(void, , keyserver_import_keyid, ());
|
||||
DUMMY(void, , keyserver_import_wkd, ());
|
||||
DUMMY(void, , merge_keys_and_selfsig, (ctrl_t ctrl, kbnode_t keyblock));
|
||||
DUMMY(void, , parse_keyserver_uri, ());
|
||||
DUMMY(void, , parse_preferred_keyserver, ());
|
||||
DUMMY(void, , passphrase_clear_cache, (const char *cacheid));
|
||||
DUMMY(DEK *, NULL, passphrase_to_dek, (int cipher_algo, STRING2KEY *s2k, int create, int nocache, const char *tryagain_text, int *canceled));
|
||||
DUMMY(void, , print_fingerprint, (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int mode));
|
||||
DUMMY(void, , print_key_line, (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret));
|
||||
DUMMY(void, , print_utf8_buffer, (estream_t fp, const void *p, size_t n));
|
||||
DUMMY(void, , show_photos, ());
|
||||
DUMMY(struct notation *, NULL, sig_to_notation, (PKT_signature *sig));
|
||||
DUMMY(const char *, NULL, strtimestamp, (u32 stamp));
|
||||
DUMMY(void, , trust_value_to_string, ());
|
||||
DUMMY(char *, NULL, utf8_to_native, (const char *string, size_t length, int delim));
|
||||
DUMMY(int, 0, get_pubkey_byfprint, (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock, const byte *fprint, size_t fprint_len));
|
||||
DUMMY(const char *, NULL, strtimevalue, (u32 stamp));
|
||||
DUMMY(char *, NULL, try_make_printable_string, (const void *p, size_t n, int delim));
|
||||
DUMMY(void, , zb32_encode, ());
|
||||
DUMMY(void, , image_type_to_string, ());
|
||||
DUMMY(int, 0, get_pubkey_fast, (PKT_public_key *pk, u32 *keyid));
|
||||
DUMMY(void, , parse_image_header, ());
|
||||
DUMMY(char *, NULL, make_outfile_name, (const char *iname));
|
||||
DUMMY(char *, NULL, ask_outfile_name, (const char *name, size_t namelen));
|
||||
DUMMY(int, 0, overwrite_filep, (const char *fname));
|
||||
DUMMY(void, , tty_get, ());
|
||||
DUMMY(void, , display_online_help, (const char *keyword));
|
||||
DUMMY(void, , tty_kill_prompt, ());
|
||||
DUMMY(int, 0, text_filter, (void *opaque, int control, iobuf_t chain, byte *buf, size_t *ret_len));
|
||||
DUMMY(iobuf_t, NULL, open_sigfile, (const char *sigfilename, progress_filter_context_t *pfx));
|
||||
DUMMY(void, , tty_printf, ());
|
||||
DUMMY(char *, NULL, gnupg_getcwd, ());
|
151
repos/ports/src/app/verify/gnupg.c
Normal file
151
repos/ports/src/app/verify/gnupg.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* \brief Wrapper for safely calling into GnuPG from C++ code
|
||||
* \author Norman Feske
|
||||
* \date 2018-01-06
|
||||
*
|
||||
* We cannot directly include GnuPG's 'main.h' from C++ code. E.g., because
|
||||
* the header uses C++ keywords as variable names. By using this wrapper,
|
||||
* we keep C++ and C nicely separated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include "gnupg.h"
|
||||
|
||||
/* libc includes */
|
||||
#include <ctype.h> /* isascii, needed by gnupg headers */
|
||||
|
||||
/* GnuPG headers */
|
||||
#include <gpg.h>
|
||||
#include <main.h>
|
||||
#include <options.h>
|
||||
|
||||
|
||||
/*
|
||||
* Global variable that is incremented by GnuPG whenever a signature check
|
||||
* failed.
|
||||
*/
|
||||
int g10_errors_seen = 0;
|
||||
|
||||
|
||||
enum Read_pubkey_result { READ_PUBKEY_OK,
|
||||
READ_PUBKEY_MISSING_FILE,
|
||||
READ_PUBKEY_INVALID_FORMAT };
|
||||
|
||||
/**
|
||||
* Read public key into new packet
|
||||
*
|
||||
* The packet is allocated by this function and returned as 'packet_out_ptr'
|
||||
* whenever it returns with 'READ_PUBKEY_OK'.
|
||||
*/
|
||||
static enum Read_pubkey_result
|
||||
read_pubkey_from_file(char const *pubkey_path, PACKET **packet_out_ptr)
|
||||
{
|
||||
*packet_out_ptr = NULL;
|
||||
|
||||
/* set up parser context for parsing the public key data */
|
||||
struct parse_packet_ctx_s parse_ctx;
|
||||
memset(&parse_ctx, 0, sizeof(parse_ctx));
|
||||
|
||||
parse_ctx.inp = iobuf_open(pubkey_path);
|
||||
if (!parse_ctx.inp)
|
||||
return READ_PUBKEY_MISSING_FILE;
|
||||
|
||||
/* convert public key from ASCII-armored to binary representation */
|
||||
armor_filter_context_t *afx = new_armor_context ();
|
||||
push_armor_filter(afx, parse_ctx.inp);
|
||||
|
||||
/* parse public key data */
|
||||
PACKET * const packet = xmalloc(sizeof(*packet));
|
||||
memset(packet, 0, sizeof(*packet));
|
||||
int const parse_ok = (parse_packet(&parse_ctx, packet) == 0);
|
||||
|
||||
release_armor_context(afx);
|
||||
iobuf_close(parse_ctx.inp);
|
||||
|
||||
if (parse_ok && packet->pkt.public_key) {
|
||||
*packet_out_ptr = packet;
|
||||
return READ_PUBKEY_OK;
|
||||
}
|
||||
|
||||
xfree(packet);
|
||||
return READ_PUBKEY_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emulation of a key ring with only one public key.
|
||||
*/
|
||||
static PACKET *_pubkey_packet;
|
||||
|
||||
|
||||
|
||||
/********************************************
|
||||
** Implementation of the public interface **
|
||||
********************************************/
|
||||
|
||||
enum Gnupg_verify_result gnupg_verify_detached_signature(char const *pubkey_path,
|
||||
char const *data_path,
|
||||
char const *sig_path)
|
||||
{
|
||||
/*
|
||||
* Obtain pointer to public-key packet. The packet is allocated by
|
||||
* 'read_pubkey_from_file' and freed by 'verify_signatures'.
|
||||
*/
|
||||
switch (read_pubkey_from_file(pubkey_path, &_pubkey_packet)) {
|
||||
case READ_PUBKEY_OK: break;
|
||||
case READ_PUBKEY_MISSING_FILE: return GNUPG_VERIFY_PUBKEY_UNAVAILABLE;
|
||||
case READ_PUBKEY_INVALID_FORMAT: return GNUPG_VERIFY_PUBKEY_INVALID;
|
||||
};
|
||||
|
||||
/*
|
||||
* Set up the GnuPG control context, which is normally the job of
|
||||
* 'gpg_init_default_ctrl'.
|
||||
*/
|
||||
struct server_control_s control;
|
||||
memset(&control, 0, sizeof(control));
|
||||
ctrl_t ctrl = &control;
|
||||
ctrl->magic = SERVER_CONTROL_MAGIC;
|
||||
|
||||
opt.quiet = 1; /* prevent disclaimer about key compliance */
|
||||
|
||||
/*
|
||||
* Remember 'g10_errors_seen' before calling into GnuPG to obtain the
|
||||
* feedback about the success of the signature verification.
|
||||
*/
|
||||
int const orig_errors_seen = g10_errors_seen;
|
||||
|
||||
/*
|
||||
* Call into GnuPG to verify the data with a detached signature. The
|
||||
* 'verify_signatures' function indirectly calls 'get_pubkey' and
|
||||
* 'get_pubkeyblock', which hand out our '_pubkey_packet'.
|
||||
*/
|
||||
char *file_names[2] = { strdup(sig_path), strdup(data_path) };
|
||||
verify_signatures(ctrl, 2, file_names);
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
free(file_names[i]);
|
||||
|
||||
return (orig_errors_seen == g10_errors_seen) ? GNUPG_VERIFY_OK
|
||||
: GNUPG_VERIFY_SIGNATURE_INVALID;
|
||||
}
|
||||
|
||||
|
||||
int get_pubkey(ctrl_t ctrl, PKT_public_key *pk, u32 *keyid)
|
||||
{
|
||||
copy_public_key(pk, _pubkey_packet->pkt.public_key);
|
||||
pk->flags.valid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
kbnode_t get_pubkeyblock(ctrl_t ctrl, u32 *keyid)
|
||||
{
|
||||
return new_kbnode(_pubkey_packet);
|
||||
}
|
||||
|
33
repos/ports/src/app/verify/gnupg.h
Normal file
33
repos/ports/src/app/verify/gnupg.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* \brief Interface used for invoking GnuPG code
|
||||
* \author Norman Feske
|
||||
* \date 2018-01-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _GNUPG_H_
|
||||
#define _GNUPG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum Gnupg_verify_result { GNUPG_VERIFY_OK,
|
||||
GNUPG_VERIFY_PUBKEY_UNAVAILABLE,
|
||||
GNUPG_VERIFY_PUBKEY_INVALID,
|
||||
GNUPG_VERIFY_SIGNATURE_INVALID };
|
||||
|
||||
enum Gnupg_verify_result gnupg_verify_detached_signature(char const *pubkey_path,
|
||||
char const *data_path,
|
||||
char const *sig_path);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _GNUPG_H_ */
|
104
repos/ports/src/app/verify/main.cc
Normal file
104
repos/ports/src/app/verify/main.cc
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* \brief Tool for verifying detached signatures
|
||||
* \author Norman Feske
|
||||
* \date 2018-01-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <os/reporter.h>
|
||||
|
||||
/* local includes */
|
||||
#include <gnupg.h>
|
||||
|
||||
namespace Verify {
|
||||
using namespace Genode;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
struct Verify::Main
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
bool _verbose = false;
|
||||
|
||||
Constructible<Reporter> _reporter { };
|
||||
|
||||
typedef String<256> Path;
|
||||
typedef String<64> Message;
|
||||
|
||||
static Message _message(Gnupg_verify_result result)
|
||||
{
|
||||
switch(result) {
|
||||
case GNUPG_VERIFY_OK: return Message("good signature");
|
||||
case GNUPG_VERIFY_PUBKEY_UNAVAILABLE: return Message("public key unavailable");
|
||||
case GNUPG_VERIFY_PUBKEY_INVALID: return Message("malformed public key");
|
||||
case GNUPG_VERIFY_SIGNATURE_INVALID: return Message("bad signature");
|
||||
};
|
||||
return Message();
|
||||
}
|
||||
|
||||
void _process_verify_node(Xml_node, Xml_generator &);
|
||||
void _handle_config_with_libc();
|
||||
void _handle_config() { Libc::with_libc([&] () { _handle_config_with_libc(); }); }
|
||||
|
||||
Signal_handler<Main> _config_handler { _env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_config.sigh(_config_handler);
|
||||
_handle_config();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Verify::Main::_process_verify_node(Xml_node node, Xml_generator &xml)
|
||||
{
|
||||
Path const data_path = node.attribute_value("path", Path());
|
||||
Path const pubkey_path = node.attribute_value("pubkey", Path());
|
||||
|
||||
Gnupg_verify_result const result =
|
||||
gnupg_verify_detached_signature(pubkey_path.string(),
|
||||
data_path.string(),
|
||||
Path(data_path, ".sig").string());
|
||||
if (_verbose)
|
||||
log(data_path, ": ", _message(result));
|
||||
|
||||
bool const success = (result == GNUPG_VERIFY_OK);
|
||||
xml.node(success ? "good" : "bad", [&] () {
|
||||
xml.attribute("path", data_path);
|
||||
if (!success)
|
||||
xml.attribute("reason", _message(result));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Verify::Main::_handle_config_with_libc()
|
||||
{
|
||||
Xml_node const config = _config.xml();
|
||||
|
||||
_verbose = _config.xml().attribute_value("verbose", false);
|
||||
|
||||
if (!_reporter.constructed()) {
|
||||
_reporter.construct(_env, "result");
|
||||
_reporter->enabled(true);
|
||||
}
|
||||
|
||||
Reporter::Xml_generator xml(*_reporter, [&] () {
|
||||
config.for_each_sub_node("verify", [&] (Xml_node node) {
|
||||
_process_verify_node(node, xml); }); });
|
||||
}
|
||||
|
||||
|
||||
void Libc::Component::construct(Libc::Env &env) { static Verify::Main main(env); }
|
38
repos/ports/src/app/verify/target.mk
Normal file
38
repos/ports/src/app/verify/target.mk
Normal file
@ -0,0 +1,38 @@
|
||||
TARGET = verify
|
||||
SRC_CC = main.cc
|
||||
LIBS = base libc pthread libgcrypt
|
||||
|
||||
GNUPG_SRC_DIR := $(call select_from_ports,gnupg)/src/app/gnupg/g10
|
||||
|
||||
INC_DIR += $(PRG_DIR) $(GNUPG_SRC_DIR)
|
||||
|
||||
SRC_C := gnupg.c dummies.c
|
||||
|
||||
# source codes from GnuPG
|
||||
SRC_C += verify.c armor.c iobuf.c stringhelp.c progress.c strlist.c \
|
||||
cpr.c status.c mainproc.c sig-check.c keyid.c kbnode.c parse-packet.c \
|
||||
misc.c logging.c compliance.c free-packet.c mdfilter.c plaintext.c \
|
||||
seskey.c pkglue.c openpgp-oid.c
|
||||
|
||||
CC_OPT += -DGPGRT_ENABLE_ES_MACROS \
|
||||
-DHAVE_ISASCII \
|
||||
-DHAVE_FSEEKO \
|
||||
-DHAVE_SIGNAL_H \
|
||||
-DGNUPG_NAME='"GnuPG"' \
|
||||
-DPRINTABLE_OS_NAME='"Genode"' \
|
||||
-DVERSION='"$(< $(GNUPG_SRC_DIR)/../VERSION)"' \
|
||||
-DGPG_USE_RSA
|
||||
|
||||
CC_OPT_armor += -Wno-pointer-sign
|
||||
CC_OPT_iobuf += -Wno-pointer-sign
|
||||
CC_OPT_stringhelp += -Wno-pointer-sign
|
||||
CC_OPT_progress += -Wno-pointer-sign
|
||||
CC_OPT_mainproc += -Wno-pointer-sign
|
||||
CC_OPT_sig-check += -Wno-pointer-sign
|
||||
CC_OPT_parse-packet += -Wno-pointer-sign
|
||||
CC_OPT_misc += -DSCDAEMON_NAME='"scdaemon"' -DEXTSEP_S='"."' -DPATHSEP_S='";"'
|
||||
|
||||
vpath gnupg.c $(PRG_DIR)
|
||||
vpath dummies.c $(PRG_DIR)
|
||||
vpath %.c $(GNUPG_SRC_DIR)
|
||||
vpath %.c $(GNUPG_SRC_DIR)/../common
|
1
repos/ports/src/app/verify/test/expect_invalid.txt
Normal file
1
repos/ports/src/app/verify/test/expect_invalid.txt
Normal file
@ -0,0 +1 @@
|
||||
Streifenhoernchen sind lecker
|
BIN
repos/ports/src/app/verify/test/expect_invalid.txt.sig
Normal file
BIN
repos/ports/src/app/verify/test/expect_invalid.txt.sig
Normal file
Binary file not shown.
1
repos/ports/src/app/verify/test/expect_valid.txt
Normal file
1
repos/ports/src/app/verify/test/expect_valid.txt
Normal file
@ -0,0 +1 @@
|
||||
Kinder moegen Suessigkeiten
|
BIN
repos/ports/src/app/verify/test/expect_valid.txt.sig
Normal file
BIN
repos/ports/src/app/verify/test/expect_valid.txt.sig
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user