RFC 9001 TLS를 사용하여 QUIC 보호하기 2021년 5월
Thomson & Turner 표준 트랙 [페이지]
스트림:
인터넷 엔지니어링 태스크포스 (IETF)
RFC:
9001
분류:
표준 트랙
게시일:
ISSN:
2070-1721
저자:
M. Thomson, 편집자
Mozilla
S. Turner, 편집자
sn3rd

RFC 9001

TLS를 사용하여 QUIC 보호하기

초록

이 문서는 QUIC을 보호하는 데 Transport Layer Security (TLS)가 어떻게 사용되는지 설명한다.

이 메모의 상태

이 문서는 인터넷 표준 트랙 문서이다.

이 문서는 인터넷 엔지니어링 태스크포스 (IETF)의 산출물이다. 이는 IETF 커뮤니티의 합의를 나타낸다. 이 문서는 공개 검토를 받았으며 인터넷 엔지니어링 운영 그룹 (IESG)에 의해 발행 승인을 받았다. 인터넷 표준에 관한 추가 정보는 RFC 7841의 2절에서 확인할 수 있다.

이 문서의 현재 상태, 모든 정오표, 그리고 이에 대한 피드백 제공 방법에 관한 정보는 https://www.rfc-editor.org/info/rfc9001에서 얻을 수 있다.

목차

1. 서론

이 문서는 TLS [TLS13]를 사용하여 QUIC [QUIC-TRANSPORT]이 어떻게 보호되는지 설명한다.

TLS 1.3은 이전 버전에 비해 연결 설정에서 중요한 지연 시간 개선을 제공한다. 패킷 손실이 없으면 대부분의 새 연결은 단일 왕복 내에 설정되고 보호될 수 있다. 동일한 클라이언트와 서버 사이의 후속 연결에서는 클라이언트가 종종 애플리케이션 데이터를 즉시 보낼 수 있는데, 즉 0 왕복 설정을 사용하는 것이다.

이 문서는 TLS가 QUIC의 보안 구성요소로 어떻게 동작하는지 설명한다.

2. 표기 규칙

이 문서의 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 및 "OPTIONAL"은 여기에 표시된 것처럼 모두 대문자로 나타날 때, 그리고 오직 그 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석된다.

이 문서는 [QUIC-TRANSPORT]에서 정립된 용어를 사용한다.

간결함을 위해 약어 TLS는 TLS 1.3을 가리키는 데 사용하지만, 더 새로운 버전이 사용될 수도 있다. 4.2절을 보라.

2.1. TLS 개요

TLS는 두 엔드포인트가 신뢰할 수 없는 매체(예: 인터넷)를 통해 통신 수단을 설정할 방법을 제공한다. TLS는 피어 인증을 가능하게 하고 엔드포인트가 교환하는 메시지에 대한 기밀성 및 무결성 보호를 제공한다.

내부적으로 TLS는 계층화된 프로토콜이며, 그 구조는 그림 1에 표시되어 있다.

          +-------------+------------+--------------+---------+
Content   |             |            |  Application |         |
Layer     |  Handshake  |   Alerts   |     Data     |   ...   |
          |             |            |              |         |
          +-------------+------------+--------------+---------+
Record    |                                                   |
Layer     |                      Records                      |
          |                                                   |
          +---------------------------------------------------+
그림 1: TLS 계층

각 콘텐츠 계층 메시지(예: 핸드셰이크, 경고, 애플리케이션 데이터)는 레코드 계층에 의해 일련의 형식화된 TLS 레코드로 운반된다. 레코드는 개별적으로 암호학적으로 보호된 다음, 순서 지정과 보장된 전달을 제공하는 신뢰성 있는 전송(일반적으로 TCP)을 통해 전송된다.

TLS 인증 키 교환은 클라이언트와 서버라는 두 엔드포인트 사이에서 발생한다. 클라이언트가 교환을 시작하고 서버가 응답한다. 키 교환이 성공적으로 완료되면 클라이언트와 서버 모두 하나의 비밀 값에 동의한다. TLS는 유한체 또는 타원 곡선 기반 Diffie-Hellman ((EC)DHE) 키 교환과 사전 공유 키(PSK)를 모두 지원한다. PSK는 Early Data (0-RTT)의 기반이다. 후자는 (EC)DHE 키가 폐기될 때 전방 보안(FS)을 제공한다. 두 모드를 결합하여 PSK를 인증에 사용하면서도 전방 보안을 제공할 수도 있다.

TLS 핸드셰이크를 완료한 후 클라이언트는 서버의 신원을 알아내고 인증하게 되며, 서버는 선택적으로 클라이언트의 신원을 알아내고 인증할 수 있다. TLS는 서버와 클라이언트 모두에 대해 X.509 [RFC5280] 인증서 기반 인증을 지원한다. PSK 키 교환이 사용되는 경우(재개에서처럼), PSK에 대한 지식은 피어를 인증하는 역할을 한다.

TLS 키 교환은 공격자의 변조에 저항하며, 참여하는 어느 피어도 제어할 수 없는 공유 비밀 값을 생성한다.

TLS는 QUIC에 관심 있는 두 가지 기본 핸드셰이크 모드를 제공한다.

  • 전체 1-RTT 핸드셰이크. 이 방식에서 클라이언트는 한 번의 왕복 후 애플리케이션 데이터를 보낼 수 있으며, 서버는 클라이언트로부터 첫 번째 핸드셰이크 메시지를 받은 직후 응답한다.
  • 0-RTT 핸드셰이크. 이 방식에서 클라이언트는 서버에 대해 이전에 학습한 정보를 사용하여 애플리케이션 데이터를 즉시 보낸다. 이 애플리케이션 데이터는 공격자에 의해 재생될 수 있으므로, 0-RTT는 재생될 경우 원치 않는 효과를 일으킬 수 있는 동작을 시작할 수 있는 지시를 운반하는 데 적합하지 않다.

0-RTT 애플리케이션 데이터를 포함하는 단순화된 TLS 핸드셰이크가 그림 2에 표시되어 있다.

    Client                                             Server

    ClientHello
   (0-RTT Application Data)  -------->
                                                  ServerHello
                                         {EncryptedExtensions}
                                                    {Finished}
                             <--------      [Application Data]
   {Finished}                -------->

   [Application Data]        <------->      [Application Data]

    () Indicates messages protected by Early Data (0-RTT) Keys
    {} Indicates messages protected using Handshake Keys
    [] Indicates messages protected using Application Data
       (1-RTT) Keys
그림 2: 0-RTT를 사용한 TLS 핸드셰이크

그림 2는 QUIC에서 사용되지 않는 EndOfEarlyData 메시지를 생략한다. 8.3절을 보라. 마찬가지로 ChangeCipherSpec과 KeyUpdate 메시지도 QUIC에서 사용되지 않는다. ChangeCipherSpec은 TLS 1.3에서 중복적이다. 8.4절을 보라. QUIC은 자체 키 갱신 메커니즘을 가진다. 6절을 보라.

데이터는 여러 암호화 수준을 사용하여 보호된다.

  • Initial 키
  • Early data (0-RTT) 키
  • Handshake 키
  • Application data (1-RTT) 키

애플리케이션 데이터는 early data 및 application data 수준에만 나타날 수 있다. 핸드셰이크 및 경고 메시지는 어느 수준에도 나타날 수 있다.

0-RTT 핸드셰이크는 클라이언트와 서버가 이전에 통신한 적이 있는 경우 사용할 수 있다. 1-RTT 핸드셰이크에서 클라이언트는 서버가 보낸 모든 핸드셰이크 메시지를 수신할 때까지 보호된 애플리케이션 데이터를 보낼 수 없다.

3. 프로토콜 개요

QUIC [QUIC-TRANSPORT]은 패킷의 기밀성 및 무결성 보호에 대한 책임을 맡는다. 이를 위해 TLS 핸드셰이크 [TLS13]에서 파생된 키를 사용하지만, TLS 레코드를 QUIC 위에서 운반하는 대신(TCP에서와 같이) TLS 핸드셰이크 및 경고 메시지는 QUIC 전송 위에서 직접 운반된다. QUIC 전송은 그림 3에 표시된 것처럼 TLS 레코드 계층의 책임을 대신 수행한다.

+--------------+--------------+ +-------------+
|     TLS      |     TLS      | |    QUIC     |
|  Handshake   |    Alerts    | | Applications|
|              |              | |  (h3, etc.) |
+--------------+--------------+-+-------------+
|                                             |
|                QUIC Transport               |
|   (streams, reliability, congestion, etc.)  |
|                                             |
+---------------------------------------------+
|                                             |
|            QUIC Packet Protection           |
|                                             |
+---------------------------------------------+
그림 3: QUIC 계층

QUIC은 또한 보안과 성능에 중요한 매개변수의 인증 및 협상을 위해 TLS에 의존한다.

엄격한 계층화라기보다, 이 두 프로토콜은 협력한다. QUIC은 TLS 핸드셰이크를 사용하고, TLS는 QUIC이 제공하는 신뢰성, 순서화된 전달, 레코드 계층을 사용한다.

높은 수준에서 TLS와 QUIC 구성요소 사이에는 두 가지 주요 상호작용이 있다.

그림 4는 QUIC 패킷 보호를 특별히 표시하여 이러한 상호작용을 더 자세히 보여준다.

+------------+                               +------------+
|            |<---- Handshake Messages ----->|            |
|            |<- Validate 0-RTT Parameters ->|            |
|            |<--------- 0-RTT Keys ---------|            |
|    QUIC    |<------- Handshake Keys -------|    TLS     |
|            |<--------- 1-RTT Keys ---------|            |
|            |<------- Handshake Done -------|            |
+------------+                               +------------+
 |         ^
 | Protect | Protected
 v         | Packet
+------------+
|   QUIC     |
|  Packet    |
| Protection |
+------------+
그림 4: QUIC과 TLS의 상호작용

TCP 위의 TLS와 달리, 데이터를 보내려는 QUIC 애플리케이션은 TLS Application Data 레코드를 사용해 데이터를 보내지 않는다. 대신 QUIC STREAM 프레임이나 다른 프레임 유형으로 보내며, 이들은 QUIC 패킷에 실려 운반된다.

4. TLS 메시지 운반

QUIC은 TLS 핸드셰이크 데이터를 CRYPTO 프레임에 담아 운반한다. 각 CRYPTO 프레임은 오프셋과 길이로 식별되는 연속적인 핸드셰이크 데이터 블록으로 구성된다. 이러한 프레임은 QUIC 패킷으로 패키징되고 현재 암호화 수준으로 암호화된다. TCP 위의 TLS와 마찬가지로, TLS 핸드셰이크 데이터가 QUIC에 전달되면 이를 신뢰성 있게 전달하는 것은 QUIC의 책임이다. TLS가 생성하는 각 데이터 조각은 TLS가 현재 사용 중인 키 집합과 연관된다. QUIC이 해당 데이터를 재전송해야 하는 경우, TLS가 이미 더 새로운 키로 업데이트되었더라도 MUST 같은 키를 사용해야 한다.

각 암호화 수준은 하나의 패킷 번호 공간에 대응한다. 사용되는 패킷 번호 공간은 프레임의 의미를 결정한다. 일부 프레임은 서로 다른 패킷 번호 공간에서 금지된다. [QUIC-TRANSPORT]의 12.5절을 보라.

패킷은 네트워크상에서 재정렬될 수 있으므로, QUIC은 표 1에 표시된 것처럼 주어진 패킷을 보호하는 데 어떤 키가 사용되었는지 나타내기 위해 패킷 유형을 사용한다. 서로 다른 유형의 패킷을 보내야 할 때, 엔드포인트는 이들을 같은 UDP 데이터그램으로 보내기 위해 병합된 패킷을 사용해야 SHOULD 한다.

표 1: 패킷 유형별 암호화 키
패킷 유형 암호화 키 PN 공간
Initial Initial 비밀 Initial
0-RTT Protected 0-RTT 애플리케이션 데이터
Handshake Handshake Handshake
Retry Retry N/A
Version Negotiation N/A N/A
Short Header 1-RTT 애플리케이션 데이터

[QUIC-TRANSPORT]의 17절은 다양한 암호화 수준의 패킷이 핸드셰이크 과정에 어떻게 들어맞는지 보여준다.

4.1. TLS와의 인터페이스

그림 4에 표시된 것처럼, QUIC에서 TLS로 이어지는 인터페이스는 네 가지 주요 기능으로 구성된다.

  • 핸드셰이크 메시지 송수신
  • 재개된 세션에서 저장된 전송 및 애플리케이션 상태를 처리하고 0-RTT 데이터를 생성하거나 수락하는 것이 유효한지 결정
  • 키 재설정(송신과 수신 모두)
  • 핸드셰이크 상태 업데이트

TLS를 구성하기 위해 추가 기능이 필요할 수 있다. 특히 QUIC과 TLS는 인증서 검증 [RFC5280]과 같은 피어 자격 증명 검증에 대해 어느 쪽이 책임을 질지 합의해야 한다.

4.1.1. 핸드셰이크 완료

이 문서에서 TLS 핸드셰이크는 TLS 스택이 핸드셰이크가 완료되었다고 보고할 때 완료된 것으로 간주된다. 이는 TLS 스택이 Finished 메시지를 보냈고 피어의 Finished 메시지를 검증했을 때 발생한다. 피어의 Finished 메시지를 검증하면 이전 핸드셰이크 메시지가 수정되지 않았다는 보증이 엔드포인트에 제공된다. 핸드셰이크는 두 엔드포인트에서 동시에 완료되지 않는다는 점에 유의하라. 따라서 핸드셰이크 완료에 기반한 모든 요구사항은 해당 엔드포인트의 관점에 의존한다.

4.1.2. 핸드셰이크 확인됨

이 문서에서 TLS 핸드셰이크는 서버에서 핸드셰이크가 완료될 때 확인된 것으로 간주된다. 서버는 핸드셰이크가 완료되는 즉시 HANDSHAKE_DONE 프레임을 보내야 MUST 한다. 클라이언트에서는 HANDSHAKE_DONE 프레임을 수신할 때 핸드셰이크가 확인된 것으로 간주된다.

추가로, 클라이언트는 1-RTT 패킷에 대한 확인 응답을 받았을 때 핸드셰이크가 확인되었다고 간주할 수 MAY 있다. 이는 1-RTT 키로 보낸 가장 낮은 패킷 번호를 기록하고 이를 수신한 1-RTT ACK 프레임의 Largest Acknowledged 필드와 비교함으로써 구현할 수 있다. 후자가 전자보다 크거나 같아지면 핸드셰이크가 확인된다.

4.1.3. 핸드셰이크 메시지 송수신

핸드셰이크를 구동하기 위해 TLS는 핸드셰이크 메시지를 보내고 받을 수 있어야 한다. 이 인터페이스에는 두 가지 기본 기능이 있다. 하나는 QUIC이 핸드셰이크 메시지를 요청하는 경우이고, 다른 하나는 QUIC이 핸드셰이크 메시지를 구성하는 바이트를 제공하는 경우이다.

핸드셰이크를 시작하기 전에 QUIC은 TLS에 자신이 운반하고자 하는 전송 매개변수(8.2절 참조)를 제공한다.

QUIC 클라이언트는 TLS에 TLS 핸드셰이크 바이트를 요청함으로써 TLS를 시작한다. 클라이언트는 첫 번째 패킷을 보내기 전에 핸드셰이크 바이트를 획득한다. QUIC 서버는 클라이언트의 핸드셰이크 바이트를 TLS에 제공함으로써 프로세스를 시작한다.

어느 시점이든 엔드포인트의 TLS 스택에는 현재 송신 암호화 수준과 수신 암호화 수준이 있다. TLS 암호화 수준은 데이터를 보호하는 데 사용되는 QUIC 패킷 유형과 키를 결정한다.

각 암호화 수준은 서로 다른 바이트 시퀀스와 연관되며, 이는 CRYPTO 프레임을 통해 피어에게 신뢰성 있게 전송된다. TLS가 보낼 핸드셰이크 바이트를 제공하면, 그 바이트는 현재 암호화 수준의 핸드셰이크 바이트에 추가된다. 암호화 수준은 결과 CRYPTO 프레임이 어떤 유형의 패킷에 실릴지를 결정한다. 표 1을 보라.

네 가지 암호화 수준이 사용되어 Initial, 0-RTT, Handshake, 1-RTT 패킷을 위한 키를 생성한다. CRYPTO 프레임은 이들 중 0-RTT 수준을 제외한 세 가지 수준에만 실린다. 이 네 수준은 세 개의 패킷 번호 공간에 대응한다. Initial 및 Handshake 암호화 패킷은 각각 별도의 공간을 사용하고, 0-RTT 및 1-RTT 패킷은 application data 패킷 번호 공간을 사용한다.

QUIC은 TLS 핸드셰이크 레코드의 보호되지 않은 콘텐츠를 CRYPTO 프레임의 콘텐츠로 취한다. TLS 레코드 보호는 QUIC에서 사용되지 않는다. QUIC은 CRYPTO 프레임을 QUIC 패킷으로 조립하고, 이는 QUIC 패킷 보호를 사용해 보호된다.

