Sunday, December 12, 2021

സെക്യൂർ ബൂട്ട്: MOK - മെഷീൻ ഓണർ കീ

ഉബുണ്ടുവിനെ വലിച്ചെറിനുള്ള തീരുമാനം എടുത്ത് ഡെബിയനിലേയ്‌‌ക്ക് മടങ്ങിയപ്പോ മൊത്തത്തിലൊരു ഹീറോ ഫീലിങ്ങൊക്കെ ആയിരുന്നു. ചൂമ്മാ ഒരു രസത്തിന്. പക്ഷേ പ്രശ്നങ്ങൾ ആരംഭിച്ചത് ടിപി ലിങ്കിന്റെ ഡ്രൈവർ മാനുവലായി കമ്പൈലുചെയ്യണ്ട വന്നപ്പോളാണ്. പിന്നെ എൻവിഡിയ ഡ്രൈവറും. കമ്പൈലേഷനൊന്നും പ്രശ്നമല്ല, പക്ഷേ മൊഡ്യൂൾ ലോഡ് ചെയ്യാൻ പറ്റില്ല. കാരണം മൊഡ്യൂൾ സൈൻഡ് അല്ല എന്നത് തന്നെ. പ്രശ്നം സെക്യൂർ ബൂട്ട് ആണ്. ലിനക്സ് ബൂട്ട് ചെയ്യാൻ പ്രയാസമില്ല. പക്ഷേ പുറമേ‌ ഉള്ള ഡ്രൈവറുകൾ കമ്പൈൽ ചെയ്യണ്ട വരുമ്പോൾ, അല്ലെങ്കിൽ കസ്റ്റം കമ്പൈൽഡ് കെർണലുകൾ ഉപയോഗിക്കുമ്പോൾ ഒക്കെ സെക്യൂർ ബൂട്ട് വില്ലനാകും. എവിടെ നോക്കിയാലും സെക്യൂർ ബൂട്ട് ഡിസേബിൾ ചെയ്യുക എന്ന ഈസി സൊല്യൂഷനാണ് കാണാൻ പറ്റുന്നത്. ഇത് പലപ്പോളും പ്രായോഗികമല്ല. മാത്രമല്ല സെക്യൂർ ബൂട്ടിന് അതിന്റേതായ സുരക്ഷാ പ്രയോജനങ്ങളും ഉണ്ട്. ഇക്കാര്യങ്ങളെപ്പറ്റിയൊന്നും ഉബുണ്ടുവിലായിരുന്നപ്പോൾ ചിന്തിക്കണ്ട കാര്യമേ ഇല്ലായിരുന്നു. ആവശ്യമായ കീയും മൊഡ്യൂൾ സൈനിങ്ങിനുള്ള സംവിധാനങ്ങളും ഒക്കെ ഇൻസ്റ്റാളേഷൻ സമയത്ത് തന്നെ ഉബുണ്ടു സെറ്റപ്പ് ചെയ്യും. ഡികെ‌‌എംഎസ് ഉപയോഗിച്ച് പിന്നീട് ഇൻസ്റ്റാൾ ചെയ്യുന്ന മൊഡ്യൂളുകൾ ഒക്കെ ഓട്ടോമാറ്റിക്കായി സൈൻ ചെയ്യപ്പെടുകയും ചെയ്യും. കെർണൽ അപ്ഡേഷൻ്റെ സമയത്തൊക്കെ പിനെൻ അതിനെപ്പറ്റി ഒന്നും ചിന്തിക്കേണ്ടതില്ല.

ഈ കീകളും മൊഡ്യൂൾ സൈനിങ്ങും ഒക്കെ ക്രമീകരിക്കാനുള്ള നിരവധി‌‌ ഗൈഡുകൾ ലഭ്യമാണെങ്കിലും കൺവീനിയന്റായി വർക്ക് ചെയ്യിക്കാൻ വിഷമമണ്. മിക്ക ഗൈഡൂകളും പാസ്സ്ഫ്രേസുള്ള സൈനിങ്ങ് കീകൾ ആണ് സെറ്റപ്പ് ചെയ്യുന്നത്. അതുകൊണ്ട് ഓരോ തവണയും സൈൻ ചെയ്യാൻ പാസ്സ്‌വേർഡ് വേണം. ബാക്ക് ഗ്രൗണ്ടിൽ കമ്പൈലേഷനൊക്കെ നടക്കുന്ന കേസുകളിൽ, ലൈക്ക് കെർണൽ അപ്ഡേറ്റ്, എൻവിഡിയ ഡ്രൈവർ ഇൻസ്റ്റാളേഷൻ ഒക്കെ, ബിൽഡ് പരാജയപ്പെടാനും സ്റ്റക്ക് ആവാനും ഒക്കെ ഇത് കാരണമാകുകയും ചെയ്യും.

