#!/bin/bash

## Copyright (C) 2019 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

# shellcheck source=../libexec/helper-scripts/check_runtime.bsh
source "${HELPER_SCRIPTS_PATH:-}"/usr/libexec/helper-scripts/check_runtime.bsh

if was_executed "${BASH_SOURCE[0]}"; then
  shim_signed_mok_setup_sourced='false'
else
  shim_signed_mok_setup_sourced='true'
fi

if [ "${shim_signed_mok_setup_sourced}" = 'false' ]; then
  set -o errexit
  set -o nounset
  set -o errtrace
  set -o pipefail

  # shellcheck source=../libexec/helper-scripts/log_run_die.sh
  source "${HELPER_SCRIPTS_PATH:-}"/usr/libexec/helper-scripts/log_run_die.sh

  # shellcheck source=../libexec/helper-scripts/as_root.sh
  source "${HELPER_SCRIPTS_PATH:-}"/usr/libexec/helper-scripts/as_root.sh

  # shellcheck source=../libexec/helper-scripts/has.sh
  source "${HELPER_SCRIPTS_PATH:-}"/usr/libexec/helper-scripts/has.sh
fi

dkms_mok_variables_set() {
  ## NOTE: This function is 'source'ed by other scripts. It should stay simple.
  ##       I.e. it should not depend to 'source' other scripts.
  dkms_mok_dir='/var/lib/dkms'
  dkms_mok_public_file="${dkms_mok_dir}/mok.pub"
  dkms_mok_private_file="${dkms_mok_dir}/mok.key"
  shim_mok_dir='/var/lib/shim-signed/mok'
  shim_mok_public_file="${shim_mok_dir}/MOK.der"
  shim_mok_private_file="${shim_mok_dir}/MOK.priv"
}

shim_signed_mok_setup() {
  local dkms_mok_public_file dkms_mok_private_file \
    shim_mok_dir shim_mok_public_file shim_mok_private_file \
    mok_keys_present third_party_kernel_module_warning

  as_root
  dkms_mok_variables_set

  mok_keys_present='n'
  third_party_kernel_module_warning="

Note: This script does not enable Secure Boot.
If Secure Boot is enabled on this computer, some optional drivers or features
that rely on non-mainline kernel modules may not load until they are properly signed.
More information:
https://www.kicksecure.com/wiki/Secure_Boot"

  log notice "Preparing Secure Boot module-signing keys (used only if Secure Boot is enabled)..."
  log notice "See also:"
  printf '%s\n' "https://www.kicksecure.com/wiki/Secure_Boot"
  log notice "Expected DKMS key files: '${dkms_mok_public_file}' and '${dkms_mok_private_file}'"
  log notice "Expected shim key links: '${shim_mok_public_file}' and '${shim_mok_private_file}'"

  if ! has dkms; then
    log error "The 'dkms' tool is not available, so keys cannot be prepared.${third_party_kernel_module_warning}"
    return 1
  fi

  if [ -f "${dkms_mok_public_file}" ] && [ -f "${dkms_mok_private_file}" ]; then
    log notice "Key files already exist: yes"
    mok_keys_present='y'
  else
    log notice "Key files already exist: no - trying to create them using 'dkms generate_mok'..."
    if log_run notice dkms generate_mok; then
      if [ -f "${dkms_mok_public_file}" ] && [ -f "${dkms_mok_private_file}" ]; then
        mok_keys_present='y'
        log notice "Key files created: yes"
      else
        log error "The command 'dkms generate_mok' reported success, but the expected key files were not found afterwards:"
        log error "Missing one or both of: '${dkms_mok_public_file}', '${dkms_mok_private_file}'.${third_party_kernel_module_warning}"
        return 1
      fi
    else
      log error "The command 'dkms generate_mok' failed, so the key files could not be created.${third_party_kernel_module_warning}"
      return 1
    fi
  fi

  if [ "${mok_keys_present}" != 'y' ]; then
    log error "Key files are still missing, so setup cannot continue."
    log error "Expected: '${dkms_mok_public_file}' and '${dkms_mok_private_file}'.${third_party_kernel_module_warning}"
    return 1
  fi

  if ! mkdir --parents -- "${shim_mok_dir}"; then
    log error "Could not create the folder '${shim_mok_dir}'.${third_party_kernel_module_warning}"
    return 1
  fi

  if ! test -L "${shim_mok_public_file}"; then
    if ! ln -s -- "${dkms_mok_public_file}" "${shim_mok_public_file}"; then
      log error "Could not create the symlink '${shim_mok_public_file}' -> '${dkms_mok_public_file}'.${third_party_kernel_module_warning}"
      return 1
    fi
  fi

  if ! test -L "${shim_mok_private_file}"; then
    if ! ln -s -- "${dkms_mok_private_file}" "${shim_mok_private_file}"; then
      log error "Could not create the symlink '${shim_mok_private_file}' -> '${dkms_mok_private_file}'.${third_party_kernel_module_warning}"
      return 1
    fi
  fi

  log notice "Key links are in place: yes"
  #log notice "'${shim_mok_public_file}' (should link to '${dkms_mok_public_file}')"
  #log notice "'${shim_mok_private_file}' (should link to '${dkms_mok_private_file}')"

  log notice "Successfully prepared Secure Boot module-signing keys/links."
}

if [ "${shim_signed_mok_setup_sourced}" = 'false' ]; then
  shim_signed_mok_setup
fi