QUIC CRYPTO 프레임은 TLS 핸드셰이크 메시지만 운반한다. TLS 경고는 QUIC CONNECTION_CLOSE 오류 코드로 변환된다. 4.8절을 보라. TLS 애플리케이션 데이터와 다른 콘텐츠 유형은 어떤 암호화 수준에서도 QUIC에 의해 운반될 수 없다. TLS 스택에서 이를 수신하면 오류이다.

엔드포인트가 네트워크에서 CRYPTO 프레임을 포함하는 QUIC 패킷을 수신하면 다음과 같이 진행한다.

  • 패킷이 현재 TLS 수신 암호화 수준을 사용하는 경우, 평소처럼 데이터를 입력 흐름에 순서화한다. STREAM 프레임과 마찬가지로, 오프셋은 데이터 시퀀스의 적절한 위치를 찾는 데 사용된다. 이 과정의 결과 새 데이터가 사용 가능해지면, 그 데이터는 순서대로 TLS에 전달된다.
  • 패킷이 이전에 설치된 암호화 수준에서 온 경우, 해당 흐름에서 이전에 수신한 데이터의 끝을 넘어서는 데이터를 포함해서는 MUST NOT 안 된다. 구현은 이 요구사항의 위반을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 MUST 한다.
  • 패킷이 새로운 암호화 수준에서 온 경우, 나중에 TLS가 처리하도록 저장된다. TLS가 이 암호화 수준에서 수신하도록 이동하면 저장된 데이터를 TLS에 제공할 수 있다. TLS가 더 높은 암호화 수준에 대한 키를 제공할 때, TLS가 아직 소비하지 않은 이전 암호화 수준의 데이터가 있다면, 이는 PROTOCOL_VIOLATION 유형의 연결 오류로 처리되어야 MUST 한다.

TLS에 새 데이터가 제공될 때마다 TLS에서 새 핸드셰이크 바이트를 요청한다. 수신한 핸드셰이크 메시지가 불완전하거나 보낼 데이터가 없으면 TLS는 아무 바이트도 제공하지 않을 수 있다.

CRYPTO 프레임의 콘텐츠는 TLS에 의해 증분적으로 처리되거나, 완전한 메시지 또는 플라이트가 사용 가능할 때까지 버퍼링될 수 있다. TLS는 순서대로 도착한 핸드셰이크 바이트를 버퍼링할 책임이 있다. QUIC은 순서가 어긋나 도착한 핸드셰이크 바이트나 아직 준비되지 않은 암호화 수준의 핸드셰이크 바이트를 버퍼링할 책임이 있다. QUIC은 CRYPTO 프레임에 대해 어떤 흐름 제어 수단도 제공하지 않는다. [QUIC-TRANSPORT]의 7.5절을 보라.

TLS 핸드셰이크가 완료되면, 이는 TLS가 보내야 할 마지막 핸드셰이크 바이트와 함께 QUIC에 표시된다. 이 단계에서 피어가 핸드셰이크 중 광고한 전송 매개변수는 인증된다. 8.2절을 보라.

핸드셰이크가 완료되면 TLS는 수동적이 된다. TLS는 여전히 피어로부터 데이터를 수신하고 그에 맞게 응답할 수 있지만, 애플리케이션이나 QUIC에 의해 명시적으로 요청되지 않는 한 더 이상 데이터를 보낼 필요가 없다. 데이터를 보내는 한 가지 이유는 서버가 클라이언트에 추가 또는 갱신된 세션 티켓을 제공하고자 할 수 있기 때문이다.

핸드셰이크가 완료되면, QUIC은 CRYPTO 스트림에 도착하는 데이터만 TLS에 제공하면 된다. 핸드셰이크 중에 사용된 것과 같은 방식으로, 수신한 데이터를 제공한 후 TLS에서 새 데이터를 요청한다.

4.1.4. 암호화 수준 변경

주어진 암호화 수준의 키가 TLS에서 사용 가능해지면, TLS는 해당 암호화 수준에서 읽기 또는 쓰기 키가 사용 가능하다는 것을 QUIC에 알린다.

새 키의 가용성은 항상 TLS에 입력을 제공한 결과이다. TLS는 (클라이언트에 의해) 초기화된 후 또는 새 핸드셰이크 데이터가 제공될 때만 새 키를 제공한다.

그러나 TLS 구현은 처리의 일부를 비동기적으로 수행할 수 있다. 특히 인증서 검증 과정은 시간이 걸릴 수 있다. TLS 처리가 완료되기를 기다리는 동안 엔드포인트는 아직 사용 가능하지 않은 키를 사용해 처리될 수 있는 수신 패킷을 버퍼링해야 SHOULD 한다. 이러한 패킷은 TLS가 키를 제공하면 처리될 수 있다. 엔드포인트는 이 시간 동안 처리 가능한 패킷에는 계속 응답해야 SHOULD 한다.

입력을 처리한 후 TLS는 핸드셰이크 바이트, 새 암호화 수준의 키, 또는 둘 모두를 생성할 수 있다.

새 암호화 수준이 사용 가능해질 때 TLS는 QUIC에 세 가지 항목을 제공한다.

  • 비밀 값
  • 연관 데이터가 있는 인증 암호화(AEAD) 함수
  • 키 파생 함수(KDF)

이 값들은 TLS가 협상한 값에 기반하며, QUIC이 패킷 및 헤더 보호 키를 생성하는 데 사용된다. 5절5.4절을 보라.

0-RTT가 가능하다면, 이는 클라이언트가 TLS ClientHello 메시지를 보낸 후 또는 서버가 그 메시지를 받은 후 준비된다. QUIC 클라이언트에 첫 번째 핸드셰이크 바이트를 제공한 후, TLS 스택은 0-RTT 키로의 변경을 신호할 수 있다. 서버에서는 ClientHello 메시지를 포함하는 핸드셰이크 바이트를 수신한 후, TLS 서버가 0-RTT 키가 사용 가능하다는 것을 신호할 수 있다.

TLS는 한 번에 하나의 암호화 수준만 사용하지만, QUIC은 둘 이상의 수준을 사용할 수 있다. 예를 들어 Finished 메시지(Handshake 암호화 수준의 CRYPTO 프레임 사용)를 보낸 후 엔드포인트는 STREAM 데이터 (1-RTT 암호화)를 보낼 수 있다. Finished 메시지가 손실되면, 엔드포인트는 손실된 메시지를 재전송하기 위해 Handshake 암호화 수준을 사용한다. 패킷의 재정렬 또는 손실은 QUIC이 여러 암호화 수준의 패킷을 처리해야 함을 의미할 수 있다. 핸드셰이크 중에는 TLS가 사용하는 현재 암호화 수준보다 더 높거나 낮은 암호화 수준의 패킷을 처리해야 할 가능성이 있음을 의미한다.

특히 서버 구현은 Handshake 암호화 수준의 패킷을 0-RTT 암호화 수준과 동시에 읽을 수 있어야 한다. 클라이언트는 Handshake 키로 보호된 ACK 프레임을 0-RTT 데이터와 교차시킬 수 있으며, 서버는 손실된 Handshake 패킷을 감지하기 위해 이러한 확인 응답을 처리해야 한다.

QUIC은 또한 TLS 구현에서 일반적으로 사용 가능하지 않을 수 있는 키에 접근할 필요가 있다. 예를 들어 클라이언트는 해당 암호화 수준에서 CRYPTO 프레임을 보낼 준비가 되기 전에 Handshake 패킷에 확인 응답해야 할 수 있다. 따라서 TLS는 자체 사용을 위해 키를 생성하기 전에 QUIC에 키를 제공해야 한다.

4.1.5. TLS 인터페이스 요약

그림 5는 클라이언트와 서버 모두에 대해 QUIC과 TLS 사이의 교환을 요약한다. 실선 화살표는 핸드셰이크 데이터를 운반하는 패킷을 나타내고, 점선 화살표는 애플리케이션 데이터를 보낼 수 있는 위치를 보여준다. 각 화살표에는 해당 전송에 사용되는 암호화 수준이 표시되어 있다.

Client                                                    Server
======                                                    ======

Get Handshake
                     Initial ------------->
Install tx 0-RTT keys
                     0-RTT - - - - - - - ->

                                              Handshake Received
                                                   Get Handshake
                     <------------- Initial
                                           Install rx 0-RTT keys
                                          Install Handshake keys
                                                   Get Handshake
                     <----------- Handshake
                                           Install tx 1-RTT keys
                     <- - - - - - - - 1-RTT

Handshake Received (Initial)
Install Handshake keys
Handshake Received (Handshake)
Get Handshake
                     Handshake ----------->
Handshake Complete
Install 1-RTT keys
                     1-RTT - - - - - - - ->

                                              Handshake Received
                                              Handshake Complete
                                             Handshake Confirmed
                                           Install rx 1-RTT keys
                     <--------------- 1-RTT
                           (HANDSHAKE_DONE)
Handshake Confirmed
그림 5: QUIC과 TLS 사이의 상호작용 요약

그림 5는 단일 메시지 "flight"를 구성하는 여러 패킷이 개별적으로 처리되는 것을 보여주며, 어떤 수신 메시지가 서로 다른 동작을 유발하는지 나타낸다. 이는 서로 다른 암호화 수준에서 핸드셰이크 메시지를 가져오기 위한 여러 "Get Handshake" 호출을 보여준다. 새 핸드셰이크 메시지는 수신 패킷이 처리된 후 요청된다.

그림 5는 단순한 핸드셰이크 교환의 한 가능한 구조를 보여준다. 정확한 과정은 엔드포인트 구현의 구조와 패킷이 도착하는 순서에 따라 달라진다. 구현은 다른 수의 작업을 사용하거나 다른 순서로 실행할 수 있다.

4.2. TLS 버전

이 문서는 TLS 1.3 [TLS13]이 QUIC과 함께 어떻게 사용되는지 설명한다.

실제로 TLS 핸드셰이크는 사용할 TLS 버전을 협상한다. 두 엔드포인트가 해당 버전을 지원한다면 TLS 1.3보다 새로운 TLS 버전이 협상될 수 있다. QUIC이 사용하는 TLS 1.3의 기능이 그 새로운 버전에서 지원된다면 이는 허용된다.

클라이언트는 TLS 1.3보다 오래된 TLS 버전을 제안해서는 MUST NOT 안 된다. 잘못 구성된 TLS 구현은 TLS 1.2 또는 다른 더 오래된 TLS 버전을 협상할 수 있다. 엔드포인트는 TLS 1.3보다 오래된 TLS 버전이 협상되면 연결을 종료해야 MUST 한다.

4.3. ClientHello 크기

클라이언트의 첫 번째 Initial 패킷은 첫 번째 암호학적 핸드셰이크 메시지의 시작 또는 전체를 포함하며, TLS에서는 이것이 ClientHello이다. 서버는 새로 들어오는 QUIC 연결을 수락할지 결정하기 위해 ClientHello 전체를 파싱해야 할 수 있다(예: Server Name Identification (SNI) 또는 Application-Layer Protocol Negotiation (ALPN) 같은 확장에 접근하기 위해). ClientHello가 여러 Initial 패킷에 걸쳐 있는 경우, 그러한 서버는 처음 수신한 조각을 버퍼링해야 하며, 클라이언트 주소가 아직 검증되지 않았다면 과도한 리소스를 소비할 수 있다. 이를 피하기 위해 서버는 검증된 주소를 가진 클라이언트의 부분 ClientHello 메시지만 버퍼링하도록 Retry 기능 ([QUIC-TRANSPORT]의 8.1절 참조)을 사용할 수 MAY 있다.

QUIC 패킷과 프레이밍은 ClientHello 메시지에 최소 36바이트의 오버헤드를 추가한다. 클라이언트가 0바이트보다 긴 Source Connection ID 필드를 선택하면 이 오버헤드는 증가한다. 오버헤드에는 서버가 Retry 패킷을 보낼 경우 필요할 수 있는 토큰이나 8바이트보다 긴 Destination Connection ID도 포함되지 않는다.

일반적인 TLS ClientHello는 1200바이트 패킷 안에 쉽게 들어갈 수 있다. 그러나 QUIC이 추가하는 오버헤드 외에도 이 한계를 초과하게 만들 수 있는 여러 변수가 있다. 큰 세션 티켓, 여러 개이거나 큰 key share, 지원되는 암호군, 서명 알고리즘, 버전, QUIC 전송 매개변수, 그리고 기타 협상 가능한 매개변수 및 확장의 긴 목록은 이 메시지를 커지게 할 수 있다.

서버의 경우, 연결 ID와 토큰 외에도 TLS 세션 티켓의 크기는 클라이언트가 효율적으로 연결할 수 있는 능력에 영향을 줄 수 있다. 이러한 값의 크기를 최소화하면 클라이언트가 이를 사용하면서도 전체 ClientHello 메시지를 첫 번째 Initial 패킷에 맞출 수 있을 가능성이 높아진다.

TLS 구현은 ClientHello가 Initial 패킷을 운반하는 데이터그램에 대한 QUIC의 요구사항을 충족할 만큼 충분히 큰지 보장할 필요가 없다. [QUIC-TRANSPORT]의 14.1절을 보라. QUIC 구현은 PADDING 프레임이나 패킷 병합을 사용해 데이터그램이 충분히 크도록 보장한다.

4.4. 피어 인증

인증 요구사항은 사용 중인 애플리케이션 프로토콜에 따라 달라진다. TLS는 서버 인증을 제공하고 서버가 클라이언트 인증을 요청하는 것을 허용한다.

클라이언트는 서버의 신원을 인증해야 MUST 한다. 일반적으로 이는 서버의 신원이 인증서에 포함되어 있고 그 인증서가 신뢰된 엔터티에 의해 발급되었는지 검증하는 것을 포함한다 (예: [RFC2818] 참조).

서버는 핸드셰이크 중 클라이언트가 인증하도록 요청할 수 MAY 있다. 서버는 요청받았을 때 클라이언트가 인증할 수 없으면 연결을 거부할 수 MAY 있다. 클라이언트 인증 요구사항은 애플리케이션 프로토콜과 배포 방식에 따라 달라진다.

서버는 핸드셰이크 후 클라이언트 인증 ([TLS13]의 4.6.2절에 정의됨)을 사용해서는 MUST NOT 안 된다. QUIC이 제공하는 다중화가 클라이언트가 인증서 요청을 그것을 유발한 애플리케이션 수준 이벤트와 연관시키지 못하게 하기 때문이다 ([HTTP2-TLS13] 참조). 더 구체적으로, 서버는 핸드셰이크 후 TLS CertificateRequest 메시지를 보내서는 MUST NOT 안 되며, 클라이언트는 이러한 메시지의 수신을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 MUST 한다.

4.5. 세션 재개

QUIC은 TLS 1.3의 세션 재개 기능을 사용할 수 있다. 이는 핸드셰이크가 완료된 후 NewSessionTicket 메시지를 CRYPTO 프레임에 담아 운반함으로써 수행된다. 세션 재개는 0-RTT를 제공하는 데 사용될 수 있으며, 0-RTT가 비활성화된 경우에도 사용될 수 있다.

세션 재개를 사용하는 엔드포인트는 재개된 연결을 만들 때 현재 연결에 관한 일부 정보를 기억해야 할 수 있다. TLS는 일부 정보가 유지되도록 요구한다. [TLS13]의 4.6.1절을 보라. QUIC 자체는 0-RTT도 사용되지 않는 한 연결을 재개할 때 어떤 상태가 유지되는지에 의존하지 않는다. [QUIC-TRANSPORT]의 7.4.1절4.6.1절을 보라. 애플리케이션 프로토콜은 재개된 연결 사이에 유지되는 상태에 의존할 수 있다.

클라이언트는 재개에 필요한 모든 상태를 세션 티켓과 함께 저장할 수 있다. 서버는 세션 티켓을 사용하여 상태를 운반하는 데 도움을 줄 수 있다.

세션 재개는 서버가 원래 연결에서의 활동을 재개된 연결과 연결할 수 있게 하며, 이는 클라이언트에게 개인정보 보호 문제가 될 수 있다. 클라이언트는 이러한 상관관계를 만들지 않기 위해 재개를 활성화하지 않도록 선택할 수 있다. 클라이언트는 티켓을 재사용해서는 SHOULD NOT 안 된다. 이는 서버가 아닌 엔터티도 연결을 상관시킬 수 있게 하기 때문이다. [TLS13]의 부록 C.4를 보라.

4.6. 0-RTT

QUIC의 0-RTT 기능은 클라이언트가 핸드셰이크가 완료되기 전에 애플리케이션 데이터를 보낼 수 있게 한다. 이는 이전 연결에서 협상된 매개변수를 재사용함으로써 가능해진다. 이를 활성화하기 위해 0-RTT는 클라이언트가 중요한 매개변수를 기억하고, 서버가 동일한 정보를 복구할 수 있게 하는 TLS 세션 티켓을 서버에 제공하는 것에 의존한다.

이 정보에는 [TLS13]에 의해 관리되는 TLS 상태를 결정하는 매개변수, QUIC 전송 매개변수, 선택된 애플리케이션 프로토콜, 그리고 애플리케이션 프로토콜이 필요로 할 수 있는 모든 정보가 포함된다. 4.6.3절을 보라. 이 정보는 0-RTT 패킷과 그 내용이 형성되는 방식을 결정한다.

