diff --git a/Makefile-tests.am b/Makefile-tests.am index 5498fd4317..0abfaa3912 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -134,6 +134,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh \ tests/test-config.sh \ + tests/test-signed-commit.sh \ $(NULL) if USE_GPGME diff --git a/tests/libtest.sh b/tests/libtest.sh index 8832e63ccc..d3db678f8e 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -652,6 +652,16 @@ which_gpg () { echo ${gpg} } +has_libsodium () { + local ret + ${CMD_PREFIX} ostree --version > version.txt + grep -q -e '- libsodium' version.txt + ret=$? + rm -f version.txt + return ${ret} +} + + libtest_cleanup_gpg () { local gpg_homedir=${1:-${test_tmpdir}/gpghome} gpg-connect-agent --homedir "${gpg_homedir}" killagent /bye || true diff --git a/tests/test-signed-commit.sh b/tests/test-signed-commit.sh new file mode 100755 index 0000000000..08993c60fa --- /dev/null +++ b/tests/test-signed-commit.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# +# Copyright (C) 2019 Collabora Ltd. +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +echo "1..6" + +mkdir ${test_tmpdir}/repo +ostree_repo_init repo --mode="archive" + +echo "Unsigned commit" > file.txt +${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo commit -b main -s 'Unsigned commit' +COMMIT="$(ostree --repo=${test_tmpdir}/repo rev-parse main)" + +# Test `ostree sign` with dummy module first +DUMMYSIGN="dummysign" +${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=dummy ${COMMIT} ${DUMMYSIGN} + +# Ensure that detached metadata really contain expected string +EXPECTEDSIGN="$(echo $DUMMYSIGN | hexdump -n 9 -e '8/1 "0x%.2x, " 1/1 " 0x%.2x"')" +${CMD_PREFIX} ostree --repo=repo show ${COMMIT} --print-detached-metadata-key=ostree.sign.dummy | grep -q -e "${EXPECTEDSIGN}" +echo "ok Detached dummy signature added" + +# Verify vith sign mechanism +${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=dummy --verify ${COMMIT} ${DUMMYSIGN} +echo "ok dummy signature verified" + +echo "Signed commit with dummy key: ${DUMMYSIGN}" >> file.txt +${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo commit -b main -s 'Signed with dummy module' --sign=${DUMMYSIGN} --sign-type=dummy +COMMIT="$(ostree --repo=${test_tmpdir}/repo rev-parse main)" +${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=dummy --verify ${COMMIT} ${DUMMYSIGN} +echo "ok commit with dummy signing" + +# Test ostree sign with 'ed25519' module +# Generate private key in PEM format +PEMFILE="$(mktemp -p ${test_tmpdir} ed25519_XXXXXX.pem)" +openssl genpkey -algorithm ed25519 -outform PEM -out "${PEMFILE}" + +# tests below require libsodium support +if has_libsodium; then + # Based on: http://openssl.6102.n7.nabble.com/ed25519-key-generation-td73907.html + # Extract the private and public parts from generated key. + PUBLIC="$(openssl pkey -outform DER -pubout -in ${PEMFILE} | hexdump -s 12 -e '16/1 "%.2x"')" + SEED="$(openssl pkey -outform DER -in ${PEMFILE} | hexdump -s 16 -e '16/1 "%.2x"')" + # Secret key is concantination of SEED and PUBLIC + SECRET="${SEED}${PUBLIC}" + + echo "SEED = $SEED" + echo "PUBLIC = $PUBLIC" + + echo "Signed commit with ed25519: ${SECRET}" >> file.txt + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo commit -b main -s "Signed with ed25519 module" --sign=${SECRET} --sign-type=ed25519 + COMMIT="$(ostree --repo=${test_tmpdir}/repo rev-parse main)" + + # Ensure that detached metadata contain signature + ${CMD_PREFIX} ostree --repo=repo show ${COMMIT} --print-detached-metadata-key=ostree.sign.ed25519 &>/dev/null + echo "ok Detached ed25519 signature added" + + # Verify vith sign mechanism + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --verify --sign-type=ed25519 ${COMMIT} ${PUBLIC} + echo "ok ed25519 signature verified" + + # Check if we able to use all available modules to sign the same commit + echo "Unsigned commit for multi-sign" >> file.txt + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo commit -b main -s 'Unsigned commit' + COMMIT="$(ostree --repo=${test_tmpdir}/repo rev-parse main)" + # Check if we have no signatures + for mod in "dummy" "ed25519"; do + if ostree --repo=repo show ${COMMIT} --print-detached-metadata-key=ostree.sign.${mod}; then + echo "Unexpected signature for ${mod} found" + exit 1 + fi + done + + # Sign with all available modules + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=dummy ${COMMIT} ${DUMMYSIGN} + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=ed25519 ${COMMIT} ${SECRET} + # and verify + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --verify --sign-type=ed25519 ${COMMIT} ${PUBLIC} + ${CMD_PREFIX} ostree --repo=${test_tmpdir}/repo sign --sign-type=dummy --verify ${COMMIT} ${DUMMYSIGN} + echo "ok multiple signing " +else + echo "ok Detached ed25519 signature # SKIP due libsodium unavailability" + echo "ok ed25519 signature verified # SKIP due libsodium unavailability" + echo "ok multiple signing # SKIP due libsodium unavailability" +fi