eclass/verify-sig: Sync with gentoo

It's from gentoo commit 347c196669c9272cbc67836c9ddb8ccefa338c18.
This commit is contained in:
Krzesimir Nowak 2022-03-09 20:28:04 +01:00
parent b076f42d73
commit 9458c28090

View File

@ -1,10 +1,10 @@
# Copyright 2020 Gentoo Authors # Copyright 2020-2022 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# @ECLASS: verify-sig.eclass # @ECLASS: verify-sig.eclass
# @MAINTAINER: # @MAINTAINER:
# Michał Górny <mgorny@gentoo.org> # Michał Górny <mgorny@gentoo.org>
# @SUPPORTED_EAPIS: 7 # @SUPPORTED_EAPIS: 7 8
# @BLURB: Eclass to verify upstream signatures on distfiles # @BLURB: Eclass to verify upstream signatures on distfiles
# @DESCRIPTION: # @DESCRIPTION:
# verify-sig eclass provides a streamlined approach to verifying # verify-sig eclass provides a streamlined approach to verifying
@ -20,7 +20,15 @@
# signatures to SRC_URI and set VERIFY_SIG_OPENPGP_KEY_PATH. The eclass # signatures to SRC_URI and set VERIFY_SIG_OPENPGP_KEY_PATH. The eclass
# provides verify-sig USE flag to toggle the verification. # provides verify-sig USE flag to toggle the verification.
# #
# If you need to use signify, you may want to copy distfiles into WORKDIR to
# work around "Too many levels of symbolic links" error.
#
# A more complete guide can be found at:
# https://mgorny.pl/articles/verify-sig-by-example.html
#
# @EXAMPLE:
# Example use: # Example use:
#
# @CODE # @CODE
# inherit verify-sig # inherit verify-sig
# #
@ -29,18 +37,12 @@
# BDEPEND=" # BDEPEND="
# verify-sig? ( app-crypt/openpgp-keys-example )" # verify-sig? ( app-crypt/openpgp-keys-example )"
# #
# VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/example.asc # VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/example.asc
# @CODE # @CODE
case "${EAPI:-0}" in case ${EAPI} in
0|1|2|3|4|5|6) 7|8) ;;
die "Unsupported EAPI=${EAPI} (obsolete) for ${ECLASS}" *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
;;
7)
;;
*)
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
;;
esac esac
EXPORT_FUNCTIONS src_unpack EXPORT_FUNCTIONS src_unpack
@ -49,11 +51,30 @@ if [[ ! ${_VERIFY_SIG_ECLASS} ]]; then
IUSE="verify-sig" IUSE="verify-sig"
BDEPEND=" # @ECLASS-VARIABLE: VERIFY_SIG_METHOD
verify-sig? ( # @PRE_INHERIT
app-crypt/gnupg # @DESCRIPTION:
>=app-portage/gemato-16 # Signature verification method to use. The allowed value are:
)" #
# - openpgp -- verify PGP signatures using app-crypt/gnupg (the default)
# - signify -- verify signatures with Ed25519 public key using app-crypt/signify
: ${VERIFY_SIG_METHOD:=openpgp}
case ${VERIFY_SIG_METHOD} in
openpgp)
BDEPEND="
verify-sig? (
app-crypt/gnupg
>=app-portage/gemato-16
)"
;;
signify)
BDEPEND="verify-sig? ( app-crypt/signify )"
;;
*)
die "${ECLASS}: unknown method '${VERIFY_SIG_METHOD}'"
;;
esac
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_PATH # @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_PATH
# @DEFAULT_UNSET # @DEFAULT_UNSET
@ -61,6 +82,9 @@ BDEPEND="
# Path to key bundle used to perform the verification. This is required # Path to key bundle used to perform the verification. This is required
# when using default src_unpack. Alternatively, the key path can be # when using default src_unpack. Alternatively, the key path can be
# passed directly to the verification functions. # passed directly to the verification functions.
#
# NB: this variable is also used for non-OpenPGP signatures. The name
# contains "OPENPGP" for historical reasons.
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEYSERVER # @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEYSERVER
# @DEFAULT_UNSET # @DEFAULT_UNSET
@ -68,6 +92,8 @@ BDEPEND="
# Keyserver used to refresh keys. If not specified, the keyserver # Keyserver used to refresh keys. If not specified, the keyserver
# preference from the key will be respected. If no preference # preference from the key will be respected. If no preference
# is specified by the key, the GnuPG default will be used. # is specified by the key, the GnuPG default will be used.
#
# Supported for OpenPGP only.
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_REFRESH # @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_REFRESH
# @USER_VARIABLE # @USER_VARIABLE
@ -75,6 +101,8 @@ BDEPEND="
# Attempt to refresh keys via WKD/keyserver. Set it to "yes" # Attempt to refresh keys via WKD/keyserver. Set it to "yes"
# in make.conf to enable. Note that this requires working Internet # in make.conf to enable. Note that this requires working Internet
# connection. # connection.
#
# Supported for OpenPGP only.
: ${VERIFY_SIG_OPENPGP_KEY_REFRESH:=no} : ${VERIFY_SIG_OPENPGP_KEY_REFRESH:=no}
# @FUNCTION: verify-sig_verify_detached # @FUNCTION: verify-sig_verify_detached
@ -94,9 +122,14 @@ verify-sig_verify_detached() {
local extra_args=() local extra_args=()
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R ) [[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R )
[[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=( if [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]]; then
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}" [[ ${VERIFY_SIG_METHOD} == openpgp ]] ||
) die "${FUNCNAME}: VERIFY_SIG_OPENPGP_KEYSERVER is not supported"
extra_args+=(
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
)
fi
# GPG upstream knows better than to follow the spec, so we can't # GPG upstream knows better than to follow the spec, so we can't
# override this directory. However, there is a clean fallback # override this directory. However, there is a clean fallback
@ -106,9 +139,17 @@ verify-sig_verify_detached() {
local filename=${file##*/} local filename=${file##*/}
[[ ${file} == - ]] && filename='(stdin)' [[ ${file} == - ]] && filename='(stdin)'
einfo "Verifying ${filename} ..." einfo "Verifying ${filename} ..."
gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \ case ${VERIFY_SIG_METHOD} in
gpg --verify "${sig}" "${file}" || openpgp)
die "PGP signature verification failed" gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
gpg --verify "${sig}" "${file}" ||
die "PGP signature verification failed"
;;
signify)
signify -V -p "${key}" -m "${file}" -x "${sig}" ||
die "Signify signature verification failed"
;;
esac
} }
# @FUNCTION: verify-sig_verify_message # @FUNCTION: verify-sig_verify_message
@ -130,9 +171,14 @@ verify-sig_verify_message() {
local extra_args=() local extra_args=()
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R ) [[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R )
[[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=( if [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]]; then
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}" [[ ${VERIFY_SIG_METHOD} == openpgp ]] ||
) die "${FUNCNAME}: VERIFY_SIG_OPENPGP_KEYSERVER is not supported"
extra_args+=(
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
)
fi
# GPG upstream knows better than to follow the spec, so we can't # GPG upstream knows better than to follow the spec, so we can't
# override this directory. However, there is a clean fallback # override this directory. However, there is a clean fallback
@ -142,30 +188,42 @@ verify-sig_verify_message() {
local filename=${file##*/} local filename=${file##*/}
[[ ${file} == - ]] && filename='(stdin)' [[ ${file} == - ]] && filename='(stdin)'
einfo "Verifying ${filename} ..." einfo "Verifying ${filename} ..."
gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \ case ${VERIFY_SIG_METHOD} in
gpg --verify --output="${output_file}" "${file}" || openpgp)
die "PGP signature verification failed" gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
gpg --verify --output="${output_file}" "${file}" ||
die "PGP signature verification failed"
;;
signify)
signify -V -e -p "${key}" -m "${output_file}" -x "${file}" ||
die "Signify signature verification failed"
;;
esac
} }
# @FUNCTION: verify-sig_verify_signed_checksums # @FUNCTION: verify-sig_verify_unsigned_checksums
# @USAGE: <checksum-file> <algo> <files> [<key-file>] # @USAGE: <checksum-file> <algo> <files>
# @DESCRIPTION: # @DESCRIPTION:
# Verify the checksums for all files listed in the space-separated list # Verify the checksums for all files listed in the space-separated list
# <files> (akin to ${A}) using a PGP-signed <checksum-file>. <algo> # <files> (akin to ${A}) using a <checksum-file>. <algo> specifies
# specified the checksum algorithm (e.g. sha256). <key-file> can either # the checksum algorithm (e.g. sha256). <checksum-file> can be "-"
# be passed directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH. # for stdin.
# #
# The function dies if PGP verification fails, the checksum file # The function dies if one of the files does not match checksums or
# contains unsigned data, one of the files do not match checksums # is missing from the checksum file.
# or are missing from the checksum file. #
verify-sig_verify_signed_checksums() { # Note that this function itself can only verify integrity of the files.
# In order to verify their authenticity, the <checksum-file> must
# be verified against a signature first, e.g. using
# verify-sig_verify_detached. If it contains inline signature, use
# verify-sig_verify_signed_checksums instead.
verify-sig_verify_unsigned_checksums() {
local checksum_file=${1} local checksum_file=${1}
local algo=${2} local algo=${2}
local files=() local files=()
read -r -d '' -a files <<<"${3}" read -r -d '' -a files <<<"${3}"
local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
local chksum_prog chksum_len local chksum_prog chksum_len
case ${algo} in case ${algo} in
sha256) sha256)
chksum_prog=sha256sum chksum_prog=sha256sum
@ -176,11 +234,13 @@ verify-sig_verify_signed_checksums() {
;; ;;
esac esac
[[ -n ${key} ]] || [[ ${checksum_file} == - ]] && checksum_file=/dev/stdin
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
local checksum filename junk ret=0 count=0 local checksum filename junk ret=0 count=0
while read -r checksum filename junk; do while read -r checksum filename junk; do
if [[ ${checksum} == "-----BEGIN" ]]; then
die "${FUNCNAME}: PGP armor found, use verify-sig_verify_signed_checksums instead"
fi
[[ ${#checksum} -eq ${chksum_len} ]] || continue [[ ${#checksum} -eq ${chksum_len} ]] || continue
[[ -z ${checksum//[0-9a-f]} ]] || continue [[ -z ${checksum//[0-9a-f]} ]] || continue
has "${filename}" "${files[@]}" || continue has "${filename}" "${files[@]}" || continue
@ -192,7 +252,7 @@ verify-sig_verify_signed_checksums() {
else else
ret=1 ret=1
fi fi
done < <(verify-sig_verify_message "${checksum_file}" - "${key}") done < "${checksum_file}"
[[ ${ret} -eq 0 ]] || [[ ${ret} -eq 0 ]] ||
die "${FUNCNAME}: at least one file did not verify successfully" die "${FUNCNAME}: at least one file did not verify successfully"
@ -200,6 +260,56 @@ verify-sig_verify_signed_checksums() {
die "${FUNCNAME}: checksums for some of the specified files were missing" die "${FUNCNAME}: checksums for some of the specified files were missing"
} }
# @FUNCTION: _gpg_verify_signed_checksums
# @INTERNAL
# @USAGE: <checksum-file> <algo> <files> [<key-file>]
# @DESCRIPTION:
# GnuPG-specific function to verify a signed checksums list.
_gpg_verify_signed_checksums() {
local checksum_file=${1}
local algo=${2}
local files=${3}
local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
verify-sig_verify_unsigned_checksums - "${algo}" "${files}" < <(
verify-sig_verify_message "${checksum_file}" - "${key}"
)
}
# @FUNCTION: verify-sig_verify_signed_checksums
# @USAGE: <checksum-file> <algo> <files> [<key-file>]
# @DESCRIPTION:
# Verify the checksums for all files listed in the space-separated list
# <files> (akin to ${A}) using a signed <checksum-file>. <algo> specifies
# the checksum algorithm (e.g. sha256). <key-file> can either be passed
# directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH.
#
# The function dies if signature verification fails, the checksum file
# contains unsigned data, one of the files do not match checksums or
# are missing from the checksum file.
verify-sig_verify_signed_checksums() {
local checksum_file=${1}
local algo=${2}
local files=()
read -r -d '' -a files <<<"${3}"
local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
[[ -n ${key} ]] ||
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
case ${VERIFY_SIG_METHOD} in
openpgp)
_gpg_verify_signed_checksums \
"${checksum_file}" "${algo}" "${files[@]}" "${key}"
;;
signify)
signify -C -p "${key}" \
-x "${checksum_file}" "${files[@]}" ||
die "Signify signature verification failed"
;;
esac
}
# @FUNCTION: verify-sig_src_unpack # @FUNCTION: verify-sig_src_unpack
# @DESCRIPTION: # @DESCRIPTION:
# Default src_unpack override that verifies signatures for all # Default src_unpack override that verifies signatures for all