양쪽 엔드포인트에서 동일한 정보를 사용할 수 있도록 하기 위해, 0-RTT를 설정하는 데 사용되는 모든 정보는 동일한 연결에서 나온다. 엔드포인트는 0-RTT의 송신 또는 처리를 변경할 수 있는 정보를 선택적으로 무시할 수 없다.

[TLS13]은 원래 연결과 0-RTT 사용 시도 사이의 시간에 7일의 한계를 설정한다. 0-RTT 사용에는 다른 제약도 있으며, 특히 재생 공격에 노출될 가능성으로 인한 제약이 있다. 9.2절을 보라.

4.6.1. 0-RTT 활성화

NewSessionTicket 메시지의 TLS early_data 확장은 서버가 수락할 의향이 있는 TLS 0-RTT 데이터의 양을 (max_early_data_size 매개변수로) 전달하도록 정의되어 있다. QUIC은 TLS early data를 사용하지 않는다. QUIC은 early data를 운반하기 위해 0-RTT 패킷을 사용한다. 따라서 max_early_data_size 매개변수는 서버가 QUIC 0-RTT 데이터를 수락할 의향이 있음을 나타내기 위한 sentinel 값 0xffffffff를 담도록 용도가 변경된다. 서버가 0-RTT 데이터를 수락하지 않음을 나타내기 위해 early_data 확장은 NewSessionTicket에서 생략된다. 클라이언트가 QUIC 0-RTT로 보낼 수 있는 데이터의 양은 서버가 제공한 initial_max_data 전송 매개변수에 의해 제어된다.

서버는 max_early_data_size 필드가 0xffffffff 이외의 값으로 설정된 early_data 확장을 보내서는 MUST NOT 안 된다. 클라이언트는 다른 값을 가진 early_data 확장을 포함하는 NewSessionTicket의 수신을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 MUST 한다.

0-RTT 패킷을 보내고자 하는 클라이언트는 후속 핸드셰이크의 ClientHello 메시지에서 early_data 확장을 사용한다. [TLS13]의 4.2.10절을 보라. 그런 다음 0-RTT 패킷으로 애플리케이션 데이터를 보낸다.

0-RTT를 시도하는 클라이언트는 서버가 NEW_TOKEN 프레임을 보냈다면 주소 검증 토큰도 제공할 수 있다. [QUIC-TRANSPORT]의 8.1절을 보라.

4.6.2. 0-RTT 수락 및 거부

서버는 EncryptedExtensions에서 early_data 확장을 보냄으로써 0-RTT를 수락한다. [TLS13]의 4.2.10절을 보라. 그런 다음 서버는 수신한 0-RTT 패킷을 처리하고 확인 응답한다.

서버는 early_data 확장 없이 EncryptedExtensions를 보냄으로써 0-RTT를 거부한다. 서버는 TLS HelloRetryRequest를 보내면 항상 0-RTT를 거부한다. 0-RTT를 거부할 때 서버는 가능하더라도 어떤 0-RTT 패킷도 처리해서는 MUST NOT 안 된다. 0-RTT가 거부되었을 때, 클라이언트는 그 조건을 감지할 수 있다면 0-RTT 패킷에 대한 확인 응답 수신을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 SHOULD 한다.

0-RTT가 거부되면, 클라이언트가 가정한 모든 연결 특성이 부정확할 수 있다. 여기에는 애플리케이션 프로토콜 선택, 전송 매개변수, 그리고 모든 애플리케이션 구성이 포함된다. 따라서 클라이언트는 해당 스트림에 바인딩된 애플리케이션 상태를 포함하여 모든 스트림의 상태를 재설정해야 MUST 한다.

클라이언트는 Retry 또는 Version Negotiation 패킷을 받으면 0-RTT를 다시 시도할 수 MAY 있다. 이러한 패킷은 0-RTT의 거부를 의미하지 않는다.

4.6.3. 0-RTT 구성 검증

서버가 early_data 확장을 포함하는 ClientHello를 수신하면, 클라이언트의 0-RTT 데이터를 수락할지 거부할지 결정해야 한다. 이 결정의 일부는 TLS 스택에 의해 이루어진다(예: 재개되는 암호군이 ClientHello에 포함되었는지 확인. [TLS13]의 4.2.10절 참조). TLS 스택이 0-RTT 데이터를 거부할 이유가 없더라도, QUIC 스택이나 QUIC을 사용하는 애플리케이션 프로토콜은 재개된 세션과 연관된 전송 또는 애플리케이션 구성이 서버의 현재 구성과 호환되지 않기 때문에 0-RTT 데이터를 거부할 수 있다.

QUIC은 추가 전송 상태가 0-RTT 세션 티켓과 연관되도록 요구한다. 이를 구현하는 일반적인 방법 중 하나는 무상태 세션 티켓을 사용하고 이 상태를 세션 티켓에 저장하는 것이다. QUIC을 사용하는 애플리케이션 프로토콜도 상태를 연관시키거나 저장하는 것과 관련하여 유사한 요구사항을 가질 수 있다. 이 연관된 상태는 0-RTT 데이터를 거부해야 하는지 결정하는 데 사용된다. 예를 들어 HTTP/3 설정 [QUIC-HTTP]은 클라이언트의 0-RTT 데이터가 해석되는 방식을 결정한다. QUIC을 사용하는 다른 애플리케이션은 0-RTT 데이터를 수락할지 거부할지 결정하기 위한 서로 다른 요구사항을 가질 수 있다.

4.7. HelloRetryRequest

HelloRetryRequest 메시지([TLS13]의 4.1.4절 참조)는 클라이언트가 key share와 같은 새 정보를 제공하도록 요청하거나 클라이언트의 일부 특성을 검증하는 데 사용될 수 있다. QUIC의 관점에서 HelloRetryRequest는 Initial 패킷에 실리는 다른 암호학적 핸드셰이크 메시지와 구별되지 않는다. 원칙적으로 이 기능을 주소 검증에 사용할 수 있지만, QUIC 구현은 대신 Retry 기능을 사용해야 SHOULD 한다. [QUIC-TRANSPORT]의 8.1절을 보라.

4.8. TLS 오류

TLS에 오류가 발생하면, 이는 [TLS13]의 6절에 정의된 적절한 경고를 생성한다.

TLS 경고는 QUIC 연결 오류로 변환된다. AlertDescription 값은 CRYPTO_ERROR를 위해 예약된 범위의 QUIC 오류 코드를 생성하기 위해 0x0100에 더해진다. [QUIC-TRANSPORT]의 20.1절을 보라. 결과 값은 0x1c 유형의 QUIC CONNECTION_CLOSE 프레임에 실려 전송된다.

QUIC은 "fatal" 경고 수준만 전달할 수 있다. TLS 1.3에서 "warning" 수준의 유일한 기존 사용은 연결 종료를 알리는 것이다. [TLS13]의 6.1절을 보라. QUIC은 연결 종료를 위한 대체 메커니즘을 제공하고, TLS 연결은 오류가 발생한 경우에만 닫히므로, QUIC 엔드포인트는 TLS의 모든 경고를 "fatal" 수준인 것처럼 처리해야 MUST 한다.

QUIC은 특정 오류 코드 대신 일반 코드를 사용하는 것을 허용한다. [QUIC-TRANSPORT]의 11절을 보라. TLS 경고의 경우, 이는 어떤 경고든 handshake_failure (QUIC에서 0x0128)와 같은 일반 경고로 대체하는 것을 포함한다. 엔드포인트는 기밀 정보를 노출할 가능성을 피하기 위해 일반 오류 코드를 사용할 수 MAY 있다.

4.9. 사용하지 않는 키 폐기

QUIC이 새 암호화 수준으로의 이동을 완료한 후, 이전 암호화 수준의 패킷 보호 키는 폐기될 수 있다. 이는 핸드셰이크 중 여러 번 발생하며, 키가 갱신될 때도 발생한다. 6절을 보라.

새 키가 사용 가능해졌다고 해서 패킷 보호 키가 즉시 폐기되지는 않는다. 낮은 암호화 수준의 패킷이 CRYPTO 프레임을 포함하는 경우, 그 데이터를 재전송하는 프레임은 동일한 암호화 수준에서 전송되어야 MUST 한다. 마찬가지로 엔드포인트는 확인 응답 대상 패킷과 동일한 암호화 수준에서 패킷에 대한 확인 응답을 생성한다. 따라서 더 새로운 암호화 수준의 키가 사용 가능해진 후에도 낮은 암호화 수준의 키가 짧은 시간 동안 필요할 수 있다.

엔드포인트는 특정 암호화 수준에서 피어의 모든 암호학적 핸드셰이크 메시지를 수신했고 피어도 동일하게 했다는 것을 알기 전에는 해당 암호화 수준의 키를 폐기할 수 없다. 이를 결정하는 서로 다른 방법이 Initial 키 (4.9.1절)와 Handshake 키 (4.9.2절)에 대해 제공된다. 이러한 방법은 피어가 필요한 모든 확인 응답을 받지 못했을 수 있기 때문에 해당 암호화 수준에서 패킷이 수신되거나 전송되는 것을 막지 않는다.

엔드포인트가 이전 키를 보유할 수는 있지만, 새 데이터는 현재 사용 가능한 가장 높은 암호화 수준에서 전송되어야 MUST 한다. ACK 프레임과 CRYPTO 프레임의 데이터 재전송만 이전 암호화 수준에서 전송된다. 이러한 패킷은 PADDING 프레임도 포함할 수 MAY 있다.

4.9.1. Initial 키 폐기

Initial 비밀(5.2절)로 보호된 패킷은 인증되지 않는다. 이는 공격자가 연결을 방해하려는 의도로 패킷을 위조할 수 있음을 의미한다. 이러한 공격을 제한하기 위해 Initial 패킷 보호 키는 다른 키보다 더 적극적으로 폐기된다.

Handshake 패킷의 성공적인 사용은 더 이상 Initial 패킷을 교환할 필요가 없음을 나타낸다. 이러한 키는 Initial 패킷의 모든 CRYPTO 프레임을 수신한 후에만 생성될 수 있기 때문이다. 따라서 클라이언트는 처음 Handshake 패킷을 보낼 때 Initial 키를 폐기해야 MUST 하고, 서버는 Handshake 패킷을 처음 성공적으로 처리할 때 Initial 키를 폐기해야 MUST 한다. 엔드포인트는 이 시점 이후에 Initial 패킷을 보내서는 MUST NOT 안 된다.

이는 Initial 암호화 수준에 대한 손실 복구 상태를 포기하고, outstanding Initial 패킷을 무시하는 결과를 낳는다.

4.9.2. Handshake 키 폐기

엔드포인트는 TLS 핸드셰이크가 확인될 때 (4.1.2절) Handshake 키를 폐기해야 MUST 한다.

4.9.3. 0-RTT 키 폐기

0-RTT와 1-RTT 패킷은 동일한 패킷 번호 공간을 공유하며, 클라이언트는 1-RTT 패킷을 보낸 후에는 0-RTT 패킷을 보내지 않는다 (5.6절).

따라서 클라이언트는 1-RTT 키를 설치하자마자 0-RTT 키를 폐기해야 SHOULD 한다. 그 시점 이후에는 해당 키가 아무 쓸모가 없기 때문이다.

추가로, 서버는 1-RTT 패킷을 수신하자마자 0-RTT 키를 폐기할 수 MAY 있다. 그러나 패킷 재정렬로 인해 0-RTT 패킷이 1-RTT 패킷 이후에 도착할 수 있다. 서버는 그 내용이 1-RTT 키로 재전송되도록 요구하지 않고 재정렬된 패킷을 복호화할 수 있도록 0-RTT 키를 일시적으로 보유할 수 MAY 있다. 1-RTT 패킷을 받은 후 서버는 짧은 시간 내에 0-RTT 키를 폐기해야 MUST 한다. 권장되는 시간은 Probe Timeout (PTO, [QUIC-RECOVERY] 참조)의 세 배이다. 서버는 누락된 패킷 번호를 추적함으로써 모든 0-RTT 패킷을 수신했다고 판단하면 0-RTT 키를 더 일찍 폐기할 수 MAY 있다.

5. 패킷 보호

TCP 위의 TLS와 마찬가지로, QUIC은 TLS가 협상한 AEAD 알고리즘 [AEAD]을 사용하여 TLS 핸드셰이크에서 파생된 키로 패킷을 보호한다.

QUIC 패킷은 유형에 따라 서로 다른 보호를 가진다.

이 절은 패킷 보호가 Handshake 패킷, 0-RTT 패킷, 그리고 1-RTT 패킷에 어떻게 적용되는지 설명한다. 동일한 패킷 보호 과정은 Initial 패킷에도 적용된다. 그러나 Initial 패킷에 사용되는 키를 결정하는 것은 사소하므로, 이러한 패킷은 기밀성 또는 무결성 보호를 가진 것으로 간주되지 않는다. Retry 패킷은 고정 키를 사용하므로 마찬가지로 기밀성 및 무결성 보호가 없다.

5.1. 패킷 보호 키

QUIC은 TLS가 레코드 보호 키를 파생하는 것과 같은 방식으로 패킷 보호 키를 파생한다.

각 암호화 수준은 각 방향으로 전송되는 패킷 보호를 위한 별도의 비밀 값을 가진다. 이러한 트래픽 비밀 값은 TLS에 의해 파생되며([TLS13]의 7.1절 참조), Initial 암호화 수준을 제외한 모든 암호화 수준에서 QUIC에 의해 사용된다. Initial 암호화 수준의 비밀 값은 5.2절에 설명된 것처럼 클라이언트의 초기 Destination Connection ID에 기반하여 계산된다.

패킷 보호에 사용되는 키는 TLS가 제공하는 KDF를 사용하여 TLS 비밀 값에서 계산된다. TLS 1.3에서는 협상된 암호군의 해시 함수와 함께 [TLS13]의 7.1절에 설명된 HKDF-Expand-Label 함수가 사용된다. QUIC에서 HKDF-Expand-Label을 사용하는 모든 경우 Context는 길이가 0이다.

문자열로 설명되는 레이블은 따옴표나 뒤따르는 NUL 바이트 없이 ASCII [ASCII]를 사용해 바이트로 인코딩된다는 점에 유의하라.

다른 버전의 TLS는 QUIC과 함께 사용되기 위해 유사한 함수를 제공해야 MUST 한다.

현재 암호화 수준 비밀 값과 레이블 "quic key"는 AEAD 키를 생성하기 위한 KDF 입력이 된다. 레이블 "quic iv"는 Initialization Vector (IV)를 파생하는 데 사용된다. 5.3절을 보라. 헤더 보호 키는 "quic hp" 레이블을 사용한다. 5.4절을 보라. 이러한 레이블을 사용하면 QUIC과 TLS 사이의 키 분리가 제공된다. 9.6절을 보라.

"quic key"와 "quic hp"는 모두 키를 생성하는 데 사용되므로, 이러한 레이블과 함께 HKDF-Expand-Label에 제공되는 Length는 AEAD 또는 헤더 보호 알고리즘의 키 크기에 의해 결정된다. "quic iv"와 함께 제공되는 Length는 AEAD nonce의 최소 길이 또는 그것이 더 큰 경우 8바이트이다. [AEAD]를 보라.

초기 비밀 값에 사용되는 KDF는 항상 TLS 1.3의 HKDF-Expand-Label 함수이다. 5.2절을 보라.

5.2. Initial 비밀 값

Initial 패킷은 패킷 보호 과정을 적용하지만, 클라이언트의 첫 번째 Initial 패킷의 Destination Connection ID 필드에서 파생된 비밀 값을 사용한다.

이 비밀 값은 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a를 salt로 사용하고 Destination Connection ID 필드의 입력 키 재료(IKM)를 사용하여 HKDF-Extract([HKDF]의 2.2절 참조)를 적용함으로써 결정된다. 이는 송신과 수신을 위한 두 개의 별도 비밀 값을 파생하는 데 사용되는 중간 의사난수 키(PRK)를 생성한다.

클라이언트가 Initial 패킷을 구성하는 데 사용하는 비밀 값은 PRK와 레이블 "client in"을 TLS [TLS13]의 HKDF-Expand-Label 함수에 대한 입력으로 사용하여 32바이트 비밀 값을 생성한다. 서버가 구성하는 패킷은 레이블 "server in"과 함께 같은 과정을 사용한다. 초기 비밀 값과 키를 파생할 때 HKDF의 해시 함수는 SHA-256 [SHA]이다.

이 과정은 의사코드로 다음과 같다.

initial_salt = 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a
initial_secret = HKDF-Extract(initial_salt,
                              client_dst_connection_id)

client_initial_secret = HKDF-Expand-Label(initial_secret,
                                          "client in", "",
                                          Hash.length)
server_initial_secret = HKDF-Expand-Label(initial_secret,
                                          "server in", "",
                                          Hash.length)

HKDF-Expand-Label과 함께 사용되는 연결 ID는 클라이언트가 보낸 Initial 패킷의 Destination Connection ID이다. 클라이언트가 Retry 패킷을 받은 후 Initial 패킷을 생성하는 경우를 제외하면, 이는 무작위로 선택된 값이다. Retry 패킷 이후에는 Destination Connection ID가 서버에 의해 선택된다.

