Zastosowanie zabezpieczenia kodu przed odczytem w mikrokontrolerach LPC1100 oraz LPC1300

 

Zabezpieczenie kodu przed odczytem (Code Read Protection) jest mechanizmem, który pozwala użytkownikom włączyć różne poziomy bezpieczeństwa w systemie, aby chronić zarówno oprogramowanie, jak i sprzęt. Mikrokontrolery LPC1100/LPC1300 mają trzy różne aktywne poziomy zabezpieczenia: CRP1, CRP2 i CRP3. Każdy kolejny tryb zwiększa poziom bezpieczeństwa, aż do CRP3, który ogranicza jakikolwiek dostęp do układu. Mikrokontrolery LPC1100/LPC1300 są również wyposażone w nowy poziom ochrony „NO_ISP”, który tłumi odpowiedź na pinie ISP (In-System Programming) przy uruchomieniu systemu (ale nie ogranicza debugowania przez interfejs SWD – Serial Wire Debug, ani dostępu do odczytu pamięci Flash). W niniejszym artykule zostaną opisane wszystkie te poziomy bezpieczeństwa oraz ich wykorzystanie w zależności od różnych wymagań bezpieczeństwa. Również podany zostanie przykład testowania wszystkich tych trybów. Opis będzie obejmować użycie płytek ewaluacyjnych LPCXpresso1114, LPCXpresso1343 oraz LPCXpresso Baseboard. Do opracowania programu wykorzystano środowisko programistyczne IDE LPCXpresso.

 

 

Metody dostępu do pamięci Flash

Ogólnie dostęp do pamięci Flash mikrokontrolerów LPC1100/LPC1300 można uzyskać na dwa sposoby:

  • wykorzystując interfejs programowania SWD pamięci Flash – jest to metoda z zastosowaniem narzędzi debugowania w celu załadowania kodu do urządzenia i wykonania uruchomienia/zatrzymania,
  • wykorzystując programowanie pamięci Flash poprzez ISP – tę metodę udostępnia bootloader (program rozruchowy) za pomocą portu szeregowego UART0 (lub USB w przypadku mikrokontrolera LPC1300).

Poziomy bezpieczeństwa CRP

Jak wynika z nazwy, zabezpieczenie kodu przed odczytem (CRP – Code Read Protection) jest sposobem ochrony kodu użytkownika przed jego odczytaniem z pamięci Flash mikrokontrolera. W ten sposób projektanci mogą uniemożliwić nieautoryzowanym użytkownikom uzyskanie dostępu do ich kodu, który mógłby być usunięty lub pobrany i załadowany na inną platformę sprzętową. Należy pamiętać, że wszystkie zmiany w zabezpieczeniu CRP wymagają wyłączenia i ponownego włączenia zasilania, zanim zabezpieczenie będzie aktywne.

Jak pokazano w tabeli 1, dla wszystkich włączonych poziomów CRP dostęp przez interfejs SWD jest wyłączony. Przez wyłączenie dostępu do pamięci przez debugowanie, zawartości pamięci nie można odczytać (lub zapisać) bez uprawnień za pomocą powszechnie dostępnych narzędzi debugowania. Konsekwencją tego jest jednak to, że jeśli CRP zostanie przypadkowo włączone w trakcie opracowywania programu, debugowanie nie będzie mogło mieć miejsca dopóty, dopóki ta część programu nie zostanie usunięta przez ISP i nie zostanie zaprogramowany kod, który włączy CRP. Również, kiedy urządzenia LPC1100 i LPC1300 są uruchamiane w trybie ISP, to włączone poziomy CRP wyłączają pamięć do odczytu. Ustawienia CRP nie mają wpływu na polecenia IAP (operacji kasowania i zapisu wbudowanej pamięci Flash, które są wykonywane programowo przez kod aplikacji użytkownika końcowego).

Poziom CRP1 ma na celu zablokowanie dostępu do odczytu układu, umożliwiając jednocześnie zmianę pamięci Flash sektor po sektorze. Należy pamiętać, że sektor 0 może być usunięty tylko w przypadku pełnego kasowania układu, i nie może być zapisywany przy włączonym poziomie CRP1. To skutecznie zapobiega modyfikacji sektora 0. Poziom CRP1 jest wymagany, na przykład, gdy w projekcie przeznacza się jeden lub więcej sektorów pamięci Flash do przechowywania danych kalibracji, numerów seryjnych itp. Jeśli podczas aktualizacji oprogramowania wbudowanego w urządzenie (firmware) wystąpi pełne kasowanie, wtedy dane kalibracji zostaną utracone. Poziom CRP1 może być także przydatny, na przykład, jeśli projekt obejmuje implementację własnego, zabezpieczonego bootloadera. CRP1 programuje sektor 0 i umożliwia tylko aktualizację pól do modyfikacji sektorów aplikacji, jednocześnie umożliwiając bootloaderowi pozostanie bez zmian.

Chociaż jest mało prawdopodobne, nie można wykluczyć, że atakujący, który zna system, mógłby częściowo zmienić firmware w taki sposób, aby uzyskać dostęp do odczytu wewnętrznej pamięci Flash. Aby temu zapobiec, poziom CRP2 dodatkowo zwiększa bezpieczeństwo, wspierając tylko pełne kasowanie chipu. To zapewnia, że układy są całkowicie puste (wykasowana pamięć) przed aktualizacją, a zatem nie podlegają modyfikacji przez atakującego.

Poziom CRP3 jest najwyższym poziomem bezpieczeństwa obsługiwanym przez mikrokontrolery LPC1100/LPC1300. Wykorzystując zaawansowaną inżynierię wsteczną (proces rozpoznania produktu), złodziej własności intelektualnej mógłby być w stanie poznać zastrzeżone informacje na temat projektu poprzez pełne kasowanie, a następnie programowanie docelowego urządzenia z własnego kodu testowego, i analizowanie, w jaki sposób zachowuje się urządzenie. W dalszej kolejności to umożliwiłoby złodziejowi zaimplementowanie podrobionego projektu, nie widząc oryginalnego kodu. Poziom CRP3 skutecznie wyłącza funkcjonalność ISP oraz SWD i w ten sposób pamięć Flash układu nie może być modyfikowana. Aby uniemożliwić uruchamianie nieautoryzowanego kodu, powinny być stosowane poziom CRP3. Należy pamiętać, że po włączeniu poziomu CRP3 nie ma funkcjonalności wbudowanego odzyskiwania projektów. Najprostszym sposobem realizacji własnego mechanizmu odzyskiwania jest użycie polecenia IAP „Re-Invoke ISP” (ponowne wywołanie ISP).

 

Tab. 1. Porównanie poziomów CRP

  Odczytywanie kodu Kasowanie pełne Kasowanie sektorów Sektory programu Dostęp SWD
Brak CRP Włączone Włączone Włączone Włączone Włączony
CRP1 Wyłączone Włączone Włączone Włączone Wyłączony
CRP2 Wyłączone Włączone Wyłączone Włączone Wyłączony
CRP3 Wyłączone Wyłączone Wyłączone Wyłączone Wyłączony
NO_ISP Brak ochrony Wyłączone Wyłączone Wyłączone Włączony
Należy pamiętać, że gdy CRP1 jest włączony, to Sektor 0 nie jest kasowany, chyba, że wystąpi pełne kasowanie pamięci flash urządzenia.

 

O autorze