콘텐츠로 이동

v0.6

SE 정책 버전 관리 및 정책 변경 이력 해시 체인 설계

1. 개요

1.1. 설계 목적

본 문서는 SE 정책 버전의 단조 증가 관리와 정책 변경 이력의 해시 체인 구조를 설계한다. 이를 통해 감사인이 임의 시점의 정책 상태를 SE policy_hash에서 역추적하여 암호학적으로 증명할 수 있다.

핵심 가치: - 정책 변경 이력이 해시 체인으로 연결되어 중간 변조가 불가능 - SE의 policy_hash가 해시 체인의 최신 앵커로 기능 - 감사인이 "시점 T에 어떤 정책이 적용되어 있었는지"를 SE 서명으로 증명 가능 - 정책 롤백(다운그레이드) 공격이 SE 레벨에서 차단됨

1.2. 규제 근거

요건 근거 본 문서 대응
POL-04 SE 정책 버전 관리 + 변경 이력 해시 체인 PolicyVersionRecord + 해시 체인
CORE-09 정책 변경 이력 관리 전 이력의 변조 불가 기록
REG-EU-01 MiCA 거버넌스 체계 쿼럼 승인 이력의 암호학적 증명
SOC 2 CC7.2 변경 관리 통제 정책 변경의 감사 추적

1.3. 선행 산출물 연결점

산출물 연결 방식
se-audit-digest-schema.md (Phase 30) SE policy_hash(32B)가 해시 체인의 최신 앵커
audit-sync-integrity-chain.md (Phase 30) POLICY_CHANGE 이벤트가 AuditSyncPayload로 동기화
policy-update-bundle.md (Plan 01) PolicyUpdateBundle 적용이 PolicyVersionRecord 생성 트리거
regulatory-tag-bitmap.md (Plan 01) 정책 변경 시 reg_tags before/after 기록

2. PolicyVersionRecord CDDL 스키마

2.1. CDDL 정의

; ====================================================================
; D'CENT Enterprise PolicyVersionRecord Schema
; 정책 변경 이력 해시 체인의 단위 레코드
; Phase: 31-hardware-policy-engine
; ====================================================================

PolicyVersionRecord = {
    version_number:     uint .size 4,           ; 정책 버전 (단조 증가, uint32)
    policy_hash:        bstr .size 32,          ; 이 버전 정책의 SHA-256 해시
    prev_version_hash:  bstr .size 32,          ; SHA-256(직전 PolicyVersionRecord)
    applied_at:         uint .size 4,           ; 적용 시점 (epoch seconds)
    applied_by:         ActorSummary,           ; 적용 주체 (요약)
    bundle_id:          bstr .size 16,          ; PolicyUpdateBundle UUID
    jurisdiction_id:    JurisdictionCode,       ; 적용된 관할 코드
    change_summary:     ChangeSummary,          ; 변경 요약
    quorum_proof:       QuorumProof,            ; 쿼럼 승인 증명
    reg_tags_snapshot:  RegulationTagBitmap,    ; 이 버전의 규제 태그 스냅샷
    record_hash:        bstr .size 32,          ; SHA-256(이 레코드 전체) - 해시 체인 링크
}

ActorSummary = {
    role:       RBACRole,                       ; RBAC 역할
    device_id:  bstr .size 8,                   ; 기기 식별자
}

ChangeSummary = {
    change_type:    PolicyChangeType,           ; 변경 유형
    rules_added:    uint .size 2,               ; 추가된 규칙 수
    rules_modified: uint .size 2,               ; 수정된 규칙 수
    rules_removed:  uint .size 2,               ; 제거된 규칙 수
    jurisdictions_changed: bool,                ; 관할 변경 여부
}

PolicyChangeType = &(
    change-initial:     1,                      ; 최초 정책 적용
    change-normal:      2,                      ; 정상 정책 변경
    change-emergency:   3,                      ; 긴급 정책 (Emergency Override)
    change-jurisdiction: 4,                     ; 관할 변경/추가
    change-rollforward: 5,                      ; 긴급 정책 만료 후 정상 복구
)