ഇതെല്ലാം പരിഗണിച്ച് രണ്ട് ദിവസം കുത്തിയിരുന്ന് ഉബുണ്ടു ഇതെങ്ങനെ ആണ് ചെയ്യുന്നത് എന്ന് മനസ്സിലാക്കി അതേ രീതിയിൽ കീ സെറ്റപ്പ് ചെയ്തു. എന്നാപ്പിനെൻ അതൊന്ന് ഡോക്യുമെൻ്റ് ചെയ്തേക്കാമെന്നും കരുതി. ഇത് ഡെബിയനിൽ മാത്രമല്ല, യു ഇ എഫ് ഐ സെക്യൂർ ബൂട്ട് എനേബിൾ ചെയ്തിരിക്കുന്ന ഏത് സിസ്റ്റത്തിലും പറ്റും.

ആദ്യമായി സെക്യൂർ ബൂട്ട് സെറ്റപ്പിനെ പറ്റി ഒരു പാരഗ്രാഫ്. യു ഇ എഫ് ഐ സെക്യൂർ ബൂട്ട് എനേബിൾഡായ സിസ്റ്റങ്ങളിൽ സൈൻഡ് ആയ ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റങ്ങൾ മാത്രമേ ബൂട്ട് ചെയ്യാൻ പറ്റൂ. ഈ സിഗ്നേച്ചർ വെരിഫിക്കേഷനായുള്ള കീകൾ യു ഇ എഫ് ഐ ഫേംവെയറിൽ ആണ് ഉണ്ടായിരിക്കുന്നത്. ഓരോ ഓ ഇ എമ്മുകളും അവരുടെ കീകളും മൈക്രോസോഫ്റ്റിൻ്റെ കീകളും ഒക്കെ ഇതുപോലെ ഫേംവെയറിൽ ഉൾക്കൊള്ളിച്ചിരിക്കും. അതുകൊണ്ട് ഓ ഇ എം ഒപ്പിട്ട മൊഡ്യൂളുകളും മൈക്രോസോഫ്റ്റ് ഒപ്പിട്ട മൊഡ്യൂളുകളും ഒക്കെയേ ആ ഉപകരണങ്ങളിൽ ബൂട്ട് ചെയ്യാൻ പറ്റൂ. അപ്പോ ലിനക്സും മറ്റ് ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റങ്ങളുമോ? അവർ തങ്ങളുടെ കീകൾ ഒന്നുകിൽ യു ഇ എഫ് ഐ ഫേംവെയറിൽ ഉൾപ്പെടുത്തണം. അല്ലെങ്കിൽ ഓ ഇ എമ്മുകളോടോ മൈക്രോസോഫ്റ്റിനോടോ തങ്ങളുടെ ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ഇമേജുകൾ സൈൻ ചെയ്ത് തരാൻ പറയണം. ഓരോ പുതിയ കെർണൽ ഇമേജും റിലീസും ഇങ്ങനെ സൈൻ ചെയ്യാൻ പറ്റില്ല. അപ്പോൾ ചെയ്യുന്നത് മൈക്രോസോഫ്റ്റിനെക്കൊണ്ട് ഷിം (shim) യു ഇ എഫ് ഐ ഇമേജ് സൈൻ ചെയ്ത് വാങ്ങുകയാണ്. ഷിം ഇമേജിൽ കെർണൽ ഇമേജ് സൈൻ ചെയ്യാൻ ഉപയോഗിച്ച കീ ഉണ്ടാകും. സിസ്റ്റം ബൂട്ട് ചെയ്യുമ്പോൾ ആദ്യം യു ഇ എഫ് ഐ ഫേംവെയർ അതിലുള്ള കീ ഉപയോഗിച്ച് ഷിം സിഗ്നേച്ചർ വെരിഫൈ ചെയ്യും. എന്നിട്ട് ഷിമ്മിനെ ഓടാൻ സമ്മതിക്കും. ഷിം അതിലുള്ള കീ ഉപയോഗിച്ച് ഗ്രബ് ഇമേജ് വെരിഫൈ ചെയ്യും. എന്നിട്ട് ഗ്രബ്ബിൻ്റെ ഓടാൻ സമ്മതിക്കും. ഗ്രബ് കെർണൽ ഇമേജ് വായിച്ചെടുത്തിട്ട് ഷിമ്മിനോട് അതിനെ വാലിഡേറ്റ് ചെയ്യാൻ പറയും. ഷിം ഓകെ പറഞ്ഞാൽ ഗ്രബ് അതിനെ ഓടിക്കും.