QUIC의 향후 버전은 새 salt 값을 생성해야 SHOULD 하며, 따라서 QUIC의 각 버전에 대해 키가 달라지도록 보장해야 한다. 이는 하나의 QUIC 버전만 인식하는 미들박스가 향후 버전의 패킷 내용을 보거나 수정하는 것을 방지한다.

제안된 TLS 버전에 TLS 1.3이 포함되지 않는 경우에도 Initial 패킷에는 TLS 1.3에 정의된 HKDF-Expand-Label 함수를 사용해야 MUST 한다.

서버가 선택한 연결 ID 값을 사용하기 위해 서버가 Retry 패킷을 보내면, 이후 Initial 패킷을 구성하는 데 사용되는 비밀 값이 변경된다. 서버의 Initial 패킷에 대한 응답으로 클라이언트가 사용하는 Destination Connection ID를 변경하는 경우에는 비밀 값이 변경되지 않는다.

부록 A에는 샘플 Initial 패킷이 포함되어 있다.

5.3. AEAD 사용

QUIC 패킷 보호에 사용되는 Authenticated Encryption with Associated Data (AEAD) 함수([AEAD] 참조)는 TLS 연결과 함께 사용하도록 협상된 AEAD이다. 예를 들어 TLS가 TLS_AES_128_GCM_SHA256 암호군을 사용한다면, AEAD_AES_128_GCM 함수가 사용된다.

QUIC은 TLS_AES_128_CCM_8_SHA256을 제외하고 [TLS13]에 정의된 어떤 암호군도 사용할 수 있다. 암호군에 대한 헤더 보호 방식이 정의되어 있지 않으면 암호군을 협상해서는 MUST NOT 안 된다. 이 문서는 TLS_AES_128_CCM_8_SHA256을 제외하고 [TLS13]에 정의된 모든 암호군에 대한 헤더 보호 방식을 정의한다. 이러한 암호군은 16바이트 인증 태그를 가지며 입력보다 16바이트 큰 출력을 생성한다.

엔드포인트는 자신이 지원하지 않는 암호군을 제안하는 ClientHello를 거부해서는 MUST NOT 안 된다. 그렇지 않으면 새 암호군을 배포하는 것이 불가능해진다. 이는 TLS_AES_128_CCM_8_SHA256에도 적용된다.

패킷을 구성할 때 AEAD 함수는 헤더 보호를 적용하기 전에 적용된다. 5.4절을 보라. 보호되지 않은 패킷 헤더는 연관 데이터(A)의 일부이다. 패킷을 처리할 때 엔드포인트는 먼저 헤더 보호를 제거한다.

패킷의 키와 IV는 5.1절에 설명된 대로 계산된다. nonce N은 패킷 보호 IV와 패킷 번호를 결합하여 형성된다. 복원된 QUIC 패킷 번호의 62비트는 네트워크 바이트 순서로 IV 크기에 맞게 왼쪽에 0이 채워진다. 패딩된 패킷 번호와 IV의 배타적 OR가 AEAD nonce를 형성한다.

AEAD의 연관 데이터 A는 짧은 헤더 또는 긴 헤더의 첫 번째 바이트부터 시작하여 보호되지 않은 패킷 번호까지 포함하는 QUIC 헤더의 내용이다.

AEAD의 입력 평문 P는 [QUIC-TRANSPORT]에 설명된 QUIC 패킷의 페이로드이다.

AEAD의 출력 암호문 C는 P 대신 전송된다.

일부 AEAD 함수는 동일한 키와 IV 아래에서 암호화할 수 있는 패킷 수에 한계가 있다. 6.6절을 보라. 이는 패킷 번호 한계보다 낮을 수 있다. 엔드포인트는 사용 중인 AEAD에 대해 설정된 어떤 한계도 초과하기 전에 키 갱신(6절)을 시작해야 MUST 한다.

5.4. 헤더 보호

QUIC 패킷 헤더의 일부, 특히 Packet Number 필드는 패킷 보호 키와 IV에서 별도로 파생된 키를 사용하여 보호된다. "quic hp" 레이블을 사용하여 파생된 키는 경로상의 요소에 노출되지 않는 필드에 대한 기밀성 보호를 제공하는 데 사용된다.

이 보호는 첫 번째 바이트의 최하위 비트와 Packet Number 필드에 적용된다. 긴 헤더가 있는 패킷에서는 첫 번째 바이트의 최하위 4비트가 보호되며, 짧은 헤더가 있는 패킷에서는 첫 번째 바이트의 최하위 5비트가 보호된다. 두 헤더 형식 모두에서 이는 예약 비트와 Packet Number Length 필드를 포함한다. 짧은 헤더가 있는 패킷에서는 Key Phase 비트도 보호된다.

동일한 헤더 보호 키는 연결이 지속되는 동안 사용되며, 키 갱신 (6절 참조) 후에도 값이 변경되지 않는다. 이를 통해 헤더 보호를 사용하여 키 위상을 보호할 수 있다.

이 과정은 Retry 또는 Version Negotiation 패킷에는 적용되지 않는다. 이러한 패킷은 보호된 페이로드나 이 과정에 의해 보호되는 필드를 포함하지 않기 때문이다.

5.4.1. 헤더 보호 적용

헤더 보호는 패킷 보호가 적용된 후 적용된다 (5.3절 참조). 패킷의 암호문이 샘플링되어 암호화 알고리즘의 입력으로 사용된다. 사용되는 알고리즘은 협상된 AEAD에 따라 달라진다.

이 알고리즘의 출력은 5바이트 마스크이며, 배타적 OR를 사용하여 보호된 헤더 필드에 적용된다. 패킷 첫 번째 바이트의 최하위 비트는 첫 번째 마스크 바이트의 최하위 비트로 마스킹되고, 패킷 번호는 나머지 바이트로 마스킹된다. 더 짧은 패킷 번호 인코딩으로 인해 생길 수 있는 사용되지 않은 마스크 바이트는 사용되지 않는다.

그림 6은 헤더 보호를 적용하기 위한 샘플 알고리즘을 보여준다. 헤더 보호를 제거하는 것은 패킷 번호 길이(pn_length)가 결정되는 순서만 다르다(여기서 "^"는 배타적 OR를 나타내는 데 사용된다).

mask = header_protection(hp_key, sample)

pn_length = (packet[0] & 0x03) + 1
if (packet[0] & 0x80) == 0x80:
   # Long header: 4 bits masked
   packet[0] ^= mask[0] & 0x0f
else:
   # Short header: 5 bits masked
   packet[0] ^= mask[0] & 0x1f

# pn_offset is the start of the Packet Number field.
packet[pn_offset:pn_offset+pn_length] ^= mask[1:1+pn_length]
그림 6: 헤더 보호 의사코드

특정 헤더 보호 함수는 선택된 암호군에 기반하여 정의된다. 5.4.3절5.4.4절을 보라.

그림 7은 긴 헤더 패킷(Initial)과 짧은 헤더 패킷(1-RTT)의 예를 보여준다. 그림 7은 각 헤더에서 헤더 보호의 대상이 되는 필드와 샘플링되는 보호된 패킷 페이로드의 부분을 보여준다.

Initial Packet {
  Header Form (1) = 1,
  Fixed Bit (1) = 1,
  Long Packet Type (2) = 0,
  Reserved Bits (2),         # Protected
  Packet Number Length (2),  # Protected
  Version (32),
  DCID Len (8),
  Destination Connection ID (0..160),
  SCID Len (8),
  Source Connection ID (0..160),
  Token Length (i),
  Token (..),
  Length (i),
  Packet Number (8..32),     # Protected
  Protected Payload (0..24), # Skipped Part
  Protected Payload (128),   # Sampled Part
  Protected Payload (..)     # Remainder
}

1-RTT Packet {
  Header Form (1) = 0,
  Fixed Bit (1) = 1,
  Spin Bit (1),
  Reserved Bits (2),         # Protected
  Key Phase (1),             # Protected
  Packet Number Length (2),  # Protected
  Destination Connection ID (0..160),
  Packet Number (8..32),     # Protected
  Protected Payload (0..24), # Skipped Part
  Protected Payload (128),   # Sampled Part
  Protected Payload (..),    # Remainder
}
그림 7: 헤더 보호와 암호문 샘플

TLS 암호군이 QUIC과 함께 사용될 수 있으려면, 해당 암호군과 함께 사용되는 AEAD에 대해 헤더 보호 알고리즘이 지정되어야 MUST 한다. 이 문서는 AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM(이 모든 AES AEAD는 [AEAD]에 정의됨), 그리고 AEAD_CHACHA20_POLY1305([CHACHA]에 정의됨)에 대한 알고리즘을 정의한다. TLS가 암호군을 선택하기 전에는 AEAD_AES_128_GCM 패킷 보호와 일치하는 AES 헤더 보호가 사용된다 (5.4.3절).

5.4.2. 헤더 보호 샘플

헤더 보호 알고리즘은 헤더 보호 키와 패킷 Payload 필드의 암호문 샘플을 모두 사용한다.

항상 같은 수의 바이트가 샘플링되지만, 수신 엔드포인트가 보호를 제거할 때 Packet Number 필드의 길이를 알지 못한다는 점을 고려해야 한다. 암호문 샘플은 Packet Number 필드의 시작으로부터 4바이트 뒤의 오프셋에서 시작하여 취한다. 즉, 헤더 보호를 위한 패킷 암호문 샘플링에서는 Packet Number 필드가 4바이트 길이(가능한 최대 인코딩 길이)라고 가정한다.

엔드포인트는 완전한 샘플을 포함하기에 충분히 길지 않은 패킷을 폐기해야 MUST 한다.

샘플링에 충분한 데이터가 사용 가능하도록 보장하기 위해, 패킷은 인코딩된 패킷 번호와 보호된 페이로드의 결합 길이가 헤더 보호에 필요한 샘플보다 최소 4바이트 길도록 패딩된다. [TLS13]에 정의된 암호군은 -- 이 문서에서 헤더 보호 방식이 정의되지 않은 TLS_AES_128_CCM_8_SHA256을 제외하고 -- 16바이트 확장과 16바이트 헤더 보호 샘플을 가진다. 이는 패킷 번호가 단일 바이트로 인코딩된 경우 보호되지 않은 페이로드에 최소 3바이트의 프레임이 필요하고, 2바이트 패킷 번호 인코딩의 경우 2바이트의 프레임이 필요하다는 결과를 낳는다.

샘플링된 암호문은 다음 의사코드로 결정할 수 있다.

# pn_offset is the start of the Packet Number field.
sample_offset = pn_offset + 4

sample = packet[sample_offset..sample_offset+sample_length]

짧은 헤더 패킷의 패킷 번호 오프셋은 다음과 같이 계산할 수 있다.

pn_offset = 1 + len(connection_id)

그리고 긴 헤더 패킷의 패킷 번호 오프셋은 다음과 같이 계산할 수 있다.

pn_offset = 7 + len(destination_connection_id) +
                len(source_connection_id) +
                len(payload_length)
if packet_type == Initial:
    pn_offset += len(token_length) +
                 len(token)

예를 들어, 짧은 헤더와 8바이트 연결 ID가 있으며 AEAD_AES_128_GCM으로 보호된 패킷의 경우, 샘플은 0 기반 인덱싱을 사용하여 13번째 바이트부터 28번째 바이트까지를 포함한다.

여러 QUIC 패킷이 동일한 UDP 데이터그램에 포함될 수 있다. 각 패킷은 별도로 처리된다.

5.4.3. AES 기반 헤더 보호

이 절은 AEAD_AES_128_GCM, AEAD_AES_128_CCM, 그리고 AEAD_AES_256_GCM에 대한 패킷 보호 알고리즘을 정의한다. AEAD_AES_128_GCM과 AEAD_AES_128_CCM은 Electronic Codebook (ECB) 모드에서 128비트 AES를 사용한다. AEAD_AES_256_GCM은 ECB 모드에서 256비트 AES를 사용한다. AES는 [AES]에 정의되어 있다.

이 알고리즘은 패킷 암호문에서 16바이트를 샘플링한다. 이 값은 AES-ECB의 입력으로 사용된다. 의사코드에서 헤더 보호 함수는 다음과 같이 정의된다.

header_protection(hp_key, sample):
  mask = AES-ECB(hp_key, sample)

5.4.4. ChaCha20 기반 헤더 보호

AEAD_CHACHA20_POLY1305가 사용 중일 때, 헤더 보호는 [CHACHA]의 2.4절에 정의된 원시 ChaCha20 함수를 사용한다. 이는 256비트 키와 패킷 보호 출력에서 샘플링된 16바이트를 사용한다.

샘플링된 암호문의 처음 4바이트는 블록 카운터이다. ChaCha20 구현은 바이트 시퀀스 대신 32비트 정수를 받을 수 있으며, 이 경우 바이트 시퀀스는 little-endian 값으로 해석된다.

나머지 12바이트는 nonce로 사용된다. ChaCha20 구현은 바이트 시퀀스 대신 세 개의 32비트 정수 배열을 받을 수 있으며, 이 경우 nonce 바이트는 32비트 little-endian 정수의 시퀀스로 해석된다.

암호화 마스크는 ChaCha20을 호출하여 5개의 0바이트를 보호함으로써 생성된다. 의사코드에서 헤더 보호 함수는 다음과 같이 정의된다.

header_protection(hp_key, sample):
  counter = sample[0..3]
  nonce = sample[4..15]
  mask = ChaCha20(hp_key, counter, nonce, {0,0,0,0,0})

5.5. 보호된 패킷 수신

엔드포인트가 주어진 패킷 번호의 패킷을 성공적으로 수신하면, 동일한 키 또는 -- 키 갱신이 있는 경우 -- 이후의 패킷 보호 키로 성공적으로 보호를 제거할 수 없는 경우, 같은 패킷 번호 공간에서 더 높은 패킷 번호를 가진 모든 패킷을 폐기해야 MUST 한다. 6절을 보라. 마찬가지로, 키 갱신을 트리거하는 것처럼 보이지만 성공적으로 보호를 제거할 수 없는 패킷은 폐기되어야 MUST 한다.

패킷의 보호 제거에 실패했다고 해서 반드시 피어의 프로토콜 오류나 공격이 존재함을 나타내는 것은 아니다. QUIC에서 사용되는 잘린 패킷 번호 인코딩은 패킷이 크게 지연될 경우 패킷 번호가 잘못 디코딩되게 할 수 있다.

5.6. 0-RTT 키 사용

0-RTT 키를 사용할 수 있는 경우(4.6.1절 참조), 재생 보호가 없다는 것은 프로토콜에 대한 재생 공격을 피하기 위해 그 사용에 제한이 필요함을 의미한다.

[QUIC-TRANSPORT]에 정의된 프레임 중 STREAM, RESET_STREAM, STOP_SENDING, CONNECTION_CLOSE 프레임은 애플리케이션 데이터를 운반하므로 0-RTT와 함께 사용하기에 잠재적으로 안전하지 않다. 0-RTT로 수신된 애플리케이션 데이터는 서버의 애플리케이션이 데이터를 한 번이 아니라 여러 번 처리하게 만들 수 있다. 재생된 애플리케이션 데이터를 처리한 결과로 서버가 수행하는 추가 동작은 원치 않는 결과를 초래할 수 있다. 따라서 클라이언트는 사용 중인 애플리케이션이 구체적으로 요청하지 않는 한 0-RTT를 애플리케이션 데이터에 사용해서는 MUST NOT 안 된다.

QUIC을 사용하는 애플리케이션 프로토콜은 0-RTT의 허용 가능한 사용을 정의하는 프로파일을 포함해야 MUST 한다. 그렇지 않으면 0-RTT는 애플리케이션 데이터를 운반하지 않는 QUIC 프레임을 운반하는 데만 사용될 수 있다. 예를 들어 HTTP에 대한 프로파일은 [HTTP-REPLAY]에 설명되어 있으며 HTTP/3에서 사용된다. [QUIC-HTTP]의 10.9절을 보라.

패킷 재생이 추가 연결 시도를 초래할 수는 있지만, 애플리케이션 데이터를 운반하지 않는 재생된 프레임을 처리하는 효과는 영향을 받는 연결의 상태를 변경하는 것으로 제한된다. TLS 핸드셰이크는 재생된 패킷을 사용하여 성공적으로 완료될 수 없다.

클라이언트는 TLS 핸드셰이크가 완료되기 전에 보내는 데이터에 대해 추가 제한을 적용하고자 할 수 MAY 있다.

클라이언트는 그 밖에는 0-RTT 키를 1-RTT 키와 동등하게 취급하지만, 0-RTT 키로 특정 프레임을 보낼 수 없다는 점은 예외이다. [QUIC-TRANSPORT]의 12.5절을 보라.

서버가 자신의 0-RTT 데이터를 수락했다는 표시를 받은 클라이언트는 서버의 모든 핸드셰이크 메시지를 수신할 때까지 0-RTT 데이터를 보낼 수 있다. 클라이언트는 0-RTT 데이터가 거부되었다는 표시를 받으면 0-RTT 데이터 전송을 중단해야 SHOULD 한다.

서버는 패킷을 보호하기 위해 0-RTT 키를 사용해서는 MUST NOT 안 된다. 서버는 0-RTT 패킷에 대한 확인 응답을 보호하기 위해 1-RTT 키를 사용한다. 클라이언트는 수신한 0-RTT 패킷을 복호화하려고 시도해서는 MUST NOT 안 되며, 대신 이를 폐기해야 MUST 한다.

