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
|
package handshake
import (
"encoding/binary"
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
"github.com/pion/dtls/v2/pkg/crypto/hash"
"github.com/pion/dtls/v2/pkg/crypto/signature"
)
// MessageServerKeyExchange supports ECDH and PSK
type MessageServerKeyExchange struct {
IdentityHint []byte
EllipticCurveType elliptic.CurveType
NamedCurve elliptic.Curve
PublicKey []byte
HashAlgorithm hash.Algorithm
SignatureAlgorithm signature.Algorithm
Signature []byte
}
// Type returns the Handshake Type
func (m MessageServerKeyExchange) Type() Type {
return TypeServerKeyExchange
}
// Marshal encodes the Handshake
func (m *MessageServerKeyExchange) Marshal() ([]byte, error) {
if m.IdentityHint != nil {
out := append([]byte{0x00, 0x00}, m.IdentityHint...)
binary.BigEndian.PutUint16(out, uint16(len(out)-2))
return out, nil
}
out := []byte{byte(m.EllipticCurveType), 0x00, 0x00}
binary.BigEndian.PutUint16(out[1:], uint16(m.NamedCurve))
out = append(out, byte(len(m.PublicKey)))
out = append(out, m.PublicKey...)
if m.HashAlgorithm == hash.None && m.SignatureAlgorithm == signature.Anonymous && len(m.Signature) == 0 {
return out, nil
}
out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...)
binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature)))
out = append(out, m.Signature...)
return out, nil
}
// Unmarshal populates the message from encoded data
func (m *MessageServerKeyExchange) Unmarshal(data []byte) error {
if len(data) < 2 {
return errBufferTooSmall
}
// If parsed as PSK return early and only populate PSK Identity Hint
if pskLength := binary.BigEndian.Uint16(data); len(data) == int(pskLength+2) {
m.IdentityHint = append([]byte{}, data[2:]...)
return nil
}
if _, ok := elliptic.CurveTypes()[elliptic.CurveType(data[0])]; ok {
m.EllipticCurveType = elliptic.CurveType(data[0])
} else {
return errInvalidEllipticCurveType
}
if len(data[1:]) < 2 {
return errBufferTooSmall
}
m.NamedCurve = elliptic.Curve(binary.BigEndian.Uint16(data[1:3]))
if _, ok := elliptic.Curves()[m.NamedCurve]; !ok {
return errInvalidNamedCurve
}
if len(data) < 4 {
return errBufferTooSmall
}
publicKeyLength := int(data[3])
offset := 4 + publicKeyLength
if len(data) < offset {
return errBufferTooSmall
}
m.PublicKey = append([]byte{}, data[4:offset]...)
// Anon connection doesn't contains hashAlgorithm, signatureAlgorithm, signature
if len(data) == offset {
return nil
} else if len(data) <= offset {
return errBufferTooSmall
}
m.HashAlgorithm = hash.Algorithm(data[offset])
if _, ok := hash.Algorithms()[m.HashAlgorithm]; !ok {
return errInvalidHashAlgorithm
}
offset++
if len(data) <= offset {
return errBufferTooSmall
}
m.SignatureAlgorithm = signature.Algorithm(data[offset])
if _, ok := signature.Algorithms()[m.SignatureAlgorithm]; !ok {
return errInvalidSignatureAlgorithm
}
offset++
if len(data) < offset+2 {
return errBufferTooSmall
}
signatureLength := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2
if len(data) < offset+signatureLength {
return errBufferTooSmall
}
m.Signature = append([]byte{}, data[offset:offset+signatureLength]...)
return nil
}
|