SW 개발

[OPTEE 문서번역] OPTEE Architecture - 7 Porting Guide

. . . 2019. 10. 11. 17:00
반응형

개요

https://optee.readthedocs.io 문서를 구글 번역기 + 네이버번역기를 이용하여 번역하였습니다.

즉, 기계가 번역한 내용이므로 대략적인 내용은 확인가능합니다. 제대로 보시려면 원문을 보시길 권유드립니다.

글순서

7. Porting guidelines

이 문서는 다음과 같은 두 가지 목적으로 사용됩니다.

  • 초기 xtest 유효성 검사가 통과 된 새 장치에서 OP-TEE를 실행하고 실행하기 위한 기반으로 사용합니다. 이것이이 문서의 첫 번째 섹션 입니다.
  • 실제 보안 제품을 만들려는 경우 누락 된 조각을 강조 표시하십시오. 즉, 이 문서의 두 번째 섹션에 대한 것입니다.

우리는 일반적인 방법으로 OP-TEE에서 엔드 투 엔드 보안을 구현하기 위해 최선을 다하고 있지만 장치의 특성상 NDA 등으로 인해 항상 그렇게 할 수 있는 것은 아닙니다. 대부분의 경우 일반 API를 작성하려고하지만 코드를 스텁해야합니다. 이 포팅 가이드 라인은 실제 안전한 소비자 장치에서 해결해야 하는 누락 된 부분을 강조합니다. 우리가 조만간 우리가 여기서 말하는 누락 된 부분에 대해 모든 사람에게 공개적으로 참조 구현을 제공 할 수있는 장치에 조만간 액세스 할 수 있기를 바랍니다.

7.1. Add a new platform

OP-TEE를 다른 장치에 이식하기로 결정한 후에해야 할 첫 번째 일은 새로운 플랫폼 장치를 추가하는 것입니다. 이미 지원되는 패밀리의 디바이스라면 새로운 플랫폼 변형 (PLATFORM_FLAVOR)을 추가 할 수도 있고 완전히 새로운 플랫폼 패밀리 (PLATFORM) 일 수도 있습니다. 일반적으로이 초기 설정에는 UART, 메모리 주소 등을 설정하는 작업이 포함됩니다. "gendev"에 대한 가상 플랫폼을 간단히 부르겠습니다. 그러면 예제를 작성할 때 참조해야 할 것이 있습니다.

7.1.1. core/arch/arm

core/arch/arm에는 현재 지원되는 모든 장치가 있습니다. 새로운 플랫폼을 추가하거나 기존 플랫폼을 수정해야하는 곳입니다. 일반적으로이 파일 세트는 특정 플랫폼 폴더에 있습니다.

ls
conf.mk  main.c  platform_config.h  sub.mk

그래서 gendev 플랫폼에서 파일이이 폴더에 있어야한다는 것을 의미합니다 :

core/arch/arm/plat-gendev

conf.mk

이것은 플랫폼에 고유 한 구성을 정의하는 장치 별 메이크 파일입니다. 이는 주로 두 가지로 구성됩니다. - OP-TEE 구성 변수 (CFG_). 두 가지 방법으로 값을 할당 할 수 있습니다. CFG_FOO? = bar는 컴파일시 수정 될 수있는 기본값을 제공하기 위해 사용되어야합니다. 반면에, 어떤 값으로 설정되어야하고 수정할 수없는 변수는$ (call force, CFG_FOO, bar)에 의해 설정되어야합니다. - TEE 코어, 사용자 모드 라이브러리 및 신뢰할 수있는 응용 프로그램 용 컴파일러 플래그. 빌드 시스템에서 사용되는 매크로에 추가 될 수 있습니다. 빌드 시스템 문서에서 플랫폼 별 구성 및 플래그를 참조하십시오.

기존 플랫폼 구성 파일을 시작점으로 사용하는 것이 좋습니다. 예를 들어면, core/arch/arm/plat-hikey/conf.mk.

플랫폼 conf.mk 파일은 최소한 default platform flavor for the platform, the core configurations (architecture and number of cores), the main configuration directives (generic boot, arm trusted firmware support, generic time source, console driver, etc…) 및 일부 플랫폼 기본 구성 설정을 정의해야 한다.

PLATFORM_FLAVOR ?= hikey