클라이언트가 1-RTT 키를 설치한 후에는 더 이상 0-RTT 패킷을 보내서는 MUST NOT 안 된다.

5.7. 순서가 어긋난 보호된 패킷 수신

재정렬과 손실로 인해, 최종 TLS 핸드셰이크 메시지를 수신하기 전에 보호된 패킷이 엔드포인트에 수신될 수 있다. 클라이언트는 서버로부터의 1-RTT 패킷을 복호화할 수 없지만, 서버는 클라이언트로부터의 1-RTT 패킷을 복호화할 수 있다. 어느 역할의 엔드포인트든 핸드셰이크를 완료하기 전에 피어로부터의 1-RTT 패킷을 복호화해서는 MUST NOT 안 된다.

서버는 클라이언트로부터 첫 번째 핸드셰이크 메시지를 받은 후 1-RTT 키를 사용할 수 있더라도, 클라이언트 상태에 대한 보증이 부족하다.

  • 서버가 사전 공유 키를 사용하기로 선택하고 클라이언트의 사전 공유 키 바인더를 검증하지 않은 한, 클라이언트는 인증되지 않는다. [TLS13]의 4.2.11절을 보라.
  • 서버가 Retry 패킷 또는 다른 수단으로 클라이언트의 주소를 검증하지 않은 한, 클라이언트는 생존성을 증명하지 않았다. [QUIC-TRANSPORT]의 8.1절을 보라.
  • 서버가 응답하는 수신된 0-RTT 데이터는 재생 공격으로 인한 것일 수 있다.

따라서 핸드셰이크가 완료되기 전 서버의 1-RTT 키 사용은 데이터 전송으로 제한된다. 서버는 TLS 핸드셰이크가 완료되기 전에 수신된 1-RTT 보호 패킷을 처리해서는 MUST NOT 안 된다. 확인 응답을 보내는 것은 패킷의 모든 프레임이 처리되었음을 나타내므로, 서버는 TLS 핸드셰이크가 완료될 때까지 1-RTT 패킷에 대한 확인 응답을 보낼 수 없다. 1-RTT 키로 보호된 수신 패킷은 저장되었다가 핸드셰이크가 완료된 후 나중에 복호화되고 사용될 수 MAY 있다.

서버가 클라이언트 Finished 메시지를 기다려야 한다는 요구사항은 그 메시지가 전달되어야 한다는 의존성을 만든다. 클라이언트는 Handshake 패킷 중 하나가 확인 응답될 때까지 Finished 메시지를 운반하는 CRYPTO 프레임의 사본을 포함하는 Handshake 패킷과 함께 1-RTT 패킷을 병합하여 전송함으로써, 이것이 의미하는 head-of-line blocking 가능성을 피할 수 있다. 이는 서버가 해당 패킷을 즉시 처리할 수 있게 한다.

서버는 TLS ClientHello를 수신하기 전에 0-RTT 키로 보호된 패킷을 받을 수 있다. 서버는 ClientHello 수신을 예상하여 나중에 복호화하기 위해 이러한 패킷을 보관할 수 MAY 있다.

클라이언트는 일반적으로 핸드셰이크가 완료되는 것과 동시에 1-RTT 키를 수신한다. 1-RTT 비밀 값을 가지고 있더라도, 클라이언트는 TLS 핸드셰이크가 완료되기 전에 수신되는 1-RTT 보호 패킷을 처리해서는 MUST NOT 안 된다.

5.8. Retry 패킷 무결성

Retry 패킷([QUIC-TRANSPORT]의 17.2.5절 참조)은 두 가지 속성을 제공하는 Retry Integrity Tag를 운반한다. 이는 네트워크에 의해 우발적으로 손상된 패킷을 폐기할 수 있게 하고, Initial 패킷을 관찰한 엔터티만 유효한 Retry 패킷을 보낼 수 있게 한다.

Retry Integrity Tag는 다음 입력과 함께 사용되는 AEAD_AES_128_GCM [AEAD]의 출력으로 계산되는 128비트 필드이다.

  • 비밀 키 K는 0xbe0c690b9f66575a1d766b54e368c84e와 같은 128비트이다.
  • nonce N은 0x461599d35d632bf2239825bb와 같은 96비트이다.
  • 평문 P는 비어 있다.
  • 연관 데이터 A는 그림 8에 나타난 Retry Pseudo-Packet의 내용이다.

비밀 키와 nonce는 0xd9c9943e6101fd200021506bcc02814c73030f25c79d71ce876eca876e6fca8e를 비밀 값으로 사용하고 레이블 "quic key"와 "quic iv"를 사용하여 HKDF-Expand-Label을 호출함으로써 파생된 값이다(5.1절).

Retry Pseudo-Packet {
  ODCID Length (8),
  Original Destination Connection ID (0..160),
  Header Form (1) = 1,
  Fixed Bit (1) = 1,
  Long Packet Type (2) = 3,
  Unused (4),
  Version (32),
  DCID Len (8),
  Destination Connection ID (0..160),
  SCID Len (8),
  Source Connection ID (0..160),
  Retry Token (..),
}
그림 8: Retry Pseudo-Packet

Retry Pseudo-Packet은 네트워크상으로 전송되지 않는다. 이는 전송된 Retry 패킷에서 Retry Integrity Tag를 제거하고 다음 두 필드를 앞에 붙여 계산된다.

ODCID Length:

ODCID Length 필드는 뒤따르는 Original Destination Connection ID 필드의 길이를 바이트 단위로 포함하며, 8비트 부호 없는 정수로 인코딩된다.

Original Destination Connection ID:

Original Destination Connection ID는 이 Retry가 응답하는 Initial 패킷의 Destination Connection ID 값을 포함한다. 이 필드의 길이는 ODCID Length에 지정된다. 이 필드가 존재함으로써 Initial 패킷을 관찰한 엔터티만 유효한 Retry 패킷을 보낼 수 있음이 보장된다.

6. 키 갱신

핸드셰이크가 확인되면(4.1.2절 참조), 엔드포인트는 키 갱신을 시작할 수 MAY 있다.

Key Phase 비트는 패킷을 보호하는 데 어떤 패킷 보호 키가 사용되는지 나타낸다. Key Phase 비트는 첫 번째 1-RTT 패킷 집합에 대해 처음에는 0으로 설정되고, 이후 각 키 갱신을 알리기 위해 토글된다.

Key Phase 비트는 수신자가 변경을 트리거한 첫 번째 패킷을 받지 않아도 키 재료의 변경을 감지할 수 있게 한다. 변경된 Key Phase 비트를 감지한 엔드포인트는 키를 갱신하고 변경된 값을 포함하는 패킷을 복호화한다.

키 갱신을 시작하면 양쪽 엔드포인트가 키를 갱신한다. 이는 엔드포인트가 독립적으로 키를 갱신할 수 있는 TLS와 다르다.

이 메커니즘은 1-RTT 암호화 키를 사용해 전송되는 KeyUpdate 메시지에 의존하는 TLS의 키 갱신 메커니즘을 대체한다. 엔드포인트는 TLS KeyUpdate 메시지를 보내서는 MUST NOT 안 된다. 엔드포인트는 TLS KeyUpdate 메시지 수신을 unexpected_message의 치명적 TLS 경고와 동등한 0x010a 유형의 연결 오류로 처리해야 MUST 한다. 4.8절을 보라.

그림 9는 처음 사용된 키 집합(@M으로 식별됨)이 갱신된 키(@N으로 식별됨)로 대체되는 키 갱신 과정을 보여준다. Key Phase 비트의 값은 대괄호 [] 안에 표시된다.

   Initiating Peer                    Responding Peer

@M [0] QUIC Packets

... Update to @N
@N [1] QUIC Packets
                      -------->
                                         Update to @N ...
                                      QUIC Packets [1] @N
                      <--------
                                      QUIC Packets [1] @N
                                    containing ACK
                      <--------
... Key Update Permitted

@N [1] QUIC Packets
         containing ACK for @N packets
                      -------->
                                 Key Update Permitted ...
그림 9: 키 갱신

6.1. 키 갱신 시작

엔드포인트는 패킷 보호를 위해 별도의 읽기 및 쓰기 비밀 값을 유지한다. 엔드포인트는 패킷 보호 쓰기 비밀 값을 갱신하고 이를 사용해 새 패킷을 보호함으로써 키 갱신을 시작한다. 엔드포인트는 [TLS13]의 7.2절에서 수행되는 것처럼 기존 쓰기 비밀 값에서 새 쓰기 비밀 값을 생성한다. 이는 TLS가 제공하는 KDF 함수와 "quic ku" 레이블을 사용한다. 해당 키와 IV는 5.1절에 정의된 대로 그 비밀 값에서 생성된다. 헤더 보호 키는 갱신되지 않는다.

예를 들어 TLS 1.3으로 쓰기 키를 갱신하려면 HKDF-Expand-Label이 다음과 같이 사용된다.

secret_<n+1> = HKDF-Expand-Label(secret_<n>, "quic ku",
                                 "", Hash.length)

엔드포인트는 Key Phase 비트의 값을 토글하고, 갱신된 키와 IV를 사용하여 이후 모든 패킷을 보호한다.

엔드포인트는 핸드셰이크를 확인하기 전에는 키 갱신을 시작해서는 MUST NOT 안 된다(4.1.2절). 엔드포인트는 현재 키 위상의 키로 보호되어 전송된 패킷에 대한 확인 응답을 받기 전에는 후속 키 갱신을 시작해서는 MUST NOT 안 된다. 이는 또 다른 키 갱신이 시작되기 전에 키가 양쪽 피어 모두에서 사용 가능하도록 보장한다. 이는 각 키 위상으로 보낸 가장 낮은 패킷 번호와 1-RTT 공간에서 가장 높은 확인 응답된 패킷 번호를 추적함으로써 구현할 수 있다. 후자가 전자보다 크거나 같으면 또 다른 키 갱신을 시작할 수 있다.

키 갱신을 시작한 엔드포인트는 패킷 수신에 사용하는 키도 갱신한다. 이러한 키는 피어가 갱신한 후 보내는 패킷을 처리하는 데 필요하다.

엔드포인트는 새 키를 사용해 전송된 패킷의 보호를 성공적으로 제거할 때까지 이전 키를 보유해야 MUST 한다. 엔드포인트는 새 키를 사용해 전송된 패킷의 보호를 제거한 후에도 얼마 동안 이전 키를 보유해야 SHOULD 한다. 이전 키를 너무 일찍 폐기하면 지연된 패킷이 폐기될 수 있다. 패킷 폐기는 피어에 의해 패킷 손실로 해석되며 성능에 나쁜 영향을 줄 수 있다.

6.2. 키 갱신에 응답

피어는 현재 키 위상의 패킷에 대한 확인 응답을 받은 후 키 갱신을 시작할 수 있다. 엔드포인트는 자신이 마지막으로 보낸 패킷을 보호하는 데 사용한 값과 다른 키 위상을 가진 패킷을 처리할 때 키 갱신을 감지한다. 이 패킷을 처리하기 위해 엔드포인트는 다음 패킷 보호 키와 IV를 사용한다. 이러한 키를 생성하는 것에 대한 고려사항은 6.3절을 보라.

패킷이 다음 키와 IV를 사용하여 성공적으로 처리되면, 피어가 키 갱신을 시작한 것이다. 엔드포인트는 이에 응답하여 자신의 송신 키를 해당 키 위상으로 갱신해야 MUST 하며, 이는 6.1절에 설명된 대로 수행된다. 송신 키는 갱신된 키로 수신된 패킷에 대한 확인 응답을 보내기 전에 갱신되어야 MUST 한다. 키 갱신을 트리거한 패킷에 대한 확인 응답을 갱신된 키로 보호된 패킷에 담아 보냄으로써, 엔드포인트는 키 갱신이 완료되었음을 알린다.

엔드포인트는 일반적인 패킷 전송 동작에 따라 패킷이나 확인 응답의 전송을 지연할 수 있다. 키 갱신에 대한 응답으로 즉시 패킷을 생성할 필요는 없다. 엔드포인트가 다음에 보내는 패킷은 갱신된 키를 사용한다. 확인 응답을 포함하는 다음 패킷은 키 갱신이 완료되게 한다. 엔드포인트가 키 갱신을 시작한 패킷에 대한 확인 응답을 포함하는 갱신된 키의 패킷을 하나도 보내기 전에 두 번째 갱신을 감지하면, 이는 피어가 확인을 기다리지 않고 키를 두 번 갱신했음을 나타낸다. 엔드포인트는 이러한 연속적인 키 갱신을 KEY_UPDATE_ERROR 유형의 연결 오류로 처리할 수 MAY 있다.

엔드포인트가 이전 키로 보호된 패킷에 실린 확인 응답을 수신했는데, 그 확인 응답된 패킷 중 하나라도 더 새로운 키로 보호되어 있었다면, 이를 KEY_UPDATE_ERROR 유형의 연결 오류로 처리할 수 MAY 있다. 이는 피어가 키 갱신을 시작하는 패킷을 수신하고 확인 응답했지만 이에 응답하여 키를 갱신하지 않았음을 나타낸다.

6.3. 수신 키 생성 시점

겉보기 키 갱신에 응답하는 엔드포인트는 Key Phase 비트가 유효하지 않았음을 나타낼 수 있는 타이밍 부채널 신호를 생성해서는 MUST NOT 안 된다(9.5절 참조). 키 갱신이 아직 허용되지 않을 때 엔드포인트는 폐기된 키 대신 무작위 패킷 보호 키를 사용할 수 있다. 무작위 키를 사용하면 패킷 보호 제거 시도가 타이밍 변화를 초래하지 않도록 보장하고, 유효하지 않은 Key Phase 비트를 가진 패킷이 거부되게 한다.

수신 패킷을 위한 새 패킷 보호 키를 생성하는 과정은 키 갱신이 발생했음을 드러낼 수 있다. 엔드포인트는 패킷 처리의 일부로 새 키를 생성할 수 MAY 있지만, 이는 공격자가 키 갱신이 언제 일어나는지 알아내고 따라서 Key Phase 비트 값을 누출하는 데 사용할 수 있는 타이밍 신호를 만든다.

엔드포인트는 일반적으로 현재 및 다음 수신 패킷 보호 키를 사용할 수 있어야 한다. 키 갱신이 완료된 후 짧은 기간 동안, 최대 PTO까지, 엔드포인트는 다음 수신 패킷 보호 키 집합 생성을 지연할 수 MAY 있다. 이를 통해 엔드포인트는 두 집합의 수신 키만 보유할 수 있다. 6.5절을 보라.

일단 생성되면, 다음 패킷 보호 키 집합은 수신된 패킷이 이후 폐기되더라도 보유되어야 SHOULD 한다. 겉보기 키 갱신을 포함하는 패킷은 위조하기 쉽고, 키 갱신 과정이 큰 노력을 요구하지는 않지만, 이 과정을 트리거하는 것은 공격자가 DoS에 사용할 수 있다.

이러한 이유로, 엔드포인트는 수신 패킷을 위한 두 집합의 패킷 보호 키, 즉 현재 키와 다음 키를 보유할 수 있어야 MUST 한다. 이들에 더해 이전 키를 보유하면 성능이 향상될 수 있지만 필수는 아니다.

6.4. 갱신된 키로 전송

엔드포인트는 이전 키로 보호된 패킷을 절대 보내지 않는다. 현재 키만 사용된다. 패킷 보호에 사용되는 키는 더 새로운 키로 전환한 직후 폐기될 수 있다.

더 높은 패킷 번호를 가진 패킷은 더 낮은 패킷 번호를 가진 패킷과 동일하거나 더 새로운 패킷 보호 키로 보호되어야 MUST 한다. 더 낮은 패킷 번호의 패킷에 더 새로운 키가 사용되었는데 이전 키로 보호를 성공적으로 제거한 엔드포인트는 이를 KEY_UPDATE_ERROR 유형의 연결 오류로 처리해야 MUST 한다.

6.5. 서로 다른 키로 수신

키 갱신 중 패킷을 수신할 때, 네트워크에 의해 지연된 경우 이전 키로 보호된 패킷이 도착할 수 있다. 이전 패킷 보호 키를 보유하면 이러한 패킷을 성공적으로 처리할 수 있다.

다음 키 위상의 키로 보호된 패킷은 이전 키 위상의 키로 보호된 패킷과 동일한 Key Phase 값을 사용하므로, 이전 키로 보호된 패킷을 처리하려면 둘을 구별할 필요가 있다. 이는 패킷 번호를 사용하여 수행할 수 있다. 복구된 패킷 번호가 현재 키 위상의 어떤 패킷 번호보다 낮으면 이전 패킷 보호 키를 사용한다. 복구된 패킷 번호가 현재 키 위상의 어떤 패킷 번호보다 높으면 다음 패킷 보호 키를 사용해야 한다.

이전, 현재, 다음 패킷 보호 키 중에서 선택하는 모든 과정이 어떤 키가 패킷 보호 제거에 사용되었는지를 드러낼 수 있는 타이밍 부채널을 노출하지 않도록 주의가 필요하다. 자세한 내용은 9.5절을 보라.

