#!/bin/bash
clear

C_RED_BLD='\033[1;31m' C_YLW_BLD='\033[1;93m' C_GRN_BLD='\033[1;32m' C_BLU_BLD='\033[1;94m' C_CYN_BLD='\033[1;36m' C_WHT_BLD='\033[1;37m'	C_GRY_BLD='\033[1;30m'
C_RED='\033[0;91m'	  C_YLW='\033[0;93m'		 C_GRN='\033[0;92m'		C_BLU='\033[0;94m'	  C_CYN='\033[0;36m'		 C_WHT='\033[0;37m'		C_GRY='\033[0;30m'
C_BLANK='\033[0m'      C_FLASH='\033[1;5m'

TOOLKIT_PATH="$(pwd)" # "${HOME}/ps4"

KEY_EAP="eap_hdd_key.bin"
KEY_EAPR="eap_hdd_key_reversed.bin"
KEY_KERNEL="eap_kernel_key.bin"
KEY_SAMU="samu_hdd_key.bin"

KEY_ES_HDD="es_hdd_key.bin"
KEY_ES_META="es_meta_key.bin"
KEY_ES_SEED="es_seed.bin"

function function_continue() {
	echo
	read -p "Press enter key to continue. "
	echo
	}

function function_exit() {
	echo
	read -p "Press enter key to exit script. "
	exit
	}

function function_exit_2() {
	read -p "You didn't chose propper option... Press enter key to exit script. "
	exit
	}

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

echo -e "${C_GRN_BLD}PS4 HDD Keygen v1.5 by Berion"
echo -e "${C_YLW}Script for keys manipulations.${C_BLANK}"
echo

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

echo -e "${C_WHT_BLD}Choose option:${C_BLANK}"
echo -e " ${C_WHT_BLD}1.${C_BLANK} Reverse EAP HDD Key from Orbis Kernel dump."
echo -e " ${C_WHT_BLD}2.${C_BLANK} Extract EAP HDD Key from Orbis Kernel dump."
echo -e " ${C_WHT_BLD}3.${C_BLANK} Extract EAP HDD Key from SFLASH0 dump."
echo -e " ${C_WHT_BLD}4.${C_BLANK} Calculate External Storage HDD Key."
echo

