github.com/pion/dtls/v2@v2.2.12/pkg/protocol/extension/supported_elliptic_curves.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/elliptic"
    10  )
    11  
    12  const (
    13  	supportedGroupsHeaderSize = 6
    14  )
    15  
    16  // SupportedEllipticCurves allows a Client/Server to communicate
    17  // what curves they both support
    18  //
    19  // https://tools.ietf.org/html/rfc8422#section-5.1.1
    20  type SupportedEllipticCurves struct {
    21  	EllipticCurves []elliptic.Curve
    22  }
    23  
    24  // TypeValue returns the extension TypeValue
    25  func (s SupportedEllipticCurves) TypeValue() TypeValue {
    26  	return SupportedEllipticCurvesTypeValue
    27  }
    28  
    29  // Marshal encodes the extension
    30  func (s *SupportedEllipticCurves) Marshal() ([]byte, error) {
    31  	out := make([]byte, supportedGroupsHeaderSize)
    32  
    33  	binary.BigEndian.PutUint16(out, uint16(s.TypeValue()))
    34  	binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2)))
    35  	binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2))
    36  
    37  	for _, v := range s.EllipticCurves {
    38  		out = append(out, []byte{0x00, 0x00}...)
    39  		binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v))
    40  	}
    41  
    42  	return out, nil
    43  }
    44  
    45  // Unmarshal populates the extension from encoded data
    46  func (s *SupportedEllipticCurves) Unmarshal(data []byte) error {
    47  	if len(data) <= supportedGroupsHeaderSize {
    48  		return errBufferTooSmall
    49  	} else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() {
    50  		return errInvalidExtensionType
    51  	}
    52  
    53  	groupCount := int(binary.BigEndian.Uint16(data[4:]) / 2)
    54  	if supportedGroupsHeaderSize+(groupCount*2) > len(data) {
    55  		return errLengthMismatch
    56  	}
    57  
    58  	for i := 0; i < groupCount; i++ {
    59  		supportedGroupID := elliptic.Curve(binary.BigEndian.Uint16(data[(supportedGroupsHeaderSize + (i * 2)):]))
    60  		if _, ok := elliptic.Curves()[supportedGroupID]; ok {
    61  			s.EllipticCurves = append(s.EllipticCurves, supportedGroupID)
    62  		}
    63  	}
    64  	return nil
    65  }