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.
のように作ればよい。