mirror of https://github.com/bjdgyc/anylink.git
97 lines
2.7 KiB
Go
97 lines
2.7 KiB
Go
// Package extension implements the extension values in the ClientHello/ServerHello
|
|
package extension
|
|
|
|
import "encoding/binary"
|
|
|
|
// TypeValue is the 2 byte value for a TLS Extension as registered in the IANA
|
|
//
|
|
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
|
|
type TypeValue uint16
|
|
|
|
// TypeValue constants
|
|
const (
|
|
ServerNameTypeValue TypeValue = 0
|
|
SupportedEllipticCurvesTypeValue TypeValue = 10
|
|
SupportedPointFormatsTypeValue TypeValue = 11
|
|
SupportedSignatureAlgorithmsTypeValue TypeValue = 13
|
|
UseSRTPTypeValue TypeValue = 14
|
|
UseExtendedMasterSecretTypeValue TypeValue = 23
|
|
RenegotiationInfoTypeValue TypeValue = 65281
|
|
)
|
|
|
|
// Extension represents a single TLS extension
|
|
type Extension interface {
|
|
Marshal() ([]byte, error)
|
|
Unmarshal(data []byte) error
|
|
TypeValue() TypeValue
|
|
}
|
|
|
|
// Unmarshal many extensions at once
|
|
func Unmarshal(buf []byte) ([]Extension, error) {
|
|
switch {
|
|
case len(buf) == 0:
|
|
return []Extension{}, nil
|
|
case len(buf) < 2:
|
|
return nil, errBufferTooSmall
|
|
}
|
|
|
|
declaredLen := binary.BigEndian.Uint16(buf)
|
|
if len(buf)-2 != int(declaredLen) {
|
|
return nil, errLengthMismatch
|
|
}
|
|
|
|
extensions := []Extension{}
|
|
unmarshalAndAppend := func(data []byte, e Extension) error {
|
|
err := e.Unmarshal(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
extensions = append(extensions, e)
|
|
return nil
|
|
}
|
|
|
|
for offset := 2; offset < len(buf); {
|
|
if len(buf) < (offset + 2) {
|
|
return nil, errBufferTooSmall
|
|
}
|
|
var err error
|
|
switch TypeValue(binary.BigEndian.Uint16(buf[offset:])) {
|
|
case ServerNameTypeValue:
|
|
err = unmarshalAndAppend(buf[offset:], &ServerName{})
|
|
case SupportedEllipticCurvesTypeValue:
|
|
err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{})
|
|
case UseSRTPTypeValue:
|
|
err = unmarshalAndAppend(buf[offset:], &UseSRTP{})
|
|
case UseExtendedMasterSecretTypeValue:
|
|
err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{})
|
|
case RenegotiationInfoTypeValue:
|
|
err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{})
|
|
default:
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(buf) < (offset + 4) {
|
|
return nil, errBufferTooSmall
|
|
}
|
|
extensionLength := binary.BigEndian.Uint16(buf[offset+2:])
|
|
offset += (4 + int(extensionLength))
|
|
}
|
|
return extensions, nil
|
|
}
|
|
|
|
// Marshal many extensions at once
|
|
func Marshal(e []Extension) ([]byte, error) {
|
|
extensions := []byte{}
|
|
for _, e := range e {
|
|
raw, err := e.Marshal()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
extensions = append(extensions, raw...)
|
|
}
|
|
out := []byte{0x00, 0x00}
|
|
binary.BigEndian.PutUint16(out, uint16(len(extensions)))
|
|
return append(out, extensions...), nil
|
|
}
|