Ověřovač OSNMA Galileo na straně přijímače
Ověřovač na straně přijímače pro autentizaci navigačních zpráv otevřené služby Galileo (OSNMA), v čistém Rustu. Čte stránky I/NAV a hlásí pro každou družici a epochu, zda jsou navigační data kryptograficky ověřena, a proč kontrola selhala.
Pouze poradní charakter. Jde o výstup analýzy a monitorování a nikoli o typově schválené navigační zařízení. Zde hlášený stav ověření není službou integrity navigace a nesmí být jediným podkladem pro žádné rozhodnutí o navigaci ani bezpečnosti.
UPOZORNĚNÍ: duševní vlastnictví v rozhraní OSNMA Galileo#
Kshana neuděluje žádná práva z duševního vlastnictví Evropské unie k řídicímu dokumentu rozhraní signálu ve vesmíru Galileo OSNMA (Signal-in-Space Interface Control Document, „ICD IPRs"). ICD nese vlastní oprávnění (jeho příloha E), které je nevýhradní a bezplatné a má vlastní podmínky, rozsah a omezení. Každý, kdo používá, sestavuje nebo distribuuje software založený na tomto modulu, se spoléhá přímo na toto oprávnění a musí si jeho podmínky sám přečíst a přijmout. Licence Kshana (AGPL-3.0-only, nebo komerční licence) se vztahuje pouze na vlastní kód Kshana.
Tento modul implementuje algoritmy, které popisují níže uvedené dokumenty. Text ICD není reprodukován; číselné hodnoty (uspořádání polí, výčty, vyhledávací tabulka MAC) jsou vyjádřeny znovu ve vlastním zápisu Kshana, se zdrojem citovaným v kódu. ICD a Receiver Guidelines jsou © Evropská unie; zdroj je zde uveden. Kshanu nevyvíjí, nepoužívá, neschvaluje ani nepodporuje Evropská unie, Evropská komise, EUSPA ani jiný orgán.
Referenční dokumenty#
Vydává European GNSS Service Centre.
| Dokument | Verze | Datum |
|---|---|---|
| Galileo OSNMA Signal-in-Space ICD („SIS ICD") | Vydání 1,1 | říjen 2023 |
| Galileo OSNMA Receiver Guidelines | Vydání 1,3 | leden 2024 |
Čísla oddílů a tabulek citovaná v kódu a zde odkazují na tyto verze.
Co se ověřuje#
Řetězec důvěry, od kořene k datům:
- Veřejný klíč (ICD 3.2.2, 6,2). DSM-PKR se složí z jeho bloků a jeho cesta Merkle se projde až k důvěryhodnému kořenu Merkle (SHA-256).
- KROOT (ICD 3.2.3, 6,3). DSM-KROOT se složí; jeho podpis ECDSA (P-256/SHA-256 nebo P-521/SHA-512) se ověří proti veřejnému klíči, který uvádí, přes hlavičku NMA a parametry řetězce.
- Klíče TESLA (ICD 5,5, 6,4). Každý klíč ve zprávě MACK se zpětně projde až ke KROOT nebo k dřívějšímu ověřenému klíči, pomocí hashovací funkce řetězce.
- MACSEQ (ICD 4.1.2, 6,6). Pružná pole Tag-Info se kontrolují proti MACSEQ klíčem, který otevírá daný MACK.
- Značky (ICD 4,2, 6,7). Každá značka (tag) se přepočítá (HMAC-SHA-256 nebo CMAC-AES, zkrácené na délku značky řetězce) přes identity družic, čas podrámce, polohu značky, stav NMA a navigační data, která kryje, a porovná se. Zpracovávají se ADKD 0 (efemeridy, hodiny a stav), ADKD 4 (časovací parametry) a ADKD 12 (pomalý MAC, klíč zveřejněný o deset podrámců později), s křížovou autentizací družic, které samy OSNMA nenesou, a fiktivními značkami (COP 0).
Značka, která uvádí rezervovanou hodnotu nebo jejíž ADKD neodpovídá slotu vyhledávací tabulky MAC, se odloží stranou (Receiver Guidelines říkají ji zahodit) a hlásí se jako discarded, nikoli jako selhání.
Stránky se před čímkoli jiným kontrolují proti svému CRC (CRC-24Q systému Galileo); stránka, která neuspěje, se zahodí a nahlásí (bad_crc).
Hodnoty stavu#
Na značku: authenticated, failed s důvodem (tag_mismatch, macseq_mismatch, key_chain_mismatch, key_conflict), pending s důvodem (no_chain, awaiting_key, no_nav_data, unknown_maclt, unsupported_function, service_not_usable, chain_mismatch), nebo discarded. Fiktivní značka (COP 0) se na úrovni značky ukáže jako authenticated, protože prokazuje klíč, ale nekryje žádná navigační data a nikdy se nezapočítává pro družici.
Na družici, ve tvaru, který spotřebovává monitor receiver-trust:
Authenticatedpouze dokud nejnovější ověřená data efemerid a hodin (ADKD 0 nebo- této družice jsou nedávná (ve výchozím nastavení do 600 s od času ověřovače) a stále jsou používanými daty. Kontrola se týká dat, nikoli IODnav: ověřovač uchovává SHA-256 ověřeného bitového řetězce (typy slov 1 až 5, jak je kryje ADKD 0) a nejnovějšího takového řetězce, který družice vysílá, a ty se musí rovnat. Zkopírovaný IODnav nad jinými slovy nebo změněné bity typu slova 5 (které IODnav nenesou) se čtou jako
Unavailable, dokud se nová data neověří. Podrámec, který nese slova efemerid, ale ne úplnou sadu typů slov 1 až 5 pod jedním IODnav, stav odebírá stejným způsobem (každý skutečný podrámec E1-B nese všech pět); ten, který nemá žádná slova efemerid, neříká nic. Značky jiné družice (křížová autentizace) se počítají pro družici, jejíž data kryjí.
- této družice jsou nedávná (ve výchozím nastavení do 600 s od času ověřovače) a stále jsou používanými daty. Kontrola se týká dat, nikoli IODnav: ověřovač uchovává SHA-256 ověřeného bitového řetězce (typy slov 1 až 5, jak je kryje ADKD 0) a nejnovějšího takového řetězce, který družice vysílá, a ty se musí rovnat. Zkopírovaný IODnav nad jinými slovy nebo změněné bity typu slova 5 (které IODnav nenesou) se čtou jako
Failed, když v paměti selhání (ve výchozím nastavení 600 s času ověřovače) selhala kontrola dat družice, i když se pozdější data ověří. Neshoda se přičte družici, jejíž data značka kryje, i družici, která značku vysílala, protože chyba může být na kterékoli straně; neshoda MACSEQ se přičte vysílající družici.Unavailablejinak, a pro každou družici po ověřené výstražné zprávě, při stavu NMA „don't use" nebo rezervovaném stavu a dokud se neověří první klíč.
Celková hodnota je Failed, pokud selhala kterákoli družice, Authenticated, pokud je alespoň jedna ověřena a žádná neselhala, jinak Unavailable. $PKSOS,<A|F|N>[,<sat>:<A|F|N>...] je odpovídající věta; kshana::osnma::pksos_sentence ji sestavuje.
Čas#
Řetězec klíčů ukazuje, že klíč patří danému podrámci, nikoli že podrámec je současný. Ověřovač proto nikdy nebere „teď" z neověřené stránky. Jeho čas je pozdější z referenčního času zadaného pomocí set_reference_time (--reference-time) a podrámce nejnovějšího ověřeného klíče TESLA (klíč nemůže být znám před svým slotem, takže dokazuje, že čas není dřívější). Paměť selhání, okno platnosti ověření a vyřazování starých dat běží podle tohoto času. Podrámec s razítkem více než tři podrámce za nejnovějším ověřeným klíčem se odloží stranou, pokud jeho vlastní klíč neprokáže jeho čas; klíčové a výstražné zprávy v něm se přesto zpracují, protože nesou vlastní důkaz (podpis nebo kořen Merkle).
Hodiny stojí, když OSNMA přestane, protože je posouvají jen klíče. Živé volání musí volat set_reference_time s časem hostitele každý podrámec; ověření pak vyprší samo a poll_clock (spouštěné rovněž s každým podrámcem) vrátí událost KeyStall, jakmile se po dobu delší než okno ověření neověřil žádný klíč.
To, co to nedává, je čerstvost. Bez referenčního času ze zdroje, který útočník nemůže posunout, se přehrání starých autentických dat pod starými razítky ověří a razítka stránek jsou jen tak dobrá jako jejich zdroj: CLI to říká (freshness: NOT enforced), kdykoli není zadán žádný referenční čas. S referenčním časem je tolerance pod jedním podrámcem (výchozí 29 s; větší hodnoty se odmítnou). Referenční čas je jediný okamžik: podrámce od něj vzdálenější než tolerance se odloží stranou a započítají, takže se hodí pro živá nebo právě zaznamenaná data, nikoli pro dlouhý záznam. U záznamu referenční čas vynechejte a výsledek čtěte jako „autentické, nemusí být čerstvé". Formální požadavek uvádějí Receiver Guidelines.
Razítka stránek proudu u-blox pocházejí ze samotných neověřených dat (viz Vstup), takže ani ona neposkytují ochranu čerstvosti.
Řetězce, klíče a výstrahy#
Ověřené řetězce se uchovávají podle identifikátoru řetězce (CID); značky se kontrolují řetězcem, který uvádí hlavička NMA, a hlavička uvádějící řetězec, který nebyl ověřen, nechá značky podrámce nezkontrolované (chain_mismatch). Druhý KROOT řetězce v platnosti přidá kotvu; KROOT jiného řetězce se ponechá vedle, takže opětovné oznámení starého řetězce po obnovení ten nový neruší.
Hlavička NMA není ověřena, takže to, co oznamuje, se počítá jen po potvrzení: když stejnou hlavičku v podrámci vysílá více než jedna družice, nebo když ji nese podepsaná zpráva ověřeného KROOT (hlavička je součástí této zprávy). Tato dvě nejsou rovnocenná. Shoda více než jedné družice chrání před anomálií jediné družice, nikoli před spooferem: jeden spoofer může podvrhnout dvě identity družic. Získá tím odepření služby a nic víc, protože potvrzené „don't use" smaže ověřená data každé družice: jeho zrušení, podvržené či pravé, nic neobnoví, dokud se nové značky neověří pod pravými provozními podrámci. (Před tímto smazáním mohlo podvržené zrušení vrátit na dobu až okna ověření data, která už byla ověřena.) Skutečným potvrzením je hlavička podepsaná KROOT, která také znovu zruší „don't use", když nese provozní stav. Hlavička jediné družice nemění nic kromě kontroly značek jejího vlastního podrámce. KROOT, jehož čas použitelnosti není pozdější než u řetězce drženého pod stejným identifikátorem (přehrání staršího), se odmítne (stale); KROOT téhož řetězce přidá kotvu.
Revokaci řídí stav a hodnota CPKS potvrzené hlavičky. Při stavu NMA „don't use“ hodnota CPKS „chain revoked“ zahodí řetězec, který hlavička uvádí, a od té chvíle odmítá jeho KROOT; hodnota CPKS „public key revoked“ zahodí veřejný klíč, který tento řetězec podepsal, i všechny řetězce jím podepsané. Pokud byl náhradní řetězec pro dané id přijat před potvrzením hlavičky, bez ohledu na to, jak dlouho předtím, je zrušený klíč klíčem předchozího řetězce, nikoli nového; tato paměť se uchovává, dokud se revokace neprovede nebo dokud není potvrzena hlavička jiného postupu, a revokační hlavička opakovaná v každém podrámci se provede jednou. Stejné hodnoty CPKS se stavem operational označují přechod na náhradní řetězec a nic neruší. Samotná hlavička není ověřena, takže padělaná revokace může autentizaci pouze odebrat a je konečná, dokud se ověřovač nerestartuje. Tato konečnost platí i pro platný klíč: padělaná revokace veřejného klíče vynuluje paměť nahrazeného klíče a zruší klíč, který se používá, a vrátí ji zpět jen restart.
DSM-PKR s NPKT 4 je výstražná zpráva; ověřuje se přes Merkleův strom jako klíč a její náhodné pole NPK je součástí listu. Ověřená výstraha vymaže všechny řetězce a veřejné klíče, odmítne každý další KROOT a veřejný klíč a nastaví každou družici na Unavailable, jak předepisují Receiver Guidelines, dokud se ověřovač nerestartuje.
Výplňové pole zprávy DSM-KROOT je hash podepsané zprávy a podpisu. Kontroluje se před podpisem a také říká, s jakou hlavičkou NMA byla podepsaná zpráva sestavena, pokud se hlavička během sestavování zprávy změnila.
Co se neověřuje nebo nezkouší#
- Aktuálnost. Viz Čas výše: vyžaduje referenční čas zvenčí.
- Obnova a revokace. Řetězce a klíče se sledují tak, jak je zkoušejí proudy publikovaných vektorů (obnova, konec řetězce, revokace řetězce a klíče, nový veřejný klíč, nový Merkleův strom, výstraha), nikoli ve všech případech, které ICD připouští. Revokace oznámená neautentizovanou hlavičkou se bere za slovo a je pro relaci konečná. Nový Merkleův strom se přebírá jen přes Merkleův kořen, který ověřovač dostane.
- Hash Merkleova stromu. Zprávy DSM-PKR se kontrolují stromem SHA-256. Strom SHA3-256, který ICD v budoucnu připouští, není podporován. Hashovací funkcí řetězce může být SHA-256 nebo SHA3-256.
- Seznamy stavů klíčů. Revokace se sleduje přes hlavičku NMA a zprávy v proudu; seznamy zrušených certifikátů se nečtou.
- Pokrytí autentizovaných dat. ADKD 4 s COP 1 odeslaný v lichém podrámci nemůže autentizovat (Word Type 10 může být odeslán o jeden nebo dva podrámce dříve); stojí to jen dostupnost, nikdy správnost.
- Provoz v konstantním čase. Neposkytuje se a není potřeba: ověřovač nedrží žádná tajemství (jen veřejné klíče, publikované klíče řetězce a přijatá data).
- Kvalita signálu a dat. Stránky se kontrolují CRC a výstražné stránky se zahazují, ale o signálu, na němž dorazily, se nic neví. Obnova slov I/NAV 1 až 4 pomocí Reed-Solomonova kódu se nepoužívá: data se musí přijímat přímo.
- Nejde o službu integrity polohy. Autentizace říká, že data pocházejí ze systému. Neříká nic o signálu, na němž dorazila, ani o kvalitě určené polohy.
Vstup#
- Prostý formát stránek. Jeden pár stránek na řádek:
<svid> <gst_seconds> <60 hex digits>, komentáře#jsou povoleny.gst_secondsje GST v sekundách (week * 604800 + time of week) na začátku stránky; hex je 240 bitů sudé a liché poloviny (včetně koncovek), nejvýznamnější bit první. - CSV s testovacími vektory. Rozvržení publikovaných vektorů (
SVID,NumNavBits,NavBitsHEX). Počáteční čas se bere z--start-gstnebo z názvu souboru s datem. - u-blox UBX-RXM-SFRBX. Surový bajtový proud UBX (
--format ubx, rozpoznaný automaticky). Zprávy Galileo E1-B I/NAV se skládají zpět do párů stránek (src/osnma/ubx.rs); ostatní systémy, E5b, výstražné stránky a rámce se špatným kontrolním součtem se ignorují. SFRBX nenese čas, takže se každá stránka označí časem z vlastních dat (typy slov 5 a 0) a přijme se jen tehdy, když po sobě jdoucí stránky nesoucí čas souhlasí s počtem stránek přijatých mezi nimi; stránky, které nelze zařadit, se zahazují, nikdy se nehádají. Tento čas pochází ze samotných dat a neposkytuje ochranu aktuálnosti (viz Čas výše). ID signálu 0 (E1-C) nenese žádná data, takže jeho přijetí vedle E1-B je neškodné. Zbloudilý synchronizační pár s absurdní délkou čtečku nezdrží. Kód rámování je třetí kopií rámování UBX ve stromu zdrojů (src/realdata/ubx.rs, příjem receiver-trust); je držen odděleně, aby se chování receiver-trust nezměnilo, a tyto tři by později mohly sdílet jednu čtečku. Rozvržení slov zprávy SFRBX je převzato z veřejných popisů a ověřeno pouze na syntetických rámcích, nikoli na živém přijímači.
Příkazový řádek#
kshana osnma verify <input> [--format pages|vector-csv|ubx] [--start-gst SECONDS]
[--merkle-root HEX] [--public-key ID:TYPE:HEX]
[--reference-time SECONDS [--max-time-error SECONDS]] [--epochs] [--json]
Textový výstup udává stav po družicích a s --epochs po značkách a epochách; --json udává totéž se seznamem značek. Stavový kód ukončení 3 znamená, že selhala kontrola dat některé družice, 2 znamená chybu použití nebo vstupu. Poradní upozornění výše se vypisuje jako první na každé cestě, včetně chyb a nápovědy k použití.
Z Pythonu a WebAssembly#
kshana.osnma_verify(data, format="", start_gst=None, merkle_root_hex="", public_keys=None, reference_time=None, max_time_error=None) (Python) a osnma_verify(input_base64, format, start_gst, merkle_root_hex, public_keys, reference_time, max_time_error) (WebAssembly) spouštějí stejný ověřovač nad bajty v paměti a vracejí JSON, který vypisuje kshana osnma verify --json, včetně poradního upozornění. Server MCP jej nenabízí: vstupem je dlouhý surový proud z přijímače, pro který se lépe hodí příkazový řádek a Python, a nástroj pro agenta by přidal rozsáhlý vstupní povrch bez užitku. Platí stejné poradní upozornění a stejná omezení; stav není služba integrity navigace.
Testy a testovací data#
Testovací data jsou syntetická a vytváří je vlastní kód a testy Kshana. V tomto repozitáři nejsou uloženy žádné vektory z ICD ani Guidelines, žádné propracované příklady ani klíčový materiál. Výchozí testy (tests/osnma_synthetic.rs a jednotkové testy) z rovnic sestaví řetězec, stránky a značky a kontrolují konzistenci a to, že se zachytí záměrné poškození: překlopený navigační bit, překlopený bit klíče, přehrané značky, chybná časová razítka, čas mimo reference, chybějící data a útoky, které odhalila revize (podvržený podrámec z daleké budoucnosti, který nesmí smazat selhání, autentizace, která musí vypršet a sledovat IODnav, výstraha, stav NMA „don't use“, fiktivní značky, nesoulad MACSEQ, konfliktní klíče, revokace a obnova řetězce, špatné vyplnění nebo podpis), přičemž ověřovačem prochází CMAC-AES, řetězec SHA3-256 a podpis P-521. Protože tato data vycházejí z našeho vlastního čtení ICD, ukazují vnitřní konzistenci, nikoli shodu.
Primitiva se kontrolují proti publikovaným testům se známou odpovědí, z nichž žádný nepochází z ICD: RFC 4231 (HMAC-SHA-256), RFC 4493 (CMAC-AES-128), FIPS 197 (AES), FIPS 202 (SHA3-256) a RFC 6979 (ECDSA P-256). Podpisy P-521 se kontrolují z hlediska kódování a volby hashe jednorázovým klíčem vytvořeným v testu; aritmetika křivky patří knihovně.
Shodu kontroluje tests/osnma_official_vectors.rs, který je dobrovolný: čte kopii oficiálního archivu testovacích vektorů, kterou si stahujete sami, z adresáře pojmenovaného v KSHANA_OSNMA_VECTORS, a když proměnná není nastavena, nedělá nic. Nic neukládá ani nedistribuuje a výchozí běhy testů nepoužívají síť. Ověřovači dává jen Merkleův kořen a veřejné klíče jednoho stromu, jako by je měl přijímač, takže se řetězce zakládají z podepsaného DSM-KROOT v proudu a běží celá cesta: Merkle, podpis, řetězec klíčů, MACSEQ a značky. Pro každou sadu vektorů tvrdí spodní mez počtu autentizovaných značek, že žádná neselhala, které řetězce a klíče proud oznamuje, autentizované značky ADKD 0, 4 a 12, že se autentizace obnoví po konci řetězce, revokaci řetězce, revokaci klíče a novém veřejném klíči, že se výstražná zpráva ověří a nenechá nic autentizovaného a že každý vektor používá jen HMAC-SHA-256, řetězec SHA-256, 128bitové klíče, 40bitové značky a položky vyhledávací tabulky 33 a 34. Jiné volby algoritmů a parametrů z ICD tedy pokrývají jen výše uvedené testy se známou odpovědí a syntetické testy.
Závislosti#
Knihovny RustCrypto, čistý Rust, MIT OR Apache-2.0, sestavené bez výchozích funkcí: hmac, cmac, aes, sha3, p256 a p521 (funkce ecdsa, používaná jen k ověřování), vedle sha2, které už ve stromu je. Sestavují se pro wasm32-unknown-unknown a procházejí cargo deny.