include core/arch/arm/cpu/cortex-armv8-0.mk

$(call force,CFG_TEE_CORE_NB_CORE,8)
$(call force,CFG_GENERIC_BOOT,y)
$(call force,CFG_PL011,y)
$(call force,CFG_PM_STUBS,y)
$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
$(call force,CFG_WITH_LPAE,y)

ta-targets = ta_arm32
ta-targets += ta_arm64

CFG_NUM_THREADS ?= 8
CFG_CRYPTO_WITH_CE ?= y
CFG_WITH_STACK_CANARIES ?= y
CFG_CONSOLE_UART ?= 3
CFG_DRAM_SIZE_GB ?= 2

main.c

이 플랫폼 특정 파일에는 전원 관리 핸들러와 UART와 관련된 코드가 포함됩니다. 이 문서에서 다루는 핸들러 관련 정보에 대해 더 자세히 설명하겠습니다. 우리의 gendev 장치에서는 다음과 같이 보일 수 있습니다 (여기서는 약간의 공간을 절약하기 위해 필요한 라이센스 헤더 제외).

#include <console.h>
#include <drivers/serial8250_uart.h>
#include <kernel/generic_boot.h>
#include <kernel/panic.h>
#include <kernel/pm_stubs.h>
#include <mm/core_mmu.h>
#include <platform_config.h>
#include <stdint.h>
#include <tee/entry_fast.h>
#include <tee/entry_std.h>

static void main_fiq(void)
{
    panic();
}

static const struct thread_handlers handlers = {
    .std_smc = tee_entry_std,
    .fast_smc = tee_entry_fast,
    .nintr = main_fiq,
    .cpu_on = cpu_on_handler,
    .cpu_off = pm_do_nothing,
    .cpu_suspend = pm_do_nothing,
    .cpu_resume = pm_do_nothing,
    .system_off = pm_do_nothing,
    .system_reset = pm_do_nothing,
};

const struct thread_handlers *generic_boot_get_handlers(void)
{
    return &handlers;
}

/*
 * Register the physical memory area for peripherals etc. Here we are
 * registering the UART console.
 */
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE);

static struct serial8250_uart_data console_data;

void console_init(void)
{
    serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
                         CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
    register_serial_console(&console_data.chip);
}

platform_config.h

이 특정 파일이 존재하면 여러 개의 파일이 릴레이되므로 모든 플랫폼에 대해 필수 헤더 파일이다. 이 파일은 당신이 메모리 구성을 하고, 기본 주소를 정의하는 등 다른 플랫폼들 간의 주요한 차이점을 찾을 수 있는 곳이다. 우리는 여기에 몇 가지를 열거할 것이지만, 아마도 이미 존재하는 'platform_config'를 보는 것이 더 이치에 맞을 것이다.다른 플랫폼의 파일. 우리의 열정적인 gendev 는 다음과 같이 보일 수 있다.

#ifndef PLATFORM_CONFIG_H
#define PLATFORM_CONFIG_H

/* Make stacks aligned to data cache line length */
#define STACK_ALIGNMENT             64

/* 8250 UART */
#define CONSOLE_UART_BASE   0xcafebabe /* UART0 */
#define CONSOLE_BAUDRATE    115200
#define CONSOLE_UART_CLK_IN_HZ      19200000

/* Optional: when used with CFG_WITH_PAGER, defines the device SRAM */
#define TZSRAM_BASE         0x3F000000
#define TZSRAM_SIZE         (200 * 1024)

/* Mandatory main secure RAM usually DDR */
#define TZDRAM_BASE         0x60000000
#define TZDRAM_SIZE         (32 * 1024 * 1024)

/* Mandatory TEE RAM location and core load address */
#define TEE_RAM_START               TZDRAM_BASE
#define TEE_RAM_PH_SIZE             TEE_RAM_VA_SIZE
#define TEE_RAM_VA_SIZE             (4 * 1024 * 1024)
#define TEE_LOAD_ADDR               (TZDRAM_BASE + 0x20000)

/* Mandatory TA RAM (external less secure RAM) */
#define TA_RAM_START                (TZDRAM_BASE + TEE_RAM_VA_SIZE)
#define TA_RAM_SIZE         (TZDRAM_SIZE - TEE_RAM_VA_SIZE)

