Etusivu


15. toukokuuta 2022

  UEFI-siirtymän vaikutus loppukäyttäjän digitaalisiin vapauksiin

Vuonna 1981 julkaistussa IBM PC-tietokoneessa, jonka kanssa suurin osa
nykyään kotikäytössä olevista mikrotietokoneista on yhteensopivia,
käyttöjärjestelmän tai muun ohjelman alkulataus toimii varsin
yksinkertaisella tavalla: Jos tallennusvälineen ensimmäisen sektorin lopussa
on niin sanottu "boot sector signature" (1), eli tavut 0x55 ja 0xAA, sektorin
sisältö ladataan muistiin osoitteeseen 0:7C00 ja sen jälkeen prosessori
hyppää kyseiseen osoitteeseen. IBM PC ei alkulatausproseduurinsa
yksinkertaisuudessa ole mikään poikkeus - käytännössä kaikki saman aikakauden
kotitietokoneet ovat käynnistystavaltaan vastaavalla tavalla yksinkertaisia
ja ROM-muistilla oleva firmware-ohjelma tekee mahdollisimman vähän oletuksia
käytössä olevasta tallennusvälineestä ja sillä olevasta sisällöstä. Tämä
on järkevää, sillä näin saadaan annettua ohjelmoijalle vapaat kädet saada
tietokone tekemään mitä tahansa, mikä vain laitteiston asettamissa rajoissa
on mahdollista.

Useimmissa tuon ajan mikrotietokoneissa, IBM PC mukaanlukien, firmware pystyy
lataamaan ohjelman tietokoneen muistiin myös kasetilta, jolloin edes sektorin
koko ei ole käytettävien tallennusvälineiden kirjoa rajoittava tekijä. Kyse
lienee tietoisesta valinnasta. Tietokoneen ROM-piirillä kiinteästi oleva
firmware-ohjelma on haluttu suunnitella niin, että se tulee mahdollisimman
vähän ohjelmoijan "tielle", mikäli ohjelmoija haluaa tehdä jotain, mikä ei
ole tullut mieleenkään tietokoneen suunnittelijoille. Ohjelmoijalle on myös
haluttu antaa mahdollisuus olla kokonaan välittämättä firmware-ohjelman
tarjoamista palveluista ja halutessaan vaikka ylikirjoittaa tietokoneen
muistiin käynnistyksessä ensimmäisenä ladatut firmwaren osat omalla
ohjelmakoodillaan.

UEFI tekee kaiken päin vastoin. UEFI-firmwaren ohjelmointirajapinta on jaettu
käynnistyksen ja ajonaikaisiin palveluihin, joista ensinmainittuihin kuuluu
useita tärkeitä palveluita kuten levyjen lukemiseen ja kirjoittamiseen
liittyvät palvelut. Käynnistyksen aikaiset palvelut kuitenkin katoavat siinä
vaiheessa, kun käyttäjän ohjelma "boottaa" ja hakee muistikartan, jonka
perusteella tietää, mihin muistiosoitteisiin ylipäätään voi kirjoittaa
sekoittamatta firmwaren palveluita. Jäljelle jää ainoastaan ajonaikaiset
palvelut, joita ei kovin paljoa ole, eikä niistä ole käyttöjärjestelmän
kannalta oikein mitään hyötyä. Ei-vakioiduissa paikoissa muistissa
sijaitsevat firmware-palvelujen koodit tekevät myös muistinhallinnasta
hankalaa.

Sen lisäksi UEFI pakottaa käyttämään GPT-osiointia ja kiintolevyllä on oltava
ainakin yksi FAT32-osio, jolta firmware lataa käynnistysbinäärin muistiin.
Se tekee UEFIsta täysin yhteensopimattoman useimpien käyttöjärjestelmien
kanssa, koska yksinkertaisemmat käyttöjärjestelmät yleensä toimivat vain
tietyntyyppisen osiotaulun ja tietyntyyppisten osioinnin kanssa - ja
oikeastaan osiointikaan ei välttämättä ole edes itsestäänselvyys, vaan
yksinkertaisemmat käyttöjärjestelmät ja suoraan boottaavat ohjelmat (monet
diagnostiikkaohjelmat mukaanlukien) käyttävät jonkinlaista omaa hyvin
pelkistettyä tiedostojärjestelmäänsä, joka ei noudata minkäänlaista
osiointilogiikkaa. 

UEFI-binäärin on myös pakko olla ns. PE-formaatissa, jossa
ohjelmatiedoston alussa on oltava mm. kokonainen DOS-ohjelma, jonka ainoa
tehtävä on tulostaa näytölle teksti, jonka mukaan kyseistä ohjelmaa ei voi
ajaa DOS-käyttöjärjestelmässä - tosin kyseistä koodinpätkää ei koskaan voida
suorittaa edes DOSissa, koska DOS ei ole yhteensopiva UEFIn kanssa ja
useimmat DOS-toteutukset eivät myöskään tunnista .EFI-päätteellä (jota UEFI
käyttää suoritettaville binääreille) olevia tiedostoja suoritettaviksi
ohjelmiksi.