대안으로, 엔드포인트는 패킷이 네트워크에서 재정렬될 수 있는 충분한 시간이 지난 후 이전 키를 다음 키로 교체하면서 두 집합의 패킷 보호 키만 보유할 수 있다. 이 경우 Key Phase 비트만으로 키를 선택할 수 있다.

엔드포인트는 다음 수신 키 집합을 현재 키로 승격한 후 약 Probe Timeout(PTO; [QUIC-RECOVERY] 참조) 정도의 기간 동안 이후 패킷 보호 키 집합 생성을 허용할 수 MAY 있다. 이러한 갱신된 키는 그 시점에 이전 키를 대체할 수 MAY 있다. PTO가 주관적 측정값이라는 점, 즉 피어가 RTT에 대해 다른 관점을 가질 수 있다는 주의사항과 함께, 이 시간은 어떤 재정렬된 패킷도 확인 응답되었더라도 피어에 의해 손실로 선언될 만큼 충분히 길고, 피어가 추가 키 갱신을 시작할 수 있을 만큼 충분히 짧을 것으로 예상된다.

엔드포인트는 피어가 이전 키를 보유하는 기간 동안 키 갱신을 시작하는 패킷을 피어가 복호화하지 못할 가능성을 고려해야 한다. 엔드포인트는 이전 키 갱신이 수신되었음을 확인하는 확인 응답을 받은 후 키 갱신을 시작하기 전에 PTO의 세 배를 기다려야 SHOULD 한다. 충분한 시간을 허용하지 않으면 패킷이 폐기될 수 있다.

엔드포인트는 새 키를 사용해 보호된 패킷을 수신한 후 PTO의 세 배를 넘지 않는 기간 동안만 이전 읽기 키를 보유해야 SHOULD 한다. 이 기간이 지나면 이전 읽기 키와 해당 비밀 값은 폐기되어야 SHOULD 한다.

6.6. AEAD 사용 한계

이 문서는 QUIC을 사용할 때 과도한 사용이 통신의 기밀성과 무결성을 공격하는 데 공격자에게 불균형한 이점을 주지 않도록 보장하기 위해 AEAD 알고리즘의 사용 한계를 설정한다.

TLS 1.3에 정의된 사용 한계는 기밀성에 대한 공격을 방지하기 위한 것이며, AEAD 보호가 성공적으로 적용된 경우에 적용된다. 인증 암호화의 무결성 보호도 패킷 위조 시도 횟수를 제한하는 것에 의존한다. TLS는 어떤 레코드가 인증 검사에 실패한 후 연결을 닫음으로써 이를 달성한다. 이에 비해 QUIC은 인증될 수 없는 모든 패킷을 무시하여 여러 위조 시도를 허용한다.

QUIC은 AEAD 기밀성 한계와 무결성 한계를 별도로 계산한다. 기밀성 한계는 주어진 키로 암호화된 패킷 수에 적용된다. 무결성 한계는 주어진 연결 내에서 복호화된 패킷 수에 적용된다. 각 AEAD 알고리즘에 대해 이러한 한계를 강제하는 세부사항은 아래에 이어진다.

엔드포인트는 각 키 집합에 대해 암호화된 패킷 수를 세어야 MUST 한다. 같은 키로 암호화된 총 패킷 수가 선택된 AEAD의 기밀성 한계를 초과하면, 엔드포인트는 해당 키 사용을 중단해야 MUST 한다. 엔드포인트는 선택된 AEAD의 기밀성 한계가 허용하는 것보다 더 많은 보호된 패킷을 보내기 전에 키 갱신을 시작해야 MUST 한다. 키 갱신이 불가능하거나 무결성 한계에 도달하면, 엔드포인트는 연결 사용을 중단해야 MUST 하며, 패킷을 수신한 것에 대한 응답으로 stateless reset만 보내야 한다. 키 갱신이 불가능한 상태에 도달하기 전에 AEAD_LIMIT_REACHED 유형의 연결 오류로 연결을 즉시 닫는 것이 RECOMMENDED 된다.

AEAD_AES_128_GCM 및 AEAD_AES_256_GCM의 경우 기밀성 한계는 223개의 암호화된 패킷이다. 부록 B.1을 보라. AEAD_CHACHA20_POLY1305의 경우 기밀성 한계는 가능한 패킷 수(262)보다 크므로 무시할 수 있다. AEAD_AES_128_CCM의 경우 기밀성 한계는 221.5개의 암호화된 패킷이다. 부록 B.2를 보라. 한계를 적용하면 공격자가 사용 중인 AEAD를 무작위 순열과 구별할 확률이 줄어든다. [AEBounds], [ROBUST], 및 [GCM-MU]을 보라.

전송된 패킷을 세는 것 외에도, 엔드포인트는 연결 수명 동안 인증에 실패한 수신 패킷 수를 세어야 MUST 한다. 연결 내에서 모든 키를 통틀어 인증에 실패한 수신 패킷의 총 수가 선택된 AEAD의 무결성 한계를 초과하면, 엔드포인트는 AEAD_LIMIT_REACHED 유형의 연결 오류로 연결을 즉시 닫고 더 이상 어떤 패킷도 처리하지 않아야 MUST 한다.

AEAD_AES_128_GCM 및 AEAD_AES_256_GCM의 경우 무결성 한계는 252개의 유효하지 않은 패킷이다. 부록 B.1을 보라. AEAD_CHACHA20_POLY1305의 경우 무결성 한계는 236개의 유효하지 않은 패킷이다. [AEBounds]를 보라. AEAD_AES_128_CCM의 경우 무결성 한계는 221.5개의 유효하지 않은 패킷이다. 부록 B.2를 보라. 이 한계를 적용하면 공격자가 패킷을 성공적으로 위조할 확률이 줄어든다. [AEBounds], [ROBUST], 및 [GCM-MU]을 보라.

패킷 크기를 제한하는 엔드포인트는 더 높은 기밀성 및 무결성 한계를 사용할 수 MAY 있다. 자세한 내용은 부록 B를 보라.

향후 분석과 명세는 AEAD에 대한 기밀성 또는 무결성 한계를 완화할 수 MAY 있다.

QUIC과 함께 사용하도록 지정된 모든 TLS 암호군은 관련 AEAD 함수의 사용 한계를 정의해야 MUST 하며, 이는 기밀성과 무결성을 위한 여유를 보존해야 한다. 즉, 인증될 수 있는 패킷 수와 인증에 실패할 수 있는 패킷 수에 대한 한계가 지정되어야 MUST 한다. 값의 근거가 되는 모든 분석과 해당 분석에서 사용된 모든 가정에 대한 참조를 제공하면, 한계를 다양한 사용 조건에 맞게 조정할 수 있다.

6.7. 키 갱신 오류 코드

KEY_UPDATE_ERROR 오류 코드(0x0e)는 키 갱신과 관련된 오류를 알리는 데 사용된다.

7. Initial 메시지의 보안

Initial 패킷은 비밀 키로 보호되지 않으므로, 공격자에 의한 잠재적 변조의 대상이 된다. QUIC은 패킷을 읽을 수 없는 공격자에 대한 보호를 제공하지만, 공격자가 패킷을 관찰하고 주입할 수 있는 공격에 대해서는 추가 보호를 제공하려고 시도하지 않는다. TLS 메시지 자체를 수정하는 것과 같은 일부 형태의 변조는 탐지 가능하지만, ACK를 수정하는 것과 같은 일부 형태는 그렇지 않다.

예를 들어 공격자는 ACK 프레임을 포함하는 패킷을 주입하여 어떤 패킷이 수신되지 않은 것처럼 보이게 하거나, 연결 상태에 대한 잘못된 인상을 만들 수 있다(예: ACK Delay를 수정함으로써). 이러한 패킷은 정상적인 패킷이 중복으로 간주되어 폐기되게 할 수 있음에 유의하라. 구현은 Initial 패킷에 포함되어 있지만 달리 인증되지 않은 모든 데이터에 의존할 때 주의해야 SHOULD 한다.

공격자가 Handshake 패킷에 실린 데이터를 변조하는 것도 가능하지만, 그러한 종류의 변조는 TLS 핸드셰이크 메시지를 수정해야 하므로, 그러한 모든 변조는 TLS 핸드셰이크 실패를 일으킨다.

8. TLS 핸드셰이크에 대한 QUIC 전용 조정

TLS 핸드셰이크의 특정 측면은 QUIC과 함께 사용될 때 달라진다.

QUIC은 또한 TLS로부터 추가 기능을 요구한다. 암호학적 매개변수의 협상에 더해, TLS 핸드셰이크는 QUIC 전송 매개변수의 값을 운반하고 인증한다.

8.1. 프로토콜 협상

QUIC은 암호학적 핸드셰이크가 인증된 프로토콜 협상을 제공할 것을 요구한다. TLS는 애플리케이션 프로토콜을 선택하기 위해 Application-Layer Protocol Negotiation [ALPN]을 사용한다. 애플리케이션 프로토콜에 합의하기 위한 다른 메커니즘이 사용되지 않는 한, 엔드포인트는 이 목적을 위해 ALPN을 사용해야 MUST 한다.

ALPN을 사용할 때, 애플리케이션 프로토콜이 협상되지 않으면 엔드포인트는 no_application_protocol TLS 경고(QUIC 오류 코드 0x0178; 4.8절 참조)와 함께 연결을 즉시 닫아야 MUST 한다([QUIC-TRANSPORT]의 10.2절 참조). [ALPN]은 서버가 이 경고를 사용한다고만 명시하지만, QUIC 클라이언트는 ALPN 협상이 실패할 때 연결을 종료하기 위해 오류 0x0178을 사용해야 MUST 한다.

애플리케이션 프로토콜은 자신이 동작할 수 있는 QUIC 버전을 제한할 수 MAY 있다. 서버는 클라이언트가 선택한 QUIC 버전과 호환되는 애플리케이션 프로토콜을 선택해야 MUST 한다. 서버는 호환되는 애플리케이션 프로토콜을 선택할 수 없음을 0x0178(no_application_protocol) 유형의 연결 오류로 처리해야 MUST 한다. 마찬가지로 클라이언트는 서버가 호환되지 않는 애플리케이션 프로토콜을 선택한 것을 0x0178 유형의 연결 오류로 처리해야 MUST 한다.

8.2. QUIC 전송 매개변수 확장

QUIC 전송 매개변수는 TLS 확장에 실려 운반된다. 서로 다른 QUIC 버전은 전송 구성을 협상하기 위한 서로 다른 방법을 정의할 수 있다.

TLS 핸드셰이크에 전송 매개변수를 포함하면 이러한 값에 대한 무결성 보호가 제공된다.

   enum {
      quic_transport_parameters(0x39), (65535)
   } ExtensionType;

quic_transport_parameters 확장의 extension_data 필드는 사용 중인 QUIC 버전에 의해 정의되는 값을 포함한다.

quic_transport_parameters 확장은 핸드셰이크 중 ClientHello 및 EncryptedExtensions 메시지에 실려 운반된다. 엔드포인트는 quic_transport_parameters 확장을 보내야 MUST 한다. quic_transport_parameters 확장이 없는 ClientHello 또는 EncryptedExtensions 메시지를 수신한 엔드포인트는 0x016d 유형의 오류(치명적 TLS missing_extension 경고와 동등함, 4.8절 참조)로 연결을 닫아야 MUST 한다.

전송 매개변수는 핸드셰이크 완료 전에 사용 가능해진다. 서버는 이러한 값을 핸드셰이크 완료보다 먼저 사용할 수 있다. 그러나 전송 매개변수의 값은 핸드셰이크가 완료될 때까지 인증되지 않으므로, 이러한 매개변수의 어떤 사용도 그 진정성에 의존할 수 없다. 전송 매개변수에 대한 모든 변조는 핸드셰이크 실패를 일으킨다.

엔드포인트는 QUIC을 사용하지 않는 TLS 연결(예: [TLS13]에 정의된 TCP와 함께 TLS를 사용하는 경우)에서 이 확장을 보내서는 MUST NOT 안 된다. 이 확장을 지원하는 구현은 전송이 QUIC이 아닐 때 이 확장을 수신하면 치명적 unsupported_extension 경고를 보내야 MUST 한다.

quic_transport_parameters 확장을 협상하면 EndOfEarlyData가 제거된다. 8.3절을 보라.

8.3. EndOfEarlyData 메시지 제거

TLS EndOfEarlyData 메시지는 QUIC과 함께 사용되지 않는다. QUIC은 0-RTT 데이터의 끝을 표시하거나 Handshake 키로의 변경을 알리기 위해 이 메시지에 의존하지 않는다.

클라이언트는 EndOfEarlyData 메시지를 보내서는 MUST NOT 안 된다. 서버는 0-RTT 패킷의 CRYPTO 프레임 수신을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 MUST 한다.

그 결과 EndOfEarlyData는 TLS 핸드셰이크 transcript에 나타나지 않는다.

8.4. TLS 미들박스 호환성 모드 금지

[TLS13]의 부록 D.4는 일부 미들박스의 버그를 우회하기 위한 방안으로 TLS 1.3 핸드셰이크의 변경을 설명한다. TLS 1.3 미들박스 호환성 모드는 ClientHello와 ServerHello에서 legacy_session_id 필드를 32바이트 값으로 설정한 다음 change_cipher_spec 레코드를 보내는 것을 포함한다. 이 필드와 레코드는 모두 의미 내용을 담지 않으며 무시된다.

이 모드는 TCP 위의 TLS를 방해하는 미들박스에만 적용되므로 QUIC에서는 쓸모가 없다. QUIC은 change_cipher_spec 레코드를 운반할 수단도 제공하지 않는다. 클라이언트는 TLS 1.3 호환성 모드의 사용을 요청해서는 MUST NOT 안 된다. 서버는 비어 있지 않은 legacy_session_id 필드가 있는 TLS ClientHello의 수신을 PROTOCOL_VIOLATION 유형의 연결 오류로 처리해야 SHOULD 한다.

9. 보안 고려사항

TLS에 적용되는 모든 보안 고려사항은 QUIC에서 TLS를 사용하는 경우에도 적용된다. [TLS13] 전체와 그 부록들을 읽는 것이 QUIC의 보안 속성을 이해하는 가장 좋은 방법이다.

이 절은 TLS 통합에 특정한 더 중요한 보안 측면 중 일부를 요약하지만, 문서의 나머지 부분에도 보안과 관련된 세부사항이 많이 있다.

9.1. 세션 연결 가능성

TLS 세션 티켓의 사용은 서버 및 가능하게는 다른 엔터티가 같은 클라이언트가 만든 연결을 상관시킬 수 있게 한다. 자세한 내용은 4.5절을 보라.

9.2. 0-RTT를 사용한 재생 공격

[TLS13]의 8절에 설명된 것처럼, TLS early data의 사용에는 재생 공격에 대한 노출이 따른다. QUIC에서 0-RTT를 사용하는 것도 마찬가지로 재생 공격에 취약하다.

엔드포인트는 [TLS13]에 설명된 재생 보호를 구현하고 사용해야 MUST 하지만, 이러한 보호가 완전하지 않다는 점은 인정된다. 따라서 재생 위험에 대한 추가 고려가 필요하다.

QUIC은 그것이 운반할 수 있는 애플리케이션 프로토콜 정보를 제외하면 재생 공격에 취약하지 않다. [QUIC-TRANSPORT]에 정의된 프레임 유형에 기반한 QUIC 프로토콜 상태 관리는 재생에 취약하지 않다. QUIC 프레임 처리는 멱등적이며, 프레임이 재생되거나 재정렬되거나 손실되더라도 유효하지 않은 연결 상태를 초래할 수 없다. QUIC 연결은 QUIC이 제공하는 애플리케이션 프로토콜에 의해 생성되는 것을 제외하고, 연결 수명을 넘어 지속되는 효과를 생성하지 않는다.

TLS 세션 티켓과 주소 검증 토큰은 연결 사이에서 QUIC 구성 정보를 운반하는 데 사용되며, 구체적으로는 연결 설정 및 주소 검증에 사용되는 상태를 서버가 효율적으로 복구할 수 있게 하는 데 사용된다. 이들은 엔드포인트 사이에서 애플리케이션 의미를 전달하는 데 사용되어서는 MUST NOT 안 된다. 클라이언트는 이를 불투명한 값으로 처리해야 MUST 한다. 이러한 토큰의 재사용 가능성은 재생에 대한 더 강한 보호가 필요함을 의미한다.

연결에서 0-RTT를 수락하는 서버는 0-RTT 없이 연결을 수락하는 경우보다 더 높은 비용을 부담한다. 여기에는 더 높은 처리 및 계산 비용이 포함된다. 서버는 0-RTT를 수락할 때 재생 가능성과 모든 관련 비용을 고려해야 한다.

궁극적으로 0-RTT를 사용한 재생 공격의 위험을 관리할 책임은 애플리케이션 프로토콜에 있다. QUIC을 사용하는 애플리케이션 프로토콜은 프로토콜이 0-RTT를 어떻게 사용하는지와 재생 공격을 방지하기 위해 사용되는 조치를 설명해야 MUST 한다. 재생 위험 분석은 애플리케이션 의미를 운반하는 모든 QUIC 프로토콜 기능을 고려해야 한다.

0-RTT를 완전히 비활성화하는 것이 재생 공격에 대한 가장 효과적인 방어이다.