/* Mandatory: for static SHM, need a hardcoded physical address */
#define TEE_SHMEM_START             0x08000000
#define TEE_SHMEM_SIZE              (4 * 1024 * 1024)

#endif /* PLATFORM_CONFIG_H */

이것은platform_config.h 파일에서 최소한의 정보량입니다. 즉, 온칩 및 외장 RAM 용 메모리 레이아웃입니다. DDR의 일부는 일반적으로 일반 세계와 공유해야하므로,이를 위해 일종의 메모리 방화벽이 필요합니다 (자세한 내용은 자세히 설명합니다). 보시다시피 여기에 UART 설정 즉,DEVICE0_xyz 부분을 추가했습니다.

7.1.2. Official board support in OP-TEE?

우리는 모든 사람들이 보드 지원을 OP-TEE 프로젝트 자체에 제출하도록 권장하기 때문에 공식 릴리스의 일부가되며 OP-TEE 커뮤니티 자체에서 유지 관리됩니다. 그렇게하기를 원할 경우,해야 할 일이 몇 가지 더 있습니다.

Update platforms supported

"Platforms supported" 페이지에는 OP-TEE에서 공식적으로 지원되는 모든 장치가 나열된 섹션이 있습니다. 귀하의 장치를 열거하십시오. 그것은 플랫폼의 이름을 포함하고,PLATFORM 플래그와 장치가 공개적으로 사용 가능한지 여부를 포함해야합니다. 기기의 인터넷에 제품 페이지가있는 경우 기기 이름을 쓸 때 링크를 만드십시오.

Update .shippable.yml

우리가 Shippable을 사용하여 끌어 오기 요청을 테스트하기 때문에 ".shippable.yml" 파일에 장치를 추가하여 누군가가 끌어 오기 요청을 할 때 적어도 만들어지기를 바랍니다. 파일 끝 부분에 줄을 추가하십시오.

- _make PLATFORM=<platform-name>_

Maintainer

업스트림 보드 지원을 제출하고 Linaro 유지 보수 자에게 디바이스를 제공 할 수없는 경우, 추가 한 디바이스의 유지 보수자가 되도록 요청할 것입니다. 즉, 그에 따라 MAINTAINERS.md 파일도 업데이트 해야합니다. 장치 유지 보수자가되면 최신 상태로 유지할 책임이 있으며 최신 OP-TEE 소프트웨어를 실행하는 장치를 테스트하기 위해 OP-TEE 릴리스 일정의 일부로 매 분기마다 질문을 받게됩니다.

Update build.git and manifest.git

이것은 꼭 필요한 것은 아니지만 다양한 장치에서 OP-TEE를 쉽게 설정, 구축 및 배포 할 수 있도록 OP-TEE 개발자 빌드를 만들고 유지하려고합니다. 우리는 모든 유지 보수 책임자가 자신들이 책임지고있는 이사회에 대해 똑같이하도록 권장합니다. 따라서 OP-TEE에 추가 ​​한 기기의 새로운 manifest (and a new *.mk in build)를 만드는 것을 고려해보십시오.

7.2. Hardware Unique Key

대부분의 장치에는 주로 다른 키를 유도하는 데 사용되는 일종의 하드웨어 고유 키 (HUK)가 있습니다. HUK는 예를 들어 안전한 저장 장치 등에 사용되는 키를 도출 할 때 사용될 수 있습니다. HUK의 중요한 점은 HUK가 잘 보호되어야 하고 최상의 경우 HUK가 소프트웨어에서 직접 읽을 수 없도록해야한다는 것입니다. 안전한 측면. 이것에 대한 다른 해결책이 있습니다. 암호화 가속기는 암호화 가속기를 지원하거나 다른 보안 코 프로세서를 포함 할 수 있습니다.

OP-TEE에서는 HUK가 스텁되고 core/include/kernel/tee_common_otp.htee_otp_get_hw_unique_key(...) 함수에서이를 볼 수 있습니다. 진짜 안전한 제품에서는 이것을 다른 것으로 대체해야합니다. 장치에 HUK에 대한 하드웨어 지원이 없다면, 적어도 이것을 0 이상으로 변경해야합니다. 그러나 소프트웨어에 키를 저장하는 것은 안전하지 못하다는 것을 기억하십시오. 특히 다른 모든 키의 핵심이 아니라는 점을 기억하십시오. 따라서 이것이 권장할만한 것은 아닙니다.