while :; do
read MENU
echo
case $MENU in
		1)
			cd "${TOOLKIT_PATH}/keys" &> /dev/null
			if [[ -f "keys.bin" ]]; then
				mv keys.bin ${KEY_EAPR}
				objcopy -I binary -O binary --reverse-bytes=16 ${KEY_EAPR} ${KEY_EAP}
				echo -e "${C_YLW_BLD}EAP HDD Key (reversed):${C_BLANK}"
				hexdump -C ${KEY_EAPR}
				echo
				echo -e "${C_YLW_BLD}EAP HDD Key:${C_BLANK}"
				hexdump -C ${KEY_EAP}
				else
					echo -e "${C_RED_BLD}ERROR:${C_RED} \"${TOOLKIT_PATH}/keys/${C_RED_BLD}keys.bin${C_RED}\" file not found.${C_RED}"
					function_exit
			fi
			break;;

		2)
			if [[ ! -f "${TOOLKIT_PATH}/storage/ram/kernel.bin" ]]; then
				echo -e "${C_RED_BLD}ERROR:${C_RED} \"${TOOLKIT_PATH}/storage/ram/${C_RED_BLD}kernel.bin${C_RED}\" file not found.${C_RED}"
				function_exit
			fi
			echo -e "${C_WHT_BLD}Choose firmware version on which kernel dump was made:${C_BLANK}"
			echo -e " ${C_WHT_BLD}A.${C_BLANK} 5.00, 5.01, 5.03, 5.05"
			echo -e " ${C_WHT_BLD}B.${C_BLANK} 5.50, 5.53"
			echo -e " ${C_WHT_BLD}C.${C_BLANK} 7.01, 7.02"
			echo -e " ${C_WHT_BLD}D.${C_BLANK} 7.50, 7.51, 7.55"
			echo -e " ${C_WHT_BLD}E.${C_BLANK} 8.00, 8.01, 8.03"
			echo -e " ${C_WHT_BLD}F.${C_BLANK} 8.50, 8.52"
			echo -e " ${C_WHT_BLD}G.${C_BLANK} 9.00, 9.03, 9.04"
			echo -e " ${C_WHT_BLD}H.${C_BLANK} 9.50, 9.51, 9.60"
			echo -e " ${C_WHT_BLD}I.${C_BLANK} 10.00, 10.01, 10.50, 10.70, 10.71"
			echo -e " ${C_WHT_BLD}J.${C_BLANK} 11.00, 11.02"
			echo -e " ${C_WHT_BLD}K.${C_BLANK} 11.50, 11.52, 12.00, 12.02"
			echo

			while :; do
			read MENU_SUB
			echo
			case $MENU_SUB in
				A | a) # v5.0X (0x2790C90 = 41443536)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=41443536 count=32 status=none
					break;;

				B | b) # v5.5X (0x26C0CF0 = 40635632)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40635632 count=32 status=none
					break;;

				C | c) # v7.0X (0x26E0CD0 = 40766672)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40766672 count=32 status=none
					break;;

				D | d) # v7.5X (0x26D4C90 = 40717456)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40717456 count=32 status=none
					break;;

				E | e) # v8.0X (0x26BCC60 = 40619104)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40619104 count=32 status=none
					break;;

				F | f) # v8.5X (0x26BCCF0 = 40619248)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40619248 count=32 status=none
					break;;

				G | g) # v9.0X (0x26C0C90 = 40635536)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40635536 count=32 status=none
					break;;

				H | h) # v9.5X, 9.6X (0x26B4C60 = 40586336)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40586336 count=32 status=none
					break;;

				I | i) # v10.XX (0x26C4D00 = 40652032)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40652032 count=32 status=none
					break;;

				J | j) # v11.0X (0x26C4CD0 = 40651984)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40651984 count=32 status=none
					break;;

				K | k) # v11.50+ (0x26C4CF0 = 40652016)
					dd if="${TOOLKIT_PATH}/storage/ram/kernel.bin" of="${TOOLKIT_PATH}/keys/${KEY_EAPR}" bs=1 skip=40652016 count=32 status=none
					break;;

				*)
					function_exit_2
					break;;
			esac
			done
			objcopy -I binary -O binary --reverse-bytes=16 "${TOOLKIT_PATH}/keys/${KEY_EAPR}" "${TOOLKIT_PATH}/keys/${KEY_EAP}"
			echo -e "${C_YLW_BLD}EAP HDD Key (reversed):${C_BLANK}"
			hexdump -C "${TOOLKIT_PATH}/keys/${KEY_EAPR}"
			echo
			echo -e "${C_YLW_BLD}EAP HDD Key:${C_BLANK}"
			hexdump -C "${TOOLKIT_PATH}/keys/${KEY_EAP}"
			break;;

		3)
			if [[ ! -f "${TOOLKIT_PATH}/storage/sflash/sflash0.bin" ]]; then
				echo -e "${C_RED_BLD}ERROR:${C_RED} \"${TOOLKIT_PATH}/storage/sflash/${C_RED_BLD}sflash0.bin${C_RED}\" file not found.${C_RED}"
				function_exit
			fi
			echo -e "${C_GRN_BLD}Supported${C_GRN} dumps only from: ${C_GRN_BLD}Aeolia & Belize   (CUH-1xxx/20xx)${C_BLANK}"
			echo -e "${C_RED_BLD}Unsupported${C_RED} dumps from:    ${C_RED_BLD}Baikal & Belize 2 (CUH-21xx/22xx/7xxx)${C_BLANK}"
			echo
			echo -e "${C_WHT_BLD}Choose which Python you want to use:${C_BLANK}"
			echo -e " ${C_WHT_BLD}A.${C_BLANK} Python 2 (Linux Mint 21.3 and older)"
			echo -e " ${C_WHT_BLD}B.${C_BLANK} Python 3 (Linux Mint 22 and newer)"
			echo

			while :; do
			read MENU_SUB
			echo
			case $MENU_SUB in
				A | a)
					echo -e "Mandatory packages listed below will be downloaded and installed:${C_BLANK}"
					echo -e "${C_YLW}python2${C_BLANK}, ${C_YLW}python-pip${C_BLANK}, ${C_YLW}pathlib${C_BLANK}, ${C_YLW}pycryptodome${C_BLANK}"
					function_continue
					sudo apt update
					sudo apt install python2 python-pip -y
					pip2 install pathlib pycryptodome
					cd "${TOOLKIT_PATH}/storage/sflash" &> /dev/null
					python2 "${TOOLKIT_PATH}/apps/SFLASH0-to-EAP (2020-08-20).py"
					mv keys.bin "${TOOLKIT_PATH}/keys/${KEY_EAP}"
					break;;

				B | b)
				 # echo -e "Mandatory packages listed below will be downloaded and installed:${C_BLANK}"
				 # echo -e "${C_YLW}python3-pycryptodome${C_BLANK}"
				 # function_continue
				 # sudo apt update
				 # sudo apt install python3-pycryptodome -y
					cd "${TOOLKIT_PATH}/storage/sflash" &> /dev/null
					python3 "${TOOLKIT_PATH}/apps/SFLASH0-to-EAP (2025-10-26).py"
					mv keys.bin "${TOOLKIT_PATH}/keys/${KEY_EAP}"
					break;;
				*)
					function_exit_2
					break;;
			esac
			done
			break;;

		4)
			cd "${TOOLKIT_PATH}/keys" &> /dev/null
			if [[ ! -f ${KEY_ES_SEED} ]]; then echo "7213197452C6CC7EC8A3C06C3E22F91A7617B6E7A97360FC4C67BF38D07FD72D" | xxd -r -p > ${KEY_ES_SEED}; fi

			echo -e "Choose your ${C_YLW_BLD}External Storage${C_BLANK} disk (type eg: ${C_YLW}/dev/sdx${C_BLANK}) from below device list:"
			echo
			lsblk -p -o MODEL,NAME,SIZE,LABEL,MOUNTPOINT
			echo
			read DEVICE
			echo -e "Ok, so You've chose: \"${C_YLW_BLD}${DEVICE}${C_BLANK}\""
			echo

			sudo cryptsetup create -r -c aes-xts-plain64 -d ${KEY_ES_SEED} -s 256 ps4hdd_es_meta ${DEVICE}
			sudo dd if=/dev/mapper/ps4hdd_es_meta of=${KEY_ES_META} skip=1 bs=32 count=1 status=none
			sudo cryptsetup remove ps4hdd_es_meta

			dd if=${KEY_ES_SEED} of=/tmp/es_hmac_part_a.bin bs=16 count=1 skip=1 status=none
			dd if=${KEY_ES_SEED} of=/tmp/es_hmac_part_b.bin bs=16 count=1 status=none
			cat /tmp/es_hmac_part_a.bin /tmp/es_hmac_part_b.bin > /tmp/es_hmac.bin

			KEY_ES_HMAC=$(cat /tmp/es_hmac.bin)
			cat ${KEY_ES_META} | openssl sha256 -hex -mac HMAC -macopt key:${KEY_ES_HMAC} | awk '{print $2}' | cut -c 1-32  | xxd -r -p > /tmp/es_tweak.bin
			cat ${KEY_ES_META} | openssl sha256 -hex -mac HMAC -macopt key:${KEY_ES_HMAC} | awk '{print $2}' | cut -c 33-64 | xxd -r -p > /tmp/es_data.bin
			cat /tmp/es_data.bin /tmp/es_tweak.bin > ${KEY_ES_HDD}

			echo -e "\n${C_YLW}External Storage ${C_YLW_BLD}META${C_YLW} key${C_BLANK}:"
			od -An -tx1 ${KEY_ES_META} | tr -d ' \n' | tr '[:lower:]' '[:upper:]' && echo
			echo -e "\n${C_YLW}External Storage ${C_YLW_BLD}HDD${C_YLW} key${C_BLANK}:"
			od -An -tx1 ${KEY_ES_HDD} | tr -d ' \n' | tr '[:lower:]' '[:upper:]' && echo
			break;;

		*)
			function_exit_2
			break;;
esac
done

# sudo chown -R $(id -nu):$(id -ng) ${TOOLKIT_PATH}/keys
find "${TOOLKIT_PATH}/keys" -type f -exec chmod 444 {} \;

# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

unset MENU
unset MENU_SUB
unset SOUTH_BRIDGE

echo -e ${C_WHT_BLD}
read -p "All done. Press enter key to exit. "
