#!/bin/bash

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

source /usr/libexec/helper-scripts/get_colors.sh
source /usr/libexec/helper-scripts/secure_boot_enabled_check.bsh
source /usr/sbin/shim-signed-mok-setup

systemcheck_autostart_functions+=" check_build_mok_keys "

check_secure_boot() {
   local mokutil_present mokutil_output link_cli link_gui \
      mokutil_link_cli mokutil_link_gui MSG reason \
      secure_boot_enabled_check_retcode

   if [ "$silent" -ge "4" ]; then
      true "silent is $silent. Skipping ${FUNCNAME[0]}."
      return 0
   fi

   link_cli="https://www.kicksecure.com/wiki/Secure_Boot"
   link_gui="<a href=\"$link_cli\">Secure Boot</a>"
   mokutil_link_cli="https://www.kicksecure.com/wiki/Debian#Install_mokutil"
   mokutil_link_gui="<a href=\"$mokutil_link_cli\">mokutil installed</a>"

   if [ "$qubes_detected" = "true" ]; then
      reason="\
- Reason: Qubes detected.
<br/>- Known Qubes issue: <a href=\"https://github.com/QubesOS/qubes-issues/issues/5241\">https://github.com/QubesOS/qubes-issues/issues/5241</a>
<br/>- No need to report this."
   else
      reason="\
- Reason: Not booted in EFI (UEFI) mode. Secure Boot is only available in EFI (UEFI) mode."
   fi

   if ! [ -d /sys/firmware/efi ]; then
      MSG="<p>$link_gui: <font color=\"orange\">Unavailable</font>
<br/>
<br/>$reason</p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="Secure Boot: ${yellow}Unavailable${nocolor}

$reason
- See also: $link_cli"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      return 0
   fi

   mokutil_present='y'
   if ! command -v mokutil >/dev/null; then
      mokutil_present='n'
   fi

   ## 'check_secure_boot_enabled' internally uses 'mokutil'.
   secure_boot_enabled_check_retcode='0'
   mokutil_output="$(check_secure_boot_enabled 2>&1)" || secure_boot_enabled_check_retcode="$?"

   if [ "${secure_boot_enabled_check_retcode}" = '0' ]; then
      ## Used by 'check_tirdad_module.bsh'.
      secure_boot_status_enabled=true

      MSG="<p>$link_gui: <font color=\"green\">Enabled</font></p>"
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="Secure Boot: ${green}Enabled${nocolor}
See also: $link_cli"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   elif [ "${secure_boot_enabled_check_retcode}" = '1' ]; then
      secure_boot_status_enabled=false

      MSG="<p>$link_gui: <font color=\"orange\">Disabled</font></p>"
      $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="Secure Boot: ${yellow}Disabled${nocolor}
See also: $link_cli"
      $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   else
      MSG="<p>$link_gui: <font color=\"orange\">Unknown</font>
<br/>
<br/>Debugging information:
<br/>mokutil_output: '${mokutil_output}'</p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="Secure Boot: ${yellow}Unknown${nocolor}
See also: $link_cli
Debugging information:
mokutil_output: '${mokutil_output}'"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi

   if [ "${mokutil_present}" = 'y' ]; then
      MSG="<p>$mokutil_link_gui: <font color=\"green\">Yes</font></p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="mokutil installed: ${green}Yes${nocolor}
See also: $mokutil_link_cli"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   else
      MSG="<p>$mokutil_link_gui: <font color=\"orange\">No</font></p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="mokutil installed: ${yellow}No${nocolor}
See also: $mokutil_link_cli"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi

   ## sets: 'dkms_mok_*' variables
   dkms_mok_variables_set

   if [ -f "${dkms_mok_public_file}" ] \
      && [ -f "${dkms_mok_private_file}" ]; then
      MSG="<p>DKMS module signing keys present: <font color=\"green\">Yes</font></p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="DKMS module signing keys present: ${green}Yes${nocolor}"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"

      if [ "${secure_boot_status_enabled}" = 'true' ] \
         && [ "${mokutil_present}" = 'y' ]; then
         ## Confusingly, 'mokutil --test-key' returns 1 if the key is already
         ## enrolled, and 0 if it is not.
         if ! mokutil_output="$(leaprun mokutil-test-key 2>&1)"; then
            if [ "${mokutil_output}" = '/var/lib/dkms/mok.pub is already enrolled' ]; then
               MSG="<p>DKMS module signing keys enrolled in firmware: <font color=\"green\">Yes</font></p>"
               output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

               MSG="DKMS module signing keys enrolled in firmware: ${green}Yes${nocolor}"
               output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
            else
               MSG="<p>DKMS module signing keys enrolled in firmware: <font color=\"orange\">Unknown</font>
<br/>
<br/>Debugging information:
<br/>mokutil output: '${mokutil_output}'</p>"
               output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

               MSG="DKMS module signing keys enrolled in firmware: ${yellow}Unknown${nocolor}
Debugging information:
mokutil output: '${mokutil_output}'"
               output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
            fi
         else
            MSG="<p>DKMS module signing keys enrolled in firmware: <font color=\"orange\">No</font></p>"
            output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

            MSG="DKMS module signing keys enrolled in firmware: ${yellow}No${nocolor}"
            output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
         fi
      fi
   else
      MSG="<p>DKMS module signing keys present: <font color=\"orange\">No</font></p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="DKMS module signing keys present: ${yellow}No${nocolor}"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi

   if [ -f "${shim_mok_public_file}" ] && [ -f "${shim_mok_private_file}" ]; then
      if [ -L "${shim_mok_public_file}" ] \
         && [ -L "${shim_mok_private_file}" ] \
         && [ "$(readlink "${shim_mok_public_file}")" = "${dkms_mok_public_file}" ] \
         && [ "$(readlink "${shim_mok_private_file}")" = "${dkms_mok_private_file}" ]; then
         MSG="<p>Shim module signing keys set up: <font color=\"green\">Yes</font></p>"
         output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

         MSG="Shim module signing keys set up: ${green}Yes${nocolor}"
         output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      else
         MSG="<p>Shim module signing keys status: <font color=\"orange\">Not symlinked to DKMS keys</font></p>"
         output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

         MSG="Shim module signing keys status: ${yellow}Not symlinked to DKMS keys${nocolor}"
         output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
      fi
   else
      MSG="<p>Shim module signing keys status: <font color=\"orange\">Absent</font></p>"
      output_if_verbose $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"

      MSG="Shim module signing keys status: ${yellow}Absent${nocolor}"
      output_if_verbose $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
   fi
}

