1// +build !go1.15
2
3package qtls
4
5import (
6	"crypto"
7	"crypto/cipher"
8	"crypto/tls"
9	"net"
10	"unsafe"
11
12	"github.com/marten-seemann/qtls"
13)
14
15type (
16	// Alert is a TLS alert
17	Alert = qtls.Alert
18	// A Certificate is qtls.Certificate.
19	Certificate = qtls.Certificate
20	// CertificateRequestInfo contains inforamtion about a certificate request.
21	CertificateRequestInfo = qtls.CertificateRequestInfo
22	// A CipherSuiteTLS13 is a cipher suite for TLS 1.3
23	CipherSuiteTLS13 = qtls.CipherSuiteTLS13
24	// ClientHelloInfo contains information about a ClientHello.
25	ClientHelloInfo = qtls.ClientHelloInfo
26	// ClientSessionCache is a cache used for session resumption.
27	ClientSessionCache = qtls.ClientSessionCache
28	// ClientSessionState is a state needed for session resumption.
29	ClientSessionState = qtls.ClientSessionState
30	// A Config is a qtls.Config.
31	Config = qtls.Config
32	// A Conn is a qtls.Conn.
33	Conn = qtls.Conn
34	// ConnectionState contains information about the state of the connection.
35	ConnectionState = qtls.ConnectionState
36	// EncryptionLevel is the encryption level of a message.
37	EncryptionLevel = qtls.EncryptionLevel
38	// Extension is a TLS extension
39	Extension = qtls.Extension
40	// RecordLayer is a qtls RecordLayer.
41	RecordLayer = qtls.RecordLayer
42)
43
44type ExtraConfig struct {
45	// GetExtensions, if not nil, is called before a message that allows
46	// sending of extensions is sent.
47	// Currently only implemented for the ClientHello message (for the client)
48	// and for the EncryptedExtensions message (for the server).
49	// Only valid for TLS 1.3.
50	GetExtensions func(handshakeMessageType uint8) []Extension
51
52	// ReceivedExtensions, if not nil, is called when a message that allows the
53	// inclusion of extensions is received.
54	// It is called with an empty slice of extensions, if the message didn't
55	// contain any extensions.
56	// Currently only implemented for the ClientHello message (sent by the
57	// client) and for the EncryptedExtensions message (sent by the server).
58	// Only valid for TLS 1.3.
59	ReceivedExtensions func(handshakeMessageType uint8, exts []Extension)
60
61	// AlternativeRecordLayer is used by QUIC
62	AlternativeRecordLayer RecordLayer
63
64	// Enforce the selection of a supported application protocol.
65	// Only works for TLS 1.3.
66	// If enabled, client and server have to agree on an application protocol.
67	// Otherwise, connection establishment fails.
68	EnforceNextProtoSelection bool
69
70	// If MaxEarlyData is greater than 0, the client will be allowed to send early
71	// data when resuming a session.
72	// Requires the AlternativeRecordLayer to be set.
73	//
74	// It has no meaning on the client.
75	MaxEarlyData uint32
76
77	// The Accept0RTT callback is called when the client offers 0-RTT.
78	// The server then has to decide if it wants to accept or reject 0-RTT.
79	// It is only used for servers.
80	Accept0RTT func(appData []byte) bool
81
82	// 0RTTRejected is called when the server rejectes 0-RTT.
83	// It is only used for clients.
84	Rejected0RTT func()
85
86	// If set, the client will export the 0-RTT key when resuming a session that
87	// allows sending of early data.
88	// Requires the AlternativeRecordLayer to be set.
89	//
90	// It has no meaning to the server.
91	Enable0RTT bool
92
93	// Is called when the client saves a session ticket to the session ticket.
94	// This gives the application the opportunity to save some data along with the ticket,
95	// which can be restored when the session ticket is used.
96	GetAppDataForSessionState func() []byte
97
98	// Is called when the client uses a session ticket.
99	// Restores the application data that was saved earlier on GetAppDataForSessionTicket.
100	SetAppDataFromSessionState func([]byte)
101}
102
103const (
104	// EncryptionHandshake is the Handshake encryption level
105	EncryptionHandshake = qtls.EncryptionHandshake
106	// Encryption0RTT is the 0-RTT encryption level
107	Encryption0RTT = qtls.Encryption0RTT
108	// EncryptionApplication is the application data encryption level
109	EncryptionApplication = qtls.EncryptionApplication
110)
111
112// CipherSuiteName gets the name of a cipher suite.
113func CipherSuiteName(id uint16) string {
114	return qtls.CipherSuiteName(id)
115}
116
117// HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
118func HkdfExtract(hash crypto.Hash, newSecret, currentSecret []byte) []byte {
119	return qtls.HkdfExtract(hash, newSecret, currentSecret)
120}
121
122// HkdfExpandLabel HKDF expands a label
123func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte {
124	return qtls.HkdfExpandLabel(hash, secret, hashValue, label, L)
125}
126
127// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3
128func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
129	return qtls.AEADAESGCMTLS13(key, fixedNonce)
130}
131
132// Client returns a new TLS client side connection.
133func Client(conn net.Conn, config *tls.Config, extraConfig *ExtraConfig) *Conn {
134	return qtls.Client(conn, tlsConfigToQtlsConfig(config, extraConfig))
135}
136
137// Server returns a new TLS server side connection.
138func Server(conn net.Conn, config *tls.Config, extraConfig *ExtraConfig) *Conn {
139	return qtls.Server(conn, tlsConfigToQtlsConfig(config, extraConfig))
140}
141
142func GetConnectionState(conn *Conn) ConnectionState {
143	return conn.ConnectionState()
144}
145
146// ToTLSConnectionState extracts the tls.ConnectionState
147// Warning: Calling ExportKeyingMaterial won't work.
148func ToTLSConnectionState(cs ConnectionState) tls.ConnectionState {
149	return tls.ConnectionState{
150		Version:                     cs.Version,
151		HandshakeComplete:           cs.HandshakeComplete,
152		DidResume:                   cs.DidResume,
153		CipherSuite:                 cs.CipherSuite,
154		NegotiatedProtocol:          cs.NegotiatedProtocol,
155		NegotiatedProtocolIsMutual:  cs.NegotiatedProtocolIsMutual,
156		ServerName:                  cs.ServerName,
157		PeerCertificates:            cs.PeerCertificates,
158		VerifiedChains:              cs.VerifiedChains,
159		SignedCertificateTimestamps: cs.SignedCertificateTimestamps,
160		OCSPResponse:                cs.OCSPResponse,
161		TLSUnique:                   cs.TLSUnique,
162	}
163}
164
165type cipherSuiteTLS13 struct {
166	ID     uint16
167	KeyLen int
168	AEAD   func(key, fixedNonce []byte) cipher.AEAD
169	Hash   crypto.Hash
170}
171
172//go:linkname cipherSuiteTLS13ByID github.com/marten-seemann/qtls.cipherSuiteTLS13ByID
173func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13
174
175// CipherSuiteTLS13ByID gets a TLS 1.3 cipher suite.
176func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 {
177	val := cipherSuiteTLS13ByID(id)
178	cs := (*cipherSuiteTLS13)(unsafe.Pointer(val))
179	return &qtls.CipherSuiteTLS13{
180		ID:     cs.ID,
181		KeyLen: cs.KeyLen,
182		AEAD:   cs.AEAD,
183		Hash:   cs.Hash,
184	}
185}
186