7.3. Secure Clock

GlobalPlatform Internal Core API 사양의 Time API는 time 의 세 가지 소스를 정의합니다 : system time, TA persistent time, REE time. REE time 은 본질적으로 보안되지 않은 time 소스로 간주되지만 다른 두 사람은 완전히 신뢰할 수있는 하드웨어에서 신뢰할 수있는 소스, 즉 secure time 를 사용해야합니다. GlobalPlatform 관점에서 보자면 secure time 를 사용할 필요가 없다는 것, 즉 REE 로부터 시간을 사용하는 것은 괜찮지 만 신뢰 수준은gpd.tee.systemTime.protectionLevel 속성에 반영되어야한다는 것에 주의하십시오 및 gpd.tee.TAPersistentTime.protectionLevel 속성 (100=REE controlled clock, 1000=TEE controlled clock)이 있습니다. 따라서 주목해야 할 함수는tee_time_get_sys_time (...)tee_time_get_ta_time (...)입니다. 하드웨어에 보안 시계가 있다면 보안 시계를 사용하기 위해 구현을 변경하고 싶을 것입니다 (그리고tee_time_get_sys_time_protection_level ()ta_time_prot_lvl 변수를 적절히 업데이트 해야 합니다) tee_svc.c).

7.4. Root and Chain of Trust

장치가 작동하도록 (조작되지 않은) 바이너리를 실행하고 있음을 보장하려면 장치에 일종의 트러스트 앵커를 설정해야합니다.

가장 일반적인 방법은 루트 공개 키를 장치의 일부 읽기 전용 메모리에 저장하는 것입니다. 종종 SoC / OEM은 공개 키를 직접 저장하거나 OTP 의 공개 키 해시를 저장합니다. 일반적으로 ROM 이 되어야하는 부트 ROM이 첫 번째 단계 부트 로더를로드하려고 할 때 일반적으로 소프트웨어 바이너리에서 공용 키를 읽고 해시 키로 OTP 키와 비교합니다. 일치하는 경우 부트 ROM은 첫 번째 단계 부트 로더가 실제로 해당 개인 키로 서명되었는지 확인할 수 있습니다.

OP-TEE에서는 이와 관련된 코드를 전혀 찾을 수 없으며, 이는 디바이스 제조업체가 모두 고유 한 방식으로이 작업을 수행하는 경향이 있기 때문에 일반적으로이 작업을 수행하기가 어려운 경우에 좋은 예입니다. 낮은 수준의 부팅 세부 사항 및 보안 구현을 다른 world 와 공유하는 데별로 관심이 없습니다. ARMv7-A에서 특히 그렇습니다. ARMv8-A의 경우 신뢰할 수있는 펌웨어 A의 ARM이 추상 신뢰 체인 (see auth-framework.rst)을 구현하고 정의 했으므로 조금 나아졌습니다. 우리는 Trusted Firmware A (see Secure boot for the details)의 인증 프레임 워크를 사용하여 OP-TEE를 성공적으로 검증했습니다.

7.5. Hardware Crypto IP

기본적으로 OP-TEE는 소프트웨어 암호화 라이브러리 (현재 mbed TLS 및 LibTomCrypt)를 사용하며 ARMv8-A에서 도입 된 Crypto Extensions를 사용할 수 있습니다 (장치에서 가능하다면). 우리가 손에 가지고있는 장치 중 일부는 하드웨어 암호화 IP를 가지고 있지만 NDA 등으로 인해이를 가능하게하지 못했습니다. 전용 암호화 블록에서 암호화 작업을 수행 할 수있는 장치가 있고이 장치를 소프트웨어 구현에 사용하려는 경우 core/include/crypto/crypto.h 에 정의 된 관련 기능, Crypto API를 구현하고 낮은 수준 드라이버를 작성해야합니다. 우리의 Cryptographic implementation 페이지에서는 Crypto API가 어떻게 통합되는지 자세히 설명합니다. 암호화 블록과의 통신은 사용자가 가지고있는 암호화 IP의 종류에 따라 매우 다르기 때문에 우리는 어떻게해야 하는지를 작성하지 않았습니다. 우리가 암호 블록을 사용할 수있는 장치를 장악 할 때 미래에 그렇게 할 수 있습니다.