QuorumProof = {
    required_m:     uint .size 1,               ; 필요 서명 수 (M)
    total_n:        uint .size 1,               ; 전체 서명자 수 (N)
    signer_ids:     [+ bstr .size 8],           ; 서명자 기기 ID 목록
    proof_hash:     bstr .size 32,              ; SHA-256(모든 쿼럼 서명 연결)
}

2.2. 해시 체인 구조

Genesis (v0)        Version 1           Version 2           Version N (현재)
┌──────────┐     ┌──────────┐        ┌──────────┐        ┌──────────┐
│ v_num: 0 │     │ v_num: 1 │        │ v_num: 2 │        │ v_num: N │
│ p_hash:  │     │ p_hash:  │        │ p_hash:  │        │ p_hash:  │
│  0x00*32 │     │  <hash1> │        │  <hash2> │        │  <hashN> │
│ prev:    │     │ prev:    │        │ prev:    │        │ prev:    │
│  0x00*32 │──>  │  SHA256  │──>     │  SHA256  │──> ... │  SHA256  │
│          │     │  (v0)    │        │  (v1)    │        │  (vN-1)  │
│ r_hash:  │     │ r_hash:  │        │ r_hash:  │        │ r_hash:  │
│  <rh_0>  │     │  <rh_1>  │        │  <rh_2>  │        │  <rh_N>  │
└──────────┘     └──────────┘        └──────────┘        └──────────┘
                                                               │
                                                               v
                                                     SE policy_hash = <hashN>
                                                     (SEAuditDigest 내)

해시 체인 규칙: 1. prev_version_hash = SHA-256(직전 PolicyVersionRecord 전체) 2. record_hash = SHA-256(이 레코드의 모든 필드, record_hash 자신은 제외) 3. Genesis 레코드(v0): prev_version_hash = 0x00 * 32, policy_hash = 0x00 * 32 4. SE에 저장되는 policy_hash는 최신 버전의 policy_hash와 일치해야 함

2.3. 레코드 크기 추정

필드 크기 비고
version_number 4B uint32
policy_hash 32B SHA-256
prev_version_hash 32B SHA-256
applied_at 4B epoch
applied_by ~10B role + device_id
bundle_id 16B UUID
jurisdiction_id 1B 열거형
change_summary ~10B 유형 + 카운터
quorum_proof ~50B M/N + IDs + hash
reg_tags_snapshot 8B 비트맵
record_hash 32B SHA-256
CBOR 오버헤드 ~20B 맵 헤더
합계 ~219B ~0.21KB/record

3. 3-Zone 정책 이력 분산 저장

3.1. Zone별 역할

Zone 저장 내용 용량 역할
Zone 3 (SE) policy_hash(32B) + policy_version(4B) 36B 최신 상태의 암호학적 앵커
Zone 2 (오프라인 앱) 최근 N개 PolicyVersionRecord ~11KB (50개) 로컬 캐시, SE 대조 검증
Zone 1 (대시보드) 전체 PolicyVersionRecord 체인 무제한 영구 보존, 검색/필터/보고서

3.2. Zone 3 (SE) 상세

SE는 해시 체인의 앵커 역할만 수행한다. 전체 체인을 저장하지 않는다.

SE NVM 정책 영역:

Offset  Size  Field            Description
------  ----  ---------------  ------------------------------------------
0x00    4     policy_version   현재 적용 정책 버전 (단조 증가)
0x04    32    policy_hash      현재 정책의 SHA-256 (SEAuditDigest와 동일 값)
------  ----  ---------------  ------------------------------------------
Total:  36 bytes (NVM 별도 영역, SEAuditDigest와 별개)

(*) SEAuditDigest.policy_hash(32B)와 이 영역의 policy_hash는 동일 값.
    SEAuditDigest는 다이제스트 서명에 포함되는 복사본.
    이 영역은 APPLY_POLICY 시 원자적으로 갱신되는 마스터 카피.

