github.com/pion/dtls/v2@v2.2.12/pkg/protocol/handshake/message_certificate.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  	"github.com/pion/dtls/v2/internal/util"
     8  )
     9  
    10  // MessageCertificate is a DTLS Handshake Message
    11  // it can contain either a Client or Server Certificate
    12  //
    13  // https://tools.ietf.org/html/rfc5246#section-7.4.2
    14  type MessageCertificate struct {
    15  	Certificate [][]byte
    16  }
    17  
    18  // Type returns the Handshake Type
    19  func (m MessageCertificate) Type() Type {
    20  	return TypeCertificate
    21  }
    22  
    23  const (
    24  	handshakeMessageCertificateLengthFieldSize = 3
    25  )
    26  
    27  // Marshal encodes the Handshake
    28  func (m *MessageCertificate) Marshal() ([]byte, error) {
    29  	out := make([]byte, handshakeMessageCertificateLengthFieldSize)
    30  
    31  	for _, r := range m.Certificate {
    32  		// Certificate Length
    33  		out = append(out, make([]byte, handshakeMessageCertificateLengthFieldSize)...)
    34  		util.PutBigEndianUint24(out[len(out)-handshakeMessageCertificateLengthFieldSize:], uint32(len(r)))
    35  
    36  		// Certificate body
    37  		out = append(out, append([]byte{}, r...)...)
    38  	}
    39  
    40  	// Total Payload Size
    41  	util.PutBigEndianUint24(out[0:], uint32(len(out[handshakeMessageCertificateLengthFieldSize:])))
    42  	return out, nil
    43  }
    44  
    45  // Unmarshal populates the message from encoded data
    46  func (m *MessageCertificate) Unmarshal(data []byte) error {
    47  	if len(data) < handshakeMessageCertificateLengthFieldSize {
    48  		return errBufferTooSmall
    49  	}
    50  
    51  	if certificateBodyLen := int(util.BigEndianUint24(data)); certificateBodyLen+handshakeMessageCertificateLengthFieldSize != len(data) {
    52  		return errLengthMismatch
    53  	}
    54  
    55  	offset := handshakeMessageCertificateLengthFieldSize
    56  	for offset < len(data) {
    57  		certificateLen := int(util.BigEndianUint24(data[offset:]))
    58  		offset += handshakeMessageCertificateLengthFieldSize
    59  
    60  		if offset+certificateLen > len(data) {
    61  			return errLengthMismatch
    62  		}
    63  
    64  		m.Certificate = append(m.Certificate, append([]byte{}, data[offset:offset+certificateLen]...))
    65  		offset += certificateLen
    66  	}
    67  
    68  	return nil
    69  }