ഇതുവരെ എല്ലാം ഓകെ, പക്ഷേ ഡെബിയനും ഫെഡോറയും ഒക്കെ കെർണൽ സൈൻ ചെയ്യാൻ ഉപയോഗിച്ച കീ അവരുടെ കയ്യിലല്ലേ ഉള്ളു. അത് ഡപ്പിയിൽ ഇരിക്കുന്നു. എനിക്ക് കിട്ടില്ല. അപ്പോ ഞാനൊരു കെർണൽ കമ്പൈൽ ചെയ്താൽ, അല്ലെങ്കിൽ ഒരു മൊഡ്യൂൾ ലോക്കലായി ബിൽഡ് ചെയ്താൽ എന്ത് ചെയ്യും? അത് ഓടില്ല. പക്ഷേ ഞാൻ കാശുകൊടുത്ത് വാങ്ങിയ കമ്പ്യൂട്ടറല്ലേ, എനിക്കൊരു വെലയുമില്ലേ! വെൽ, യു ഇ എഫ് ഐ സ്പെസിഫിക്കേഷനിൽ അതിനുള്ള വഴിയുണ്ട്. 

മൊതലാളി ഓവർ റൈഡ് അഥവാ മെഷീൻ ഓണർ കീ. (എം ഓ കെ).

ഞാൻ ഒരു കീ ക്രിയേറ്റ് ചെയ്യുന്നു. അനന്തരം ഞാൻ യു ഇ എഫ് ഐ ഫേംവെയറിനോട് പറയുന്നു,

“ഇത് എൻ്റെ കീ ആകുന്നു. ഇതിനെ നീ നിൻ്റെ മാറിലേയ്ക്ക് സ്വീകരിയ്ക്കുക, ഇനിവരുന്ന മൊഡ്യൂളുകൾ ഈ കീ കൊണ്ട് ഒപ്പിട്ടവയാണെങ്കിൽ അവയെ ഓടാൻ വിടുക”,

അപ്പോ ഫേംവെയർ ചോദിക്കും, “മൊതലാളീ, ഈ കീ മൊതളാളി ഉണ്ടാക്കിയ കീ തന്നെയാണോന്ന് ഞാനെങ്ങനെ ഉറപ്പിക്കും?”

അതിനിപ്പോ എന്ത് ചെയ്യും? കീ എൻറോൾ ചെയ്യുമ്പോ ഞാനൊരു പാസ്സ്‌വേർഡ് സെറ്റ് ചെയ്യും. അടുത്ത തവണ മെഷീൻ ഓണാക്കുമ്പോ ഫേം വെയർ ചോദിക്കും, “മൊതലാളീ, കീയൊരെണ്ണം വന്നിട്ടൊണ്ട്. ഞാൻ എടുക്കണോന്ന്”

അപ്പ ഞാൻ എടുക്കണന്ന് പറയും. അപ്പോ ഫേംവെയർ എന്നോട് എന്നാപ്പിന്നെ ആ പാസ്സ്‌വേർഡ് ഒന്ന് പറഞ്ഞേന്ന് പറയും. ഞാൻ പറയും. അതോടെ മോക് കീ എൻറോൾ ചെയ്യപ്പെടും. ഇനി എനിക്ക് മോക് കീ കൊണ്ട് എന്തും ഒപ്പിടാം. ആരും പരാതി പറയില്ല. എൻ്റെ കീ, എൻ്റെ മെഷീൻ.

മെഷീൻ ഓണർ കീയും ഡി കെ എം എസ് വഴിയുള്ള ഓട്ടോമാറ്റിക്ക് സൈനിങ്ങും എങ്ങനെ ക്രമീകരിക്കാം എന്നതിനെ പറ്റി:

