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 }