github.com/pion/dtls/v2@v2.2.12/pkg/protocol/handshake/message_client_key_exchange.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package handshake
     5  
     6  import (
     7  	"encoding/binary"
     8  
     9  	"github.com/pion/dtls/v2/internal/ciphersuite/types"
    10  )
    11  
    12  // MessageClientKeyExchange is a DTLS Handshake Message
    13  // With this message, the premaster secret is set, either by direct
    14  // transmission of the RSA-encrypted secret or by the transmission of
    15  // Diffie-Hellman parameters that will allow each side to agree upon
    16  // the same premaster secret.
    17  //
    18  // https://tools.ietf.org/html/rfc5246#section-7.4.7
    19  type MessageClientKeyExchange struct {
    20  	IdentityHint []byte
    21  	PublicKey    []byte
    22  
    23  	// for unmarshaling
    24  	KeyExchangeAlgorithm types.KeyExchangeAlgorithm
    25  }
    26  
    27  // Type returns the Handshake Type
    28  func (m MessageClientKeyExchange) Type() Type {
    29  	return TypeClientKeyExchange
    30  }
    31  
    32  // Marshal encodes the Handshake
    33  func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) {
    34  	if m.IdentityHint == nil && m.PublicKey == nil {
    35  		return nil, errInvalidClientKeyExchange
    36  	}
    37  
    38  	if m.IdentityHint != nil {
    39  		out = append([]byte{0x00, 0x00}, m.IdentityHint...)
    40  		binary.BigEndian.PutUint16(out, uint16(len(out)-2))
    41  	}
    42  
    43  	if m.PublicKey != nil {
    44  		out = append(out, byte(len(m.PublicKey)))
    45  		out = append(out, m.PublicKey...)
    46  	}
    47  
    48  	return out, nil
    49  }
    50  
    51  // Unmarshal populates the message from encoded data
    52  func (m *MessageClientKeyExchange) Unmarshal(data []byte) error {
    53  	switch {
    54  	case len(data) < 2:
    55  		return errBufferTooSmall
    56  	case m.KeyExchangeAlgorithm == types.KeyExchangeAlgorithmNone:
    57  		return errCipherSuiteUnset
    58  	}
    59  
    60  	offset := 0
    61  	if m.KeyExchangeAlgorithm.Has(types.KeyExchangeAlgorithmPsk) {
    62  		pskLength := int(binary.BigEndian.Uint16(data))
    63  		if pskLength > len(data)-2 {
    64  			return errBufferTooSmall
    65  		}
    66  
    67  		m.IdentityHint = append([]byte{}, data[2:pskLength+2]...)
    68  		offset += pskLength + 2
    69  	}
    70  
    71  	if m.KeyExchangeAlgorithm.Has(types.KeyExchangeAlgorithmEcdhe) {
    72  		publicKeyLength := int(data[offset])
    73  		if publicKeyLength > len(data)-1-offset {
    74  			return errBufferTooSmall
    75  		}
    76  
    77  		m.PublicKey = append([]byte{}, data[offset+1:]...)
    78  	}
    79  
    80  	return nil
    81  }