/
crypto_setup_tls.go
139 lines (117 loc) · 3.64 KB
/
crypto_setup_tls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package handshake
import (
"crypto/tls"
"fmt"
"io"
"sync"
"github.com/bifurcation/mint"
"github.com/lucas-clemente/quic-go/internal/crypto"
"github.com/lucas-clemente/quic-go/internal/protocol"
)
// KeyDerivationFunction is used for key derivation
type KeyDerivationFunction func(crypto.MintController, protocol.Perspective) (crypto.AEAD, error)
type cryptoSetupTLS struct {
mutex sync.RWMutex
perspective protocol.Perspective
keyDerivation KeyDerivationFunction
mintConf *mint.Config
conn crypto.MintController
nullAEAD crypto.AEAD
aead crypto.AEAD
aeadChanged chan<- protocol.EncryptionLevel
}
// NewCryptoSetupTLS creates a new CryptoSetup instance for a server
func NewCryptoSetupTLS(
hostname string, // only needed for the client
perspective protocol.Perspective,
version protocol.VersionNumber,
tlsConfig *tls.Config,
cryptoStream io.ReadWriter,
aeadChanged chan<- protocol.EncryptionLevel,
) (CryptoSetup, error) {
mintConf, err := tlsToMintConfig(tlsConfig, perspective)
if err != nil {
return nil, err
}
mintConf.ServerName = hostname
var conn *mint.Conn
if perspective == protocol.PerspectiveServer {
conn = mint.Server(&fakeConn{cryptoStream}, mintConf)
} else {
conn = mint.Client(&fakeConn{cryptoStream}, mintConf)
}
return &cryptoSetupTLS{
perspective: perspective,
mintConf: mintConf,
conn: &mintController{conn},
nullAEAD: crypto.NewNullAEAD(perspective, version),
keyDerivation: crypto.DeriveAESKeys,
aeadChanged: aeadChanged,
}, nil
}
func (h *cryptoSetupTLS) HandleCryptoStream() error {
alert := h.conn.Handshake()
if alert != mint.AlertNoAlert {
return fmt.Errorf("TLS handshake error: %s (Alert %d)", alert.String(), alert)
}
aead, err := h.keyDerivation(h.conn, h.perspective)
if err != nil {
return err
}
h.mutex.Lock()
h.aead = aead
h.mutex.Unlock()
// signal to the outside world that the handshake completed
h.aeadChanged <- protocol.EncryptionForwardSecure
close(h.aeadChanged)
return nil
}
func (h *cryptoSetupTLS) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if h.aead != nil {
data, err := h.aead.Open(dst, src, packetNumber, associatedData)
if err != nil {
return nil, protocol.EncryptionUnspecified, err
}
return data, protocol.EncryptionForwardSecure, nil
}
data, err := h.nullAEAD.Open(dst, src, packetNumber, associatedData)
if err != nil {
return nil, protocol.EncryptionUnspecified, err
}
return data, protocol.EncryptionUnencrypted, nil
}
func (h *cryptoSetupTLS) GetSealer() (protocol.EncryptionLevel, Sealer) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if h.aead != nil {
return protocol.EncryptionForwardSecure, h.aead
}
return protocol.EncryptionUnencrypted, h.nullAEAD
}
func (h *cryptoSetupTLS) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) {
errNoSealer := fmt.Errorf("CryptoSetup: no sealer with encryption level %s", encLevel.String())
h.mutex.RLock()
defer h.mutex.RUnlock()
switch encLevel {
case protocol.EncryptionUnencrypted:
return h.nullAEAD, nil
case protocol.EncryptionForwardSecure:
if h.aead == nil {
return nil, errNoSealer
}
return h.aead, nil
default:
return nil, errNoSealer
}
}
func (h *cryptoSetupTLS) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
return protocol.EncryptionUnencrypted, h.nullAEAD
}
func (h *cryptoSetupTLS) DiversificationNonce() []byte {
panic("diversification nonce not needed for TLS")
}
func (h *cryptoSetupTLS) SetDiversificationNonce([]byte) {
panic("diversification nonce not needed for TLS")
}