check_build_mok_keys() {
   local MSG secure_boot_enabled_check_retcode check_image_builtin_mok_retcode

   check_image_builtin_mok_retcode='0'
   leaprun check-image-builtin-mok || check_image_builtin_mok_retcode="$?"

   if [ "${check_image_builtin_mok_retcode}" = '0' ]; then
      return 0
   elif [ "${check_image_builtin_mok_retcode}" = '1' ]; then
      MSG="<p>systemcheck has detected that a Machine Owner Key (MOK) embedded in the installation image is present on the disk. It can be automatically deleted, but has not been yet. Most likely this means that you did not upgrade <code>legacy-dist</code>, or did not reboot after upgrading it. Run a full system update and reboot to fix this.</p>"
      $output_x ${output_opts[@]} --messagex --typex "warning" --message "$MSG"

      MSG="systemcheck has detected that a Machine Owner Key (MOK) embedded in the installation image is present on the disk. It can be automatically deleted, but has not been yet. Most likely this means that you did not upgrade 'legacy-dist', or did not reboot after upgrading it. Run a full system update and reboot to fix this."
      $output_cli ${output_opts[@]} --messagecli --typecli "warning" --message "$MSG"

      return 0
   fi

   ## Exit code was 2 or higher, show the warning about user intervention
   ## being required.

   secure_boot_enabled_check_retcode='0'
   check_secure_boot_enabled >/dev/null 2>&1 || secure_boot_enabled_check_retcode="$?"
   if [ "${secure_boot_enabled_check_retcode}" = '0' ]; then
      MSG="<p>systemcheck has detected that a Machine Owner Key (MOK) embedded in the installation image is likely enrolled in the firmware. Secure Boot is enabled, but this may allow an attacker with physical or root account access to bypass it. Fixing this requires user intervention.<br/>"
   else
      MSG="<p>systemcheck has detected that a Machine Owner Key (MOK) embedded in the installation image is likely enrolled in the firmware. Secure Boot is not enabled, but this may allow an attacker with physical or root account access to bypass Secure Boot if it is enabled in the future. Fixing this requires user intervention.<br/>"
   fi

   MSG+="<br/>
To remove the problematic MOK:</p>
<ul>"

  if [ "${user_sysmaint_split_installed}" = 'true' ]; then
    MSG+="<li>Boot into <code>PERSISTENT Mode | SYSMAINT Session | system maintenance tasks</code>.</li>
<li>Click 'Reset Secure Boot MOK'.</li>"
  elif package-installed-check sysmaint-panel; then
    MSG+="<li>Click the Start Menu -> System Tools -> System Maintenance Panel.</li>
<li>Click 'Reset Secure Boot MOK'.</li>"
  else
    MSG+="<li>Open a terminal and run <code>/usr/sbin/shim-reset-mok</code>.</li>"
  fi
  MSG+="<li>Follow the on-screen instructions.</li>
</ul>
<p>This will wipe the system's MOK and unenroll all MOK keys from the firmware. You can then generate and enroll a new MOK.<br/>
<br/>
For more information, see <a href=\"https://kicksecure.com/wiki/Secure_Boot#Regnerate_MOK_Keys\">https://kicksecure.com/wiki/Secure_Boot#Regnerate_MOK_Keys</a>.<br/>
<br/>
Note that this message is not an indicator of compromise. See <a href=\"https://kicksecure.com/wiki/Malware_and_Firmware_Trojans#Valid_Compromise_Indicators_versus_Invalid_Compromise_Indicators\">https://kicksecure.com/wiki/Malware_and_Firmware_Trojans#Valid_Compromise_Indicators_versus_Invalid_Compromise_Indicators</a>."
   $output_x ${output_opts[@]} --messagex --typex "warning" --message "$MSG"

   if [ "${secure_boot_enabled_check_retcode}" = '0' ]; then
      MSG="
systemcheck has detected that a Machine Owner Key (MOK) embedded in the
installation image is likely enrolled in the firmware. Secure Boot is enabled,
but this may allow an attacker with physical or root account access to bypass
it. Fixing this requires user intervention."
   else
      MSG="
systemcheck has detected that a Machine Owner Key (MOK) embedded in the
installation image is likely enrolled in the firmware. Secure Boot is not
enabled, but this may allow an attacker with physical or root account access
to bypass Secure Boot if it is enabled in the future. Fixing this requires
user intervention."
   fi

   MSG+="

To remove the problematic MOK:"
  if [ "${user_sysmaint_split_installed}" = 'true' ]; then
    MSG+="

* Boot into 'PERSISTENT Mode | SYSMAINT Session | system maintenance tasks'.
* Click 'Reset Secure Boot MOK'."
  elif package-installed-check sysmaint-panel; then
    MSG+="

* Click the 'Start Menu -> System Tools -> System Maintenance Panel'.
* Click 'Reset Secure Boot MOK'."
  else
    MSG+="
* Open a terminal and run '/usr/sbin/shim-reset-mok'."
  fi
  MSG+="
* Follow the on-screen instructions.

This will wipe the system's MOK and unenroll all MOK keys from the firmware.
You can then generate and enroll a new MOK.

For more information, see:
https://kicksecure.com/wiki/Secure_Boot#Regnerate_MOK_Keys

Note that this message is not an indicator of compromise. See:
https://kicksecure.com/wiki/Malware_and_Firmware_Trojans#Valid_Compromise_Indicators_versus_Invalid_Compromise_Indicators"
  $output_cli ${output_opts[@]} --messagecli --typecli "warning" --message "$MSG"
}
