#!/bin/bash
# shellcheck disable=SC2155

## Get FIPS module HMAC key
generate_fips_hmac_key () {
	echo -n 'Synology Cryptographic Module' | openssl sha256 | cut -d' ' -f2
}

## Check and regenerate FIPS module config
##
## - `module-mac` may be changed if we stripped so file
## - `install-version`, `install-status` and `install-mac` are generated by
##   `openssl fipsinstall` command in the theory.
##   To make all simple, we just generate it here and use SynoCI to ensure it is correct.
install_fips_config () {
	local inst_dir="$1"
	local fips_key=$(generate_fips_hmac_key)

	local module_path="$inst_dir/usr/lib/openssl-3/ossl-modules/fips.so"
	local config_path="${inst_dir}/etc/ssl/openssl-3/fipsmodule.cnf"
	local temp_path="${inst_dir}/etc/ssl/openssl-3/fipsmodule.cnf.tmp"

	# fields
	local fields=(activate install-version conditional-errors security-checks module-mac install-mac install-status)

	# predefined
	# shellcheck disable=SC2034
	local install_version=1
	local install_status='INSTALL_SELF_TEST_KATS_RUN'

	# MAC
	# shellcheck disable=SC2034
	local module_mac=$(openssl sha256 -c -hex -mac HMAC -macopt "hexkey:${fips_key}" < "${module_path}" |
	      cut -d' ' -f2 | tr '[:lower:]' '[:upper:]')
	# shellcheck disable=SC2034
	local install_mac=$(echo -n "${install_status}" |
	      openssl sha256 -c -hex -mac HMAC -macopt "hexkey:${fips_key}" |
	      cut -d' ' -f2 | tr '[:lower:]' '[:upper:]')

	# write config
	echo '[fips_sect]' > "${temp_path}"
	for name in "${fields[@]}"; do
		local variable_name="${name//-/_}"
		local value="${!variable_name}"

		if [[ -z "${value}" ]]; then
			value=$(grep -oP "(?<=${name} = ).+" "${config_path}")
		fi
		if [[ -z "${value}" ]]; then
			echo "Error: Failed to get '${name}' value" >&2
			exit 1
		fi
		echo "${name} = ${value}" >> "${temp_path}"
	done

	mv "${temp_path}" "${config_path}"
}

## Move some files around
rename_openssl3 () {
	local inst_dir="$1"

	# binary
	# TODO: remove if default changes to v3
	if [ -e "${inst_dir}/usr/bin" ]; then
		mv "${inst_dir}/usr/bin/openssl" "${inst_dir}/usr/bin/openssl-3"
	fi

	# library
	if [ -e "${inst_dir}/usr/lib/openssl-3" ]; then
		mv "${inst_dir}/usr/lib/openssl-3"/*.so.* "${inst_dir}/usr/lib/"
		ln -sf ../libcrypto.so.3 "${inst_dir}/usr/lib/openssl-3/libcrypto.so"
		ln -sf ../libssl.so.3 "${inst_dir}/usr/lib/openssl-3/libssl.so"
	fi

	# headers
	if [ -e "${inst_dir}/usr/include/openssl" ]; then
		install -dm755 "${inst_dir}/usr/include/openssl-3"
		mv "${inst_dir}/usr/include/openssl" "${inst_dir}/usr/include/openssl-3/"
	fi

	# pkgconfig
	if [ -e "${inst_dir}/usr/lib/openssl-3/pkgconfig" ]; then
		sed -e 's|/include$|/include/openssl-3|' \
		    -e 's|libssl|libssl-3|'              \
		    -e 's|libcrypto|libcrypto-3|'        \
		    -i "${inst_dir}/usr/lib/openssl-3/pkgconfig"/*.pc

		install -dm755 "${inst_dir}/usr/lib/pkgconfig"
		for pc in openssl libcrypto libssl; do
			ln -sf "../openssl-3/pkgconfig/${pc}.pc" "${inst_dir}/usr/lib/pkgconfig/${pc}-3.pc"
		done
	fi

	# config
	# FIXME: remove this block after `openssldir` changes to `/etc/ssl`.
	if [ -e "${inst_dir}/etc/ssl/openssl-3" ]; then
		ln -sf ../certs "${inst_dir}/etc/ssl/openssl-3/certs"
	fi
}
