콘텐츠로 이동

v0.5

엔터프라이즈 펌웨어 요구사항

1. Approval Signing Applet 요구사항

1.1. 개요

Approval Signing Applet은 개인 서명 기기(Zone 3+)의 SE 내부에서 실행되는 엔터프라이즈 전용 애플릿이다. Phase 24-03에서 정의한 NFC APDU 7개 명령(INS 0x50~0x71)을 펌웨어 수준의 요구사항으로 구체화한다.

책임 범위: - approval_sk 키 생성, 보관, 서명 실행 - ApprovalRequest 수신 및 WYSIWYS 표시 - 생체/PIN 인증 후 ECDSA secp256k1 승인 서명 생성 - 키 라이프사이클(생성/등록/폐기) 관리

1.2. NFC APDU 명령 상세

1.2.1. APPROVAL_REQ (INS 0x50) — 승인 요청 수신

필드 설명
CLA 0x80 독점(proprietary) 클래스
INS 0x50 승인 요청 수신
P1 0x00=BTC, 0x01=EVM 체인 유형 구분
P2 0x00=단일 APDU, 0x01~0xFF=청크 시퀀스 번호 다중 청크 전송 시 사용
Lc 가변 입력 데이터 길이
Data ApprovalRequest CBOR 인코딩 UR type 45050 데이터 (tx_hash + 메타데이터)
Le 0x00 응답 없음 (상태 워드만 반환)

입력 데이터 포맷 (ApprovalRequest CBOR):

approval-request = {
  1: bytes .size 32,     ; tx_hash: PSBT sighash(BTC) 또는 safeTxHash(EVM)
  2: text,               ; policy_id: 적용 정책 ID
  3: quorum,             ; quorum: 정족수 정보 (required, total)
  ? 4: uint,             ; chain_id: EVM 전용
  5: display-metadata,   ; WYSIWYS 표시용 메타데이터
  6: bytes .size 16,     ; request_id: 승인 요청 고유 ID
  7: uint,               ; timestamp: 요청 생성 시간
}

display-metadata = {
  1: text,               ; to_address: 수신 주소 (전체 표시용)
  2: bytes,              ; amount: 전송 금액 (빅엔디안 정수)
  3: text,               ; amount_unit: 단위 ("BTC", "ETH", "USDT" 등)
  4: bytes,              ; fee: 수수료
  5: text,               ; fee_unit: 수수료 단위
  ? 6: uint,             ; operation: EVM 전용 (0=call, 1=delegatecall)
  ? 7: bytes .size 4,    ; function_selector: EVM 전용
  ? 8: text,             ; function_name: 알려진 컨트랙트 함수명
  9: text,               ; chain_name: 체인 이름 ("Bitcoin", "Ethereum" 등)
}

응답 상태 워드 (SW1/SW2):

SW 의미 설명
0x9000 SUCCESS 요청 수신 완료, WYSIWYS 표시 시작
0x6A80 WRONG_DATA CBOR 디코딩 실패 또는 필수 필드 누락
0x6A82 FILE_NOT_FOUND approval_sk 미생성 상태
0x6985 CONDITIONS_NOT_SATISFIED 카드 타입 금액 한도 초과 (디스플레이 없는 기기)
0x6986 COMMAND_NOT_ALLOWED delegatecall TX를 카드 타입에서 시도
0x6D00 INS_NOT_SUPPORTED 지원하지 않는 P1 체인 유형

1.2.2. APPROVAL_RESP (INS 0x51) — 승인 서명 반환

필드 설명
CLA 0x80 독점 클래스
INS 0x51 승인 서명 요청
P1 0x00 예약
P2 0x00 예약
Lc 0x00 입력 데이터 없음
Le 0x00 최대 길이 응답 요청

인증 필요: 예 — 생체(지문) 또는 PIN 인증 완료 후에만 서명 생성 및 반환.

응답 데이터 포맷 (ApprovalResponse CBOR):

