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 서명된 객체예요. 전체 검증 과정은 다음 단계를 포함해요.

  1. CBOR 객체를 디코딩해 COSE_Sign1 구조로 매핑해요.
  2. COSE_Sign1 구조에서 Attestation Document를 추출해요.
  3. 인증서 체인을 검증해요.
  4. 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);
}

더 알아보기