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  }