

# NitroTPM アテステーションドキュメントを検証する
<a name="nitrotpm-attestation-document-validate"></a>

**注記**  
このトピックは、サードパーティーのキー管理サービスを使用していて、独自のアテステーションドキュメント検証メカニズムを構築する必要があるユーザーを対象としています。

このトピックでは、NitroTPM アテステーションフロー全体の概要を詳しく説明します。また、アテステーションドキュメントがリクエストされたときに AWS Nitro システムによって生成される内容と、キー管理サービスがアテステーションドキュメントを処理する方法について説明します。

**Topics**
+ [アテステーションドキュメント](#doc-def)
+ [アテステーションドキュメントの検証](#validation-process)

アテステーションの目的は、実行中のコードと設定に基づいて、インスタンスが信頼できるエンティティであることを証明することです。インスタンスの信頼の根源は、アテステーションドキュメントを提供する AWS Nitro システム内にあります。

アテステーションドキュメントは AWS Nitro Attestation Public Key Infrastructure (PKI) によって署名されます。PKI には、任意のサービスに組み込むことができる公開認証機関が含まれます。

## アテステーションドキュメント
<a name="doc-def"></a>

アテステーションドキュメントは Concise Binary Object Representation (CBOR) でエンコードされ、CBOR Object Signing and Encryption (COSE) を使用して署名されます。

CBOR の詳細については、「[RFC 8949: Concise Binary Object Representation (CBOR)](https://www.rfc-editor.org/rfc/rfc8949.html)」を参照してください。

### アテステーションドキュメントの仕様
<a name="doc-spec"></a>

以下は、アテステーションドキュメントの構造を示しています。

```
AttestationDocument = {
    module_id: text,                     ; issuing Nitro hypervisor module ID
    timestamp: uint .size 8,             ; UTC time when document was created, in
                                         ; milliseconds since UNIX epoch
    digest: digest,                      ; the digest function used for calculating the
                                         ; register values
    nitrotpm_pcrs: { + index => pcr },   ; map of PCRs at the moment the Attestation Document was generated
    certificate: cert,                   ; the public key certificate for the public key 
                                         ; that was used to sign the Attestation Document
    cabundle: [* cert],                  ; issuing CA bundle for infrastructure certificate
    ? public_key: user_data,             ; an optional DER-encoded key the attestation
                                         ; consumer can use to encrypt data with
    ? user_data: user_data,              ; additional signed user data, defined by protocol
    ? nonce: user_data,                  ; an optional cryptographic nonce provided by the
                                         ; attestation consumer as a proof of authenticity
}

cert = bytes .size (1..1024)       ; DER encoded certificate
user_data = bytes .size (0..1024)
pcr = bytes .size (32/48/64)       ; PCR content
index = 0..31
digest = "SHA384"
```

アテステーションドキュメントのオプションパラメータ (`public_key`、`user_data`、および `nonce`) を使用して、アテステーションを行うインスタンスと外部サービスの間にカスタム検証プロトコルを確立できます。

## アテステーションドキュメントの検証
<a name="validation-process"></a>

Nitro Hypervisor からアテステーションドキュメントをリクエストすると、署名されたアテステーションドキュメントを含むバイナリ BLOB を受け取ります。署名付きアテステーションドキュメントは、CBOR エンコードされ、 COSE 署名 (COSE\$1Sign1 署名構造を使用) されたオブジェクトです。全体的な検証プロセスには、次のステップが含まれます。

1. CBOR オブジェクトをデコードし、COSE\$1Sign1 構造にマッピングします。

1. COSE\$1Sign1 構造からアテステーションドキュメントを抽出します。

1. 証明書のチェーンを確認します。

1. アテステーションドキュメントが正しく署名されていることを確認します。

アテステーションドキュメントは、商用 AWS パーティションのルート証明書を含む AWS Nitro Attestation PKI によって署名されます。ルート証明書は [https://aws-nitro-enclaves.amazonaws.com/AWS\$1NitroEnclaves\$1Root-G1.zip](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
```

**Topics**
+ [COSE と CBOR](#COSE-CBOR)
+ [セマンティックの有効性](#semantic-validation)
+ [証明書の有効性](#cert-validity)
+ [証明書チェーンの有効性](#chain)

### COSE と CBOR
<a name="COSE-CBOR"></a>

通常、COSE\$1Sign1 署名構造は、1 つの署名のみがメッセージに配置される場合に使用されます。コンテンツと署名を処理するパラメータは、COSE\$1Sign を分離するのではなく、保護されたヘッダーに配置されます。構造は、使用するコンテキストに応じて、タグ付けまたはタグ無しのいずれかでエンコードできます。タグ付きの COSE\$1Sign1 構造は、CBOR タグ 18 によって識別されます。

本文、署名、および本文と署名に関する情報を保持する CBOR オブジェクトは、COSE\$1Sign1 構造と呼ばれます。COSE\$1Sign1 構造は CBOR 配列です。配列には、次のフィールドが含まれます。

```
[
  protected:   Header,
  unprotected: Header,
  payload:     This field contains the serialized content to be signed,
  signature:   This field contains the computed signature value.
]
```

アテステーションドキュメントのコンテキストでは、配列には以下が含まれます。

```
18(/* COSE_Sign1 CBOR tag is 18 */
    {1: -35}, /* This is equivalent with {algorithm: ECDS 384} */
    {}, /* We have nothing in unprotected */
    $ATTESTATION_DOCUMENT_CONTENT /* Attestation Document */,
    signature /* This is the signature */
)
```

CBOR の詳細については、「[RFC 8949: Concise Binary Object Representation (CBOR)](https://www.rfc-editor.org/rfc/rfc8949.html)」を参照してください。

### セマンティックの有効性
<a name="semantic-validation"></a>

アテステーションドキュメントには、常に次の順序で CA バンドルがあります。

```
[ ROOT_CERT - INTERM_1 - INTERM_2 .... - INTERM_N]
      0          1          2             N - 1
```

この順序は、「[Java PKI プログラマーズガイド](https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html)」の Java の CertPath など、既存のツールによっては順序が異なる必要がある場合があることに注意してください。

証明書を検証するには、アテステーションドキュメント CA バンドルから開始し、必要なチェーンを生成します。ここで、`TARGET_CERT` はアテステーションドキュメントの証明書です。

```
[TARGET_CERT, INTERM_N, ..... , INTERM_2, INTERM_1, ROOT_CERT]
```

### 証明書の有効性
<a name="cert-validity"></a>

チェーン内のすべての証明書について、現在の日付が証明書で指定された有効期間内であることを確認する必要があります。

### 証明書チェーンの有効性
<a name="chain"></a>

一般的に、ある CA によって署名されたパブリックキー所有者の証明書と、他の CA によって署名された CA の追加の証明書 (無くてもよく、複数でもよい) で構成される、複数の証明書のチェーンが必要になる場合があります。パブリックキーユーザーは限られた数の保証された CA パブリックキーでのみ初期化されるため、認証パスと呼ばれるこのようなチェーンが必要です。インターネット PKI の認証パスの検証手順は、X.509 で提供されているアルゴリズムに基づいています。認証パス処理は、サブジェクト識別名および/またはサブジェクト代替名と、サブジェクトパブリックキーとの間のバインドを検証します。バインドは、そのパスを構成する証明書で指定された制約と、証明書利用者によって指定された入力によって制限されます。基本的な制約とポリシー制約の拡張により、認証パス処理ロジックで意思決定プロセスを自動化できます。

**注記**  
検証を実行するときは CRL を無効にする必要があります。

ルートパスと生成された証明書チェーンから Java の使用を開始する場合、チェーンの検証は次のようになります。

```
validateCertsPath(certChain, rootCertficate) {
    /* The trust anchor is the root CA to trust */
    trustAnchors.add(rootCertificate);

    /* We need PKIX parameters to specify the trust anchors
     * and disable the CRL validation
     */
    validationParameters = new PKIXParameters(trustAnchors);
    certPathValidator = CertPathValidator.getInstance(PKIX);
    validationParameters.setRevocationEnabled(false);

    /* We are ensuring that certificates are chained correctly */
    certPathValidator.validate(certPath, validationParameters);
}
```