인터넷 엔지니어링 태스크 포스 (IETF) E. Rescorla
의견 요청서: 8446 Mozilla
폐기: 5077, 5246, 6961 2018년 8월
갱신: 5705, 6066
범주: 표준 트랙
ISSN: 2070-1721
전송 계층 보안(TLS) 프로토콜 버전 1.3
초록
이 문서는 전송 계층 보안(TLS) 프로토콜의 버전 1.3을
명세한다. TLS는 클라이언트/서버 애플리케이션이 도청,
변조 및 메시지 위조를 방지하도록 설계된 방식으로
인터넷을 통해 통신할 수 있게 한다.
이 문서는 RFC 5705와 6066을 갱신하고, RFC 5077,
5246 및 6961을 폐기한다. 또한 이 문서는 TLS 1.2
구현에 대한 새로운 요구사항도 명세한다.
이 메모의 상태
이 문서는 인터넷 표준 트랙 문서이다.
이 문서는 인터넷 엔지니어링 태스크 포스(IETF)의 산출물이다.
이는 IETF 커뮤니티의 합의를 나타낸다. 공개 검토를 거쳤으며
인터넷 엔지니어링 운영 그룹(IESG)에 의해 출판 승인을 받았다.
인터넷 표준에 대한 자세한 정보는 RFC 7841의 섹션 2에서
확인할 수 있다.
이 문서의 현재 상태, 모든 정오표 및 이에 대한 피드백 제공
방법에 관한 정보는
https://www.rfc-editor.org/info/rfc8446에서 얻을 수 있다.
Rescorla 표준 트랙 [1페이지]
RFC 8446 TLS 2018년 8월
Copyright Notice
Copyright (c) 2018 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
This document may contain material from IETF Documents or IETF
Contributions published or made publicly available before November
10, 2008. The person(s) controlling the copyright in some of this
material may not have granted the IETF Trust the right to allow
modifications of such material outside the IETF Standards Process.
Without obtaining an adequate license from the person(s) controlling
the copyright in such materials, this document may not be modified
outside the IETF Standards Process, and derivative works of it may
not be created outside the IETF Standards Process, except to format
it for publication as an RFC or to translate it into languages other
than English.
Rescorla 표준 트랙 [2페이지]
RFC 8446 TLS 2018년 8월
목차
1. 소개 .........................................................6
1.1. 규약 및 용어 .............................................7
1.2. TLS 1.2와의 주요 차이점 .................................8
1.3. TLS 1.2에 영향을 주는 갱신 ..............................9
2. 프로토콜 개요 ...............................................10
2.1. 잘못된 DHE 공유값 ......................................14
2.2. 재개 및 사전 공유 키(PSK) ..............................15
2.3. 0-RTT 데이터 ............................................17
3. 표현 언어 ..................................................19
3.1. 기본 블록 크기 .........................................19
3.2. 기타 ...................................................20
3.3. 숫자 ...................................................20
3.4. 벡터 ...................................................20
3.5. 열거형 .................................................21
3.6. 구성 타입 ..............................................22
3.7. 상수 ...................................................23
3.8. 변형 ...................................................23
4. 핸드셰이크 프로토콜 ........................................24
4.1. 키 교환 메시지 .........................................25
4.1.1. 암호학적 협상 .................................26
4.1.2. Client Hello ....................................27
4.1.3. Server Hello ....................................31
4.1.4. Hello Retry Request .............................33
4.2. 확장 ...................................................35
4.2.1. 지원 버전 ......................................39
4.2.2. 쿠키 ............................................40
4.2.3. 서명 알고리즘 ..................................41
4.2.4. 인증서 기관 ....................................45
4.2.5. OID 필터 ........................................45
4.2.6. 핸드셰이크 후 클라이언트 인증 .................47
4.2.7. 지원 그룹 ......................................47
4.2.8. 키 공유 ........................................48
4.2.9. 사전 공유 키 교환 모드 .........................51
4.2.10. 조기 데이터 표시 ..............................52
4.2.11. 사전 공유 키 확장 .............................55
4.3. 서버 매개변수 ..........................................59
4.3.1. 암호화된 확장 .................................60
4.3.2. 인증서 요청 ...................................60
4.4. 인증 메시지 ............................................61
4.4.1. 전사 해시 ......................................63
4.4.2. 인증서 .........................................64
4.4.3. 인증서 검증 ...................................69
4.4.4. Finished ........................................71
4.5. 조기 데이터의 종료 ....................................72
Rescorla 표준 트랙 [3페이지]
RFC 8446 TLS 2018년 8월
4.6. 핸드셰이크 후 메시지 ...................................73
4.6.1. 새 세션 티켓 메시지 ............................73
4.6.2. 핸드셰이크 후 인증 .............................75
4.6.3. 키 및 초기화 벡터 갱신 .........................76
5. 레코드 프로토콜 .............................................77
5.1. 레코드 계층 ............................................78
5.2. 레코드 페이로드 보호 .................................80
5.3. 레코드별 논스 .........................................82
5.4. 레코드 패딩 ............................................83
5.5. 키 사용 제한 ...........................................84
6. 경고 프로토콜 ..............................................85
6.1. 종료 경고 ..............................................87
6.2. 오류 경고 ..............................................88
7. 암호학적 계산 ..............................................90
7.1. 키 스케줄 ..............................................91
7.2. 트래픽 시크릿 갱신 ....................................94
7.3. 트래픽 키 계산 ........................................95
7.4. (EC)DHE 공유 시크릿 계산 ..............................95
7.4.1. 유한체 Diffie-Hellman ..........................95
7.4.2. 타원곡선 Diffie-Hellman ........................96
7.5. 익스포터 ...............................................97
8. 0-RTT 및 재생 방지 .........................................98
8.1. 일회용 티켓 ............................................99
8.2. Client Hello 기록 ......................................99
8.3. 신선도 검사 ...........................................101
9. 준수 요구사항 .............................................102
9.1. 필수 구현 암호 스위트 .................................102
9.2. 필수 구현 확장 ........................................103
9.3. 프로토콜 불변조건 .....................................104
10. 보안 고려사항 ............................................106
11. IANA 고려사항 ............................................106
12. 참고문헌 .................................................109
12.1. 규범적 참고문헌 .....................................109
12.2. 정보성 참고문헌 .....................................112
부록 A. 상태 기계 ..............................................120
A.1. 클라이언트 .............................................120
A.2. 서버 ...................................................121
부록 B. 프로토콜 데이터 구조와 상수 값 .........................122
B.1. 레코드 계층 ............................................122
B.2. 경고 메시지 ............................................123
B.3. 핸드셰이크 프로토콜 ...................................124
B.3.1. 키 교환 메시지 .....................................125
B.3.2. 서버 매개변수 메시지 ..............................131
B.3.3. 인증 메시지 ........................................132
B.3.4. 티켓 설정 ..........................................132
B.3.5. 키 갱신 ............................................133
B.4. 암호 스위트 ............................................133
Rescorla 표준 트랙 [4페이지]
RFC 8446 TLS 2018년 8월
부록 C. 구현 참고사항 ..........................................134
C.1. 난수 생성 및 시딩 ......................................134
C.2. 인증서와 인증 ..........................................135
C.3. 구현상의 함정 ..........................................135
C.4. 클라이언트 추적 방지 ..................................137
C.5. 미인증 동작 ............................................137
부록 D. 하위 호환성 ............................................138
D.1. 오래된 서버와의 협상 ..................................139
D.2. 오래된 클라이언트와의 협상 ............................139
D.3. 0-RTT 하위 호환성 ......................................140
D.4. 미들박스 호환성 모드 ..................................140
D.5. 하위 호환성과 관련된 보안 제한 .........................141
부록 E. 보안 속성 개요 .........................................142
E.1. 핸드셰이크 .............................................142
E.1.1. 키 파생 및 HKDF ....................................145
E.1.2. 클라이언트 인증 ....................................146
E.1.3. 0-RTT ...............................................146
E.1.4. 익스포터 독립성 ....................................146
E.1.5. 침해 후 보안 .......................................146
E.1.6. 외부 참고문헌 ......................................147
E.2. 레코드 계층 ............................................147
E.2.1. 외부 참고문헌 ......................................148
E.3. 트래픽 분석 ............................................148
E.4. 부채널 공격 ............................................149
E.5. 0-RTT에 대한 재생 공격 ................................150
E.5.1. 재생과 익스포터 ....................................151
E.6. PSK 식별자 노출 ........................................152
E.7. PSK 공유 ...............................................152
E.8. 정적 RSA에 대한 공격 ..................................152
기여자 ........................................................153
저자 주소 .....................................................160
Rescorla 표준 트랙 [5페이지]
RFC 8446 TLS 2018년 8월
1. 소개
TLS의 주된 목표는 통신하는 두 피어 사이에 보안 채널을
제공하는 것이다. 기반 전송에 대한 유일한 요구사항은 신뢰성
있고 순서가 보장되는 데이터 스트림이다. 구체적으로, 보안
채널은 다음 속성을 제공해야 한다.
- 인증: 채널의 서버 측은 항상 인증된다. 클라이언트 측은
선택적으로 인증된다. 인증은 비대칭 암호학(예: RSA
[RSA], 타원곡선 디지털 서명 알고리즘(ECDSA)
[ECDSA], 또는 Edwards-Curve 디지털 서명 알고리즘(EdDSA)
[RFC8032])이나 대칭 사전 공유 키(PSK)를 통해 일어날 수 있다.
- 기밀성: 설정 후 채널을 통해 전송되는 데이터는 엔드포인트에만
보인다. TLS는 자신이 전송하는 데이터의 길이를 숨기지 않지만,
엔드포인트는 길이를 흐리게 하고 트래픽 분석 기법에 대한
보호를 개선하기 위해 TLS 레코드를 패딩할 수 있다.
- 무결성: 설정 후 채널을 통해 전송되는 데이터는 공격자가
탐지되지 않은 채 수정할 수 없다.
이러한 속성은 [RFC3552]에 설명된 것처럼 네트워크를 완전히 제어하는
공격자가 있는 상황에서도 참이어야 한다. 관련 보안 속성에 대한
더 완전한 설명은 부록 E를 참조하라.
TLS는 두 가지 주된 구성요소로 이루어진다.
- 통신 당사자를 인증하고, 암호학적 모드와 매개변수를 협상하며,
공유 키 자료를 설정하는 핸드셰이크 프로토콜(섹션 4).
핸드셰이크 프로토콜은 변조에 저항하도록 설계되었다. 능동
공격자는 연결이 공격받고 있지 않았다면 피어들이 협상했을
매개변수와 다른 매개변수를 협상하도록 강제할 수 없어야 한다.
- 핸드셰이크 프로토콜이 설정한 매개변수를 사용하여 통신하는
피어 사이의 트래픽을 보호하는 레코드 프로토콜(섹션 5).
레코드 프로토콜은 트래픽을 일련의 레코드로 나누며, 각
레코드는 트래픽 키를 사용하여 독립적으로 보호된다.
Rescorla 표준 트랙 [6페이지]
RFC 8446 TLS 2018년 8월
TLS는 애플리케이션 프로토콜에 독립적이다. 상위 수준 프로토콜은
TLS 위에 투명하게 계층화될 수 있다. 그러나 TLS 표준은
프로토콜이 TLS로 보안을 추가하는 방법을 명세하지 않는다.
TLS 핸드셰이크를 시작하는 방법과 교환된 인증 인증서를 해석하는
방법은 TLS 위에서 실행되는 프로토콜의 설계자와 구현자의 판단에
맡겨진다.
이 문서는 TLS 버전 1.3을 정의한다. TLS 1.3은 이전 버전과
직접 호환되지는 않지만, 모든 TLS 버전은 클라이언트와 서버가
양쪽 피어가 모두 지원하는 공통 버전을 상호 운용 가능하게
협상할 수 있게 하는 버전 지정 메커니즘을 포함한다.
이 문서는 버전 1.2 [RFC5246]를 포함한 이전 TLS 버전들을
대체하고 폐기한다. 또한 [RFC5077]에 정의된 TLS 티켓
메커니즘을 폐기하고 이를 섹션 2.2에 정의된 메커니즘으로
대체한다. TLS 1.3은 키가 파생되는 방식을 변경하므로,
섹션 7.5에 설명된 대로 [RFC5705]를 갱신한다. 또한 Online
Certificate Status Protocol(OCSP) 메시지가 전달되는 방식을
변경하므로, 섹션 4.4.2.1에 설명된 대로 [RFC6066]을
갱신하고 [RFC6961]을 폐기한다.
1.1. 규약 및 용어
이 문서의 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL",
"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",
"NOT RECOMMENDED", "MAY", "OPTIONAL"은 여기에 보인 것처럼
모두 대문자로 나타날 때, 그리고 오직 그때에만
BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석된다.
다음 용어가 사용된다.
client: TLS 연결을 시작하는 엔드포인트.
connection: 두 엔드포인트 사이의 전송 계층 연결.
endpoint: 연결의 클라이언트 또는 서버 중 하나.
handshake: TLS 내에서 이후 상호작용의 매개변수를 설정하는,
클라이언트와 서버 사이의 초기 협상.
peer: 엔드포인트. 특정 엔드포인트를 논의할 때 "peer"는
논의의 주된 대상이 아닌 엔드포인트를 가리킨다.
Rescorla 표준 트랙 [7페이지]
RFC 8446 TLS 2018년 8월
receiver: 레코드를 수신하는 엔드포인트.
sender: 레코드를 전송하는 엔드포인트.
server: TLS 연결을 시작하지 않은 엔드포인트.
1.2. TLS 1.2와의 주요 차이점
다음은 TLS 1.2와 TLS 1.3 사이의 주요 기능적 차이점 목록이다.
이 목록은 완전한 것을 의도하지 않으며, 많은 사소한 차이점이
있다.
- 지원되는 대칭 암호화 알고리즘 목록에서 레거시로 간주되는
모든 알고리즘이 제거되었다. 남은 것은 모두 AEAD
(Authenticated Encryption with Associated Data) 알고리즘이다.
암호 스위트 개념은 인증 및 키 교환 메커니즘을 레코드 보호
알고리즘(비밀 키 길이 포함) 및 키 파생 함수와 핸드셰이크
메시지 인증 코드(MAC) 모두에 사용할 해시와 분리하도록
변경되었다.
- 일부 애플리케이션 데이터에 대해 연결 설정 시 왕복을 절약하는
zero round-trip time(0-RTT) 모드가 추가되었으며, 그 대가로
특정 보안 속성이 약화된다.
- 정적 RSA 및 Diffie-Hellman 암호 스위트가 제거되었다. 이제
모든 공개 키 기반 키 교환 메커니즘은 순방향 비밀성을
제공한다.
- ServerHello 이후의 모든 핸드셰이크 메시지는 이제 암호화된다.
새로 도입된 EncryptedExtensions 메시지는 이전에 ServerHello에서
평문으로 전송되던 여러 확장도 기밀성 보호를 누릴 수 있게
한다.
- 키 파생 함수가 재설계되었다. 새 설계는 개선된 키 분리 속성
때문에 암호학자가 더 쉽게 분석할 수 있다. HMAC 기반
Extract-and-Expand Key Derivation Function(HKDF)이 기초
프리미티브로 사용된다.
- 핸드셰이크 상태 기계는 더 일관되도록, 그리고
ChangeCipherSpec과 같은 불필요한 메시지를 제거하도록
상당히 재구성되었다(미들박스 호환성을 위해 필요할 때 제외).
- 타원곡선 알고리즘은 이제 기본 명세에 포함되며, EdDSA와 같은
새로운 서명 알고리즘도 포함된다. TLS 1.3은 각 곡선에 대해
단일 포인트 형식을 사용하는 대신 포인트 형식 협상을 제거했다.
Rescorla 표준 트랙 [8페이지]
RFC 8446 TLS 2018년 8월
- RSA 패딩을 RSA Probabilistic Signature Scheme(RSASSA-PSS)을
사용하도록 변경하고, 압축, Digital Signature Algorithm(DSA),
사용자 지정 Ephemeral Diffie-Hellman(DHE) 그룹을 제거하는 등
다른 암호학적 개선도 이루어졌다.
- TLS 1.2 버전 협상 메커니즘은 확장 내 버전 목록을 선호하는
방식으로 폐기 예정 처리되었다. 이는 버전 협상을 잘못 구현한
기존 서버와의 호환성을 높인다.
- 서버 측 상태가 있거나 없는 세션 재개 및 이전 TLS 버전의
PSK 기반 암호 스위트는 단일의 새로운 PSK 교환으로 대체되었다.
- 참고문헌은 적절한 경우 RFC의 갱신된 버전을 가리키도록
갱신되었다(예: RFC 3280이 아니라 RFC 5280).
1.3. TLS 1.2에 영향을 주는 갱신
이 문서는 TLS 1.3도 지원하지 않는 구현을 포함하여, TLS 1.2
구현에 선택적으로 영향을 주는 몇 가지 변경을 정의한다.
- 버전 다운그레이드 보호 메커니즘은 섹션 4.1.3에 설명되어
있다.
- RSASSA-PSS 서명 방식은 섹션 4.2.3에 정의되어 있다.
- ClientHello의 legacy_version 필드보다 우선하여 사용할 TLS
버전을 협상하기 위해 "supported_versions" ClientHello 확장을
사용할 수 있다.
- "signature_algorithms_cert" 확장은 클라이언트가 X.509
인증서에서 검증할 수 있는 서명 알고리즘을 나타낼 수 있게
한다.
또한 이 문서는 이전 TLS 버전에 대한 일부 준수 요구사항을
명확히 한다. 섹션 9.3을 참조하라.
Rescorla 표준 트랙 [9페이지]
RFC 8446 TLS 2018년 8월
2. 프로토콜 개요
보안 채널에서 사용하는 암호학적 매개변수는 TLS 핸드셰이크
프로토콜에 의해 생성된다. TLS의 이 하위 프로토콜은 클라이언트와
서버가 처음 서로 통신할 때 사용된다. 핸드셰이크 프로토콜은
피어가 프로토콜 버전을 협상하고, 암호학적 알고리즘을 선택하며,
선택적으로 서로를 인증하고, 공유 비밀 키 자료를 설정할 수 있게
한다. 핸드셰이크가 완료되면 피어는 설정된 키를 사용하여
애플리케이션 계층 트래픽을 보호한다.
핸드셰이크 실패나 다른 프로토콜 오류는 연결 종료를 유발하며,
선택적으로 그 전에 경고 메시지(섹션 6)가 올 수 있다.
TLS는 세 가지 기본 키 교환 모드를 지원한다.
- (EC)DHE(유한체 또는 타원곡선을 통한 Diffie-Hellman)
- PSK-only
- (EC)DHE를 수반한 PSK
Rescorla 표준 트랙 [10페이지]
RFC 8446 TLS 2018년 8월
아래 그림 1은 기본 전체 TLS 핸드셰이크를 보여준다.
Client Server
Key ^ ClientHello
Exch | + key_share*
| + signature_algorithms*
| + psk_key_exchange_modes*
v + pre_shared_key* -------->
ServerHello ^ Key
+ key_share* | Exch
+ pre_shared_key* v
{EncryptedExtensions} ^ Server
{CertificateRequest*} v Params
{Certificate*} ^
{CertificateVerify*} | Auth
{Finished} v
<-------- [Application Data*]
^ {Certificate*}
Auth | {CertificateVerify*}
v {Finished} -------->
[Application Data] <-------> [Application Data]
+ 앞서 표시된 메시지에서 전송되는 주목할 만한
확장을 나타낸다.
* 항상 전송되지는 않는 선택적 또는 상황 의존적
메시지/확장을 나타낸다.
{} [sender]_handshake_traffic_secret에서 파생된
키를 사용하여 보호되는 메시지를 나타낸다.
[] [sender]_application_traffic_secret_N에서 파생된
키를 사용하여 보호되는 메시지를 나타낸다.
그림 1: 전체 TLS 핸드셰이크의 메시지 흐름
핸드셰이크는 세 단계(위 다이어그램에 표시됨)로 생각할 수 있다.
- 키 교환: 공유 키 자료를 설정하고 암호학적 매개변수를
선택한다. 이 단계 이후의 모든 것은 암호화된다.
- 서버 매개변수: 다른 핸드셰이크 매개변수(클라이언트 인증
여부, 애플리케이션 계층 프로토콜 지원 등)를 설정한다.
Rescorla 표준 트랙 [11페이지]
RFC 8446 TLS 2018년 8월
- 인증: 서버(및 선택적으로 클라이언트)를 인증하고, 키 확인 및
핸드셰이크 무결성을 제공한다.
키 교환 단계에서 클라이언트는 ClientHello(섹션 4.1.2)
메시지를 전송한다. 이 메시지는 임의 논스(ClientHello.random),
제공하는 프로토콜 버전, 대칭 암호/HKDF 해시 쌍 목록, Diffie-
Hellman 키 공유 집합("key_share"(섹션 4.2.8) 확장), 사전 공유
키 레이블 집합("pre_shared_key"(섹션 4.2.11) 확장), 또는 둘
모두, 그리고 잠재적으로 추가 확장을 포함한다. 미들박스 호환성을
위해 추가 필드 및/또는 메시지가 있을 수도 있다.
서버는 ClientHello를 처리하고 연결에 적절한 암호학적 매개변수를
결정한다. 그런 다음 협상된 연결 매개변수를 나타내는 자체
ServerHello(섹션 4.1.3)로 응답한다. ClientHello와
ServerHello의 조합이 공유 키를 결정한다. (EC)DHE 키 설정이
사용 중이면 ServerHello에는 서버의 임시 Diffie-Hellman 공유값이
포함된 "key_share" 확장이 들어간다. 서버의 공유값은 클라이언트의
공유값 중 하나와 같은 그룹에 있어야 한다(MUST). PSK 키 설정이
사용 중이면 ServerHello에는 클라이언트가 제공한 PSK 중 어느
것이 선택되었는지를 나타내는 "pre_shared_key" 확장이 들어간다.
구현은 (EC)DHE와 PSK를 함께 사용할 수 있으며, 이 경우 두 확장이
모두 제공된다는 점에 유의하라.
그런 다음 서버는 서버 매개변수를 설정하기 위해 두 메시지를
전송한다.
EncryptedExtensions: 암호학적 매개변수를 결정하는 데 필요하지
않은 ClientHello 확장에 대한 응답. 단, 개별 인증서에 특정한
확장은 제외한다. [섹션 4.3.1]
CertificateRequest: 인증서 기반 클라이언트 인증이 필요한 경우,
해당 인증서에 대해 원하는 매개변수. 클라이언트 인증이 필요하지
않으면 이 메시지는 생략된다. [섹션 4.3.2]
Rescorla 표준 트랙 [12페이지]
RFC 8446 TLS 2018년 8월
마지막으로 클라이언트와 서버는 인증 메시지를 교환한다. TLS는
인증서 기반 인증이 필요할 때마다 동일한 메시지 집합을 사용한다.
(PSK 기반 인증은 키 교환의 부수 효과로 일어난다.) 구체적으로는
다음과 같다.
Certificate: 엔드포인트의 인증서 및 인증서별 확장. 서버가
인증서로 인증하지 않는 경우, 그리고 서버가 CertificateRequest를
보내지 않아 클라이언트가 인증서로 인증해서는 안 됨을 나타낸
경우 클라이언트에 의해 이 메시지는 생략된다. 원시 공개 키
[RFC7250]나 캐시된 정보 확장 [RFC7924]을 사용 중인 경우,
이 메시지는 인증서를 포함하지 않고 서버의 장기 키에 대응하는
다른 값을 포함한다는 점에 유의하라. [섹션 4.4.2]
CertificateVerify: Certificate 메시지의 공개 키에 대응하는
개인 키를 사용하여 전체 핸드셰이크에 대해 생성한 서명. 이
메시지는 엔드포인트가 인증서로 인증하지 않는 경우 생략된다.
[섹션 4.4.3]
Finished: 전체 핸드셰이크에 대한 MAC(Message Authentication
Code). 이 메시지는 키 확인을 제공하고, 엔드포인트의 신원을
교환된 키에 결속하며, PSK 모드에서는 핸드셰이크도 인증한다.
[섹션 4.4.4]
서버의 메시지를 수신하면, 클라이언트는 자신의 인증 메시지,
즉 요청된 경우 Certificate와 CertificateVerify, 그리고 Finished로
응답한다.
이 시점에서 핸드셰이크는 완료되며, 클라이언트와 서버는 인증된
암호화를 통해 보호되는 애플리케이션 계층 데이터를 교환하기 위해
레코드 계층에 필요한 키 자료를 파생한다. 섹션 2.3에 명시된
경우를 제외하고, Application Data는 Finished 메시지를 보내기
전에 전송되어서는 안 된다(MUST NOT). 서버는 클라이언트의 인증
메시지를 받기 전에 Application Data를 보낼 수 있지만, 그 시점에
전송되는 모든 데이터는 당연히 인증되지 않은 피어에게 보내지는
것이라는 점에 유의하라.
Rescorla 표준 트랙 [13페이지]
RFC 8446 TLS 2018년 8월
2.1. 잘못된 DHE 공유값
클라이언트가 충분한 "key_share" 확장을 제공하지 않은 경우
(예: 서버가 수용할 수 없거나 지원하지 않는 DHE 또는 ECDHE
그룹만 포함하는 경우), 서버는 HelloRetryRequest로 불일치를
수정하고 클라이언트는 그림 2에 보인 것처럼 적절한 "key_share"
확장을 사용하여 핸드셰이크를 다시 시작해야 한다. 공통 암호학적
매개변수를 협상할 수 없는 경우, 서버는 적절한 경고와 함께
핸드셰이크를 중단해야 한다(MUST).
Client Server
ClientHello
+ key_share -------->
HelloRetryRequest
<-------- + key_share
ClientHello
+ key_share -------->
ServerHello
+ key_share
{EncryptedExtensions}
{CertificateRequest*}
{Certificate*}
{CertificateVerify*}
{Finished}
<-------- [Application Data*]
{Certificate*}
{CertificateVerify*}
{Finished} -------->
[Application Data] <-------> [Application Data]
그림 2: 매개변수가 일치하지 않는 전체 핸드셰이크의
메시지 흐름
참고: 핸드셰이크 전사에는 초기 ClientHello/HelloRetryRequest
교환이 포함된다. 새 ClientHello로 재설정되지 않는다.
TLS는 또한 다음 섹션에 설명된 것처럼 기본 핸드셰이크의 여러
최적화된 변형을 허용한다.
Rescorla 표준 트랙 [14페이지]
RFC 8446 TLS 2018년 8월
2.2. 재개 및 사전 공유 키(PSK)
TLS PSK는 대역 외에서 설정될 수 있지만, PSK는 이전 연결에서
설정된 뒤 새 연결을 설정하는 데 사용될 수도 있다("세션 재개"
또는 PSK로 "재개"). 핸드셰이크가 완료되면 서버는 초기 핸드셰이크
에서 파생된 고유 키에 대응하는 PSK 식별자를 클라이언트에 보낼
수 있다(섹션 4.6.1 참조). 그러면 클라이언트는 이후
핸드셰이크에서 해당 PSK 식별자를 사용하여 연관된 PSK 사용을
협상할 수 있다. 서버가 PSK를 수락하면 새 연결의 보안 컨텍스트는
원래 연결에 암호학적으로 결속되며, 초기 핸드셰이크에서 파생된
키가 전체 핸드셰이크 대신 암호학적 상태를 부트스트랩하는 데
사용된다. TLS 1.2 이하에서는 이 기능이 "session IDs"와
"session tickets" [RFC5077]로 제공되었다. 두 메커니즘은 TLS 1.3에서
폐기된다.
PSK는 공유 키와 결합하여 순방향 비밀성을 제공하기 위해 (EC)DHE
키 교환과 함께 사용할 수 있거나, 애플리케이션 데이터에 대한
순방향 비밀성을 잃는 대가로 단독으로 사용할 수 있다.
Rescorla 표준 트랙 [15페이지]
RFC 8446 TLS 2018년 8월
그림 3은 첫 번째 핸드셰이크가 PSK를 설정하고 두 번째 핸드셰이크가
이를 사용하는 한 쌍의 핸드셰이크를 보여준다.
Client Server
Initial Handshake:
ClientHello
+ key_share -------->
ServerHello
+ key_share
{EncryptedExtensions}
{CertificateRequest*}
{Certificate*}
{CertificateVerify*}
{Finished}
<-------- [Application Data*]
{Certificate*}
{CertificateVerify*}
{Finished} -------->
<-------- [NewSessionTicket]
[Application Data] <-------> [Application Data]
Subsequent Handshake:
ClientHello
+ key_share*
+ pre_shared_key -------->
ServerHello
+ pre_shared_key
+ key_share*
{EncryptedExtensions}
{Finished}
<-------- [Application Data*]
{Finished} -------->
[Application Data] <-------> [Application Data]
그림 3: 재개 및 PSK의 메시지 흐름
서버가 PSK를 통해 인증하므로 Certificate 또는 CertificateVerify
메시지를 보내지 않는다. 클라이언트가 PSK를 통한 재개를 제공할
때, 필요한 경우 서버가 재개를 거절하고 전체 핸드셰이크로
폴백할 수 있도록 "key_share" 확장도 제공해야 한다(SHOULD).
서버는 PSK 키 설정 사용을 협상하기 위해 "pre_shared_key" 확장으로
응답하며, 여기 보인 것처럼 (EC)DHE 키 설정을 수행하기 위해
"key_share" 확장으로 응답할 수 있으므로 순방향 비밀성을 제공한다.
Rescorla 표준 트랙 [16페이지]
RFC 8446 TLS 2018년 8월
PSK가 대역 외에서 제공되는 경우, PSK 식별자와 PSK에 사용할 KDF
해시 알고리즘도 함께 제공되어야 한다(MUST).
참고: 대역 외에서 제공된 사전 공유 비밀을 사용할 때, [RFC4086]에서
논의된 것처럼 키 생성 중 충분한 엔트로피를 사용하는 것이
매우 중요하다. 비밀번호나 다른 낮은 엔트로피 소스에서 공유
비밀을 파생하는 것은 안전하지 않다. 낮은 엔트로피 비밀 또는
비밀번호는 PSK 바인더에 기반한 사전 공격의 대상이 된다.
명세된 PSK 인증은 Diffie-Hellman 키 설정과 함께 사용되더라도
강력한 비밀번호 기반 인증 키 교환이 아니다. 구체적으로,
핸드셰이크를 관찰할 수 있는 공격자가 비밀번호/사전 공유 키에
대해 무차별 대입 공격을 수행하는 것을 막지 못한다.
2.3. 0-RTT 데이터
클라이언트와 서버가 PSK(외부에서 얻었거나 이전 핸드셰이크를
통해 얻은 것)를 공유할 때, TLS 1.3은 클라이언트가 첫 번째
flight에서 데이터("early data")를 보낼 수 있게 한다. 클라이언트는
PSK를 사용하여 서버를 인증하고 조기 데이터를 암호화한다.
그림 4에 보인 것처럼, 0-RTT 데이터는 첫 번째 flight에서
1-RTT 핸드셰이크에 추가될 뿐이다. 핸드셰이크의 나머지는 PSK
재개를 사용하는 1-RTT 핸드셰이크와 동일한 메시지를 사용한다.
Rescorla 표준 트랙 [17페이지]
RFC 8446 TLS 2018년 8월
Client Server
ClientHello
+ early_data
+ key_share*
+ psk_key_exchange_modes
+ pre_shared_key
(Application Data*) -------->
ServerHello
+ pre_shared_key
+ key_share*
{EncryptedExtensions}
+ early_data*
{Finished}
<-------- [Application Data*]
(EndOfEarlyData)
{Finished} -------->
[Application Data] <-------> [Application Data]
+ 앞서 표시된 메시지에서 전송되는 주목할 만한
확장을 나타낸다.
* 항상 전송되지는 않는 선택적 또는 상황 의존적
메시지/확장을 나타낸다.
() client_early_traffic_secret에서 파생된 키를
사용하여 보호되는 메시지를 나타낸다.
{} [sender]_handshake_traffic_secret에서 파생된
키를 사용하여 보호되는 메시지를 나타낸다.
[] [sender]_application_traffic_secret_N에서 파생된
키를 사용하여 보호되는 메시지를 나타낸다.
그림 4: 0-RTT 핸드셰이크의 메시지 흐름
Rescorla 표준 트랙 [18페이지]
RFC 8446 TLS 2018년 8월
중요 참고: 0-RTT 데이터의 보안 속성은 다른 종류의 TLS 데이터보다
약하다. 구체적으로는 다음과 같다.
1. 이 데이터는 제공된 PSK를 사용해 파생된 키로만 암호화되므로
순방향 비밀성을 갖지 않는다.
2. 연결 사이의 비재생성 보장이 없다. 일반 TLS 1.3 1-RTT 데이터에
대한 재생 방지는 서버의 Random 값으로 제공되지만, 0-RTT
데이터는 ServerHello에 의존하지 않으므로 더 약한 보장을
가진다. 이는 데이터가 TLS 클라이언트 인증으로 또는
애플리케이션 프로토콜 내부에서 인증되는 경우 특히 관련이
있다. 같은 경고는 early_exporter_master_secret의 모든 사용에도
적용된다.
0-RTT 데이터는 연결 내에서 복제될 수 없으며(즉, 서버는 같은
연결에 대해 같은 데이터를 두 번 처리하지 않음), 공격자는
0-RTT 데이터가 1-RTT 데이터처럼 보이게 만들 수 없다(서로 다른
키로 보호되기 때문). 부록 E.5에는 잠재적 공격에 대한 설명이
포함되어 있으며, 섹션 8은 서버가 재생의 영향을 제한하는 데
사용할 수 있는 메커니즘을 설명한다.
3. 표현 언어
이 문서는 외부 표현에서 데이터 형식을 다룬다. 다음의 매우
기본적이고 다소 느슨하게 정의된 표현 구문이 사용된다.
3.1. 기본 블록 크기
모든 데이터 항목의 표현은 명시적으로 지정된다. 기본 데이터
블록 크기는 1바이트(즉, 8비트)이다. 다중 바이트 데이터 항목은
왼쪽에서 오른쪽으로, 위에서 아래로 바이트를 연결한 것이다.
바이트 스트림에서 다중 바이트 항목(다음 예의 numeric)은
(C 표기법을 사용하여) 다음과 같이 형성된다.
value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
... | byte[n-1];
이 다중 바이트 값의 바이트 순서는 일반적인 네트워크 바이트
순서 또는 빅 엔디언 형식이다.
Rescorla 표준 트랙 [19페이지]
RFC 8446 TLS 2018년 8월
3.2. 기타
주석은 "/*"로 시작하여 "*/"로 끝난다.
선택적 구성요소는 "[[ ]]"(이중 대괄호)로 둘러싸 표시한다.
해석되지 않는 데이터를 포함하는 단일 바이트 엔터티는
opaque 타입이다.
기존 타입 T에 대한 타입 별칭 T'는 다음과 같이 정의된다.
T T';
3.3. 숫자
기본 숫자 데이터 타입은 부호 없는 바이트(uint8)이다. 더 큰 모든
숫자 데이터 타입은 섹션 3.1에 설명된 대로 고정 길이의
바이트 시퀀스를 연결하여 구성되며 역시 부호 없다. 다음 숫자
타입이 미리 정의되어 있다.
uint8 uint16[2];
uint8 uint24[3];
uint8 uint32[4];
uint8 uint64[8];
명세의 여기와 다른 곳의 모든 값은 네트워크 바이트(빅 엔디언)
순서로 전송된다. 16진수 바이트 01 02 03 04로 표현되는 uint32는
십진수 값 16909060과 동일하다.
3.4. 벡터
벡터(1차원 배열)는 동종 데이터 요소의 스트림이다. 벡터의 크기는
문서화 시점에 지정될 수도 있고 실행 시점까지 지정되지 않은 채로
남을 수도 있다. 어느 경우든 길이는 벡터의 요소 수가 아니라
바이트 수를 선언한다. 타입 T의 고정 길이 벡터인 새 타입 T'를
지정하는 구문은 다음과 같다.
T T'[n];
여기서 T'는 데이터 스트림에서 n바이트를 차지하며, n은 T 크기의
배수이다. 벡터의 길이는 인코딩된 스트림에 포함되지 않는다.
Rescorla 표준 트랙 [20페이지]
RFC 8446 TLS 2018년 8월
다음 예에서 Datum은 프로토콜이 해석하지 않는 연속된 세 바이트로
정의되고, Data는 연속된 세 개의 Datum으로 총 9바이트를 소비한다.
opaque Datum[3]; /* 해석되지 않는 세 바이트 */
Datum Data[9]; /* 연속된 세 개의 3바이트 벡터 */
가변 길이 벡터는 <floor..ceiling> 표기법을 사용하여 허용되는
길이의 부분 범위를 양끝 포함으로 지정해 정의된다. 이들이
인코딩될 때 실제 길이는 벡터 내용 앞에 바이트 스트림으로 온다.
길이는 벡터에 지정된 최대(ceiling) 길이를 담는 데 필요한 만큼의
바이트를 소비하는 숫자 형식이다. 실제 길이 필드가 0인 가변 길이
벡터를 빈 벡터라고 한다.
T T'<floor..ceiling>;
다음 예에서 "mandatory"는 opaque 타입의 300에서 400바이트 사이를
반드시 포함해야 하는 벡터이다. 이는 결코 비어 있을 수 없다.
실제 길이 필드는 uint16인 2바이트를 소비하며, 이는 값 400을
표현하기에 충분하다(섹션 3.3 참조). 마찬가지로 "longer"는
최대 800바이트의 데이터, 또는 400개의 uint16 요소를 표현할 수
있으며, 비어 있을 수 있다. 그 인코딩은 벡터 앞에 2바이트 실제
길이 필드를 포함한다. 인코딩된 벡터의 길이는 단일 요소 길이의
정확한 배수여야 한다(예: uint16의 17바이트 벡터는 불법).
opaque mandatory<300..400>;
/* 길이 필드는 2바이트, 비어 있을 수 없음 */
uint16 longer<0..800>;
/* 0에서 400개의 16비트 부호 없는 정수 */
3.5. 열거형
"enum" 또는 "enumerated"라 불리는 추가적인 희소 데이터 타입을
사용할 수 있다. 각 정의는 서로 다른 타입이다. 같은 타입의
열거형만 할당하거나 비교할 수 있다. 다음 예에 보인 것처럼
열거형의 모든 요소에는 값이 할당되어야 한다. 열거형의 요소는
순서가 없으므로, 어떤 고유 값이든 어떤 순서로든 할당될 수 있다.
enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;
프로토콜의 향후 확장이나 추가는 새 값을 정의할 수 있다.
필드 정의가 달리 명시하지 않는 한 구현은 알 수 없는 값을
파싱하고 무시할 수 있어야 한다.
Rescorla 표준 트랙 [21페이지]
RFC 8446 TLS 2018년 8월
열거형은 최대 정의된 서수 값이 바이트 스트림에서 차지하는 만큼의
공간을 차지한다. 다음 정의는 Color 타입 필드를 전달하는 데
1바이트가 사용되게 한다.
enum { red(3), blue(5), white(7) } Color;
불필요한 요소를 정의하지 않고 폭 정의를 강제하기 위해 연관된
태그 없이 값을 선택적으로 지정할 수 있다.
다음 예에서 Taste는 데이터 스트림에서 2바이트를 소비하지만,
현재 프로토콜 버전에서는 값 1, 2, 또는 4만 가질 수 있다.
enum { sweet(1), sour(2), bitter(4), (32000) } Taste;
열거형 요소의 이름은 정의된 타입 내에서 스코프를 가진다. 첫 번째
예에서 열거형의 두 번째 요소에 대한 완전 수식 참조는
Color.blue이다. 할당 대상이 명확하게 지정된 경우 이러한 수식은
필요하지 않다.
Color color = Color.blue; /* 과도하게 지정됨, 적법 */
Color color = blue; /* 올바름, 타입이 암시됨 */
열거형에 할당된 이름은 고유할 필요가 없다. 숫자 값은 같은 이름이
적용되는 범위를 설명할 수 있다. 값은 두 개의 마침표 문자로
구분된, 그 범위의 포함되는 최소값과 최대값을 포함한다. 이는
주로 공간의 영역을 예약하는 데 유용하다.
enum { sad(0), meh(1..254), happy(255) } Mood;
3.6. 구성 타입
구조체 타입은 편의를 위해 원시 타입에서 구성될 수 있다. 각
명세는 새롭고 고유한 타입을 선언한다. 정의에 사용되는 구문은
C의 구문과 매우 유사하다.
struct {
T1 f1;
T2 f2;
...
Tn fn;
} T;
표준 벡터 구문을 사용하여 고정 길이 및 가변 길이 벡터 필드를
허용한다. 변형 예(섹션 3.8)의 구조체 V1과 V2가 이를 보여준다.
Rescorla 표준 트랙 [22페이지]
RFC 8446 TLS 2018년 8월
구조체 내 필드는 열거형에서 사용할 수 있는 것과 매우 유사한
구문으로 타입 이름을 사용해 수식될 수 있다. 예를 들어 T.f2는
앞선 선언의 두 번째 필드를 가리킨다.
3.7. 상수
필드와 변수에는 다음과 같이 "="를 사용하여 고정 값을 할당할 수
있다.
struct {
T1 f1 = 8; /* T.f1은 항상 8이어야 함 */
T2 f2;
} T;
3.8. 변형
정의된 구조체는 환경 내에서 사용할 수 있는 어떤 지식에 기반한
변형을 가질 수 있다. selector는 구조체가 정의하는 가능한 변형을
정의하는 열거형 타입이어야 한다. 아래 select의 각 arm은 해당
변형 필드의 타입과 선택적 필드 레이블을 지정한다. 런타임에
변형이 선택되는 메커니즘은 표현 언어에서 규정하지 않는다.
struct {
T1 f1;
T2 f2;
....
Tn fn;
select (E) {
case e1: Te1 [[fe1]];
case e2: Te2 [[fe2]];
....
case en: Ten [[fen]];
};
} Tv;
Rescorla 표준 트랙 [23페이지]
RFC 8446 TLS 2018년 8월
예를 들면 다음과 같다.
enum { apple(0), orange(1) } VariantTag;
struct {
uint16 number;
opaque string<0..10>; /* 가변 길이 */
} V1;
struct {
uint32 number;
opaque string[10]; /* 고정 길이 */
} V2;
struct {
VariantTag type;
select (VariantRecord.type) {
case apple: V1;
case orange: V2;
};
} VariantRecord;
4. 핸드셰이크 프로토콜
핸드셰이크 프로토콜은 연결의 보안 매개변수를 협상하는 데
사용된다. 핸드셰이크 메시지는 TLS 레코드 계층에 제공되며,
그곳에서 현재 활성 연결 상태가 지정하는 대로 처리되고 전송되는
하나 이상의 TLSPlaintext 또는 TLSCiphertext 구조 안에 캡슐화된다.
Rescorla 표준 트랙 [24페이지]
RFC 8446 TLS 2018년 8월
enum {
client_hello(1),
server_hello(2),
new_session_ticket(4),
end_of_early_data(5),
encrypted_extensions(8),
certificate(11),
certificate_request(13),
certificate_verify(15),
finished(20),
key_update(24),
message_hash(254),
(255)
} HandshakeType;
struct {
HandshakeType msg_type; /* 핸드셰이크 타입 */
uint24 length; /* 메시지의 남은 바이트 */
select (Handshake.msg_type) {
case client_hello: ClientHello;
case server_hello: ServerHello;
case end_of_early_data: EndOfEarlyData;
case encrypted_extensions: EncryptedExtensions;
case certificate_request: CertificateRequest;
case certificate: Certificate;
case certificate_verify: CertificateVerify;
case finished: Finished;
case new_session_ticket: NewSessionTicket;
case key_update: KeyUpdate;
};
} Handshake;
프로토콜 메시지는 섹션 4.4.1에 정의되고 섹션 2의
다이어그램에 보인 순서로 전송되어야 한다(MUST). 예상하지 못한
순서로 핸드셰이크 메시지를 수신한 피어는 "unexpected_message"
경고와 함께 핸드셰이크를 중단해야 한다(MUST).
새 핸드셰이크 메시지 타입은 섹션 11에 설명된 대로 IANA가
할당한다.
4.1. 키 교환 메시지
키 교환 메시지는 클라이언트와 서버의 보안 기능을 결정하고,
핸드셰이크의 나머지 부분과 데이터를 보호하는 데 사용되는 트래픽
키를 포함한 공유 비밀을 설정하는 데 사용된다.
Rescorla 표준 트랙 [25페이지]
RFC 8446 TLS 2018년 8월
4.1.1. 암호학적 협상
TLS에서 암호학적 협상은 클라이언트가 ClientHello에서 다음 네
가지 옵션 집합을 제공하면서 진행된다.
- 클라이언트가 지원하는 AEAD 알고리즘/HKDF 해시 쌍을 나타내는
암호 스위트 목록.
- 클라이언트가 지원하는 (EC)DHE 그룹을 나타내는
"supported_groups"(섹션 4.2.7) 확장과, 이 그룹 중 일부
또는 전부에 대한 (EC)DHE 공유값을 포함하는 "key_share"
(섹션 4.2.8) 확장.
- 클라이언트가 수락할 수 있는 서명 알고리즘을 나타내는
"signature_algorithms"(섹션 4.2.3) 확장. 인증서별 서명
알고리즘을 나타내기 위해 "signature_algorithms_cert" 확장
(섹션 4.2.3)도 추가될 수 있다.
- 클라이언트에 알려진 대칭 키 식별자 목록을 포함하는
"pre_shared_key"(섹션 4.2.11) 확장과, PSK와 함께 사용할 수
있는 키 교환 모드를 나타내는 "psk_key_exchange_modes"
(섹션 4.2.9) 확장.
서버가 PSK를 선택하지 않으면, 이 옵션들 중 앞의 세 가지는
완전히 직교적이다. 서버는 암호 스위트, 키 설정을 위한 (EC)DHE
그룹과 키 공유, 그리고 클라이언트에 자신을 인증하기 위한 서명
알고리즘/인증서 쌍을 독립적으로 선택한다. 수신된
"supported_groups"와 서버가 지원하는 그룹 사이에 겹치는 것이
없으면, 서버는 "handshake_failure" 또는 "insufficient_security"
경고와 함께 핸드셰이크를 중단해야 한다(MUST).
서버가 PSK를 선택하면, 클라이언트의 "psk_key_exchange_modes"
확장에 표시된 집합에서 키 설정 모드도 선택해야 한다(MUST)
(현재는 PSK 단독 또는 (EC)DHE와 함께). PSK를 (EC)DHE 없이 사용할
수 있다면, "supported_groups" 매개변수의 불일치가 이전 단락에서
논의한 비-PSK 경우처럼 반드시 치명적일 필요는 없다는 점에
유의하라.
서버가 (EC)DHE 그룹을 선택했는데 클라이언트가 초기 ClientHello에
호환되는 "key_share" 확장을 제공하지 않았다면, 서버는
HelloRetryRequest(섹션 4.1.4) 메시지로 응답해야 한다(MUST).
Rescorla 표준 트랙 [26페이지]
RFC 8446 TLS 2018년 8월
서버가 매개변수를 성공적으로 선택하고 HelloRetryRequest가 필요하지
않으면, 다음과 같이 ServerHello에서 선택된 매개변수를 나타낸다.
- PSK가 사용 중이면, 서버는 선택된 키를 나타내는
"pre_shared_key" 확장을 보낸다.
- (EC)DHE가 사용 중이면, 서버는 "key_share" 확장도 제공한다.
PSK가 사용 중이 아니면 (EC)DHE와 인증서 기반 인증이 항상
사용된다.
- 인증서로 인증할 때, 서버는 Certificate(섹션 4.4.2) 및
CertificateVerify(섹션 4.4.3) 메시지를 보낸다. 이 문서가
정의하는 TLS 1.3에서는 PSK 또는 인증서 중 하나가 항상
사용되지만, 둘 다 사용되지는 않는다. 향후 문서에서 둘을
함께 사용하는 방법을 정의할 수 있다.
서버가 지원되는 매개변수 집합을 협상할 수 없는 경우(즉,
클라이언트와 서버 매개변수 사이에 겹침이 없는 경우), 서버는
"handshake_failure" 또는 "insufficient_security" 치명적 경고와
함께 핸드셰이크를 중단해야 한다(MUST) (섹션 6 참조).
4.1.2. Client Hello
클라이언트가 처음 서버에 연결할 때, 첫 TLS 메시지로 ClientHello를
보내야 한다(REQUIRED). 서버가 ClientHello에 대해
HelloRetryRequest로 응답한 경우에도 클라이언트는 ClientHello를
보낸다. 이 경우 클라이언트는 다음을 제외하고 수정 없이 같은
ClientHello를 보내야 한다(MUST).
- HelloRetryRequest에 "key_share" 확장이 제공된 경우, 공유값
목록을 표시된 그룹의 단일 KeyShareEntry를 포함하는 목록으로
대체한다.
- "early_data" 확장(섹션 4.2.10)이 존재했다면 제거한다.
HelloRetryRequest 이후에는 조기 데이터가 허용되지 않는다.
- HelloRetryRequest에서 제공된 경우 "cookie" 확장을 포함한다.
Rescorla 표준 트랙 [27페이지]
RFC 8446 TLS 2018년 8월
- 존재하는 경우 "obfuscated_ticket_age"와 바인더 값을 다시
계산하고, (선택적으로) 서버가 표시한 암호 스위트와 호환되지
않는 모든 PSK를 제거하여 "pre_shared_key" 확장을 갱신한다.
- 선택적으로 "padding" 확장 [RFC7685]을 추가, 제거하거나
그 길이를 변경한다.
- 향후 정의되고 HelloRetryRequest에 존재하는 확장이 허용할 수
있는 다른 수정.
TLS 1.3은 재협상을 금지하므로, 서버가 TLS 1.3을 협상한 뒤
다른 시점에 ClientHello를 수신하면, "unexpected_message" 경고와
함께 연결을 종료해야 한다(MUST).
서버가 이전 TLS 버전으로 TLS 연결을 설정했고 재협상 중 TLS 1.3
ClientHello를 수신하면, 이전 프로토콜 버전을 유지해야 한다(MUST).
특히 TLS 1.3을 협상해서는 안 된다(MUST NOT).
이 메시지의 구조:
uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2]; /* 암호학적 스위트 선택자 */
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<8..2^16-1>;
} ClientHello;
Rescorla 표준 트랙 [28페이지]
RFC 8446 TLS 2018년 8월
legacy_version: 이전 TLS 버전에서 이 필드는 버전 협상에 사용되었고
클라이언트가 지원하는 가장 높은 버전 번호를 나타냈다. 경험상
많은 서버가 버전 협상을 제대로 구현하지 않아, 서버가 자신이
지원하는 것보다 높은 버전 번호를 가진, 그 외에는 수용 가능한
ClientHello를 거부하는 "version intolerance"로 이어졌다.
TLS 1.3에서 클라이언트는 "supported_versions" 확장
(섹션 4.2.1)으로 자신의 버전 선호를 나타내며,
legacy_version 필드는 TLS 1.2의 버전 번호인 0x0303으로 설정되어야
한다(MUST). TLS 1.3 ClientHello는 legacy_version이 0x0303이고
그 안에 표시된 가장 높은 버전으로 0x0304가 있는
supported_versions 확장이 존재하는 것으로 식별된다.
(하위 호환성에 대한 자세한 내용은 부록 D를 참조하라.)
random: 보안 난수 생성기가 생성한 32바이트. 추가 정보는
부록 C를 참조하라.
legacy_session_id: TLS 1.3 이전의 TLS 버전은 "session resumption"
기능을 지원했으며, 이 버전에서는 사전 공유 키와 병합되었다
(섹션 2.2 참조). pre-TLS 1.3 서버가 설정한 캐시된 세션 ID가
있는 클라이언트는 이 필드를 그 값으로 설정해야 한다(SHOULD).
호환성 모드(부록 D.4 참조)에서는 이 필드가 비어 있으면 안
되므로(MUST), pre-TLS 1.3 세션을 제공하지 않는 클라이언트는
새 32바이트 값을 생성해야 한다(MUST). 이 값은 임의일 필요는
없지만, 구현이 특정 값에 고착되는 것(ossification이라고도 함)을
피하기 위해 예측 불가능해야 한다(SHOULD). 그 밖의 경우에는
0 길이 벡터(즉, 값이 0인 단일 바이트 길이 필드)로 설정되어야
한다(MUST).
cipher_suites: 클라이언트가 지원하는 대칭 암호 옵션 목록,
구체적으로는 레코드 보호 알고리즘(비밀 키 길이 포함)과 HKDF와
함께 사용할 해시이며, 클라이언트 선호도 내림차순으로 나열된다.
값은 부록 B.4에 정의되어 있다. 목록에 서버가 인식하지
못하거나, 지원하지 않거나, 사용하고 싶지 않은 암호 스위트가
포함되어 있으면, 서버는 그 암호 스위트를 무시하고 나머지를
평소처럼 처리해야 한다(MUST). 클라이언트가 PSK 키 설정을
시도하는 경우, PSK와 연관된 Hash를 나타내는 암호 스위트를
적어도 하나 광고해야 한다(SHOULD).
Rescorla 표준 트랙 [29페이지]
RFC 8446 TLS 2018년 8월
legacy_compression_methods: TLS 1.3 이전의 TLS 버전은 지원되는
압축 방법 목록을 이 필드에 보내는 방식으로 압축을 지원했다.
모든 TLS 1.3 ClientHello에 대해 이 벡터는 정확히 1바이트를
포함해야 하며(MUST), 이전 TLS 버전의 "null" 압축 방법에
대응하는 0으로 설정되어야 한다. 이 필드에 다른 값을 가진
TLS 1.3 ClientHello가 수신되면, 서버는 "illegal_parameter"
경고와 함께 핸드셰이크를 중단해야 한다(MUST). TLS 1.3 서버는
다른 압축 방법을 포함하는 TLS 1.2 또는 이전 ClientHello를
수신할 수 있으며, (그러한 이전 버전을 협상하는 경우) 적절한
이전 TLS 버전의 절차를 따라야 한다(MUST)는 점에 유의하라.
extensions: 클라이언트는 extensions 필드에 데이터를 보내 서버에
확장 기능을 요청한다. 실제 "Extension" 형식은 섹션 4.2에
정의되어 있다. TLS 1.3에서는 이전 TLS 버전과의 ClientHello
호환성을 보존하기 위해 기능이 확장으로 이동했으므로 특정
확장의 사용이 필수이다. 서버는 인식하지 못하는 확장을
무시해야 한다(MUST).
모든 TLS 버전은 extensions 필드가 compression_methods 필드 뒤에
선택적으로 올 수 있게 한다. TLS 1.3 ClientHello 메시지는 항상
확장을 포함한다(최소한 "supported_versions". 그렇지 않으면
TLS 1.2 ClientHello 메시지로 해석된다). 그러나 TLS 1.3 서버는
이전 TLS 버전에서 extensions 필드가 없는 ClientHello 메시지를
받을 수 있다. 확장의 존재는 ClientHello 끝의 compression_methods
필드 뒤에 바이트가 있는지를 확인하여 탐지할 수 있다. 선택적
데이터를 탐지하는 이 방법은 가변 길이 필드를 갖는 일반 TLS
방식과 다르지만, 확장이 정의되기 전의 TLS와의 호환성을 위해
사용된다는 점에 유의하라. TLS 1.3 서버는 먼저 이 검사를 수행한
다음 "supported_versions" 확장이 존재하는 경우에만 TLS 1.3
협상을 시도해야 한다. TLS 1.3 이전 버전의 TLS를 협상하는 경우,
서버는 메시지가 legacy_compression_methods 뒤에 데이터를 포함하지
않거나, 뒤따르는 데이터 없이 유효한 확장 블록을 포함하는지
검사해야 한다(MUST). 그렇지 않으면 "decode_error" 경고와 함께
핸드셰이크를 중단해야 한다(MUST).
클라이언트가 확장을 사용하여 추가 기능을 요청했는데 이 기능이
서버에 의해 제공되지 않는 경우, 클라이언트는 핸드셰이크를
중단할 수 있다(MAY).
ClientHello 메시지를 보낸 뒤 클라이언트는 ServerHello 또는
HelloRetryRequest 메시지를 기다린다. 조기 데이터가 사용 중이면,
클라이언트는 다음 핸드셰이크 메시지를 기다리는 동안 조기
Application Data(섹션 2.3)를 전송할 수 있다.
Rescorla 표준 트랙 [30페이지]
RFC 8446 TLS 2018년 8월
4.1.3. Server Hello
서버는 ClientHello에 기반하여 수용 가능한 핸드셰이크 매개변수
집합을 협상할 수 있는 경우, 핸드셰이크를 진행하기 위해 이
메시지를 ClientHello 메시지에 대한 응답으로 보낸다.
이 메시지의 구조:
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id_echo<0..32>;
CipherSuite cipher_suite;
uint8 legacy_compression_method = 0;
Extension extensions<6..2^16-1>;
} ServerHello;
legacy_version: 이전 TLS 버전에서 이 필드는 버전 협상에 사용되었고
연결에 대해 선택된 버전 번호를 나타냈다. 안타깝게도 일부
미들박스는 새 값이 제시되면 실패한다. TLS 1.3에서 TLS 서버는
"supported_versions" 확장(섹션 4.2.1)을 사용하여 자신의
버전을 나타내며, legacy_version 필드는 TLS 1.2의 버전 번호인
0x0303으로 설정되어야 한다(MUST). (하위 호환성에 대한 자세한
내용은 부록 D를 참조하라.)
random: 보안 난수 생성기가 생성한 32바이트. 추가 정보는
부록 C를 참조하라. TLS 1.2 또는 TLS 1.1을 협상하는
경우 마지막 8바이트는 아래에 설명된 대로 덮어써야 하지만(MUST),
나머지 바이트는 임의여야 한다(MUST). 이 구조는 서버가 생성하며
ClientHello.random과 독립적으로 생성되어야 한다(MUST).
legacy_session_id_echo: 클라이언트의 legacy_session_id 필드의
내용. 이 필드는 클라이언트의 값이 서버가 재개하지 않기로
선택한 캐시된 pre-TLS 1.3 세션에 대응하더라도 에코된다는 점에
유의하라. 자신이 ClientHello에서 보낸 것과 일치하지 않는
legacy_session_id_echo 필드를 수신한 클라이언트는
"illegal_parameter" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
cipher_suite: ClientHello.cipher_suites 목록에서 서버가 선택한
단일 암호 스위트. 제공하지 않은 암호 스위트를 수신한
클라이언트는 "illegal_parameter" 경고와 함께 핸드셰이크를
중단해야 한다(MUST).
legacy_compression_method: 값이 0이어야 하는(MUST) 단일 바이트.
Rescorla 표준 트랙 [31페이지]
RFC 8446 TLS 2018년 8월
extensions: 확장 목록. ServerHello는 암호학적 컨텍스트를 설정하고
프로토콜 버전을 협상하는 데 필요한 확장만 포함해야 한다(MUST).
모든 TLS 1.3 ServerHello 메시지는 "supported_versions" 확장을
포함해야 한다(MUST). 현재 ServerHello 메시지는 추가로
"pre_shared_key" 확장 또는 "key_share" 확장, 또는 둘 모두
((EC)DHE 키 설정과 함께 PSK를 사용하는 경우)를 포함한다.
다른 확장(섹션 4.2 참조)은 EncryptedExtensions 메시지에서
별도로 전송된다.
미들박스와의 하위 호환성 이유로(부록 D.4 참조),
HelloRetryRequest 메시지는 ServerHello와 동일한 구조를 사용하지만,
Random은 "HelloRetryRequest"의 SHA-256이라는 특수 값으로 설정된다.
CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C
server_hello 타입의 메시지를 수신하면 구현은 먼저 Random 값을
검사해야 하며(MUST), 이 값과 일치하면 섹션 4.1.4에 설명된
대로 처리해야 한다.
TLS 1.3은 서버의 random 값에 내장된 다운그레이드 보호 메커니즘을
가진다. TLS 1.3 서버가 ClientHello에 대한 응답으로 TLS 1.2 이하를
협상하는 경우, ServerHello에서 Random 값의 마지막 8바이트를
특별히 설정해야 한다(MUST).
TLS 1.2를 협상하는 경우, TLS 1.3 서버는 Random 값의 마지막
8바이트를 다음 바이트로 설정해야 한다(MUST).
44 4F 57 4E 47 52 44 01
TLS 1.1 이하를 협상하는 경우, TLS 1.3 서버는 ServerHello.Random
값의 마지막 8바이트를 다음 바이트로 설정해야 하며(MUST),
TLS 1.2 서버는 그렇게 설정해야 한다(SHOULD).
44 4F 57 4E 47 52 44 00
TLS 1.2 이하를 나타내는 ServerHello를 수신한 TLS 1.3 클라이언트는
마지막 8바이트가 이 두 값 중 어느 것과도 같지 않은지 검사해야
한다(MUST). TLS 1.2 클라이언트도 ServerHello가 TLS 1.1 이하를
나타내는 경우 마지막 8바이트가 두 번째 값과 같지 않은지 검사해야
한다(SHOULD). 일치가 발견되면 클라이언트는 "illegal_parameter"
경고와 함께 핸드셰이크를 중단해야 한다(MUST). 이 메커니즘은
Finished 교환이 제공하는 것에 더하여 다운그레이드 공격에 대한
제한적인 보호를 제공한다. TLS 1.2 이하에 존재하는 메시지인
ServerKeyExchange가 두 random 값 모두에 대한 서명을 포함하므로,
임시 암호가 사용되는 한 능동 공격자가 탐지되지 않고 random 값을
Rescorla 표준 트랙 [32페이지]
RFC 8446 TLS 2018년 8월
수정하는 것은 불가능하다. 정적 RSA가 사용될 때에는 다운그레이드
보호를 제공하지 않는다.
참고: 이는 [RFC5246]로부터의 변경이므로, 실제로 많은 TLS 1.2
클라이언트와 서버는 위에 명세된 대로 동작하지 않을 것이다.
TLS 1.2 이하로 재협상을 수행하는 레거시 TLS 클라이언트가 재협상
중 TLS 1.3 ServerHello를 수신하면, "protocol_version" 경고와 함께
핸드셰이크를 중단해야 한다(MUST). TLS 1.3이 협상된 경우 재협상은
불가능하다는 점에 유의하라.
4.1.4. Hello Retry Request
서버는 수용 가능한 매개변수 집합을 찾을 수 있지만 ClientHello가
핸드셰이크를 진행하기에 충분한 정보를 포함하지 않는 경우, 이
메시지를 ClientHello 메시지에 대한 응답으로 보낸다. 섹션 4.1.3에서
논의한 것처럼 HelloRetryRequest는 ServerHello 메시지와 동일한
형식을 가지며, legacy_version, legacy_session_id_echo,
cipher_suite, legacy_compression_method 필드는 같은 의미를 가진다.
그러나 편의를 위해 이 문서 전체에서 "HelloRetryRequest"를 별개의
메시지인 것처럼 논의한다.
서버의 확장은 "supported_versions"를 포함해야 한다(MUST). 또한
클라이언트가 올바른 ClientHello 쌍을 생성하는 데 필요한 최소
확장 집합을 포함해야 한다(SHOULD). ServerHello와 마찬가지로,
HelloRetryRequest는 선택적으로 "cookie"(섹션 4.2.2 참조)
확장을 포함하는 예외를 제외하고, 클라이언트가 자신의 ClientHello에서
처음 제공하지 않은 확장을 포함해서는 안 된다(MUST NOT).
HelloRetryRequest를 수신하면, 클라이언트는 섹션 4.1.3에 명세된
대로 legacy_version, legacy_session_id_echo, cipher_suite,
legacy_compression_method를 검사한 다음, "supported_versions"를
사용한 버전 결정으로 시작하여 확장을 처리해야 한다(MUST).
HelloRetryRequest가 ClientHello에 어떠한 변경도 일으키지 않는다면
클라이언트는 "illegal_parameter" 경고와 함께 핸드셰이크를
중단해야 한다(MUST). 클라이언트가 같은 연결에서 두 번째
HelloRetryRequest를 수신하면(즉, ClientHello 자체가 HelloRetryRequest에
대한 응답이었던 경우), "unexpected_message" 경고와 함께
핸드셰이크를 중단해야 한다(MUST).
Rescorla 표준 트랙 [33페이지]
RFC 8446 TLS 2018년 8월
그렇지 않으면, 클라이언트는 HelloRetryRequest의 모든 확장을 처리하고
두 번째 갱신된 ClientHello를 보내야 한다(MUST). 이 명세에 정의된
HelloRetryRequest 확장은 다음과 같다.
- supported_versions (섹션 4.2.1 참조)
- cookie (섹션 4.2.2 참조)
- key_share (섹션 4.2.8 참조)
제공하지 않은 암호 스위트를 수신한 클라이언트는 핸드셰이크를
중단해야 한다(MUST). 서버는 준수하는 갱신된 ClientHello를 수신할
때 같은 암호 스위트를 협상하도록 보장해야 한다(MUST)(서버가 협상의
첫 단계로 암호 스위트를 선택하면 이는 자동으로 일어난다).
ServerHello를 수신하면, 클라이언트는 ServerHello에 제공된 암호
스위트가 HelloRetryRequest의 것과 동일한지 검사해야 하며(MUST),
그렇지 않으면 "illegal_parameter" 경고와 함께 핸드셰이크를
중단해야 한다.
또한 갱신된 ClientHello에서 클라이언트는 선택된 암호 스위트의
해시가 아닌 해시와 연관된 사전 공유 키를 제공하지 않는 것이
좋다(SHOULD NOT). 이를 통해 클라이언트는 두 번째 ClientHello에서
여러 해시에 대한 부분 해시 전사를 계산하지 않아도 된다.
HelloRetryRequest "supported_versions" 확장의 selected_version 값은
ServerHello에 유지되어야 하며(MUST), 값이 변경되면 클라이언트는
"illegal_parameter" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
Rescorla 표준 트랙 [34페이지]
RFC 8446 TLS 2018년 8월
4.2. 확장
여러 TLS 메시지는 태그-길이-값으로 인코딩된 확장 구조를 포함한다.
struct {
ExtensionType extension_type;
opaque extension_data<0..2^16-1>;
} Extension;
enum {
server_name(0), /* RFC 6066 */
max_fragment_length(1), /* RFC 6066 */
status_request(5), /* RFC 6066 */
supported_groups(10), /* RFC 8422, 7919 */
signature_algorithms(13), /* RFC 8446 */
use_srtp(14), /* RFC 5764 */
heartbeat(15), /* RFC 6520 */
application_layer_protocol_negotiation(16), /* RFC 7301 */
signed_certificate_timestamp(18), /* RFC 6962 */
client_certificate_type(19), /* RFC 7250 */
server_certificate_type(20), /* RFC 7250 */
padding(21), /* RFC 7685 */
pre_shared_key(41), /* RFC 8446 */
early_data(42), /* RFC 8446 */
supported_versions(43), /* RFC 8446 */
cookie(44), /* RFC 8446 */
psk_key_exchange_modes(45), /* RFC 8446 */
certificate_authorities(47), /* RFC 8446 */
oid_filters(48), /* RFC 8446 */
post_handshake_auth(49), /* RFC 8446 */
signature_algorithms_cert(50), /* RFC 8446 */
key_share(51), /* RFC 8446 */
(65535)
} ExtensionType;
Rescorla 표준 트랙 [35페이지]
RFC 8446 TLS 2018년 8월
여기서:
- "extension_type"은 특정 확장 타입을 식별한다.
- "extension_data"는 특정 확장 타입에 특화된 정보를 포함한다.
확장 타입 목록은 섹션 11에 설명된 대로 IANA가 유지한다.
확장은 일반적으로 요청/응답 방식으로 구성되지만, 일부 확장은
대응하는 응답이 없는 표시일 뿐이다. 클라이언트는 ClientHello
메시지에서 확장 요청을 보내고, 서버는 ServerHello,
EncryptedExtensions, HelloRetryRequest 및 Certificate 메시지에서
확장 응답을 보낸다. 서버는 CertificateRequest 메시지에서 확장
요청을 보내며, 클라이언트는 Certificate 메시지로 이에 응답할 수
있다(MAY). 서버는 NewSessionTicket에서 요청되지 않은 확장을 보낼
수도 있지만(MAY), 클라이언트는 이에 직접 응답하지 않는다.
구현은 원격 엔드포인트가 대응하는 확장 요청을 보내지 않았다면
확장 응답을 보내서는 안 되며(MUST NOT), HelloRetryRequest의
"cookie" 확장은 예외이다. 이러한 확장을 수신하면 엔드포인트는
"unsupported_extension" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
아래 표는 주어진 확장이 나타날 수 있는 메시지를 표시하며, 다음
표기법을 사용한다. CH(ClientHello), SH(ServerHello),
EE(EncryptedExtensions), CT(Certificate), CR(CertificateRequest),
NST(NewSessionTicket), HRR(HelloRetryRequest). 구현이 인식하는
확장을 그 확장이 나타난 메시지에 대해 지정되지 않은 위치에서
수신하면, 구현은 "illegal_parameter" 경고와 함께 핸드셰이크를
중단해야 한다(MUST).
Rescorla 표준 트랙 [36페이지]
RFC 8446 TLS 2018년 8월
+--------------------------------------------------+-------------+
| 확장 | TLS 1.3 |
+--------------------------------------------------+-------------+
| server_name [RFC6066] | CH, EE |
| | |
| max_fragment_length [RFC6066] | CH, EE |
| | |
| status_request [RFC6066] | CH, CR, CT |
| | |
| supported_groups [RFC7919] | CH, EE |
| | |
| signature_algorithms (RFC 8446) | CH, CR |
| | |
| use_srtp [RFC5764] | CH, EE |
| | |
| heartbeat [RFC6520] | CH, EE |
| | |
| application_layer_protocol_negotiation [RFC7301] | CH, EE |
| | |
| signed_certificate_timestamp [RFC6962] | CH, CR, CT |
| | |
| client_certificate_type [RFC7250] | CH, EE |
| | |
| server_certificate_type [RFC7250] | CH, EE |
| | |
| padding [RFC7685] | CH |
| | |
| key_share (RFC 8446) | CH, SH, HRR |
| | |
| pre_shared_key (RFC 8446) | CH, SH |
| | |
| psk_key_exchange_modes (RFC 8446) | CH |
| | |
| early_data (RFC 8446) | CH, EE, NST |
| | |
| cookie (RFC 8446) | CH, HRR |
| | |
| supported_versions (RFC 8446) | CH, SH, HRR |
| | |
| certificate_authorities (RFC 8446) | CH, CR |
| | |
| oid_filters (RFC 8446) | CR |
| | |
| post_handshake_auth (RFC 8446) | CH |
| | |
| signature_algorithms_cert (RFC 8446) | CH, CR |
+--------------------------------------------------+-------------+
Rescorla 표준 트랙 [37페이지]
RFC 8446 TLS 2018년 8월
여러 다른 타입의 확장이 존재할 때, 확장은 어떤 순서로든 나타날
수 있다(MAY). 단, "pre_shared_key"(섹션 4.2.11)는 예외로,
ClientHello에서 마지막 확장이어야 한다(MUST)(그러나 ServerHello
확장 블록에서는 어디에나 나타날 수 있다). 주어진 확장 블록에
같은 타입의 확장이 둘 이상 있어서는 안 된다(MUST NOT).
TLS 1.3에서는 TLS 1.2와 달리, 재개-PSK 모드에서도 각 핸드셰이크마다
확장이 협상된다. 그러나 0-RTT 매개변수는 이전 핸드셰이크에서
협상된 것이며, 불일치는 0-RTT 거부를 필요로 할 수 있다
(섹션 4.2.10 참조).
이 프로토콜에서는 새 기능과 기존 기능 사이에 미묘한(때로는
명백한) 상호작용이 발생하여 전체 보안의 상당한 감소로 이어질
수 있다. 새 확장을 설계할 때 다음 고려사항을 고려해야 한다.
- 서버가 확장에 동의하지 않는 일부 경우는 오류 조건이며
(예: 핸드셰이크가 계속될 수 없음), 일부는 단순히 특정 기능
지원을 거부하는 것이다. 일반적으로 전자에는 오류 경고를
사용하고 후자에는 서버 확장 응답의 필드를 사용해야 한다.
- 확장은 가능한 한 핸드셰이크 메시지 조작으로 특정 기능의 사용
(또는 미사용)을 강제하는 공격을 방지하도록 설계되어야 한다.
이 원칙은 해당 기능이 보안 문제를 일으킨다고 여겨지는지와
관계없이 따라야 한다. 종종 확장 필드가 Finished 메시지 해시의
입력에 포함된다는 사실만으로 충분하지만, 확장이 핸드셰이크
단계에서 전송되는 메시지의 의미를 변경할 때에는 극도의 주의가
필요하다. 설계자와 구현자는 핸드셰이크가 인증되기 전까지
능동 공격자가 메시지를 수정하고 확장을 삽입, 제거 또는
대체할 수 있다는 사실을 알고 있어야 한다.
Rescorla 표준 트랙 [38페이지]
RFC 8446 TLS 2018년 8월
4.2.1. 지원 버전
struct {
select (Handshake.msg_type) {
case client_hello:
ProtocolVersion versions<2..254>;
case server_hello: /* 및 HelloRetryRequest */
ProtocolVersion selected_version;
};
} SupportedVersions;
"supported_versions" 확장은 클라이언트가 자신이 지원하는 TLS 버전을
나타내고, 서버가 자신이 사용하는 버전을 나타내는 데 사용된다.
이 확장은 선호도 순서의 지원 버전 목록을 포함하며, 가장 선호하는
버전이 먼저 온다. 이 명세의 구현은 자신이 협상할 준비가 된 모든
TLS 버전을 포함하는 이 확장을 ClientHello에서 보내야 한다(MUST)
(이 명세의 경우 최소한 0x0304를 의미하지만, 이전 TLS 버전의
협상을 허용하는 경우 그것들도 존재해야 한다(MUST)).
이 확장이 존재하지 않는 경우, 이 명세를 준수하고 TLS 1.2도
지원하는 서버는 ClientHello.legacy_version이 0x0304 이상이더라도
[RFC5246]에 명세된 대로 TLS 1.2 또는 그 이전을 협상해야 한다(MUST).
서버는 legacy_version 0x0304 이상인 ClientHello를 수신하면
핸드셰이크를 중단할 수 있다(MAY).
이 확장이 ClientHello에 존재하는 경우, 서버는 버전 협상에
ClientHello.legacy_version 값을 사용해서는 안 되며(MUST NOT),
클라이언트 선호를 결정하는 데 "supported_versions" 확장만
사용해야 한다(MUST). 서버는 그 확장에 존재하는 TLS 버전만
선택해야 하며(MUST), 그 확장에 존재하는 알 수 없는 버전은
무시해야 한다(MUST). 이 메커니즘은 한쪽이 희소 범위를 지원하는
경우 TLS 1.2 이전 버전도 협상할 수 있게 한다는 점에 유의하라.
이전 TLS 버전 지원을 선택한 TLS 1.3 구현은 TLS 1.2를 지원해야
한다(SHOULD). 서버는 이 확장을 포함하지만 버전 목록에 0x0304를
포함하지 않는 ClientHello를 받을 준비가 되어 있어야 한다(MUST).
TLS 1.3 이전의 TLS 버전을 협상하는 서버는 ServerHello.version을
설정해야 하며(MUST), "supported_versions" 확장을 보내서는 안
된다(MUST NOT). TLS 1.3을 협상하는 서버는 선택된 버전 값(0x0304)을
포함하는 "supported_versions" 확장을 보내 응답해야 한다(MUST).
ServerHello.legacy_version 필드는 0x0303(TLS 1.2)으로 설정해야 한다.
클라이언트는 ServerHello의 나머지를 처리하기 전에 이 확장을
검사해야 한다(MUST)(확장을 읽으려면 ServerHello를 파싱해야 하긴
Rescorla 표준 트랙 [39페이지]
RFC 8446 TLS 2018년 8월
하지만). 이 확장이 존재하면, 클라이언트는 ServerHello.legacy_version
값을 무시해야 하며(MUST), 선택된 버전을 결정하는 데
"supported_versions" 확장만 사용해야 한다(MUST). ServerHello의
"supported_versions" 확장이 클라이언트가 제공하지 않은 버전을
포함하거나 TLS 1.3 이전 버전을 포함하면, 클라이언트는
"illegal_parameter" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
4.2.2. 쿠키
struct {
opaque cookie<1..2^16-1>;
} Cookie;
쿠키는 두 가지 주된 목적을 가진다.
- 서버가 클라이언트에게 자신이 보이는 네트워크 주소에서 도달
가능함을 입증하도록 강제할 수 있게 한다(따라서 DoS 보호의
한 척도를 제공한다). 이는 주로 비연결 지향 전송에 유용하다
(예는 [RFC6347] 참조).
- 서버가 상태를 클라이언트에 오프로드할 수 있게 하여, 상태를
저장하지 않고 HelloRetryRequest를 보낼 수 있게 한다. 서버는
ClientHello의 해시를 HelloRetryRequest 쿠키에 저장함으로써
이를 수행할 수 있다(적절한 무결성 보호 알고리즘으로 보호됨).
HelloRetryRequest를 보낼 때 서버는 클라이언트에 "cookie" 확장을
제공할 수 있다(MAY)(이는 보낼 수 있는 확장이 ClientHello에
나타난 것뿐이라는 일반 규칙의 예외이다). 새 ClientHello를 보낼
때, 클라이언트는 HelloRetryRequest에서 수신한 확장의 내용을 새
ClientHello의 "cookie" 확장에 복사해야 한다(MUST). 클라이언트는
이후 연결의 초기 ClientHello에서 쿠키를 사용해서는 안 된다(MUST NOT).
서버가 상태 없이 동작할 때, 첫 번째와 두 번째 ClientHello 사이에
change_cipher_spec 타입의 보호되지 않은 레코드를 수신할 수 있다
(섹션 5 참조). 서버가 어떤 상태도 저장하지 않으므로, 이는
수신된 첫 번째 메시지인 것처럼 보일 것이다. 상태 없이 동작하는
서버는 이러한 레코드를 무시해야 한다(MUST).
Rescorla 표준 트랙 [40페이지]
RFC 8446 TLS 2018년 8월
4.2.3. 서명 알고리즘
TLS 1.3은 디지털 서명에서 사용할 수 있는 서명 알고리즘을
나타내기 위해 두 가지 확장을 제공한다. "signature_algorithms_cert"
확장은 인증서의 서명에 적용되고, 원래 TLS 1.2에 등장한
"signature_algorithms" 확장은 CertificateVerify 메시지의 서명에
적용된다. 인증서에서 발견되는 키도 함께 사용되는 서명 알고리즘에
적절한 타입이어야 한다(MUST). 이는 아래에 설명된 것처럼 RSA 키와
PSS 서명에서 특히 문제가 된다. "signature_algorithms_cert" 확장이
존재하지 않으면, "signature_algorithms" 확장은 인증서에 나타나는
서명에도 적용된다. 서버가 인증서를 통해 자신을 인증하기를 원하는
클라이언트는 "signature_algorithms" 확장을 보내야 한다(MUST).
서버가 인증서를 통해 인증하는데 클라이언트가
"signature_algorithms" 확장을 보내지 않은 경우, 서버는
"missing_extension" 경고와 함께 핸드셰이크를 중단해야 한다(MUST)
(섹션 9.2 참조).
"signature_algorithms_cert" 확장은 인증서와 TLS 자체에서 서로 다른
알고리즘 집합을 지원하는 구현이 자신의 기능을 명확하게 알릴 수
있도록 추가되었다. TLS 1.2 구현도 이 확장을 처리해야 한다(SHOULD).
두 경우에 같은 정책을 가진 구현은 "signature_algorithms_cert"
확장을 생략할 수 있다(MAY).
Rescorla 표준 트랙 [41페이지]
RFC 8446 TLS 2018년 8월
이 확장들의 "extension_data" 필드는 SignatureSchemeList 값을
포함한다.
enum {
/* RSASSA-PKCS1-v1_5 알고리즘 */
rsa_pkcs1_sha256(0x0401),
rsa_pkcs1_sha384(0x0501),
rsa_pkcs1_sha512(0x0601),
/* ECDSA 알고리즘 */
ecdsa_secp256r1_sha256(0x0403),
ecdsa_secp384r1_sha384(0x0503),
ecdsa_secp521r1_sha512(0x0603),
/* 공개 키 OID rsaEncryption을 사용하는 RSASSA-PSS 알고리즘 */
rsa_pss_rsae_sha256(0x0804),
rsa_pss_rsae_sha384(0x0805),
rsa_pss_rsae_sha512(0x0806),
/* EdDSA 알고리즘 */
ed25519(0x0807),
ed448(0x0808),
/* 공개 키 OID RSASSA-PSS를 사용하는 RSASSA-PSS 알고리즘 */
rsa_pss_pss_sha256(0x0809),
rsa_pss_pss_sha384(0x080a),
rsa_pss_pss_sha512(0x080b),
/* 레거시 알고리즘 */
rsa_pkcs1_sha1(0x0201),
ecdsa_sha1(0x0203),
/* 예약된 코드 포인트 */
private_use(0xFE00..0xFFFF),
(0xFFFF)
} SignatureScheme;
struct {
SignatureScheme supported_signature_algorithms<2..2^16-2>;
} SignatureSchemeList;
참고: 이 enum은 "SignatureScheme"이라는 이름을 가진다. TLS 1.2에
이미 "SignatureAlgorithm" 타입이 있고, 이것이 이를 대체하기
때문이다. 본문 전체에서는 "signature algorithm"이라는 용어를
사용한다.
Rescorla 표준 트랙 [42페이지]
RFC 8446 TLS 2018년 8월
각 SignatureScheme 값은 클라이언트가 검증할 의향이 있는 단일 서명
알고리즘을 나열한다. 값은 선호도 내림차순으로 표시된다. 서명
알고리즘은 다이제스트가 아니라 임의 길이의 메시지를 입력으로
받는다는 점에 유의하라. 전통적으로 다이제스트에 작용하는
알고리즘은 TLS에서 먼저 지정된 해시 알고리즘으로 입력을 해시한
뒤 평소처럼 진행하도록 정의되어야 한다. 위에 나열된 코드 포인트
그룹은 다음 의미를 가진다.
RSASSA-PKCS1-v1_5 알고리즘: [RFC8017]의 RSASSA-PKCS1-v1_5를
[SHS]에 정의된 대응하는 해시 알고리즘과 함께 사용하는 서명
알고리즘을 나타낸다. 이 값들은 인증서에 나타나는 서명
(섹션 4.4.2.2 참조)에만 해당하며, TLS 1.2와의 하위
호환성을 위해 "signature_algorithms" 및
"signature_algorithms_cert"에 나타날 수는 있지만(MAY),
서명된 TLS 핸드셰이크 메시지에서 사용하도록 정의되지는 않는다.
ECDSA 알고리즘: [ECDSA]의 ECDSA, ANSI X9.62 [ECDSA] 및
FIPS 186-4 [DSS]에 정의된 대응하는 곡선, 그리고 [SHS]에
정의된 대응하는 해시 알고리즘을 사용하는 서명 알고리즘을
나타낸다. 서명은 DER 인코딩된 [X690] ECDSA-Sig-Value 구조로
표현된다.
RSASSA-PSS RSAE 알고리즘: 마스크 생성 함수 1과 함께
RSASSA-PSS [RFC8017]를 사용하는 서명 알고리즘을 나타낸다. 마스크
생성 함수에서 사용되는 다이제스트와 서명되는 다이제스트는
모두 [SHS]에 정의된 대응하는 해시 알고리즘이다. Salt의 길이는
다이제스트 알고리즘 출력의 길이와 같아야 한다(MUST). 공개 키가
X.509 인증서에 담기는 경우, rsaEncryption OID [RFC5280]를
사용해야 한다(MUST).
EdDSA 알고리즘: [RFC8032] 또는 그 후속 문서에 정의된 EdDSA를
사용하는 서명 알고리즘을 나타낸다. 이들은 "PureEdDSA"
알고리즘에 대응하며 "prehash" 변형이 아니라는 점에 유의하라.
RSASSA-PSS PSS 알고리즘: 마스크 생성 함수 1과 함께
RSASSA-PSS [RFC8017]를 사용하는 서명 알고리즘을 나타낸다. 마스크
생성 함수에서 사용되는 다이제스트와 서명되는 다이제스트는
모두 [SHS]에 정의된 대응하는 해시 알고리즘이다. Salt의 길이는
다이제스트 알고리즘의 길이와 같아야 한다(MUST). 공개 키가
X.509 인증서에 담기는 경우, RSASSA-PSS OID [RFC5756]를
사용해야 한다(MUST). 인증서 서명에 사용되는 경우, 알고리즘
매개변수는 DER 인코딩되어야 한다(MUST). 대응하는 공개 키의
매개변수가 존재한다면, 서명의 매개변수는 공개 키의 매개변수와
동일해야 한다(MUST).
Rescorla 표준 트랙 [43페이지]
RFC 8446 TLS 2018년 8월
레거시 알고리즘: 알려진 약점을 가진 알고리즘, 구체적으로 이
문맥에서 (1) RSASSA-PKCS1-v1_5를 사용하는 RSA 또는 (2) ECDSA와
함께 사용되는 SHA-1을 사용하기 때문에 폐기 예정인 알고리즘을
나타낸다. 이 값들은 인증서에 나타나는 서명(섹션 4.4.2.2
참조)에만 해당하며, TLS 1.2와의 하위 호환성을 위해
"signature_algorithms" 및 "signature_algorithms_cert"에 나타날
수는 있지만(MAY), 서명된 TLS 핸드셰이크 메시지에서 사용하도록
정의되지는 않는다. 엔드포인트는 이러한 알고리즘을 협상해서는
안 되지만(SHOULD NOT), 오직 하위 호환성을 위해 그렇게 하는 것은
허용된다. 이 값을 제공하는 클라이언트는 이를 가장 낮은 우선순위
로 나열해야 한다(MUST)(SignatureSchemeList의 다른 모든 알고리즘
뒤에 나열). TLS 1.3 서버는 유효한 인증서 체인을 이것 없이
생성할 수 없는 경우가 아니라면 SHA-1로 서명된 인증서를 제공해서는
안 된다(MUST NOT) (섹션 4.4.2.2 참조).
자체 서명된 인증서 또는 신뢰 앵커인 인증서의 서명은 인증 경로를
시작하므로 검증되지 않는다([RFC5280], 섹션 3.2 참조). 인증
경로를 시작하는 인증서는 "signature_algorithms" 확장에서 지원되는
것으로 광고되지 않은 서명 알고리즘을 사용할 수 있다(MAY).
TLS 1.2는 이 확장을 다르게 정의한다는 점에 유의하라. TLS 1.2
협상 의향이 있는 TLS 1.3 구현은 해당 버전을 협상할 때 [RFC5246]의
요구사항에 따라 동작해야 한다(MUST). 특히 다음과 같다.
- TLS 1.2 ClientHello는 이 확장을 생략할 수 있다(MAY).
- TLS 1.2에서 이 확장은 해시/서명 쌍을 포함했다. 쌍은 두
옥텟으로 인코딩되므로, SignatureScheme 값은 TLS 1.2의 인코딩과
정렬되도록 할당되었다. 일부 레거시 쌍은 할당되지 않은 상태로
남아 있다. 이러한 알고리즘은 TLS 1.3부터 폐기 예정이다. 어떤
구현도 이를 제공하거나 협상해서는 안 된다(MUST NOT). 특히
MD5 [SLOTH], SHA-224 및 DSA는 사용되어서는 안 된다(MUST NOT).
- ECDSA 서명 방식은 TLS 1.2의 ECDSA 해시/서명 쌍과 정렬된다.
그러나 이전 의미론은 서명 곡선을 제한하지 않았다. TLS 1.2가
협상되는 경우, 구현은 "supported_groups" 확장에서 자신이
광고한 어떤 곡선을 사용하는 서명도 수락할 준비가 되어 있어야
한다(MUST).
- RSASSA-PSS 지원을 광고하는 구현(TLS 1.3에서는 필수)은 TLS 1.2가
협상되는 경우에도 해당 방식을 사용하는 서명을 수락할 준비가
되어 있어야 한다(MUST). TLS 1.2에서는 RSASSA-PSS가 RSA 암호
스위트와 함께 사용된다.
Rescorla 표준 트랙 [44페이지]
RFC 8446 TLS 2018년 8월
4.2.4. 인증서 기관
"certificate_authorities" 확장은 엔드포인트가 지원하며 수신
엔드포인트가 인증서 선택을 안내하는 데 사용해야 하는(SHOULD)
인증서 기관(CA)을 나타내는 데 사용된다.
"certificate_authorities" 확장의 본문은
CertificateAuthoritiesExtension 구조로 구성된다.
opaque DistinguishedName<1..2^16-1>;
struct {
DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;
authorities: 허용 가능한 인증서 기관의 식별 이름 [X501] 목록으로,
DER 인코딩된 [X690] 형식으로 표현된다. 이러한 식별 이름은
신뢰 앵커 또는 하위 CA에 대해 원하는 식별 이름을 지정한다.
따라서 이 메시지는 알려진 신뢰 앵커와 원하는 인가 공간을
설명하는 데 사용될 수 있다.
클라이언트는 ClientHello 메시지에서 "certificate_authorities"
확장을 보낼 수 있다(MAY). 서버는 이를 CertificateRequest 메시지에서
보낼 수 있다(MAY).
유사한 목적을 가지지만 더 복잡한 "trusted_ca_keys" 확장
[RFC6066]은 TLS 1.3에서 사용되지 않는다(이전 TLS 버전을 제공하는
클라이언트의 ClientHello 메시지에는 나타날 수 있음).
4.2.5. OID 필터
"oid_filters" 확장은 서버가 클라이언트의 인증서가 일치하기를
원하는 OID/값 쌍의 집합을 제공할 수 있게 한다. 이 확장은 서버가
제공하는 경우 CertificateRequest 메시지에서만 전송되어야 한다(MUST).
struct {
opaque certificate_extension_oid<1..2^8-1>;
opaque certificate_extension_values<0..2^16-1>;
} OIDFilter;
struct {
OIDFilter filters<0..2^16-1>;
} OIDFilterExtension;
Rescorla 표준 트랙 [45페이지]
RFC 8446 TLS 2018년 8월
filters: 인증서 확장 OID [RFC5280]와 허용되는 값의 목록으로,
DER 인코딩된 [X690] 형식으로 표현된다. 일부 인증서 확장 OID는
여러 값을 허용한다(예: Extended Key Usage). 서버가 비어 있지
않은 filters 목록을 포함했다면, 응답에 포함된 클라이언트
인증서는 클라이언트가 인식하는 지정된 모든 확장 OID를 포함해야
한다(MUST). 클라이언트가 인식하는 각 확장 OID에 대해, 지정된
모든 값이 클라이언트 인증서에 존재해야 한다(MUST)(하지만
인증서는 다른 값도 가질 수 있음(MAY)). 그러나 클라이언트는
인식하지 못하는 인증서 확장 OID를 무시하고 건너뛰어야 한다(MUST).
클라이언트가 요구된 인증서 확장 OID 중 일부를 무시하고 요청을
만족하지 않는 인증서를 제공한 경우, 서버는 재량에 따라
클라이언트 인증 없이 연결을 계속하거나 "unsupported_certificate"
경고와 함께 핸드셰이크를 중단할 수 있다(MAY). 어떤 OID도
filters 목록에 한 번을 초과해 나타나서는 안 된다(MUST NOT).
PKIX RFC들은 다양한 인증서 확장 OID와 그 대응 값 타입을 정의한다.
타입에 따라 일치하는 인증서 확장 값이 반드시 비트 단위로 같지는
않다. TLS 구현은 인증서 확장 OID를 사용한 인증서 선택을 수행하기
위해 자신의 PKI 라이브러리에 의존할 것으로 예상된다.
이 문서는 [RFC5280]에 정의된 두 가지 표준 인증서 확장에 대한
일치 규칙을 정의한다.
- 인증서의 Key Usage 확장은 요청에서 주장된 모든 키 사용 비트가
Key Usage 인증서 확장에서도 주장된 경우 요청과 일치한다.
- 인증서의 Extended Key Usage 확장은 요청에 존재하는 모든 키
목적 OID가 Extended Key Usage 인증서 확장에서도 발견되는 경우
요청과 일치한다. 특수 anyExtendedKeyUsage OID는 요청에서
사용되어서는 안 된다(MUST NOT).
별도의 명세가 다른 인증서 확장에 대한 일치 규칙을 정의할 수 있다.
Rescorla 표준 트랙 [46페이지]
RFC 8446 TLS 2018년 8월
4.2.6. 핸드셰이크 후 클라이언트 인증
"post_handshake_auth" 확장은 클라이언트가 핸드셰이크 후 인증
(섹션 4.6.2)을 수행할 의향이 있음을 나타내는 데 사용된다.
서버는 이 확장을 제공하지 않은 클라이언트에 핸드셰이크 후
CertificateRequest를 보내서는 안 된다(MUST NOT). 서버는 이 확장을
보내서는 안 된다(MUST NOT).
struct {} PostHandshakeAuth;
"post_handshake_auth" 확장의 "extension_data" 필드는 길이가 0이다.
4.2.7. 지원 그룹
클라이언트가 보낼 때, "supported_groups" 확장은 클라이언트가 키
교환을 위해 지원하는 명명된 그룹을 가장 선호하는 것부터 가장 덜
선호하는 것 순서로 나타낸다.
참고: TLS 1.3 이전 버전에서 이 확장은 "elliptic_curves"라는
이름이었고 타원곡선 그룹만 포함했다. [RFC8422]와 [RFC7919]를
참조하라. 이 확장은 ECDSA 곡선을 협상하는 데에도 사용되었다.
서명 알고리즘은 이제 독립적으로 협상된다(섹션 4.2.3 참조).
이 확장의 "extension_data" 필드는 "NamedGroupList" 값을 포함한다.
enum {
/* 타원곡선 그룹(ECDHE) */
secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
x25519(0x001D), x448(0x001E),
/* 유한체 그룹(DHE) */
ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
ffdhe6144(0x0103), ffdhe8192(0x0104),
/* 예약된 코드 포인트 */
ffdhe_private_use(0x01FC..0x01FF),
ecdhe_private_use(0xFE00..0xFEFF),
(0xFFFF)
} NamedGroup;
struct {
NamedGroup named_group_list<2..2^16-1>;
} NamedGroupList;
Rescorla 표준 트랙 [47페이지]
RFC 8446 TLS 2018년 8월
타원곡선 그룹(ECDHE): FIPS 186-4 [DSS] 또는 [RFC7748]에 정의된
대응하는 명명 곡선에 대한 지원을 나타낸다. 0xFE00부터 0xFEFF까지의
값은 Private Use [RFC8126]를 위해 예약되어 있다.
유한체 그룹(DHE): [RFC7919]에 정의된 대응하는 유한체 그룹에 대한
지원을 나타낸다. 0x01FC부터 0x01FF까지의 값은 Private Use를 위해
예약되어 있다.
named_group_list의 항목은 송신자의 선호도에 따라 정렬된다(가장
선호하는 선택이 먼저).
TLS 1.3부터 서버는 클라이언트에 "supported_groups" 확장을 보낼 수
있다. 클라이언트는 핸드셰이크가 성공적으로 완료되기 전에는
"supported_groups"에서 발견한 어떤 정보에도 따라 동작해서는
안 되지만(MUST NOT), 성공적으로 완료된 핸드셰이크에서 알게 된
정보를 사용하여 이후 연결에서 "key_share" 확장에 사용하는 그룹을
변경할 수 있다(MAY). 서버가 "key_share" 확장의 그룹보다 선호하는
그룹을 가지고 있지만 여전히 ClientHello를 수락할 의향이 있다면,
클라이언트의 서버 선호에 대한 관점을 갱신하기 위해
"supported_groups"를 보내야 한다(SHOULD). 이 확장은 클라이언트가
현재 지원하는지 여부와 관계없이 서버가 지원하는 모든 그룹을
포함해야 한다(SHOULD).
4.2.8. 키 공유
"key_share" 확장은 엔드포인트의 암호학적 매개변수를 포함한다.
클라이언트는 추가 왕복을 감수하고 서버에 그룹 선택을 요청하기
위해 빈 client_shares 벡터를 보낼 수 있다(MAY)(섹션 4.1.4 참조).
struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
group: 교환되는 키의 명명된 그룹.
key_exchange: 키 교환 정보. 이 필드의 내용은 지정된 그룹과 그
대응 정의에 의해 결정된다. 유한체 Diffie-Hellman [DH76]
매개변수는 섹션 4.2.8.1에 설명되어 있고, 타원곡선
Diffie-Hellman 매개변수는 섹션 4.2.8.2에 설명되어 있다.
Rescorla 표준 트랙 [48페이지]
RFC 8446 TLS 2018년 8월
ClientHello 메시지에서 이 확장의 "extension_data" 필드는
"KeyShareClientHello" 값을 포함한다.
struct {
KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;
client_shares: 클라이언트 선호도 내림차순으로 제공되는
KeyShareEntry 값 목록.
클라이언트가 HelloRetryRequest를 요청하는 경우 이 벡터는 비어 있을
수 있다(MAY). 각 KeyShareEntry 값은 "supported_groups" 확장에서
제공된 그룹에 대응해야 하며(MUST), 같은 순서로 나타나야 한다(MUST).
그러나 값은 "supported_groups" 확장의 비연속 부분집합일 수 있고(MAY),
가장 선호하는 그룹을 생략할 수 있다(MAY). 가장 선호하는 그룹이
새롭고 충분한 곳에서 지원될 가능성이 낮아, 해당 그룹에 대한 키
공유를 미리 생성하는 것이 효율적이지 않은 경우 이런 상황이
발생할 수 있다.
클라이언트는 자신이 제공하는 지원 그룹 수만큼 많은 KeyShareEntry
값을 제공할 수 있으며, 각 값은 단일 키 교환 매개변수 집합을
나타낸다. 예를 들어 클라이언트는 여러 타원곡선 또는 여러 FFDHE
그룹에 대한 공유값을 제공할 수 있다. 각 KeyShareEntry의
key_exchange 값은 독립적으로 생성되어야 한다(MUST). 클라이언트는
같은 그룹에 대해 여러 KeyShareEntry 값을 제공해서는 안 된다(MUST NOT).
클라이언트는 클라이언트의 "supported_groups" 확장에 나열되지 않은
그룹에 대해 어떤 KeyShareEntry 값도 제공해서는 안 된다(MUST NOT).
서버는 이러한 규칙 위반을 검사할 수 있으며(MAY), 위반이 있으면
"illegal_parameter" 경고와 함께 핸드셰이크를 중단할 수 있다.
HelloRetryRequest 메시지에서 이 확장의 "extension_data" 필드는
KeyShareHelloRetryRequest 값을 포함한다.
struct {
NamedGroup selected_group;
} KeyShareHelloRetryRequest;
selected_group: 서버가 협상하려고 하며 재시도된 ClientHello/KeyShare를
요청하는 상호 지원 그룹.
HelloRetryRequest에서 이 확장을 수신하면, 클라이언트는 (1)
selected_group 필드가 원래 ClientHello의 "supported_groups" 확장에서
제공된 그룹에 대응하는지, (2) selected_group 필드가 원래
ClientHello의 "key_share" 확장에서 제공된 그룹에 대응하지 않는지
검증해야 한다(MUST). 이 검사 중 하나라도 실패하면, 클라이언트는
"illegal_parameter" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
그렇지 않으면 새 ClientHello를 보낼 때, 클라이언트는 원래
Rescorla 표준 트랙 [49페이지]
RFC 8446 TLS 2018년 8월
"key_share" 확장을 트리거한 HelloRetryRequest의 selected_group 필드에
표시된 그룹에 대한 새 KeyShareEntry 하나만 포함하는 확장으로
대체해야 한다(MUST).
ServerHello 메시지에서 이 확장의 "extension_data" 필드는
KeyShareServerHello 값을 포함한다.
struct {
KeyShareEntry server_share;
} KeyShareServerHello;
server_share: 클라이언트 공유값 중 하나와 같은 그룹에 있는 단일
KeyShareEntry 값.
(EC)DHE 키 설정을 사용하는 경우, 서버는 ServerHello에서 정확히
하나의 KeyShareEntry를 제공한다. 이 값은 협상된 키 교환을 위해
서버가 선택한 클라이언트 제공 KeyShareEntry 값과 같은 그룹에
있어야 한다(MUST). 서버는 클라이언트의 "supported_groups" 확장에
표시되지 않은 어떤 그룹에 대해서도 KeyShareEntry를 보내서는
안 되며(MUST NOT), "psk_ke" PskKeyExchangeMode를 사용할 때는
KeyShareEntry를 보내서는 안 된다(MUST NOT). (EC)DHE 키 설정을
사용하고 "key_share" 확장을 포함하는 HelloRetryRequest가 클라이언트에
의해 수신된 경우, 클라이언트는 ServerHello의 선택된 NamedGroup이
HelloRetryRequest의 것과 같은지 검증해야 한다(MUST). 이 검사가
실패하면, 클라이언트는 "illegal_parameter" 경고와 함께 핸드셰이크를
중단해야 한다(MUST).
4.2.8.1. Diffie-Hellman 매개변수
클라이언트와 서버 모두에 대한 Diffie-Hellman [DH76] 매개변수는
KeyShare 구조의 KeyShareEntry 안 opaque key_exchange 필드에
인코딩된다. opaque 값은 지정된 그룹의 Diffie-Hellman 공개 값
(Y = g^X mod p)을 포함하며([RFC7919]의 그룹 정의 참조), 빅 엔디언
정수로 인코딩되고 p의 바이트 크기까지 왼쪽에 0으로 패딩된다.
참고: 주어진 Diffie-Hellman 그룹에 대해, 패딩은 모든 공개 키가
같은 길이를 가지게 한다.
피어는 1 < Y < p-1임을 보장하여 서로의 공개 키 Y를 검증해야
한다(MUST). 이 검사는 원격 피어가 올바르게 동작하며 로컬 시스템을
작은 부분군으로 강제하지 않는다는 것을 보장한다.
Rescorla 표준 트랙 [50페이지]
RFC 8446 TLS 2018년 8월
4.2.8.2. ECDHE 매개변수
클라이언트와 서버 모두에 대한 ECDHE 매개변수는 KeyShare 구조의
KeyShareEntry 안 opaque key_exchange 필드에 인코딩된다.
secp256r1, secp384r1 및 secp521r1의 경우, 내용은 다음 struct의
직렬화된 값이다.
struct {
uint8 legacy_form = 4;
opaque X[coordinate_length];
opaque Y[coordinate_length];
} UncompressedPointRepresentation;
X와 Y는 각각 네트워크 바이트 순서의 x 및 y 값의 이진 표현이다.
내부 길이 마커는 없으므로, 각 숫자 표현은 곡선 매개변수가
암시하는 만큼의 옥텟을 차지한다. P-256의 경우 이는 X와 Y가 각각
32옥텟을 사용하며, 필요하면 왼쪽에 0으로 패딩됨을 의미한다.
P-384의 경우 각각 48옥텟을 차지한다. P-521의 경우 각각 66옥텟을
차지한다.
secp256r1, secp384r1 및 secp521r1 곡선의 경우, 피어는 포인트가
타원곡선 위의 유효한 포인트인지 보장하여 서로의 공개 값 Q를
검증해야 한다(MUST). 적절한 검증 절차는 [ECDSA]의
섹션 4.3.7 및 대안적으로 [KEYAGREEMENT]의 섹션 5.6.2.3에
정의되어 있다. 이 과정은 세 단계로 구성된다. (1) Q가 무한원점
(O)이 아님을 검증하고, (2) Q = (x, y)에 대해 두 정수 x와 y가
올바른 구간에 있음을 검증하고, (3) (x, y)가 타원곡선 방정식의
올바른 해인지 보장한다. 이 곡선들에 대해 구현자는 올바른
부분군의 구성원인지 검증할 필요가 없다.
X25519와 X448의 경우, 공개 값의 내용은 [RFC7748]에 정의된
대응 함수의 바이트 문자열 입력 및 출력이다. X25519는 32바이트,
X448은 56바이트이다.
참고: TLS 1.3 이전 버전은 포인트 형식 협상을 허용했지만,
TLS 1.3은 각 곡선에 대해 단일 포인트 형식을 사용하는 것을
선호하여 이 기능을 제거한다.
4.2.9. 사전 공유 키 교환 모드
PSK를 사용하기 위해 클라이언트는 "psk_key_exchange_modes" 확장도
보내야 한다(MUST). 이 확장의 의미는 클라이언트가 이 모드들과 함께
PSK 사용만 지원한다는 것으로, 이 ClientHello에서 제공되는 PSK와
서버가 NewSessionTicket을 통해 제공할 수 있는 PSK의 사용을 모두
제한한다.
Rescorla 표준 트랙 [51페이지]
RFC 8446 TLS 2018년 8월
클라이언트는 "pre_shared_key" 확장을 제공하는 경우
"psk_key_exchange_modes" 확장을 제공해야 한다(MUST). 클라이언트가
"psk_key_exchange_modes" 확장 없이 "pre_shared_key"를 제공하면,
서버는 핸드셰이크를 중단해야 한다(MUST). 서버는 클라이언트가
나열하지 않은 키 교환 모드를 선택해서는 안 된다(MUST NOT). 이
확장은 PSK 재개에 사용할 모드도 제한한다. 서버는 광고된 모드와
호환되지 않는 티켓을 포함해 NewSessionTicket을 보내서는 안 된다
(SHOULD NOT). 그러나 서버가 그렇게 하더라도 그 영향은 클라이언트의
재개 시도가 실패하는 것뿐이다.
서버는 "psk_key_exchange_modes" 확장을 보내서는 안 된다(MUST NOT).
enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
struct {
PskKeyExchangeMode ke_modes<1..255>;
} PskKeyExchangeModes;
psk_ke: PSK-only 키 설정. 이 모드에서 서버는 "key_share" 값을
제공해서는 안 된다(MUST NOT).
psk_dhe_ke: (EC)DHE 키 설정을 수반한 PSK. 이 모드에서 클라이언트와
서버는 섹션 4.2.8에 설명된 대로 "key_share" 값을 제공해야
한다(MUST).
향후 할당되는 모든 값은 전송된 프로토콜 메시지가 서버가 어떤
모드를 선택했는지 모호하지 않게 식별하도록 보장해야 한다. 현재는
ServerHello에 "key_share"가 존재하는 것으로 이를 나타낸다.
4.2.10. 조기 데이터 표시
PSK가 사용되고 해당 PSK에 조기 데이터가 허용되는 경우, 클라이언트는
첫 번째 메시지 flight에서 Application Data를 보낼 수 있다. 클라이언트가
그렇게 하기로 선택하면, "pre_shared_key" 및 "early_data" 확장을
모두 제공해야 한다(MUST).
이 확장의 "extension_data" 필드는 "EarlyDataIndication" 값을
포함한다.
Rescorla 표준 트랙 [52페이지]
RFC 8446 TLS 2018년 8월
struct {} Empty;
struct {
select (Handshake.msg_type) {
case new_session_ticket: uint32 max_early_data_size;
case client_hello: Empty;
case encrypted_extensions: Empty;
};
} EarlyDataIndication;
max_early_data_size 필드의 사용에 대한 자세한 내용은
섹션 4.6.1을 참조하라.
0-RTT 데이터의 매개변수(버전, 대칭 암호 스위트,
Application-Layer Protocol Negotiation(ALPN) [RFC7301] 프로토콜 등)는
사용 중인 PSK와 연관된 것이다. 외부에서 제공된 PSK의 경우,
연관된 값은 키와 함께 제공된 값이다. NewSessionTicket 메시지를
통해 설정된 PSK의 경우, 연관된 값은 PSK를 설정한 연결에서
협상된 값이다. 조기 데이터를 암호화하는 데 사용되는 PSK는
클라이언트의 "pre_shared_key" 확장에 나열된 첫 번째 PSK이어야
한다(MUST).
NewSessionTicket을 통해 제공된 PSK의 경우, 서버는 선택된 PSK
식별자의 티켓 나이(PskIdentity.obfuscated_ticket_age에서
ticket_age_add를 빼서 modulo 2^32로 계산)가 티켓 발행 이후 시간의
작은 허용오차 내에 있는지 검증해야 한다(MUST)(섹션 8 참조).
그렇지 않으면 서버는 핸드셰이크를 진행하되 0-RTT를 거부해야 하며
(SHOULD), 이 ClientHello가 신선하다고 가정하는 다른 어떤 조치도
취해서는 안 된다(SHOULD NOT).
첫 번째 flight에서 전송되는 0-RTT 메시지는 다른 flight에서 전송되는
같은 타입의 메시지(handshake 및 application_data)와 동일한
(암호화된) 콘텐츠 타입을 가지지만 다른 키로 보호된다. 서버의
Finished 메시지를 수신한 뒤, 서버가 조기 데이터를 수락했다면,
키 변경을 나타내기 위해 EndOfEarlyData 메시지가 전송된다. 이
메시지는 0-RTT 트래픽 키로 암호화된다.
Rescorla 표준 트랙 [53페이지]
RFC 8446 TLS 2018년 8월
"early_data" 확장을 수신한 서버는 세 가지 방식 중 하나로 동작해야
한다(MUST).
- 확장을 무시하고 일반 1-RTT 응답을 반환한다. 그런 다음 서버는
핸드셰이크 트래픽 키를 사용하여 수신된 레코드의 보호 해제를
시도하고, 보호 해제에 실패하는 레코드를 폐기하여(구성된
max_early_data_size까지) 조기 데이터를 건너뛴다. 레코드가
성공적으로 보호 해제되면, 이는 클라이언트의 두 번째 flight의
시작으로 처리되고 서버는 일반 1-RTT 핸드셰이크처럼 진행한다.
- HelloRetryRequest로 응답하여 클라이언트가 다른 ClientHello를
보내도록 요청한다. 클라이언트는 후속 ClientHello에 "early_data"
확장을 포함해서는 안 된다(MUST NOT). 그런 다음 서버는 구성된
max_early_data_size까지 외부 콘텐츠 타입이 "application_data"인
모든 레코드(암호화되었음을 나타냄)를 건너뛰어 조기 데이터를
무시한다.
- EncryptedExtensions에서 자신의 "early_data" 확장을 반환하여,
조기 데이터를 처리할 의도임을 나타낸다. 서버가 조기 데이터
메시지의 일부만 수락하는 것은 불가능하다. 서버가 조기 데이터를
수락한다는 메시지를 보내더라도, 실제 조기 데이터 자체는 서버가
이 메시지를 생성할 때 이미 전송 중일 수 있다.
조기 데이터를 수락하기 위해 서버는 PSK 암호 스위트를 수락하고
클라이언트의 "pre_shared_key" 확장에서 제공된 첫 번째 키를
선택했어야 한다(MUST). 또한 다음 값들이 선택된 PSK와 연관된
값들과 동일한지 검증해야 한다(MUST).
- TLS 버전 번호
- 선택된 암호 스위트
- 선택된 ALPN [RFC7301] 프로토콜이 있다면 그것
이러한 요구사항은 해당 PSK를 사용하여 1-RTT 핸드셰이크를 수행하는
데 필요한 요구사항의 상위집합이다. 외부에서 설정된 PSK의 경우,
연관된 값은 키와 함께 제공된 값이다. NewSessionTicket 메시지를
통해 설정된 PSK의 경우, 연관된 값은 티켓이 설정된 연결에서
협상된 값이다.
향후 확장은 0-RTT와의 상호작용을 정의해야 한다(MUST).
Rescorla 표준 트랙 [54페이지]
RFC 8446 TLS 2018년 8월
이러한 검사 중 하나라도 실패하면, 서버는 확장으로 응답해서는
안 되며(MUST NOT), 위에 나열된 처음 두 메커니즘 중 하나를 사용하여
모든 첫 번째 flight 데이터를 폐기해야 한다(따라서 1-RTT 또는
2-RTT로 폴백). 클라이언트가 0-RTT 핸드셰이크를 시도하지만 서버가
이를 거부하는 경우, 서버는 일반적으로 0-RTT 레코드 보호 키를
갖지 않으며, 대신 첫 번째 비-0-RTT 메시지를 찾기 위해 시험 복호화
(1-RTT 핸드셰이크 키를 사용하거나 HelloRetryRequest의 경우 평문
ClientHello를 찾음)를 사용해야 한다.
서버가 "early_data" 확장을 수락하기로 선택하면, 조기 데이터
레코드를 처리할 때 모든 레코드에 대해 지정된 동일한 오류 처리
요구사항을 준수해야 한다(MUST). 구체적으로, 서버가 수락된
"early_data" 확장 뒤의 0-RTT 레코드 복호화에 실패하면,
섹션 5.2에 따라 "bad_record_mac" 경고와 함께 연결을
종료해야 한다(MUST).
서버가 "early_data" 확장을 거부하면, 클라이언트 애플리케이션은
핸드셰이크가 완료된 뒤 조기 데이터로 이전에 보낸 Application
Data를 재전송하도록 선택할 수 있다(MAY). 조기 데이터의 자동
재전송은 연결 상태에 관한 잘못된 가정을 초래할 수 있음에
유의하라. 예를 들어 협상된 연결이 조기 데이터에 사용된 것과
다른 ALPN 프로토콜을 선택하면, 애플리케이션은 다른 메시지를
구성해야 할 수 있다. 마찬가지로 조기 데이터가 연결 상태에 관해
어떤 가정을 한다면, 핸드셰이크가 완료된 뒤 오류로 전송될 수 있다.
TLS 구현은 조기 데이터를 자동으로 다시 보내서는 안 된다(SHOULD NOT).
애플리케이션이 언제 재전송이 적절한지 결정하기에 더 나은 위치에
있다. TLS 구현은 협상된 연결이 같은 ALPN 프로토콜을 선택하지 않는
한 조기 데이터를 자동으로 다시 보내서는 안 된다(MUST NOT).
4.2.11. 사전 공유 키 확장
"pre_shared_key" 확장은 PSK 키 설정과 관련하여 주어진 핸드셰이크에
사용할 사전 공유 키의 식별자를 협상하는 데 사용된다.
Rescorla 표준 트랙 [55페이지]
RFC 8446 TLS 2018년 8월
이 확장의 "extension_data" 필드는 "PreSharedKeyExtension" 값을
포함한다.
struct {
opaque identity<1..2^16-1>;
uint32 obfuscated_ticket_age;
} PskIdentity;
opaque PskBinderEntry<32..255>;
struct {
PskIdentity identities<7..2^16-1>;
PskBinderEntry binders<33..2^16-1>;
} OfferedPsks;
struct {
select (Handshake.msg_type) {
case client_hello: OfferedPsks;
case server_hello: uint16 selected_identity;
};
} PreSharedKeyExtension;
identity: 키에 대한 레이블. 예를 들어 부록 B.3.4에 정의된
티켓 또는 외부에서 설정된 사전 공유 키에 대한 레이블.
obfuscated_ticket_age: 키 나이의 난독화된 버전.
섹션 4.2.11.1은 NewSessionTicket 메시지를 통해 설정된
식별자에 대해 이 값을 형성하는 방법을 설명한다. 외부에서 설정된
식별자의 경우 obfuscated_ticket_age 0을 사용해야 하며(SHOULD),
서버는 이 값을 무시해야 한다(MUST).
identities: 클라이언트가 서버와 협상할 의향이 있는 식별자 목록.
"early_data" 확장(섹션 4.2.10 참조)과 함께 전송되는 경우,
첫 번째 식별자는 0-RTT 데이터에 사용되는 것이다.
binders: identities 목록의 각 값에 대해, 같은 순서로 아래에
설명된 대로 계산된 HMAC 값의 시리즈.
selected_identity: 클라이언트 목록의 identities에 대한 (0 기반)
인덱스로 표현된 서버가 선택한 식별자.
각 PSK는 단일 Hash 알고리즘과 연관된다. 티켓 메커니즘
(섹션 4.6.1)을 통해 설정된 PSK의 경우, 이는 티켓이 설정된
연결의 KDF Hash 알고리즘이다. 외부에서 설정된 PSK의 경우, PSK가
Rescorla 표준 트랙 [56페이지]
RFC 8446 TLS 2018년 8월
설정될 때 Hash 알고리즘이 설정되어야 하며(MUST), 그러한 알고리즘이
정의되지 않은 경우 SHA-256을 기본값으로 한다. 서버는 호환되는 PSK
(있는 경우)와 암호 스위트를 선택하도록 보장해야 한다(MUST).
TLS 1.3 이전의 TLS 버전에서 Server Name Identification(SNI) 값은
세션과 연관되도록 의도되었으며([RFC6066]의 섹션 3), 서버는
세션과 연관된 SNI 값이 재개 핸드셰이크에서 지정된 것과 일치함을
강제해야 했다. 그러나 실제 구현은 제공된 두 SNI 값 중 어느 것을
사용할지 일관되지 않았고, 그 결과 일관성 요구사항은 사실상
클라이언트에 의해 강제되었다. TLS 1.3에서 SNI 값은 재개
핸드셰이크에서 항상 명시적으로 지정되며, 서버가 SNI 값을 티켓과
연관시킬 필요가 없다. 그러나 클라이언트는 섹션 4.6.1의
요구사항을 충족하기 위해 SNI를 PSK와 함께 저장해야 한다(SHOULD).
구현자 참고: 세션 재개가 PSK의 주된 사용 사례인 경우,
PSK/암호 스위트 일치 요구사항을 구현하는 가장 직접적인 방법은
먼저 암호 스위트를 협상한 다음 호환되지 않는 PSK를 제외하는 것이다.
알 수 없는 PSK(예: PSK 데이터베이스에 없거나 알 수 없는 키로
암호화된 것)는 단순히 무시해야 한다(SHOULD). 허용 가능한 PSK가
발견되지 않으면 서버는 가능하다면 비-PSK 핸드셰이크를 수행해야
한다(SHOULD). 하위 호환성이 중요하다면, 클라이언트가 제공한 외부
설정 PSK가 암호 스위트 선택에 영향을 주어야 한다(SHOULD).
PSK 키 설정을 수락하기 전에 서버는 대응하는 binder 값을 검증해야
한다(MUST)(아래 섹션 4.2.11.2 참조). 이 값이 존재하지 않거나
검증되지 않으면, 서버는 핸드셰이크를 중단해야 한다(MUST). 서버는
여러 binder 검증을 시도해서는 안 되며(SHOULD NOT), 대신 단일 PSK를
선택하고 해당 PSK에 대응하는 binder만 검증해야 한다(SHOULD). 이
요구사항의 보안 근거는 섹션 8.2 및 부록 E.6을 참조하라.
PSK 키 설정을 수락하기 위해 서버는 선택된 식별자를 나타내는
"pre_shared_key" 확장을 보낸다.
클라이언트는 서버의 selected_identity가 클라이언트가 제공한 범위
내에 있는지, 서버가 PSK와 연관된 Hash를 나타내는 암호 스위트를
선택했는지, 그리고 ClientHello "psk_key_exchange_modes" 확장에서
요구하는 경우 서버 "key_share" 확장이 존재하는지 검증해야 한다(MUST).
이 값들이 일관되지 않으면 클라이언트는 "illegal_parameter" 경고와
함께 핸드셰이크를 중단해야 한다(MUST).
Rescorla 표준 트랙 [57페이지]
RFC 8446 TLS 2018년 8월
서버가 "early_data" 확장을 제공하면, 클라이언트는 서버의
selected_identity가 0인지 검증해야 한다(MUST). 다른 값이 반환되면,
클라이언트는 "illegal_parameter" 경고와 함께 핸드셰이크를 중단해야
한다(MUST).
"pre_shared_key" 확장은 ClientHello의 마지막 확장이어야 한다(MUST)
(이는 아래 설명된 것처럼 구현을 용이하게 한다). 서버는 이것이
마지막 확장인지 검사해야 하며(MUST), 그렇지 않으면
"illegal_parameter" 경고와 함께 핸드셰이크에 실패해야 한다.
4.2.11.1. 티켓 나이
티켓 나이에 대한 클라이언트의 관점은 NewSessionTicket 메시지를
수신한 이후의 시간이다. 클라이언트는 티켓과 함께 제공된
"ticket_lifetime" 값보다 나이가 큰 티켓을 사용하려고 시도해서는
안 된다(MUST NOT). 각 PskIdentity의 "obfuscated_ticket_age" 필드는
밀리초 단위 나이에 티켓과 함께 포함된 "ticket_age_add" 값
(섹션 4.6.1 참조)을 더하고 modulo 2^32를 취해 형성된 티켓
나이의 난독화된 버전을 포함한다. 이 더하기는 티켓이 재사용되지
않는 한 수동 관찰자가 연결을 상관시키는 것을 방지한다.
NewSessionTicket 메시지의 "ticket_lifetime" 필드는 초 단위이지만
"obfuscated_ticket_age"는 밀리초 단위라는 점에 유의하라. 티켓
수명은 일주일로 제한되므로, 32비트는 밀리초 단위에서도 가능한
모든 나이를 표현하기에 충분하다.
4.2.11.2. PSK 바인더
PSK binder 값은 PSK와 현재 핸드셰이크 사이의 결속을 형성하며,
PSK가 생성된 핸드셰이크(NewSessionTicket 메시지를 통해 생성된
경우)와 현재 핸드셰이크 사이의 결속도 형성한다. binders 목록의
각 항목은 PreSharedKeyExtension.identities 필드까지 포함하는 부분
ClientHello를 포함한 transcript hash(섹션 4.4.1 참조)에 대한
HMAC으로 계산된다. 즉, ClientHello 전체를 포함하지만 binders 목록
자체는 포함하지 않는다. 메시지의 길이 필드(전체 길이, 확장 블록
길이, "pre_shared_key" 확장 길이 포함)는 모두 올바른 길이의
binder가 존재하는 것처럼 설정된다.
PskBinderEntry는 Finished 메시지(섹션 4.4.4)와 같은 방식으로
계산되지만, BaseKey는 제공 중인 대응 PSK로부터 키 스케줄을 통해
파생된 binder_key이다(섹션 7.1 참조).
Rescorla 표준 트랙 [58페이지]
RFC 8446 TLS 2018년 8월
핸드셰이크가 HelloRetryRequest를 포함하면, 초기 ClientHello와
HelloRetryRequest는 새 ClientHello와 함께 전사에 포함된다. 예를
들어 클라이언트가 ClientHello1을 보내면, 그 binder는 다음에 대해
계산된다.
Transcript-Hash(Truncate(ClientHello1))
여기서 Truncate()는 ClientHello에서 binders 목록을 제거한다.
서버가 HelloRetryRequest로 응답하고 클라이언트가 ClientHello2를
보내면, 그 binder는 다음에 대해 계산된다.
Transcript-Hash(ClientHello1,
HelloRetryRequest,
Truncate(ClientHello2))
전체 ClientHello1/ClientHello2는 다른 모든 핸드셰이크 해시 계산에
포함된다. 첫 번째 flight에서는 Truncate(ClientHello1)가 직접
해시되지만, 두 번째 flight에서는 섹션 4.4.1에 설명된 대로
ClientHello1이 해시된 뒤 "message_hash" 메시지로 다시 주입된다는
점에 유의하라.
4.2.11.3. 처리 순서
클라이언트는 서버의 Finished를 수신할 때까지 0-RTT 데이터를
"스트리밍"할 수 있으며, 그때에만 EndOfEarlyData 메시지를 보낸 뒤
핸드셰이크의 나머지를 보낸다. 교착 상태를 피하기 위해,
"early_data"를 수락할 때 서버는 클라이언트의 EndOfEarlyData 메시지를
기다린 뒤 ServerHello를 보내는 것이 아니라, 클라이언트의
ClientHello를 처리한 다음 즉시 자신의 메시지 flight를 보내야
한다(MUST).
4.3. 서버 매개변수
서버의 다음 두 메시지인 EncryptedExtensions와 CertificateRequest는
핸드셰이크의 나머지를 결정하는 서버의 정보를 포함한다. 이
메시지들은 server_handshake_traffic_secret에서 파생된 키로
암호화된다.
Rescorla 표준 트랙 [59페이지]
RFC 8446 TLS 2018년 8월
4.3.1. 암호화된 확장
모든 핸드셰이크에서 서버는 ServerHello 메시지 직후
EncryptedExtensions 메시지를 보내야 한다(MUST). 이는
server_handshake_traffic_secret에서 파생된 키로 암호화되는 첫
번째 메시지이다.
EncryptedExtensions 메시지는 보호될 수 있는 확장, 즉 암호학적
컨텍스트 설정에는 필요하지 않지만 개별 인증서와 연관되지 않은
확장을 포함한다. 클라이언트는 EncryptedExtensions에서 금지된
확장이 존재하는지 검사해야 하며(MUST), 발견되면
"illegal_parameter" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
이 메시지의 구조:
struct {
Extension extensions<0..2^16-1>;
} EncryptedExtensions;
extensions: 확장 목록. 자세한 내용은 섹션 4.2의 표를
참조하라.
4.3.2. 인증서 요청
인증서로 인증하는 서버는 선택적으로 클라이언트에게 인증서를
요청할 수 있다(MAY). 이 메시지는 전송되는 경우
EncryptedExtensions 뒤에 와야 한다(MUST).
이 메시지의 구조:
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
Rescorla 표준 트랙 [60페이지]
RFC 8446 TLS 2018년 8월
certificate_request_context: 인증서 요청을 식별하며 클라이언트의
Certificate 메시지에서 에코될 opaque 문자열. certificate_request_context는
이 연결의 범위 내에서 고유해야 한다(MUST)(따라서 클라이언트
CertificateVerify 메시지의 재생을 방지). 이 필드는 섹션 4.6.2에
설명된 핸드셰이크 후 인증 교환에 사용되지 않는 한 길이가 0이어야
한다(SHALL). 핸드셰이크 후 인증을 요청할 때, 서버는 클라이언트의
개인 키에 일시적으로 접근한 공격자가 유효한 CertificateVerify
메시지를 미리 계산하지 못하도록 컨텍스트를 클라이언트가 예측할
수 없게 만들어야 한다(SHOULD)(예: 무작위 생성).
extensions: 요청되는 인증서의 매개변수를 설명하는 확장 집합.
"signature_algorithms" 확장은 지정되어야 하며(MUST), 이 메시지에
대해 정의된 경우 다른 확장도 선택적으로 포함될 수 있다.
클라이언트는 인식하지 못하는 확장을 무시해야 한다(MUST).
이전 TLS 버전에서 CertificateRequest 메시지는 서버가 수락할 서명
알고리즘 및 인증서 기관 목록을 전달했다. TLS 1.3에서 전자는
"signature_algorithms" 및 선택적으로 "signature_algorithms_cert"
확장을 보내 표현된다. 후자는 "certificate_authorities" 확장을
보내 표현된다(섹션 4.2.4 참조).
PSK로 인증하는 서버는 주 핸드셰이크에서 CertificateRequest 메시지를
보내서는 안 되지만(MUST NOT), 클라이언트가 "post_handshake_auth"
확장(섹션 4.2.6 참조)을 보낸 경우, 핸드셰이크 후 인증
(섹션 4.6.2 참조)에서 이를 보낼 수 있다(MAY).
4.4. 인증 메시지
섹션 2에서 논의한 것처럼, TLS는 일반적으로 인증, 키 확인 및
핸드셰이크 무결성을 위해 공통 메시지 집합인 Certificate,
CertificateVerify 및 Finished를 사용한다. (PSK binder도 유사한
방식으로 키 확인을 수행한다.) 이 세 메시지는 항상 각 핸드셰이크
flight의 마지막 메시지로 전송된다. Certificate 및 CertificateVerify
메시지는 아래 정의된 특정 상황에서만 전송된다. Finished 메시지는
항상 Authentication Block의 일부로 전송된다. 이 메시지들은
[sender]_handshake_traffic_secret에서 파생된 키로 암호화된다.
Rescorla 표준 트랙 [61페이지]
RFC 8446 TLS 2018년 8월
Authentication 메시지에 대한 계산은 모두 동일하게 다음 입력을
받는다.
- 사용할 인증서와 서명 키.
- transcript hash에 포함될 메시지 집합으로 구성된 Handshake Context.
- MAC 키를 계산하는 데 사용할 Base Key.
이 입력에 기반하여 메시지들은 다음을 포함한다.
Certificate: 인증에 사용할 인증서 및 체인 내 모든 지원 인증서.
인증서 기반 클라이언트 인증은 PSK 핸드셰이크 흐름(0-RTT 포함)
에서 사용할 수 없다는 점에 유의하라.
CertificateVerify: Transcript-Hash(Handshake Context, Certificate)
값에 대한 서명.
Finished: Base Key에서 파생된 MAC 키를 사용하여
Transcript-Hash(Handshake Context, Certificate, CertificateVerify)
값에 대해 계산한 MAC.
다음 표는 각 시나리오에 대한 Handshake Context 및 MAC Base Key를
정의한다.
+-----------+-------------------------+-----------------------------+
| 모드 | Handshake Context | Base Key |
+-----------+-------------------------+-----------------------------+
| Server | ClientHello ... later | server_handshake_traffic_ |
| | of EncryptedExtensions/ | secret |
| | CertificateRequest | |
| | | |
| Client | ClientHello ... later | client_handshake_traffic_ |
| | of server | secret |
| | Finished/EndOfEarlyData | |
| | | |
| Post- | ClientHello ... client | client_application_traffic_ |
| Handshake | Finished + | secret_N |
| | CertificateRequest | |
+-----------+-------------------------+-----------------------------+
Rescorla 표준 트랙 [62페이지]
RFC 8446 TLS 2018년 8월
4.4.1. 전사 해시
TLS의 많은 암호학적 계산은 transcript hash를 사용한다. 이 값은
포함된 각 핸드셰이크 메시지의 연결을 해시하여 계산된다. 여기에는
핸드셰이크 메시지 타입 및 길이 필드를 담는 핸드셰이크 메시지
헤더가 포함되지만 레코드 계층 헤더는 포함되지 않는다. 즉,
Transcript-Hash(M1, M2, ... Mn) = Hash(M1 || M2 || ... || Mn)
이 일반 규칙의 예외로, 서버가 ClientHello에 HelloRetryRequest로
응답할 때 ClientHello1의 값은 Hash(ClientHello1)을 포함하는
"message_hash" 핸드셰이크 타입의 특수 합성 핸드셰이크 메시지로
대체된다. 즉,
Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) =
Hash(message_hash || /* 핸드셰이크 타입 */
00 00 Hash.length || /* 핸드셰이크 메시지 길이(바이트) */
Hash(ClientHello1) || /* ClientHello1의 해시 */
HelloRetryRequest || ... || Mn)
이 구성의 이유는 서버가 전체 중간 해시 상태를 내보내야 하는 대신
ClientHello1의 해시만 쿠키에 저장함으로써 상태 없는
HelloRetryRequest를 수행할 수 있게 하기 위함이다(섹션 4.2.2
참조).
구체적으로, transcript hash는 항상 첫 번째 ClientHello에서 시작하고
전송된 메시지만 포함하는 다음 핸드셰이크 메시지 시퀀스에서
취한다. ClientHello, HelloRetryRequest, ClientHello, ServerHello,
EncryptedExtensions, server CertificateRequest, server Certificate,
server CertificateVerify, server Finished, EndOfEarlyData, client
Certificate, client CertificateVerify, client Finished.
일반적으로 구현은 협상된 해시에 기반해 실행 중인 transcript hash
값을 유지함으로써 전사를 구현할 수 있다. 그러나 이후의
핸드셰이크 후 인증들은 서로를 포함하지 않으며, 주 핸드셰이크의
끝까지의 메시지만 포함한다는 점에 유의하라.
Rescorla 표준 트랙 [63페이지]
RFC 8446 TLS 2018년 8월
4.4.2. 인증서
이 메시지는 엔드포인트의 인증서 체인을 피어에게 전달한다.
합의된 키 교환 방법이 인증에 인증서를 사용하는 경우, 서버는
Certificate 메시지를 보내야 한다(MUST)(PSK를 제외한 이 문서에
정의된 모든 키 교환 방법 포함).
클라이언트는 서버가 CertificateRequest 메시지(섹션 4.3.2)를
통해 클라이언트 인증을 요청한 경우에만, 그리고 그 경우에만
Certificate 메시지를 보내야 한다(MUST). 서버가 클라이언트 인증을
요청했지만 적합한 인증서가 없는 경우, 클라이언트는 인증서를
포함하지 않는 Certificate 메시지(즉, "certificate_list" 필드의
길이가 0인 메시지)를 보내야 한다(MUST). Certificate 메시지가 비어
있는지 여부와 관계없이 Finished 메시지는 전송되어야 한다(MUST).
이 메시지의 구조:
enum {
X509(0),
RawPublicKey(2),
(255)
} CertificateType;
struct {
select (certificate_type) {
case RawPublicKey:
/* RFC 7250 ASN.1_subjectPublicKeyInfo에서 옴 */
opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
case X509:
opaque cert_data<1..2^24-1>;
};
Extension extensions<0..2^16-1>;
} CertificateEntry;
struct {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>;
} Certificate;
Rescorla 표준 트랙 [64페이지]
RFC 8446 TLS 2018년 8월
certificate_request_context: 이 메시지가 CertificateRequest에 대한
응답인 경우, 해당 메시지의 certificate_request_context 값. 그렇지
않은 경우(서버 인증의 경우), 이 필드는 길이가 0이어야 한다(SHALL).
certificate_list: CertificateEntry 구조의 시퀀스(체인)로, 각각
단일 인증서와 확장 집합을 포함한다.
extensions: CertificateEntry에 대한 확장 값 집합. "Extension"
형식은 섹션 4.2에 정의되어 있다. 현재 서버 인증서에 대한
유효한 확장에는 OCSP Status 확장 [RFC6066] 및
SignedCertificateTimestamp 확장 [RFC6962]이 포함된다. 향후 이
메시지에 대한 확장이 정의될 수도 있다. 서버의 Certificate
메시지에 있는 확장은 ClientHello 메시지의 확장에 대응해야
한다(MUST). 클라이언트의 Certificate 메시지에 있는 확장은 서버의
CertificateRequest 메시지의 확장에 대응해야 한다(MUST). 확장이
전체 체인에 적용되는 경우, 첫 번째 CertificateEntry에 포함되어야
한다(SHOULD).
대응하는 인증서 타입 확장("server_certificate_type" 또는
"client_certificate_type")이 EncryptedExtensions에서 협상되지
않았거나 X.509 인증서 타입이 협상된 경우, 각 CertificateEntry는
DER 인코딩된 X.509 인증서를 포함한다. 송신자의 인증서는 목록의
첫 번째 CertificateEntry에 와야 한다(MUST). 그 뒤의 각 인증서는
바로 앞의 인증서를 직접 인증해야 한다(SHOULD). 인증서 검증에는
신뢰 앵커가 독립적으로 배포되어야 하므로, 지원되는 피어가 생략된
인증서를 보유한 것으로 알려진 경우, 신뢰 앵커를 지정하는 인증서는
체인에서 생략될 수 있다(MAY).
참고: TLS 1.3 이전에는 "certificate_list" 순서가 각 인증서가 바로
앞의 인증서를 인증할 것을 요구했다. 그러나 일부 구현은 어느 정도
유연성을 허용했다. 서버는 전환 목적을 위해 현재 중간 인증서와
폐기 예정 중간 인증서를 모두 보내기도 하고, 단순히 잘못 구성된
경우도 있지만, 이러한 경우도 적절히 검증될 수 있다. 최대 호환성을
위해 모든 구현은 모든 TLS 버전에서 잠재적으로 불필요한 인증서와
임의의 순서를 처리할 준비가 되어 있어야 한다(SHOULD). 단, 최종
엔터티 인증서는 반드시 첫 번째여야 한다(MUST).
RawPublicKey 인증서 타입이 협상된 경우, certificate_list는
[RFC7250], 섹션 3에 정의된 ASN1_subjectPublicKeyInfo 값을
포함하는 CertificateEntry를 하나 이하로 포함해야 한다(MUST).
Rescorla 표준 트랙 [65페이지]
RFC 8446 TLS 2018년 8월
OpenPGP 인증서 타입 [RFC6091]은 TLS 1.3과 함께 사용되어서는 안 된다(MUST NOT).
서버의 certificate_list는 항상 비어 있지 않아야 한다(MUST). 클라이언트는
서버의 인증 요청에 대한 응답으로 보낼 적절한 인증서가 없는 경우
빈 certificate_list를 보낸다.
4.4.2.1. OCSP 상태 및 SCT 확장
[RFC6066] 및 [RFC6961]은 서버가 클라이언트에 OCSP 응답을 보내는
것을 협상하기 위한 확장을 제공한다. TLS 1.2 이하에서 서버는 이
확장의 협상을 나타내기 위해 빈 확장으로 응답하고 OCSP 정보는
CertificateStatus 메시지에 담긴다. TLS 1.3에서 서버의 OCSP 정보는
연관된 인증서를 포함하는 CertificateEntry의 확장에 담긴다.
구체적으로, 서버의 "status_request" 확장의 본문은 [RFC6066]에
정의된 CertificateStatus 구조여야 하며(MUST), [RFC6960]에
정의된 대로 해석된다.
참고: status_request_v2 확장 [RFC6961]은 폐기 예정이다. TLS 1.3 서버는
ClientHello 메시지를 처리할 때 그 존재나 그 안의 정보에 따라
동작해서는 안 된다(MUST NOT). 특히 EncryptedExtensions,
CertificateRequest 또는 Certificate 메시지에서 status_request_v2
확장을 보내서는 안 된다(MUST NOT). TLS 1.3 서버는 이전 프로토콜
버전에서 이를 사용하려는 클라이언트가 보낼 수 있으므로(MAY), 이를
포함하는 ClientHello 메시지를 처리할 수 있어야 한다(MUST).
서버는 CertificateRequest 메시지에서 빈 "status_request" 확장을
보내 클라이언트가 자신의 인증서와 함께 OCSP 응답을 제시하도록
요청할 수 있다(MAY). 클라이언트가 OCSP 응답을 보내기로 선택하면,
그 "status_request" 확장의 본문은 [RFC6066]에 정의된
CertificateStatus 구조여야 한다(MUST).
마찬가지로, [RFC6962]는 서버가 TLS 1.2 이하에서 ServerHello의
확장으로 Signed Certificate Timestamp(SCT)를 보낼 수 있는
메커니즘을 제공한다. TLS 1.3에서 서버의 SCT 정보는 CertificateEntry의
확장에 담긴다.
Rescorla 표준 트랙 [66페이지]
RFC 8446 TLS 2018년 8월
4.4.2.2. 서버 인증서 선택
서버가 보내는 인증서에는 다음 규칙이 적용된다.
- 명시적으로 달리 협상되지 않은 한(예: [RFC7250]), 인증서 타입은
X.509v3 [RFC5280]이어야 한다(MUST).
- 서버의 최종 엔터티 인증서의 공개 키(및 연관된 제한)는 클라이언트의
"signature_algorithms" 확장에서 선택된 인증 알고리즘(현재 RSA,
ECDSA 또는 EdDSA)과 호환되어야 한다(MUST).
- 인증서는 클라이언트의 "signature_algorithms"/
"signature_algorithms_cert" 확장(섹션 4.2.3 참조)에 표시된
서명 방식으로 키를 서명에 사용할 수 있도록 허용해야 한다(MUST)
(즉, Key Usage 확장이 존재하면 digitalSignature 비트가 설정되어야
함(MUST)).
- "server_name" [RFC6066] 및 "certificate_authorities" 확장은 인증서
선택을 안내하는 데 사용된다. 서버가 "server_name" 확장의 존재를
요구할 수 있으므로(MAY), 클라이언트는 적용 가능한 경우 이
확장을 보내야 한다(SHOULD).
서버가 제공하는 모든 인증서는, 그러한 체인을 제공할 수 있다면,
클라이언트가 광고한 서명 알고리즘으로 서명되어야 한다(MUST)
(섹션 4.2.3 참조). 자체 서명된 인증서 또는 신뢰 앵커일 것으로
예상되는 인증서는 체인의 일부로 검증되지 않으므로 어떤 알고리즘으로
서명되어도 된다(MAY).
서버가 표시된 지원 알고리즘만으로 서명된 인증서 체인을 생성할 수
없다면, 서버는 클라이언트가 지원하는 것으로 알려지지 않은 알고리즘을
포함할 수 있는 임의의 인증서 체인을 클라이언트에 보내 핸드셰이크를
계속해야 한다(SHOULD). 이 폴백 체인은 일반적으로 폐기 예정인 SHA-1
해시 알고리즘을 사용해서는 안 되지만(SHOULD NOT), 클라이언트의
광고가 허용하면 그렇게 할 수 있으며(MAY), 그렇지 않으면 그렇게
해서는 안 된다(MUST NOT).
클라이언트가 제공된 인증서를 사용하여 허용 가능한 체인을 구성할
수 없고 핸드셰이크를 중단하기로 결정하면, 적절한 인증서 관련
경고(기본적으로 "unsupported_certificate", 자세한 내용은
섹션 6.2 참조)와 함께 핸드셰이크를 중단해야 한다(MUST).
서버가 여러 인증서를 가진 경우, 위에서 언급한 기준(전송 계층
엔드포인트, 로컬 구성, 선호도 같은 다른 기준에 더하여)에 기반해
그중 하나를 선택한다.
Rescorla 표준 트랙 [67페이지]
RFC 8446 TLS 2018년 8월
4.4.2.3. 클라이언트 인증서 선택
클라이언트가 보내는 인증서에는 다음 규칙이 적용된다.
- 명시적으로 달리 협상되지 않은 한(예: [RFC7250]), 인증서 타입은
X.509v3 [RFC5280]이어야 한다(MUST).
- CertificateRequest 메시지에 "certificate_authorities" 확장이
존재했다면, 인증서 체인 내 인증서 중 적어도 하나는 나열된 CA 중
하나가 발행한 것이어야 한다(SHOULD).
- 인증서는 섹션 4.3.2에 설명된 대로 허용 가능한 서명 알고리즘을
사용해 서명되어야 한다(MUST). 이는 이전 TLS 버전에서 발견되는
인증서 서명 알고리즘에 대한 제약을 완화한다는 점에 유의하라.
- CertificateRequest 메시지가 비어 있지 않은 "oid_filters" 확장을
포함했다면, 최종 엔터티 인증서는 섹션 4.2.5에 설명된 대로
클라이언트가 인식하는 확장 OID와 일치해야 한다(MUST).
4.4.2.4. Certificate 메시지 수신
일반적으로 상세한 인증서 검증 절차는 TLS의 범위를 벗어난다
([RFC5280] 참조). 이 섹션은 TLS에 특화된 요구사항을 제공한다.
서버가 빈 Certificate 메시지를 제공하면, 클라이언트는
"decode_error" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
클라이언트가 어떤 인증서도 보내지 않는 경우(즉, 빈 Certificate
메시지를 보내는 경우), 서버는 재량에 따라 클라이언트 인증 없이
핸드셰이크를 계속하거나 "certificate_required" 경고와 함께
핸드셰이크를 중단할 수 있다(MAY). 또한 인증서 체인의 어떤 측면이
허용 불가능한 경우(예: 알려진 신뢰된 CA가 서명하지 않은 경우),
서버는 재량에 따라 핸드셰이크를 계속하거나(클라이언트를 인증되지
않은 것으로 간주) 핸드셰이크를 중단할 수 있다(MAY).
MD5 해시를 사용하는 서명 알고리즘으로 검증해야 하는 인증서를
수신한 모든 엔드포인트는 "bad_certificate" 경고와 함께
핸드셰이크를 중단해야 한다(MUST). SHA-1은 폐기 예정이며, SHA-1
해시를 사용하는 서명 알고리즘으로 검증해야 하는 인증서를 수신한
모든 엔드포인트는 "bad_certificate" 경고와 함께 핸드셰이크를
중단하는 것이 권장된다(RECOMMENDED). 명확히 하자면, 이는 엔드포인트가
자체 서명된 인증서 또는 신뢰 앵커인 인증서에 대해서는 이러한
알고리즘을 수락할 수 있음을 의미한다.
Rescorla 표준 트랙 [68페이지]
RFC 8446 TLS 2018년 8월
현재 SHA-1 지원을 단계적으로 제거하는 과정에 있는 구현과의 상호
운용성을 유지하기 위해, 모든 엔드포인트가 가능한 한 빨리 SHA-256
이상으로 전환하는 것이 권장된다(RECOMMENDED).
한 서명 알고리즘용 키를 포함하는 인증서가 다른 서명 알고리즘으로
서명될 수 있음에 유의하라(예: ECDSA 키로 서명된 RSA 키).
4.4.3. 인증서 검증
이 메시지는 엔드포인트가 자신의 인증서에 대응하는 개인 키를
보유하고 있음을 명시적으로 증명하는 데 사용된다. CertificateVerify
메시지는 또한 이 시점까지의 핸드셰이크에 대한 무결성을 제공한다.
서버는 인증서를 통해 인증할 때 이 메시지를 보내야 한다(MUST).
클라이언트는 인증서를 통해 인증할 때마다(즉, Certificate 메시지가
비어 있지 않을 때) 이 메시지를 보내야 한다(MUST). 전송되는 경우,
이 메시지는 Certificate 메시지 바로 뒤와 Finished 메시지 바로 앞에
나타나야 한다(MUST).
이 메시지의 구조:
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
algorithm 필드는 사용된 서명 알고리즘을 지정한다(이 타입의 정의는
섹션 4.2.3 참조). signature는 해당 알고리즘을 사용하는 디지털
서명이다. 서명이 적용되는 내용은 섹션 4.4.1에 설명된 해시
출력, 즉 다음이다.
Transcript-Hash(Handshake Context, Certificate)
그런 다음 디지털 서명은 다음의 연결에 대해 계산된다.
- 옥텟 32(0x20)가 64번 반복된 문자열
- 컨텍스트 문자열
- 구분자 역할을 하는 단일 0 바이트
- 서명할 내용
Rescorla 표준 트랙 [69페이지]
RFC 8446 TLS 2018년 8월
이 구조는 ServerKeyExchange 형식 때문에 공격자가 선택한 32바이트
접두사(ClientHello.random)를 가진 메시지의 서명을 얻을 수 있었던
이전 TLS 버전에 대한 공격을 방지하기 위한 것이다. 초기 64바이트
패드는 그 접두사와 서버가 제어하는 ServerHello.random을 함께
지운다.
서버 서명의 컨텍스트 문자열은
"TLS 1.3, server CertificateVerify"이다. 클라이언트 서명의 컨텍스트
문자열은 "TLS 1.3, client CertificateVerify"이다. 이는 서로 다른
컨텍스트에서 만들어진 서명 간 분리를 제공하여 잠재적 교차
프로토콜 공격을 방지하는 데 도움을 준다.
예를 들어 transcript hash가 01의 32바이트였다면(이 길이는
SHA-256에 적합함), 서버 CertificateVerify의 디지털 서명이 적용되는
내용은 다음과 같다.
2020202020202020202020202020202020202020202020202020202020202020
2020202020202020202020202020202020202020202020202020202020202020
544c5320312e332c207365727665722043657274696669636174655665726966
79
00
0101010101010101010101010101010101010101010101010101010101010101
송신자 측에서 CertificateVerify 메시지의 signature 필드를 계산하는
과정은 다음을 입력으로 받는다.
- 디지털 서명이 적용되는 내용
- 이전 메시지에서 전송된 인증서에 대응하는 개인 서명 키
CertificateVerify 메시지가 서버에 의해 전송되는 경우, 유효한
인증서 체인을 지원되지 않는 알고리즘 없이 생성할 수 없는 경우를
제외하고(섹션 4.2.3 참조), 서명 알고리즘은 클라이언트의
"signature_algorithms" 확장에서 제공된 것 중 하나여야 한다(MUST).
클라이언트에 의해 전송되는 경우, 서명에 사용되는 서명 알고리즘은
CertificateRequest 메시지의 "signature_algorithms" 확장의
supported_signature_algorithms 필드에 존재하는 것 중 하나여야
한다(MUST).
또한 서명 알고리즘은 송신자의 최종 엔터티 인증서 안의 키와
호환되어야 한다(MUST). RSA 서명은 "signature_algorithms"에
RSASSA-PKCS1-v1_5 알고리즘이 나타나는지 여부와 관계없이
RSASSA-PSS 알고리즘을 사용해야 한다(MUST). SHA-1 알고리즘은
CertificateVerify 메시지의 어떤 서명에도 사용되어서는 안 된다(MUST NOT).
Rescorla 표준 트랙 [70페이지]
RFC 8446 TLS 2018년 8월
이 명세의 모든 SHA-1 서명 알고리즘은 오직 레거시 인증서에서
사용하도록 정의되며 CertificateVerify 서명에는 유효하지 않다.
CertificateVerify 메시지의 수신자는 signature 필드를 검증해야
한다(MUST). 검증 과정은 다음을 입력으로 받는다.
- 디지털 서명이 적용되는 내용
- 연관된 Certificate 메시지에서 발견된 최종 엔터티 인증서에
포함된 공개 키
- CertificateVerify 메시지의 signature 필드에서 수신된 디지털 서명
검증이 실패하면, 수신자는 "decrypt_error" 경고와 함께 핸드셰이크를
종료해야 한다(MUST).
4.4.4. Finished
Finished 메시지는 Authentication Block의 최종 메시지이다. 이는
핸드셰이크 및 계산된 키의 인증을 제공하는 데 필수적이다.
Finished 메시지의 수신자는 내용이 올바른지 검증해야 하며(MUST),
올바르지 않으면 "decrypt_error" 경고와 함께 연결을 종료해야 한다(MUST).
한쪽이 자신의 Finished 메시지를 보내고 피어의 Finished 메시지를
수신하여 검증하면, 연결을 통해 Application Data를 송수신하기
시작할 수 있다. 피어의 Finished를 수신하기 전에 데이터를 보내는
것이 허용되는 두 가지 설정이 있다.
1. 섹션 4.2.10에 설명된 대로 0-RTT 데이터를 보내는 클라이언트.
2. 서버는 자신의 첫 번째 flight를 보낸 뒤 데이터를 보낼 수 있다(MAY).
그러나 핸드셰이크가 아직 완료되지 않았으므로 피어의 신원이나
생존성에 대한 보장이 없다(즉, ClientHello가 재생되었을 수 있음).
Rescorla 표준 트랙 [71페이지]
RFC 8446 TLS 2018년 8월
Finished 메시지를 계산하는 데 사용되는 키는 HKDF를 사용하여
섹션 4.4에 정의된 Base Key에서 계산된다(섹션 7.1 참조).
구체적으로는 다음과 같다.
finished_key =
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
이 메시지의 구조:
struct {
opaque verify_data[Hash.length];
} Finished;
verify_data 값은 다음과 같이 계산된다.
verify_data =
HMAC(finished_key,
Transcript-Hash(Handshake Context,
Certificate*, CertificateVerify*))
* 존재하는 경우에만 포함된다.
HMAC [RFC2104]은 핸드셰이크의 Hash 알고리즘을 사용한다. 위에서
언급했듯이, HMAC 입력은 일반적으로 실행 중인 해시, 즉 이 시점의
핸드셰이크 해시로 구현될 수 있다.
이전 TLS 버전에서 verify_data는 항상 12옥텟 길이였다. TLS 1.3에서는
핸드셰이크에 사용된 Hash의 HMAC 출력 크기이다.
참고: 경고 및 다른 비-핸드셰이크 레코드 타입은 핸드셰이크 메시지가
아니며 해시 계산에 포함되지 않는다.
Finished 메시지 뒤의 모든 레코드는 섹션 7.2에 설명된 대로
적절한 애플리케이션 트래픽 키로 암호화되어야 한다(MUST). 특히
여기에는 클라이언트 Certificate 및 CertificateVerify 메시지에 대한
응답으로 서버가 보내는 모든 경고가 포함된다.
4.5. 조기 데이터의 종료
struct {} EndOfEarlyData;
서버가 EncryptedExtensions에서 "early_data" 확장을 보낸 경우,
클라이언트는 서버 Finished를 수신한 뒤 EndOfEarlyData 메시지를
보내야 한다(MUST). 서버가 EncryptedExtensions에서 "early_data"
확장을 보내지 않으면, 클라이언트는 EndOfEarlyData 메시지를
보내서는 안 된다(MUST NOT). 이 메시지는 모든 0-RTT application_data
메시지가 있다면 전송되었으며, 그
Rescorla 표준 트랙 [72페이지]
RFC 8446 TLS 2018년 8월
뒤의 레코드가 핸드셰이크 트래픽 키로 보호됨을 나타낸다. 서버는
이 메시지를 보내서는 안 되며(MUST NOT), 이를 수신한 클라이언트는
"unexpected_message" 경고와 함께 연결을 종료해야 한다(MUST). 이
메시지는 client_early_traffic_secret에서 파생된 키로 암호화된다.
4.6. 핸드셰이크 후 메시지
TLS는 주 핸드셰이크 후에도 다른 메시지를 보낼 수 있게 한다.
이러한 메시지는 핸드셰이크 콘텐츠 타입을 사용하며 적절한
애플리케이션 트래픽 키로 암호화된다.
4.6.1. 새 세션 티켓 메시지
서버가 클라이언트 Finished 메시지를 수신한 뒤 언제든지
NewSessionTicket 메시지를 보낼 수 있다(MAY). 이 메시지는 티켓 값과
resumption master secret에서 파생된 비밀 PSK 사이의 고유한 연관을
만든다(섹션 7 참조).
클라이언트는 향후 핸드셰이크에서 이 PSK를 사용하기 위해 자신의
ClientHello의 "pre_shared_key" 확장에 티켓 값을 포함할 수 있다(MAY)
(섹션 4.2.11). 서버는 단일 연결에서 여러 티켓을 보낼 수 있으며(MAY),
서로 바로 이어 보내거나 특정 이벤트 후에 보낼 수 있다(부록 C.4
참조). 예를 들어 서버는 추가 클라이언트 인증 상태를 캡슐화하기
위해 핸드셰이크 후 인증 뒤에 새 티켓을 보낼 수 있다. 여러 티켓은
다음을 포함한 다양한 목적에서 클라이언트에 유용하다.
- 여러 병렬 HTTP 연결 열기.
- Happy Eyeballs [RFC8305] 또는 관련 기법을 통해 인터페이스와
주소 패밀리 전반에서 connection racing 수행.
어떤 티켓도 원래 연결을 설정하는 데 사용된 것과 같은 KDF 해시
알고리즘을 가진 암호 스위트로만 재개되어야 한다(MUST).
클라이언트는 새 SNI 값이 원래 세션에서 제시된 서버 인증서에 대해
유효한 경우에만 재개해야 하며(MUST), SNI 값이 원래 세션에서 사용된
것과 일치하는 경우에만 재개해야 한다(SHOULD). 후자는 성능 최적화이다.
일반적으로 단일 인증서가 포괄하는 서로 다른 서버가 서로의 티켓을
수락할 수 있다고 기대할 이유가 없으므로, 그런 경우 재개를 시도하면
일회용 티켓을 낭비하게 된다. 그러한 표시가 제공되는 경우(외부적으로
또는 다른 수단으로), 클라이언트는 다른 SNI 값으로 재개할 수 있다(MAY).
Rescorla 표준 트랙 [73페이지]
RFC 8446 TLS 2018년 8월
재개 시, 호출 애플리케이션에 SNI 값을 보고하는 경우 구현은 이전
세션에서 보낸 값이 아니라 재개 ClientHello에서 보낸 값을 사용해야
한다(MUST). 서버 구현이 다른 SNI 값을 가진 모든 PSK 식별자를
거절하는 경우, 이 두 값은 항상 같다는 점에 유의하라.
참고: resumption master secret은 클라이언트의 두 번째 flight에
의존하지만, 클라이언트 인증을 요청하지 않는 서버는 나머지 전사를
독립적으로 계산한 다음 클라이언트 Finished를 기다리는 대신 자신의
Finished를 보내자마자 NewSessionTicket을 보낼 수 있다(MAY). 예를
들어 클라이언트가 여러 TLS 연결을 병렬로 열 것으로 예상되고 재개
핸드셰이크의 감소된 오버헤드로 이익을 얻을 수 있는 경우 이것이
적절할 수 있다.
struct {
uint32 ticket_lifetime;
uint32 ticket_age_add;
opaque ticket_nonce<0..255>;
opaque ticket<1..2^16-1>;
Extension extensions<0..2^16-2>;
} NewSessionTicket;
ticket_lifetime: 티켓 발행 시점부터의 수명을 초 단위로, 네트워크
바이트 순서의 32비트 부호 없는 정수로 나타낸다. 서버는
604800초(7일)를 초과하는 값을 사용해서는 안 된다(MUST NOT).
0 값은 티켓이 즉시 폐기되어야 함을 나타낸다. 클라이언트는
ticket_lifetime과 관계없이 7일보다 오래 티켓을 캐시해서는
안 되며(MUST NOT), 로컬 정책에 따라 더 일찍 티켓을 삭제할 수
있다(MAY). 서버는 ticket_lifetime에 명시된 것보다 더 짧은 기간
동안 티켓을 유효한 것으로 처리할 수 있다(MAY).
ticket_age_add: 클라이언트가 "pre_shared_key" 확장에 포함하는
티켓 나이를 흐리게 하는 데 사용되는, 안전하게 생성된 무작위
32비트 값. 클라이언트 측 티켓 나이는 이 값에 modulo 2^32로
더해져 클라이언트가 전송하는 값을 얻는다. 서버는 자신이 보내는
각 티켓마다 새로운 값을 생성해야 한다(MUST).
ticket_nonce: 이 연결에서 발행된 모든 티켓에 걸쳐 고유한 티켓별
값.
Rescorla 표준 트랙 [74페이지]
RFC 8446 TLS 2018년 8월
ticket: PSK 식별자로 사용할 티켓 값. 티켓 자체는 opaque 레이블이다.
이는 데이터베이스 조회 키이거나 자체 암호화 및 자체 인증된 값일
수 있다(MAY).
extensions: 티켓에 대한 확장 값 집합. "Extension" 형식은
섹션 4.2에 정의되어 있다. 클라이언트는 인식하지 못하는 확장을
무시해야 한다(MUST).
현재 NewSessionTicket에 대해 정의된 유일한 확장은 "early_data"로,
티켓이 0-RTT 데이터를 보내는 데 사용될 수 있음을 나타낸다
(섹션 4.2.10). 이는 다음 값을 포함한다.
max_early_data_size: 이 티켓을 사용할 때 클라이언트가 보낼 수 있는
0-RTT 데이터의 최대 양(바이트 단위). Application Data 페이로드
(즉, 평문이지만 패딩 또는 내부 콘텐츠 타입 바이트는 제외)만
계산된다. max_early_data_size 바이트를 초과하는 0-RTT 데이터를
수신한 서버는 "unexpected_message" 경고와 함께 연결을 종료해야
한다(SHOULD). 암호학적 자료 부족으로 조기 데이터를 거부하는
서버는 패딩과 콘텐츠를 구분할 수 없으므로, 클라이언트는 조기
데이터 레코드에서 많은 양의 패딩을 보낼 수 있음에 의존해서는
안 된다(SHOULD NOT).
티켓과 연관된 PSK는 다음과 같이 계산된다.
HKDF-Expand-Label(resumption_master_secret,
"resumption", ticket_nonce, Hash.length)
ticket_nonce 값은 각 NewSessionTicket 메시지마다 다르므로, 각
티켓마다 다른 PSK가 파생된다.
원칙적으로 초기 비-PSK 핸드셰이크(대부분 피어의 인증서에 결속된)
에서 원래 파생된 키 자료의 수명을 무기한 연장하는 새 티켓을 계속
발행할 수 있음에 유의하라. 구현은 그러한 키 자료의 총 수명에
제한을 두는 것이 권장된다(RECOMMENDED). 이러한 제한은 피어의
인증서 수명, 중간에 폐기가 발생할 가능성, 그리고 피어의 온라인
CertificateVerify 서명 이후 경과 시간을 고려해야 한다.
4.6.2. 핸드셰이크 후 인증
클라이언트가 "post_handshake_auth" 확장(섹션 4.2.6 참조)을
보낸 경우, 서버는 핸드셰이크가 완료된 뒤 언제든지
CertificateRequest 메시지를 보내 클라이언트 인증을 요청할 수
있다(MAY). 클라이언트는 적절한 Authentication 메시지(섹션 4.4
참조)로 응답해야 한다(MUST). 클라이언트가 인증하기로 선택하면,
Certificate, CertificateVerify,
Rescorla 표준 트랙 [75페이지]
RFC 8446 TLS 2018년 8월
그리고 Finished를 보내야 한다(MUST). 거절하는 경우, 인증서를 포함하지
않는 Certificate 메시지를 보낸 뒤 Finished를 보내야 한다(MUST).
주어진 응답에 대한 클라이언트의 모든 메시지는 다른 타입의 메시지가
사이에 끼지 않고 연속해서 wire에 나타나야 한다(MUST).
"post_handshake_auth" 확장을 보내지 않았는데 CertificateRequest
메시지를 수신한 클라이언트는 "unexpected_message" 치명적 경고를
보내야 한다(MUST).
참고: 클라이언트 인증은 사용자에게 프롬프트를 표시하는 일을
포함할 수 있으므로, 서버는 CertificateRequest를 보낸 후 응답을
받기 전 사이에 임의 개수의 다른 메시지를 받는 것을 포함하여 어느
정도 지연에 대비해야 한다(MUST). 또한 여러 CertificateRequest를
짧은 간격으로 수신한 클라이언트는 수신한 순서와 다른 순서로
응답할 수 있다(MAY)(certificate_request_context 값은 서버가 응답을
구분할 수 있게 한다).
4.6.3. 키 및 초기화 벡터 갱신
KeyUpdate 핸드셰이크 메시지는 송신자가 자신의 송신 암호학적 키를
갱신하고 있음을 나타내는 데 사용된다. 이 메시지는 어느 피어든
Finished 메시지를 보낸 뒤 보낼 수 있다. Finished 메시지를 수신하기
전에 KeyUpdate 메시지를 수신한 구현은 "unexpected_message" 경고와
함께 연결을 종료해야 한다(MUST). KeyUpdate 메시지를 보낸 뒤 송신자는
섹션 7.2에 설명된 대로 계산된 다음 세대의 키를 사용하여 모든
트래픽을 보내야 한다(SHALL). KeyUpdate를 수신하면, 수신자는 자신의
수신 키를 갱신해야 한다(MUST).
enum {
update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;
struct {
KeyUpdateRequest request_update;
} KeyUpdate;
request_update: KeyUpdate의 수신자가 자신의 KeyUpdate로 응답해야
하는지 여부를 나타낸다. 구현이 다른 값을 수신하면,
"illegal_parameter" 경고와 함께 연결을 종료해야 한다(MUST).
request_update 필드가 "update_requested"로 설정된 경우, 수신자는
다음 Application Data 레코드를 보내기 전에 request_update를
"update_not_requested"로 설정한 자신의 KeyUpdate를 보내야 한다(MUST).
이 메커니즘은 어느 쪽이든 전체 연결에 대한 갱신을 강제할 수 있게
하지만, 침묵 중에 여러 KeyUpdate를 수신한 구현이 하나의 갱신으로
응답하게 한다. request_update가 "update_requested"로 설정된 KeyUpdate를
보낸 뒤 피어의 KeyUpdate를 수신하기 전 사이에 임의 개수의 메시지를
받을 수 있음에 유의하라. 그러한 메시지는 이미 전송 중일 수 있기
때문이다. 그러나 송신 키와 수신 키는 독립적인 트래픽 시크릿에서
파생되므로, 수신 트래픽 시크릿을 보관하더라도 송신자가 키를 바꾸기
전에 보낸 데이터의 순방향 비밀성을 위협하지 않는다.
Rescorla 표준 트랙 [76페이지]
RFC 8446 TLS 2018년 8월
침묵 중에 여러 KeyUpdate를 수신한 구현이 하나의 갱신으로 응답하게
한다. request_update가 "update_requested"로 설정된 KeyUpdate를
보낸 뒤 피어의 KeyUpdate를 수신하기 전 사이에 임의 개수의 메시지를
받을 수 있음에 유의하라. 그러한 메시지는 이미 전송 중일 수 있기
때문이다. 그러나 송신 키와 수신 키는 독립적인 트래픽 시크릿에서
파생되므로, 수신 트래픽 시크릿을 보관하더라도 송신자가 키를 바꾸기
전에 보낸 데이터의 순방향 비밀성을 위협하지 않는다.
구현이 독립적으로 request_update가 "update_requested"로 설정된
자신의 KeyUpdate를 보내고, 이들이 전송 중 교차하면, 각 쪽은 응답도
보내게 되며, 그 결과 각 쪽은 두 세대씩 증가한다.
송신자와 수신자는 모두 이전 키로 자신의 KeyUpdate 메시지를
암호화해야 한다(MUST). 또한 양쪽은 새 키로 암호화된 메시지를
수락하기 전에 이전 키로 된 KeyUpdate가 수신되었음을 강제해야
한다(MUST). 그렇게 하지 않으면 메시지 절단 공격이 허용될 수 있다.
5. 레코드 프로토콜
TLS 레코드 프로토콜은 전송할 메시지를 받아 데이터를 관리 가능한
블록으로 조각내고, 레코드를 보호한 뒤 결과를 전송한다. 수신된
데이터는 검증되고, 복호화되고, 재조립된 뒤 상위 수준 클라이언트에
전달된다.
TLS 레코드는 타입이 지정되어 있어, 여러 상위 수준 프로토콜을 같은
레코드 계층 위에서 다중화할 수 있다. 이 문서는 네 가지 콘텐츠
타입인 handshake, application_data, alert 및 change_cipher_spec을
지정한다. change_cipher_spec 레코드는 오직 호환성 목적으로만
사용된다(부록 D.4 참조).
구현은 첫 번째 ClientHello 메시지가 전송되거나 수신된 뒤, 그리고
피어의 Finished 메시지가 수신되기 전 언제든지 단일 바이트 값 0x01로
구성된 change_cipher_spec 타입의 암호화되지 않은 레코드를 수신할 수
있으며, 추가 처리 없이 이를 단순히 버려야 한다(MUST). 이 레코드는
구현이 보호된 레코드를 기대하는 핸드셰이크 지점에 나타날 수 있으므로,
레코드 보호 해제를 시도하기 전에 이 조건을 감지해야 한다. 다른
change_cipher_spec 값을 수신하거나 보호된 change_cipher_spec 레코드를
수신한 구현은 "unexpected_message" 경고와 함께 핸드셰이크를
중단해야 한다(MUST). 구현이 첫 번째 ClientHello 메시지 이전 또는
피어의 Finished 메시지 이후에 수신된 change_cipher_spec 레코드를
감지하면, 이는 예상치 못한 레코드 타입으로 처리되어야 한다(MUST)
(다만 상태 없는 서버는 이러한 경우를 허용된 경우와 구분하지 못할 수
있음).
Rescorla 표준 트랙 [77페이지]
RFC 8446 TLS 2018년 8월
구현은 어떤 확장에 의해 협상되지 않는 한 이 문서에 정의되지 않은
레코드 타입을 보내서는 안 된다(MUST NOT). TLS 구현이 예상치 못한
레코드 타입을 수신하면, "unexpected_message" 경고와 함께 연결을
종료해야 한다(MUST). 새 레코드 콘텐츠 타입 값은 섹션 11에
설명된 대로 TLS ContentType 레지스트리에서 IANA가 할당한다.
5.1. 레코드 계층
레코드 계층은 정보 블록을 2^14바이트 이하의 청크로 데이터를 담는
TLSPlaintext 레코드로 조각낸다. 메시지 경계는 기반 ContentType에
따라 다르게 처리된다. 향후 모든 콘텐츠 타입은 적절한 규칙을
지정해야 한다(MUST). 이 규칙은 TLS 1.2에서 강제되던 것보다 더
엄격하다는 점에 유의하라.
Handshake 메시지는 다음 조건을 만족하는 경우 단일 TLSPlaintext
레코드로 결합되거나 여러 레코드에 걸쳐 조각날 수 있다(MAY).
- Handshake 메시지는 다른 레코드 타입과 섞여서는 안 된다(MUST NOT).
즉, 핸드셰이크 메시지가 두 개 이상의 레코드로 나뉘는 경우, 그
사이에 다른 레코드가 있어서는 안 된다(MUST NOT).
- Handshake 메시지는 키 변경을 가로질러서는 안 된다(MUST NOT).
구현은 키 변경 바로 앞의 모든 메시지가 레코드 경계에 맞춰져
있는지 검증해야 하며(MUST), 그렇지 않으면 "unexpected_message"
경고와 함께 연결을 종료해야 한다(MUST). ClientHello,
EndOfEarlyData, ServerHello, Finished 및 KeyUpdate 메시지는 키
변경 바로 앞에 올 수 있으므로, 구현은 이 메시지들을 레코드 경계에
맞춰 보내야 한다(MUST).
구현은 Handshake 타입의 길이 0 조각을 보내서는 안 된다(MUST NOT).
해당 조각이 패딩을 포함하더라도 마찬가지이다.
Alert 메시지(섹션 6)는 레코드에 걸쳐 조각나서는 안 되며(MUST NOT),
여러 alert 메시지가 단일 TLSPlaintext 레코드로 결합되어서는 안 된다
(MUST NOT). 다시 말해, Alert 타입의 레코드는 정확히 하나의 메시지만
포함해야 한다(MUST).
Application Data 메시지는 TLS에 대해 opaque인 데이터를 포함한다.
Application Data 메시지는 항상 보호된다. Application Data의 길이 0
조각은 트래픽 분석 대응수단으로 잠재적으로 유용하므로 전송될 수
있다(MAY). Application Data 조각은 여러 레코드에 걸쳐 나뉘거나
단일 레코드로 결합될 수 있다(MAY).
Rescorla 표준 트랙 [78페이지]
RFC 8446 TLS 2018년 8월
enum {
invalid(0),
change_cipher_spec(20),
alert(21),
handshake(22),
application_data(23),
(255)
} ContentType;
struct {
ContentType type;
ProtocolVersion legacy_record_version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
type: 포함된 fragment를 처리하는 데 사용되는 상위 수준 프로토콜.
legacy_record_version: 초기 ClientHello(즉, HelloRetryRequest 이후
생성된 것이 아닌 것)를 제외하고 TLS 1.3 구현이 생성하는 모든
레코드에 대해 0x0303으로 설정되어야 한다(MUST). 초기 ClientHello의
경우 호환성 목적으로 0x0301일 수도 있다(MAY). 이 필드는 폐기
예정이며 모든 목적에서 무시되어야 한다(MUST). 이전 TLS 버전은
특정 상황에서 이 필드에 다른 값을 사용했다.
length: 뒤따르는 TLSPlaintext.fragment의 길이(바이트 단위). 길이는
2^14바이트를 초과해서는 안 된다(MUST NOT). 이 길이를 초과하는
레코드를 수신한 엔드포인트는 "record_overflow" 경고와 함께 연결을
종료해야 한다(MUST).
fragment: 전송되는 데이터. 이 값은 투명하며 type 필드가 지정하는
상위 수준 프로토콜이 처리할 독립 블록으로 취급된다.
이 문서는 버전 0x0304를 사용하는 TLS 1.3을 설명한다. 이 버전 값은
역사적인 것으로, TLS 1.0에 0x0301이 사용되고 SSL 3.0에 0x0300이
사용된 데서 비롯된다. 하위 호환성을 극대화하기 위해, 초기
ClientHello를 포함하는 레코드는 버전 0x0301(TLS 1.0을 반영)을
가져야 하며(SHOULD), 두 번째 ClientHello 또는 ServerHello를 포함하는
레코드는 버전 0x0303(TLS 1.2를 반영)을 가져야 한다(MUST). 이전 TLS
버전을 협상할 때 엔드포인트는 부록 D에 제공된 절차와 요구사항을
따른다.
Rescorla 표준 트랙 [79페이지]
RFC 8446 TLS 2018년 8월
레코드 보호가 아직 적용되지 않은 경우, TLSPlaintext 구조는 wire에
직접 기록된다. 레코드 보호가 시작되면, TLSPlaintext 레코드는 다음
섹션에 설명된 대로 보호되어 전송된다. Application Data 레코드는
보호되지 않은 채 wire에 기록되어서는 안 된다는 점에 유의하라(MUST NOT)
(자세한 내용은 섹션 2 참조).
5.2. 레코드 페이로드 보호
레코드 보호 함수는 TLSPlaintext 구조를 TLSCiphertext 구조로 변환한다.
보호 해제 함수는 이 과정을 역으로 수행한다. TLS 1.3에서는 이전 TLS
버전과 달리 모든 암호가 "Authenticated Encryption with Associated
Data"(AEAD) [RFC5116]로 모델링된다. AEAD 함수는 평문을 인증된
암호문으로, 다시 그 반대로 바꾸는 통합 암호화 및 인증 동작을
제공한다. 각 암호화된 레코드는 평문 헤더와 그 뒤의 암호화된 본문으로
구성되며, 본문 자체는 타입과 선택적 패딩을 포함한다.
struct {
opaque content[TLSPlaintext.length];
ContentType type;
uint8 zeros[length_of_padding];
} TLSInnerPlaintext;
struct {
ContentType opaque_type = application_data; /* 23 */
ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
content: 핸드셰이크 또는 alert 메시지의 바이트 인코딩, 또는 전송할
애플리케이션 데이터의 원시 바이트를 포함하는 TLSPlaintext.fragment
값.
type: 레코드의 콘텐츠 타입을 포함하는 TLSPlaintext.type 값.
zeros: 타입 필드 뒤의 cleartext에는 임의 길이의 0값 바이트열이
나타날 수 있다. 이는 전체가 레코드 크기 제한 안에 머무르는 한,
송신자가 선택한 양만큼 어떤 TLS 레코드든 패딩할 기회를 제공한다.
자세한 내용은 섹션 5.4를 참조하라.
Rescorla 표준 트랙 [80페이지]
RFC 8446 TLS 2018년 8월
opaque_type: TLSCiphertext 레코드의 외부 opaque_type 필드는 이전 TLS
버전을 파싱하는 데 익숙한 미들박스와의 외향 호환성을 위해 항상
값 23(application_data)으로 설정된다. 레코드의 실제 콘텐츠 타입은
복호화 후 TLSInnerPlaintext.type에서 발견된다.
legacy_record_version: legacy_record_version 필드는 항상 0x0303이다.
TLS 1.3 TLSCiphertext는 TLS 1.3이 협상된 뒤에야 생성되므로, 다른
값이 수신될 수 있는 역사적 호환성 우려가 없다. ClientHello와
ServerHello 메시지를 포함한 핸드셰이크 프로토콜이 프로토콜 버전을
인증하므로, 이 값은 중복적이라는 점에 유의하라.
length: 뒤따르는 TLSCiphertext.encrypted_record의 길이(바이트 단위)로,
content와 padding의 길이 합에 내부 콘텐츠 타입을 위한 1바이트와
AEAD 알고리즘이 추가한 확장을 더한 값이다. 길이는 2^14 + 256
바이트를 초과해서는 안 된다(MUST NOT). 이 길이를 초과하는 레코드를
수신한 엔드포인트는 "record_overflow" 경고와 함께 연결을 종료해야
한다(MUST).
encrypted_record: 직렬화된 TLSInnerPlaintext 구조의 AEAD 암호화된
형태.
AEAD 알고리즘은 [[RFC5116]의 섹션 2.1]에 설명된 대로 단일 키,
nonce, 평문, 그리고 인증 검사에 포함될 "additional data"를 입력으로
받는다. 키는 client_write_key 또는 server_write_key이고, nonce는
시퀀스 번호와 client_write_iv 또는 server_write_iv에서 파생되며
(섹션 5.3 참조), additional data 입력은 레코드 헤더이다.
즉,
additional_data = TLSCiphertext.opaque_type ||
TLSCiphertext.legacy_record_version ||
TLSCiphertext.length
AEAD 알고리즘에 대한 평문 입력은 인코딩된 TLSInnerPlaintext 구조이다.
트래픽 키 파생은 섹션 7.3에 정의되어 있다.
AEAD 출력은 AEAD 암호화 동작의 암호문 출력으로 구성된다.
TLSInnerPlaintext.type과 송신자가 제공한 모든 패딩이 포함되므로,
평문의 길이는 대응하는 TLSPlaintext.length보다 크다. AEAD 출력의
길이는 일반적으로 평문보다 크지만, 그 양은 AEAD 알고리즘에 따라
달라진다.
Rescorla 표준 트랙 [81페이지]
RFC 8446 TLS 2018년 8월
암호가 패딩을 포함할 수 있으므로 오버헤드의 양은 평문 길이에 따라
달라질 수 있다. 기호적으로는 다음과 같다.
AEADEncrypted =
AEAD-Encrypt(write_key, nonce, additional_data, plaintext)
TLSCiphertext의 encrypted_record 필드는 AEADEncrypted로 설정된다.
복호화 및 검증을 위해, 암호는 키, nonce, additional data 및
AEADEncrypted 값을 입력으로 받는다. 출력은 평문이거나 복호화가
실패했음을 나타내는 오류이다. 별도의 무결성 검사는 없다.
기호적으로는 다음과 같다.
plaintext of encrypted_record =
AEAD-Decrypt(peer_write_key, nonce,
additional_data, AEADEncrypted)
복호화가 실패하면, 수신자는 "bad_record_mac" 경고와 함께 연결을
종료해야 한다(MUST).
TLS 1.3에서 사용되는 AEAD 알고리즘은 255옥텟을 초과하는 확장을
생성해서는 안 된다(MUST NOT). 피어로부터 TLSCiphertext.length가
2^14 + 256옥텟보다 큰 레코드를 수신한 엔드포인트는 "record_overflow"
경고와 함께 연결을 종료해야 한다(MUST). 이 제한은 최대
TLSInnerPlaintext 길이 2^14옥텟 + ContentType을 위한 1옥텟 + 최대
AEAD 확장 255옥텟에서 파생된다.
5.3. 레코드별 nonce
64비트 시퀀스 번호는 레코드 읽기와 쓰기에 대해 별도로 유지된다.
적절한 시퀀스 번호는 각 레코드를 읽거나 쓴 뒤 1씩 증가한다. 각
시퀀스 번호는 연결 시작 시와 키가 변경될 때마다 0으로 설정된다.
특정 트래픽 키 아래에서 전송되는 첫 번째 레코드는 시퀀스 번호 0을
사용해야 한다(MUST).
시퀀스 번호의 크기는 64비트이므로 wrap되어서는 안 된다. TLS 구현이
시퀀스 번호를 wrap해야 할 경우, rekey(섹션 4.6.3)하거나 연결을
종료해야 한다(MUST).
Rescorla 표준 트랙 [82페이지]
RFC 8446 TLS 2018년 8월
각 AEAD 알고리즘은 입력의 N_MIN 바이트부터 N_MAX 바이트까지
레코드별 nonce에 가능한 길이 범위를 지정한다 [RFC5116].
TLS 레코드별 nonce의 길이(iv_length)는 AEAD 알고리즘에 대해 8바이트와
N_MIN 중 더 큰 값으로 설정된다([RFC5116], 섹션 4 참조).
N_MAX가 8바이트보다 작은 AEAD 알고리즘은 TLS와 함께 사용되어서는
안 된다(MUST NOT). AEAD 구성에 대한 레코드별 nonce는 다음과 같이
형성된다.
1. 64비트 레코드 시퀀스 번호는 네트워크 바이트 순서로 인코딩되고,
iv_length까지 왼쪽에 0으로 패딩된다.
2. 패딩된 시퀀스 번호는 역할에 따라 정적 client_write_iv 또는
server_write_iv와 XOR된다.
결과 값(iv_length 길이)이 레코드별 nonce로 사용된다.
참고: 이는 부분적으로 명시적인 nonce를 지정했던 TLS 1.2와 다른
구성이다.
5.4. 레코드 패딩
모든 암호화된 TLS 레코드는 TLSCiphertext의 크기를 늘리도록 패딩될
수 있다. 이를 통해 송신자는 트래픽의 크기를 관찰자로부터 숨길 수
있다.
TLSCiphertext 레코드를 생성할 때, 구현은 패딩을 선택할 수 있다(MAY).
패딩되지 않은 레코드는 패딩 길이가 0인 레코드일 뿐이다. 패딩은
암호화 전에 ContentType 필드 뒤에 추가되는 0값 바이트 문자열이다.
구현은 암호화하기 전에 패딩 옥텟을 모두 0으로 설정해야 한다(MUST).
송신자가 원하는 경우 Application Data 레코드는 길이 0의
TLSInnerPlaintext.content를 포함할 수 있다. 이는 활동의 존재 또는
부재가 민감할 수 있는 컨텍스트에서 그럴듯한 크기의 cover traffic을
생성하는 것을 허용한다. 구현은 길이 0의 TLSInnerPlaintext.content를
가진 Handshake 및 Alert 레코드를 보내서는 안 된다(MUST NOT). 그러한
메시지가 수신되면, 수신 구현은 "unexpected_message" 경고와 함께
연결을 종료해야 한다(MUST).
Rescorla 표준 트랙 [83페이지]
RFC 8446 TLS 2018년 8월
전송된 패딩은 레코드 보호 메커니즘에 의해 자동으로 검증된다.
TLSCiphertext.encrypted_record의 복호화가 성공하면, 수신 구현은
필드의 끝에서 시작 방향으로 0이 아닌 옥텟을 찾을 때까지 스캔한다.
이 0이 아닌 옥텟이 메시지의 콘텐츠 타입이다. 이 패딩 방식은 새
콘텐츠 타입을 도입하지 않고도 어떤 암호화된 TLS 레코드든 임의
크기(0부터 TLS 레코드 크기 제한까지)로 패딩할 수 있기 때문에
선택되었다. 이 설계는 또한 모든 패딩 옥텟이 0임을 강제하여 패딩
오류를 빠르게 감지할 수 있게 한다.
구현은 AEAD 복호화에서 반환된 cleartext로 스캔을 제한해야 한다(MUST).
수신 구현이 cleartext에서 0이 아닌 옥텟을 찾지 못하면,
"unexpected_message" 경고와 함께 연결을 종료해야 한다(MUST).
패딩의 존재는 전체 레코드 크기 제한을 변경하지 않는다. 전체 인코딩된
TLSInnerPlaintext는 2^14 + 1옥텟을 초과해서는 안 된다(MUST NOT).
예를 들어 [RFC8449]의 record_size_limit 확장으로 최대 조각 길이가
줄어든 경우, 줄어든 제한은 콘텐츠 타입과 패딩을 포함한 전체 평문에
적용된다.
언제, 얼마나 패딩할지를 제안하는 패딩 정책을 선택하는 것은 복잡한
주제이며 이 명세의 범위를 벗어난다. TLS 위의 애플리케이션 계층
프로토콜이 자체 패딩을 가지고 있다면, 애플리케이션 계층 내에서
Application Data TLS 레코드를 패딩하는 것이 더 바람직할 수 있다.
그러나 암호화된 Handshake 또는 Alert 레코드의 패딩은 여전히 TLS
계층에서 처리되어야 한다. 이후 문서가 패딩 선택 알고리즘을 정의하거나
TLS 확장 또는 다른 수단을 통한 패딩 정책 요청 메커니즘을 정의할 수
있다.
5.5. 키 사용 제한
주어진 키 집합 아래에서 안전하게 암호화할 수 있는 평문의 양에는
암호학적 제한이 있다. [AEAD-LIMITS]는 기반 primitive(AES 또는
ChaCha20)에 약점이 없다는 가정 아래 이러한 제한을 분석한다.
구현은 이러한 제한에 도달하기 전에 섹션 4.6.3에 설명된 대로 키
갱신을 수행해야 한다(SHOULD).
AES-GCM의 경우, Authenticated Encryption(AE) 보안에 대해 약 2^-57의
안전 여유를 유지하면서, 주어진 연결에서 최대 2^24.5개의 전체 크기
레코드(약 2,400만 개)를 암호화할 수 있다. ChaCha20/Poly1305의 경우,
안전 한계에 도달하기 전에 레코드 시퀀스 번호가 wrap될 것이다.
Rescorla 표준 트랙 [84페이지]
RFC 8446 TLS 2018년 8월
6. 경고 프로토콜
TLS는 종료 정보와 오류를 나타내기 위해 Alert 콘텐츠 타입을 제공한다.
다른 메시지와 마찬가지로 alert 메시지는 현재 연결 상태가 지정하는
대로 암호화된다.
Alert 메시지는 경고의 설명과 이전 TLS 버전에서 메시지의 심각도
수준을 전달하던 레거시 필드를 전달한다. Alert는 종료 경고와 오류
경고라는 두 클래스로 나뉜다. TLS 1.3에서 심각도는 전송되는 alert의
타입에 암시되어 있으며, "level" 필드는 안전하게 무시될 수 있다.
"close_notify" 경고는 연결의 한 방향이 질서 있게 종료됨을 나타내는
데 사용된다. 이러한 경고를 수신하면 TLS 구현은 애플리케이션에
데이터 종료를 나타내야 한다(SHOULD).
오류 경고는 연결의 중단 종료를 나타낸다(섹션 6.2 참조). 오류
경고를 수신하면 TLS 구현은 애플리케이션에 오류를 나타내야 하며
(SHOULD), 연결에서 더 이상 데이터를 보내거나 받는 것을 허용해서는
안 된다(MUST NOT). 서버와 클라이언트는 실패한 연결에서 설정된 비밀
값과 키를 잊어야 한다(MUST). 단, 세션 티켓과 연관된 PSK는 예외이며
가능한 경우 폐기해야 한다(SHOULD).
섹션 6.2에 나열된 모든 alert는 AlertLevel=fatal로 전송되어야
하며(MUST), 메시지의 AlertLevel과 관계없이 수신 시 오류 경고로
처리되어야 한다(MUST). 알 수 없는 Alert 타입은 오류 경고로
처리되어야 한다(MUST).
참고: TLS는 메시지 파싱 실패 시 사용할 두 가지 일반 경고
(섹션 6 참조)를 정의한다. 구문에 따라 파싱할 수 없는 메시지
(예: 메시지 경계를 넘어 확장되는 길이를 가지거나 범위를 벗어난 길이를
포함)를 수신한 피어는 "decode_error" 경고와 함께 연결을 종료해야
한다(MUST). 구문적으로는 올바르지만 의미적으로 유효하지 않은 메시지
(예: p - 1인 DHE share 또는 유효하지 않은 enum)를 수신한 피어는
"illegal_parameter" 경고와 함께 연결을 종료해야 한다(MUST).
Rescorla 표준 트랙 [85페이지]
RFC 8446 TLS 2018년 8월
enum { warning(1), fatal(2), (255) } AlertLevel;
enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
record_overflow(22),
handshake_failure(40),
bad_certificate(42),
unsupported_certificate(43),
certificate_revoked(44),
certificate_expired(45),
certificate_unknown(46),
illegal_parameter(47),
unknown_ca(48),
access_denied(49),
decode_error(50),
decrypt_error(51),
protocol_version(70),
insufficient_security(71),
internal_error(80),
inappropriate_fallback(86),
user_canceled(90),
missing_extension(109),
unsupported_extension(110),
unrecognized_name(112),
bad_certificate_status_response(113),
unknown_psk_identity(115),
certificate_required(116),
no_application_protocol(120),
(255)
} AlertDescription;
struct {
AlertLevel level;
AlertDescription description;
} Alert;
Rescorla 표준 트랙 [86페이지]
RFC 8446 TLS 2018년 8월
6.1. 종료 경고
클라이언트와 서버는 절단 공격을 피하기 위해 연결이 종료된다는
지식을 공유해야 한다.
close_notify: 이 경고는 송신자가 이 연결에서 더 이상 메시지를
보내지 않을 것임을 수신자에게 알린다. 종료 경고가 수신된 뒤
수신된 모든 데이터는 무시되어야 한다(MUST).
user_canceled: 이 경고는 송신자가 프로토콜 실패와 관련 없는 어떤
이유로 핸드셰이크를 취소하고 있음을 수신자에게 알린다. 핸드셰이크가
완료된 뒤 사용자가 동작을 취소하는 경우, "close_notify"를 보내
연결을 닫는 것만으로도 더 적절하다. 이 경고 뒤에는
"close_notify"가 따라야 한다(SHOULD). 이 경고는 일반적으로
AlertLevel=warning을 가진다.
어느 쪽이든 "close_notify" 경고를 보내 연결의 쓰기 측 종료를 시작할
수 있다(MAY). 종료 경고가 수신된 뒤 수신된 모든 데이터는 무시되어야
한다(MUST). "close_notify" 이전에 전송 계층 종료가 수신되면, 수신자는
전송된 모든 데이터가 수신되었는지 알 수 없다.
각 당사자는 이미 어떤 오류 경고를 보낸 경우가 아니라면 자신의 연결
쓰기 측을 닫기 전에 "close_notify" 경고를 보내야 한다(MUST). 이는
연결의 읽기 측에는 아무 영향도 없다. 이는 TLS 1.3 이전 버전에서
구현이 "close_notify"에 반응하여 대기 중인 쓰기를 폐기하고 즉시
자체 "close_notify" 경고를 보내도록 요구되던 것과 다른 변경 사항임에
유의하라. 이전 요구사항은 읽기 측에서 절단을 야기할 수 있었다.
양쪽은 연결의 읽기 측을 닫기 전에 "close_notify" 경고 수신을 기다릴
필요는 없지만, 그렇게 하면 절단 가능성이 도입된다.
TLS를 사용하는 애플리케이션 프로토콜이 TLS 연결이 닫힌 뒤에도
기반 전송 위로 어떤 데이터든 운반될 수 있도록 제공한다면, TLS 구현은
애플리케이션 계층에 데이터 종료를 나타내기 전에 "close_notify"
경고를 수신해야 한다(MUST). 이 표준의 어떤 부분도 TLS 사용 프로파일이
연결을 여닫는 시점을 포함하여 자신의 데이터 전송을 관리하는 방식을
지시하는 것으로 받아들여서는 안 된다.
참고: 연결의 쓰기 측을 닫는 것은 전송을 파괴하기 전에 대기 중인
데이터를 신뢰성 있게 전달한다고 가정한다.
Rescorla 표준 트랙 [87페이지]
RFC 8446 TLS 2018년 8월
6.2. 오류 경고
TLS의 오류 처리는 매우 단순하다. 오류가 감지되면 감지한 쪽이
피어에게 메시지를 보낸다. 치명적 alert 메시지를 전송하거나 수신하면,
양쪽은 즉시 연결을 닫아야 한다(MUST).
구현이 치명적 오류 조건을 만날 때마다, 적절한 치명적 경고를 보내야
하며(SHOULD), 추가 데이터를 보내거나 받지 않고 연결을 닫아야 한다
(MUST). 이 명세의 나머지에서 "terminate the connection" 및 "abort the
handshake"라는 구문이 특정 alert 없이 사용될 때, 이는 구현이 아래
설명에 표시된 alert를 보내야 함(SHOULD)을 의미한다. "terminate the
connection with an X alert" 및 "abort the handshake with an X alert"라는
구문은 구현이 어떤 alert든 보낸다면 alert X를 보내야 함(MUST)을
의미한다. 이 섹션 아래에 정의된 모든 alert와 모든 알 수 없는 alert는
TLS 1.3부터 보편적으로 치명적인 것으로 간주된다(섹션 6 참조).
구현은 alert의 송수신 로깅을 용이하게 하는 방법을 제공해야 한다
(SHOULD).
다음 오류 경고가 정의된다.
unexpected_message: 부적절한 메시지(예: 잘못된 핸드셰이크 메시지,
조기 Application Data 등)가 수신되었다. 이 alert는 올바른 구현
사이의 통신에서는 결코 관찰되어서는 안 된다.
bad_record_mac: 보호 해제할 수 없는 레코드가 수신된 경우 이 경고가
반환된다. AEAD 알고리즘은 복호화와 검증을 결합하며, 부채널 공격을
피하기 위해서도 이 alert는 모든 보호 해제 실패에 사용된다. 이
alert는 네트워크에서 메시지가 손상된 경우를 제외하고 올바른 구현
사이의 통신에서는 결코 관찰되어서는 안 된다.
record_overflow: 길이가 2^14 + 256바이트를 초과하는 TLSCiphertext
레코드가 수신되었거나, 2^14바이트(또는 다른 협상된 제한)를 초과하는
TLSPlaintext 레코드로 복호화된 레코드가 수신되었다. 이 alert는
네트워크에서 메시지가 손상된 경우를 제외하고 올바른 구현 사이의
통신에서는 결코 관찰되어서는 안 된다.
handshake_failure: "handshake_failure" alert 메시지의 수신은 송신자가
사용 가능한 옵션에서 허용 가능한 보안 매개변수 집합을 협상할 수
없었음을 나타낸다.
bad_certificate: 인증서가 손상되었거나, 올바르게 검증되지 않는
서명을 포함하는 등의 경우.
Rescorla 표준 트랙 [88페이지]
RFC 8446 TLS 2018년 8월
unsupported_certificate: 인증서가 지원되지 않는 타입이었다.
certificate_revoked: 인증서가 그 서명자에 의해 폐기되었다.
certificate_expired: 인증서가 만료되었거나 현재 유효하지 않다.
certificate_unknown: 인증서 처리 중 다른(지정되지 않은) 문제가
발생하여 인증서가 허용 불가능해졌다.
illegal_parameter: 핸드셰이크의 필드가 올바르지 않거나 다른 필드와
일관되지 않았다. 이 alert는 형식적 프로토콜 구문에는 부합하지만
그 외에는 올바르지 않은 오류에 사용된다.
unknown_ca: 유효한 인증서 체인 또는 부분 체인이 수신되었지만, CA
인증서를 찾을 수 없거나 알려진 신뢰 앵커와 일치시킬 수 없어
인증서가 수락되지 않았다.
access_denied: 유효한 인증서 또는 PSK가 수신되었지만, 접근 제어가
적용되었을 때 송신자가 협상을 진행하지 않기로 결정했다.
decode_error: 어떤 필드가 지정된 범위를 벗어났거나 메시지 길이가
올바르지 않아 메시지를 디코딩할 수 없었다. 이 alert는 메시지가
형식적 프로토콜 구문에 부합하지 않는 오류에 사용된다. 이 alert는
네트워크에서 메시지가 손상된 경우를 제외하고 올바른 구현 사이의
통신에서는 결코 관찰되어서는 안 된다.
decrypt_error: 서명을 올바르게 검증하거나 Finished 메시지 또는 PSK
binder를 검증할 수 없는 경우를 포함하여, 핸드셰이크(레코드 계층이
아닌) 암호학적 동작이 실패했다.
protocol_version: 피어가 협상하려고 시도한 프로토콜 버전이 인식되었지만
지원되지 않는다(부록 D 참조).
insufficient_security: 서버가 클라이언트가 지원하는 것보다 더 안전한
매개변수를 요구하기 때문에 특별히 협상이 실패한 경우,
"handshake_failure" 대신 반환된다.
internal_error: 피어 또는 프로토콜의 올바름과 관련 없는 내부 오류
(예: 메모리 할당 실패)로 인해 계속 진행할 수 없다.
inappropriate_fallback: 클라이언트의 유효하지 않은 연결 재시도 시도에
대한 응답으로 서버가 보낸다([RFC7507] 참조).
Rescorla 표준 트랙 [89페이지]
RFC 8446 TLS 2018년 8월
missing_extension: 제공된 TLS 버전 또는 다른 협상된 매개변수에 대해
전송이 필수인 확장을 포함하지 않는 핸드셰이크 메시지를 수신한
엔드포인트가 보낸다.
unsupported_extension: 주어진 핸드셰이크 메시지에 포함하는 것이
금지된 것으로 알려진 확장을 포함하는 핸드셰이크 메시지를 수신한
엔드포인트, 또는 대응하는 ClientHello나 CertificateRequest에서
먼저 제공되지 않은 확장을 ServerHello나 Certificate에 포함한 경우
엔드포인트가 보낸다.
unrecognized_name: 클라이언트가 "server_name" 확장을 통해 제공한
이름으로 식별되는 서버가 존재하지 않을 때 서버가 보낸다
([RFC6066] 참조).
bad_certificate_status_response: 서버가 "status_request" 확장을 통해
유효하지 않거나 허용 불가능한 OCSP 응답을 제공할 때 클라이언트가
보낸다([RFC6066] 참조).
unknown_psk_identity: PSK 키 설정이 필요하지만 클라이언트가 허용
가능한 PSK 식별자를 제공하지 않았을 때 서버가 보낸다. 이 alert를
보내는 것은 선택 사항이다(OPTIONAL). 서버는 대신 단지 유효하지
않은 PSK 식별자를 나타내기 위해 "decrypt_error" alert를 보내도록
선택할 수 있다(MAY).
certificate_required: 클라이언트 인증서가 필요하지만 클라이언트가
제공하지 않았을 때 서버가 보낸다.
no_application_protocol: 클라이언트의
"application_layer_protocol_negotiation" 확장이 서버가 지원하지 않는
프로토콜만 광고할 때 서버가 보낸다([RFC7301] 참조).
새 Alert 값은 섹션 11에 설명된 대로 IANA가 할당한다.
7. 암호학적 계산
TLS 핸드셰이크는 하나 이상의 입력 시크릿을 설정하며, 이는 아래에
자세히 설명된 실제 작업용 키 자료를 만들기 위해 결합된다. 키 파생
과정은 입력 시크릿과 핸드셰이크 전사를 모두 통합한다. 핸드셰이크
전사가 Hello 메시지의 무작위 값을 포함하므로, 같은 입력 시크릿이
사용되는 경우에도(예: 같은 PSK가 여러 연결에 사용되는 경우) 주어진
핸드셰이크는 서로 다른 트래픽 시크릿을 가지게 된다는 점에 유의하라.
Rescorla 표준 트랙 [90페이지]
RFC 8446 TLS 2018년 8월
7.1. 키 스케줄
키 파생 과정은 HKDF [RFC5869]에 대해 정의된 HKDF-Extract 및
HKDF-Expand 함수와 아래 정의된 함수를 사용한다.
HKDF-Expand-Label(Secret, Label, Context, Length) =
HKDF-Expand(Secret, HkdfLabel, Length)
여기서 HkdfLabel은 다음과 같이 지정된다.
struct {
uint16 length = Length;
opaque label<7..255> = "tls13 " + Label;
opaque context<0..255> = Context;
} HkdfLabel;
Derive-Secret(Secret, Label, Messages) =
HKDF-Expand-Label(Secret, Label,
Transcript-Hash(Messages), Hash.length)
Transcript-Hash 및 HKDF가 사용하는 Hash 함수는 암호 스위트 해시
알고리즘이다. Hash.length는 그 출력 길이(바이트 단위)이다. Messages는
표시된 핸드셰이크 메시지의 연결이며, 핸드셰이크 메시지 타입과 길이
필드를 포함하지만 레코드 계층 헤더는 포함하지 않는다. 일부 경우에는
길이 0 Context(""로 표시)가 HKDF-Expand-Label에 전달된다는 점에
유의하라. 이 문서에 지정된 레이블은 모두 ASCII 문자열이며 trailing
NUL 바이트를 포함하지 않는다.
참고: 일반적인 해시 함수에서 12자를 초과하는 레이블은 계산을 위해
해시 함수의 추가 반복을 요구한다. 이 명세의 레이블은 모두 이 제한
안에 맞도록 선택되었다.
Rescorla 표준 트랙 [91페이지]
RFC 8446 TLS 2018년 8월
키는 HKDF-Extract 및 Derive-Secret 함수를 사용하여 두 입력 시크릿에서
파생된다. 새 시크릿을 추가하는 일반 패턴은 현재 시크릿 상태를 Salt로,
추가할 새 시크릿을 Input Keying Material(IKM)로 하여 HKDF-Extract를
사용하는 것이다. TLS 1.3의 이 버전에서 두 입력 시크릿은 다음과 같다.
- PSK(외부에서 설정된 사전 공유 키 또는 이전 연결의
resumption_master_secret 값에서 파생된 것)
- (EC)DHE 공유 시크릿(섹션 7.4)
이는 아래 다이어그램에 표시된 전체 키 파생 스케줄을 생성한다.
이 다이어그램에는 다음 형식 규칙이 적용된다.
- HKDF-Extract는 위쪽에서 Salt 인자를, 왼쪽에서 IKM 인자를 받아,
출력을 아래쪽으로 내보내고 출력 이름을 오른쪽에 표시하는 것으로
그려진다.
- Derive-Secret의 Secret 인자는 들어오는 화살표로 표시된다. 예를
들어 Early Secret은 client_early_traffic_secret을 생성하기 위한
Secret이다.
- "0"은 Hash.length 바이트가 0으로 설정된 문자열을 나타낸다.
Rescorla 표준 트랙 [92페이지]
RFC 8446 TLS 2018년 8월
0
|
v
PSK -> HKDF-Extract = Early Secret
|
+-----> Derive-Secret(., "ext binder" | "res binder", "")
| = binder_key
|
+-----> Derive-Secret(., "c e traffic", ClientHello)
| = client_early_traffic_secret
|
+-----> Derive-Secret(., "e exp master", ClientHello)
| = early_exporter_master_secret
v
Derive-Secret(., "derived", "")
|
v
(EC)DHE -> HKDF-Extract = Handshake Secret
|
+-----> Derive-Secret(., "c hs traffic",
| ClientHello...ServerHello)
| = client_handshake_traffic_secret
|
+-----> Derive-Secret(., "s hs traffic",
| ClientHello...ServerHello)
| = server_handshake_traffic_secret
v
Derive-Secret(., "derived", "")
|
v
0 -> HKDF-Extract = Master Secret
|
+-----> Derive-Secret(., "c ap traffic",
| ClientHello...server Finished)
| = client_application_traffic_secret_0
|
+-----> Derive-Secret(., "s ap traffic",
| ClientHello...server Finished)
| = server_application_traffic_secret_0
|
+-----> Derive-Secret(., "exp master",
| ClientHello...server Finished)
| = exporter_master_secret
|
+-----> Derive-Secret(., "res master",
ClientHello...client Finished)
= resumption_master_secret
Rescorla 표준 트랙 [93페이지]
RFC 8446 TLS 2018년 8월
여기서의 일반 패턴은 다이어그램의 왼쪽 아래로 표시된 시크릿은
컨텍스트가 없는 원시 엔트로피일 뿐인 반면, 오른쪽 아래의 시크릿은
Handshake Context를 포함하므로 추가 컨텍스트 없이 작업용 키를
파생하는 데 사용할 수 있다는 것이다. 같은 시크릿을 사용하더라도
Derive-Secret에 대한 서로 다른 호출은 서로 다른 Messages 인자를
받을 수 있음에 유의하라. 0-RTT 교환에서는 Derive-Secret이 네 개의
서로 다른 전사로 호출된다. 1-RTT-only 교환에서는 세 개의 서로 다른
전사로 호출된다.
주어진 시크릿을 사용할 수 없는 경우, Hash.length 바이트가 0으로
설정된 문자열로 구성된 0값이 사용된다. 이는 라운드를 건너뛴다는
의미가 아님에 유의하라. 따라서 PSK가 사용되지 않더라도 Early Secret은
여전히 HKDF-Extract(0, 0)이 된다. binder_key 계산에서 레이블은 외부
PSK(TLS 외부에서 제공된 것)에 대해서는 "ext binder"이고, 재개 PSK
(이전 핸드셰이크의 resumption master secret으로 제공된 것)에 대해서는
"res binder"이다. 서로 다른 레이블은 한 타입의 PSK가 다른 타입으로
대체되는 것을 방지한다.
서버가 최종적으로 어떤 PSK를 선택하는지에 따라 여러 잠재적인 Early
Secret 값이 있다. 클라이언트는 각 잠재적 PSK에 대해 하나씩 계산해야
한다. PSK가 선택되지 않으면, 0 PSK에 대응하는 Early Secret을
계산해야 한다.
주어진 시크릿에서 파생될 모든 값이 계산되면, 그 시크릿은 지워져야
한다(SHOULD).
7.2. 트래픽 시크릿 갱신
핸드셰이크가 완료되면, 어느 쪽이든 섹션 4.6.3에 정의된
KeyUpdate 핸드셰이크 메시지를 사용해 자신의 송신 트래픽 키를 갱신할
수 있다. 다음 세대의 트래픽 키는 이 섹션에 설명된 대로
client_/server_application_traffic_secret_N에서
client_/server_application_traffic_secret_N+1을 생성한 다음
섹션 7.3에 설명된 대로 트래픽 키를 다시 파생하여 계산된다.
다음 세대 application_traffic_secret은 다음과 같이 계산된다.
application_traffic_secret_N+1 =
HKDF-Expand-Label(application_traffic_secret_N,
"traffic upd", "", Hash.length)
client_/server_application_traffic_secret_N+1 및 그 연관 트래픽 키가
계산되면, 구현은 client_/server_application_traffic_secret_N 및 그
연관 트래픽 키를 삭제해야 한다(SHOULD).
Rescorla 표준 트랙 [94페이지]
RFC 8446 TLS 2018년 8월
7.3. 트래픽 키 계산
트래픽 키 자료는 다음 입력 값에서 생성된다.
- 시크릿 값
- 생성되는 특정 값을 나타내는 목적 값
- 생성되는 키의 길이
트래픽 키 자료는 입력 트래픽 시크릿 값을 사용하여 다음과 같이
생성된다.
[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
[sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)
[sender]는 송신 측을 나타낸다. 각 레코드 타입에 대한 Secret의
값은 아래 표에 표시되어 있다.
+-------------------+---------------------------------------+
| 레코드 타입 | Secret |
+-------------------+---------------------------------------+
| 0-RTT Application | client_early_traffic_secret |
| | |
| Handshake | [sender]_handshake_traffic_secret |
| | |
| Application Data | [sender]_application_traffic_secret_N |
+-------------------+---------------------------------------+
기반 Secret이 변경될 때마다(예: 핸드셰이크에서 Application Data 키로
변경하거나 키 갱신 시) 모든 트래픽 키 자료가 다시 계산된다.
7.4. (EC)DHE 공유 시크릿 계산
7.4.1. 유한체 Diffie-Hellman
유한체 그룹의 경우, 전통적인 Diffie-Hellman [DH76] 계산이 수행된다.
협상된 키(Z)는 빅 엔디언 형식으로 인코딩되고 소수의 크기까지 왼쪽에
0으로 패딩되어 바이트 문자열로 변환된다. 이 바이트 문자열은 위에
지정된 대로 키 스케줄에서 공유 시크릿으로 사용된다.
이 구성은 선행 0을 제거했던 이전 TLS 버전과 다르다는 점에 유의하라.
Rescorla 표준 트랙 [95페이지]
RFC 8446 TLS 2018년 8월
7.4.2. 타원곡선 Diffie-Hellman
secp256r1, secp384r1 및 secp521r1의 경우, ECDH 계산(매개변수 및 키
생성과 공유 시크릿 계산 포함)은 [IEEE1363]에 따라, 키 파생 함수
(KDF)로 identity map을 사용하는 ECKAS-DH1 방식을 사용하여 수행된다.
따라서 공유 시크릿은 옥텟 문자열로 표현된 ECDH 공유 시크릿 타원곡선
포인트의 x 좌표이다. FE2OSP(Field Element to Octet String Conversion
Primitive)가 출력하는 이 옥텟 문자열(IEEE 1363 용어로 "Z")은 주어진
필드에 대해 일정한 길이를 가지며, 이 옥텟 문자열에서 발견되는
선행 0은 잘려서는 안 된다(MUST NOT).
(identity KDF의 이 사용은 기술적 세부사항이라는 점에 유의하라. 전체
그림은 TLS가 이 시크릿을 다른 시크릿 계산 외에는 어떤 것에도 직접
사용하지 않기 때문에 ECDH가 비자명한 KDF와 함께 사용된다는 것이다.)
X25519와 X448의 경우, ECDH 계산은 다음과 같다.
- KeyShareEntry.key_exchange 구조에 넣을 공개 키는 적절한 길이의
비밀 키(스칼라 입력으로)와 표준 공개 basepoint(u-coordinate point
입력으로)에 ECDH 스칼라 곱셈 함수를 적용한 결과이다.
- ECDH 공유 시크릿은 비밀 키(스칼라 입력으로)와 피어의 공개 키
(u-coordinate point 입력으로)에 ECDH 스칼라 곱셈 함수를 적용한
결과이다. 출력은 아무 처리 없이 그대로 사용된다.
이 곡선들에 대해 구현은 Diffie-Hellman 공유 시크릿을 계산하기 위해
[RFC7748]에 지정된 접근법을 사용해야 한다(SHOULD). 구현은 계산된
Diffie-Hellman 공유 시크릿이 모두 0인 값인지 검사하고, 그렇다면
[RFC7748]의 섹션 6에 설명된 대로 중단해야 한다(MUST). 구현자가
이러한 타원곡선의 대체 구현을 사용하는 경우, [RFC7748]의 섹션 7에
지정된 추가 검사를 수행해야 한다(SHOULD).
Rescorla 표준 트랙 [96페이지]
RFC 8446 TLS 2018년 8월
7.5. 익스포터
[RFC5705]는 TLS 의사난수 함수(PRF)의 관점에서 TLS용 키 자료
익스포터를 정의한다. 이 문서는 PRF를 HKDF로 대체하므로 새 구성이
필요하다. 익스포터 인터페이스는 동일하게 유지된다.
익스포터 값은 다음과 같이 계산된다.
TLS-Exporter(label, context_value, key_length) =
HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
"exporter", Hash(context_value), key_length)
여기서 Secret은 early_exporter_master_secret 또는
exporter_master_secret이다. 구현은 애플리케이션이 명시적으로 지정하지
않는 한 exporter_master_secret을 사용해야 한다(MUST).
early_exporter_master_secret은 0-RTT 데이터에 익스포터가 필요한
설정에서 사용하도록 정의된다. early exporter에 대한 별도 인터페이스가
권장된다(RECOMMENDED). 이는 익스포터 사용자가 일반 익스포터가 필요한
때 실수로 early exporter를 사용하거나 그 반대의 경우를 피하게 한다.
context가 제공되지 않으면, context_value는 길이가 0이다. 따라서
context를 제공하지 않는 것은 빈 context를 제공하는 것과 같은 값을
계산한다. 이는 빈 context가 부재한 context와 다른 출력을 생성했던
이전 TLS 버전과의 변경 사항이다. 이 문서 출판 시점에서, 할당된
exporter label 중 context가 있는 경우와 없는 경우 모두에 사용되는
것은 없다. 향후 명세는 같은 label에 대해 빈 context와 context 없음
모두를 허용하는 익스포터 사용을 정의해서는 안 된다(MUST NOT).
익스포터의 새 사용은 모든 익스포터 계산에서 context를 제공해야
한다(SHOULD). 다만 그 값은 비어 있을 수 있다.
익스포터 레이블 형식에 대한 요구사항은 [RFC5705]의 섹션 4에
정의되어 있다.
Rescorla 표준 트랙 [97페이지]
RFC 8446 TLS 2018년 8월
8. 0-RTT와 재생 방지
섹션 2.3 및 부록 E.5에서 언급했듯이, TLS는 0-RTT 데이터에 대해
내재적인 재생 보호를 제공하지 않는다. 우려해야 할 잠재적 위협은
두 가지이다.
- 0-RTT 데이터의 flight를 단순히 복제하여 재생 공격을 수행하는
네트워크 공격자.
- 클라이언트 재시도 동작을 악용하여 서버가 애플리케이션 메시지의
여러 사본을 수신하도록 만드는 네트워크 공격자. 이 위협은 강건성을
중시하는 클라이언트가 네트워크 오류에 대해 요청 재시도를 시도하기
때문에 이미 어느 정도 존재한다. 그러나 0-RTT는 전역적으로 일관된
서버 상태를 유지하지 않는 모든 서버 시스템에 추가 차원을 더한다.
구체적으로, 서버 시스템에 zone A의 티켓이 zone B에서 수락되지 않는
여러 zone이 있는 경우, 공격자는 A를 의도한 ClientHello와 조기
데이터를 A와 B 모두에 복제할 수 있다. A에서는 데이터가 0-RTT로
수락되지만, B에서는 서버가 0-RTT 데이터를 거부하고 대신 전체
핸드셰이크를 강제한다. 공격자가 A의 ServerHello를 차단하면,
클라이언트는 B와 핸드셰이크를 완료하고 아마도 요청을 재시도하여,
서버 시스템 전체에서 중복이 발생한다.
첫 번째 유형의 공격은 0-RTT 데이터가 최대 한 번만 수락되도록 보장하기
위해 상태를 공유함으로써 방지할 수 있다. 서버는 이 섹션에 설명된
방법 중 하나 또는 동등한 수단을 구현하여 그 수준의 재생 안전성을
제공해야 한다(SHOULD). 그러나 운영상의 우려로 모든 배포가 그 수준의
상태를 유지하지는 않을 것임이 이해된다. 따라서 정상 운영에서
클라이언트는 서버가 이러한 메커니즘 중 어느 것을 실제로 구현하는지
알 수 없으며, 그러므로 재생되어도 안전하다고 판단하는 조기 데이터만
보내야 한다(MUST).
재생의 직접적인 영향 외에도, 일반적으로 멱등적이라고 간주되는
작업조차 많은 수의 재생에 의해 악용될 수 있는 공격 유형이 있다
(타이밍 공격, 리소스 제한 고갈 등, 부록 E.5에 설명됨). 이는
모든 0-RTT 페이로드가 제한된 횟수만 재생될 수 있도록 보장함으로써
완화될 수 있다. 서버는 관련 서비스 인프라 내의 어떤 인스턴스
(기계, 스레드 또는 다른 엔터티)이든 같은 0-RTT 핸드셰이크에 대해
0-RTT를 최대 한 번만 수락하도록 보장해야 한다(MUST). 이는 재생
횟수를 배포 내 서버 인스턴스 수로 제한한다. 이러한 보장은 최근
수신된 ClientHello의 데이터를 로컬에 기록하고 반복을 거부하거나,
동일하거나 더 강한 보장을 제공하는 다른 방법으로 달성할 수 있다.
Rescorla 표준 트랙 [98페이지]
RFC 8446 TLS 2018년 8월
"서버 인스턴스당 최대 한 번" 보장은 최소 요구사항이다. 서버는 가능할
때 0-RTT 재생을 더 제한해야 한다(SHOULD).
두 번째 유형의 공격은 TLS 계층에서 방지할 수 없으며, 어떤 애플리케이션이든
이를 처리해야 한다(MUST). 어떤 종류의 재시도 동작이든 구현하는
클라이언트를 가진 애플리케이션은 이미 어떤 형태의 재생 방어를
구현해야 한다는 점에 유의하라.
8.1. 일회용 티켓
가장 단순한 재생 방어 형태는 서버가 각 세션 티켓을 한 번만 사용할
수 있도록 허용하는 것이다. 예를 들어 서버는 모든 미결 유효 티켓의
데이터베이스를 유지하고, 각 티켓이 사용될 때 데이터베이스에서
삭제할 수 있다. 알 수 없는 티켓이 제공되면, 서버는 전체 핸드셰이크로
폴백한다.
티켓이 자체 포함된 것이 아니라 데이터베이스 키이고, 대응하는 PSK가
사용 시 삭제된다면, PSK를 사용해 설정된 연결은 순방향 비밀성을
누린다. 이는 PSK가 (EC)DHE 없이 사용될 때 모든 0-RTT 데이터 및 PSK
사용에 대한 보안을 향상시킨다.
이 메커니즘은 여러 분산 서버가 있는 환경에서 서버 노드 사이에 세션
데이터베이스를 공유해야 하므로, 자체 암호화 티켓과 비교해 높은
성공률의 PSK 0-RTT 연결을 달성하기 어려울 수 있다. 세션 데이터베이스와
달리 세션 티켓은 일관된 저장소 없이도 PSK 기반 세션 설정을 성공적으로
수행할 수 있다. 하지만 0-RTT가 허용되는 경우, 다음 섹션에 자세히
설명된 대로 0-RTT 데이터의 재생 방지를 위해 여전히 일관된 저장소가
필요하다.
8.2. ClientHello 기록
재생 방지의 대안적 형태는 ClientHello에서 파생된 고유 값(일반적으로
random 값 또는 PSK binder)을 기록하고 중복을 거부하는 것이다. 모든
ClientHello를 기록하면 상태가 무한히 증가하지만, 서버는 대신 주어진
시간 창 내의 ClientHello를 기록하고 "obfuscated_ticket_age"를 사용하여
티켓이 그 창 밖에서 재사용되지 않도록 보장할 수 있다.
이를 구현하기 위해, ClientHello가 수신되면 서버는 먼저
섹션 4.2.11에 설명된 대로 PSK binder를 검증한다. 그런 다음 다음
섹션에 설명된 대로 expected_arrival_time을 계산하고, 이것이 기록
창 밖에 있으면 0-RTT를 거부하여 1-RTT 핸드셰이크로 폴백한다.
Rescorla 표준 트랙 [99페이지]
RFC 8446 TLS 2018년 8월
expected_arrival_time이 창 안에 있으면, 서버는 일치하는 ClientHello를
기록했는지 확인한다. 발견되면, "illegal_parameter" 경고와 함께
핸드셰이크를 중단하거나 PSK는 수락하되 0-RTT를 거부한다. 일치하는
ClientHello가 발견되지 않으면, 0-RTT를 수락한 다음 expected_arrival_time이
창 안에 있는 동안 ClientHello를 저장한다. 서버는 Bloom filter와 같은
false positive가 있는 데이터 저장소도 구현할 수 있으며(MAY), 이 경우
명백한 재생에는 0-RTT를 거부하여 응답해야 하지만(MUST), 핸드셰이크를
중단해서는 안 된다(MUST NOT).
서버는 ClientHello의 검증된 섹션에서만 저장 키를 파생해야 한다(MUST).
ClientHello가 여러 PSK 식별자를 포함하면, 공격자는 서버가 이를
검증하지 않을 것이라는 가정(섹션 4.2.11에서 권장됨) 아래 덜
선호되는 식별자에 대해 서로 다른 binder 값을 가진 여러 ClientHello를
만들 수 있다. 즉, 클라이언트가 PSK A와 B를 보내지만 서버가 A를
선호하는 경우, 공격자는 A에 대한 binder에 영향을 주지 않고 B에 대한
binder를 변경할 수 있다. B에 대한 binder가 저장 키의 일부라면, 이
ClientHello는 중복으로 나타나지 않게 되고, 그 결과 ClientHello가
수락되며 replay cache pollution 같은 부작용을 일으킬 수 있다. 다만
0-RTT 데이터는 다른 키를 사용하므로 복호화될 수 없다. 검증된 binder
또는 ClientHello.random이 저장 키로 사용되면, 이 공격은 불가능하다.
이 메커니즘은 모든 미결 티켓을 저장할 필요가 없으므로, 재개 및
0-RTT 비율이 높은 분산 시스템에서 구현하기 더 쉬울 수 있다. 그러나
수신된 ClientHello 메시지를 신뢰성 있게 저장하고 검색하기 어렵기
때문에 잠재적으로 더 약한 재생 방어를 대가로 한다. 많은 이러한
시스템에서는 수신된 모든 ClientHello의 전역적으로 일관된 저장소를
갖는 것이 비현실적이다. 이 경우, 주어진 티켓에 대해 단일 저장 zone이
권위를 가지도록 하고, 다른 모든 zone에서 그 티켓에 대해 0-RTT를
거부함으로써 최선의 재생 방지 보호가 제공된다. 이 접근법은 하나의
zone만 0-RTT 데이터를 수락하므로 공격자의 단순 재생을 방지한다.
더 약한 설계는 각 zone에 별도의 저장소를 구현하지만 어떤 zone에서도
0-RTT를 허용하는 것이다. 이 접근법은 재생 횟수를 zone당 한 번으로
제한한다. 물론 애플리케이션 메시지 중복은 어느 설계에서도 여전히
가능하다.
구현이 새로 시작될 때는, 기록 창의 어느 부분이든 시작 시간과 겹치는
동안 0-RTT를 거부해야 한다(SHOULD). 그렇지 않으면 해당 기간에 원래
전송된 재생을 수락할 위험이 있다.
Rescorla 표준 트랙 [100페이지]
RFC 8446 TLS 2018년 8월
참고: 클라이언트의 시계가 서버의 시계보다 훨씬 빠르게 동작하는 경우,
ClientHello가 미래의 창 밖에서 수신될 수 있으며, 이 경우 1-RTT로
수락되어 클라이언트 재시도를 유발하고 나중에 0-RTT에 대해 허용
가능해질 수 있다. 이는 섹션 8에 설명된 두 번째 형태의 공격의
또 다른 변형이다.
8.3. 신선도 검사
ClientHello는 클라이언트가 이를 보낸 시간을 나타내므로, ClientHello가
합리적으로 최근에 보내졌을 가능성이 있는지 효율적으로 판단하고
그러한 ClientHello에 대해서만 0-RTT를 수락하며, 그렇지 않으면
1-RTT 핸드셰이크로 폴백할 수 있다. 이는 섹션 8.2에 설명된
ClientHello 저장 메커니즘에 필요하다. 그렇지 않으면 서버가 무제한의
ClientHello를 저장해야 하기 때문이다. 또한 자체 포함된 일회용
티켓에 유용한 최적화인데, 0-RTT에 사용할 수 없는 ClientHello를
효율적으로 거부할 수 있기 때문이다.
이 메커니즘을 구현하기 위해, 서버는 서버가 세션 티켓을 생성한
시간을 클라이언트와 서버 사이의 왕복 시간 추정치만큼 오프셋하여
저장해야 한다. 즉,
adjusted_creation_time = creation_time + estimated_RTT
이 값은 티켓에 인코딩될 수 있으므로, 각 미결 티켓에 대해 상태를
유지할 필요를 피한다. 서버는 클라이언트의 "pre_shared_key" 확장의
"obfuscated_ticket_age" 매개변수에서 티켓의 "ticket_age_add" 값을
빼서, 티켓 나이에 대한 클라이언트의 관점을 결정할 수 있다. 서버는
ClientHello의 expected_arrival_time을 다음과 같이 결정할 수 있다.
expected_arrival_time = adjusted_creation_time + clients_ticket_age
새 ClientHello가 수신되면, expected_arrival_time은 현재 서버 벽시계
시간과 비교되고, 이 둘이 일정량 이상 차이 나면 0-RTT는 거부된다.
다만 1-RTT 핸드셰이크는 완료되도록 허용될 수 있다.
Rescorla 표준 트랙 [101페이지]
RFC 8446 TLS 2018년 8월
expected_arrival_time과 측정된 시간 사이의 불일치를 유발할 수 있는
잠재적 오류 원인은 여러 가지가 있다. 클라이언트와 서버 시계 속도의
변동은 최소일 가능성이 높지만, 절대 시간은 큰 값만큼 벗어날 수 있다.
네트워크 전파 지연은 경과 시간의 적법한 값에서 불일치가 발생하는
가장 가능성 높은 원인이다. NewSessionTicket 및 ClientHello 메시지는
재전송되어 지연될 수 있고, 이는 TCP에 의해 숨겨질 수 있다. 인터넷의
클라이언트에 대해 이는 시계 오류와 측정 변동을 고려하기 위해 대략
10초 정도의 창을 의미한다. 다른 배포 시나리오는 다른 요구를 가질 수
있다. 시계 skew 분포는 대칭이 아니므로, 최적의 절충은 허용 가능한
불일치 값의 비대칭 범위를 포함할 수 있다.
신선도 검사만으로는 재생을 방지하기에 충분하지 않다는 점에 유의하라.
이는 오류 창 동안 재생을 감지하지 못하며, 이 창은 대역폭과 시스템
용량에 따라 실제 환경에서 수십억 건의 재생을 포함할 수 있기 때문이다.
또한 이 신선도 검사는 ClientHello가 수신되는 시점에만 수행되고,
이후의 조기 Application Data 레코드가 수신될 때는 수행되지 않는다.
조기 데이터가 수락된 뒤, 레코드는 더 긴 기간 동안 계속 서버로
스트리밍될 수 있다.
9. 준수 요구사항
9.1. 구현 필수 암호 스위트
달리 지정하는 애플리케이션 프로파일 표준이 없는 경우:
TLS 준수 애플리케이션은 TLS_AES_128_GCM_SHA256 [GCM] 암호 스위트를
구현해야 하며(MUST), TLS_AES_256_GCM_SHA384 [GCM] 및
TLS_CHACHA20_POLY1305_SHA256 [RFC8439] 암호 스위트를 구현해야 한다
(SHOULD)(부록 B.4 참조).
TLS 준수 애플리케이션은 rsa_pkcs1_sha256(인증서용),
rsa_pss_rsae_sha256(CertificateVerify 및 인증서용), 그리고
ecdsa_secp256r1_sha256을 사용한 디지털 서명을 지원해야 한다(MUST).
TLS 준수 애플리케이션은 secp256r1(NIST P-256)을 사용한 키 교환을
지원해야 하며(MUST), X25519 [RFC7748]를 사용한 키 교환을 지원해야
한다(SHOULD).
Rescorla 표준 트랙 [102페이지]
RFC 8446 TLS 2018년 8월
9.2. 구현 필수 확장
달리 지정하는 애플리케이션 프로파일 표준이 없는 경우, TLS 준수
애플리케이션은 다음 TLS 확장을 구현해야 한다(MUST).
- Supported Versions ("supported_versions"; 섹션 4.2.1)
- Cookie ("cookie"; 섹션 4.2.2)
- Signature Algorithms ("signature_algorithms"; 섹션 4.2.3)
- Signature Algorithms Certificate ("signature_algorithms_cert";
섹션 4.2.3)
- Negotiated Groups ("supported_groups"; 섹션 4.2.7)
- Key Share ("key_share"; 섹션 4.2.8)
- Server Name Indication ("server_name"; [RFC6066]의 섹션 3)
모든 구현은 적용 가능한 기능을 제공할 때 이 확장들을 보내고 사용해야
한다(MUST).
- "supported_versions"는 모든 ClientHello, ServerHello 및
HelloRetryRequest 메시지에 대해 필수이다(REQUIRED).
- "signature_algorithms"는 인증서 인증에 필수이다(REQUIRED).
- "supported_groups"는 DHE 또는 ECDHE 키 교환을 사용하는 ClientHello
메시지에 필수이다(REQUIRED).
- "key_share"는 DHE 또는 ECDHE 키 교환에 필수이다(REQUIRED).
- "pre_shared_key"는 PSK 키 합의에 필수이다(REQUIRED).
- "psk_key_exchange_modes"는 PSK 키 합의에 필수이다(REQUIRED).
Rescorla 표준 트랙 [103페이지]
RFC 8446 TLS 2018년 8월
ClientHello가 본문에 0x0304를 포함하는 "supported_versions" 확장을
포함하면, 클라이언트는 이 명세를 사용하여 협상을 시도하는 것으로
간주된다. 그러한 ClientHello 메시지는 다음 요구사항을 충족해야
한다(MUST).
- "pre_shared_key" 확장을 포함하지 않는 경우, "signature_algorithms"
확장과 "supported_groups" 확장을 모두 포함해야 한다(MUST).
- "supported_groups" 확장을 포함하는 경우, "key_share" 확장도 포함해야
하며(MUST), 그 반대도 마찬가지이다. 빈 KeyShare.client_shares
벡터는 허용된다.
이러한 요구사항에 부합하지 않는 ClientHello를 수신한 서버는
"missing_extension" 경고와 함께 핸드셰이크를 중단해야 한다(MUST).
추가로, 모든 구현은 이를 사용할 수 있는 애플리케이션과 함께
"server_name" 확장의 사용을 지원해야 한다(MUST). 서버는 클라이언트가
유효한 "server_name" 확장을 보내도록 요구할 수 있다(MAY). 이 확장을
요구하는 서버는 "server_name" 확장이 없는 ClientHello에 대해
"missing_extension" 경고와 함께 연결을 종료하여 응답해야 한다(SHOULD).
9.3. 프로토콜 불변성
이 섹션은 TLS 엔드포인트와 미들박스가 따라야 하는 불변성을 설명한다
(MUST). 이는 이전 TLS 버전에도 적용된다.
TLS는 안전하고 호환 가능하게 확장 가능하도록 설계되었다. 더 새로운
클라이언트 또는 서버는 더 새로운 피어와 통신할 때 가장 선호되는
공통 매개변수를 협상해야 한다. TLS 핸드셰이크는 다운그레이드 보호를
제공한다. TLS를 종료하지 않고 더 새로운 클라이언트와 더 새로운 서버
사이의 트래픽을 전달하는 미들박스는 핸드셰이크에 영향을 줄 수 없어야
한다(부록 E.1 참조). 동시에 배포는 서로 다른 속도로 업데이트되므로,
더 새로운 클라이언트 또는 서버는 더 오래된 엔드포인트와 상호 운용할
수 있도록 오래된 매개변수를 계속 지원할 수 있다(MAY).
Rescorla 표준 트랙 [104페이지]
RFC 8446 TLS 2018년 8월
이것이 작동하려면, 구현은 확장 가능한 필드를 올바르게 처리해야
한다(MUST).
- ClientHello를 보내는 클라이언트는 그 안에 광고된 모든 매개변수를
지원해야 한다(MUST). 그렇지 않으면 서버가 그 매개변수 중 하나를
선택함으로써 상호 운용에 실패할 수 있다.
- ClientHello를 수신한 서버는 인식하지 못하는 모든 암호 스위트,
확장 및 기타 매개변수를 올바르게 무시해야 한다(MUST). 그렇지
않으면 더 새로운 클라이언트와의 상호 운용에 실패할 수 있다.
TLS 1.3에서는 CertificateRequest 또는 NewSessionTicket을 수신한
클라이언트도 인식하지 못하는 모든 확장을 무시해야 한다(MUST).
- TLS 연결을 종료하는 미들박스는 (원래 클라이언트에 대해) 준수
TLS 서버로 동작해야 하며(MUST), 여기에는 클라이언트가 수락할
의향이 있는 인증서를 보유하는 것이 포함된다. 또한 (원래 서버에
대해) 준수 TLS 클라이언트로도 동작해야 하며(MUST), 여기에는 원래
서버의 인증서를 검증하는 것이 포함된다. 특히, 미들박스는 자신이
이해하는 매개변수만 포함하는 자체 ClientHello를 생성해야 하며(MUST),
엔드포인트의 값을 전달하는 대신 새로운 ServerHello random 값을
생성해야 한다(MUST).
TLS의 프로토콜 요구사항과 보안 분석은 두 연결에 별도로만 적용된다는
점에 유의하라. TLS terminator를 안전하게 배포하려면 이 문서의
범위를 벗어나는 추가 보안 고려사항이 필요하다.
- 자신이 이해하지 못하는 ClientHello 매개변수를 전달하는 미들박스는
그 ClientHello 이후의 어떤 메시지도 처리해서는 안 된다(MUST NOT).
모든 이후 트래픽을 수정 없이 전달해야 한다(MUST). 그렇지 않으면
더 새로운 클라이언트 및 서버와의 상호 운용에 실패할 수 있다.
전달된 ClientHello는 미들박스가 지원하지 않는 기능에 대한 광고를
포함할 수 있으므로, 응답은 미들박스가 인식하지 못하는 향후 TLS
추가사항을 포함할 수 있다. 이러한 추가사항은 ClientHello 이후의
모든 메시지를 임의로 변경할 수 있다(MAY). 특히 ServerHello에서
전송되는 값이 변경될 수 있고, ServerHello 형식이 변경될 수 있으며,
TLSCiphertext 형식이 변경될 수 있다.
TLS 1.3의 설계는 널리 배포된 비준수 TLS 미들박스에 의해 제약을 받았다
(부록 D.4 참조). 그러나 불변성을 완화하지는 않는다. 그러한
미들박스는 계속 비준수이다.
Rescorla 표준 트랙 [105페이지]
RFC 8446 TLS 2018년 8월
10. 보안 고려사항
보안 문제는 이 메모 전반, 특히 부록 C, D 및 E에서 논의된다.
11. IANA 고려사항
이 문서는 원래 [RFC4346]에서 생성되고 [RFC8447]에서 갱신된 여러
레지스트리를 사용한다. IANA는 이 문서를 참조하도록 이들을 갱신했다.
레지스트리와 그 할당 정책은 아래와 같다.
- TLS Cipher Suites 레지스트리: 첫 번째 바이트가 0-254(십진수) 범위인
값은 Specification Required [RFC8126]를 통해 할당된다. 첫 번째
바이트가 255(십진수)인 값은 Private Use [RFC8126]를 위해
예약된다.
IANA는 부록 B.4에 나열된 암호 스위트를 레지스트리에 추가했다.
"Value" 및 "Description" 열은 표에서 가져온다. "DTLS-OK" 및
"Recommended" 열은 각 새 암호 스위트에 대해 모두 "Y"로 표시된다.
- TLS ContentType 레지스트리: 향후 값은 Standards Action [RFC8126]를
통해 할당된다.
- TLS Alerts 레지스트리: 향후 값은 Standards Action [RFC8126]를 통해
할당된다. IANA는 이 레지스트리를 부록 B.2의 값으로 채웠다.
"DTLS-OK" 열은 이러한 모든 값에 대해 "Y"로 표시된다. "_RESERVED"로
표시된 값에는 이전 사용을 설명하는 주석이 있다.
- TLS HandshakeType 레지스트리: 향후 값은 Standards Action [RFC8126]를
통해 할당된다. IANA는 항목 4의 이름을 "NewSessionTicket"에서
"new_session_ticket"으로 바꾸도록 이 레지스트리를 갱신했고,
부록 B.3의 값으로 이 레지스트리를 채웠다. "DTLS-OK" 열은
이러한 모든 값에 대해 "Y"로 표시된다. "_RESERVED"로 표시된 값에는
이전 또는 임시 사용을 설명하는 주석이 있다.
Rescorla 표준 트랙 [106페이지]
RFC 8446 TLS 2018년 8월
이 문서는 또한 원래 [RFC4366]에서 생성된 TLS ExtensionType Values
레지스트리를 사용한다. IANA는 이 문서를 참조하도록 이를 갱신했다.
레지스트리 변경 사항은 다음과 같다.
- IANA는 등록 정책을 다음과 같이 갱신했다.
첫 번째 바이트가 0-254(십진수) 범위인 값은 Specification Required
[RFC8126]를 통해 할당된다. 첫 번째 바이트가 255(십진수)인 값은
Private Use [RFC8126]를 위해 예약된다.
- IANA는 이 문서에 정의된 값과 "Recommended" 값 "Y"로, "key_share",
"pre_shared_key", "psk_key_exchange_modes", "early_data",
"cookie", "supported_versions", "certificate_authorities",
"oid_filters", "post_handshake_auth", 그리고
"signature_algorithms_cert" 확장을 포함하도록 이 레지스트리를
갱신했다.
- IANA는 이 확장이 나타날 수 있는 메시지를 나열하는 "TLS 1.3" 열을
포함하도록 이 레지스트리를 갱신했다. 이 열은 섹션 4.2의 표에서
처음 채워졌으며, 그곳에 나열되지 않은 모든 확장은 TLS 1.3에서
사용되지 않음을 나타내기 위해 "-"로 표시된다.
이 문서는 원래 [RFC6091]에서 생성되고 [RFC8447]에서 갱신된 TLS
Certificate Types 레지스트리의 항목 하나를 갱신한다. IANA는 값 1의
항목이 이름 "OpenPGP_RESERVED", "Recommended" 값 "N", 그리고 주석
"Used in TLS versions prior to 1.3."을 가지도록 갱신했다.
이 문서는 원래 [RFC6961]에서 생성된 TLS Certificate Status Types
레지스트리의 항목 하나를 갱신한다. IANA는 값 2의 항목이 이름
"ocsp_multi_RESERVED"와 주석 "Used in TLS versions prior to 1.3"을
가지도록 갱신했다.
이 문서는 TLS Supported Groups 레지스트리([RFC4492]에 의해 다른
이름으로 생성되었고, 현재 [RFC8422]가 유지하며, [RFC7919] 및
[RFC8447]에 의해 갱신됨)의 두 항목을 갱신한다. 값 29와 30
(x25519 및 x448)에 대한 항목은 이 문서도 참조하도록 갱신되었다.
Rescorla 표준 트랙 [107페이지]
RFC 8446 TLS 2018년 8월
또한 이 문서는 IANA가 유지하는 두 개의 새 레지스트리를 정의한다.
- TLS SignatureScheme 레지스트리: 첫 번째 바이트가 0-253(십진수)
범위인 값은 Specification Required [RFC8126]를 통해 할당된다.
첫 번째 바이트가 254 또는 255(십진수)인 값은 Private Use
[RFC8126]를 위해 예약된다. 첫 번째 바이트가 0-6 범위이거나
두 번째 바이트가 0-3 범위인 현재 할당되지 않은 값은 하위 호환성을
위해 예약된다. 이 레지스트리는 "Recommended" 열을 가진다.
레지스트리는 섹션 4.2.3에 설명된 값으로 처음 채워졌다.
다음 값은 "Recommended"로 표시된다.
ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,
rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,
rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, 그리고
ed25519. "Recommended" 열은 명시적으로 요청되지 않는 한 "N" 값이
할당되며, "Recommended" 값 "Y"를 가진 값을 추가하려면 Standards
Action [RFC8126]가 필요하다. Y->N 전환에는 IESG 승인이
필요하다(REQUIRED).
- TLS PskKeyExchangeMode 레지스트리: 0-253(십진수) 범위의 값은
Specification Required [RFC8126]를 통해 할당된다. 254와 255
(십진수) 값은 Private Use [RFC8126]를 위해 예약된다. 이
레지스트리는 "Recommended" 열을 가진다. 레지스트리는 psk_ke (0)와
psk_dhe_ke (1)로 처음 채워졌다. 둘 다 "Recommended"로 표시된다.
"Recommended" 열은 명시적으로 요청되지 않는 한 "N" 값이 할당되며,
"Recommended" 값 "Y"를 가진 값을 추가하려면 Standards Action
[RFC8126]가 필요하다. Y->N 전환에는 IESG 승인이 필요하다
(REQUIRED).
Rescorla 표준 트랙 [108페이지]
RFC 8446 TLS 2018년 8월
12. 참고문헌
12.1. 규범적 참고문헌
[DH76] Diffie, W. and M. Hellman, "New directions in
cryptography", IEEE Transactions on Information
Theory, Vol. 22 No. 6, pp. 644-654,
DOI 10.1109/TIT.1976.1055638, November 1976.
[ECDSA] American National Standards Institute, "Public Key
Cryptography for the Financial Services Industry: The
Elliptic Curve Digital Signature Algorithm (ECDSA)",
ANSI ANS X9.62-2005, November 2005.
[GCM] Dworkin, M., "Recommendation for Block Cipher Modes of
Operation: Galois/Counter Mode (GCM) and GMAC",
NIST Special Publication 800-38D,
DOI 10.6028/NIST.SP.800-38D, November 2007.
[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
Hashing for Message Authentication", RFC 2104,
DOI 10.17487/RFC2104, February 1997,
<https://www.rfc-editor.org/info/rfc2104>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC5116] McGrew, D., "An Interface and Algorithms for Authenticated
Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008,
<https://www.rfc-editor.org/info/rfc5116>.
[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
Housley, R., and W. Polk, "Internet X.509 Public Key
Infrastructure Certificate and Certificate Revocation List
(CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
<https://www.rfc-editor.org/info/rfc5280>.
[RFC5705] Rescorla, E., "Keying Material Exporters for Transport
Layer Security (TLS)", RFC 5705, DOI 10.17487/RFC5705,
March 2010, <https://www.rfc-editor.org/info/rfc5705>.
[RFC5756] Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk,
"Updates for RSAES-OAEP and RSASSA-PSS Algorithm
Parameters", RFC 5756, DOI 10.17487/RFC5756, January 2010,
<https://www.rfc-editor.org/info/rfc5756>.
Rescorla 표준 트랙 [109페이지]
RFC 8446 TLS 2018년 8월
[RFC5869] Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
Key Derivation Function (HKDF)", RFC 5869,
DOI 10.17487/RFC5869, May 2010,
<https://www.rfc-editor.org/info/rfc5869>.
[RFC6066] Eastlake 3rd, D., "Transport Layer Security (TLS)
Extensions: Extension Definitions", RFC 6066,
DOI 10.17487/RFC6066, January 2011,
<https://www.rfc-editor.org/info/rfc6066>.
[RFC6655] McGrew, D. and D. Bailey, "AES-CCM Cipher Suites for
Transport Layer Security (TLS)", RFC 6655,
DOI 10.17487/RFC6655, July 2012,
<https://www.rfc-editor.org/info/rfc6655>.
[RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A.,
Galperin, S., and C. Adams, "X.509 Internet Public Key
Infrastructure Online Certificate Status Protocol - OCSP",
RFC 6960, DOI 10.17487/RFC6960, June 2013,
<https://www.rfc-editor.org/info/rfc6960>.
[RFC6961] Pettersen, Y., "The Transport Layer Security (TLS)
Multiple Certificate Status Request Extension", RFC 6961,
DOI 10.17487/RFC6961, June 2013,
<https://www.rfc-editor.org/info/rfc6961>.
[RFC6962] Laurie, B., Langley, A., and E. Kasper, "Certificate
Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
<https://www.rfc-editor.org/info/rfc6962>.
[RFC6979] Pornin, T., "Deterministic Usage of the Digital Signature
Algorithm (DSA) and Elliptic Curve Digital Signature
Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979,
August 2013, <https://www.rfc-editor.org/info/rfc6979>.
[RFC7301] Friedl, S., Popov, A., Langley, A., and E. Stephan,
"Transport Layer Security (TLS) Application-Layer Protocol
Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301,
July 2014, <https://www.rfc-editor.org/info/rfc7301>.
[RFC7507] Moeller, B. and A. Langley, "TLS Fallback Signaling Cipher
Suite Value (SCSV) for Preventing Protocol Downgrade
Attacks", RFC 7507, DOI 10.17487/RFC7507, April 2015,
<https://www.rfc-editor.org/info/rfc7507>.
[RFC7748] Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves
for Security", RFC 7748, DOI 10.17487/RFC7748,
January 2016, <https://www.rfc-editor.org/info/rfc7748>.
Rescorla 표준 트랙 [110페이지]
RFC 8446 TLS 2018년 8월
[RFC7919] Gillmor, D., "Negotiated Finite Field Diffie-Hellman
Ephemeral Parameters for Transport Layer Security (TLS)",
RFC 7919, DOI 10.17487/RFC7919, August 2016,
<https://www.rfc-editor.org/info/rfc7919>.
[RFC8017] Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch,
"PKCS #1: RSA Cryptography Specifications Version 2.2",
RFC 8017, DOI 10.17487/RFC8017, November 2016,
<https://www.rfc-editor.org/info/rfc8017>.
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
Signature Algorithm (EdDSA)", RFC 8032,
DOI 10.17487/RFC8032, January 2017,
<https://www.rfc-editor.org/info/rfc8032>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in
RFC 2119 Key Words", BCP 14, RFC 8174,
DOI 10.17487/RFC8174, May 2017,
<https://www.rfc-editor.org/info/rfc8174>.
[RFC8439] Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF
Protocols", RFC 8439, DOI 10.17487/RFC8439, June 2018,
<https://www.rfc-editor.org/info/rfc8439>.
[SHS] Dang, Q., "Secure Hash Standard (SHS)", National Institute
of Standards and Technology report,
DOI 10.6028/NIST.FIPS.180-4, August 2015.
[X690] ITU-T, "Information technology -- ASN.1 encoding rules:
Specification of Basic Encoding Rules (BER), Canonical
Encoding Rules (CER) and Distinguished Encoding Rules
(DER)", ISO/IEC 8825-1:2015, November 2015.
Rescorla 표준 트랙 [111페이지]
RFC 8446 TLS 2018년 8월
12.2. 정보성 참고문헌
[AEAD-LIMITS]
Luykx, A. and K. Paterson, "Limits on Authenticated
Encryption Use in TLS", August 2017,
<http://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf>.
[BBFGKZ16]
Bhargavan, K., Brzuska, C., Fournet, C., Green, M.,
Kohlweiss, M., and S. Zanella-Beguelin, "Downgrade
Resilience in Key-Exchange Protocols", Proceedings of IEEE
Symposium on Security and Privacy (San Jose),
DOI 10.1109/SP.2016.37, May 2016.
[BBK17] Bhargavan, K., Blanchet, B., and N. Kobeissi, "Verified
Models and Reference Implementations for the TLS 1.3
Standard Candidate", Proceedings of IEEE Symposium on
Security and Privacy (San Jose), DOI 10.1109/SP.2017.26,
May 2017.
[BDFKPPRSZZ16]
Bhargavan, K., Delignat-Lavaud, A., Fournet, C.,
Kohlweiss, M., Pan, J., Protzenko, J., Rastogi, A., Swamy,
N., Zanella-Beguelin, S., and J. Zinzindohoue,
"Implementing and Proving the TLS 1.3 Record Layer",
Proceedings of IEEE Symposium on Security and Privacy (San
Jose), May 2017, <https://eprint.iacr.org/2016/1178>.
[Ben17a] Benjamin, D., "Presentation before the TLS WG at
IETF 100", November 2017,
<https://datatracker.ietf.org/meeting/100/materials/
slides-100-tls-sessa-tls13/>.
[Ben17b] Benjamin, D., "Additional TLS 1.3 results from Chrome",
message to the TLS mailing list, 18 December 2017,
<https://www.ietf.org/mail-archive/web/tls/current/
msg25168.html>.
[Blei98] Bleichenbacher, D., "Chosen Ciphertext Attacks against
Protocols Based on RSA Encryption Standard PKCS #1",
Proceedings of CRYPTO '98, 1998.
[BMMRT15] Badertscher, C., Matt, C., Maurer, U., Rogaway, P., and B.
Tackmann, "Augmented Secure Channels and the Goal of the
TLS 1.3 Record Layer", ProvSec 2015, September 2015,
<https://eprint.iacr.org/2015/394>.
Rescorla 표준 트랙 [112페이지]
RFC 8446 TLS 2018년 8월
[BT16] Bellare, M. and B. Tackmann, "The Multi-User Security of
Authenticated Encryption: AES-GCM in TLS 1.3", Proceedings
of CRYPTO 2016, July 2016,
<https://eprint.iacr.org/2016/564>.
[CCG16] Cohn-Gordon, K., Cremers, C., and L. Garratt, "On
Post-compromise Security", IEEE Computer Security
Foundations Symposium, DOI 10.1109/CSF.2016.19, July 2015.
[CHECKOWAY]
Checkoway, S., Maskiewicz, J., Garman, C., Fried, J.,
Cohney, S., Green, M., Heninger, N., Weinmann, R.,
Rescorla, E., and H. Shacham, "A Systematic Analysis of
the Juniper Dual EC Incident", Proceedings of the 2016 ACM
SIGSAC Conference on Computer and Communications Security
- CCS '16, DOI 10.1145/2976749.2978395, October 2016.
[CHHSV17] Cremers, C., Horvat, M., Hoyland, J., Scott, S., and T.
van der Merwe, "Awkward Handshake: Possible mismatch of
client/server view on client authentication in
post-handshake mode in Revision 18", message to the TLS
mailing list, 10 February 2017, <https://www.ietf.org/
mail-archive/web/tls/current/msg22382.html>.
[CHSV16] Cremers, C., Horvat, M., Scott, S., and T. van der Merwe,
"Automated Analysis and Verification of TLS 1.3: 0-RTT,
Resumption and Delayed Authentication", Proceedings of
IEEE Symposium on Security and Privacy (San Jose),
DOI 10.1109/SP.2016.35, May 2016,
<https://ieeexplore.ieee.org/document/7546518/>.
[CK01] Canetti, R. and H. Krawczyk, "Analysis of Key-Exchange
Protocols and Their Use for Building Secure Channels",
Proceedings of Eurocrypt 2001,
DOI 10.1007/3-540-44987-6_28, April 2001.
[CLINIC] Miller, B., Huang, L., Joseph, A., and J. Tygar, "I Know
Why You Went to the Clinic: Risks and Realization of HTTPS
Traffic Analysis", Privacy Enhancing Technologies, pp.
143-163, DOI 10.1007/978-3-319-08506-7_8, 2014.
[DFGS15] Dowling, B., Fischlin, M., Guenther, F., and D. Stebila,
"A Cryptographic Analysis of the TLS 1.3 Handshake
Protocol Candidates", Proceedings of ACM CCS 2015,
October 2015, <https://eprint.iacr.org/2015/914>.
Rescorla 표준 트랙 [113페이지]
RFC 8446 TLS 2018년 8월
[DFGS16] Dowling, B., Fischlin, M., Guenther, F., and D. Stebila,
"A Cryptographic Analysis of the TLS 1.3 Full and
Pre-shared Key Handshake Protocol", TRON 2016,
February 2016, <https://eprint.iacr.org/2016/081>.
[DOW92] Diffie, W., van Oorschot, P., and M. Wiener,
"Authentication and authenticated key exchanges", Designs,
Codes and Cryptography, DOI 10.1007/BF00124891, June 1992.
[DSS] National Institute of Standards and Technology, U.S.
Department of Commerce, "Digital Signature Standard
(DSS)", NIST FIPS PUB 186-4, DOI 10.6028/NIST.FIPS.186-4,
July 2013.
[FG17] Fischlin, M. and F. Guenther, "Replay Attacks on Zero
Round-Trip Time: The Case of the TLS 1.3 Handshake
Candidates", Proceedings of EuroS&P 2017, April 2017,
<https://eprint.iacr.org/2017/082>.
[FGSW16] Fischlin, M., Guenther, F., Schmidt, B., and B. Warinschi,
"Key Confirmation in Key Exchange: A Formal Treatment and
Implications for TLS 1.3", Proceedings of IEEE Symposium
on Security and Privacy (San Jose),
DOI 10.1109/SP.2016.34, May 2016,
<https://ieeexplore.ieee.org/document/7546517/>.
[FW15] Weimer, F., "Factoring RSA Keys With TLS Perfect Forward
Secrecy", September 2015.
[HCJC16] Husak, M., Cermak, M., Jirsik, T., and P. Celeda, "HTTPS
traffic analysis and client identification using passive
SSL/TLS fingerprinting", EURASIP Journal on Information
Security, Vol. 2016, DOI 10.1186/s13635-016-0030-7,
February 2016.
[HGFS15] Hlauschek, C., Gruber, M., Fankhauser, F., and C. Schanes,
"Prying Open Pandora's Box: KCI Attacks against TLS",
Proceedings of USENIX Workshop on Offensive Technologies,
August 2015.
[IEEE1363]
IEEE, "IEEE Standard Specifications for Public Key
Cryptography", IEEE Std. 1363-2000,
DOI 10.1109/IEEESTD.2000.92292.
Rescorla 표준 트랙 [114페이지]
RFC 8446 TLS 2018년 8월
[JSS15] Jager, T., Schwenk, J., and J. Somorovsky, "On the
Security of TLS 1.3 and QUIC Against Weaknesses in PKCS#1
v1.5 Encryption", Proceedings of ACM CCS 2015,
DOI 10.1145/2810103.2813657, October 2015,
<https://www.nds.rub.de/media/nds/
veroeffentlichungen/2015/08/21/Tls13QuicAttacks.pdf>.
[KEYAGREEMENT]
Barker, E., Chen, L., Roginsky, A., Vassilev, A., and R.
Davis, "Recommendation for Pair-Wise Key Establishment
Schemes Using Discrete Logarithm Cryptography", National
Institute of Standards and Technology,
DOI 10.6028/NIST.SP.800-56Ar3, April 2018.
[Kraw10] Krawczyk, H., "Cryptographic Extraction and Key
Derivation: The HKDF Scheme", Proceedings of CRYPTO 2010,
August 2010, <https://eprint.iacr.org/2010/264>.
[Kraw16] Krawczyk, H., "A Unilateral-to-Mutual Authentication
Compiler for Key Exchange (with Applications to Client
Authentication in TLS 1.3", Proceedings of ACM CCS 2016,
October 2016, <https://eprint.iacr.org/2016/711>.
[KW16] Krawczyk, H. and H. Wee, "The OPTLS Protocol and TLS 1.3",
Proceedings of EuroS&P 2016, March 2016,
<https://eprint.iacr.org/2015/978>.
[LXZFH16] Li, X., Xu, J., Zhang, Z., Feng, D., and H. Hu, "Multiple
Handshakes Security of TLS 1.3 Candidates", Proceedings of
IEEE Symposium on Security and Privacy (San Jose),
DOI 10.1109/SP.2016.36, May 2016,
<https://ieeexplore.ieee.org/document/7546519/>.
[Mac17] MacCarthaigh, C., "Security Review of TLS1.3 0-RTT",
March 2017, <https://github.com/tlswg/tls13-spec/
issues/1001>.
[PS18] Patton, C. and T. Shrimpton, "Partially specified
channels: The TLS 1.3 record layer without elision", 2018,
<https://eprint.iacr.org/2018/634>.
[PSK-FINISHED]
Scott, S., Cremers, C., Horvat, M., and T. van der Merwe,
"Revision 10: possible attack if client authentication is
allowed during PSK", message to the TLS mailing list,
31 October 2015, <https://www.ietf.org/
mail-archive/web/tls/current/msg18215.html>.
Rescorla 표준 트랙 [115페이지]
RFC 8446 TLS 2018년 8월
[REKEY] Abdalla, M. and M. Bellare, "Increasing the Lifetime of a
Key: A Comparative Analysis of the Security of Re-keying
Techniques", ASIACRYPT 2000, DOI 10.1007/3-540-44448-3_42,
October 2000.
[Res17a] Rescorla, E., "Preliminary data on Firefox TLS 1.3
Middlebox experiment", message to the TLS mailing list,
5 December 2017, <https://www.ietf.org/
mail-archive/web/tls/current/msg25091.html>.
[Res17b] Rescorla, E., "More compatibility measurement results",
message to the TLS mailing list, 22 December 2017,
<https://www.ietf.org/mail-archive/web/tls/current/
msg25179.html>.
[RFC3552] Rescorla, E. and B. Korver, "Guidelines for Writing RFC
Text on Security Considerations", BCP 72, RFC 3552,
DOI 10.17487/RFC3552, July 2003,
<https://www.rfc-editor.org/info/rfc3552>.
[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker,
"Randomness Requirements for Security", BCP 106, RFC 4086,
DOI 10.17487/RFC4086, June 2005,
<https://www.rfc-editor.org/info/rfc4086>.
[RFC4346] Dierks, T. and E. Rescorla, "The Transport Layer Security
(TLS) Protocol Version 1.1", RFC 4346,
DOI 10.17487/RFC4346, April 2006,
<https://www.rfc-editor.org/info/rfc4346>.
[RFC4366] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J.,
and T. Wright, "Transport Layer Security (TLS)
Extensions", RFC 4366, DOI 10.17487/RFC4366, April 2006,
<https://www.rfc-editor.org/info/rfc4366>.
[RFC4492] Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B.
Moeller, "Elliptic Curve Cryptography (ECC) Cipher Suites
for Transport Layer Security (TLS)", RFC 4492,
DOI 10.17487/RFC4492, May 2006,
<https://www.rfc-editor.org/info/rfc4492>.
[RFC5077] Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig,
"Transport Layer Security (TLS) Session Resumption without
Server-Side State", RFC 5077, DOI 10.17487/RFC5077,
January 2008, <https://www.rfc-editor.org/info/rfc5077>.
Rescorla 표준 트랙 [116페이지]
RFC 8446 TLS 2018년 8월
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
(TLS) Protocol Version 1.2", RFC 5246,
DOI 10.17487/RFC5246, August 2008,
<https://www.rfc-editor.org/info/rfc5246>.
[RFC5764] McGrew, D. and E. Rescorla, "Datagram Transport Layer
Security (DTLS) Extension to Establish Keys for the Secure
Real-time Transport Protocol (SRTP)", RFC 5764,
DOI 10.17487/RFC5764, May 2010,
<https://www.rfc-editor.org/info/rfc5764>.
[RFC5929] Altman, J., Williams, N., and L. Zhu, "Channel Bindings
for TLS", RFC 5929, DOI 10.17487/RFC5929, July 2010,
<https://www.rfc-editor.org/info/rfc5929>.
[RFC6091] Mavrogiannopoulos, N. and D. Gillmor, "Using OpenPGP Keys
for Transport Layer Security (TLS) Authentication",
RFC 6091, DOI 10.17487/RFC6091, February 2011,
<https://www.rfc-editor.org/info/rfc6091>.
[RFC6101] Freier, A., Karlton, P., and P. Kocher, "The Secure
Sockets Layer (SSL) Protocol Version 3.0", RFC 6101,
DOI 10.17487/RFC6101, August 2011,
<https://www.rfc-editor.org/info/rfc6101>.
[RFC6176] Turner, S. and T. Polk, "Prohibiting Secure Sockets Layer
(SSL) Version 2.0", RFC 6176, DOI 10.17487/RFC6176,
March 2011, <https://www.rfc-editor.org/info/rfc6176>.
[RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer
Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347,
January 2012, <https://www.rfc-editor.org/info/rfc6347>.
[RFC6520] Seggelmann, R., Tuexen, M., and M. Williams, "Transport
Layer Security (TLS) and Datagram Transport Layer Security
(DTLS) Heartbeat Extension", RFC 6520,
DOI 10.17487/RFC6520, February 2012,
<https://www.rfc-editor.org/info/rfc6520>.
[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
Protocol (HTTP/1.1): Message Syntax and Routing",
RFC 7230, DOI 10.17487/RFC7230, June 2014,
<https://www.rfc-editor.org/info/rfc7230>.
Rescorla 표준 트랙 [117페이지]
RFC 8446 TLS 2018년 8월
[RFC7250] Wouters, P., Ed., Tschofenig, H., Ed., Gilmore, J.,
Weiler, S., and T. Kivinen, "Using Raw Public Keys in
Transport Layer Security (TLS) and Datagram Transport
Layer Security (DTLS)", RFC 7250, DOI 10.17487/RFC7250,
June 2014, <https://www.rfc-editor.org/info/rfc7250>.
[RFC7465] Popov, A., "Prohibiting RC4 Cipher Suites", RFC 7465,
DOI 10.17487/RFC7465, February 2015,
<https://www.rfc-editor.org/info/rfc7465>.
[RFC7568] Barnes, R., Thomson, M., Pironti, A., and A. Langley,
"Deprecating Secure Sockets Layer Version 3.0", RFC 7568,
DOI 10.17487/RFC7568, June 2015,
<https://www.rfc-editor.org/info/rfc7568>.
[RFC7627] Bhargavan, K., Ed., Delignat-Lavaud, A., Pironti, A.,
Langley, A., and M. Ray, "Transport Layer Security (TLS)
Session Hash and Extended Master Secret Extension",
RFC 7627, DOI 10.17487/RFC7627, September 2015,
<https://www.rfc-editor.org/info/rfc7627>.
[RFC7685] Langley, A., "A Transport Layer Security (TLS) ClientHello
Padding Extension", RFC 7685, DOI 10.17487/RFC7685,
October 2015, <https://www.rfc-editor.org/info/rfc7685>.
[RFC7924] Santesson, S. and H. Tschofenig, "Transport Layer Security
(TLS) Cached Information Extension", RFC 7924,
DOI 10.17487/RFC7924, July 2016,
<https://www.rfc-editor.org/info/rfc7924>.
[RFC8305] Schinazi, D. and T. Pauly, "Happy Eyeballs Version 2:
Better Connectivity Using Concurrency", RFC 8305,
DOI 10.17487/RFC8305, December 2017,
<https://www.rfc-editor.org/info/rfc8305>.
[RFC8422] Nir, Y., Josefsson, S., and M. Pegourie-Gonnard, "Elliptic
Curve Cryptography (ECC) Cipher Suites for Transport Layer
Security (TLS) Versions 1.2 and Earlier", RFC 8422,
DOI 10.17487/RFC8422, August 2018,
<https://www.rfc-editor.org/info/rfc8422>.
[RFC8447] Salowey, J. and S. Turner, "IANA Registry Updates for TLS
and DTLS", RFC 8447, DOI 10.17487/RFC8447, August 2018,
<https://www.rfc-editor.org/info/rfc8447>.
[RFC8449] Thomson, M., "Record Size Limit Extension for TLS",
RFC 8449, DOI 10.17487/RFC8449, August 2018,
<https://www.rfc-editor.org/info/rfc8449>.
Rescorla 표준 트랙 [118페이지]
RFC 8446 TLS 2018년 8월
[RSA] Rivest, R., Shamir, A., and L. Adleman, "A Method for
Obtaining Digital Signatures and Public-Key
Cryptosystems", Communications of the ACM, Vol. 21 No. 2,
pp. 120-126, DOI 10.1145/359340.359342, February 1978.
[SIGMA] Krawczyk, H., "SIGMA: The 'SIGn-and-MAc' Approach to
Authenticated Diffie-Hellman and its Use in the IKE
Protocols", Proceedings of CRYPTO 2003,
DOI 10.1007/978-3-540-45146-4_24, August 2003.
[SLOTH] Bhargavan, K. and G. Leurent, "Transcript Collision
Attacks: Breaking Authentication in TLS, IKE, and SSH",
Network and Distributed System Security
Symposium (NDSS 2016), DOI 10.14722/ndss.2016.23418,
February 2016.
[SSL2] Hickman, K., "The SSL Protocol", February 1995.
[TIMING] Boneh, D. and D. Brumley, "Remote Timing Attacks Are
Practical", USENIX Security Symposium, August 2003.
[TLS13-TRACES]
Thomson, M., "Example Handshake Traces for TLS 1.3", Work
in Progress, draft-ietf-tls-tls13-vectors-06, July 2018.
[X501] ITU-T, "Information Technology - Open Systems
Interconnection - The Directory: Models", ITU-T X.501,
October 2016, <https://www.itu.int/rec/T-REC-X.501/en>.
Rescorla 표준 트랙 [119페이지]
RFC 8446 TLS 2018년 8월
부록 A. 상태 머신
이 부록은 클라이언트 및 서버 핸드셰이크의 합법적인 상태 전이 요약을
제공한다. 상태 이름(예: START처럼 모두 대문자)은 형식적 의미는 없지만
이해를 쉽게 하기 위해 제공된다. 특정 상황에서만 수행되는 동작은
[] 안에 표시된다. 표기 "K_{send,recv} = foo"는 "송신/수신 키를 주어진
키로 설정"한다는 의미이다.
A.1. 클라이언트
START <----+
Send ClientHello | | Recv HelloRetryRequest
[K_send = early data] | |
v |
/ WAIT_SH ----+
| | Recv ServerHello
| | K_recv = handshake
Can | V
send | WAIT_EE
early | | Recv EncryptedExtensions
data | +--------+--------+
| Using | | Using certificate
| PSK | v
| | WAIT_CERT_CR
| | Recv | | Recv CertificateRequest
| | Certificate | v
| | | WAIT_CERT
| | | | Recv Certificate
| | v v
| | WAIT_CV
| | | Recv CertificateVerify
| +> WAIT_FINISHED <+
| | Recv Finished
\ | [Send EndOfEarlyData]
| K_send = handshake
| [Send Certificate [+ CertificateVerify]]
Can send | Send Finished
app data --> | K_send = K_recv = application
after here v
CONNECTED
위에 표시된 전이에 따르면, 클라이언트는 ServerHello 이후 메시지에서
파생되는 alert를 평문으로 보내거나 early data 키로 보낼 수 있음에
유의하라. 클라이언트가 그러한 alert를 보내야 한다면, 가능하면 먼저
handshake 키로 rekey해야 한다(SHOULD).
Rescorla 표준 트랙 [120페이지]
RFC 8446 TLS 2018년 8월
A.2. 서버
START <-----+
Recv ClientHello | | Send HelloRetryRequest
v |
RECVD_CH ----+
| Select parameters
v
NEGOTIATED
| Send ServerHello
| K_send = handshake
| Send EncryptedExtensions
| [Send CertificateRequest]
Can send | [Send Certificate + CertificateVerify]
app data | Send Finished
after --> | K_send = application
here +--------+--------+
No 0-RTT | | 0-RTT
| |
K_recv = handshake | | K_recv = early data
[Skip decrypt errors] | +------> WAIT_EOED -+
| | Recv | | Recv EndOfEarlyData
| | early data | | K_recv = handshake
| +------------+ |
| |
+> WAIT_FLIGHT2 <--------+
|
+--------+--------+
No auth | | Client auth
| |
| v
| WAIT_CERT
| Recv | | Recv Certificate
| empty | v
| Certificate | WAIT_CV
| | | Recv
| v | CertificateVerify
+-> WAIT_FINISHED <---+
| Recv Finished
| K_recv = application
v
CONNECTED
Rescorla 표준 트랙 [121페이지]
RFC 8446 TLS 2018년 8월
부록 B. 프로토콜 데이터 구조 및 상수 값
이 부록은 규범적 프로토콜 타입과 상수 정의를 제공한다. "_RESERVED"로
나열된 값은 이전 TLS 버전에서 사용되었으며 완전성을 위해 여기에
나열된다. TLS 1.3 구현은 이를 보내서는 안 되지만(MUST NOT), 더 오래된
TLS 구현으로부터 이를 수신할 수는 있다.
B.1. 레코드 계층
enum {
invalid(0),
change_cipher_spec(20),
alert(21),
handshake(22),
application_data(23),
heartbeat(24), /* RFC 6520 */
(255)
} ContentType;
struct {
ContentType type;
ProtocolVersion legacy_record_version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
struct {
opaque content[TLSPlaintext.length];
ContentType type;
uint8 zeros[length_of_padding];
} TLSInnerPlaintext;
struct {
ContentType opaque_type = application_data; /* 23 */
ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
Rescorla 표준 트랙 [122페이지]
RFC 8446 TLS 2018년 8월
B.2. Alert 메시지
enum { warning(1), fatal(2), (255) } AlertLevel;
enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
decryption_failed_RESERVED(21),
record_overflow(22),
decompression_failure_RESERVED(30),
handshake_failure(40),
no_certificate_RESERVED(41),
bad_certificate(42),
unsupported_certificate(43),
certificate_revoked(44),
certificate_expired(45),
certificate_unknown(46),
illegal_parameter(47),
unknown_ca(48),
access_denied(49),
decode_error(50),
decrypt_error(51),
export_restriction_RESERVED(60),
protocol_version(70),
insufficient_security(71),
internal_error(80),
inappropriate_fallback(86),
user_canceled(90),
no_renegotiation_RESERVED(100),
missing_extension(109),
unsupported_extension(110),
certificate_unobtainable_RESERVED(111),
unrecognized_name(112),
bad_certificate_status_response(113),
bad_certificate_hash_value_RESERVED(114),
unknown_psk_identity(115),
certificate_required(116),
no_application_protocol(120),
(255)
} AlertDescription;
struct {
AlertLevel level;
AlertDescription description;
} Alert;
Rescorla 표준 트랙 [123페이지]
RFC 8446 TLS 2018년 8월
B.3. 핸드셰이크 프로토콜
enum {
hello_request_RESERVED(0),
client_hello(1),
server_hello(2),
hello_verify_request_RESERVED(3),
new_session_ticket(4),
end_of_early_data(5),
hello_retry_request_RESERVED(6),
encrypted_extensions(8),
certificate(11),
server_key_exchange_RESERVED(12),
certificate_request(13),
server_hello_done_RESERVED(14),
certificate_verify(15),
client_key_exchange_RESERVED(16),
finished(20),
certificate_url_RESERVED(21),
certificate_status_RESERVED(22),
supplemental_data_RESERVED(23),
key_update(24),
message_hash(254),
(255)
} HandshakeType;
struct {
HandshakeType msg_type; /* handshake 타입 */
uint24 length; /* 메시지의 바이트 수 */
select (Handshake.msg_type) {
case client_hello: ClientHello;
case server_hello: ServerHello;
case end_of_early_data: EndOfEarlyData;
case encrypted_extensions: EncryptedExtensions;
case certificate_request: CertificateRequest;
case certificate: Certificate;
case certificate_verify: CertificateVerify;
case finished: Finished;
case new_session_ticket: NewSessionTicket;
case key_update: KeyUpdate;
};
} Handshake;
Rescorla 표준 트랙 [124페이지]
RFC 8446 TLS 2018년 8월
B.3.1. 키 교환 메시지
uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2]; /* 암호학적 스위트 선택자 */
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<8..2^16-1>;
} ClientHello;
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id_echo<0..32>;
CipherSuite cipher_suite;
uint8 legacy_compression_method = 0;
Extension extensions<6..2^16-1>;
} ServerHello;
Rescorla 표준 트랙 [125페이지]
RFC 8446 TLS 2018년 8월
struct {
ExtensionType extension_type;
opaque extension_data<0..2^16-1>;
} Extension;
enum {
server_name(0), /* RFC 6066 */
max_fragment_length(1), /* RFC 6066 */
status_request(5), /* RFC 6066 */
supported_groups(10), /* RFC 8422, 7919 */
signature_algorithms(13), /* RFC 8446 */
use_srtp(14), /* RFC 5764 */
heartbeat(15), /* RFC 6520 */
application_layer_protocol_negotiation(16), /* RFC 7301 */
signed_certificate_timestamp(18), /* RFC 6962 */
client_certificate_type(19), /* RFC 7250 */
server_certificate_type(20), /* RFC 7250 */
padding(21), /* RFC 7685 */
RESERVED(40), /* 사용되었지만
할당되지 않음 */
pre_shared_key(41), /* RFC 8446 */
early_data(42), /* RFC 8446 */
supported_versions(43), /* RFC 8446 */
cookie(44), /* RFC 8446 */
psk_key_exchange_modes(45), /* RFC 8446 */
RESERVED(46), /* 사용되었지만
할당되지 않음 */
certificate_authorities(47), /* RFC 8446 */
oid_filters(48), /* RFC 8446 */
post_handshake_auth(49), /* RFC 8446 */
signature_algorithms_cert(50), /* RFC 8446 */
key_share(51), /* RFC 8446 */
(65535)
} ExtensionType;
struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
struct {
KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;
struct {
NamedGroup selected_group;
} KeyShareHelloRetryRequest;
Rescorla 표준 트랙 [126페이지]
RFC 8446 TLS 2018년 8월
struct {
KeyShareEntry server_share;
} KeyShareServerHello;
struct {
uint8 legacy_form = 4;
opaque X[coordinate_length];
opaque Y[coordinate_length];
} UncompressedPointRepresentation;
enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
struct {
PskKeyExchangeMode ke_modes<1..255>;
} PskKeyExchangeModes;
struct {} Empty;
struct {
select (Handshake.msg_type) {
case new_session_ticket: uint32 max_early_data_size;
case client_hello: Empty;
case encrypted_extensions: Empty;
};
} EarlyDataIndication;
struct {
opaque identity<1..2^16-1>;
uint32 obfuscated_ticket_age;
} PskIdentity;
opaque PskBinderEntry<32..255>;
struct {
PskIdentity identities<7..2^16-1>;
PskBinderEntry binders<33..2^16-1>;
} OfferedPsks;
struct {
select (Handshake.msg_type) {
case client_hello: OfferedPsks;
case server_hello: uint16 selected_identity;
};
} PreSharedKeyExtension;
Rescorla 표준 트랙 [127페이지]
RFC 8446 TLS 2018년 8월
B.3.1.1. 버전 확장
struct {
select (Handshake.msg_type) {
case client_hello:
ProtocolVersion versions<2..254>;
case server_hello: /* 및 HelloRetryRequest */
ProtocolVersion selected_version;
};
} SupportedVersions;
B.3.1.2. 쿠키 확장
struct {
opaque cookie<1..2^16-1>;
} Cookie;
Rescorla 표준 트랙 [128페이지]
RFC 8446 TLS 2018년 8월
B.3.1.3. 서명 알고리즘 확장
enum {
/* RSASSA-PKCS1-v1_5 알고리즘 */
rsa_pkcs1_sha256(0x0401),
rsa_pkcs1_sha384(0x0501),
rsa_pkcs1_sha512(0x0601),
/* ECDSA 알고리즘 */
ecdsa_secp256r1_sha256(0x0403),
ecdsa_secp384r1_sha384(0x0503),
ecdsa_secp521r1_sha512(0x0603),
/* 공개 키 OID rsaEncryption을 사용하는 RSASSA-PSS 알고리즘 */
rsa_pss_rsae_sha256(0x0804),
rsa_pss_rsae_sha384(0x0805),
rsa_pss_rsae_sha512(0x0806),
/* EdDSA 알고리즘 */
ed25519(0x0807),
ed448(0x0808),
/* 공개 키 OID RSASSA-PSS를 사용하는 RSASSA-PSS 알고리즘 */
rsa_pss_pss_sha256(0x0809),
rsa_pss_pss_sha384(0x080a),
rsa_pss_pss_sha512(0x080b),
/* 레거시 알고리즘 */
rsa_pkcs1_sha1(0x0201),
ecdsa_sha1(0x0203),
/* 예약된 코드 포인트 */
obsolete_RESERVED(0x0000..0x0200),
dsa_sha1_RESERVED(0x0202),
obsolete_RESERVED(0x0204..0x0400),
dsa_sha256_RESERVED(0x0402),
obsolete_RESERVED(0x0404..0x0500),
dsa_sha384_RESERVED(0x0502),
obsolete_RESERVED(0x0504..0x0600),
dsa_sha512_RESERVED(0x0602),
obsolete_RESERVED(0x0604..0x06FF),
private_use(0xFE00..0xFFFF),
(0xFFFF)
} SignatureScheme;
struct {
SignatureScheme supported_signature_algorithms<2..2^16-2>;
} SignatureSchemeList;
Rescorla 표준 트랙 [129페이지]
RFC 8446 TLS 2018년 8월
B.3.1.4. 지원 그룹 확장
enum {
unallocated_RESERVED(0x0000),
/* 타원곡선 그룹(ECDHE) */
obsolete_RESERVED(0x0001..0x0016),
secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
obsolete_RESERVED(0x001A..0x001C),
x25519(0x001D), x448(0x001E),
/* 유한체 그룹(DHE) */
ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
ffdhe6144(0x0103), ffdhe8192(0x0104),
/* 예약된 코드 포인트 */
ffdhe_private_use(0x01FC..0x01FF),
ecdhe_private_use(0xFE00..0xFEFF),
obsolete_RESERVED(0xFF01..0xFF02),
(0xFFFF)
} NamedGroup;
struct {
NamedGroup named_group_list<2..2^16-1>;
} NamedGroupList;
"obsolete_RESERVED" 범위 내의 값은 이전 TLS 버전에서 사용되며,
TLS 1.3 구현이 제공하거나 협상해서는 안 된다(MUST NOT). 폐기 예정
곡선들은 다양한 알려진/이론적 약점을 가지고 있거나, 어떤 경우에는
의도치 않은 서버 구성 문제로 인해 매우 적게 사용되었다. 이들은 더
이상 일반적 사용에 적절한 것으로 간주되지 않으며 잠재적으로 안전하지
않다고 가정해야 한다. 여기에 지정된 곡선 집합은 현재 배포되어 있고
올바르게 구성된 모든 TLS 구현과의 상호 운용에 충분하다.
Rescorla 표준 트랙 [130페이지]
RFC 8446 TLS 2018년 8월
B.3.2. 서버 매개변수 메시지
opaque DistinguishedName<1..2^16-1>;
struct {
DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;
struct {
opaque certificate_extension_oid<1..2^8-1>;
opaque certificate_extension_values<0..2^16-1>;
} OIDFilter;
struct {
OIDFilter filters<0..2^16-1>;
} OIDFilterExtension;
struct {} PostHandshakeAuth;
struct {
Extension extensions<0..2^16-1>;
} EncryptedExtensions;
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
Rescorla 표준 트랙 [131페이지]
RFC 8446 TLS 2018년 8월
B.3.3. 인증 메시지
enum {
X509(0),
OpenPGP_RESERVED(1),
RawPublicKey(2),
(255)
} CertificateType;
struct {
select (certificate_type) {
case RawPublicKey:
/* RFC 7250 ASN.1_subjectPublicKeyInfo에서 옴 */
opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
case X509:
opaque cert_data<1..2^24-1>;
};
Extension extensions<0..2^16-1>;
} CertificateEntry;
struct {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>;
} Certificate;
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
struct {
opaque verify_data[Hash.length];
} Finished;
B.3.4. 티켓 설정
struct {
uint32 ticket_lifetime;
uint32 ticket_age_add;
opaque ticket_nonce<0..255>;
opaque ticket<1..2^16-1>;
Extension extensions<0..2^16-2>;
} NewSessionTicket;
Rescorla 표준 트랙 [132페이지]
RFC 8446 TLS 2018년 8월
B.3.5. 키 갱신
struct {} EndOfEarlyData;
enum {
update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;
struct {
KeyUpdateRequest request_update;
} KeyUpdate;
B.4. 암호 스위트
대칭 암호 스위트는 HKDF와 함께 사용할 AEAD 알고리즘과 해시 알고리즘의
쌍을 정의한다. 암호 스위트 이름은 다음 명명 규칙을 따른다.
CipherSuite TLS_AEAD_HASH = VALUE;
+-----------+------------------------------------------------+
| 구성요소 | 내용 |
+-----------+------------------------------------------------+
| TLS | 문자열 "TLS" |
| | |
| AEAD | 레코드 보호에 사용되는 AEAD 알고리즘 |
| | |
| HASH | HKDF와 함께 사용되는 해시 알고리즘 |
| | |
| VALUE | 이 암호 스위트에 할당된 2바이트 ID |
+-----------+------------------------------------------------+
이 명세는 TLS 1.3과 함께 사용할 다음 암호 스위트를 정의한다.
+------------------------------+-------------+
| 설명 | 값 |
+------------------------------+-------------+
| TLS_AES_128_GCM_SHA256 | {0x13,0x01} |
| | |
| TLS_AES_256_GCM_SHA384 | {0x13,0x02} |
| | |
| TLS_CHACHA20_POLY1305_SHA256 | {0x13,0x03} |
| | |
| TLS_AES_128_CCM_SHA256 | {0x13,0x04} |
| | |
| TLS_AES_128_CCM_8_SHA256 | {0x13,0x05} |
+------------------------------+-------------+
Rescorla 표준 트랙 [133페이지]
RFC 8446 TLS 2018년 8월
대응하는 AEAD 알고리즘 AEAD_AES_128_GCM, AEAD_AES_256_GCM 및
AEAD_AES_128_CCM은 [RFC5116]에 정의되어 있다. AEAD_CHACHA20_POLY1305는
[RFC8439]에 정의되어 있다. AEAD_AES_128_CCM_8은 [RFC6655]에
정의되어 있다. 대응하는 해시 알고리즘은 [SHS]에 정의되어 있다.
TLS 1.3은 이전 TLS 버전과 같은 암호 스위트 공간을 사용하지만,
TLS 1.3 암호 스위트는 다르게 정의되어 대칭 암호만 지정하며,
TLS 1.2에서 사용할 수 없다. 마찬가지로 TLS 1.2 이하용 암호 스위트는
TLS 1.3과 함께 사용할 수 없다.
새 암호 스위트 값은 섹션 11에 설명된 대로 IANA가 할당한다.
부록 C. 구현 참고사항
TLS 프로토콜은 많은 일반적인 보안 실수를 방지할 수 없다. 이 부록은
구현자를 돕기 위한 몇 가지 권고를 제공한다. [TLS13-TRACES]는
TLS 1.3 핸드셰이크에 대한 테스트 벡터를 제공한다.
C.1. 난수 생성 및 시딩
TLS는 암호학적으로 안전한 의사난수 생성기(CSPRNG)를 요구한다. 대부분의
경우 운영체제는 /dev/urandom과 같은 적절한 기능을 제공하며, 다른
(예: 성능) 우려가 없다면 이를 사용해야 한다. 새로 만드는 것보다
기존 CSPRNG 구현을 사용하는 것이 권장된다(RECOMMENDED). 적절한 라이선스
조건 아래 이미 많은 충분한 암호학 라이브러리가 제공된다. 그것들이
만족스럽지 않다면, [RFC4086]이 무작위 값 생성에 대한 지침을 제공한다.
TLS는 무작위 값을 (1) ClientHello와 ServerHello의 공개 Random 값 같은
공개 프로토콜 필드와 (2) 키 자료 생성에 사용한다. 제대로 동작하는
CSPRNG에서는 출력으로부터 CSPRNG 상태를 결정하는 것이 가능하지 않으므로
이는 보안 문제를 일으키지 않는다. 그러나 깨진 CSPRNG에서는 공격자가
[CHECKOWAY]에 문서화된 것처럼 공개 출력을 사용해 CSPRNG 내부 상태를
결정하고 그에 따라 키 자료를 예측할 수 있다. 구현은 공개 값과 개인
값을 생성하는 데 별도의 CSPRNG를 사용함으로써 이러한 형태의 공격에
대한 추가 보안을 제공할 수 있다.
Rescorla 표준 트랙 [134페이지]
RFC 8446 TLS 2018년 8월
C.2. 인증서 및 인증
구현은 인증서의 무결성을 검증할 책임이 있으며 일반적으로 인증서 폐기
메시지를 지원해야 한다. 애플리케이션 프로파일의 특정 표시가 없다면,
신뢰된 인증서 기관(CA)에 의해 적절히 서명되었는지 보장하기 위해
인증서는 항상 검증되어야 한다. 신뢰 앵커의 선택과 추가는 매우
신중하게 이루어져야 한다. 사용자는 인증서와 신뢰 앵커에 관한 정보를
볼 수 있어야 한다. 애플리케이션은 최소 및 최대 키 크기도 강제해야
한다(SHOULD). 예를 들어 2048비트 RSA 또는 224비트 ECDSA보다 약한 키나
서명을 포함하는 인증 경로는 안전한 애플리케이션에 적절하지 않다.
C.3. 구현 함정
구현 경험은 이전 TLS 명세의 특정 부분이 이해하기 쉽지 않았고 상호
운용성 및 보안 문제의 원인이 되었음을 보여주었다. 이러한 영역 중
많은 부분은 이 문서에서 명확해졌지만, 이 부록은 구현자가 특별히
주의해야 하는 가장 중요한 사항의 짧은 목록을 포함한다.
TLS 프로토콜 문제:
- 여러 TLS 레코드로 조각난 핸드셰이크 메시지를 올바르게 처리하는가
(섹션 5.1 참조)? ClientHello가 여러 작은 조각으로 나뉘는 것 같은
corner case를 올바르게 처리하는가? 최대 조각 크기를 초과하는
핸드셰이크 메시지를 조각내는가? 특히 Certificate 및
CertificateRequest 핸드셰이크 메시지는 조각화가 필요할 만큼 클 수
있다.
- 모든 암호화되지 않은 TLS 레코드에서 TLS 레코드 계층 버전 번호를
무시하는가(부록 D 참조)?
- TLS 1.3 이상을 지원하는 가능한 모든 구성에서 SSL, RC4, EXPORT 암호,
그리고 ("signature_algorithms" 확장을 통한) MD5에 대한 모든 지원이
완전히 제거되었고, 이러한 폐기 예정 기능을 사용하려는 시도가
올바르게 실패하도록 보장했는가(부록 D 참조)?
- 알 수 없는 확장을 포함하여 ClientHello의 TLS 확장을 올바르게
처리하는가?
Rescorla 표준 트랙 [135페이지]
RFC 8446 TLS 2018년 8월
- 서버가 클라이언트 인증서를 요청했지만 적절한 인증서가 없는 경우,
전체 메시지를 생략하는 대신 빈 Certificate 메시지를 올바르게
보내는가(섹션 4.4.2 참조)?
- AEAD-Decrypt가 생성한 plaintext fragment를 처리하고 끝에서부터
ContentType을 찾기 위해 스캔할 때, 피어가 모두 0으로 된 잘못된
plaintext를 보낸 경우 cleartext의 시작 이전까지 스캔하지 않도록
피하는가?
- ClientHello에서 인식하지 못하는 암호 스위트(섹션 4.1.2), hello
확장(섹션 4.2), named group(섹션 4.2.7), key share
(섹션 4.2.8), supported version(섹션 4.2.1), 그리고
signature algorithm(섹션 4.2.3)을 적절히 무시하는가?
- 서버로서, 호환되는 (EC)DHE 그룹을 지원하지만 "key_share" 확장에서
이를 예측하지 못한 클라이언트에게 HelloRetryRequest를 보내는가?
클라이언트로서, 서버의 HelloRetryRequest를 올바르게 처리하는가?
암호학적 세부사항:
- 타이밍 공격 [TIMING]을 방지하기 위해 어떤 대응수단을 사용하는가?
- Diffie-Hellman 키 교환을 사용할 때, 협상된 키의 선행 0 바이트를
올바르게 보존하는가(섹션 7.4.1 참조)?
- TLS 클라이언트가 서버가 보낸 Diffie-Hellman 매개변수가 허용 가능한지
검사하는가(섹션 4.2.8.1 참조)?
- Diffie-Hellman 개인 값, ECDSA "k" 매개변수 및 기타 보안상 중요한
값을 생성할 때 강력하고, 무엇보다 적절히 시드된 난수 생성기를
사용하는가(부록 C.1 참조)? 구현은 [RFC6979]에 지정된
"deterministic ECDSA"를 구현하는 것이 권장된다(RECOMMENDED).
- Diffie-Hellman 공개 키 값과 공유 시크릿을 그룹 크기까지 0으로
패딩하는가(섹션 4.2.8.1 및 섹션 7.4.1 참조)?
- RSA-CRT 키 유출 [FW15]로부터 보호하기 위해 서명을 만든 뒤
검증하는가?
Rescorla 표준 트랙 [136페이지]
RFC 8446 TLS 2018년 8월
C.4. 클라이언트 추적 방지
클라이언트는 여러 연결에 티켓을 재사용해서는 안 된다(SHOULD NOT).
티켓 재사용은 수동 관찰자가 서로 다른 연결을 상관시킬 수 있게 한다.
티켓을 발행하는 서버는 클라이언트가 사용할 수 있는 연결 수만큼의
티켓을 최소한 제공해야 한다(SHOULD). 예를 들어 HTTP/1.1 [RFC7230]을
사용하는 웹 브라우저는 서버에 여섯 개의 연결을 열 수 있다. 서버는
모든 연결마다 새 티켓을 발행해야 한다(SHOULD). 이는 클라이언트가 새
연결을 만들 때 항상 새 티켓을 사용할 수 있도록 보장한다.
C.5. 미인증 동작
이전 TLS 버전은 익명 Diffie-Hellman에 기반한 명시적 미인증 암호
스위트를 제공했다. 이러한 모드는 TLS 1.3에서 폐기 예정이다. 그러나
다음을 포함한 여러 방법으로 검증 가능한 서버 인증을 제공하지 않는
매개변수를 협상하는 것은 여전히 가능하다.
- Raw public key [RFC7250].
- 인증서에 포함된 공개 키를 사용하지만 인증서 체인 또는 그 내용의
어떤 것도 검증하지 않는 것.
어느 기법이든 단독으로 사용되면 man-in-the-middle 공격에 취약하므로
일반적 사용에는 안전하지 않다. 그러나 이러한 연결을 서버 공개 키의
out-of-band 검증, trust on first use, 또는 channel binding 같은 메커니즘
(다만 [RFC5929]에 설명된 channel binding은 TLS 1.3에 대해 정의되어 있지
않음)을 통해 외부 인증 메커니즘에 결속하는 것도 가능하다. 그러한
메커니즘이 사용되지 않는다면 연결은 능동적 man-in-the-middle 공격에
대한 보호를 가지지 않는다. 애플리케이션은 명시적 구성 또는 특정
애플리케이션 프로파일이 없는 한 TLS를 그런 방식으로 사용해서는
안 된다(MUST NOT).
Rescorla 표준 트랙 [137페이지]
RFC 8446 TLS 2018년 8월
부록 D. 하위 호환성
TLS 프로토콜은 서로 다른 TLS 버전을 잠재적으로 지원하는 엔드포인트
사이에서 버전 협상을 위한 내장 메커니즘을 제공한다.
TLS 1.x와 SSL 3.0은 호환되는 ClientHello 메시지를 사용한다. 서버는
ClientHello 형식이 호환되는 상태로 유지되고 클라이언트와 서버가 모두
지원하는 프로토콜 버전이 적어도 하나 있다면, 향후 TLS 버전을
사용하려는 클라이언트도 처리할 수 있다.
이전 TLS 버전은 레코드 계층 버전 번호(TLSPlaintext.legacy_record_version
및 TLSCiphertext.legacy_record_version)를 다양한 목적으로 사용했다.
TLS 1.3부터 이 필드는 폐기 예정이다. TLSPlaintext.legacy_record_version
값은 모든 구현에서 무시되어야 한다(MUST). TLSCiphertext.legacy_record_version
값은 보호 해제를 위한 additional data에 포함되지만, 그 외에는 무시될
수 있거나(MAY) 고정 상수 값과 일치하는지 검증될 수 있다(MAY). 버전
협상은 핸드셰이크 버전(ClientHello.legacy_version 및
ServerHello.legacy_version, 그리고 ClientHello, HelloRetryRequest 및
ServerHello "supported_versions" 확장)만 사용하여 수행된다. 더 오래된
엔드포인트와의 상호 운용성을 극대화하기 위해, TLS 1.0-1.2 사용을
협상하는 구현은 ServerHello 및 그 이후 모든 레코드에 대해 레코드 계층
버전 번호를 협상된 버전으로 설정해야 한다(SHOULD).
이전의 비표준 동작 및 잘못 구성된 배포와 최대한 호환되기 위해, 모든
구현은 이전 TLS 버전의 핸드셰이크를 처리할 때에도 이 문서의 기대에
기반한 인증 경로 검증을 지원해야 한다(SHOULD)(섹션 4.4.2.2 참조).
TLS 1.2 및 이전 버전은 핸드셰이크 전사의 큰 부분을 master secret에
digest하는 "Extended Master Secret" [RFC7627] 확장을 지원했다.
TLS 1.3은 항상 server Finished까지의 전사를 해시에 포함하므로,
TLS 1.3과 이전 버전을 모두 지원하는 구현은 TLS 1.3이 사용될 때마다
자신의 API에서 Extended Master Secret 확장의 사용을 표시해야 한다
(SHOULD).
Rescorla 표준 트랙 [138페이지]
RFC 8446 TLS 2018년 8월
D.1. 더 오래된 서버와 협상하기
TLS 1.3을 지원하지 않는 서버와 협상하려는 TLS 1.3 클라이언트는
ClientHello.legacy_version에 0x0303(TLS 1.2)을 포함하지만
"supported_versions" 확장에는 올바른 버전을 포함하는 정상적인 TLS 1.3
ClientHello를 보낸다. 서버가 TLS 1.3을 지원하지 않으면, 더 오래된
버전 번호를 포함하는 ServerHello로 응답한다. 클라이언트가 이 버전
사용에 동의하면, 협상은 협상된 프로토콜에 적절한 방식으로 진행된다.
재개를 위해 티켓을 사용하는 클라이언트는 이전에 협상된 버전을 사용하여
연결을 시작해야 한다(SHOULD).
0-RTT 데이터는 더 오래된 서버와 호환되지 않으며, 서버가 TLS 1.3을
지원한다는 지식이 없는 경우 전송되어서는 안 된다는 점에 유의하라
(SHOULD NOT). 부록 D.3을 참조하라.
서버가 선택한 버전이 클라이언트가 지원하지 않는 버전이거나 허용할 수
없는 버전이면, 클라이언트는 "protocol_version" 경고와 함께 핸드셰이크를
중단해야 한다(MUST).
일부 레거시 서버 구현은 TLS 명세를 제대로 구현하지 않는 것으로 알려져
있으며, 자신이 알지 못하는 TLS 확장 또는 버전을 만났을 때 연결을
중단할 수 있다. 버그가 있는 서버와의 상호 운용성은 이 문서의 범위를
벗어나는 복잡한 주제이다. 하위 호환 연결을 협상하기 위해 여러 번의
연결 시도가 필요할 수 있지만, 이 관행은 다운그레이드 공격에 취약하며
권장되지 않는다(NOT RECOMMENDED).
D.2. 더 오래된 클라이언트와 협상하기
TLS 서버는 자신이 지원하는 가장 높은 버전보다 작은 버전 번호를 나타내는
ClientHello도 수신할 수 있다. "supported_versions" 확장이 존재하면,
서버는 섹션 4.2.1에 설명된 대로 그 확장을 사용하여 협상해야 한다(MUST).
"supported_versions" 확장이 존재하지 않으면, 서버는
ClientHello.legacy_version과 TLS 1.2 중 작은 값을 협상해야 한다(MUST).
예를 들어 서버가 TLS 1.0, 1.1 및 1.2를 지원하고 legacy_version이
TLS 1.0이면, 서버는 TLS 1.0 ServerHello로 진행한다.
"supported_versions" 확장이 없고 서버가 ClientHello.legacy_version보다
큰 버전만 지원한다면, 서버는 "protocol_version" 경고와 함께
핸드셰이크를 중단해야 한다(MUST).
이전 TLS 버전은 모든 경우의 레코드 계층 버전 번호 값
(TLSPlaintext.legacy_record_version)을 명확히 지정하지 않았다는 점에
유의하라. 서버는 이 필드에서 다양한 TLS 1.x 버전을 수신하게 되지만,
그 값은 항상 무시되어야 한다(MUST).
Rescorla 표준 트랙 [139페이지]
RFC 8446 TLS 2018년 8월
D.3. 0-RTT 하위 호환성
0-RTT 데이터는 더 오래된 서버와 호환되지 않는다. 더 오래된 서버는
ClientHello에 더 오래된 ServerHello로 응답하지만, 0-RTT 데이터를
올바르게 건너뛰지 못하고 핸드셰이크를 완료하지 못한다. 이는
클라이언트가 0-RTT 사용을 시도할 때, 특히 다중 서버 배포를 상대로
할 때 문제를 일으킬 수 있다. 예를 들어 어떤 배포는 TLS 1.3을 점진적으로
배포하여 일부 서버는 TLS 1.3을 구현하고 일부는 TLS 1.2를 구현할 수
있으며, 또는 TLS 1.3 배포가 TLS 1.2로 다운그레이드될 수 있다.
0-RTT 데이터 전송을 시도하는 클라이언트는 TLS 1.2 이하를 포함하는
ServerHello를 수신하면 연결을 실패시켜야 한다(MUST). 그런 다음
0-RTT를 비활성화하여 연결을 재시도할 수 있다. 다운그레이드 공격을
피하기 위해, 클라이언트는 TLS 1.3이 아니라 0-RTT만 비활성화해야 한다
(SHOULD NOT disable TLS 1.3, only 0-RTT).
이 오류 조건을 피하기 위해, 다중 서버 배포는 0-RTT를 활성화하기 전에
0-RTT 없이 TLS 1.3의 균일하고 안정적인 배포를 보장해야 한다(SHOULD).
D.4. 미들박스 호환성 모드
현장 측정 [Ben17a] [Ben17b] [Res17a] [Res17b]에서는 TLS 클라이언트/서버 쌍이
TLS 1.3을 협상할 때 상당수의 미들박스가 잘못 동작함이 발견되었다.
구현은 TLS 1.3 핸드셰이크가 TLS 1.2 핸드셰이크와 더 비슷해 보이도록
만들어 그러한 미들박스를 통한 연결 가능성을 높일 수 있다.
- 클라이언트는 섹션 4.1.2의 legacy_session_id 섹션에 설명된 대로
ClientHello에서 항상 비어 있지 않은 session ID를 제공한다.
- early data를 제공하지 않는 경우, 클라이언트는 두 번째 flight 직전에
dummy change_cipher_spec 레코드(섹션 5의 세 번째 단락 참조)를
보낸다. 이는 두 번째 ClientHello 앞이거나 암호화된 핸드셰이크
flight 앞일 수 있다. early data를 제공하는 경우, 레코드는 첫 번째
ClientHello 바로 뒤에 배치된다.
- 서버는 자신의 첫 번째 핸드셰이크 메시지 바로 뒤에 dummy
change_cipher_spec 레코드를 보낸다. 이는 ServerHello 뒤이거나
HelloRetryRequest 뒤일 수 있다.
함께 적용되면, 이러한 변경은 TLS 1.3 핸드셰이크가 TLS 1.2 세션 재개와
비슷해 보이게 하며, 이는 미들박스를 통해 성공적으로 연결할 가능성을
높인다. 이 "compatibility mode"는 부분적으로 협상된다. 클라이언트는
session ID를 제공할지 선택할 수 있고, 서버는 이를 에코해야 한다.
어느 쪽이든 핸드셰이크 중 언제든지
Rescorla 표준 트랙 [140페이지]
RFC 8446 TLS 2018년 8월
change_cipher_spec을 보낼 수 있다. 피어가 이를 무시해야 하기 때문이다.
그러나 클라이언트가 비어 있지 않은 session ID를 보내면, 서버는 이
부록에 설명된 대로 change_cipher_spec을 보내야 한다(MUST).
D.5. 하위 호환성과 관련된 보안 제한
더 오래된 TLS 버전 사용을 협상하는 구현은 사용 가능한 경우 순방향
비밀성 및 AEAD 암호 스위트를 선호해야 한다(SHOULD).
RC4 암호 스위트의 보안은 [RFC7465]에 인용된 이유로 충분하지 않은
것으로 간주된다. 구현은 어떤 이유로든 어떤 TLS 버전에서도 RC4 암호
스위트를 제공하거나 협상해서는 안 된다(MUST NOT).
오래된 TLS 버전은 매우 낮은 강도의 암호 사용을 허용했다. 강도가
112비트보다 낮은 암호는 어떤 이유로든 어떤 TLS 버전에서도 제공되거나
협상되어서는 안 된다(MUST NOT).
SSL 3.0 [RFC6101]의 보안은 [RFC7568]에 열거된 이유로 충분하지
않은 것으로 간주되며, 어떤 이유로든 협상되어서는 안 된다(MUST NOT).
SSL 2.0 [SSL2]의 보안은 [RFC6176]에 열거된 이유로 충분하지 않은
것으로 간주되며, 어떤 이유로든 협상되어서는 안 된다(MUST NOT).
구현은 SSL 버전 2.0 호환 CLIENT-HELLO를 보내서는 안 된다(MUST NOT).
구현은 SSL 버전 2.0 호환 CLIENT-HELLO를 사용하여 TLS 1.3 이상을
협상해서는 안 된다(MUST NOT). 구현은 더 오래된 TLS 버전을 협상하기
위해 SSL 버전 2.0 호환 CLIENT-HELLO를 수락하는 것이 권장되지 않는다
(NOT RECOMMENDED).
구현은 0x0300 이하로 설정된 ClientHello.legacy_version 또는
ServerHello.legacy_version을 보내서는 안 된다(MUST NOT). 0x0300으로
설정된 ClientHello.legacy_version 또는 ServerHello.legacy_version을
가진 Hello 메시지를 수신한 모든 엔드포인트는 "protocol_version"
경고와 함께 핸드셰이크를 중단해야 한다(MUST).
구현은 0x0300보다 작은 버전을 가진 어떤 레코드도 보내서는 안 된다
(MUST NOT). 구현은 0x0300보다 작은 버전을 가진 어떤 레코드도
수락해서는 안 된다(SHOULD NOT)(다만 레코드 버전 번호를 완전히
무시하는 경우 의도치 않게 그렇게 할 수 있음).
구현은 [[RFC6066]의 섹션 7]에 정의된 Truncated HMAC 확장을 사용해서는
안 된다(MUST NOT). 이는 AEAD 알고리즘에 적용되지 않으며 일부
시나리오에서 안전하지 않은 것으로 나타났기 때문이다.
Rescorla 표준 트랙 [141페이지]
RFC 8446 TLS 2018년 8월
부록 E. 보안 속성 개요
TLS의 완전한 보안 분석은 이 문서의 범위를 벗어난다. 이 부록에서는
바람직한 속성에 대한 비공식 설명과 더 형식적인 정의를 제공하는
연구 문헌의 더 자세한 작업에 대한 참고문헌을 제공한다.
우리는 핸드셰이크의 속성과 레코드 계층의 속성을 별도로 다룬다.
E.1. 핸드셰이크
TLS 핸드셰이크는 단방향 인증(서버만) 및 상호 인증(클라이언트와 서버)
기능을 모두 제공하려는 Authenticated Key Exchange(AKE) 프로토콜이다.
핸드셰이크가 완료되면, 각 쪽은 다음 값에 대한 자신의 관점을 출력한다.
- 작업용 키 집합을 파생할 수 있는 "session keys" 집합(master secret에서
파생된 다양한 시크릿).
- 암호학적 매개변수 집합(알고리즘 등).
- 통신 당사자의 신원.
우리는 공격자를 능동적 네트워크 공격자로 가정한다. 이는 공격자가
당사자 사이의 통신에 사용되는 네트워크를 완전히 제어한다는 의미이다
[RFC3552]. 이러한 조건 아래에서도 핸드셰이크는 아래 나열된 속성을
제공해야 한다. 이 속성들은 반드시 서로 독립적이지는 않지만 프로토콜
소비자의 필요를 반영한다는 점에 유의하라.
같은 session key 설정: 핸드셰이크는 각 엔드포인트에서 성공적으로
완료되는 경우, 핸드셰이크 양쪽에서 같은 session key 집합을 출력해야
한다([CK01], 정의 1, 부분 1 참조).
session key의 비밀성: 공유 session key는 통신 당사자에게만 알려져야
하며 공격자에게 알려져서는 안 된다([CK01], 정의 1, 부분 2 참조).
단방향 인증 연결에서는 공격자가 서버와 자신의 session key를 설정할
수 있지만, 그 session key는 클라이언트가 설정한 것과 구별된다는
점에 유의하라.
피어 인증: 피어 신원에 대한 클라이언트의 관점은 서버의 신원을 반영해야
한다. 클라이언트가 인증되면, 피어 신원에 대한 서버의 관점은
클라이언트의 신원과 일치해야 한다.
Rescorla 표준 트랙 [142페이지]
RFC 8446 TLS 2018년 8월
session key의 고유성: 서로 다른 두 핸드셰이크는 서로 구별되고 관련
없는 session key를 생성해야 한다. 핸드셰이크가 생성한 개별
session key도 서로 구별되고 독립적이어야 한다.
다운그레이드 보호: 암호학적 매개변수는 양쪽에서 같아야 하며, 피어가
공격 없이 통신했을 때와 같아야 한다([BBFGKZ16], 정의 8 및 9
참조).
장기 키에 대한 순방향 비밀성: 핸드셰이크가 완료된 뒤 장기 키 자료
(이 경우 인증서 기반 인증 모드의 서명 키 또는 (EC)DHE를 사용하는
PSK 모드의 외부/재개 PSK)가 손상되더라도, session key 자체가
지워져 있다면 session key의 보안을 손상시키지 않는다([DOW92] 참조).
PSK가 "psk_ke" PskKeyExchangeMode에서 사용되는 경우 순방향 비밀성
속성은 만족되지 않는다.
Key Compromise Impersonation(KCI) 저항성: 인증서를 사용하는 상호 인증
연결에서, 한 행위자의 장기 시크릿 손상은 주어진 연결에서 그 행위자가
자신의 피어를 인증하는 것을 깨뜨려서는 안 된다([HGFS15] 참조).
예를 들어 클라이언트의 서명 키가 손상되더라도 이후 핸드셰이크에서
임의의 서버를 그 클라이언트에게 가장하는 것이 가능해서는 안 된다.
엔드포인트 신원 보호: 서버의 신원(인증서)은 수동 공격자로부터
보호되어야 한다. 클라이언트의 신원은 수동 및 능동 공격자 모두로부터
보호되어야 한다.
비공식적으로, TLS 1.3의 서명 기반 모드는 (EC)DHE 키 교환으로 설정되고
핸드셰이크 전사에 대한 서버의 서명으로 인증되며, MAC을 통해 서버의
신원에 결속된 고유하고 비밀인 공유 키 설정을 제공한다. 클라이언트가
인증서로 인증되면, 클라이언트도 핸드셰이크 전사에 대해 서명하고 두
신원 모두에 결속된 MAC을 제공한다. [SIGMA]는 이러한 유형의 키 교환
프로토콜 설계와 분석을 설명한다. 각 연결마다 새로운 (EC)DHE 키가
사용되면, 출력 키는 순방향 비밀성을 가진다.
외부 PSK와 재개 PSK는 장기 공유 시크릿에서 고유한 연결별 단기
session key 집합으로 부트스트랩한다. 이 시크릿은 이전 핸드셰이크에서
설정되었을 수 있다. (EC)DHE 키 설정과 함께 PSK가 사용되면, 이러한
session key도 순방향 비밀성을 가진다. 재개 PSK는 연결 N이 계산하고
연결 N+1을 형성하는 데 필요한 resumption master secret이 연결 N에서
사용된 트래픽 키와 분리되도록 설계되어,
Rescorla 표준 트랙 [143페이지]
RFC 8446 TLS 2018년 8월
연결 사이에 순방향 비밀성을 제공한다. 또한 같은 연결에서 여러 티켓이
설정되면, 이들은 서로 다른 키와 연관되므로 한 티켓과 연관된 PSK의
손상이 다른 티켓과 연관된 PSK로 설정된 연결의 손상으로 이어지지
않는다. 이 속성은 티켓이 자체 암호화되는 경우보다 데이터베이스에
저장되는 경우(따라서 삭제될 수 있는 경우)에 가장 흥미롭다.
PSK binder 값은 PSK와 현재 핸드셰이크 사이의 결속을 형성하며, PSK가
설정된 세션과 현재 세션 사이의 결속도 형성한다. 이 결속은 원래
핸드셰이크 전사를 전이적으로 포함한다. 그 전사가 resumption master
secret을 생성하는 값들에 digest되기 때문이다. 이는 resumption master
secret을 생성하는 데 사용되는 KDF와 binder를 계산하는 데 사용되는
MAC이 모두 충돌 저항성을 가질 것을 요구한다. 자세한 내용은
부록 E.1.1을 참조하라. 참고: binder는 다른 PSK의 binder 값을
포함하지 않지만, 그것들은 Finished MAC에 포함된다.
TLS는 현재 비인증서 기반 핸드셰이크(예: PSK)에서 서버가
certificate_request 메시지를 보내는 것을 허용하지 않는다. 이 제한이
향후 완화된다면, 클라이언트의 서명은 서버의 인증서를 직접 포함하지
않을 것이다. 그러나 PSK가 NewSessionTicket을 통해 설정되었다면,
클라이언트의 서명은 PSK binder를 통해 서버의 인증서를 전이적으로
포함할 것이다. [PSK-FINISHED]는 서버의 인증서에 결속하지 않는 구성에 대한
구체적 공격을 설명한다([Kraw16]도 참조). 클라이언트가 동일한
PSK/key-id 쌍을 두 서로 다른 엔드포인트와 잠재적으로 공유할 수 있다면
인증서 기반 클라이언트 인증을 사용하는 것은 안전하지 않다. 구현은
어떤 확장에 의해 협상되지 않는 한 외부 PSK를 클라이언트 또는 서버의
인증서 기반 인증과 결합해서는 안 된다(MUST NOT).
익스포터가 사용되면, 이는 고유하고 비밀인 값(고유한 session key에서
생성되기 때문)을 생성한다. 서로 다른 label과 context로 계산된
익스포터는 계산적으로 독립적이므로, 하나로부터 다른 하나 또는 내보낸
값으로부터 session secret을 계산하는 것은 가능하지 않다. 참고:
익스포터는 임의 길이 값을 생성할 수 있다. 익스포터가 channel binding으로
사용되려면, 내보낸 값은 충돌 저항성을 제공할 만큼 충분히 커야 한다
(MUST). TLS 1.3에서 제공되는 익스포터는 각각 early traffic key 및
application traffic key와 같은 Handshake Context에서 파생되므로 유사한
보안 속성을 가진다. 이들은 클라이언트 인증서를 포함하지 않는다는 점에
유의하라. 클라이언트 인증서에 결속하려는 향후 애플리케이션은 전체
핸드셰이크 전사를 포함하는 새 익스포터를 정의해야 할 수 있다.
Rescorla 표준 트랙 [144페이지]
RFC 8446 TLS 2018년 8월
모든 핸드셰이크 모드에서 Finished MAC(그리고 존재하는 경우 서명)은
다운그레이드 공격을 방지한다. 또한 섹션 4.1.3에 설명된 대로
random nonce의 특정 바이트를 사용하면 이전 TLS 버전으로의 다운그레이드를
감지할 수 있다. TLS 1.3과 다운그레이드에 대한 자세한 내용은
[BBFGKZ16]을 참조하라.
클라이언트와 서버가 공유 키를 설정하기에 충분한 정보를 교환하자마자,
핸드셰이크의 나머지는 암호화된다. 따라서 계산된 공유 키가 인증되지
않았더라도 수동 공격자에 대한 보호를 제공한다. 서버가 클라이언트보다
먼저 인증하므로, 클라이언트는 자신이 서버에 인증할 경우 자신의 신원을
인증된 서버에게만 드러낸다는 것을 보장할 수 있다. 구현은 길이로 인해
신원 정보가 누출되는 것을 피하기 위해 핸드셰이크 중 제공된 레코드
패딩 메커니즘을 사용해야 한다는 점에 유의하라. 클라이언트가 제안한
PSK 신원은 암호화되지 않으며, 서버가 선택한 것도 암호화되지 않는다.
E.1.1. 키 파생 및 HKDF
TLS 1.3의 키 파생은 [RFC5869]에 정의된 HKDF와 그 두 구성요소인
HKDF-Extract 및 HKDF-Expand를 사용한다. HKDF 구성에 대한 전체 근거는
[Kraw10]에서 찾을 수 있고, TLS 1.3에서 사용되는 방식에 대한 근거는
[KW16]에서 찾을 수 있다. 이 문서 전체에서 HKDF-Extract의 각 적용
뒤에는 하나 이상의 HKDF-Expand 호출이 따른다. 이 순서는 항상 따라야
한다(이 문서의 향후 개정에서도 포함). 특히 중간에 HKDF-Expand 없이
HKDF-Extract의 출력을 또 다른 HKDF-Extract 적용의 입력으로 사용해서는
안 된다(SHOULD NOT). 같은 입력 중 일부에 HKDF-Expand를 여러 번 적용하는
것은 이들이 키 및/또는 label을 통해 구별되는 한 허용된다.
HKDF-Expand는 입력과 출력이 모두 가변 길이인 의사난수 함수(PRF)를
구현한다는 점에 유의하라. 이 문서에서 HKDF를 사용하는 일부 경우
(예: 익스포터와 resumption_master_secret 생성)에는 HKDF-Expand의 적용이
충돌 저항성을 가질 필요가 있다. 즉, 같은 값을 출력하는 두 개의 서로
다른 HKDF-Expand 입력을 찾는 것이 불가능해야 한다. 이는 기반 해시
함수가 충돌 저항성을 가질 것과 HKDF-Expand의 출력 길이가 최소
256비트(또는 해시 함수가 충돌 찾기를 방지하는 데 필요한 만큼)일 것을
요구한다.
Rescorla 표준 트랙 [145페이지]
RFC 8446 TLS 2018년 8월
E.1.2. 클라이언트 인증
핸드셰이크 중이든 핸드셰이크 후 인증 중이든 서버에 인증 데이터를 보낸
클라이언트는 그 뒤 서버가 클라이언트를 인증된 것으로 간주하는지 여부를
확신할 수 없다. 클라이언트가 서버가 연결을 단방향 인증 또는 상호 인증
연결로 간주하는지 판단해야 한다면, 이는 애플리케이션 계층에서
제공되어야 한다. 자세한 내용은 [CHHSV17]을 참조하라. 또한
[Kraw16]의 핸드셰이크 후 인증 분석은 핸드셰이크 후 단계에서 전송된
인증서로 식별되는 클라이언트가 트래픽 키를 보유함을 보여준다. 따라서
이 당사자는 원래 핸드셰이크에 참여한 클라이언트이거나, 원래 클라이언트가
트래픽 키를 위임한 당사자이다(트래픽 키가 손상되지 않았다고 가정).
E.1.3. 0-RTT
0-RTT 동작 모드는 일반적으로 1-RTT 데이터와 유사한 보안 속성을
제공한다. 단, 두 가지 예외가 있다. 0-RTT 암호화 키는 완전한 순방향
비밀성을 제공하지 않으며, 서버는 잠재적으로 과도한 양의 상태를
유지하지 않고는 핸드셰이크의 고유성(재생 불가능성)을 보장할 수 없다.
재생 노출을 제한하는 메커니즘은 섹션 8을 참조하라.
E.1.4. 익스포터 독립성
exporter_master_secret 및 early_exporter_master_secret은 트래픽 키와
독립되도록 파생되므로, 해당 키로 암호화된 트래픽의 보안에 위협이
되지 않는다. 그러나 이러한 시크릿은 어떤 익스포터 값이든 계산하는 데
사용될 수 있으므로 가능한 한 빨리 지워져야 한다(SHOULD). 익스포터
label의 전체 집합이 알려져 있다면, 구현은 모든 해당 label에 대해
익스포터 계산의 내부 Derive-Secret 단계를 미리 계산한 다음,
[early_]exporter_master_secret을 지우고, 이어서 각 내부 값이 다시
필요하지 않을 것임을 알게 되는 즉시 그 값을 지워야 한다(SHOULD).
E.1.5. 손상 후 보안
TLS는 피어의 장기 시크릿(서명 키 또는 외부 PSK)이 손상된 뒤 일어나는
핸드셰이크에 대해 보안을 제공하지 않는다. 따라서 post-compromise
security [CCG16]를 제공하지 않으며, 이는 때때로 backward 또는 future
secrecy라고도 불린다. 이는 자기 자신의 장기 시크릿이 손상된 뒤
당사자가 가지는 보안 보장을 설명하는 KCI 저항성과 대조된다.
Rescorla 표준 트랙 [146페이지]
RFC 8446 TLS 2018년 8월
E.1.6. 외부 참고문헌
독자는 TLS 핸드셰이크 분석에 대해 다음 참고문헌을 참조해야 한다.
[DFGS15], [CHSV16], [DFGS16], [KW16], [Kraw16],
[FGSW16], [LXZFH16], [FG17], 그리고 [BBK17].
E.2. 레코드 계층
레코드 계층은 핸드셰이크가 양방향 암호화 키와 nonce를 파생하는 데
사용할 수 있는 강력한 트래픽 시크릿을 생성하는 것에 의존한다. 그것이
참이고, 키가 섹션 5.5에 표시된 것보다 더 많은 데이터에 사용되지
않는다면, 레코드 계층은 다음 보장을 제공해야 한다.
기밀성: 공격자는 주어진 레코드의 평문 내용을 결정할 수 없어야 한다.
무결성: 공격자는 기존 레코드와 다르면서 수신자가 수락할 새 레코드를
만들어낼 수 없어야 한다.
순서 보호/재생 불가능성: 공격자는 수신자가 이미 수락한 레코드를 다시
수락하게 하거나, 레코드 N을 먼저 처리하지 않고 레코드 N+1을 수락하게
할 수 없어야 한다.
길이 은닉: 주어진 외부 길이를 가진 레코드에 대해, 공격자는 레코드 중
어느 정도가 content이고 어느 정도가 padding인지 결정할 수 없어야 한다.
키 변경 후 순방향 비밀성: 섹션 4.6.3에 설명된 트래픽 키 갱신
메커니즘이 사용되었고 이전 세대 키가 삭제되었다면, 엔드포인트를
손상시킨 공격자는 이전 키로 암호화된 트래픽을 복호화할 수 없어야
한다.
비공식적으로, TLS 1.3은 평문을 강한 키로 AEAD 보호함으로써 이러한
속성을 제공한다. AEAD 암호화 [RFC5116]는 데이터에 대한 기밀성과
무결성을 제공한다. 재생 불가능성은 각 레코드에 별도의 nonce를 사용해
제공되며, 이 nonce는 레코드 시퀀스 번호에서 파생된다(섹션 5.3).
시퀀스 번호는 양쪽에서 독립적으로 유지되므로, 순서가 뒤바뀌어 전달된
레코드는 AEAD 보호 해제 실패를 일으킨다. 같은 평문이 서로 다른
사용자에 의해 같은 키 아래 반복적으로 암호화될 때(HTTP에서 흔히
그렇듯) 대량 암호 분석을 방지하기 위해, nonce는 시퀀스 번호를
Rescorla 표준 트랙 [147페이지]
RFC 8446 TLS 2018년 8월
트래픽 키와 함께 파생된 연결별 비밀 초기화 벡터와 혼합하여 형성된다.
이 구성의 분석은 [BT16]을 참조하라.
TLS 1.3의 rekeying 기법(섹션 7.2 참조)은 [REKEY]에서 논의된 직렬
생성기 구성을 따르며, 이는 rekeying이 rekeying 없이보다 더 많은 수의
암호화에 키를 사용할 수 있게 함을 보여준다. 이는 의사난수 함수(PRF)로서
HKDF-Expand-Label 함수의 보안에 의존한다. 또한 이 함수가 진정한
단방향 함수인 한, 키 변경 이전의 트래픽 키를 계산하는 것은 가능하지
않다(순방향 비밀성).
TLS는 연결의 트래픽 시크릿이 손상된 뒤 그 연결에서 전달되는 데이터에
대한 보안을 제공하지 않는다. 즉, TLS는 트래픽 시크릿에 대해
post-compromise security/future secrecy/backward secrecy를 제공하지
않는다. 실제로 트래픽 시크릿을 알게 된 공격자는 그 연결의 모든 향후
트래픽 시크릿을 계산할 수 있다. 그러한 보장을 원하는 시스템은 새
핸드셰이크를 수행하고 (EC)DHE 교환을 통해 새 연결을 설정해야 한다.
E.2.1. 외부 참고문헌
독자는 TLS 레코드 계층 분석에 대해 다음 참고문헌을 참조해야 한다.
[BMMRT15], [BT16], [BDFKPPRSZZ16], [BBK17], 그리고
[PS18].
E.3. 트래픽 분석
TLS는 암호화된 패킷의 길이와 타이밍 관찰에 기반한 다양한 트래픽 분석
공격에 취약하다 [CLINIC] [HCJC16]. 이는 고정된 콘텐츠 말뭉치를 호스팅하는
비디오 서버처럼 구별해야 할 가능한 메시지 집합이 작은 경우 특히
쉽지만, 더 복잡한 시나리오에서도 여전히 유용한 정보를 제공한다.
TLS는 이러한 형태의 공격에 대한 특정 방어를 제공하지 않지만
애플리케이션이 사용할 수 있는 패딩 메커니즘을 포함한다. AEAD 함수로
보호되는 평문은 content와 가변 길이 padding으로 구성되며, 이를 통해
애플리케이션은 임의 길이의 암호화된 레코드와 padding-only cover traffic을
만들어 전송 기간과 침묵 기간의 차이를 숨길 수 있다. 패딩은 실제
content와 함께 암호화되므로 공격자는 패딩의 길이를 직접 결정할 수는
없지만, 레코드 처리 중 노출되는 타이밍 채널을 사용하여 간접적으로
측정할 수는 있다(즉, 레코드 처리에 걸리는 시간을 보거나, 레코드를
조금씩 흘려보내 어떤 것이 서버의 응답을 유도하는지 확인).
Rescorla 표준 트랙 [148페이지]
RFC 8446 TLS 2018년 8월
일반적으로 이러한 채널을 모두 제거하는 방법은 알려져 있지 않다.
constant-time padding removal 함수조차 content를 데이터 의존적인 함수에
전달할 가능성이 높기 때문이다. 최소한 완전히 constant-time인 서버 또는
클라이언트는 해당 상위 수준 프로토콜을 constant time으로 만드는 것을
포함하여 애플리케이션 계층 프로토콜 구현과의 긴밀한 협력이 필요하다.
참고: 강건한 트래픽 분석 방어는 패킷 전송 지연과 트래픽 양 증가로 인해
성능 저하를 초래할 가능성이 높다.
E.4. 부채널 공격
일반적으로 TLS는 부채널 공격(즉, 타이밍 같은 2차 채널을 통해 통신을
공격하는 것)에 대한 특정 방어를 갖지 않으며, 이를 관련 암호학적
primitive의 구현에 맡긴다. 그러나 TLS의 특정 기능은 부채널 저항성
코드를 작성하기 쉽게 하도록 설계되어 있다.
- 복합 MAC-then-encrypt 구조를 사용했던 이전 TLS 버전과 달리,
TLS 1.3은 AEAD 알고리즘만 사용하므로 구현이 해당 primitive의
자체 포함 constant-time 구현을 사용할 수 있게 한다.
- TLS는 모든 복호화 오류에 대해 균일한 "bad_record_mac" alert를
사용하며, 이는 공격자가 메시지의 일부에 대해 조각별 통찰을 얻는
것을 방지하기 위한 것이다. 그러한 오류에서 연결을 종료함으로써
추가 저항성이 제공된다. 새 연결은 서로 다른 암호학적 자료를 가지므로,
여러 번의 시도가 필요한 암호학적 primitive에 대한 공격을 방지한다.
부채널을 통한 정보 누출은 TLS 위의 계층, 즉 애플리케이션 프로토콜과
이를 사용하는 애플리케이션에서 발생할 수 있다. 부채널 공격에 대한
저항성은 애플리케이션과 애플리케이션 프로토콜이 기밀 정보가 의도치
않게 누출되지 않도록 별도로 보장하는 데 달려 있다.
Rescorla 표준 트랙 [149페이지]
RFC 8446 TLS 2018년 8월
E.5. 0-RTT에 대한 재생 공격
재생 가능한 0-RTT 데이터는 TLS를 사용하는 애플리케이션에 여러 보안
위협을 제기한다. 단, 해당 애플리케이션이 재생 아래에서도 안전하도록
특별히 설계된 경우는 예외이다(최소한 이는 멱등성을 의미하지만, 많은
경우 constant-time 응답 같은 다른 더 강한 조건도 요구할 수 있다).
잠재적 공격에는 다음이 포함된다.
- 부작용을 일으키는 동작(예: 물품 구매 또는 송금)을 중복시켜 사이트
또는 사용자에게 해를 끼치는 것.
- 공격자가 0-RTT 메시지를 저장하고 재생하여 다른 메시지와의 관계에서
순서를 바꾸는 것(예: delete를 create 뒤로 이동).
- 0-RTT 메시지를 다른 캐시 노드에 재생한 다음 별도 연결을 사용해 요청
지연 시간을 측정하여 두 요청이 같은 리소스를 대상으로 하는지 확인함으로써,
캐시 타이밍 동작을 악용하여 0-RTT 메시지의 내용을 발견하는 것.
데이터를 많은 횟수로 재생할 수 있다면, 암호학적 동작 속도를 반복적으로
측정하는 것 같은 추가 공격이 가능해진다. 또한 rate-limiting 시스템을
과부하시킬 수도 있다. 이러한 공격에 대한 추가 설명은 [Mac17]을
참조하라.
궁극적으로, 서버는 0-RTT 데이터 복제를 사용하는 공격으로부터 자신을
보호할 책임이 있다. 섹션 8에 설명된 메커니즘은 TLS 계층에서 재생을
방지하려는 것이지만, 클라이언트 데이터의 여러 사본 수신에 대한 완전한
보호를 제공하지 않는다. TLS 1.3은 서버가 클라이언트에 대한 정보를
전혀 가지지 않을 때 1-RTT 핸드셰이크로 폴백한다. 예를 들어 상태를
공유하지 않는 다른 클러스터에 있거나 섹션 8.1에 설명된 대로
티켓이 삭제된 경우이다. 애플리케이션 계층 프로토콜이 이 설정에서
데이터를 재전송하면, 공격자는 원래 클러스터(데이터를 즉시 처리)와
1-RTT로 폴백한 뒤 애플리케이션 계층 재생 시 데이터를 처리할 다른
클러스터 모두에 ClientHello를 보내 메시지 중복을 유도할 수 있다.
이 공격의 규모는 클라이언트가 트랜잭션 재시도를 얼마나 기꺼이
수행하는지에 의해 제한되므로 제한된 양의 중복만 허용하며, 각 사본은
서버에서 새 연결로 나타난다.
Rescorla 표준 트랙 [150페이지]
RFC 8446 TLS 2018년 8월
올바르게 구현된 경우, 섹션 8.1 및 8.2에 설명된 메커니즘은 재생된
ClientHello와 그 연관 0-RTT 데이터가 일관된 상태를 가진 어떤
클러스터에서도 여러 번 수락되는 것을 방지한다. 단일 티켓에 대해
0-RTT 사용을 하나의 클러스터로 제한하는 서버의 경우, 주어진
ClientHello와 그 연관 0-RTT 데이터는 한 번만 수락된다. 그러나 상태가
완전히 일관되지 않으면, 공격자가 복제 창 동안 데이터의 여러 사본이
수락되도록 만들 수 있다. 클라이언트는 서버 동작의 정확한 세부사항을
알지 못하므로, 재생되어도 안전하지 않고 여러 1-RTT 연결에 걸쳐
재시도할 의향도 없는 메시지를 early data로 보내서는 안 된다(MUST NOT).
애플리케이션 프로토콜은 그 사용을 정의하는 프로파일 없이 0-RTT 데이터를
사용해서는 안 된다(MUST NOT). 그 프로파일은 어떤 메시지 또는 상호작용이
0-RTT와 함께 사용해도 안전한지, 그리고 서버가 0-RTT를 거부하고
1-RTT로 폴백하는 상황을 어떻게 처리할지 식별해야 한다.
또한 우발적 오용을 피하기 위해, TLS 구현은 애플리케이션이 특별히
요청하지 않는 한 0-RTT(전송 또는 수락)를 활성화해서는 안 되며(MUST NOT),
애플리케이션의 지시가 없는 한 서버가 거부한 0-RTT 데이터를 자동으로
다시 보내서는 안 된다(MUST NOT). 서버 측 애플리케이션은 일부 종류의
애플리케이션 트래픽에 대해 0-RTT 데이터의 특수 처리를 구현하고 싶을 수
있다(예: 연결 중단, 애플리케이션 계층에서 데이터 재전송 요청, 또는
핸드셰이크가 완료될 때까지 처리 지연). 애플리케이션이 이러한 처리를
구현할 수 있도록, TLS 구현은 애플리케이션이 핸드셰이크가 완료되었는지
판단할 수 있는 방법을 제공해야 한다(MUST).
E.5.1. 재생 및 익스포터
ClientHello의 재생은 같은 early exporter를 생성하므로, 이러한 익스포터를
사용하는 애플리케이션에는 추가 주의가 필요하다. 특히 이러한 익스포터가
인증 channel binding으로 사용되는 경우(예: 익스포터 출력을 서명),
PSK를 손상시킨 공격자는 인증 키를 손상시키지 않고도 연결 사이에
authenticator를 이식할 수 있다.
또한 early exporter는 server-to-client 암호화 키를 생성하는 데 사용되어서는
안 된다(SHOULD NOT). 이는 해당 키의 재사용을 수반하기 때문이다. 이는
early application traffic key가 client-to-server 방향으로만 사용되는 것과
유사하다.
Rescorla 표준 트랙 [151페이지]
RFC 8446 TLS 2018년 8월
E.6. PSK 신원 노출
구현은 유효하지 않은 PSK binder에 대해 핸드셰이크를 중단하여 응답하므로,
공격자가 주어진 PSK 신원이 유효한지 검증하는 것이 가능할 수 있다.
구체적으로, 서버가 external-PSK 핸드셰이크와 인증서 기반 핸드셰이크를
모두 수락하는 경우, 유효한 PSK 신원은 실패한 핸드셰이크를 초래하지만,
유효하지 않은 신원은 단지 건너뛰어져 성공적인 인증서 핸드셰이크를
초래한다. PSK 핸드셰이크만 지원하는 서버는 유효한 PSK 신원이 없는
경우와 신원은 있지만 유효하지 않은 binder를 가진 경우를 동일하게
처리함으로써 이러한 형태의 공격에 저항할 수 있다.
E.7. PSK 공유
TLS 1.3은 PSK를 특정 KDF에 결속함으로써 보수적인 접근을 취한다. 반대로
TLS 1.2는 PSK를 어떤 해시 함수 및 TLS 1.2 PRF와도 함께 사용할 수 있게
한다. 따라서 TLS 1.2와 TLS 1.3 모두에서 사용되는 모든 PSK는 TLS 1.3에서
하나의 해시와만 함께 사용되어야 하며, 사용자가 단일 PSK를 provision하려는
경우 이는 최적보다 덜 좋다. TLS 1.2와 TLS 1.3의 구성은 다르지만 둘 다
HMAC에 기반한다. 같은 PSK가 두 버전에서 관련 출력을 생성할 수 있는
알려진 방법은 없지만, 제한적인 분석만 수행되었다. 구현은 TLS 1.3과
TLS 1.2 사이에서 PSK를 재사용하지 않음으로써 교차 프로토콜 관련 출력에
대한 안전성을 보장할 수 있다.
E.8. 정적 RSA에 대한 공격
TLS 1.3은 RSA 키 전송을 사용하지 않으므로 Bleichenbacher 유형 공격
[Blei98]에 직접적으로 취약하지는 않지만, TLS 1.3 서버가 이전 TLS 버전
맥락에서 정적 RSA도 지원한다면 TLS 1.3 연결에 대해 서버를 가장하는
것이 가능할 수 있다 [JSS15]. TLS 1.3 구현은 모든 TLS 버전에서
정적 RSA 지원을 비활성화함으로써 이 공격을 방지할 수 있다. 원칙적으로
구현은 정적 RSA 복호화와 RSA 서명을 위해 서로 다른 keyUsage 비트를
가진 인증서를 분리할 수도 있을 것이다. 그러나 이 기법은 클라이언트가
digitalSignature 비트가 설정되지 않은 인증서의 키를 사용한 서명을
수락하지 않는 것에 의존하며, 많은 클라이언트는 이 제한을 강제하지
않는다.
Rescorla 표준 트랙 [152페이지]
RFC 8446 TLS 2018년 8월
기여자
Martin Abadi
University of California, Santa Cruz
abadi@cs.ucsc.edu
Christopher Allen
(TLS 1.0의 공동 편집자)
Alacrity Ventures
ChristopherA@AlacrityManagement.com
Richard Barnes
Cisco
rlb@ipv.sx
Steven M. Bellovin
Columbia University
smb@cs.columbia.edu
David Benjamin
Google
davidben@google.com
Benjamin Beurdouche
INRIA & Microsoft Research
benjamin.beurdouche@ens.fr
Karthikeyan Bhargavan
([RFC7627]의 편집자)
INRIA
karthikeyan.bhargavan@inria.fr
Simon Blake-Wilson
([RFC4492]의 공동 저자)
BCI
sblakewilson@bcisse.com
Nelson Bolyard
([RFC4492]의 공동 저자)
Sun Microsystems, Inc.
nelson@bolyard.com
Ran Canetti
IBM
canetti@watson.ibm.com
Rescorla 표준 트랙 [153페이지]
RFC 8446 TLS 2018년 8월
Matt Caswell
OpenSSL
matt@openssl.org
Stephen Checkoway
University of Illinois at Chicago
sfc@uic.edu
Pete Chown
Skygate Technology Ltd
pc@skygate.co.uk
Katriel Cohn-Gordon
University of Oxford
me@katriel.co.uk
Cas Cremers
University of Oxford
cas.cremers@cs.ox.ac.uk
Antoine Delignat-Lavaud
([RFC7627]의 공동 저자)
INRIA
antdl@microsoft.com
Tim Dierks
(TLS 1.0의 공동 저자, TLS 1.1 및 1.2의 공동 편집자)
Independent
tim@dierks.org
Roelof DuToit
Symantec Corporation
roelof_dutoit@symantec.com
Taher Elgamal
Securify
taher@securify.com
Pasi Eronen
Nokia
pasi.eronen@nokia.com
Cedric Fournet
Microsoft
fournet@microsoft.com
Rescorla 표준 트랙 [154페이지]
RFC 8446 TLS 2018년 8월
Anil Gangolli
anil@busybuddha.org
David M. Garrett
dave@nulldereference.com
Illya Gerasymchuk
Independent
illya@iluxonchik.me
Alessandro Ghedini
Cloudflare Inc.
alessandro@cloudflare.com
Daniel Kahn Gillmor
ACLU
dkg@fifthhorseman.net
Matthew Green
Johns Hopkins University
mgreen@cs.jhu.edu
Jens Guballa
ETAS
jens.guballa@etas.com
Felix Guenther
TU Darmstadt
mail@felixguenther.info
Vipul Gupta
([RFC4492]의 공동 저자)
Sun Microsystems Laboratories
vipul.gupta@sun.com
Chris Hawk
([RFC4492]의 공동 저자)
Corriente Networks LLC
chris@corriente.net
Kipp Hickman
Alfred Hoenes
David Hopwood
Independent Consultant
david.hopwood@blueyonder.co.uk
Rescorla 표준 트랙 [155페이지]
RFC 8446 TLS 2018년 8월
Marko Horvat
MPI-SWS
mhorvat@mpi-sws.org
Jonathan Hoyland
Royal Holloway, University of London
jonathan.hoyland@gmail.com
Subodh Iyengar
Facebook
subodh@fb.com
Benjamin Kaduk
Akamai Technologies
kaduk@mit.edu
Hubert Kario
Red Hat Inc.
hkario@redhat.com
Phil Karlton
(SSL 3.0의 공동 저자)
Leon Klingele
Independent
mail@leonklingele.de
Paul Kocher
(SSL 3.0의 공동 저자)
Cryptography Research
paul@cryptography.com
Hugo Krawczyk
IBM
hugokraw@us.ibm.com
Adam Langley
([RFC7627]의 공동 저자)
Google
agl@google.com
Olivier Levillain
ANSSI
olivier.levillain@ssi.gouv.fr
Rescorla 표준 트랙 [156페이지]
RFC 8446 TLS 2018년 8월
Xiaoyin Liu
University of North Carolina at Chapel Hill
xiaoyin.l@outlook.com
Ilari Liusvaara
Independent
ilariliusvaara@welho.com
Atul Luykx
K.U. Leuven
atul.luykx@kuleuven.be
Colm MacCarthaigh
Amazon Web Services
colm@allcosts.net
Carl Mehner
USAA
carl.mehner@usaa.com
Jan Mikkelsen
Transactionware
janm@transactionware.com
Bodo Moeller
([RFC4492]의 공동 저자)
Google
bodo@acm.org
Kyle Nekritz
Facebook
knekritz@fb.com
Erik Nygren
Akamai Technologies
erik+ietf@nygren.org
Magnus Nystrom
Microsoft
mnystrom@microsoft.com
Kazuho Oku
DeNA Co., Ltd.
kazuhooku@gmail.com
Rescorla 표준 트랙 [157페이지]
RFC 8446 TLS 2018년 8월
Kenny Paterson
Royal Holloway, University of London
kenny.paterson@rhul.ac.uk
Christopher Patton
University of Florida
cjpatton@ufl.edu
Alfredo Pironti
([RFC7627]의 공동 저자)
INRIA
alfredo.pironti@inria.fr
Andrei Popov
Microsoft
andrei.popov@microsoft.com
Marsh Ray
([RFC7627]의 공동 저자)
Microsoft
maray@microsoft.com
Robert Relyea
Netscape Communications
relyea@netscape.com
Kyle Rose
Akamai Technologies
krose@krose.org
Jim Roskind
Amazon
jroskind@amazon.com
Michael Sabin
Joe Salowey
Tableau Software
joe@salowey.net
Rich Salz
Akamai
rsalz@akamai.com
David Schinazi
Apple Inc.
dschinazi@apple.com
Rescorla 표준 트랙 [158페이지]
RFC 8446 TLS 2018년 8월
Sam Scott
Royal Holloway, University of London
me@samjs.co.uk
Thomas Shrimpton
University of Florida
teshrim@ufl.edu
Dan Simon
Microsoft, Inc.
dansimon@microsoft.com
Brian Smith
Independent
brian@briansmith.org
Brian Sniffen
Akamai Technologies
ietf@bts.evenmere.org
Nick Sullivan
Cloudflare Inc.
nick@cloudflare.com
Bjoern Tackmann
University of California, San Diego
btackmann@eng.ucsd.edu
Tim Taubert
Mozilla
ttaubert@mozilla.com
Martin Thomson
Mozilla
mt@mozilla.com
Hannes Tschofenig
Arm Limited
Hannes.Tschofenig@arm.com
Sean Turner
sn3rd
sean@sn3rd.com
Steven Valdez
Google
svaldez@google.com
Rescorla 표준 트랙 [159페이지]
RFC 8446 TLS 2018년 8월
Filippo Valsorda
Cloudflare Inc.
filippo@cloudflare.com
Thyla van der Merwe
Royal Holloway, University of London
tjvdmerwe@gmail.com
Victor Vasiliev
Google
vasilvv@google.com
Hoeteck Wee
Ecole Normale Superieure, Paris
hoeteck@alum.mit.edu
Tom Weinstein
David Wong
NCC Group
david.wong@nccgroup.trust
Christopher A. Wood
Apple Inc.
cawood@apple.com
Tim Wright
Vodafone
timothy.wright@vodafone.com
Peter Wu
Independent
peter@lekensteyn.nl
Kazu Yamamoto
Internet Initiative Japan Inc.
kazu@iij.ad.jp
저자 주소
Eric Rescorla
Mozilla
이메일: ekr@rtfm.com
Rescorla 표준 트랙 [160페이지]