approval-response = {
  1: bytes .size 33,         ; pubkey: approval_pk (compressed)
  2: bytes .size (64..65),   ; sig: ECDSA 서명 (BTC 64바이트 r||s, EVM 65바이트 r||s||v)
  3: text,                   ; device_id: 기기 고유 식별자
  4: uint,                   ; timestamp: 서명 생성 시간 (SE 내부 RTC)
  5: bytes .size 16,         ; request_id: 원본 승인 요청 ID (바인딩)
}

응답 상태 워드:

SW 의미 설명
0x9000 SUCCESS 서명 생성 및 반환 완료
0x6300 AUTH_FAILED 생체/PIN 인증 실패
0x6982 SECURITY_NOT_SATISFIED 인증 미수행 상태에서 호출
0x6985 CONDITIONS_NOT_SATISFIED WYSIWYS 사용자 거부(REJECT 버튼)
0x6A88 REFERENCED_DATA_NOT_FOUND 활성 ApprovalRequest 없음 (0x50 미수신 상태)
0x6983 AUTH_BLOCKED 인증 실패 횟수 초과로 잠금

1.2.3. DEVICE_REGISTER (INS 0x60) — 기기 등록

필드 설명
CLA 0x80 독점 클래스
INS 0x60 기기 등록
P1 0x00 예약
P2 0x00 예약
Lc 0x00 입력 없음
Le 0x00 최대 응답

인증 필요: 예 — 기기 소유자 인증 후 실행.

응답 데이터:

device-registration = {
  1: bytes .size 33,      ; pubkey: approval_pk (compressed)
  2: text,                ; device_id: 기기 고유 식별자
  3: bytes,               ; attestation_cert: SE attestation 인증서 체인
  4: uint,                ; key_index: 현재 활성 키 인덱스
  5: uint,                ; generated_at: 키 생성 타임스탬프
}

1.2.4. DEVICE_DEREGISTER (INS 0x61) — 기기 해제(키 폐기)

필드 설명
CLA 0x80 독점 클래스
INS 0x61 기기 해제
P1 0x00=정상 폐기, 0x01=긴급 폐기 폐기 유형
P2 0x00 예약
Lc 가변 폐기 인증 데이터
Data 듀얼 인증 토큰 (Admin + 기기 소유자)
Le 0x00

인증 필요: 예 — 듀얼 인증 (기기 소유자 생체 + Admin 승인 토큰).

응답 상태 워드:

SW 의미 설명
0x9000 SUCCESS 키 소거 완료, 기기 INACTIVE 상태 전환
0x6982 SECURITY_NOT_SATISFIED 듀얼 인증 실패
0x6A82 FILE_NOT_FOUND 이미 폐기된 상태

1.2.5. DEVICE_STATUS (INS 0x62) — 기기 상태 조회

필드 설명
CLA 0x80 독점 클래스
INS 0x62 상태 조회
P1 0x00 예약
P2 0x00 예약
Lc 0x00 입력 없음
Le 0x00 최대 응답

인증 필요: 아니오 — 상태 정보는 공개 가능.

응답 데이터:

device-status = {
  1: text,            ; device_id
  2: uint,            ; key_status: 0x00=미생성, 0x01=활성, 0x02=비활성, 0x03=폐기
  3: uint,            ; battery_percent: 배터리 잔량 (0-100, 카드 타입은 0xFF)
  4: uint,            ; firmware_version: 펌웨어 버전 (major.minor.patch 인코딩)
  5: uint,            ; approval_count: 누적 승인 횟수
  6: uint,            ; last_approval_at: 마지막 승인 타임스탬프
  7: uint,            ; auth_fail_count: 현재 연속 인증 실패 횟수
  8: bool,            ; is_locked: 잠금 상태 여부
}

1.2.6. KEY_GENERATE (INS 0x70) — 키 생성

필드 설명
CLA 0x80 독점 클래스
INS 0x70 키 생성
P1 0x00=신규 생성, 0x01=교체 생성 생성 유형
P2 0x00 예약
Lc 가변 듀얼 인증 토큰
Data Admin 승인 토큰 + 기기 소유자 인증
Le 0x00

인증 필요: 예 — 듀얼 인증 (키 생성은 보안 민감 작업).