ഉബുണ്ടുവിലെ shim-signed പാക്കേജിൽ update-secureboot-policy എന്നൊരു സ്ക്രിപ്റ്റ് ഉണ്ട്. ഡെബിയനിലെയും മറ്റും update-secureboot-policy യിൽ പുതിയ കീ തുടങ്ങിയ ഓപ്ഷനുകൾ ഇല്ല. ആകെ സെക്യൂർ ബൂട്ട് എനേബിൾ അല്ലെങ്കിൽ ഡിസേബിൾ ചെയ്യാനുള്ള ഓപ്ഷനുകളേ ഉള്ളു. എളുപ്പത്തിൽ ചെയ്യാവുന്ന കാര്യം, packages.ubuntu.com ഇൽ പോയി shim-signed പിന്നെ dkms എന്നിവയുടെ സോഴ്സ് ഡൗൺലോഡ് ചെയ്യുക. ഈ കമാൻ്റുകൾ ഒക്കെ ബാഷ് സ്ക്രിപ്റ്റുകൾ ആണ്. അവ വച്ച് നിങ്ങളുടെ സിറ്റത്തിൽ നിലവിലുള്ള അതേ ഫയലുകൾ റീപ്ലേസ് ചെയ്യുക, അല്ലെങ്കിൽ ചില്ലറ പണികൾ മാനുവലായി ചെയ്യുക.

ആദ്യമായി റൂട്ട് ആവുക

sudo -i
സിസ്റ്റത്തിലെ dkms കമാൻ്റ് ഏതാണെന്ന് ‘command -v dkms’ ഉപയോഗിച്ച് കണ്ടെത്തുക. മിക്കവാറും /usr/sbin/dkms എന്നായിരിക്കും കിട്ടുന്നത്. കിട്ടിയത് തുറന്ന് നോക്കുക. അതിൽ sign_build എന്ന ഫങ്ങ്ഷൻ കണ്ടെത്തുക. ഈ പാർട്ട് നിങ്ങളുടെ ഡി കെ എം എസിൽ ഇല്ലെങ്കിൽ ഉബുണ്ടുവിൻ്റെ ഡി കെ എം എസ് പാക്കേജിലെ ഡി കെ എം എസ് സ്ക്രിപ്റ്റ് വച്ച് ഇതിനെ റീപ്ലേസ് ചെയ്യുക. ഉണ്ടെങ്കിൽ ഏതാണ്ടിങ്ങനെ ആയിരിക്കും
[[ -x $(command -v kmodsign) && -d "/var/lib/shim-signed/mok/" ]] || return


ഇതിൽ kmodsign നിങ്ങളുടെ സിസ്റ്റത്തിൽ ഉണ്ടോന്ന് command -v kmodsign ഉപയോഗിച്ച് നോക്കുക. ഇല്ലെങ്കിൽ പേടിക്കണ്ട, അത് കെർണൽ സോഴ്സിലെ സൈൻ ഫയൽ കമാൻ്റ് തന്നെ ആണ്. കെർണൽ ബിൽഡിനാവശ്യമായ ഹെഡ്ഡറുകളും മറ്റും ഇൻസ്റ്റാൾ ചെയ്തിട്ടുണ്ടങ്കിൽ ആ ഫയൽ ഈ ലൊക്കേഷനിൽ കാണും.

/lib/modules/`uname -r`/build/scripts/sign-file


ഇനി ഡി കെ എം എസ്സിലെ സൈൻ ബിൽഡ് താഴെക്കാണുന്ന പോലെ ആക്കുക. മേലെ kmodsign ഒരു വേരിയബിൾ ആയി ഒന്ന് സെറ്റ് ചെയ്തേക്കുക.

kmodsign=/lib/modules/`uname -r`/build/scripts/sign-file

sign_build()
{
[[ -x $kmodsign && -d "/var/lib/shim-signed/mok/" ]] || return
local base_dir="$dkms_tree/$module/$module_version/$kernelver/$arch"
if type update-secureboot-policy >/dev/null 2>&1; then
echo $"Signing module:"
SHIM_NOTRIGGER=y update-secureboot-policy --new-key
for ko in `find "$base_dir/module/" -name "*.ko" -print`;
do
echo " - $ko"
$kmodsign sha512 \
/var/lib/shim-signed/mok/MOK.priv \
/var/lib/shim-signed/mok/MOK.der "$ko"
done
update-secureboot-policy --enroll-key
fi
}


