다수의 제어기가 신뢰할 수 있는 CA를 기반으로 암호화 된 메시지를 주고 받을 수 있도록 설계

1. CA 키 세러머니 (secp256r1)
2. 제어기 1, 2는 EC 키 쌍 생성 (secp256r1)
3. TEE 스토리지에 개인키 저장
4. 제어기 1, 2는 CSR 생성 (OID, 기기명 포함) 후 CA에 전송
5. CA에서 CSR 서명하여 각 제어기에 인증서 발급
6. 제어기 1,2에 CA 및 제어기 인증서를 하드 디스크에 저장
7. 제어기 1,2는 CA에 CRL 목록 요청 후 하드 디스크에 저장

제어기 1 Side
8. 제어기 2로 전송할 평문 생성
9. EC 임시키 생성 (secp256r1) : 1회 사용 후 폐기 (ECDHE 연산에만 사용하고, 그 결과로 세션키(HKDF)를 도출하는 용도)
10. TEE내 안전 저장소에서 개인키 로드 (2번에서 생성)
11. HKDF 인자(랜덤 salt, info(제어기1➜제어기2)) 생성 : 1회용 세션 설정을 위함.
12. HKDF 인자, 제어기1 인증서, 제어기1 임시공개키를 개인키(2번에서 생성)로 서명(SHA256withECDSA)
13. 제어기 1, 2간 세션(소켓) 생성
14. HKDF 인자, 제어기 1 인증서, 임시 공개키, 12번 값을 제어기2에 전송

제어기 2 Side
15. CA 공개키로 제어기 1의 인증서 검증 (검증 실패하면 에러 처리)
16. CRL 확인하여 폐기 여부 검사 (검사 실패하면 에러 처리)
17. 인증서 용도 확인(oid 및 인증 용도)
18. 제어기1 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
19. EC 임시키 생성 (secp256r1)
20. TEE내 안전 저장소에서 개인키 로드 (2번에서 생성)
21. 제어기2 인증서, 제어기2 임시공개키를 개인키(2번에서 생성) 로 서명 (SHA256withECDSA)
22. 제어기1의 임시 공개키와 제어기2의 임시 개인키로 ECDHE 공유키 유도 
23. 수신한 salt, info 및 공유키를 사용하여 HKDF(HMAC-based Key Derivation Function) 세션키 유도
24. 제어기 2 인증서, 임시 공개키, 21번 값을 제어기1에 전송

제어기 1 Side
25. CA 공개키로 제어기 2의 인증서 검증 (검증 실패하면 에러 처리)
26. CRL 확인하여 폐기 여부 검사 (검사 실패하면 에러 처리)
27. 제어기2 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
28. 제어기2 의 임시 공개키와 제어기1의 임시 개인키로 ECDHE 공유키 유도 
29. salt, info 및 공유키를 사용하여 HKDF 세션키 유도
30. 제어기2에 전송할 랜덤 IV, AAD(제어기1 기기명, timestamp, 시퀀스(리플레이 공격 대비)) 생성
31. HKDF 세션키로 평문을 AES-GCM 암호화
32. iv, aad, tag, 암호문을 개인키로 서명 (SHA256withECDSA)
33. iv, aad, tag, 암호문, 32번 을 제어기2에 전송

제어기 2 Side
34 제어기1 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
35. aad 내 timestamp 검증 (10초 이내면 통과)
36. aad내 시퀀스 검증 (최근 수신된 aad의 시퀀스를 확인후, 그 다음으로 예상되는 시퀀스값이 아니면 replay 공격으로 간주)
37. AAD내 기기명과 제어기1 인증서 확장필드의 기기명이 일치하는지 확인
38. HKDF 세션키로 AES-GCM 복호화 (iv, aad, tag 사용)
39. 제어기1, 2 간 세션(소켓) 해제

https://github.com/codetronik/optee-aes

1. 키 설정

TA에서는 OP-TEE API를 활용하여 eMMC의 RPMB(Replay Protected Memory Block) 파티션에 키를 생성하고 삭제할 수 있다. 이 영역은 Normal World에서 접근할 수 없다.

별칭(alias)을 지정하여 키에 접근한다. (TA간 키는 공유할 수 없다. 즉, alias가 동일하더라도, 다른 TA의 alias에 접근할 수 없다.) RPMB에 키가 존재하지 않으면, 키를 생성하여 저장한다. 

TA 관련 주요 API들은 중요 데이터 저장을 위해 세션을 제공한다. 뭘 저장할 지는 자유이며, 필자는 이 곳에 키를 저장하였다.

2. AES-GCM을 구현