처리 흐름: 1. 듀얼 인증 검증 2. SE TRNG으로 256비트 엔트로피 생성 3. secp256k1 개인 키 유도 (approval_sk) 4. 공개 키 계산 (approval_pk = approval_sk * G) 5. 키 ID 생성: {device_id}_{key_index}_{timestamp} 6. NVM에 저장 (exportable=false) 7. P1=0x01(교체)인 경우: 기존 키 비활성화 후 신규 키 활성화

응답 상태 워드:

SW 의미 설명
0x9000 SUCCESS 키 생성 완료
0x6982 SECURITY_NOT_SATISFIED 듀얼 인증 실패
0x6A84 NOT_ENOUGH_MEMORY SE NVM 용량 부족
0x6985 CONDITIONS_NOT_SATISFIED 기존 활성 키 존재 시 P1=0x00 거부 (교체 0x01 사용 필요)

1.2.7. KEY_EXPORT_PUB (INS 0x71) — 공개 키 내보내기

필드 설명
CLA 0x80 독점 클래스
INS 0x71 공개 키 내보내기
P1 0x00=현재 활성 키, 0x01=키 인덱스 지정
P2 키 인덱스 (P1=0x01일 때)
Lc 0x00 입력 없음
Le 0x00 최대 응답

인증 필요: 아니오 — 공개 키는 공개 정보.

응답 데이터:

public-key-export = {
  1: bytes .size 33,    ; pubkey: approval_pk (compressed secp256k1)
  2: text,              ; key_id: 키 식별자
  3: uint,              ; key_index: 키 인덱스
  4: uint,              ; generated_at: 키 생성 타임스탬프
  5: uint,              ; key_status: 0x01=활성, 0x02=비활성
}

1.3. SE 내부 처리 흐름

승인 요청 수신부터 서명 반환까지의 SE 내부 처리 파이프라인:

입력: ApprovalRequest (INS 0x50)
│
▼
[1] CBOR 디코딩
│   - approval-request 스키마 유효성 검증
│   - 필수 필드(tx_hash, policy_id, quorum, display-metadata) 존재 확인
│   - P1(체인 유형)과 chain_id 일관성 확인
│
▼
[2] 기기 정책 검증
│   - 카드 타입(디스플레이 없음): 금액 한도 확인
│   - delegatecall(operation=1): 카드 타입 차단
│   - 미지 컨트랙트 고액 TX: 모든 기기 차단
│
▼
[3] WYSIWYS 디스플레이 렌더링
│   - 수신 주소, 전송 금액, 수수료, 체인 이름 표시
│   - EVM: function_name/selector, operation 경고 표시
│   - 카드 타입: WYSIWYS 단계 스킵 (저액/비금전만 도달)
│
▼
[4] 사용자 물리 확인 대기
│   - APPROVE 버튼: 다음 단계 진행
│   - REJECT 버튼: SW 0x6985 반환, 상태 IDLE 복귀
│   - 타임아웃(60초): 상태 IDLE 복귀
│
▼
[5] 생체/PIN 인증 (INS 0x51 수신 시)
│   - 지문 센서 활성화 또는 PIN 입력 대기
│   - 인증 성공: 다음 단계
│   - 인증 실패: 실패 카운터 증가, 잠금 정책 확인
│
▼
[6] ECDSA secp256k1 서명 생성
│   - sig = ECDSA_Sign(approval_sk, tx_hash)
│   - BTC: 64바이트 compact (r || s)
│   - EVM: 65바이트 (r || s || v)
│
▼
[7] 감사 로그 기록
│   - {request_id, tx_hash, timestamp, result, device_id}
│   - SE NVM에 최근 50건 순환 저장
│
▼
출력: ApprovalResponse (INS 0x51 응답)

