@@ -2,6 +2,7 @@ package layers
22
33import (
44 "encoding/binary"
5+ "encoding/hex"
56 "fmt"
67 "strings"
78)
@@ -12,22 +13,29 @@ const (
1213 ClientHelloTLSVal = 0x01
1314)
1415
16+ type TLSVersion struct {
17+ Value uint16
18+ Desc string
19+ }
20+
21+ func (tv * TLSVersion ) String () string {
22+ return fmt .Sprintf ("%s (%#04x)" , tv .Desc , tv .Value )
23+ }
24+
1525type Record struct {
1626 ContentType uint8
1727 ContentTypeDesc string
18- Version uint16
19- VersionDesc string
28+ Version * TLSVersion
2029 Length uint16
2130 Data []byte
2231}
2332
2433func (r * Record ) String () string {
2534 return fmt .Sprintf (` - Content Type: %s (%d)
26- - Version: %s (%#04x)
35+ - Version: %s
2736 - Length: %d` ,
2837 r .ContentTypeDesc ,
2938 r .ContentType ,
30- r .VersionDesc ,
3139 r .Version ,
3240 r .Length )
3341}
@@ -40,6 +48,8 @@ func HSTLSParserByType(hstype uint8) HSTLSParser {
4048 switch hstype {
4149 case 1 :
4250 return & TLSClientHello {}
51+ case 2 :
52+ return & TLSServerHello {}
4353 }
4454 return nil
4555}
@@ -53,13 +63,22 @@ func (cs *CipherSuite) String() string {
5363 return fmt .Sprintf ("%s (%#x)" , cs .Desc , cs .Value )
5464}
5565
66+ type Extension struct {
67+ Value uint16
68+ Desc string
69+ }
70+
71+ func (e * Extension ) String () string {
72+ return fmt .Sprintf ("%s (%d)" , e .Desc , e .Value )
73+ }
74+
5675type ServerName struct {
5776 Type uint16
5877 Length uint16
5978 SNListLength uint16
6079 SNType uint8
6180 SNNameLength uint16
62- SNName [] byte
81+ SNName string
6382}
6483
6584func (sn * ServerName ) Parse (data []byte ) error {
@@ -68,24 +87,25 @@ func (sn *ServerName) Parse(data []byte) error {
6887 sn .SNListLength = binary .BigEndian .Uint16 (data [4 :6 ])
6988 sn .SNType = data [6 ]
7089 sn .SNNameLength = binary .BigEndian .Uint16 (data [7 :9 ])
71- sn .SNName = data [9 : 9 + sn .SNNameLength ]
90+ sn .SNName = string ( data [9 : 9 + sn .SNNameLength ])
7291 return nil
7392}
7493
7594// https://wiki.osdev.org/TLS_Handshake#Client_Hello_Message
7695type TLSClientHello struct {
7796 Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
78- Version uint16
79- VersionDesc string
97+ Version * TLSVersion
8098 Random []byte //32 bytes
8199 SessionIDLength uint8 // if 0 no session follows
82- SessionID [] byte
100+ SessionID string
83101 CipherSuitesLength uint16
84102 CipherSuites []* CipherSuite
85103 CmprMethodsLength uint8 // usually 0x01
86104 CmprMethods []byte // usually 0x00
87105 ExtensionLength uint16
106+ Extensions []* Extension
88107 ServerName * ServerName
108+ ALPN []string
89109}
90110
91111func (tch * TLSClientHello ) ParseHS (data []byte ) error {
@@ -97,12 +117,12 @@ func (tch *TLSClientHello) ParseHS(data []byte) error {
97117 if len (data )- 4 < tch .Length {
98118 return fmt .Errorf ("message should be at least %d bytes, got %d bytes" , tch .Length , len (data )- 4 )
99119 }
100- tch . Version = binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
101- tch .VersionDesc = verdesc (tch . Version )
120+ ver : = binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
121+ tch .Version = & TLSVersion { Value : ver , Desc : verdesc (ver )}
102122 tch .Random = data [6 :38 ] // 11-42 data[6:38]
103123 tch .SessionIDLength = data [38 ] // 43 data[38] 32 bytes
104124 sid := tch .SessionIDLength + 39 // 70
105- tch .SessionID = data [39 :sid ] // data[39:71]
125+ tch .SessionID = hex . EncodeToString ( data [39 :sid ]) // data[39:71]
106126 csl := binary .BigEndian .Uint16 (data [sid : sid + 2 ]) // data[71:73] suites count * 2 bytes
107127 tch .CipherSuitesLength = csl
108128 offset := uint16 (sid + 2 ) //73
@@ -123,36 +143,88 @@ func (tch *TLSClientHello) ParseHS(data []byte) error {
123143 extlen := binary .BigEndian .Uint16 (data [extoffset : extoffset + 2 ]) // data[109:111]
124144 tch .ExtensionLength = extlen
125145 i = extoffset + 2
146+ exts := make ([]* Extension , 0 , 20 )
126147 for i < extoffset + extlen {
127148 typ := binary .BigEndian .Uint16 (data [i : i + 2 ])
128149 length := binary .BigEndian .Uint16 (data [i + 2 : i + 4 ])
150+ exts = append (exts , & Extension {Value : typ , Desc : extdesc (typ )})
129151 switch typ {
130- case 0 : // TODO: add more extensions
152+ case 0 : // SNI
131153 sn := & ServerName {}
132154 err := sn .Parse (data [i : i + length + 4 ])
133155 if err != nil {
134156 return err
135157 }
136158 tch .ServerName = sn
137- i += length + 4
138- default :
139- i += length + 4
159+ case 16 : //ALPN
160+ //skip data[i+4:i+6] alpn extension length
161+ start := i + 6
162+ alpns := make ([]string , 0 , 5 )
163+ for start < i + length + 4 {
164+ alpnStringLength := data [start ]
165+ nextProto := string (data [start + 1 : start + uint16 (alpnStringLength + 1 )])
166+ alpns = append (alpns , nextProto )
167+ start += uint16 (alpnStringLength + 1 )
168+ }
169+ tch .ALPN = alpns
140170 }
171+ i += length + 4
141172 }
173+ tch .Extensions = exts
142174 return nil
143175}
144176
145177// https://wiki.osdev.org/TLS_Handshake#Server_Hello_Message
146178type TLSServerHello struct {
147- Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
148- Version uint16
149- VersionDesc string
150- Random []byte //32 bytes
151- SessionIDLength uint8 // if 0 no session follows
152- SessionID []byte
153- CipherSuite * CipherSuite
154- CmprMethod uint8
155- ExtensionLength uint16
179+ Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
180+ Version * TLSVersion
181+ Random []byte //32 bytes
182+ SessionIDLength uint8 // if 0 no session follows
183+ SessionID string
184+ CipherSuite * CipherSuite
185+ CmprMethod uint8
186+ ExtensionLength uint16
187+ Extensions []* Extension
188+ SupportedVersion * TLSVersion
189+ }
190+
191+ func (tsh * TLSServerHello ) ParseHS (data []byte ) error {
192+ // offset 7 bytes
193+ if len (data ) < 4 {
194+ return fmt .Errorf ("message should be at least 4 bytes, got %d bytes" , len (data ))
195+ }
196+ tsh .Length = int (uint (data [3 ]) | uint (data [2 ])<< 8 | uint (data [1 ])<< 16 ) // 6 - 8 bytes data[1:4]
197+ if len (data )- 4 < tsh .Length {
198+ return fmt .Errorf ("message should be at least %d bytes, got %d bytes" , tsh .Length , len (data )- 4 )
199+ }
200+ ver := binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
201+ tsh .Version = & TLSVersion {Value : ver , Desc : verdesc (ver )}
202+ tsh .Random = data [6 :38 ] // 11-42 data[6:38]
203+ tsh .SessionIDLength = data [38 ] // 43 data[38] 32 bytes
204+ sid := tsh .SessionIDLength + 39 // 70
205+ tsh .SessionID = hex .EncodeToString (data [39 :sid ]) // data[39:71]
206+ val := binary .BigEndian .Uint16 (data [sid : sid + 2 ])
207+ valdesc := csuitedesc (val )
208+ tsh .CipherSuite = & CipherSuite {Value : val , Desc : valdesc }
209+ tsh .CmprMethod = data [sid + 2 ]
210+ extoffset := uint16 (sid + 3 )
211+ extlen := binary .BigEndian .Uint16 (data [extoffset : extoffset + 2 ])
212+ tsh .ExtensionLength = extlen
213+ exts := make ([]* Extension , 0 , 20 )
214+ i := extoffset + 2
215+ for i < extoffset + extlen {
216+ typ := binary .BigEndian .Uint16 (data [i : i + 2 ])
217+ length := binary .BigEndian .Uint16 (data [i + 2 : i + 4 ])
218+ exts = append (exts , & Extension {Value : typ , Desc : extdesc (typ )})
219+ switch typ {
220+ case 43 : // supported versions
221+ ver := binary .BigEndian .Uint16 (data [i + 4 : i + 6 ])
222+ tsh .SupportedVersion = & TLSVersion {Value : ver , Desc : verdesc (ver )}
223+ }
224+ i += length + 4
225+ }
226+ tsh .Extensions = exts
227+ return nil
156228}
157229
158230// port 443
@@ -181,7 +253,7 @@ func (t *TLSMessage) Summary() string {
181253 sb .WriteString (fmt .Sprintf ("%s (%d) Len: %d " , rec .ContentTypeDesc , rec .ContentType , rec .Length ))
182254 continue
183255 }
184- sb .WriteString (fmt . Sprintf ( "%s (%#04x) " , rec .VersionDesc , rec . Version ))
256+ sb .WriteString (rec .Version . String ( ))
185257 if rec .ContentType == 22 {
186258 hstd := hstypedesc (rec .Data [0 ])
187259 sb .WriteString (fmt .Sprintf ("%s " , hstd ))
@@ -230,8 +302,7 @@ func (t *TLSMessage) Parse(data []byte) error {
230302 r := & Record {
231303 ContentType : ctype ,
232304 ContentTypeDesc : ctdesc ,
233- Version : ver ,
234- VersionDesc : verdesc ,
305+ Version : & TLSVersion {Value : ver , Desc : verdesc },
235306 Length : rlen ,
236307 Data : data [headerSizeTLS : headerSizeTLS + rlen ],
237308 }
0 commit comments