policy_version 단조 증가 강제: - SE는 APPLY_POLICY 시 수신 policy_version > NVM 저장 policy_version 확인 - 조건 미충족 시: 0x6A83 (버전 역행) 에러 반환 - 이 메커니즘이 정책 롤백 방지의 최종 방어선

3.3. Zone 2 (오프라인 앱) 상세

오프라인 앱은 최근 N개의 PolicyVersionRecord를 로컬 캐시하여 즉시 검증에 활용한다.

오프라인 앱 정책 캐시:

- 최대 저장: 50개 PolicyVersionRecord (~11KB)
- 저장 방식: 최신순 순환 버퍼 (50개 초과 시 가장 오래된 레코드 제거)
- 동기화: AuditSyncPayload에 POLICY_CHANGE 이벤트로 대시보드에 전달
- 검증: 앱 시작 시 SE READ_POLICY로 현재 policy_hash 읽고 캐시와 대조

앱 시작 시 검증 흐름:
1. SE에서 READ_POLICY(P2=0x01) -> policy_version + policy_hash 수신
2. 로컬 캐시의 최신 PolicyVersionRecord와 비교
3. 일치: 정상
4. 불일치:
   a. SE 버전 > 캐시 버전: 다른 앱에서 정책 변경됨 -> 캐시 갱신 필요
   b. SE 버전 < 캐시 버전: 불가능 (SE 단조 증가) -> 변조 의심
   c. 버전 일치, 해시 불일치: 변조 의심 -> SECURITY_EVENT 생성

3.4. Zone 1 (대시보드) 상세

대시보드는 전체 해시 체인을 영구 보존하고 감사/보고 기능을 제공한다.

대시보드 정책 이력 저장소:

- 저장: Genesis(v0)부터 현재(vN)까지 전체 PolicyVersionRecord
- 인덱스: version_number, applied_at, jurisdiction_id, change_type
- 검색: 시점 범위, 관할별, 변경 유형별 필터
- 보고서: 정책 변경 이력 보고서, 감사 대응 추출
- 검증: 주기적 해시 체인 무결성 검증 (매 동기화 수신 시)

해시 체인 무결성 검증:
1. Genesis(v0)부터 순회
2. 각 레코드의 record_hash 재계산 → 저장된 record_hash와 비교
3. 각 레코드의 prev_version_hash == 직전 레코드의 record_hash 확인
4. 최신 레코드의 policy_hash == SE에서 읽은 policy_hash 확인 (동기화 시)
5. 검증 실패 시: 변조 구간 특정 + SECURITY_EVENT 생성

4. 정책 상태 시점 증명 (Point-in-Time Attestation)

4.1. 증명 프로토콜 (4단계)

감사인이 특정 시점 T의 정책 상태를 요청했을 때, 해시 체인과 SE 서명으로 증명하는 메커니즘.

Step 1: 대시보드에서 시점 T의 PolicyVersionRecord 조회
────────────────────────────────────────────────
감사인이 시점 T 지정
  -> 대시보드 DB에서 applied_at <= T인 최신 PolicyVersionRecord 검색
  -> 결과: PolicyVersionRecord(vK) (시점 T에 유효했던 정책 버전)

Step 2: 해당 레코드의 policy_hash 확인
────────────────────────────────────────────────
PolicyVersionRecord(vK).policy_hash = 시점 T의 정책 해시
PolicyVersionRecord(vK).reg_tags_snapshot = 시점 T의 규제 태그
PolicyVersionRecord(vK).jurisdiction_id = 시점 T의 관할

Step 3: SE 현재 상태에서 역추적하여 해시 체인 검증
────────────────────────────────────────────────
SE에서 READ_POLICY -> 현재 policy_hash (vN)
대시보드에서 vN -> vN-1 -> ... -> vK+1 -> vK 해시 체인 역순회
각 단계에서 prev_version_hash == 직전 record_hash 확인
  -> 체인이 끊기지 않음 = vK가 vN의 유효한 선조임을 증명

Step 4: 쿼럼 승인 증명
────────────────────────────────────────────────
PolicyVersionRecord(vK).quorum_proof 확인:
  - required_m명 이상의 서명자가 승인했음을 proof_hash로 확인
  - 서명자 기기 ID로 역할 검증 가능