1.4. 상태 머신

                  INS 0x50
                  (요청 수신 성공)
    ┌────────┐ ─────────────────▶ ┌──────────────────┐
    │  IDLE  │                    │ BUNDLE_RECEIVED   │
    │        │ ◀──── 타임아웃 ──── │                    │
    └────────┘   (120초, 리셋)    └────────┬─────────┘
        ▲                                 │
        │                          기기 정책 검증 통과
        │                                 │
        │                                 ▼
        │                         ┌──────────────────┐
        │── 타임아웃(60초) ────── │ VERIFIED          │
        │   또는 REJECT           │ (정책 검증 완료)   │
        │                         └────────┬─────────┘
        │                                 │
        │                          WYSIWYS 렌더링 완료
        │                                 │
        │                                 ▼
        │                         ┌──────────────────┐
        │── 타임아웃(60초) ────── │ DISPLAYED         │
        │   또는 REJECT           │ (화면 표시 완료)   │
        │                         └────────┬─────────┘
        │                                 │
        │                          APPROVE 버튼
        │                          + INS 0x51 수신
        │                                 │
        │                                 ▼
        │                         ┌──────────────────┐
        │── 인증 실패(잠금) ───── │ AUTHENTICATED     │
        │                         │ (인증 완료)       │
        │                         └────────┬─────────┘
        │                                 │
        │                          서명 생성 완료
        │                                 │
        │                                 ▼
        │                         ┌──────────────────┐
        └──── 자동 복귀 ────────── │ SIGNED           │
                                  │ (서명 반환 완료)   │
                                  └──────────────────┘

1.5. 타임아웃 정책

상태 전이 최대 대기 시간 타임아웃 동작 근거
IDLE → BUNDLE_RECEIVED 120초 (APDU 청크 전송 완료 대기) 수신 버퍼 클리어, IDLE 복귀 불완전 전송 방지
BUNDLE_RECEIVED → VERIFIED 5초 (내부 처리) IDLE 복귀, SW 0x6F00 반환 SE 처리 이상 감지
VERIFIED → DISPLAYED 2초 (렌더링) IDLE 복귀 렌더링 실패 감지
DISPLAYED → AUTHENTICATED 60초 (사용자 확인 + 인증) IDLE 복귀, 세션 폐기 방치된 기기 보호
AUTHENTICATED → SIGNED 3초 (서명 생성) IDLE 복귀, 에러 로그 서명 연산 이상 감지
전체 세션 180초 (3분) 강제 IDLE 복귀 단일 승인 세션 최대 수명

1.6. 메모리 요구사항

항목 크기 영역 설명
approval_sk (개인 키) 32 바이트 NVM (보호) ECDSA secp256k1 개인 키
approval_pk (공개 키) 33 바이트 NVM compressed 공개 키
키 메타데이터 64 바이트 NVM key_id, key_index, generated_at, status
기기 설정 128 바이트 NVM 인증 정책, 금액 한도, 허용 체인 목록
감사 로그 (50건) 2,500 바이트 NVM 50 x 50바이트 (순환 버퍼)
ApprovalRequest 버퍼 1,024 바이트 RAM 수신 중인 요청 데이터 임시 저장
ECDSA 연산 작업 공간 512 바이트 RAM 서명 생성 중간 값
CBOR 파서 버퍼 512 바이트 RAM CBOR 디코딩 작업 공간
NVM 합계 ~2.8 KB NVM 최소 4KB NVM 요구 (여유 포함)
RAM 합계 ~2.0 KB RAM 일반 SE RAM(4~8KB) 이내
ApprovalBundle 최대 크기 1,024 바이트 7-of-11 기준 최대 (11 x 서명 ~80바이트 + 헤더)

2. 통신 프로토콜 요구사항

2.1. NFC APDU (필수)

항목 요구사항 등급
표준 준수 ISO 7816-4 APDU 구조 MUST
CLA 바이트 0x80 (독점 애플리케이션) MUST
Short APDU Lc/Le 최대 255바이트 MUST
Extended APDU Lc/Le 최대 65,535바이트 SHOULD
APDU Chaining CLA bit 5 = 1 (chaining 비트) MUST
통신 속도 NFC ISO 14443 106~424 kbps MUST
최대 응답 시간 단일 APDU: < 500ms, 서명 포함: < 2,000ms SHOULD
세션 관리 SELECT 명령(0xA4)으로 Applet 선택 후 명령 수행 MUST
AID (Application ID) D'CENT 엔터프라이즈 전용 AID 할당 MUST

다중 청크 전송 프로토콜 (ApprovalRequest > 255바이트 시):

