github.com/pion/dtls/v2@v2.2.12/pkg/crypto/ciphersuite/ciphersuite.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  // Package ciphersuite provides the crypto operations needed for a DTLS CipherSuite
     5  package ciphersuite
     6  
     7  import (
     8  	"encoding/binary"
     9  	"errors"
    10  
    11  	"github.com/pion/dtls/v2/pkg/protocol"
    12  	"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
    13  )
    14  
    15  var (
    16  	errNotEnoughRoomForNonce = &protocol.InternalError{Err: errors.New("buffer not long enough to contain nonce")} //nolint:goerr113
    17  	errDecryptPacket         = &protocol.TemporaryError{Err: errors.New("failed to decrypt packet")}               //nolint:goerr113
    18  	errInvalidMAC            = &protocol.TemporaryError{Err: errors.New("invalid mac")}                            //nolint:goerr113
    19  	errFailedToCast          = &protocol.FatalError{Err: errors.New("failed to cast")}                             //nolint:goerr113
    20  )
    21  
    22  func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte {
    23  	var additionalData [13]byte
    24  	// SequenceNumber MUST be set first
    25  	// we only want uint48, clobbering an extra 2 (using uint64, Golang doesn't have uint48)
    26  	binary.BigEndian.PutUint64(additionalData[:], h.SequenceNumber)
    27  	binary.BigEndian.PutUint16(additionalData[:], h.Epoch)
    28  	additionalData[8] = byte(h.ContentType)
    29  	additionalData[9] = h.Version.Major
    30  	additionalData[10] = h.Version.Minor
    31  	binary.BigEndian.PutUint16(additionalData[len(additionalData)-2:], uint16(payloadLen))
    32  
    33  	return additionalData[:]
    34  }
    35  
    36  // examinePadding returns, in constant time, the length of the padding to remove
    37  // from the end of payload. It also returns a byte which is equal to 255 if the
    38  // padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2.
    39  //
    40  // https://github.com/golang/go/blob/039c2081d1178f90a8fa2f4e6958693129f8de33/src/crypto/tls/conn.go#L245
    41  func examinePadding(payload []byte) (toRemove int, good byte) {
    42  	if len(payload) < 1 {
    43  		return 0, 0
    44  	}
    45  
    46  	paddingLen := payload[len(payload)-1]
    47  	t := uint(len(payload)-1) - uint(paddingLen)
    48  	// if len(payload) >= (paddingLen - 1) then the MSB of t is zero
    49  	good = byte(int32(^t) >> 31)
    50  
    51  	// The maximum possible padding length plus the actual length field
    52  	toCheck := 256
    53  	// The length of the padded data is public, so we can use an if here
    54  	if toCheck > len(payload) {
    55  		toCheck = len(payload)
    56  	}
    57  
    58  	for i := 0; i < toCheck; i++ {
    59  		t := uint(paddingLen) - uint(i)
    60  		// if i <= paddingLen then the MSB of t is zero
    61  		mask := byte(int32(^t) >> 31)
    62  		b := payload[len(payload)-1-i]
    63  		good &^= mask&paddingLen ^ mask&b
    64  	}
    65  
    66  	// We AND together the bits of good and replicate the result across
    67  	// all the bits.
    68  	good &= good << 4
    69  	good &= good << 2
    70  	good &= good << 1
    71  	good = uint8(int8(good) >> 7)
    72  
    73  	toRemove = int(paddingLen) + 1
    74  
    75  	return toRemove, good
    76  }