세션에서 키를 불러온 후, 이를 사용하여 데이터를 암/복호화한다. TA에서는 암호화 과정에서 IV를 랜덤하게 생성하며, 최종적으로 생성된 태그(tag)와 암호문(cipher)을 함께 반환한다.

소스 : https://github.com/codetronik/optee_example

프로젝트 구조는 아래와 같이 구성되어야 한다. (어떻게 만들던 상관없지만, Normal 과 TA는 분리되어 있어야 개발이 편해진다.)

├── include
│   └── common.h
├── normal
│   └── main.cpp
└── ta
    ├── Makefile
    ├── ta.c 
    ├── sub.mk // 필수 파일
    └── user_ta_header_defines.h // 필수 파일

유저가 OP-TEE OS의 Normal World(일반 리눅스 영역)에서 main을 실행하면, Secure World의 TA와 통신하게 된다.

TA 소스는 콜백 함수 구현이므로, 반드시 C로 작성하여야 컴파일이 된다. Normal은 C++로 작성해도 상관 없다. 

TA와 Normal 각각 컴파일 하여야 한다.

필자는 라즈베리파이를 사용 중이라 크로스컴파일러 설치를 안했으므로, 참고 바람.

normal의 경우 필자는 clang을 사용했다.

// normal
clang --sysroot=/home/code/optee/out-br/host/aarch64-buildroot-linux-gnu/sysroot -o main main.cpp -lteec -std=c++20 -lstdc++ -Wunused-parameter
// TA
make

TA 실행 파일(11223344-5566-7788-99aa-bbccddeeff00.ta)은 /lib/optee_armtz에 복사한다. Normal은 /tmp 등 적절한 곳에 복사한다. 우분투<->QEMU간 파일 전송은 #1편을 참조

Secure World 콘솔을 보면, Hello 가 로깅된 것을 확인할 수 있다.

참조 : https://optee.readthedocs.io/en/latest/building/trusted_applications.html

목표 : qemu에 op-tee os를 설치한 후 테스트

필자 환경 : ubuntu 24.04.2 (라즈베리파이)

sudo apt update
sudo apt upgrade
sudo apt install -y adb acpica-tools autoconf automake bc bison build-essential ccache cpio cscope curl device-tree-compiler e2tools expect fastboot flex ftp-upload gdisk git libattr1-dev libcap-ng-dev libfdt-dev libftdi-dev libglib2.0-dev libgmp3-dev libhidapi-dev libmpc-dev libncurses5-dev libpixman-1-dev libslirp-dev libssl-dev libtool libusb-1.0-0-dev make repo mtools ninja-build python3-cryptography python3-pip python3-pyelftools python3-serial python-is-python3 rsync swig unzip uuid-dev wget xdg-utils xsltproc xterm xz-utils zlib1g-dev

mkdir -p ~/optee && cd ~/optee

git config --global user.email "1.com"
git config --global user.name "1"

repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml -b 4.5.0
repo sync -j16 --no-clone-bundle

cd build
make -j16 toolchains

make -j16 #크로스 컴파일
make run #op-tee os 구동

make run-only # 2번째 실행부터는 이 명령어로 접속

화면이 뜨면 c 입력

 

Normal World에서 root 입력

 

예제 테스트

공유 폴더 설정하는 방법

[호스트]

vi /home/code/optee/build/Makefile

QEMU_RUN_ARGS 문자열 검색 후 아래 추가 (path는 본인 경로에 맞게)

QEMU_RUN_ARGS += -fsdev local,id=fsdev0,path=/home/code,security_model=mapped,multidevs=remap -device virtio-9p-pci,fsdev=fsdev0,mount_tag=hostshare

 

[OP-TEE OS]

mkdir -p /mnt/host
mount -t 9p -o trans=virtio hostshare /mnt/host

필자 구매 품목 (추천!)

  • 라즈베리파이 5 16GB
  • PCIE to M.2 HAT (2340 규격)
  • M.2 NVMe 2340 128GB
  • M.2 NVMe 외장 케이스
  • Micro HDMI to HDMI 변환기
  • 5V 5A 어댑터 (필수)

1. PC에 M.2 USB장착

2. Raspberry Pi Imager 다운로드 및 실행. 라즈베리파이 OS 선택 후 설치 (전력 문제로 우분투 설치는 추천하지 않음. 마우스가 먹통이 되거나, 와이파이 연결이 안됨)

3. 라즈베리파이에 M.2 장착 후 부팅

4. $sudo vi /boot/firmware/config.txt

dtparam밑에 dtparam=pciex1_gen3 추가

 

 

+ Recent posts