전송 흐름 (3청크 예시):
  Host → SE: INS 0x50, P2=0x01, Data=chunk_1 (255B)  → SW 0x9000
  Host → SE: INS 0x50, P2=0x02, Data=chunk_2 (255B)  → SW 0x9000
  Host → SE: INS 0x50, P2=0x00, Data=chunk_3 (잔여)   → SW 0x9000 (수신 완료)

  P2=0x00: 마지막 청크 (또는 단일 APDU)
  P2=0x01~0xFF: 청크 시퀀스 번호 (순차 증가)

  에러 처리:
  - 청크 순서 오류: SW 0x6A86 (WRONG_P1P2)
  - 전체 크기 초과(1,024B): SW 0x6A84 (NOT_ENOUGH_MEMORY)
  - 청크 타임아웃(120초 내 완료 필요): 버퍼 클리어

2.2. QR UR (권장)

항목 요구사항 등급
UR type 지원 dcent-approval-request (45050), dcent-approval-response (45051), dcent-approval-bundle (45052) SHOULD
UR 인코딩 BC-UR v2 Bytewords 인코딩 SHOULD
QR 생성 UR 데이터를 QR 코드로 렌더링 (디스플레이 기기) SHOULD
QR 스캔 카메라로 QR 코드 디코딩 (D'CENT X만 해당) MAY
Animated QR UR v2 멀티파트 시퀀스 (프레임 분할) MAY
Animated QR 프레임 크기 최대 300바이트/프레임 (QR 밀도 최적화) SHOULD
Animated QR 프레임 속도 4~8 FPS (카메라 디코딩 안정성) SHOULD

Phase 27 연계 기초 요구사항: - Animated QR 배치 전송 프레임워크는 Phase 27(MuSig2 QR 최적화)에서 상세 설계 - 본 요구사항은 기기 레벨의 QR 인코딩/디코딩 기초 역량만 정의

2.3. USB-C (선택)

항목 요구사항 등급
충전 USB-C PD/BC 충전 지원 SHOULD
펌웨어 업데이트 USB-C 경유 서명된 펌웨어 전송 MAY
디버그/로그 개발 빌드에서만 활성화, 프로덕션 비활성화 MAY
승인 데이터 전송 USB-C로 ApprovalRequest/Response 전달 MAY
USB 데이터 비활성화 엔터프라이즈 정책으로 USB 데이터 전송 비활성화 가능 SHOULD

USB-C 경유 승인 데이터 전송은 NFC 인프라가 없는 환경의 폴백 수단이다. 에어갭 엄격 모드에서는 USB 데이터를 비활성화하고 NFC/QR만 사용할 수 있다.

2.4. BLE — 비활성화 필수

항목 요구사항 등급 근거
BLE 스택 비활성화 엔터프라이즈 펌웨어에서 BLE 프로토콜 스택 완전 비활성화 MUST CCSS Level 2/3 에어갭 요건
BLE 하드웨어 비활성화 BLE 라디오 모듈 전원 차단 (가능한 경우) SHOULD 소프트웨어 우회 공격 방어
엔터프라이즈 펌웨어 분리 소비자용(BLE 활성) / 엔터프라이즈용(BLE 비활성) 빌드 분리 MUST 동일 기기에서 BLE 재활성화 방지
BLE 재활성화 차단 펌웨어 업데이트로 BLE 재활성화 불가 (anti-rollback) MUST 다운그레이드 공격으로 BLE 복원 방지

CCSS 에어갭 근거: - CCSS Level 2: "키 저장 시스템은 인터넷 연결이 불가능해야 한다" - CCSS Level 3: "키 저장 시스템은 네트워크 연결이 물리적으로 불가능해야 한다" - BLE는 무선 네트워크 연결로 분류되며, 활성화 시 CCSS Level 2 이상 인증 실격 사유


3. 보안 요구사항

3.1. SE 보안

항목 요구사항 등급 근거
키 비추출 approval_sk의 SE 외부 읽기/전송 원천 차단 (exportable=false) MUST 키 유출 원천 방지
DPA 방어 Differential Power Analysis 방어 회로 MUST 전력 소비 패턴 분석 공격 차단
SPA 방어 Simple Power Analysis 방어 (상수 시간 연산) MUST 단순 전력 분석 공격 차단
EMA 방어 Electromagnetic Analysis 방어 SHOULD 전자기 방사 분석 공격 차단
Fault injection 방어 전압 글리치/클럭 글리치 감지 MUST 의도적 오류 주입으로 키 추출 시도 방어
메모리 보호 SE NVM 암호화, RAM 초기화 MUST 콜드 부트 공격, 메모리 덤프 방어
단조 카운터 Monotonic counter (롤백 불가) SHOULD 재사용/롤백 공격 방어
RTC (Real-Time Clock) SE 내부 또는 외부 신뢰 시간원 SHOULD 타임스탬프 무결성, 타임아웃 정확성

3.2. 인증 보안

항목 요구사항 등급 근거
생체 인증 필수 서명 명령(0x51) 실행 전 지문 인증 MUST 비인가 서명 방지
PIN 폴백 지문 인식 반복 실패 시 PIN 입력 허용 SHOULD 사용성 보장 (습기, 상처 등)
인증 실패 카운터 연속 실패 횟수 SE 내부 관리 MUST 무차별 대입 감지
일시 잠금 연속 5회 실패 → 30초 잠금 (exponential backoff) MUST 자동화 무차별 대입 지연
영구 잠금 연속 10회 실패 → 키 소거(와이프) MUST 최종 방어선 — 기기 탈취 후 공격 차단
잠금 상태 조회 DEVICE_STATUS(0x62)로 잠금 여부 확인 가능 MUST 사용자/관리자 상태 파악
인증 토큰 유효 시간 인증 성공 후 10초 이내 서명 명령 필요 SHOULD Relay 공격 윈도우 최소화

3.3. 펌웨어 무결성

항목 요구사항 등급 근거
서명된 펌웨어 D'CENT 제조사 ECDSA/RSA 서명 검증 후에만 설치 MUST 악성 펌웨어 설치 방지
Anti-rollback 펌웨어 버전 단조 증가, 이전 버전 설치 차단 MUST 취약 버전 다운그레이드 공격 방어
Secure Boot 부트로더 → 펌웨어 서명 체인 검증 MUST 부트 과정 무결성
부트로더 잠금 프로덕션 기기 부트로더 수정 불가 MUST 부트로더 교체 공격 방어
펌웨어 해시 조회 현재 펌웨어 해시를 외부에서 조회 가능 SHOULD 무결성 원격 검증
OTA 업데이트 비허용 무선 업데이트 불가 (USB-C 또는 NFC 직접 연결만) MUST 에어갭 원칙 유지

3.4. 물리적 보안

항목 요구사항 등급 근거
Tamper detection SE 접근 시도(물리적 오프닝) 감지 MAY 고보안 기관용. 감지 시 키 소거
Tamper evidence 기기 개봉 흔적이 외부에서 육안 확인 가능 SHOULD 물리적 변조 감지
SE 칩 보호 에폭시 코팅 또는 메시 레이어 MAY SE 칩 직접 접근 방어
보안 라벨 기기 고유 시리얼 + 홀로그램 보안 라벨 SHOULD 위조 기기 구별

3.5. 감사 로깅

항목 요구사항 등급 근거
승인 이력 저장 SE NVM에 최근 50건 순환 저장 MUST 감사 추적, 부인 방지
로그 포맷 {request_id, tx_hash_prefix(8B), timestamp, result(승인/거부), device_id} MUST 최소 추적 정보
로그 항목 크기 50바이트/건 x 50건 = 2,500바이트 MUST NVM 용량 제약 내
로그 읽기 전용 APDU 명령 또는 DEVICE_STATUS 확장으로 조회 SHOULD 관리자 감사 수행
로그 변조 방지 SE 내부에서만 기록, 외부 수정 불가 MUST 로그 무결성
로그 삭제 불가 로그는 순환만 가능, 명시적 삭제 불가 MUST 감사 증적 보존

설계 기준: zone3plus-security-architecture.md Approval Signing Applet NFC APDU 7개 명령 참조 참조: btc-implementation.md ApprovalBundle CBOR 스키마 및 Approval Verifier 검증 로직 보안 기준: CCSS Level 2/3 에어갭 요건, CC EAL5+ SE 보안 기준


관련 문서