-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandshake.go
136 lines (121 loc) · 4.24 KB
/
handshake.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
package dtls
// https://tools.ietf.org/html/rfc5246#section-7.4
type handshakeType uint8
const (
handshakeTypeHelloRequest handshakeType = 0
handshakeTypeClientHello handshakeType = 1
handshakeTypeServerHello handshakeType = 2
handshakeTypeHelloVerifyRequest handshakeType = 3
handshakeTypeCertificate handshakeType = 11
handshakeTypeServerKeyExchange handshakeType = 12
handshakeTypeCertificateRequest handshakeType = 13
handshakeTypeServerHelloDone handshakeType = 14
handshakeTypeCertificateVerify handshakeType = 15
handshakeTypeClientKeyExchange handshakeType = 16
handshakeTypeFinished handshakeType = 20
// msg_len for Handshake messages assumes an extra 12 bytes for
// sequence, fragment and version information
handshakeMessageHeaderLength = 12
)
type handshakeMessage interface {
Marshal() ([]byte, error)
Unmarshal(data []byte) error
handshakeType() handshakeType
}
func (h handshakeType) String() string {
switch h {
case handshakeTypeHelloRequest:
return "HelloRequest"
case handshakeTypeClientHello:
return "ClientHello"
case handshakeTypeServerHello:
return "ServerHello"
case handshakeTypeHelloVerifyRequest:
return "HelloVerifyRequest"
case handshakeTypeCertificate:
return "TypeCertificate"
case handshakeTypeServerKeyExchange:
return "ServerKeyExchange"
case handshakeTypeCertificateRequest:
return "CertificateRequest"
case handshakeTypeServerHelloDone:
return "ServerHelloDone"
case handshakeTypeCertificateVerify:
return "CertificateVerify"
case handshakeTypeClientKeyExchange:
return "ClientKeyExchange"
case handshakeTypeFinished:
return "Finished"
}
return ""
}
// The handshake protocol is responsible for selecting a cipher spec and
// generating a master secret, which together comprise the primary
// cryptographic parameters associated with a secure session. The
// handshake protocol can also optionally authenticate parties who have
// certificates signed by a trusted certificate authority.
// https://tools.ietf.org/html/rfc5246#section-7.3
type handshake struct {
handshakeHeader handshakeHeader
handshakeMessage handshakeMessage
}
func (h handshake) contentType() contentType {
return contentTypeHandshake
}
func (h *handshake) Marshal() ([]byte, error) {
if h.handshakeMessage == nil {
return nil, errHandshakeMessageUnset
} else if h.handshakeHeader.fragmentOffset != 0 {
return nil, errUnableToMarshalFragmented
}
msg, err := h.handshakeMessage.Marshal()
if err != nil {
return nil, err
}
h.handshakeHeader.length = uint32(len(msg))
h.handshakeHeader.fragmentLength = h.handshakeHeader.length
h.handshakeHeader.handshakeType = h.handshakeMessage.handshakeType()
header, err := h.handshakeHeader.Marshal()
if err != nil {
return nil, err
}
return append(header, msg...), nil
}
func (h *handshake) Unmarshal(data []byte) error {
if err := h.handshakeHeader.Unmarshal(data); err != nil {
return err
}
reportedLen := bigEndianUint24(data[1:])
if uint32(len(data)-handshakeMessageHeaderLength) != reportedLen {
return errLengthMismatch
} else if reportedLen != h.handshakeHeader.fragmentLength {
return errLengthMismatch
}
switch handshakeType(data[0]) {
case handshakeTypeHelloRequest:
return errNotImplemented
case handshakeTypeClientHello:
h.handshakeMessage = &handshakeMessageClientHello{}
case handshakeTypeHelloVerifyRequest:
h.handshakeMessage = &handshakeMessageHelloVerifyRequest{}
case handshakeTypeServerHello:
h.handshakeMessage = &handshakeMessageServerHello{}
case handshakeTypeCertificate:
h.handshakeMessage = &handshakeMessageCertificate{}
case handshakeTypeServerKeyExchange:
h.handshakeMessage = &handshakeMessageServerKeyExchange{}
case handshakeTypeCertificateRequest:
h.handshakeMessage = &handshakeMessageCertificateRequest{}
case handshakeTypeServerHelloDone:
h.handshakeMessage = &handshakeMessageServerHelloDone{}
case handshakeTypeClientKeyExchange:
h.handshakeMessage = &handshakeMessageClientKeyExchange{}
case handshakeTypeFinished:
h.handshakeMessage = &handshakeMessageFinished{}
case handshakeTypeCertificateVerify:
h.handshakeMessage = &handshakeMessageCertificateVerify{}
default:
return errNotImplemented
}
return h.handshakeMessage.Unmarshal(data[handshakeMessageHeaderLength:])
}