github.com/pion/dtls/v2@v2.2.12/pkg/protocol/extension/extension.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package extension implements the extension values in the ClientHello/ServerHello 5 package extension 6 7 import "encoding/binary" 8 9 // TypeValue is the 2 byte value for a TLS Extension as registered in the IANA 10 // 11 // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml 12 type TypeValue uint16 13 14 // TypeValue constants 15 const ( 16 ServerNameTypeValue TypeValue = 0 17 SupportedEllipticCurvesTypeValue TypeValue = 10 18 SupportedPointFormatsTypeValue TypeValue = 11 19 SupportedSignatureAlgorithmsTypeValue TypeValue = 13 20 UseSRTPTypeValue TypeValue = 14 21 ALPNTypeValue TypeValue = 16 22 UseExtendedMasterSecretTypeValue TypeValue = 23 23 RenegotiationInfoTypeValue TypeValue = 65281 24 ) 25 26 // Extension represents a single TLS extension 27 type Extension interface { 28 Marshal() ([]byte, error) 29 Unmarshal(data []byte) error 30 TypeValue() TypeValue 31 } 32 33 // Unmarshal many extensions at once 34 func Unmarshal(buf []byte) ([]Extension, error) { 35 switch { 36 case len(buf) == 0: 37 return []Extension{}, nil 38 case len(buf) < 2: 39 return nil, errBufferTooSmall 40 } 41 42 declaredLen := binary.BigEndian.Uint16(buf) 43 if len(buf)-2 != int(declaredLen) { 44 return nil, errLengthMismatch 45 } 46 47 extensions := []Extension{} 48 unmarshalAndAppend := func(data []byte, e Extension) error { 49 err := e.Unmarshal(data) 50 if err != nil { 51 return err 52 } 53 extensions = append(extensions, e) 54 return nil 55 } 56 57 for offset := 2; offset < len(buf); { 58 if len(buf) < (offset + 2) { 59 return nil, errBufferTooSmall 60 } 61 var err error 62 switch TypeValue(binary.BigEndian.Uint16(buf[offset:])) { 63 case ServerNameTypeValue: 64 err = unmarshalAndAppend(buf[offset:], &ServerName{}) 65 case SupportedEllipticCurvesTypeValue: 66 err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{}) 67 case UseSRTPTypeValue: 68 err = unmarshalAndAppend(buf[offset:], &UseSRTP{}) 69 case ALPNTypeValue: 70 err = unmarshalAndAppend(buf[offset:], &ALPN{}) 71 case UseExtendedMasterSecretTypeValue: 72 err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{}) 73 case RenegotiationInfoTypeValue: 74 err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{}) 75 default: 76 } 77 if err != nil { 78 return nil, err 79 } 80 if len(buf) < (offset + 4) { 81 return nil, errBufferTooSmall 82 } 83 extensionLength := binary.BigEndian.Uint16(buf[offset+2:]) 84 offset += (4 + int(extensionLength)) 85 } 86 return extensions, nil 87 } 88 89 // Marshal many extensions at once 90 func Marshal(e []Extension) ([]byte, error) { 91 extensions := []byte{} 92 for _, e := range e { 93 raw, err := e.Marshal() 94 if err != nil { 95 return nil, err 96 } 97 extensions = append(extensions, raw...) 98 } 99 out := []byte{0x00, 0x00} 100 binary.BigEndian.PutUint16(out, uint16(len(extensions))) 101 return append(out, extensions...), nil 102 }