BIOS tarjoaa peruslaitteiston tunnistukseen vakiomuistiosoitteesta löytyvän
"Bios Data Tablen", josta selviää tarpeelliset tiedot useimpien perustason
oheislaitteiden kuten sarja- ja rinnakkaisporttien ohjelmointia varten,
tietoja näytönohjaimesta ja levyjen määrästä ja paljon muuta. UEFI ei tarjoa
mitään tietoa laitteistosta, vaan ohjelmoija joutuu hankkimaan laitteiston
tiedot ACPI:stä, joka on paljon monimutkaisempi ja useissa emolevyissä myös
huonosti ja spesifikaation vastaisesti toteutettu - tosin huono toteutus ei
ole UEFIn vika itsessään, mutta liittyy myös Microsoftin harjoittamaan
monopoliaseman väärinkäyttöön.

Käytännössä minkäänlaista oikeasti toimivaa BIOS-toteutusta ei ole edes
mahdollista tehdä UEFI-firmwaren tarjoamaa ohjelmointirajapintaa hyödyntäen.
Vaikka joku onnistuisikin toteuttamaan jokaisen IBM PC-yhteensopivan BIOSin
tarjoaman palvelun käyttäen pelkästään ACPI-rajapinnasta saatuja tietoja
laitteistosta, niin ongelmaksi muodostuu, ettei BIOS voi bootata samalta
levyltä kuin UEFI, koska UEFI tekee niin paljon BIOSin kanssa
yhteensopimattomia oletuksia tallennusvälineen sisällöstä. BIOS taas ei tee
yhtään mitään muita oletuksia kuin sen, että ensimmäisen sektorin lopusta
löytyy tavut 0x55 ja 0xAA.¹ Toisin päin asia onkin huomattavasti helpompaa,
eli niin, että UEFI-toteutuksen tekee BIOSin ohjelmointirajapinnan päälle,
ja niitä on tehtykin. UEFI siis aivan konkreettisesti rajoittaa asioita,
joita tietokoneella voi tehdä, kun taas BIOS on paljon sallivampi eikä
varsinaisesti rajoita mitään, vaan tarjoaa yksinkertaiset peruspalvelut
sisältävän ohjelmointirajapinnan, jota voi joko käyttää tai olla kokonaan
käyttämättä.

  Miksi UEFI-firmwaresta tuli niin yleinen?


UEFI kehitettiin alun perin Intelin Itanium-koneisiin, joissa oli kokonaan
oma arkkitehtuurinsa. Itaniumin piti olla ennennäkemättömän nopea ja
käskykannaltaan huomattavasti x86-koneita tehokkaampi, mutta loppujen
lopuksi se oli täydellinen floppi. Itanium-koneita ei koskaan saatu toimimaan
kovin nopeasti, eivätkä ne koskaan tulleet kovin yleisiksi. Jostain syystä
suuret teknologiafirmat kuitenkin alkoivat jossain vaiheessa etsiä korvaajaa
BIOSille, ja jostain syystä korvaajaksi sitten valikoitui epäonnistuneesta
Itaniumista peräisin oleva UEFI-alkulatausjärjestelmä. On kuitenkin
epäselvää, miksi BIOS piti kokonaan korvata jollain muulla, koska siihen ei
oikein ole teknisesti päteviä perusteita. Järkevämpää olisi ollut hieman
laajentaa olemassa olevaa BIOS-apia, mitä on tehty ennenkin tietokoneiden
kehittyessä.

  UEFI ja tietoturva


UEFI tarjoaa tietoturvaominaisuutena ns. Secure Boot -toiminnallisuutta.
Secure Bootin tarkoitus on estää tietokonetta lataamasta muistiin muita kuin
ennalta hyväksyttyjä ohjelmia. Yleisimmässä käyttötapauksessa sallitaan
ainoastaan tietokoneeseen valmistajan toimesta esiasennetun
käyttöjärjestelmän lataaminen ja käynnistäminen.

Secure Bootin tarjoama tietoturva on vähintäänkin kyseenalainen, koska
sallittujen käynnistettävien ohjelmien tiedot sisältävä tietue sijaitsee
CMOS-piirillä, jota ei ole fyysisesti kirjoitussuojattu, eli sen sisältöä voi
muuttaa ohjelmallisesti. Lähes mikä tahansa haittaohjelma voi siis kirjoittaa
tietueen sisällön uusiksi ja sallia minkä tahansa ei-toivotun ohjelman
käynnistämisen. Käytännössä tämä onnistuu varsin helposti hyödyntämällä
jotain käyttöjärjestelmän ns. privilege escalation -haavoittuvuutta.
Käytännössä Secure Boot ei teekään juuri muuta kuin estää loppukäyttäjää
valitsemasta itse, mitä käyttöjärjestelmää tietokoneessaan käyttää.

























1: IBMs PC:n BIOS-firmwaren ensimmäinen revisio ei tarkista boot sector
signaturen olemassaoloa, vaan suorittaa ensimmäisellä sektorilla olevan
koodin joka tapauksessa. Boot sector signaturen tarkistus tuli vasta
firmwaren toisessa versiossa. Boot sector signature saattaa olla eräänlainen
virheentarkistusmenetelmä, koska tavuissa 55 ja AA joka toinen bitti on 1 ja
joka toinen on 0, mikä tekee siitä helpoiten korruptoituvan bittijonon.