#!/bin/sh

PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

# busybox

DIGSIG_ELF_MODE=0
DIGSIG_XATTR_MODE=0
DIGSIG_ELF_VERIFICATION_MODE=0
DIGSIG_IGNORE_XATTR_KEYS=0
DIGSIG_IGNORE_GOST2001=0

. /etc/digsig/digsig_initramfs.conf

modprobe digsig_verif

# Representation of the revoked list. The file contains
# sha1 checksums of keys separated with newline.
# Keys that are in the file are to be revoked.
DIGSIG_REVOKED_KEYS=/etc/digsig/revoked_keys

# Takes a single argument, a file, and checks whether
# a key containing in the file is in the revoked list.
# Returns 0 (true) if the key is in the list, 1 (false) otherwise.
to_check_for_revoked()
{
	# $1 represents a file containing a key which is being checked

	if [ -f "$DIGSIG_REVOKED_KEYS" ]; then
		key_id=$(sha1sum "$1" | awk -F' ' '{ print $1 }')

		if grep -Fxq "$key_id" "$DIGSIG_REVOKED_KEYS"; then
			echo "  $key_id found in $DIGSIG_REVOKED_KEYS."
			return 0 # Returns true; the key is in the revoked list
		else
			echo "  $key_id is not found in $DIGSIG_REVOKED_KEYS"
		fi
	else
		echo "  $DIGSIG_REVOKED_KEYS does not exist"
	fi

	return 1 # Returns false,
		 # meaning that the key is not in the revoked list
		 # or a file representing the revoked list does not exist at all
}

# Takes three arguments:
# $1	a folder where keys (actually files containing keys) are to be found
# $2 	a sysfs interface file. The file is used to propagate keys to the digsig
# 	module
# $3	can take a function name (only to_check_for_revoked is supported now).
# 	The function will be used to check whether a key has already been revoked
# 	before its loading to the digsig module (via the sysfs interface).
# 	If any key has been revoked, it won't be loaded to the module.
# 	The parameter can be empty. In this case this function won't check
# 	any keys and will always load them to the module.
descend()
{
	find "$1" -mindepth 1 -maxdepth 1 -type f | while read f; do
		if [ -n "$3" ]; then
			"$3" "$f"
			res=$?
			if [ "$res" -eq "0" ]; then
				# A key containing in the file $f has been revoked,
				# so it must not be loaded
				echo "  Loading of $f is rejected."
				continue
			fi
		fi

		echo "  loading $f"; cat "$f" > "$2" || sleep 3;
	done

	find "$1" -mindepth 1 -maxdepth 1 -type d | while read d; do descend "$d" "$2" "$3"; done
}

if [ "$DIGSIG_ELF_MODE" != "0" ]; then
	echo "Loading DIGSIG keys"
	DIR=/etc/digsig/keys

	cat /etc/digsig/build_system_rbt_root_key_2018.gpg \
	    > /sys/digsig/keys 2>/dev/null
	cat /etc/digsig/partners_rbt_root_key_2018.gpg \
	    > /sys/digsig/keys 2>/dev/null
	sleep 1

	descend $DIR /sys/digsig/keys to_check_for_revoked
fi

if [ "$DIGSIG_IGNORE_XATTR_KEYS" = "1" ]; then
	echo 1 > /sys/digsig/ignore_xattr_keys 2>/dev/null
fi

if [ "$DIGSIG_XATTR_MODE" != "0" ] || \
	[ "$DIGSIG_ELF_MODE" != "0" -a "$DIGSIG_ELF_VERIFICATION_MODE" != "0" ]; then
	echo "Loading DIGSIG xattr keys"
	DIR=/etc/digsig/xattr_keys

	descend $DIR /sys/digsig/xattr_keys to_check_for_revoked
fi

awk 1 /etc/digsig/xattr_control > /sys/digsig/xattr_control

if [ "$DIGSIG_ELF_MODE" != "0" ] || [ "$DIGSIG_XATTR_MODE" != "0" ]; then
	echo "Loading DIGSIG certs keys"
	DIR=/etc/digsig/certs

	descend $DIR /sys/digsig/certs to_check_for_revoked
fi

DIR=/etc/digsig/external_sig
if [ "$DIGSIG_ELF_MODE" != "0" -a -d $DIR ]; then
	if [ "`(cd $DIR; ls)`" != "" ]; then
		echo "Loading DIGSIG external signatures"
		descend $DIR /sys/digsig/external_sig
	fi
fi

if [ "$DIGSIG_ELF_MODE" != "0" ]; then
	echo "Switching DIGSIG into elf/xattr mode $DIGSIG_ELF_VERIFICATION_MODE"
	echo "$DIGSIG_ELF_VERIFICATION_MODE" > /sys/digsig/elf_verification_mode 2>/dev/null

	echo "Switching DIGSIG into mode $DIGSIG_ELF_MODE for ELF"
	echo "$DIGSIG_ELF_MODE" > /sys/digsig/elf_mode 2>/dev/null
fi
if [ "$DIGSIG_XATTR_MODE" != "0" ]; then
	echo "Switching DIGSIG into mode $DIGSIG_XATTR_MODE for XATTR"
	echo "$DIGSIG_XATTR_MODE" > /sys/digsig/xattr_mode 2>/dev/null
fi

if [ "$DIGSIG_IGNORE_GOST2001" = "1" ]; then
	echo "Making DIGSIG ignore GOST-2001 keys and signatures"
	echo 1 > /sys/digsig/ignore_gost2001 2>/dev/null
fi