അപ്പോ ഡി കെ എം എസ്സിൻ്റെ കാര്യം സെറ്റായി. ഇനി വേണ്ടത് സൈൻ ചെയ്യാനുള്ള കീയും അതിനെ ബയോസിൽ എൻറോൾ ചെയ്യലും ആണ്.

command -v update-secureboot-policy ഉപയോഗിച്ച് update-secureboot-policy എവിടെയാണെന്ന് കണ്ടെത്തുക. മിക്കവാറും /usr/sbin/update-secureboot-policy ആയിരിക്കും. തുറന്ന് നോക്കുക, അതിൽ താഴെപ്പറയുന്ന ഭാഗങ്ങൾ ഉണ്ടോ എന്ന്.

'--new-key')
create_mok
exit 0
;;


ഉണ്ടെങ്കിലും ഇല്ലെങ്കിലും ഈ സെറ്റപ്പ് ചെയ്യണം. ആദ്യം /usr/lib/shim/mok/openssl.cnf എന്ന ഫയൽ ഉണ്ടാക്കി അതിൽ താഴെയുള്ള സാധനങ്ങൾ ഇടണം.

HOME = /var/lib/shim-signed/mok
RANDFILE = /var/lib/shim-signed/mok/.rnd

[ req ]
distinguished_name = req_distinguished_name

x509_extensions = v3_ca
string_mask = utf8only

[ req_distinguished_name 

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:FALSE

# We use extended key usage information to limit what this auto-generated
# key can be used for.
#
# codeSigning: specifies that this key is used to sign code.
#
# 1.3.6.1.4.1.2312.16.1.2: defines this key as used for module signing
# only. See https://lkml.org/lkml/2015/8/26/741.
#
extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2
nsComment = "OpenSSL Generated Certificate"



പിന്നെ
mkdir -p /var/lib/shim-signed/mok/

ഇനി,

Update-secureboot-policy യിൽ നേരത്തെ പറഞ്ഞ സാധനങ്ങൾ ഉണ്ടായിരുന്നെങ്കിൽ,

# update-secureboot-policy --new-key
# update-secureboot-policy --enroll-key

ഒരു പാസ്സ്‌വേർഡ് ചോദിക്കും. ഒരെണ്ണം സെറ്റ് ചെയ്യുക, ഓർത്ത് വയ്ക്കുക. ഇല്ലായിരുന്നെങ്കിൽ, ഒരു എം ഓ കെ ഉണ്ടാക്കുക,

# export SB_KEY="/var/lib/shim-signed/mok/MOK.der"
# export SB_PRIV="/var/lib/shim-signed/mok/MOK.priv"
# openssl req -config /usr/lib/shim/mok/openssl.cnf \
-subj "/CN=`hostname -s | cut -b1-31` Secure Boot Module Signature key" \
-new -x509 -newkey rsa:2048 \
-nodes -days 36500 -outform DER \
-keyout "$SB_PRIV" \
-out "$SB_KEY"

ഉണ്ടാക്കിയ കീ എൻറോൾ ചെയ്യുക,

# mokutil --import "$SB_KEY"

ഒരു പാസ്സ്‌വേർഡ് ചോദിക്കും. ഒരെണ്ണം സെറ്റ് ചെയ്യുക, ഓർത്ത് വയ്ക്കുക. സിസ്റ്റം റീസ്റ്റാർട്ട് ചെയ്യുക. ഇപ്പോൾ എംഓകെ എൻറോൾ ചെയ്യാനുള്ള ഓപ്ഷൻ കാണിക്കും. അത് സെലക്റ്റ് ചെയ്യുക, ചോദിക്കുമ്പോ നേരത്തേ സെറ്റ് ചെയ്ത പാസ്സ്‌വേർഡ് കൊടുക്കുക. അത്രേയുള്ളു.

ഇനി ഡി കെ എം എസ് ഉപയോഗിച്ച് വേണ്ട മൊഡ്യൂളുകളൊക്കെ ബിൽഡ് ചെയ്ത് ഉപയോഗിക്കാം.

അനുബന്ധ വായന:

  1. https://edk2-docs.gitbook.io/understanding-the-uefi-secure-boot-chain/additional_secure_boot_chain_implementations/machine_owner_key_mok
  2. https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support
  3. https://edk2-docs.gitbook.io/understanding-the-uefi-secure-boot-chain/secure_boot_chain_in_uefi/uefi_secure_boot
  4. https://github.com/rhboot/shim