산출물: PolicyAttestationReport

4.2. PolicyAttestationReport 구조

; 감사용 정책 상태 증명 보고서
PolicyAttestationReport = {
    report_id:          bstr .size 16,          ; UUID v7
    requested_time:     uint .size 4,           ; 감사인 요청 시점 T (epoch)
    effective_record:   PolicyVersionRecord,    ; 시점 T에 유효했던 레코드
    chain_proof: {
        current_se_hash:  bstr .size 32,        ; SE 현재 policy_hash
        current_version:  uint .size 4,         ; SE 현재 policy_version
        chain_length:     uint .size 4,         ; vK -> vN 체인 길이
        chain_valid:      bool,                 ; 체인 무결성 검증 결과
        se_digest_sig:    bstr .size 20,        ; SE 다이제스트 서명 (신뢰 앵커)
    },
    quorum_verified:    bool,                   ; 쿼럼 승인 검증 결과
    generated_at:       uint .size 4,           ; 보고서 생성 시점
    generated_by:       tstr,                   ; 생성 주체 (대시보드 ID)
}

4.3. 증명 신뢰 체인

신뢰 체인:

SE digest_sig (EAL5+ 하드웨어 서명)
    │
    v
SEAuditDigest.policy_hash (SE NVM, 하드웨어 보호)
    │
    v
PolicyVersionRecord(vN).policy_hash == SE policy_hash (일치 확인)
    │
    v
PolicyVersionRecord(vN) -> ... -> PolicyVersionRecord(vK) (해시 체인 검증)
    │
    v
PolicyVersionRecord(vK) = 시점 T의 정책 상태 (증명 완료)
    │
    v
QuorumProof = 쿼럼 승인이 있었음의 증명

신뢰 근거:
- SE 서명: EAL5+ 하드웨어가 보호하는 개인키로 서명 -> 위조 불가
- 해시 체인: 중간 레코드 변조 시 후속 레코드의 prev_version_hash 불일치
- 단조 증가: SE policy_version 롤백 불가 -> 가짜 역사 삽입 불가

5. 정책 롤백 방지 메커니즘

5.1. 다층 방어

방어 계층 메커니즘 공격 차단
Layer 1: SE 단조 증가 policy_version 이전 값 거부 (0x6A83) 이전 정책 재적용
Layer 2: 해시 체인 연속성 prev_policy_hash != SE 현재 policy_hash 시 거부 (0x6A86) 중간 정책 건너뛰기
Layer 3: 쿼럼 서명 M-of-N 서명 검증 실패 시 거부 (0x6A82) 비인가 정책 변경
Layer 4: 해시 체인 무결성 대시보드 주기적 전체 체인 검증 사후 변조 탐지

5.2. 긴급 정책과 버전 체인

긴급 정책(Emergency Override)은 정상 버전 체인에 포함되되, change_type=change-emergency로 표기된다.

정상 버전 체인에서 긴급 정책:

v5 (normal) -> v6 (emergency, 72시간 만료) -> v7 (rollforward, 정상 복구)

PolicyVersionRecord(v6) = {
    version_number:    6,
    change_summary: {
        change_type:   change-emergency (3),
        ...
    },
    quorum_proof: {
        required_m:    1,  // Org Owner 단독
        total_n:       1,
        ...
    },
}

PolicyVersionRecord(v7) = {
    version_number:    7,
    change_summary: {
        change_type:   change-rollforward (5),  // 긴급 해제 후 정상 복구
        ...
    },
    quorum_proof: {
        required_m:    2,  // 정상 쿼럼 복귀
        total_n:       3,
        ...
    },
}

5.3. 공격 시나리오별 방어

