TLS 1.3: Hello Retry Request, Change Cipher Spec

# Hello Retry Request, Change Cipher Spec

今回のお題はこの２つ。Hello Retry Request, Change Cipher Spec。

これはどちらもサーバから１パケットで送られています。clientの返答 tcp ackはお約束。

| #    | src| dest   | type    | length | info           |
| ---- | ----------------- | ----------------- | ------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| 140  | example.com       | \*\*localhost\*\* | TLSv1.3 | 165    | Hello Retry Request, Change Cipher Spec|
| 141  | \*\*localhost\*\* | example.com       | TCP     | 66     | 58364 → 443 \[ACK\] Seq=518 Ack=100 Win=131392 Len=0 TSval=107391638 TSecr=2936265727|

このTCPパケットにはTLS record layer が2つ含まれています。同時に送れるんですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/521d8b4d-87f5-0d6c-3b6e-32c3dc99dfb0.png)

一つずつ見ていきます。

## TLS 全体

```yaml
Transport Layer Security
    TLSv1.3 Record Layer: Handshake Protocol: Hello Retry Request
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 88
        Handshake Protocol: Hello Retry Request
            Handshake Type: Server Hello (2)
            Length: 84
            Version: TLS 1.2 (0x0303)
            Random: cf21ad74e59a6111be1d8c021e65b891c2a211167abb8c5e079e09e2c8a8339c (HelloRetryRequest magic)
            Session ID Length: 32
            Session ID: b1c8e600556b5561ceda33e4c9c0b59221e45d11fb5cc03de4c165861b34f642
            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
            Compression Method: null (0)
            Extensions Length: 12
            Extension: supported_versions (len=2)
                Type: supported_versions (43)
                Length: 2
                Supported Version: TLS 1.3 (0x0304)
            Extension: key_share (len=2)
                Type: key_share (51)
                Length: 2
                Key Share extension
                    Selected Group: secp256r1 (23)
            [JA3S Fullstring: 771,4866,43-51]
            [JA3S: 15af977ce25de452b96affa2addb1036]
    TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message

```


## Hello Retry Request

このTLS recordは全部で 93 bytes ありました。これは、client helloで指定された鍵交換をサーバ側で受け入れられなかったので、代わりの方式で再度client helloを送るようにサーバが要望するパケットです。

まず Content typeはhandshakeです。handshake確立前なので、 **ここは平文です！**

```yaml
Transport Layer Security
    TLSv1.3 Record Layer: Handshake Protocol: Hello Retry Request
        Content Type: Handshake (22)
```

続いて handshake protocol . ここで事件が起きます。wiresharkでは Hello Retry Requestと書いてありますが、handshake typeが Server Hello (2) です！

```yaml
        Version: TLS 1.2 (0x0303)
        Length: 88
        Handshake Protocol: Hello Retry Request
            Handshake Type: Server Hello (2)
```

どういうことだってばよ・・


## session_id

サーバ側のsession idが初登場します。client helloで来たsession idとは違うものです。以後、このidでお互いのやり取りを見分けて、他の通信と混ざらないようにします。

```yml
            Session ID: b1c8e600556b5561ceda33e4c9c0b59221e45d11fb5cc03de4c165861b34f642
```

この後サーバは server helloを送りますが、そのときに送る session id も同一です。


さらに衝撃なのが random です。wireshark的には、カッコで `(HelloRetryRequest magic)` と書いてあります・・・なんだこりゃ。 client helloのrandomとは違うものですが、長さは同じで 32bytes ありました。

```yaml
            Random: cf21ad74e59a6111be1d8c021e65b891c2a211167abb8c5e079e09e2c8a8339c (HelloRetryRequest magic)
```

ServerHelloのrandomは鍵交換で重要になるものだと思いますが、再度 client helloからのやり直しをするわけで、あまり意味がなさそうな気はする。



その他のエリアは、暗号化にまつわるものです。client helloで提示されたものの中で、サーバが選んだのはこの cipher suiteでした。


```yaml
            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
```


楕円曲線のカーブは、client指定の  x25519 をサーバが嫌がったため、代わりに `secp256r1` を返しています。パケット全体の意図としては、この secp256r1 で再度 client helloをするように、という意味のようです。

```yaml
     Extension: key_share (len=2)
                Type: key_share (51)
                Length: 2
                Key Share extension
                    Selected Group: secp256r1 (23)
```

ここはwiresharkが足してるみたい。謎。
```yaml
            [JA3S Fullstring: 771,4866,43-51]
            [JA3S: 15af977ce25de452b96affa2addb1036]
```


# Change Cipher Spec

TLS 1.2 ではサーバが送る Change Cipher Specは暗号通信開始の合図のようですが、ここではまだClientHello送り直せ状態なので、よくわからない。全部やり直すから、いったんこれは終わり、という意味なんでしょうか。

> 4. サーバーがChangeCipherSpecで終わりを通知
⇒通信の暗号化開始
https://qiita.com/developer-kikikaikai/items/055a344c847379b471f7



このChange Cipher Spec TLS recordはなんと、全部で 6 bytes しかありません。changeするよ！と宣言するだけなのかな。

長さはこんな感じ。

```yml
    TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)   # 1 byte
        Version: TLS 1.2 (0x0303)              # 2 bytes
        Length: 1                             # 2 bytes
        Change Cipher Spec Message            # 1 byte

```

Change Cipher Spec Messageは超シンプルで、 `0000001` でした。

もしくは、想像ですが、直前に同送している Hello Retry Request でCipher suiteなどを指定しているので、それに基づいて暗号化を始めろ！って感じなんですかね。