Skip to content
This repository was archived by the owner on Jun 16, 2022. It is now read-only.

Commit 84f533e

Browse files
committed
Getting ready for DTLS 1.2
No connection downgrading supported right now
1 parent a6ebf8c commit 84f533e

5 files changed

Lines changed: 84 additions & 41 deletions

File tree

client_handshake_context.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (ch *clientHandshake) continueHandshake(message *handshake) (complete bool,
4040

4141
func (ch *clientHandshake) prepareFlightOne() {
4242
cltHello := handshakeClientHello{
43-
ClientVersion: DTLS_10,
43+
ClientVersion: ch.Conn.version,
4444
Random: ch.clientRandom,
4545
SessionID: ch.sessionID,
4646
Cookie: ch.cookie,
@@ -90,7 +90,7 @@ func (ch *clientHandshake) prepareFlightThree() {
9090
}
9191
ch.clientKeyExchange = ch.buildNextHandshakeMessage(clientKeyExchange, cltKeyExchange.Bytes())
9292
masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
93-
keysFromPreMasterSecret(preMasterSecret, ch.clientRandom.Bytes(), ch.serverRandom.Bytes(),
93+
keysFromPreMasterSecret(ch.Conn.version, preMasterSecret, ch.clientRandom.Bytes(), ch.serverRandom.Bytes(),
9494
cipherSuite.macLen, cipherSuite.keyLen)
9595
ch.masterSecret = masterSecret
9696
ch.Conn.pendingWriteState.Cipher = cipherSuite.cipher(clientKey)
@@ -106,7 +106,11 @@ func (ch *clientHandshake) prepareFlightThree() {
106106
ch.finishedHash.Write(ch.serverHelloDone.Bytes())
107107
ch.finishedHash.Write(ch.clientKeyExchange.Bytes())
108108
finishedMessage := new(handshakeFinished)
109-
finishedMessage.VerifyData = ch.finishedHash.clientSum(masterSecret)
109+
if ch.Conn.version == DTLS_10 {
110+
finishedMessage.VerifyData = ch.finishedHash.clientSum10(masterSecret)
111+
} else if ch.Conn.version == DTLS_12 {
112+
finishedMessage.VerifyData = ch.finishedHash.clientSum12(masterSecret)
113+
}
110114
ch.clientFinished = ch.buildNextHandshakeMessage(finished, finishedMessage.Bytes())
111115
}
112116

@@ -126,8 +130,13 @@ func (ch *clientHandshake) isFlightFourComplete() (bool, error) {
126130
return true, err
127131
}
128132
ch.finishedHash.Write(ch.clientFinished.Bytes())
129-
if !bytes.Equal(serverFinished.VerifyData, ch.finishedHash.serverSum(ch.masterSecret)) {
133+
if ch.Conn.version == DTLS_10 && !bytes.Equal(serverFinished.VerifyData, ch.finishedHash.serverSum10(ch.masterSecret)) {
134+
err = errors.New("Server sent incorrect verify data")
135+
} else if ch.Conn.version == DTLS_12 && !bytes.Equal(serverFinished.VerifyData, ch.finishedHash.serverSum12(ch.masterSecret)) {
130136
err = errors.New("Server sent incorrect verify data")
137+
} else if ch.Conn.version != DTLS_10 && ch.Conn.version != DTLS_12 {
138+
// TODO: This should never happen
139+
err = errors.New("Unsupported version ...")
131140
}
132141
return true, err
133142
}

conn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func NewConn(c net.Conn, server bool) net.Conn {
4040
log.Printf("Opening new DTLS conenction")
4141
dtlsConn := &Conn{
4242
Conn: c,
43-
version: DTLS_10,
43+
version: DTLS_12,
4444
}
4545
if server {
4646
dtlsConn.handshakeContext = &serverHandshake{baseHandshakeContext{Conn: dtlsConn, isServer: true, handshakeMessageBuffer: make(map[uint16]*handshakeFragmentList)}}

prf.go

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
package dtls
66

77
import (
8+
"bytes"
89
"crypto/hmac"
910
"crypto/md5"
1011
"crypto/sha1"
12+
"crypto/sha256"
1113
"hash"
1214
)
1315

@@ -62,6 +64,13 @@ func pRF10(result, secret, label, seed []byte) {
6264
}
6365
}
6466

67+
func pRF12(result, secret, label, seed []byte) {
68+
labelAndSeed := make([]byte, len(label)+len(seed))
69+
copy(labelAndSeed, label)
70+
copy(labelAndSeed[len(label):], seed)
71+
pHash(result, secret, labelAndSeed, sha256.New)
72+
}
73+
6574
const (
6675
tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
6776
masterSecretLength = 48 // Length of a master secret in TLS 1.1.
@@ -76,8 +85,11 @@ var serverFinishedLabel = []byte("server finished")
7685
// keysFromPreMasterSecret generates the connection keys from the pre master
7786
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
7887
// RFC 2246, section 6.3.
79-
func keysFromPreMasterSecret(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
88+
func keysFromPreMasterSecret(version protocolVersion, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
8089
prf := pRF10
90+
if version == DTLS_12 {
91+
prf = pRF12
92+
}
8193

8294
var seed [tlsRandomLength * 2]byte
8395
copy(seed[0:len(clientRandom)], clientRandom)
@@ -102,24 +114,13 @@ func keysFromPreMasterSecret(preMasterSecret, clientRandom, serverRandom []byte,
102114
}
103115

104116
func newFinishedHash() finishedHash {
105-
return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New()}
117+
return finishedHash{Buffer: bytes.Buffer{}}
106118
}
107119

108120
// A finishedHash calculates the hash of a set of handshake messages suitable
109121
// for including in a Finished message.
110122
type finishedHash struct {
111-
clientMD5 hash.Hash
112-
clientSHA1 hash.Hash
113-
serverMD5 hash.Hash
114-
serverSHA1 hash.Hash
115-
}
116-
117-
func (h finishedHash) Write(msg []byte) (n int, err error) {
118-
h.clientMD5.Write(msg)
119-
h.clientSHA1.Write(msg)
120-
h.serverMD5.Write(msg)
121-
h.serverSHA1.Write(msg)
122-
return len(msg), nil
123+
bytes.Buffer
123124
}
124125

125126
// finishedSum10 calculates the contents of the verify_data member of a TLSv1
@@ -134,18 +135,46 @@ func finishedSum10(md5, sha1, label, masterSecret []byte) []byte {
134135
return out
135136
}
136137

137-
// clientSum returns the contents of the verify_data member of a client's
138+
func finishedSum12(hash, label, masterSecret []byte) []byte {
139+
out := make([]byte, finishedVerifyLength)
140+
pRF12(out, masterSecret, label, hash)
141+
return out
142+
}
143+
144+
// clientSum10 returns the contents of the verify_data member of a client's
138145
// Finished message.
139-
func (h finishedHash) clientSum(masterSecret []byte) []byte {
140-
md5 := h.clientMD5.Sum(nil)
141-
sha1 := h.clientSHA1.Sum(nil)
142-
return finishedSum10(md5, sha1, clientFinishedLabel, masterSecret)
146+
func (h finishedHash) clientSum10(masterSecret []byte) []byte {
147+
md5 := md5.New()
148+
md5.Write(h.Bytes())
149+
md5Digest := md5.Sum(nil)
150+
sha1 := sha1.New()
151+
sha1.Write(h.Bytes())
152+
sha1Digest := sha1.Sum(nil)
153+
return finishedSum10(md5Digest, sha1Digest, clientFinishedLabel, masterSecret)
143154
}
144155

145-
// serverSum returns the contents of the verify_data member of a server's
156+
// serverSum10 returns the contents of the verify_data member of a server's
146157
// Finished message.
147-
func (h finishedHash) serverSum(masterSecret []byte) []byte {
148-
md5 := h.serverMD5.Sum(nil)
149-
sha1 := h.serverSHA1.Sum(nil)
150-
return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret)
158+
func (h finishedHash) serverSum10(masterSecret []byte) []byte {
159+
md5 := md5.New()
160+
md5.Write(h.Bytes())
161+
md5Digest := md5.Sum(nil)
162+
sha1 := sha1.New()
163+
sha1.Write(h.Bytes())
164+
sha1Digest := sha1.Sum(nil)
165+
return finishedSum10(md5Digest, sha1Digest, serverFinishedLabel, masterSecret)
166+
}
167+
168+
func (h finishedHash) clientSum12(masterSecret []byte) []byte {
169+
sha256 := sha256.New()
170+
sha256.Write(h.Bytes())
171+
sha256Digest := sha256.Sum(nil)
172+
return finishedSum12(sha256Digest, clientFinishedLabel, masterSecret)
173+
}
174+
175+
func (h finishedHash) serverSum12(masterSecret []byte) []byte {
176+
sha256 := sha256.New()
177+
sha256.Write(h.Bytes())
178+
sha256Digest := sha256.Sum(nil)
179+
return finishedSum12(sha256Digest, serverFinishedLabel, masterSecret)
151180
}

server_handshake_context.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func (sh *serverHandshake) prepareFlightTwo() error {
6868
sh.serverRandom = newRandom()
6969

7070
srvHello := handshakeServerHello{
71-
ServerVersion: DTLS_10,
71+
ServerVersion: sh.Conn.version,
7272
Random: sh.serverRandom,
7373
CipherSuite: cipherSuite,
7474
CompressionMethod: compressionMethod,
@@ -128,7 +128,7 @@ func (sh *serverHandshake) handleKeyExchange() error {
128128
return err
129129
}
130130
masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
131-
keysFromPreMasterSecret(preMasterSecret, sh.clientRandom.Bytes(), sh.serverRandom.Bytes(),
131+
keysFromPreMasterSecret(sh.Conn.version, preMasterSecret, sh.clientRandom.Bytes(), sh.serverRandom.Bytes(),
132132
sh.cipherSuite.macLen, sh.cipherSuite.keyLen)
133133
sh.masterSecret = masterSecret
134134
sh.Conn.pendingWriteState.Cipher = sh.cipherSuite.cipher(serverKey)
@@ -153,15 +153,21 @@ func (sh *serverHandshake) isFlightThreeComplete() (complete bool, err error) {
153153
sh.finishedHash.Write(sh.serverKeyExchange.Bytes())
154154
sh.finishedHash.Write(sh.serverHelloDone.Bytes())
155155
sh.finishedHash.Write(sh.clientKeyExchange.Bytes())
156-
if !bytes.Equal(clientFinished.VerifyData, sh.finishedHash.clientSum(sh.masterSecret)) {
157-
err = errors.New("Server sent incorrect verify data")
156+
if sh.Conn.version == DTLS_10 && !bytes.Equal(clientFinished.VerifyData, sh.finishedHash.clientSum10(sh.masterSecret)) {
157+
err = errors.New("Client sent incorrect verify data")
158+
} else if sh.Conn.version == DTLS_12 && !bytes.Equal(clientFinished.VerifyData, sh.finishedHash.clientSum12(sh.masterSecret)) {
159+
err = errors.New("Client sent incorrect verify data")
158160
}
159161
return true, err
160162
}
161163

162164
func (sh *serverHandshake) prepareFlightFour() {
163165
sh.finishedHash.Write(sh.clientFinished.Bytes())
164-
serverFinished := &handshakeFinished{VerifyData: sh.finishedHash.serverSum(sh.masterSecret)}
166+
if sh.Conn.version == DTLS_10 {
167+
serverFinished := &handshakeFinished{VerifyData: sh.finishedHash.serverSum10(sh.masterSecret)}
168+
} else if sh.Conn.version == DTLS_12 {
169+
serverFinished := &handshakeFinished{VerifyData: sh.finishedHash.serverSum12(sh.masterSecret)}
170+
}
165171
sh.serverFinished = sh.buildNextHandshakeMessage(finished, serverFinished.Bytes())
166172
}
167173

testclient/testclient.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,20 @@ import (
88
)
99

1010
func main() {
11-
laddr, err := net.ResolveUDPAddr("udp", "[fe80::1cce:99ff:fe67:3645%client0]:5556")
12-
if err != nil {
13-
log.Fatalf("Unable to resolve local address: %s\n", err)
14-
}
15-
raddr, err := net.ResolveUDPAddr("udp", "[fe80::8471:57ff:fe48:9ee2%client0]:5556")
11+
raddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5556")
1612
if err != nil {
1713
log.Fatalf("Unable to resolve remote address: %v\n", err)
1814
}
19-
conn, err := net.DialUDP("udp", laddr, raddr)
15+
conn, err := net.DialUDP("udp", nil, raddr)
2016
if err != nil {
2117
log.Fatalf("Unable to connect to remote addr: %v\n", err)
2218
}
2319
dtlsConn := dtls.NewConn(conn, false)
2420
for {
25-
dtlsConn.Write([]byte("Hello World"))
21+
_, err := dtlsConn.Write([]byte("Hello World"))
22+
if err != nil {
23+
log.Fatalf("Error while writing hello world: %s:", err)
24+
}
2625
buffer := make([]byte, dtls.UDP_MAX_SIZE)
2726
n, err := dtlsConn.Read(buffer)
2827
if err != nil {

0 commit comments

Comments
 (0)