This repository has been archived by the owner on Jun 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
client_hello.go
100 lines (91 loc) · 2.65 KB
/
client_hello.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
package dtls
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
)
type handshakeClientHello struct {
ClientVersion protocolVersion
Random random
SessionID []byte
Cookie []byte
CipherSuites []*cipherSuite
CompressionMethods []compressionMethod
Extensions []extension
}
func readHandshakeClientHello(data []byte) (clientHello handshakeClientHello, err error) {
buffer := bytes.NewBuffer(data)
if clientHello.ClientVersion, err = readProtocolVersion(buffer); err != nil {
return
}
if clientHello.Random, err = readRandom(buffer); err != nil {
return
}
sessionIDLength, err := buffer.ReadByte()
if err != nil {
return
}
if int(sessionIDLength) > buffer.Len() {
err = errors.New("Insufficient data to read session ID")
return
}
clientHello.SessionID = buffer.Next(int(sessionIDLength))
cookieLength, err := buffer.ReadByte()
if err != nil {
return
}
if int(cookieLength) > buffer.Len() {
err = errors.New("Insufficient data to read cookie")
return
}
clientHello.Cookie = buffer.Next(int(cookieLength))
numCipherSuites := int(readUint16(buffer)) / 2
for i := 0; i < numCipherSuites; i++ {
cipherSuite, err := readCipherSuite(buffer)
if err != nil {
return clientHello, err
}
clientHello.CipherSuites = append(clientHello.CipherSuites, cipherSuite)
}
numCompressionMethods, err := buffer.ReadByte()
if err != nil {
return
}
for i := 0; i < int(numCompressionMethods); i++ {
compressionMethod, err := readCompressionMethod(buffer)
if err != nil {
return clientHello, err
}
clientHello.CompressionMethods = append(clientHello.CompressionMethods, compressionMethod)
}
//TODO: Extensions
return
}
func (ch handshakeClientHello) String() string {
return fmt.Sprintf("ClientHello{ ClientVersion: %s, Random: %s, SessionID: %x, Cookie: %x }", ch.ClientVersion, ch.Random, ch.SessionID, ch.Cookie)
}
func (ch handshakeClientHello) Bytes() []byte {
buffer := bytes.Buffer{}
buffer.Write(ch.ClientVersion.Bytes())
buffer.Write(ch.Random.Bytes())
buffer.Write([]byte{byte(len(ch.SessionID))})
buffer.Write(ch.SessionID)
buffer.Write([]byte{byte(len(ch.Cookie))})
buffer.Write(ch.Cookie)
cipherSuiteLength := len(ch.CipherSuites) * 2
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, uint16(cipherSuiteLength))
buffer.Write(b)
for _, cipherSuite := range ch.CipherSuites {
buffer.Write(cipherSuite.Bytes())
}
buffer.Write([]byte{byte(len(ch.CompressionMethods))})
for _, compressionMethods := range ch.CompressionMethods {
buffer.Write(compressionMethods.Bytes())
}
for _, extension := range ch.Extensions {
buffer.Write(extension.Bytes())
}
return buffer.Bytes()
}