github.com/pion/dtls/v2@v2.2.12/pkg/protocol/extension/supported_signature_algorithms.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package extension 5 6 import ( 7 "encoding/binary" 8 9 "github.com/pion/dtls/v2/pkg/crypto/hash" 10 "github.com/pion/dtls/v2/pkg/crypto/signature" 11 "github.com/pion/dtls/v2/pkg/crypto/signaturehash" 12 ) 13 14 const ( 15 supportedSignatureAlgorithmsHeaderSize = 6 16 ) 17 18 // SupportedSignatureAlgorithms allows a Client/Server to 19 // negotiate what SignatureHash Algorithms they both support 20 // 21 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 22 type SupportedSignatureAlgorithms struct { 23 SignatureHashAlgorithms []signaturehash.Algorithm 24 } 25 26 // TypeValue returns the extension TypeValue 27 func (s SupportedSignatureAlgorithms) TypeValue() TypeValue { 28 return SupportedSignatureAlgorithmsTypeValue 29 } 30 31 // Marshal encodes the extension 32 func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) { 33 out := make([]byte, supportedSignatureAlgorithmsHeaderSize) 34 35 binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) 36 binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2))) 37 binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2)) 38 for _, v := range s.SignatureHashAlgorithms { 39 out = append(out, []byte{0x00, 0x00}...) 40 out[len(out)-2] = byte(v.Hash) 41 out[len(out)-1] = byte(v.Signature) 42 } 43 44 return out, nil 45 } 46 47 // Unmarshal populates the extension from encoded data 48 func (s *SupportedSignatureAlgorithms) Unmarshal(data []byte) error { 49 if len(data) <= supportedSignatureAlgorithmsHeaderSize { 50 return errBufferTooSmall 51 } else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() { 52 return errInvalidExtensionType 53 } 54 55 algorithmCount := int(binary.BigEndian.Uint16(data[4:]) / 2) 56 if supportedSignatureAlgorithmsHeaderSize+(algorithmCount*2) > len(data) { 57 return errLengthMismatch 58 } 59 for i := 0; i < algorithmCount; i++ { 60 supportedHashAlgorithm := hash.Algorithm(data[supportedSignatureAlgorithmsHeaderSize+(i*2)]) 61 supportedSignatureAlgorithm := signature.Algorithm(data[supportedSignatureAlgorithmsHeaderSize+(i*2)+1]) 62 if _, ok := hash.Algorithms()[supportedHashAlgorithm]; ok { 63 if _, ok := signature.Algorithms()[supportedSignatureAlgorithm]; ok { 64 s.SignatureHashAlgorithms = append(s.SignatureHashAlgorithms, signaturehash.Algorithm{ 65 Hash: supportedHashAlgorithm, 66 Signature: supportedSignatureAlgorithm, 67 }) 68 } 69 } 70 } 71 72 return nil 73 }