forked from cisco/go-mls
/
extensions.go
125 lines (98 loc) · 2.5 KB
/
extensions.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
package mls
import (
"fmt"
syntax "github.com/cisco/go-tls-syntax"
)
type ExtensionType uint16
const (
ExtensionTypeInvalid ExtensionType = 0x0000
ExtensionTypeSupportedVersions ExtensionType = 0x0001
ExtensionTypeSupportedCipherSuites ExtensionType = 0x0002
ExtensionTypeLifetime ExtensionType = 0x0003
ExtensionTypeKeyID ExtensionType = 0x0004
ExtensionTypeParentHash ExtensionType = 0x0005
)
type ExtensionBody interface {
Type() ExtensionType
}
type Extension struct {
ExtensionType ExtensionType
ExtensionData []byte `tls:"head=2"`
}
type ExtensionList struct {
Entries []Extension `tls:"head=2"`
}
func NewExtensionList() ExtensionList {
return ExtensionList{[]Extension{}}
}
func (el *ExtensionList) Add(src ExtensionBody) error {
data, err := syntax.Marshal(src)
if err != nil {
return err
}
// If one already exists with this type, replace it
for i := range el.Entries {
if el.Entries[i].ExtensionType == src.Type() {
el.Entries[i].ExtensionData = data
return nil
}
}
// Otherwise append
el.Entries = append(el.Entries, Extension{
ExtensionType: src.Type(),
ExtensionData: data,
})
return nil
}
func (el ExtensionList) Has(extType ExtensionType) bool {
for _, ext := range el.Entries {
if ext.ExtensionType == extType {
return true
}
}
return false
}
func (el ExtensionList) Find(dst ExtensionBody) (bool, error) {
for _, ext := range el.Entries {
if ext.ExtensionType == dst.Type() {
read, err := syntax.Unmarshal(ext.ExtensionData, dst)
if err != nil {
return true, err
}
if read != len(ext.ExtensionData) {
return true, fmt.Errorf("Extension failed to consume all data")
}
return true, nil
}
}
return false, nil
}
//////////
type SupportedVersionsExtension struct {
SupportedVersions []ProtocolVersion `tls:"head=1"`
}
func (sve SupportedVersionsExtension) Type() ExtensionType {
return ExtensionTypeSupportedVersions
}
//////////
type SupportedCipherSuitesExtension struct {
SupportedCipherSuites []CipherSuite `tls:"head=1"`
}
func (sce SupportedCipherSuitesExtension) Type() ExtensionType {
return ExtensionTypeSupportedCipherSuites
}
//////////
type LifetimeExtension struct {
NotBefore uint64
NotAfter uint64
}
func (lte LifetimeExtension) Type() ExtensionType {
return ExtensionTypeLifetime
}
//////////
type ParentHashExtension struct {
ParentHash []byte `tls:"head=1"`
}
func (phe ParentHashExtension) Type() ExtensionType {
return ExtensionTypeParentHash
}