NitroTPM Attestation Document 검증
NitroTPM Attestation Document 검증 (Validate a NitroTPM Attestation Document)
참고: 이 주제는 타사 키 관리 서비스를 사용하고 자체 Attestation Document 검증 메커니즘을 구축해야 하는 사용자를 위한 것이에요.
이 주제는 전체 NitroTPM attestation 흐름에 대한 자세한 개요를 제공해요. Attestation Document가 요청될 때 AWS Nitro 시스템이 무엇을 생성하는지, 그리고 키 관리 서비스가 Attestation Document를 어떻게 처리해야 하는지 설명해요.
출처: 문서
본문
attestation의 목적은 인스턴스가 실행 중인 코드와 구성에 기반해 인스턴스가 신뢰할 수 있는 엔터티임을 증명하는 것이에요. 인스턴스의 신뢰 루트는 Attestation Documents를 제공하는 AWS Nitro 시스템 내에 존재해요.
Attestation Documents는 AWS Nitro Attestation 공개 키 인프라(PKI)로 서명되며, 여기에는 어떤 서비스에도 통합할 수 있는 게시된 인증 기관이 포함돼요.
Attestation Document
Attestation Documents는 CBOR(Concise Binary Object Representation, RFC 8949)로 인코딩되고, COSE(CBOR Object Signing and Encryption)로 서명돼요.
Attestation Document 사양:
AttestationDocument = {
module_id: text, ; 발급 Nitro 하이퍼바이저 모듈 ID
timestamp: uint .size 8, ; 문서 생성 시각(UNIX epoch 이후 밀리초, UTC)
digest: digest, ; 레지스터 값 계산에 사용된 해시 함수
nitrotpm_pcrs: { + index => pcr }, ; Attestation Document 생성 시점의 PCR 맵
certificate: cert, ; Attestation Document 서명에 사용된 공개 키의 인증서
cabundle: [* cert], ; 인프라 인증서용 발급 CA 번들
? public_key: user_data, ; (선택) attestation 소비자가 데이터 암호화에
; 사용할 수 있는 DER 인코딩 키
? user_data: user_data, ; (선택) 프로토콜로 정의된 추가 서명 사용자 데이터
? nonce: user_data, ; (선택) attestation 소비자가 제공한 암호화 nonce
; (진위 증명용)
}
cert = bytes .size (1..1024) ; DER 인코딩 인증서
user_data = bytes .size (0..1024)
pcr = bytes .size (32/48/64) ; PCR 내용
index = 0..31
digest = "SHA384"
Attestation Document의 선택 파라미터(public_key, user_data, nonce)는 증명 인스턴스와 외부 서비스 사이의 맞춤형 검증 프로토콜을 설정하는 데 사용할 수 있어요.
Attestation Document 검증
Nitro Hypervisor에서 Attestation Document를 요청하면 서명된 Attestation Document를 포함하는 바이너리 blob을 받아요. 서명된 Attestation Document는 CBOR 인코딩되고 COSE_Sign1 서명 구조로 COSE 서명된 객체예요. 전체 검증 과정은 다음 단계를 포함해요.
- CBOR 객체를 디코딩해 COSE_Sign1 구조로 매핑해요.
- COSE_Sign1 구조에서 Attestation Document를 추출해요.
- 인증서 체인을 검증해요.
- Attestation Document가 올바르게 서명되었는지 확인해요.
Attestation Documents는 상용 AWS 파티션용 루트 인증서를 포함하는 AWS Nitro Attestation PKI로 서명돼요. 루트 인증서는 https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip에서 다운로드할 수 있고, 다음 지문으로 검증할 수 있어요.
64:1A:03:21:A3:E2:44:EF:E4:56:46:31:95:D6:06:31:7E:D7:CD:CC:3C:17:56:E0:98:93:F3:C6:8F:79:BB:5B
루트 인증서는 AWS Certificate Manager Private Certificate Authority(AWS Private CA) 프라이빗 키를 기반으로 하며 수명이 30년이에요. PCA의 주체는 다음과 같은 형식이에요.
CN=aws.nitro-enclaves, C=US, O=Amazon, OU=AWS
COSE와 CBOR
보통 COSE_Sign1 서명 구조는 메시지에 서명 하나만 넣을 때 사용돼요. 내용과 서명을 다루는 파라미터는 COSE_Sign처럼 분리하지 않고 보호된 헤더(protected header)에 배치돼요. 구조는 사용되는 컨텍스트에 따라 tagged 또는 untagged로 인코딩될 수 있어요. tagged COSE_Sign1 구조는 CBOR 태그 18로 식별돼요.
본문, 서명, 본문·서명에 대한 정보를 담는 CBOR 객체를 COSE_Sign1 구조라고 해요. COSE_Sign1 구조는 CBOR 배열이며 다음 필드를 포함해요.
[
protected: Header,
unprotected: Header,
payload: This field contains the serialized content to be signed,
signature: This field contains the computed signature value.
]
Attestation Document 맥락에서 배열은 다음을 포함해요.
18(/* COSE_Sign1 CBOR tag is 18 */
{1: -35}, /* {algorithm: ECDS 384} 와 동일 */
{}, /* unprotected에 아무것도 없음 */
$ATTESTATION_DOCUMENT_CONTENT /* Attestation Document */,
signature /* 서명 */
)
의미론적 유효성 (Semantic validity)
Attestation Document는 항상 CA 번들을 다음 순서로 가져요.
[ ROOT_CERT - INTERM_1 - INTERM_2 .... - INTERM_N]
0 1 2 N - 1
Java의 CertPath 같은 일부 기존 도구는 다른 순서를 요구할 수 있으니 이 순서를 기억하세요. 인증서를 검증하려면 Attestation Document CA 번들에서 시작해 필요한 체인을 생성해요. 여기서 TARGET_CERT는 Attestation Document의 인증서예요.
[TARGET_CERT, INTERM_N, ..... , INTERM_2, INTERM_1, ROOT_CERT]
인증서 유효성 (Certificate validity)
체인의 모든 인증서에 대해 현재 날짜가 인증서에 지정된 유효 기간 내에 있어야 해요.
인증서 체인 유효성 (Certificate chain validity)
일반적으로 공개 키 소유자의 인증서(한 CA가 서명)와 다른 CA가 서명한 추가 인증서(0개 이상)로 구성된 여러 인증서의 체인이 필요할 수 있어요. 이런 체인(인증 경로라고 함)은 공개 키 사용자가 제한된 수의 보장된 CA 공개 키로만 초기화되기 때문에 필요해요. 인터넷 PKI의 인증 경로 검증 절차는 X.509에 제공된 알고리즘을 기반으로 해요. 인증 경로 처리는 주체 고유 이름 및/또는 주체 대체 이름과 주체 공개 키 사이의 바인딩을 검증해요.
참고: 검증 시 CRL을 비활성화해야 해요.
Java에서 루트 경로와 생성된 인증서 체인으로 시작해 체인 검증은 다음과 같이 해요.
validateCertsPath(certChain, rootCertficate) {
/* 신뢰 앵커는 신뢰할 루트 CA */
trustAnchors.add(rootCertificate);
/* 신뢰 앵커와 CRL 검증 비활성화를 위해 PKIX 파라미터 필요 */
validationParameters = new PKIXParameters(trustAnchors);
certPathValidator = CertPathValidator.getInstance(PKIX);
validationParameters.setRevocationEnabled(false);
/* 인증서가 올바르게 체인되었는지 확인 */
certPathValidator.validate(certPath, validationParameters);
}