あどけない話

Internet technologies

TLS 1.3 開発日記 その17 AEAD

TLS 1.2とTLS 1.3のAEAD の違いについて、AEADの一つであるAES 128 GCMを例にとって説明する。

TLS 1.2のAEAD

以下の3つのRFCをよーく読まないといけない。

  • RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2
  • RFC 5116: An Interface and Algorithms for Authenticated Encryption
  • RFC 5288: AES Galois Counter Mode (GCM) Cipher Suites for TLS

RFC 5246 の 6.2.3.3 節では、AEADで暗号化されたレコードが以下のように定義してある。

struct {
    opaque nonce_explicit[SecurityParameters.record_iv_length];
    aead-ciphered struct {
        opaque content[TLSCompressed.length];
    };
} GenericAEADCipher;

aead-ciphered の部分は、以下の関数で生成される。

AEADEncrypted = AEAD-Encrypt(write_key, nonce, plaintext, additional_data)

賢明な読者なら「authentication tag はどこにいった?」と疑問に思うだろう。RFC 5116の5.1節には、こう書いてある。

The AEAD_AES_128_GCM ciphertext is formed by appending the authentication tag provided as an output to the GCM encryption operation to the ciphertext that is output by that operation.

つまり、AEAD-Encryptの中身はこんな感じ:

AEAD-Encrypt(write_key, nonce, plaintext, additional_data) {
    (cipher, auth_tag) = aead-encrypt(write_key, nonce, plaintext, additional_data);
    return (cipher + auth_tag);
}

一方、AEAD-Decryptのインターフェイスは、こう定義してある:

TLSCompressed.fragment = AEAD-Decrypt(write_key, nonce, AEADEncrypted, additional_data)

中身はこんな感じになる:

AEAD-Decrypt(write_key, nonce, AEADEncrypted, additional_data) {
    (cipher, auth_tag1) = split(AEADEncrypted);
    (plaintext, auth_tag2) = aead_decrypt(write_key, nonce, cipher, additional_data);
    if (auth_tag1 != auth_tag2) throw_error();
    return plaintext;
}

引数のadditonal_dataも、RFC 5246に定義してある:

additional_data = seq_num + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length;

この後半の3つであるが、TLSCompressedレコードの定義をみると、なんのことはない、レコードヘッダだと分かるだろう。

struct {
    ContentType type;       /* same as TLSPlaintext.type */
    ProtocolVersion version;/* same as TLSPlaintext.version */
    uint16 length;
    opaque fragment[TLSCompressed.length];
} TLSCompressed;

つまり、こういうことである。

additional_data = seq_num + レコードのヘッダ

最後は nonce。RFC 5116の5.1節には、"N_MIN and N_MAX are both 12 octets" と書いてある。最小値も最大値も12バイトだから、nonceは12バイトであると分かる。RFC 5288は、こう書かれている:

          struct {
                opaque salt[4];
                opaque nonce_explicit[8];
             } GCMNonce;

   The salt is the "implicit" part of the nonce and is not sent in the
   packet.  Instead, the salt is generated as part of the handshake
   process: it is either the client_write_IV (when the client is
   sending) or the server_write_IV (when the server is sending).  The
   salt length (SecurityParameters.fixed_iv_length) is 4 octets.

というわけで、4バイトのsaltにはclient_write_IVかserver_write_IVを入れればよい。nonce_explicitについては:

The nonce_explicit MAY be the 64-bit sequence number.

なので、seq_numでよいと分かる。

TLS 1.2 を実装するの、嫌になったでしょ?

TLS 1.3のAEAD

TLS 1.3のAEADを理解するには、ドラフトを読めばよい。

the additional data input is empty (zero length)

というわけで、additional data には空文字列を渡す。

nonce は、

  • The 64-bit record sequence number is encoded in network byte order and padded to the left with zeros to iv_length.
  • The padded sequence number is XORed with the static client_write_iv or server_write_iv, depending on the role.

のように作ればよい。