기본적으로 OP-TEE는 소프트웨어 PRNG로 구성됩니다. 엔트로피는 다양한 장소에서 소프트웨어 PRNG에 추가되지만, 안타깝게도 엔트로피로 추가 된 데이터를 예측하는 것은 여전히 ​​쉽습니다. 결과적으로, RNG가 하드웨어를 기반으로하지 않는 한 생성 된 무작위는 매우 약할 것입니다.

7.6. Power Management / PSCI

main.c 파일에 대해 이야기했던 Add a new platform 섹션에서 우리는 전원 관리와 관련된 몇 가지 핸들러를 추가했습니다. 우리는 다음과 같은 라인을 이야기하고 있습니다 :

.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
.cpu_resume = pm_do_nothing,
.system_off = pm_do_nothing,
.system_reset = pm_do_nothing,

실제적으로 무언가를하는 유일한 함수는cpu_on 함수이며, 나머지는 스터브됩니다. 그 주된 이유는 일시 중지 및 재개하는 방법이 장치에 의존하는 것으로 생각하기 때문입니다. OP-TEE의 코드는 Trusted Firmware A 의 콜백 등이 OP-TEE로 라우팅 될 수 있도록 준비되었지만 기능이 스텁되기 때문에 우리는 아무것도하지 않고 그냥 반환합니다. 실제 생산 장치에서는 이러한 콜백이 호출 될 때 CPU 상태를 저장 및 복원하고 하드웨어 IP 주소와 TZASC 및 기타 메모리 방화벽 관련 설정을 보호해야합니다.

7.7. Memory firewalls / TZASC

Arm은 TrustZone Address Space Controller 라는 시스템 IP / SoC 주변 장치를 정의했습니다 (TZASC, see TZC-380 and TZC-400). TZASC를 사용하여 DDR 메모리를 실제 주소 공간의 개별 영역으로 구성 할 수 있습니다. 각 영역은 개별 보안 수준 설정을 가질 수 있습니다. TZASC를 활성화하면 메모리 또는 주변 장치와의 트랜잭션에 대한 보안 검사를 수행합니다. TZASC가 장치에 항상있는 것은 아니지만 어떤 경우에는 SoC가 동등한 것을 개발했습니다. OP-TEE에서 이는 매우 잘 반영됩니다. 즉, 플랫폼에 따라 메모리를 보호하는 다양한 방법이 있습니다. ARMv8-A 플랫폼에서 우리는 Trusted Firmware A 를 부트 펌웨어로 사용하는 대부분의 경우에 있으며 보안 부트 로더는 TZASC를 사용하여 보안 대 비보안 메모리를 구성하는 것입니다(see plat_arm_security_setup in TF-A). 여기서는 보안 및 비보안 메모리 영역을 갖도록 장치의 메모리 방화벽을 구성했는지 확인해야합니다.

7.8. Trusted Application private/public keypair

기본적으로 모든 신뢰할 수있는 응용 프로그램 (TA)은 미리 생성 된 2048 비트 RSA 개발 키 (개인 키)로 서명됩니다. 이 키는keys 폴더 (optee_os.git 의 루트에 위치)에 default_ta.pem라는 이름으로 저장되어 있습니다. 이 키는 사용자 고유의 키로 대체되어야하며 실제 제품에서 사용중인 경우 소스 코드 트리에서이 개인 키를 절대로 체크인해서는 안됩니다. 개인 키를 저장하는 권장 방법은 일종의 HSM (하드웨어 보안 모듈) 을 사용하는 것입니다. 그러나 대신 개인 키를 컴퓨터에 임시로 두는 방법도 있습니다 실제 제품에 사용하려는 TA에 서명 할 때 안전하다고 간주됩니다. 일반적으로 회사에서이 유형의 키에 액세스 할 수있는 사람은 소수에 불과합니다. OP-TEE의 키 처리는 현재 모든 TA에 사용되는 단일 키만 지원하기 때문에 약간 제한적입니다. 우리는 이것을 좀더 유연하게하기위한 계획을 가지고 있습니다. 정확히 언제 일어날 지 아직 결정되지 않았습니다.

반응형