이전 시간에서 안드로이드 시스템의 secure boot가 무엇인지 왜 사용하는지에 대해 알아 봤습니다. 못 보신 분은 먼저 아래 링크 참고해 보세요.
이번 시간은 secure boot의 각 단계별 세부 조건들에 대해 하나씩 알아보겠습니다.
먼저 안드로이드 시스템에서 Secure Boot up 과정은 크게 다음 3 단계의 검증 과정을 순서대로 진행합니다.
1. 안드로이드 시스템의 하드웨어가 부팅되면, 하드웨어 보호된 'Root of Trust'가 활성화됩니다. 이는 일반적으로 CPU 칩상에 내장된 ROM 영역에 저장된 Public Key(공개 키)를 사용하여 부트로더(Bootloader)의 서명을 검증하게 됩니다.
2. 부트로더가 RAM의 지정된 영역에 로드되면, 부트 파티션과 다른 검증된 파티션들 (시스템 정보, 벤더 정보, 제품 정보등)의 서명을 검증합니다. 이는 일반적으로 OEM이 제공한 공개 키를 사용합니다.
3. 이런 방법으로 물리적인 지정된 램에 로디된 모든 파티션 영역의 서명이 유효성이 검증 되면, 안드로이드 시스템이 정상적이고 기본적인 부팅 단계가 마무리 됩니다. 만약 각 파티션들의 서명이 유효하지 않으면 오류 메시지의 표시와 함께 Recovery mode(복구 모드)로 진입하게 됩니다.
Boot up 과정에서 각 단계별로 암호화 체크
다음은 일반적인 안드로이드 시스템의 secure boot up 과정에서 단계별 암호화 과정에 대한 설명입니다.
1. 하드웨어의 'root of trust'에서 부트로더(bootloader)의 서명(Certification)을 검증(Verified)하고, 부트로더가 부팅 파티션의 서명을 검증합니다. 이 과정을 verified boot라고 하며, 실행되는 코드의 무결성과 출처를 검증하게 됩니다.
2. 안드로이드 10 이상의 버전에서는 file-based encryption (FBE)을 사용하여 userdata 파티션의 각 파일을 다른 키로 암호화합니다. 이 FBE를 사용하면 실제로는 장치가 켜져 있지만, 잠겨 있는 상태에서도 일부 기능은 사용할 수 있습니다.
3. 안드로이드 5.0 이상의 버전에서는 secure startup 옵션을 활성화하여 장치를 켤 때마다 PIN이나 비밀번호를 입력하여 userdata 파티션을 복호화할 수 있습니다. secure startup 옵션은 설정 앱에서 찾을 수 있으며, 장치 제조사와 안드로이드 버전에 따라 이름과 위치가 다를 수 있습니다.
안드로이드 코드상에서 verified boot 사용 예제
안드로이드 코드상에서 verified boot를 사용하기 위해서는 device tree에 설정을 추가해야 합니다. device tree는 부팅 파티션에서 로드되는 하드웨어의 구성 정보를 포함합니다.
device tree상에 verified boot 관련 설정을 추가하려면 다음의 3 단계로 세팅을 해야 합니다.
Step 1. device tree source 파일에 avb 키를 정의
다음은 예제 코드입니다.
```
avb {
compatible = "android,avb";
permanent_attributes_path = "/chosen/android,perm-attr";
vbmeta_path = "/chosen/android,vbmeta";
};
```
Step 2. avb 키에 대응하는 avb_ops 구조체를 정의하고 초기화합니다.
다음 예제 코드를 참조하세요.
```
static struct avb_ops avb_ops;
static void init_avb_ops(void)
{
memset(&avb_ops, 0, sizeof(avb_ops));
avb_ops.read_from_partition = read_from_partition;
avb_ops.write_to_partition = write_to_partition;
...
}
```
Step 3. 다음 예제 코드처럼, device tree에서 avb 키와 perm-attr 및 vbmeta 값을 읽어서 verified boot 상태를 검증을 합니다.
```
int verify_boot_state(void)
{
AvbSlotVerifyData *out_data;
AvbSlotVerifyResult verify_result;
const char *requested_partitions[] = {"boot", "system", NULL};
const char *ab_suffix;
ab_suffix = get_suffix();
verify_result = avb_slot_verify(&avb_ops,
requested_partitions,
ab_suffix,
AVB_SLOT_VERIFY_FLAGS_NONE,
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
&out_data);
if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
printf("Verified boot state is green.\n");
return 0;
} else {
printf("Verified boot state is not green.\n");
return -1;
}
}
```
'Security' 카테고리의 다른 글
Linux 해킹에 취약한가? (0) | 2023.06.28 |
---|---|
INISAFE CrossWeb EX V3 확인 삭제 방법 (0) | 2023.04.12 |
Linux Kernel에 SMACK 적용 방법 (0) | 2023.03.02 |
SMACK 적용 후 테스트 방법 (0) | 2023.02.27 |
Android 소스 코드에서 SELinux 구성 방법 (0) | 2023.01.31 |
댓글