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 -> 해시 체인 역추적 -> 쿼럼 증명
관련 문서¶
- 규제 관할별 사전 구성 정책 프로파일 설계 -- 펌웨어 요구사항
- PolicyUpdateBundle UR 타입 및 에어갭 정책 동기화 프로토콜 -- 펌웨어 요구사항
- 규제 태그 비트맵 CDDL 스키마 및 SE 불변 규칙 매핑 -- 펌웨어 요구사항