QUIC 확장은 재생 공격이 자신의 동작에 어떤 영향을 미치는지 설명하거나, 0-RTT에서 해당 확장의 사용을 금지해야 MUST 한다. 애플리케이션 프로토콜은 애플리케이션 의미를 운반하는 확장의 0-RTT 사용을 금지하거나 재생 완화 전략을 제공해야 MUST 한다.

9.3. 패킷 반사 공격 완화

서버로부터 큰 핸드셰이크 메시지 블록을 유발하는 작은 ClientHello는 공격자가 생성하는 트래픽을 증폭하기 위한 패킷 반사 공격에 사용될 수 있다.

QUIC은 이 공격에 대해 세 가지 방어를 포함한다. 첫째, ClientHello를 포함하는 패킷은 최소 크기로 패딩되어야 MUST 한다. 둘째, 검증되지 않은 출발지 주소에 응답하는 경우, 서버는 자신이 받은 바이트 수의 세 배보다 더 많은 바이트를 보내는 것이 금지된다 ([QUIC-TRANSPORT]의 8.1절 참조). 마지막으로, Handshake 패킷의 확인 응답은 인증되므로, blind 공격자는 이를 위조할 수 없다. 종합하면 이러한 방어는 증폭 수준을 제한한다.

9.4. 헤더 보호 분석

[NAN]은 nonce privacy를 제공하는 인증 암호화 알고리즘을 분석하며, 이를 "Hide Nonce" (HN) 변환이라고 부른다. 이 문서의 일반 헤더 보호 구성은 그러한 알고리즘 중 하나(HN1)이다. 헤더 보호는 패킷 보호 AEAD 이후에 적용되며, AEAD 출력에서 바이트 집합(sample)을 샘플링하고 다음과 같이 의사난수 함수(PRF)를 사용하여 헤더 필드를 암호화한다.

protected_field = field XOR PRF(hp_key, sample)

이 문서의 헤더 보호 변형은 일반 PRF 대신 의사난수 순열(PRP)을 사용한다. 그러나 모든 PRP는 또한 PRF이므로 [IMC], 이러한 변형은 HN1 구성에서 벗어나지 않는다.

hp_key는 패킷 보호 키와 구별되므로, 헤더 보호는 [NAN]에 정의된 AE2 보안을 달성하며 따라서 보호된 패킷 헤더인 field의 프라이버시를 보장한다. 이 구성에 기반한 향후 헤더 보호 변형은 동등한 보안 보장을 보장하기 위해 PRF를 사용해야 MUST 한다.

같은 키와 암호문 샘플을 두 번 이상 사용하면 헤더 보호가 손상될 위험이 있다. 같은 키와 암호문 샘플로 두 개의 서로 다른 헤더를 보호하면 보호된 필드들의 배타적 OR가 드러난다. AEAD가 PRF로 동작한다고 가정할 때, L비트가 샘플링되면 두 암호문 샘플이 동일할 확률은 2-L/2, 즉 birthday bound에 접근한다. 이 문서에 설명된 알고리즘의 경우 그 확률은 264분의 1이다.

공격자가 패킷 헤더를 수정하는 것을 방지하기 위해, 헤더는 패킷 보호를 사용해 전이적으로 인증된다. 전체 패킷 헤더는 인증된 추가 데이터의 일부이다. 위조되거나 수정된 보호 필드는 패킷 보호가 제거된 후에만 탐지될 수 있다.

9.5. 헤더 보호 타이밍 부채널

공격자는 패킷 번호 또는 Key Phase에 대한 값을 추측하고, 엔드포인트가 타이밍 부채널을 통해 추측을 확인하게 할 수 있다. 마찬가지로 패킷 번호 길이에 대한 추측도 시도되고 노출될 수 있다. 패킷 수신자가 패킷 보호 제거를 시도하지 않고 중복 패킷 번호를 가진 패킷을 폐기한다면, 패킷 번호가 수신된 패킷과 일치한다는 것을 타이밍 부채널을 통해 드러낼 수 있다. 인증이 부채널로부터 자유롭기 위해서는, 헤더 보호 제거, 패킷 번호 복구, 패킷 보호 제거의 전체 과정이 타이밍 및 기타 부채널 없이 함께 적용되어야 MUST 한다.

패킷을 보낼 때, 패킷 페이로드와 패킷 번호의 구성 및 보호는 패킷 번호나 그 인코딩 크기를 드러내는 부채널이 없어야 MUST 한다.

키 갱신 중 새 키를 생성하는 데 걸리는 시간은 키 갱신이 발생했음을 타이밍 부채널을 통해 드러낼 수 있다. 또는 공격자가 패킷을 주입하는 경우, 이 부채널은 주입된 패킷의 Key Phase 값을 드러낼 수 있다. 키 갱신을 수신한 후, 엔드포인트는 6.3절에 설명된 대로 다음 수신 패킷 보호 키 집합을 생성하고 저장해야 SHOULD 한다. 키 갱신이 수신되기 전에 새 키를 생성함으로써, 패킷 수신이 Key Phase 값을 누출하는 타이밍 신호를 만들지 않게 된다.

이는 패킷 처리 중에 이 키 생성을 하지 않는 것에 의존하며, 엔드포인트가 수신을 위해 이전 키 위상, 현재 키 위상, 다음 키 위상에 대한 세 집합의 패킷 보호 키를 유지해야 할 수 있다. 엔드포인트는 대신 어느 시점에서든 두 집합의 수신 키만 보유하면 되도록, 이전 키를 폐기할 때까지 다음 수신 패킷 보호 키 생성을 지연하도록 선택할 수 있다.

9.6. 키 다양성

TLS를 사용할 때 TLS의 중앙 키 스케줄이 사용된다. TLS 핸드셰이크 메시지가 비밀 값 계산에 통합된 결과, QUIC 전송 매개변수 확장의 포함은 핸드셰이크 및 1-RTT 키가 TCP 위에서 TLS를 실행하는 서버에 의해 생성될 수 있는 것과 같지 않도록 보장한다. 교차 프로토콜 키 동기화 가능성을 피하기 위해, 키 분리를 개선하는 추가 조치가 제공된다.

QUIC 패킷 보호 키와 IV는 TLS의 동등한 키와 다른 레이블을 사용하여 파생된다.

이 분리를 보존하기 위해, QUIC의 새 버전은 패킷 보호 키와 IV, 그리고 헤더 보호 키의 키 파생을 위한 새 레이블을 정의해야 SHOULD 한다. 이 QUIC 버전은 문자열 "quic"을 사용한다. 다른 버전은 그 문자열 대신 버전별 레이블을 사용할 수 있다.

초기 비밀 값은 협상된 QUIC 버전에 특정한 키를 사용한다. 새 QUIC 버전은 초기 비밀 값 계산에 사용되는 새 salt 값을 정의해야 SHOULD 한다.

9.7. 무작위성

QUIC은 엔드포인트가 connection ID와 같은 프로토콜 값에 직접, 그리고 TLS를 통해 전이적으로 안전한 난수를 생성할 수 있는 것에 의존한다. 안전한 난수 생성에 대한 지침은 [RFC4086]을 보라.

10. IANA 고려사항

IANA는 "TLS ExtensionType Values" 레지스트리 [TLS-REGISTRIES]에서 quic_transport_parameters 확장 (8.2절에 정의됨)에 대해 57(또는 0x39)의 codepoint를 등록했다.

이 확장의 Recommended 열은 Yes로 표시된다. TLS 1.3 열에는 CH(ClientHello)와 EE(EncryptedExtensions)가 포함된다.

표 2: TLS ExtensionType Values 레지스트리 항목
확장 이름 TLS 1.3 권장 참조
57 quic_transport_parameters CH, EE Y 이 문서

11. 참고문헌

11.1. 규범적 참고문헌

[AEAD]
McGrew, D., "인증 암호화를 위한 인터페이스와 알고리즘", RFC 5116, DOI 10.17487/RFC5116, , <https://www.rfc-editor.org/info/rfc5116>.
[AES]
"고급 암호화 표준(AES)", National Institute of Standards and Technology report, DOI 10.6028/nist.fips.197, , <https://doi.org/10.6028/nist.fips.197>.
[ALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) 애플리케이션 계층 프로토콜 협상 확장", RFC 7301, DOI 10.17487/RFC7301, , <https://www.rfc-editor.org/info/rfc7301>.
[CHACHA]
Nir, Y. and A. Langley, "IETF 프로토콜을 위한 ChaCha20 및 Poly1305", RFC 8439, DOI 10.17487/RFC8439, , <https://www.rfc-editor.org/info/rfc8439>.
[HKDF]
Krawczyk, H. and P. Eronen, "HMAC 기반 Extract-and-Expand 키 파생 함수(HKDF)", RFC 5869, DOI 10.17487/RFC5869, , <https://www.rfc-editor.org/info/rfc5869>.
[QUIC-RECOVERY]
Iyengar, J., Ed. and I. Swett, Ed., "QUIC 손실 감지 및 혼잡 제어", RFC 9002, DOI 10.17487/RFC9002, , <https://www.rfc-editor.org/info/rfc9002>.
[QUIC-TRANSPORT]
Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: UDP 기반 다중화 및 보안 전송", RFC 9000, DOI 10.17487/RFC9000, , <https://www.rfc-editor.org/info/rfc9000>.
[RFC2119]
Bradner, S., "요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC4086]
Eastlake 3rd, D., Schiller, J., and S. Crocker, "보안을 위한 무작위성 요구사항", BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
[RFC8174]
Leiba, B., "RFC 2119 핵심 단어에서 대문자와 소문자의 모호성", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[SHA]
Dang, Q., "보안 해시 표준", National Institute of Standards and Technology report, DOI 10.6028/nist.fips.180-4, , <https://doi.org/10.6028/nist.fips.180-4>.
[TLS-REGISTRIES]
Salowey, J. and S. Turner, "TLS 및 DTLS를 위한 IANA 레지스트리 업데이트", RFC 8447, DOI 10.17487/RFC8447, , <https://www.rfc-editor.org/info/rfc8447>.
[TLS13]
Rescorla, E., "Transport Layer Security (TLS) 프로토콜 버전 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/info/rfc8446>.

11.2. 정보성 참고문헌

[AEBounds]
Luykx, A. and K. Paterson, "TLS에서 인증 암호화 사용 한계", , <https://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf>.
[ASCII]
Cerf, V., "네트워크 교환을 위한 ASCII 형식", STD 80, RFC 20, DOI 10.17487/RFC0020, , <https://www.rfc-editor.org/info/rfc20>.
[CCM-ANALYSIS]
Jonsson, J., "CTR + CBC-MAC의 보안에 관하여", Selected Areas in Cryptography, SAC 2002, Lecture Notes in Computer Science, vol 2595, pp. 76-93, DOI 10.1007/3-540-36492-7_7, , <https://doi.org/10.1007/3-540-36492-7_7>.
[COMPRESS]
Ghedini, A. and V. Vasiliev, "TLS 인증서 압축", RFC 8879, DOI 10.17487/RFC8879, , <https://www.rfc-editor.org/info/rfc8879>.
[GCM-MU]
Hoang, V., Tessaro, S., and A. Thiruvengadam, "GCM의 다중 사용자 보안 재검토: Nonce 무작위화에 대한 긴밀한 경계", CCS '18: Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pp. 1429-1440, DOI 10.1145/3243734.3243816, , <https://doi.org/10.1145/3243734.3243816>.
[HTTP-REPLAY]
Thomson, M., Nottingham, M., and W. Tarreau, "HTTP에서 Early Data 사용", RFC 8470, DOI 10.17487/RFC8470, , <https://www.rfc-editor.org/info/rfc8470>.
[HTTP2-TLS13]
Benjamin, D., "HTTP/2에서 TLS 1.3 사용", RFC 8740, DOI 10.17487/RFC8740, , <https://www.rfc-editor.org/info/rfc8740>.
[IMC]
Katz, J. and Y. Lindell, "현대 암호학 입문, 제2판", ISBN 978-1466570269, .
[NAN]
Bellare, M., Ng, R., and B. Tackmann, "Nonce는 관찰된다: AEAD 재검토", Advances in Cryptology - CRYPTO 2019, Lecture Notes in Computer Science, vol 11692, pp. 235-265, DOI 10.1007/978-3-030-26948-7_9, , <https://doi.org/10.1007/978-3-030-26948-7_9>.
[QUIC-HTTP]
Bishop, M., Ed., "Hypertext Transfer Protocol Version 3 (HTTP/3)", 진행 중인 작업, Internet-Draft, draft-ietf-quic-http-34, , <https://tools.ietf.org/html/draft-ietf-quic-http-34>.
[RFC2818]
Rescorla, E., "TLS 위의 HTTP", RFC 2818, DOI 10.17487/RFC2818, , <https://www.rfc-editor.org/info/rfc2818>.
[RFC5280]
Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "인터넷 X.509 공개 키 인프라 인증서 및 인증서 폐기 목록(CRL) 프로파일", RFC 5280, DOI 10.17487/RFC5280, , <https://www.rfc-editor.org/info/rfc5280>.
[ROBUST]
Fischlin, M., Günther, F., and C. Janson, "강건한 채널: QUIC 및 DTLS 1.3의 레코드 계층에서 신뢰할 수 없는 네트워크 처리", , <https://eprint.iacr.org/2020/718>.

부록 A. 샘플 패킷 보호

이 절은 구현을 점진적으로 검증할 수 있도록 패킷 보호의 예를 보여준다. 클라이언트와 서버 양쪽의 Initial 패킷 샘플과 Retry 패킷이 정의되어 있다. 이러한 패킷은 클라이언트가 선택한 8바이트 Destination Connection ID 0x8394c8f03e515708을 사용한다. 일부 중간 값도 포함되어 있다. 모든 값은 16진수로 표시된다.

A.1.

HKDF-Expand-Label 함수 실행 중 생성되는 레이블(즉, HkdfLabel.label)과 그 출력을 생성하기 위해 HKDF-Expand 함수에 제공되는 값의 일부는 다음과 같다.

client in:

00200f746c73313320636c69656e7420696e00

server in:

00200f746c7331332073657276657220696e00

quic key:

00100e746c7331332071756963206b657900

quic iv:

000c0d746c733133207175696320697600

quic hp:

00100d746c733133207175696320687000

초기 비밀 값은 공통이다.

initial_secret = HKDF-Extract(initial_salt, cid)
    = 7db5df06e7a69e432496adedb0085192
      3595221596ae2ae9fb8115c1e9ed0a44

클라이언트 패킷을 보호하기 위한 비밀 값은 다음과 같다.

client_initial_secret
    = HKDF-Expand-Label(initial_secret, "client in", "", 32)
    = c00cf151ca5be075ed0ebfb5c80323c4
      2d6b7db67881289af4008f1f6c357aea

key = HKDF-Expand-Label(client_initial_secret, "quic key", "", 16)
    = 1f369613dd76d5467730efcbe3b1a22d

iv  = HKDF-Expand-Label(client_initial_secret, "quic iv", "", 12)
    = fa044b2f42a3fd3b46fb255c

hp  = HKDF-Expand-Label(client_initial_secret, "quic hp", "", 16)
    = 9f50449e04a0e810283a1e9933adedd2

서버 패킷을 보호하기 위한 비밀 값은 다음과 같다.

server_initial_secret
    = HKDF-Expand-Label(initial_secret, "server in", "", 32)
    = 3c199828fd139efd216c155ad844cc81
      fb82fa8d7446fa7d78be803acdda951b

key = HKDF-Expand-Label(server_initial_secret, "quic key", "", 16)
    = cf3a5331653c364c88f0f379b6067e37

iv  = HKDF-Expand-Label(server_initial_secret, "quic iv", "", 12)
    = 0ac1493ca1905853b0bba03e

hp  = HKDF-Expand-Label(server_initial_secret, "quic hp", "", 16)
    = c206b8d9b9f0f37644430b490eeaa314

A.2. 클라이언트 Initial

클라이언트는 Initial 패킷을 보낸다. 이 패킷의 보호되지 않은 페이로드에는 다음 CRYPTO 프레임과, 1162바이트 페이로드를 만들기에 충분한 PADDING 프레임이 포함된다.

060040f1010000ed0303ebf8fa56f129 39b9584a3896472ec40bb863cfd3e868
04fe3a47f06a2b69484c000004130113 02010000c000000010000e00000b6578
616d706c652e636f6dff01000100000a 00080006001d00170018001000070005
04616c706e0005000501000000000033 00260024001d00209370b2c9caa47fba
baf4559fedba753de171fa71f50f1ce1 5d43e994ec74d748002b000302030400
0d0010000e0403050306030203080408 050806002d00020101001c0002400100
3900320408ffffffffffffffff050480 00ffff07048000ffff08011001048000
75300901100f088394c8f03e51570806 048000ffff

보호되지 않은 헤더는 1182바이트의 길이를 나타낸다. 즉 4바이트 패킷 번호, 1162바이트 프레임, 16바이트 인증 태그이다. 헤더는 연결 ID와 패킷 번호 2를 포함한다.

c300000001088394c8f03e5157080000449e00000002

페이로드를 보호하면 헤더 보호를 위해 샘플링되는 출력이 생성된다. 헤더가 4바이트 패킷 번호 인코딩을 사용하므로, 보호된 페이로드의 처음 16바이트가 샘플링되고 다음과 같이 헤더에 적용된다.

