-
Secure Boot카테고리 없음 2025. 3. 15. 02:07
시작하기 전에
- 부트로더와 사이버 보안 기능인 시큐어 부트에 관해서 설명하려고 한다.
- 자동차 제동 제어기인 ESC (Electronic Stability Control. ESC 차체 자세 제어 작동원리 [숏버전/요약] #shorts 유튜브 검색에서 제일 위에 나온 쇼츠다.)를 대상으로 설명한다.
- 소프트웨어는 C로 짠다. 코드의 양은 수백 개 파일에 수십만 라인에 이른다. (요즘은 더 클 수도 있겠다.) 이를 컴파일하면 마이크로콘트롤러에서 실행할 수 있는 형태의 파일로 변환된다. 파일 형식이 몇 가지 있다. elf, hex, bin 등이다. 편의상 헥스라고 부르겠다. 컴파일 결과 헥스 파일이 두 개 생긴다. 하나가 부트로더(bootloader)이고 다른 하나가 어플리케이션(application, 앱)이다.
- 부트로더와 앱은 플래시 메모리(이하 플래시)의 미리 지정된 영역에 각각 쓰여진다. 이를 프로그램한다 혹은 플래시한다 라고 한다.
- 아래 그림과 위와 같이 했을 때 메모리 구조의 한 예이다.
자동차 제어기의 메모리 구조 예 - 그림의 요소들을 하나씩 설명을 시도한다. 앱 영역의 코드와 캘리브레이션 부터 시작한다.
코드와 캘리브레이션
- ESC에는 브레이크 패드 온도를 추측하는 로직이 있다. 로직의 근간은 간단하다. 제동을 하면 패드 온도가 올라간다. 제동 중 속도 변화가 크면 온도가 많이 올라간다. (운동 에너지가 열 에너지로 변환되니까. 운동 에너지는 속도 제곱에 비례하니까.) 주행을 하면 패드 온도가 떨어진다. 빨리 달리면 더 빨리 떨어진다. (바람이 패드를 식혀주니까. 바람이 세면 더 빨리 식으니까.)
- 엔진 제어기에서 공기 온도와 대기압 정보를 받고, ESC의 제동 압력, 바퀴 속도, 차량 감속도 등을 보고, 바퀴 인근의 지오메트리를 고려하고, 포함할 수 있는 다른 것들을 함께 해서, 물리학과 수학을 동원하면 패드 온도 추측을 정밀하게 할 수 있을 것이다. (요즘은 어떤지 모르겠지만 내가 캘리브레이션 엔지니어였을 때) ESC의 패드 온도 추측은 그렇게 복잡하고 정밀하지 않았다.
- 실제 온도보다 추측 온도가 높도록 설정한다. 온도 추측의 목적은 패드 온도가 너무 높을 경우 제동력이 약해질 수 있다는 위험을 계기판의 램프를 켜서 운전자에게 경고를 하기 위함이었다. 추측 온도가 실제 보다 높으면 조기 경보가 된다. 늦은 경보는 위험하고 조기(가짜) 경보는 불편하다.
- 이 글을 읽는 사람들 중에 패드 온도가 너무 높다는 가짜 경보로 불편을 경험한 사람이 있는가? 패드 온도로 인한 경고등을 경험한 사람이 있는가? 경고 기준 온도는 충분히 높다. 실제 보통 운전을 하는 사람들은 물론이고 과격한 운전을 하는 사람들도 기준 온도까지 도달하는 경우는 드물다. 간혹 브레이크 페달을 살짝 밟은 채로 운전하는 사람들이 있다. 이들 중에는 이 경고등을 경험한 사람이 있을 것이다. ESC가 보기에는 항상 제동 중이기고 속도 변화가 크게 있기 때문이다.
- 패드 온도 추측 방법으로 로직과 캘리브레이션을 설명하려고 했었는데, 글을 쓰다보니 너무 복잡하다. 경고등 점등으로 설명해야겠다. ^^
- 추측한 패드 온도를 temp_pad_estimate이라고 하자. 경고등 점등 기준 온도를 k_temp_pad_too_hot이라고 하자. 추측한 패드 온도가 경고등 점등 기준 온도보다 높으면 경고등을 점등한다. 아래와 같은 초간단 코드를 짤 수 있을 것이다. 이를 "로직"이라고한다. (알고리즘보다 로직이라고 주로 하는 것 같다.)
if temp_pad_estimate > k_temp_pad_too_hot turn_warning_lamp(on)
- 브레이크 패드는 수출 지역에 따라 물리적인 특성이 다르다. 지역 A에는 a 패드를, 지역 B에는 b 패드를 적용하는 식이다. a 패드의 기준 온도는 200 degC이고 b 패드의 기준 온도는 250 degC라고 하자. 위 코드에서 k_temp_pad_too_hot의 값을 200 혹은 250으로 변경하는 것으로 패드에 맞게 (결국 지역에 맞게) "조절"해 줄 수 있다. "튜닝"해 줄 수 있다.
- k_temp_pad_too_hot을 파라미터라고 부른다. (각종 시험 결과나 이론 계산을 통해서 근거를 갖고) 이 값을 결정하여 소프트웨어에서 설정하는 작업을 캘리브레이션(calibration)이라고 한다.
- k_temp_pad_too_hot을 캘리브레이션 파라미터, 캘리브레이션 혹은 (쿨하게) 캘이라고 부른다. 캘리브레이션 하는 것을 캘한다고 하기도 한다. 튜닝이라고 하기도 한다. 나는 문맥과 어감에 따라 아무거나 편하게 쓰겠다.
- 코드라고 하면 통상 캘리브레이션과 구분하기 위한 목적으로 캘리브레이션을 제외한 로직 부분을 일컫는다.
- 파라미터는 캘리브레이션 중에는 엔지니어가 이값저값으로 바꿔가며 실험을 하지만, 한 번 결정되면 변하지 않는 고정된 값이다. 상수(constant)이다.
- temp_pad_estimate은 어떤가? 이 값은 계산에 따라 변동될 수 있다. 변수이다. 메저먼트(measurement)라고도 한다. 메저먼트라고 하는 이유는 언젠가 올 기회까지 설명을 미룬다.
- 코드 수준에서 k_temp_pad_too_hot 값을 200, 250으로 바꾸는 방식으로 소프트웨어 개발과 관리를 할 수 있다.
- 이보다 더 효율적인 방식이 있다. 코드를 컴파일 하면 헥스 파일이 된다. 헥스 파일 어딘가에는 k_temp_pad_too_hot 값이 써져있다. 그곳의 주소가 0x12345라고 하자. 1 바이트 크기로 써졌다고 하자. 그렇다면 코드를 수정하는 대신 헥스 파일의 0x12345 번지의 1 바이트를 200 혹은 250으로 쓰는 방식으로 파라미터를 변경할 수 있다.
- 헥스 파일을 변경하면 파라미터를 바꿀 때마다 컴파일을 다시 하는데 들어가는 시간과 노력과 투자비를 절약할 수 있다.
- 컴파일러는 상당히 비싸다. 캘리브레이션 엔지니어들에게도 컴파일러를 주려면 비용이 많이 든다. 캘리브레이션 툴은 컴파일러에 비하면 싸다.
- ESC 처럼 코드가 큰 소프트웨어의 컴파일에는 시간이 제법 든다. 엔진 제어기의 코드는 ESC 코드보다 10배 정도는 더 클 것이다. 컴파일에 시간이 더 많이 든다.
- 캘리브레이션을 위한 시험에는 돈이 많이 든다. 차량 시험의 경우, 비싼 시험차, 비싼 시험 장비, 그것들 보다 더 비싼 시험장이 있어야 한다. 그런 이유로 시험장에서 1분은 사무실에서 1분보다 훨씬 비싸다. 그런 시간을 파라미터를 바꿀 때마다 컴파일하는데 사용한다??? 그렇다면 크게 원가 절감을 할 수 있는좋은 기회를 갖고 있다고 긍정적으로 볼 수 있다.
- 이전 블로그(UDS 진단 통신으로 하는 소프트웨어 업데이트 1 - 작업 개요 :: hsl's tsmaster 사용기, Secure Flash - 서명이란? :: hsl's tsmaster 사용기)에서 프로그래밍을 설명했다. 프로그래밍은 제어기 제조사나 자동차사에서 할 수 있다. 어디서 하건 프로그래밍에는 시간이 든다. 시간은 비용이다. 프로그래밍 시간을 단축하면 비용을 절감할 수 있다.
- 헥스 파일에서 캘리브레이션 파라미터의 위치를 그림으로 표현하면 아래와 같이 할 수 있다. 파일 안 여기저기에 파라미터들이 흩어져 있다. 로직은 동일한데 파라미터만 변경된 경우에 프로그래밍을 하려면 전체 영역을 덮어써야 한다.
헥스 파일 중에 파라미터 위치 - 파라미터들을 아래 그림처럼 모을 수 있다. 이렇게 하면 파라미터 영역만 덮어쓰는 방법으로 프로그래밍 시간을 단축할 수 있다. 맨 위 그림에서 코드와 캘리브레이션 영역을 구분해서 표시한 이유이다.
코드와 파라미터를 분리할 수 있다. 배리언트 코딩과 EEPROM
- 위에 설명한 것처럼 판매 지역별로 혹은 차량 형상별로 파라미터가 다를 수 있다. 플래시 메모리에 공간이 충분하다면 파라미터 세트들을 모두 저장할 수 있다. 그리고 어느 파라미터 세트를 사용할 것인지를 선택하는 값만 변경하면, 해당 파라미터 세트가 적용되도록 할 수 있다. 이를 배리언트 코딩이라고 한다.
- 제어기는 동일한 하드웨어라도 소프트웨어가 다르면 다른 부품 번호(품번)을 갖게된다. 품번이 많으면 관리 비용이 늘어난다. 아래 그림의 경우, 배리언트 코딩으로 품번 3개를 1개로 줄이는 비용 절감 효과가 있다.
파라미터 세트가 여러 개라면 배리언트 코딩으로 선택된 파라미터 세트가 적용되도록 할 수 있다. - 배리언트 코드는 수 바이트 정도의 크기이다. 플래시 메모리는 구조상 바이트 단위로 덮어쓰기를 할 수 없다. 단 한 바이트를 변경하기 위해서도 그 바이트가 포함된 블록을 덮어써야 한다. 배리언트 코드는 비트 단위로 변경할 수 있는 EEPROM에 기록한다. 일반적으로.
- EEPROM 가격이 플래시 메모리보다 비싸다. 원가 절감을 위해서 배리언트 코드를 플래시에 기록하기도 한다. 요즘의 추세일 거다. 이를 EEPROM 에뮬레이션이라고 하는 것 같다.
- 배리언트 코드 외에도 EEPROM에 기록되는 데이터가 있다. 예를 들면 조향각 센서의 0점 오프셋 값이다. 조향각 센서 장착에 공차가 없을 수 없다. 센서의 0도가 실제 조향의 0도가 아닐 수 있다. 차량 제작의 마지막 단계에서 바퀴가 정확하게 정렬된 상태(실제 조향 0도)에서 센서의 출력값이 5도라면, 이를 오프셋이 5도라고 한다. 센서 출력값이 0도가 되도록 보정해줘야 한다. 이 오프셋 값은 설계나 개발 과정이 아닌 생산 시에만 결정할 수 있다. 이런 값은 주로 EEPROM에 기록된다. EEPROM 에뮬레이션을 포함하여.
부트로더
- 제어기에 전원이 들어오면 먼저 부트로더가 실행된다.
- 부트로더는 하드웨어를 초기화 하고 진단을 실시한다. 그외에몇 가지 기능들이 더 있다. 차차 설명한다. 이 과정을 부팅이라고 한다.
- 부팅이 완료되면 부트로더는 앱이 실행되도록 한다. 제어를 앱으로 넘긴다고 한다.
- ESC가 하는 제동 제어와 관련된 기능들이 앱 영역에 들어간다. 앱 영역에는 제동 제어 기능 외에 OBD(On-Board Diagnostic, a.k.a. 페일-세이프 (fail-safe) 기능도 들어간다. 진단 통신의 "대부분" 서비스도 들어간다.
- 소프트웨어 업데이트를 한다고 생각해보자. 업데이트는 앱 영역을 새 헥스 파일로 덮어쓰는 것이다. 업데이트를 하는 기능이 앱 영역에 있다면 어떻게 될까? 업데이트 중에 이 기능이 있는 부분도 덮어써질 것이다. 덮어써진 데이터와 기존 데이터가 다르다면 (거의 항상 그럴 것이다) 업데이트 기능이 깨진다. 업데이트는 엉망이될 것이다. 제어기가 제대로 작동하지 않게 된다. 따라서 앱 영역을 업데이트 하는 기능은 앱 영역이 아닌 영역에 있어야 한다.
- 그래서 진단 통신 서비스들 중에 업데이트 관련된 서비스들은 부트로더에 있다. (앱 영역과 부트로더 영역 양쪽에 있는 서비스들도 있다.) UDS 진단 통신 (3 / 4) - 진단 요청/ 응답 메시지 설정 :: hsl's tsmaster 사용기에서 진단 통신의 서비스들을 UDS 진단 통신으로 하는 소프트웨어 업데이트 1 - 작업 개요 :: hsl's tsmaster 사용기 시리즈에서 업데이트 관련된 서비스들을 설명하였다.
- 소프트웨어 업데이트로 앱 영역이 덮어써지는 중간에 전원 공급 이상 등 모종의 원인으로 업데이트 실패가 발생할 수 있다. 제어기에 전원 공급을 오프 후 온 하면 앱 영역이 망가져있다. 진단 통신으로 복구가 가능해야 한다. 복구방법은 소프트웨어 업데이트다. 그러므로 소프트웨어 업데이트에 필요한 진단 통신 서비스들은 부트로더에 있어야 한다.
- 하지만 부트로더에 진단 통신 전체 서비스들이 있을 필요는 없다. 앱 영역에 소프트웨어 다운로드 서비스가 필요 없는 것과 같은 이치다. 그래서 나는 위에 앱 영역에 진단 통신 서비스의 "대부분"이 들어가 있다고 했다.
- 어쨌든, 부트로더에는 소프트웨어 업데이트 기능이 들어있다.
부프로더에는 코드, 캘리브레이션 영역을 업데이트 하는 기능이 포함되어 있다. 부트로더의 무결성 점검
※ 시큐어 부트를 잘못 설명했다. 글을 수정한다.
- 부트로더는 제어를 앱으로 넘기기 전에 앱에 이상이 없는지 확인한다. 소위, 무결성 점검을 한다.
- 무결성 점검은 첵섬이나 해쉬 같은 것을 이용한다. 해쉬를 이용한다고 하자.
- 소프트웨어를 배포할 때 온전한 소프트웨어의 해쉬값을 계산한다. 이 해쉬 값을 제어기의 비휘발성 저장 공간(플래시나 EEPROM)에 기록해둔다. 헥스 파일에 포함하면 간편하다.
- 매 부팅 때마다, 부트로더는 앱 영역을 읽어 해쉬값을 계산한다. 부트로더는 계산한 해쉬값과 저장된 해쉬값을 비교한다. 부트로더는 두 값이 같으면 제어를 앱으로 넘긴다. 다르면 이상이다. 이상 시에 미리 정한 (예, 경고등을 켜고 작동 중지) 조치를 한다.
- 어쨌든, 부트로더에는 앱의 무결성 점검 기능이 들어있다.
- 소프트웨어를 배포할 때 온전한 소프트웨어의 해쉬값을 시큐어 플래시(Secure Flash - 서명이란? :: hsl's tsmaster 사용기)에서 설명했던 것처럼 암호용키로 암호화한 해쉬값을 비휘발성 저장 공간(플래시나 EEPROM)에 기록할 수 있다.
- 매 부팅 때마다, 부트로더는 앱 영역의 해쉬값을 계산한다. 부트로더는 저장된 해쉬값을 복호용키로 복호한다. 부트로더는 계산한 해쉬값과 복호된 해쉬값을 비교한다. ...
- 이렇게 하면 앱의 무결성뿐 아니라 진위성(authenticity)을 확인할 수 있다. 단순히 무결성을 점검하는 일반 부트에 비해 더 보안성이 높다.
부트로더의 어플리케이션 무결성과 진위성 점검 - 무결성과 진위성을 함께 점검하면 해커가 자신의 소프트웨어로 앱을 업데이트하여도 부트로더가 계산한 해쉬값과 저장된 해쉬값이 일치하지 않을 것이기 때문에 해커의 소프트웨어는 실행되지 않아 안전하다.
- 그런데 복호용키가 일반 플래시에 저장되어 있다면 어떤가? 해커는 자기 암호용키와 짝인 복호용키로 기존 복호용키를 덮어쓸 수 있다. 그리고 자기 암호용 키로 계산한 해쉬값으로 기존 해쉬값을 덮어쓸 수 있다. 그렇게 되면 부트로더는 해커가 심어둔 복호용 키로 복호하기 때문에 계산한 해쉬값과 저장된 해쉬값이 일치한다. 무결성과 진위성 점검이 무효화 된다. 그런 이유로 복호용키를 일반 플래시가 아닌 보안 저장소에 보관해야 한다는 주장이 있다.
- 애초에 시큐어 플래시가 적용되어 "완전무결"하게 작동하고 있다면 해커는 일반 플래시에 있는 앱을 덮어쓸 수도 없고 역시 일반 플래시에 있는 복호용키와 해쉬값을 덮어쓸 수도 없다. 그렇게 생각하면 복호용키를 일반 플래시에 저장해도 안전하지 않을 것이 없다. "완전무결"은 논란의 대상이다. 그래서 복호용키를 보안 저장소에 보관해야 하는가는 논란의 대상이다.
- 아래 그림의 책( [전자책] This Is How They Tell Me the World Ends - 예스24, 인류의 종말은 사이버로부터 온다 - 예스24. 흥미롭고 유익하고 잘 읽힌다. 한글책이 저렴하게 이북으로 나오면 좋은데 ...) 에 따르면, 국가 기관들도 해킹을 한다. 국가 기관은 엄청난 물적, 인적 자원을 동원할 수 있다. 해킹은 자연 법칙의 영역이 아니라 창의성의 영역에 속한다. 해킹의 위험이 없다고 증명하는 것은 창의성의 한계를 증명하는 일이다. 어려운 일이라고 생각한다.
시큐어 부트 (Secure Boot)
- 부트로더는 무결성과 진위성 점검이 필요 없는가? 필요하다. 그러면 부트로더의 무결성과 진위성을 점검하는 부트로더의 부트로더를 또 만들어야 하는가? 그러면 그 부트로더는 무결성과 진위성 점검이 필요 없는가? 필요하다. 이 문의와 답은 무한 반복될 수 있다. 이런 문제를 해결하기 위한 방법으로 (이 방법이 유일한 방법인지는 모르겠다.) HSM (Hardware Security Module)이라는 하드웨어 해결책을 적용한다.
- HSM은 마이크로콘트롤러 안에 들어있는 사이버 보안 전용 마이크로콘트롤러이다. 개념적으로 아래 그림처럼 표현할 수 있다.
개념적으로 HSM은 마이크로콘트롤러 안에 내장된 독립된 마이크로콘트롤러이다. - HSM은 두 가지 역할을 한다.
- 1. 보안 연산: 위에서 설명한 앱 영역이나 부트로더 영역의 무결성, 진위성 점검 연산을 포함하여 보안에 관련된 연산을 한다. SecOC (SecOC (Secure On-board Communication) :: hsl's tsmaster 사용기)의 MAC 계산도 HSM을 이용하여 한다.
- 2. 보안 저장소: 복호용 키나 여타 암호들와 같은 비밀을 보관하는 안전한 저장소를 제공한다.
- HSM은 한 번 잠그면 (lock) 풀 수 없거나 풀기나 매우 어려운 구조를 갖고 있다.
- HSM이 부트 영역의 무결성과 진위성을 확인한 후, 부트로더가 부팅하도록 하는 방법을 시큐어 부트(secure boot)라고 한다.
HSM 코어에서 실행되는 부트로더 점검(=시큐어 부트)과 호스트 코어에서 실행되는 앱 코드 & 캘 점검 부트로더의 업데이트는?
- 부트로더를 업데이트할 경우는 없는가? 부트로더라고 결점이 없거나 기능 개선/추가가 없을 수 있을까? 부트로더를 업데이트하려면 어떻게 하면 될까?
- (라떼^^) 콘티넨탈 ESC는 부트로더가 이중으로 되어있었다. 고객의 진단 통신 사양서대로 작성된 부트로더를 커스터머 부트로더 (CFL, Customer BootLoader)라고 불렀다. 콘티넨탈의 xmit 이라는 프로그램으로 부트로더와 통신하여 CFL을 업데이트 했던 기억이 있다. 콘티 ESC 공장에서는 xmit 통신으로 생산 제품의 정보를 제어기의 EEPROM에 기록했다.
부트로더가 커스터머 부트로더(CFL)와 제작사의 부트로더로 이중화 된 경우가 있다. CFL 업데이트가 필요하면 부트로더로 업데이트 할 수 있다. TSMaster를 사용하는 입장에서 보면 일반 부트의 무결성 점검이나 시큐어 부트의 무결성 & 진위성 점검이나 모두 제어기 안에서 일어나는 일이라는 점은 다를 바가 없다. TSMaster와 직접적인 관련이 없다. (나는 이 글을 왜 쓴 거지? :-)
위에서 코드와 캘리브레이션에 관해 언급했다. TSMaster는 캘리브레이션 기능을 지원한다. 캘리브레이션을 위해 XCP라는 프로토콜을 지원한다. XCP 프로토콜로 제어기 메모리의 특정 변수의 값을 읽을 수 있다. 이를 메저먼트라고 한다. 제어기가 XCP의 캘리브레이션과 메저먼트 기능을 지원해야 가능하다. (통신은 한 쪽만 준비된다고 할 수 있는 것이 아니라는 점을 고려하면 당연하다.)
전부터 캘리브레이션에 관해 설명하려고 했다. 내 설명은 주로 실습 과정을 순서에 따라 보여주는 방식이다. CAN 통신에 관한 내 지식과 경험은 기초가 없는 상태에서 당면한 문제를 해결하는 과정에서 좌충우돌하며 만들어진 것이다. 실습 없이 체계적인 설명을 하기에는 내 역량이 부족하다. 실습에 필요한 캘리브레이션이 가능한 제어기가 내게 없어서 나 스스로 실습을 하지 못하고 있다. 아쉬움이 없지 않다. (이 글을 읽는 분들 중에 캘리브레이션 가능한 제어기를 제공해 주실 분이 계시면 댓글로 연락주십시오. :-)