시나리오 공격 방어 결과
1. 이전 정책 재적용 공격자가 v3 PolicyUpdateBundle을 SE에 재전송 SE: policy_version(3) <= 현재(5) -> 0x6A83 거부
2. 체인 건너뛰기 v4를 건너뛰고 v5 적용 시도 SE: prev_policy_hash != 현재 -> 0x6A86 거부
3. 가짜 쿼럼 위조 서명으로 PolicyUpdateBundle 생성 SE: 쿼럼 서명 검증 실패 -> 0x6A82 거부
4. 사후 기록 변조 대시보드 DB에서 PolicyVersionRecord 수정 해시 체인 검증 실패 + SE policy_hash 불일치 탐지
5. 기기 교체 공격 정책이 적용된 SE를 다른 SE로 교체 target_device_id 불일치 -> 0x6985 거부

6. SE NVM 메모리 예산 최종 갱신

6.1. v0.6.1 최종 NVM 레이아웃

SE NVM 메모리 레이아웃 (v0.6.1 최종)

총 NVM: 16,384 bytes (16 KB)

기존 사용 (v0.5):                          ~3,712 bytes
v0.6 추가 (Phase 30):                         136 bytes
v0.6.1 추가 (Phase 31 Plan 01):              ~128 bytes
v0.6.1 추가 (Phase 31 Plan 02):               ~36 bytes
  - policy_version NVM 미러링:                   4 bytes  (*)
  - policy_hash 마스터 카피:                    32 bytes  (**)
─────────────────────────────────────────────────────────
v0.6.1 최종 총 사용:                       ~4,012 bytes (~3.92 KB)
여유 공간:                                ~12,372 bytes (~12.08 KB)
사용률:                                    24.5% (16 KB 대비)

(*) SEAuditDigest.policy_hash와 별개의 마스터 카피.
    APPLY_POLICY 시 원자적 갱신의 소스.
(**) PolicyVersionRecord 전체는 SE에 저장하지 않음.
     Zone 2/Zone 1에서 체인 유지.

6.2. Phase 31 전체 NVM 영향 요약

Phase 31 추가 항목 크기 출처
RegulationTagBitmap (글로벌) 8B Plan 01
규칙별 reg_tags 확장 ~120B Plan 01
policy_version NVM 미러링 4B Plan 02
policy_hash 마스터 카피 32B Plan 02
Phase 31 총 추가 ~164B
v0.6.1 최종 사용 ~4,012B (24.5%)
여유 ~12,372B (75.5%)

Phase 32+ 확장에 충분한 여유 확보. 16KB 한도의 1/4 미만 사용.


7. Phase 연동점

7.1. Phase 30 연동

연동점 설명
SEAuditDigest.policy_hash PolicyVersionRecord 해시 체인의 최신 앵커. SE NVM의 policy_hash와 항상 일치
POLICY_CHANGE AuditRecord 정책 변경 시 생성. PolicyVersionRecord의 소스 이벤트
AuditSyncPayload POLICY_CHANGE 이벤트가 CompactAuditRecord로 대시보드에 동기화
3계층 무결성 체인 정책 해시 체인이 3계층 무결성 체인의 일부로 기능

7.2. Phase 32 연동

연동점 설명
컴플라이언스 보고서 PolicyVersionRecord.reg_tags_snapshot이 컴플라이언스 체크리스트 생성의 입력
Compliance-as-Code 정책 이력 기반 규제 충족 상태 자동 판단
ISMS-P/MiCA/SOC 2 감사 PolicyAttestationReport가 감사 대응의 핵심 증적

7.3. CORE-09 완전 대응

본 문서의 설계로 CORE-09(정책 변경 이력 관리)가 완전히 대응된다:

CORE-09 요건 대응
정책 변경 이력 기록 PolicyVersionRecord 해시 체인
변조 불가 이력 SE policy_hash 앵커 + 해시 체인
승인 이력 추적 QuorumProof (서명자, 시점)
임의 시점 상태 확인 Point-in-Time Attestation 4단계
장기 보존 Zone 1 영구 보존

Phase: 31-hardware-policy-engine, Plan: 02 Version: 1.0 해시 체인: SHA-256 기반 PolicyVersionRecord 단방향 연결 SE NVM: v0.6.1 최종 ~4.0KB / 16KB (24.5% 사용) 시점 증명: SE digest_sig -> policy_hash -> 해시 체인 역추적 -> 쿼럼 증명


관련 문서