sample = d1b1c98dd7689fb8ec11d242b123dc9b

mask = AES-ECB(hp, sample)[0..4]
     = 437b9aec36

header[0] ^= mask[0] & 0x0f
     = c0
header[18..21] ^= mask[1..4]
     = 7b9aec34
header = c000000001088394c8f03e5157080000449e7b9aec34

그 결과 보호된 패킷은 다음과 같다.

c000000001088394c8f03e5157080000 449e7b9aec34d1b1c98dd7689fb8ec11
d242b123dc9bd8bab936b47d92ec356c 0bab7df5976d27cd449f63300099f399
1c260ec4c60d17b31f8429157bb35a12 82a643a8d2262cad67500cadb8e7378c
8eb7539ec4d4905fed1bee1fc8aafba1 7c750e2c7ace01e6005f80fcb7df6212
30c83711b39343fa028cea7f7fb5ff89 eac2308249a02252155e2347b63d58c5
457afd84d05dfffdb20392844ae81215 4682e9cf012f9021a6f0be17ddd0c208
4dce25ff9b06cde535d0f920a2db1bf3 62c23e596d11a4f5a6cf3948838a3aec
4e15daf8500a6ef69ec4e3feb6b1d98e 610ac8b7ec3faf6ad760b7bad1db4ba3
485e8a94dc250ae3fdb41ed15fb6a8e5 eba0fc3dd60bc8e30c5c4287e53805db
059ae0648db2f64264ed5e39be2e20d8 2df566da8dd5998ccabdae053060ae6c
7b4378e846d29f37ed7b4ea9ec5d82e7 961b7f25a9323851f681d582363aa5f8
9937f5a67258bf63ad6f1a0b1d96dbd4 faddfcefc5266ba6611722395c906556
be52afe3f565636ad1b17d508b73d874 3eeb524be22b3dcbc2c7468d54119c74
68449a13d8e3b95811a198f3491de3e7 fe942b330407abf82a4ed7c1b311663a
c69890f4157015853d91e923037c227a 33cdd5ec281ca3f79c44546b9d90ca00
f064c99e3dd97911d39fe9c5d0b23a22 9a234cb36186c4819e8b9c5927726632
291d6a418211cc2962e20fe47feb3edf 330f2c603a9d48c0fcb5699dbfe58964
25c5bac4aee82e57a85aaf4e2513e4f0 5796b07ba2ee47d80506f8d2c25e50fd
14de71e6c418559302f939b0e1abd576 f279c4b2e0feb85c1f28ff18f58891ff
ef132eef2fa09346aee33c28eb130ff2 8f5b766953334113211996d20011a198
e3fc433f9f2541010ae17c1bf202580f 6047472fb36857fe843b19f5984009dd
c324044e847a4f4a0ab34f719595de37 252d6235365e9b84392b061085349d73
203a4a13e96f5432ec0fd4a1ee65accd d5e3904df54c1da510b0ff20dcc0c77f
cb2c0e0eb605cb0504db87632cf3d8b4 dae6e705769d1de354270123cb11450e
fc60ac47683d7b8d0f811365565fd98c 4c8eb936bcab8d069fc33bd801b03ade
a2e1fbc5aa463d08ca19896d2bf59a07 1b851e6c239052172f296bfb5e724047
90a2181014f3b94a4e97d117b4381303 68cc39dbb2d198065ae3986547926cd2
162f40a29f0c3c8745c0f50fba3852e5 66d44575c29d39a03f0cda721984b6f4
40591f355e12d439ff150aab7613499d bd49adabc8676eef023b15b65bfc5ca0
6948109f23f350db82123535eb8a7433 bdabcb909271a6ecbcb58b936a88cd4e
8f2e6ff5800175f113253d8fa9ca8885 c2f552e657dc603f252e1a8e308f76f0
be79e2fb8f5d5fbbe2e30ecadd220723 c8c0aea8078cdfcb3868263ff8f09400
54da48781893a7e49ad5aff4af300cd8 04a6b6279ab3ff3afb64491c85194aab
760d58a606654f9f4400e8b38591356f bf6425aca26dc85244259ff2b19c41b9
f96f3ca9ec1dde434da7d2d392b905dd f3d1f9af93d1af5950bd493f5aa731b4
056df31bd267b6b90a079831aaf579be 0a39013137aac6d404f518cfd4684064
7e78bfe706ca4cf5e9c5453e9f7cfd2b 8b4c8d169a44e55c88d4a9a7f9474241
e221af44860018ab0856972e194cd934

A.3. 서버 Initial

서버는 응답으로 다음 페이로드를 보낸다. 여기에는 ACK 프레임, CRYPTO 프레임이 포함되며 PADDING 프레임은 없다.

02000000000600405a020000560303ee fce7f7b37ba1d1632e96677825ddf739
88cfc79825df566dc5430b9a045a1200 130100002e00330024001d00209d3c94
0d89690b84d08a60993c144eca684d10 81287c834d5311bcf32bb9da1a002b00
020304

서버의 헤더는 새 연결 ID와 패킷 번호 1에 대한 2바이트 패킷 번호 인코딩을 포함한다.

c1000000010008f067a5502a4262b50040750001

그 결과 보호 후에는 세 번째 보호된 바이트부터 헤더 보호 샘플을 취한다.

sample = 2cd0991cd25b0aac406a5816b6394100
mask   = 2ec0d8356a
header = cf000000010008f067a5502a4262b5004075c0d9

그런 다음 최종 보호된 패킷은 다음과 같다.

cf000000010008f067a5502a4262b500 4075c0d95a482cd0991cd25b0aac406a
5816b6394100f37a1c69797554780bb3 8cc5a99f5ede4cf73c3ec2493a1839b3
dbcba3f6ea46c5b7684df3548e7ddeb9 c3bf9c73cc3f3bded74b562bfb19fb84
022f8ef4cdd93795d77d06edbb7aaf2f 58891850abbdca3d20398c276456cbc4
2158407dd074ee

A.4. Retry

이는 부록 A.2의 Initial 패킷에 대한 응답으로 보내질 수 있는 Retry 패킷을 보여준다. 무결성 검사는 클라이언트가 선택한 연결 ID 값 0x8394c8f03e515708을 포함하지만, 그 값은 최종 Retry 패킷에는 포함되지 않는다.

ff000000010008f067a5502a4262b574 6f6b656e04a265ba2eff4d829058fb3f
0f2496ba

A.5. ChaCha20-Poly1305 짧은 헤더 패킷

이 예는 짧은 헤더를 가진 패킷을 보호하는 데 필요한 단계 중 일부를 보여준다. 이 예는 AEAD_CHACHA20_POLY1305를 사용한다.

이 예에서 TLS는 서버가 HKDF-Expand-Label을 사용하여 네 가지 값, 즉 키, IV, 헤더 보호 키, 그리고 키가 갱신된 후 사용될 비밀 값을 생성하는 application write secret을 생성한다(이 마지막 값은 이 예에서 더 이상 사용되지 않는다).

secret
    = 9ac312a7f877468ebe69422748ad00a1
      5443f18203a07d6060f688f30f21632b

key = HKDF-Expand-Label(secret, "quic key", "", 32)
    = c6d98ff3441c3fe1b2182094f69caa2e
      d4b716b65488960a7a984979fb23e1c8

iv  = HKDF-Expand-Label(secret, "quic iv", "", 12)
    = e0459b3474bdd0e44a41c144

hp  = HKDF-Expand-Label(secret, "quic hp", "", 32)
    = 25a282b9e82f06f21f488917a4fc8f1b
      73573685608597d0efcb076b0ab7a7a4

ku  = HKDF-Expand-Label(secret, "quic ku", "", 32)
    = 1223504755036d556342ee9361d25342
      1a826c9ecdf3c7148684b36b714881f9

다음은 빈 Destination Connection ID를 가진 최소 패킷을 보호하는 데 관련된 단계를 보여준다. 이 패킷은 단일 PING 프레임(즉, 페이로드가 단지 0x01임)을 포함하며 패킷 번호는 654360564이다. 이 예에서 길이 3의 패킷 번호를 사용하면(즉, 49140이 인코딩됨) 패킷 페이로드를 패딩할 필요가 없다. 패킷 번호가 더 적은 바이트로 인코딩되면 PADDING 프레임이 필요할 것이다.

pn                 = 654360564 (decimal)
nonce              = e0459b3474bdd0e46d417eb0
unprotected header = 4200bff4
payload plaintext  = 01
payload ciphertext = 655e5cd55c41f69080575d7999c25a5bfb

결과 암호문은 가능한 최소 크기이다. 헤더 보호를 위한 샘플을 생성하기 위해 1바이트를 건너뛴다.

sample = 5e5cd55c41f69080575d7999c25a5bfb
mask   = aefefe7d03
header = 4cfe4189

보호된 패킷은 가능한 가장 작은 패킷 크기인 21바이트이다.

packet = 4cfe4189655e5cd55c41f69080575d7999c25a5bfb

부록 B. AEAD 알고리즘 분석

이 절은 AEAD_AES_128_GCM, AEAD_AES_128_CCM, 그리고 AEAD_AES_256_GCM에 대한 AEAD 알고리즘 한계를 도출하는 데 사용된 분석을 문서화한다. 이어지는 분석은 곱셈(*), 나눗셈(/), 거듭제곱(^)을 위한 기호와, 우선순위를 설정하기 위한 괄호를 사용한다. 다음 기호들도 사용된다.

t:

인증 태그의 크기(비트 단위). 이러한 암호의 경우 t는 128이다.

n:

블록 함수의 크기(비트 단위). 이러한 암호의 경우 n은 128이다.

k:

키의 크기(비트 단위). AEAD_AES_128_GCM 및 AEAD_AES_128_CCM의 경우 128이고, AEAD_AES_256_GCM의 경우 256이다.

l:

각 패킷의 블록 수(아래 참조).

q:

엔드포인트가 생성하고 보호한 진짜 패킷 수. 이 값은 키를 갱신하기 전에 보호할 수 있는 패킷 수의 경계이다.

v:

엔드포인트가 수락할 위조 패킷 수. 이 값은 엔드포인트가 키를 갱신하기 전에 거부할 수 있는 위조 패킷 수의 경계이다.

o:

공격자가 수행한 오프라인 이상 암호 질의의 양.

이어지는 분석은 각 메시지를 생성하는 데 관련된 블록 연산 수의 계산에 의존한다. 이 분석은 최대 211(l = 27) 및 216(l = 212) 크기의 패킷에 대해 수행된다. 211의 크기는 일반적인 배포 패턴과 일치하는 한계로 예상되며, 216은 가능한 최대 QUIC 패킷 크기이다. 패킷 크기를 엄격히 제한하는 엔드포인트만 더 작은 패킷 크기를 사용하여 도출된 더 큰 기밀성 및 무결성 한계를 사용할 수 있다.

AEAD_AES_128_GCM 및 AEAD_AES_256_GCM의 경우, 메시지 길이(l)는 블록 단위 연관 데이터의 길이에 블록 단위 평문의 길이를 더한 것이다.

AEAD_AES_128_CCM의 경우, 블록 암호 연산의 총 수는 다음의 합이다. 블록 단위 연관 데이터의 길이, 블록 단위 암호문의 길이, 블록 단위 평문의 길이, 그리고 1. 이 분석에서는 이를 블록 단위 패킷 길이의 두 배 값으로 단순화한다 (즉, 211바이트로 제한된 패킷의 경우 2l = 28, 그렇지 않은 경우 2l = 213). 이 단순화는 패킷이 모든 연관 데이터와 암호문을 포함한다는 것에 기반한다. 이는 패킷당 연산 수를 1에서 3블록 과대평가하는 결과를 낳는다.

B.1. AEAD_AES_128_GCM 및 AEAD_AES_256_GCM 사용 한계 분석

[GCM-MU]는 TLS 1.3 및 QUIC에서 사용되는 AEAD_AES_128_GCM 및 AEAD_AES_256_GCM에 대한 구체적 경계를 명시한다. 이 절은 여러 단순화 가정을 사용하여 이 분석을 문서화한다.

  • 공격자가 위조 시도에 사용하는 암호문 블록 수는 v * l로 경계 지어진다. 이는 위조 시도 횟수에 각 패킷의 크기(블록 단위)를 곱한 것이다.
  • 공격자가 수행하는 오프라인 작업량은 분석의 다른 요소들을 지배하지 않는다.

[GCM-MU]의 경계는 [AEBounds]에서 사용된 것보다 더 엄격하고 더 완전하며, 이는 [TLS13]에 설명된 것보다 더 큰 한계를 허용한다.

B.1.1. 기밀성 한계

기밀성에 대해, [GCM-MU]의 정리 (4.3)은 nonce를 반복하지 않는 단일 사용자에 대해, 공격자가 얻는 실제 AEAD 알고리즘과 무작위 AEAD 알고리즘 사이의 구별 이점을 결정하는 지배적 항이 다음과 같음을 확립한다.

2 * (q * l)^2 / 2^n

목표 이점 2-57에 대해 이는 다음 관계를 낳는다.

q <= 2^35 / l

따라서 211바이트보다 큰 패킷을 보내지 않는 엔드포인트는 공격자가 목표인 2-57보다 더 유의미한 이점을 얻지 않도록 하려면 단일 연결에서 228개보다 많은 패킷을 보호할 수 없다. 패킷 크기가 216까지 커지는 것을 허용하는 엔드포인트의 한계는 대신 223이다.

B.1.2. 무결성 한계

무결성에 대해, [GCM-MU]의 정리 (4.3)은 공격자가 패킷을 성공적으로 위조하는 데 얻는 이점이 다음 이하임을 확립한다.

(1 / 2^(8 * n)) + ((2 * v) / 2^(2 * n))
        + ((2 * o * v) / 2^(k + n)) + (n * (v + (v * l)) / 2^k)

목표는 이 이점을 2-57로 제한하는 것이다. AEAD_AES_128_GCM의 경우, 이 부등식의 네 번째 항이 나머지를 지배하므로 결과에 큰 영향을 주지 않고 다른 항들을 제거할 수 있다. 이는 다음 근사를 생성한다.

v <= 2^64 / l

211바이트보다 큰 패킷에서 보호 제거를 시도하지 않는 엔드포인트는 최대 257개의 패킷에서 보호 제거를 시도할 수 있다. 처리되는 패킷의 크기를 제한하지 않는 엔드포인트는 최대 252개의 패킷에서 보호 제거를 시도할 수 있다.

AEAD_AES_256_GCM의 경우 같은 항이 지배하지만, 더 큰 k 값은 다음 근사를 생성한다.

v <= 2^192 / l

이는 AEAD_AES_128_GCM의 한계보다 상당히 크다. 그러나 이 문서는 어느 한계도 충분히 크므로 두 함수 모두에 같은 한계를 적용할 것을 권장한다.

B.2. AEAD_AES_128_CCM 사용 한계 분석

TLS [TLS13][AEBounds]는 AEAD_AES_128_CCM에 대한 사용 한계를 명시하지 않는다. 그러나 QUIC과 함께 사용되는 모든 AEAD는 기밀성과 무결성이 모두 보존되도록 보장하는 사용 한계를 요구한다. 이 절은 그 분석을 문서화한다.

[CCM-ANALYSIS]가 이 분석의 기반으로 사용된다. 그 분석의 결과는 [TLS13]에서 선택된 것에 기반한 사용 한계를 도출하는 데 사용된다.

기밀성에 대해, [CCM-ANALYSIS]의 정리 2는 공격자가 이상적 의사난수 순열(PRP)에 대해 얻는 구별 이점이 다음 이하임을 확립한다.

(2l * q)^2 / 2^n

[CCM-ANALYSIS]의 정리 1의 무결성 한계는 같은 메시지 수에 대해 공격자에게 엄격히 더 높은 이점을 제공한다. 기밀성 이점과 무결성 이점의 목표가 같으므로, 정리 1만 고려하면 된다.

정리 1은 공격자가 이상적 PRP에 대해 얻는 이점이 다음 이하임을 확립한다.

v / 2^t + (2l * (v + q))^2 / 2^n

tn이 모두 128이므로, 첫 번째 항은 두 번째 항에 비해 무시할 수 있으며, 따라서 결과에 큰 영향을 주지 않고 그 항을 제거할 수 있다.

이는 암호화와 복호화 시도를 모두 결합하면서 기밀성에 대한 정리만으로 생성된 것과 같은 한계를 가지는 관계를 생성한다. 목표 이점 2-57에 대해 이는 다음과 같은 결과를 낳는다.

v + q <= 2^34.5 / l

q = v로 설정하면, 기밀성과 무결성 한계 모두에 대한 값을 생성할 수 있다. 따라서 패킷을 211바이트로 제한하는 엔드포인트는 기밀성과 무결성 한계가 모두 226.5개 패킷이다. 패킷 크기를 제한하지 않는 엔드포인트의 한계는 221.5이다.

기여자

IETF QUIC Working Group은 많은 사람들로부터 엄청난 지원을 받았다. 다음 사람들은 이 문서에 실질적인 기여를 제공했다.

저자 주소

Martin Thomson (편집자)
Mozilla
Sean Turner (편집자)
sn3rd