mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-08-08 20:15:46 +08:00
添加 github.com/pion/dtls 代码
This commit is contained in:
14
dtls-2.0.9/pkg/protocol/extension/errors.go
Normal file
14
dtls-2.0.9/pkg/protocol/extension/errors.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113
|
||||
errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113
|
||||
errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113
|
||||
errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113
|
||||
)
|
96
dtls-2.0.9/pkg/protocol/extension/extension.go
Normal file
96
dtls-2.0.9/pkg/protocol/extension/extension.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Package extension implements the extension values in the ClientHello/ServerHello
|
||||
package extension
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// TypeValue is the 2 byte value for a TLS Extension as registered in the IANA
|
||||
//
|
||||
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
|
||||
type TypeValue uint16
|
||||
|
||||
// TypeValue constants
|
||||
const (
|
||||
ServerNameTypeValue TypeValue = 0
|
||||
SupportedEllipticCurvesTypeValue TypeValue = 10
|
||||
SupportedPointFormatsTypeValue TypeValue = 11
|
||||
SupportedSignatureAlgorithmsTypeValue TypeValue = 13
|
||||
UseSRTPTypeValue TypeValue = 14
|
||||
UseExtendedMasterSecretTypeValue TypeValue = 23
|
||||
RenegotiationInfoTypeValue TypeValue = 65281
|
||||
)
|
||||
|
||||
// Extension represents a single TLS extension
|
||||
type Extension interface {
|
||||
Marshal() ([]byte, error)
|
||||
Unmarshal(data []byte) error
|
||||
TypeValue() TypeValue
|
||||
}
|
||||
|
||||
// Unmarshal many extensions at once
|
||||
func Unmarshal(buf []byte) ([]Extension, error) {
|
||||
switch {
|
||||
case len(buf) == 0:
|
||||
return []Extension{}, nil
|
||||
case len(buf) < 2:
|
||||
return nil, errBufferTooSmall
|
||||
}
|
||||
|
||||
declaredLen := binary.BigEndian.Uint16(buf)
|
||||
if len(buf)-2 != int(declaredLen) {
|
||||
return nil, errLengthMismatch
|
||||
}
|
||||
|
||||
extensions := []Extension{}
|
||||
unmarshalAndAppend := func(data []byte, e Extension) error {
|
||||
err := e.Unmarshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
extensions = append(extensions, e)
|
||||
return nil
|
||||
}
|
||||
|
||||
for offset := 2; offset < len(buf); {
|
||||
if len(buf) < (offset + 2) {
|
||||
return nil, errBufferTooSmall
|
||||
}
|
||||
var err error
|
||||
switch TypeValue(binary.BigEndian.Uint16(buf[offset:])) {
|
||||
case ServerNameTypeValue:
|
||||
err = unmarshalAndAppend(buf[offset:], &ServerName{})
|
||||
case SupportedEllipticCurvesTypeValue:
|
||||
err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{})
|
||||
case UseSRTPTypeValue:
|
||||
err = unmarshalAndAppend(buf[offset:], &UseSRTP{})
|
||||
case UseExtendedMasterSecretTypeValue:
|
||||
err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{})
|
||||
case RenegotiationInfoTypeValue:
|
||||
err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{})
|
||||
default:
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(buf) < (offset + 4) {
|
||||
return nil, errBufferTooSmall
|
||||
}
|
||||
extensionLength := binary.BigEndian.Uint16(buf[offset+2:])
|
||||
offset += (4 + int(extensionLength))
|
||||
}
|
||||
return extensions, nil
|
||||
}
|
||||
|
||||
// Marshal many extensions at once
|
||||
func Marshal(e []Extension) ([]byte, error) {
|
||||
extensions := []byte{}
|
||||
for _, e := range e {
|
||||
raw, err := e.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extensions = append(extensions, raw...)
|
||||
}
|
||||
out := []byte{0x00, 0x00}
|
||||
binary.BigEndian.PutUint16(out, uint16(len(extensions)))
|
||||
return append(out, extensions...), nil
|
||||
}
|
22
dtls-2.0.9/pkg/protocol/extension/extension_test.go
Normal file
22
dtls-2.0.9/pkg/protocol/extension/extension_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExtensions(t *testing.T) {
|
||||
t.Run("Zero", func(t *testing.T) {
|
||||
extensions, err := Unmarshal([]byte{})
|
||||
if err != nil || len(extensions) != 0 {
|
||||
t.Fatal("Failed to decode zero extensions")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
extensions, err := Unmarshal([]byte{0x00})
|
||||
if !errors.Is(err, errBufferTooSmall) || len(extensions) != 0 {
|
||||
t.Fatal("Failed to error on invalid extension")
|
||||
}
|
||||
})
|
||||
}
|
43
dtls-2.0.9/pkg/protocol/extension/renegotiation_info.go
Normal file
43
dtls-2.0.9/pkg/protocol/extension/renegotiation_info.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package extension
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
const (
|
||||
renegotiationInfoHeaderSize = 5
|
||||
)
|
||||
|
||||
// RenegotiationInfo allows a Client/Server to
|
||||
// communicate their renegotation support
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc5746
|
||||
type RenegotiationInfo struct {
|
||||
RenegotiatedConnection uint8
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (r RenegotiationInfo) TypeValue() TypeValue {
|
||||
return RenegotiationInfoTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (r *RenegotiationInfo) Marshal() ([]byte, error) {
|
||||
out := make([]byte, renegotiationInfoHeaderSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(r.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(1)) // length
|
||||
out[4] = r.RenegotiatedConnection
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (r *RenegotiationInfo) Unmarshal(data []byte) error {
|
||||
if len(data) < renegotiationInfoHeaderSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != r.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
r.RenegotiatedConnection = data[4]
|
||||
|
||||
return nil
|
||||
}
|
22
dtls-2.0.9/pkg/protocol/extension/renegotiation_info_test.go
Normal file
22
dtls-2.0.9/pkg/protocol/extension/renegotiation_info_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package extension
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRenegotiationInfo(t *testing.T) {
|
||||
extension := RenegotiationInfo{RenegotiatedConnection: 0}
|
||||
|
||||
raw, err := extension.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newExtension := RenegotiationInfo{}
|
||||
err = newExtension.Unmarshal(raw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if newExtension.RenegotiatedConnection != extension.RenegotiatedConnection {
|
||||
t.Errorf("extensionRenegotiationInfo marshal: got %d expected %d", newExtension.RenegotiatedConnection, extension.RenegotiatedConnection)
|
||||
}
|
||||
}
|
78
dtls-2.0.9/pkg/protocol/extension/server_name.go
Normal file
78
dtls-2.0.9/pkg/protocol/extension/server_name.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
)
|
||||
|
||||
const serverNameTypeDNSHostName = 0
|
||||
|
||||
// ServerName allows the client to inform the server the specific
|
||||
// name it wishs to contact. Useful if multiple DNS names resolve
|
||||
// to one IP
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc6066#section-3
|
||||
type ServerName struct {
|
||||
ServerName string
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (s ServerName) TypeValue() TypeValue {
|
||||
return ServerNameTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (s *ServerName) Marshal() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddUint16(uint16(s.TypeValue()))
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8(serverNameTypeDNSHostName)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes([]byte(s.ServerName))
|
||||
})
|
||||
})
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (s *ServerName) Unmarshal(data []byte) error {
|
||||
val := cryptobyte.String(data)
|
||||
var extension uint16
|
||||
val.ReadUint16(&extension)
|
||||
if TypeValue(extension) != s.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
var extData cryptobyte.String
|
||||
val.ReadUint16LengthPrefixed(&extData)
|
||||
|
||||
var nameList cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() {
|
||||
return errInvalidSNIFormat
|
||||
}
|
||||
for !nameList.Empty() {
|
||||
var nameType uint8
|
||||
var serverName cryptobyte.String
|
||||
if !nameList.ReadUint8(&nameType) ||
|
||||
!nameList.ReadUint16LengthPrefixed(&serverName) ||
|
||||
serverName.Empty() {
|
||||
return errInvalidSNIFormat
|
||||
}
|
||||
if nameType != serverNameTypeDNSHostName {
|
||||
continue
|
||||
}
|
||||
if len(s.ServerName) != 0 {
|
||||
// Multiple names of the same name_type are prohibited.
|
||||
return errInvalidSNIFormat
|
||||
}
|
||||
s.ServerName = string(serverName)
|
||||
// An SNI value may not include a trailing dot.
|
||||
if strings.HasSuffix(s.ServerName, ".") {
|
||||
return errInvalidSNIFormat
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
22
dtls-2.0.9/pkg/protocol/extension/server_name_test.go
Normal file
22
dtls-2.0.9/pkg/protocol/extension/server_name_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package extension
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestServerName(t *testing.T) {
|
||||
extension := ServerName{ServerName: "test.domain"}
|
||||
|
||||
raw, err := extension.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newExtension := ServerName{}
|
||||
err = newExtension.Unmarshal(raw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if newExtension.ServerName != extension.ServerName {
|
||||
t.Errorf("extensionServerName marshal: got %s expected %s", newExtension.ServerName, extension.ServerName)
|
||||
}
|
||||
}
|
21
dtls-2.0.9/pkg/protocol/extension/srtp_protection_profile.go
Normal file
21
dtls-2.0.9/pkg/protocol/extension/srtp_protection_profile.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package extension
|
||||
|
||||
// SRTPProtectionProfile defines the parameters and options that are in effect for the SRTP processing
|
||||
// https://tools.ietf.org/html/rfc5764#section-4.1.2
|
||||
type SRTPProtectionProfile uint16
|
||||
|
||||
const (
|
||||
SRTP_AES128_CM_HMAC_SHA1_80 SRTPProtectionProfile = 0x0001 // nolint
|
||||
SRTP_AES128_CM_HMAC_SHA1_32 SRTPProtectionProfile = 0x0002 // nolint
|
||||
SRTP_AEAD_AES_128_GCM SRTPProtectionProfile = 0x0007 // nolint
|
||||
SRTP_AEAD_AES_256_GCM SRTPProtectionProfile = 0x0008 // nolint
|
||||
)
|
||||
|
||||
func srtpProtectionProfiles() map[SRTPProtectionProfile]bool {
|
||||
return map[SRTPProtectionProfile]bool{
|
||||
SRTP_AES128_CM_HMAC_SHA1_80: true,
|
||||
SRTP_AES128_CM_HMAC_SHA1_32: true,
|
||||
SRTP_AEAD_AES_128_GCM: true,
|
||||
SRTP_AEAD_AES_256_GCM: true,
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
)
|
||||
|
||||
const (
|
||||
supportedGroupsHeaderSize = 6
|
||||
)
|
||||
|
||||
// SupportedEllipticCurves allows a Client/Server to communicate
|
||||
// what curves they both support
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc8422#section-5.1.1
|
||||
type SupportedEllipticCurves struct {
|
||||
EllipticCurves []elliptic.Curve
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (s SupportedEllipticCurves) TypeValue() TypeValue {
|
||||
return SupportedEllipticCurvesTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (s *SupportedEllipticCurves) Marshal() ([]byte, error) {
|
||||
out := make([]byte, supportedGroupsHeaderSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(s.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2)))
|
||||
binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2))
|
||||
|
||||
for _, v := range s.EllipticCurves {
|
||||
out = append(out, []byte{0x00, 0x00}...)
|
||||
binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v))
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (s *SupportedEllipticCurves) Unmarshal(data []byte) error {
|
||||
if len(data) <= supportedGroupsHeaderSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
groupCount := int(binary.BigEndian.Uint16(data[4:]) / 2)
|
||||
if supportedGroupsHeaderSize+(groupCount*2) > len(data) {
|
||||
return errLengthMismatch
|
||||
}
|
||||
|
||||
for i := 0; i < groupCount; i++ {
|
||||
supportedGroupID := elliptic.Curve(binary.BigEndian.Uint16(data[(supportedGroupsHeaderSize + (i * 2)):]))
|
||||
if _, ok := elliptic.Curves()[supportedGroupID]; ok {
|
||||
s.EllipticCurves = append(s.EllipticCurves, supportedGroupID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
)
|
||||
|
||||
func TestExtensionSupportedGroups(t *testing.T) {
|
||||
rawSupportedGroups := []byte{0x0, 0xa, 0x0, 0x4, 0x0, 0x2, 0x0, 0x1d}
|
||||
parsedSupportedGroups := &SupportedEllipticCurves{
|
||||
EllipticCurves: []elliptic.Curve{elliptic.X25519},
|
||||
}
|
||||
|
||||
raw, err := parsedSupportedGroups.Marshal()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(raw, rawSupportedGroups) {
|
||||
t.Errorf("extensionSupportedGroups marshal: got %#v, want %#v", raw, rawSupportedGroups)
|
||||
}
|
||||
}
|
62
dtls-2.0.9/pkg/protocol/extension/supported_point_formats.go
Normal file
62
dtls-2.0.9/pkg/protocol/extension/supported_point_formats.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
)
|
||||
|
||||
const (
|
||||
supportedPointFormatsSize = 5
|
||||
)
|
||||
|
||||
// SupportedPointFormats allows a Client/Server to negotiate
|
||||
// the EllipticCurvePointFormats
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc4492#section-5.1.2
|
||||
type SupportedPointFormats struct {
|
||||
PointFormats []elliptic.CurvePointFormat
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (s SupportedPointFormats) TypeValue() TypeValue {
|
||||
return SupportedPointFormatsTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (s *SupportedPointFormats) Marshal() ([]byte, error) {
|
||||
out := make([]byte, supportedPointFormatsSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(s.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(1+(len(s.PointFormats))))
|
||||
out[4] = byte(len(s.PointFormats))
|
||||
|
||||
for _, v := range s.PointFormats {
|
||||
out = append(out, byte(v))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (s *SupportedPointFormats) Unmarshal(data []byte) error {
|
||||
if len(data) <= supportedPointFormatsSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
pointFormatCount := int(binary.BigEndian.Uint16(data[4:]))
|
||||
if supportedGroupsHeaderSize+(pointFormatCount) > len(data) {
|
||||
return errLengthMismatch
|
||||
}
|
||||
|
||||
for i := 0; i < pointFormatCount; i++ {
|
||||
p := elliptic.CurvePointFormat(data[supportedPointFormatsSize+i])
|
||||
switch p {
|
||||
case elliptic.CurvePointFormatUncompressed:
|
||||
s.PointFormats = append(s.PointFormats, p)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
)
|
||||
|
||||
func TestExtensionSupportedPointFormats(t *testing.T) {
|
||||
rawExtensionSupportedPointFormats := []byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00}
|
||||
parsedExtensionSupportedPointFormats := &SupportedPointFormats{
|
||||
PointFormats: []elliptic.CurvePointFormat{elliptic.CurvePointFormatUncompressed},
|
||||
}
|
||||
|
||||
raw, err := parsedExtensionSupportedPointFormats.Marshal()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(raw, rawExtensionSupportedPointFormats) {
|
||||
t.Errorf("extensionSupportedPointFormats marshal: got %#v, want %#v", raw, rawExtensionSupportedPointFormats)
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/hash"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signature"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
|
||||
)
|
||||
|
||||
const (
|
||||
supportedSignatureAlgorithmsHeaderSize = 6
|
||||
)
|
||||
|
||||
// SupportedSignatureAlgorithms allows a Client/Server to
|
||||
// negotiate what SignatureHash Algorithms they both support
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
|
||||
type SupportedSignatureAlgorithms struct {
|
||||
SignatureHashAlgorithms []signaturehash.Algorithm
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (s SupportedSignatureAlgorithms) TypeValue() TypeValue {
|
||||
return SupportedSignatureAlgorithmsTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) {
|
||||
out := make([]byte, supportedSignatureAlgorithmsHeaderSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(s.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2)))
|
||||
binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2))
|
||||
for _, v := range s.SignatureHashAlgorithms {
|
||||
out = append(out, []byte{0x00, 0x00}...)
|
||||
out[len(out)-2] = byte(v.Hash)
|
||||
out[len(out)-1] = byte(v.Signature)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (s *SupportedSignatureAlgorithms) Unmarshal(data []byte) error {
|
||||
if len(data) <= supportedSignatureAlgorithmsHeaderSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
algorithmCount := int(binary.BigEndian.Uint16(data[4:]) / 2)
|
||||
if supportedSignatureAlgorithmsHeaderSize+(algorithmCount*2) > len(data) {
|
||||
return errLengthMismatch
|
||||
}
|
||||
for i := 0; i < algorithmCount; i++ {
|
||||
supportedHashAlgorithm := hash.Algorithm(data[supportedSignatureAlgorithmsHeaderSize+(i*2)])
|
||||
supportedSignatureAlgorithm := signature.Algorithm(data[supportedSignatureAlgorithmsHeaderSize+(i*2)+1])
|
||||
if _, ok := hash.Algorithms()[supportedHashAlgorithm]; ok {
|
||||
if _, ok := signature.Algorithms()[supportedSignatureAlgorithm]; ok {
|
||||
s.SignatureHashAlgorithms = append(s.SignatureHashAlgorithms, signaturehash.Algorithm{
|
||||
Hash: supportedHashAlgorithm,
|
||||
Signature: supportedSignatureAlgorithm,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/hash"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signature"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
|
||||
)
|
||||
|
||||
func TestExtensionSupportedSignatureAlgorithms(t *testing.T) {
|
||||
rawExtensionSupportedSignatureAlgorithms := []byte{
|
||||
0x00, 0x0d,
|
||||
0x00, 0x08,
|
||||
0x00, 0x06,
|
||||
0x04, 0x03,
|
||||
0x05, 0x03,
|
||||
0x06, 0x03,
|
||||
}
|
||||
parsedExtensionSupportedSignatureAlgorithms := &SupportedSignatureAlgorithms{
|
||||
SignatureHashAlgorithms: []signaturehash.Algorithm{
|
||||
{Hash: hash.SHA256, Signature: signature.ECDSA},
|
||||
{Hash: hash.SHA384, Signature: signature.ECDSA},
|
||||
{Hash: hash.SHA512, Signature: signature.ECDSA},
|
||||
},
|
||||
}
|
||||
|
||||
raw, err := parsedExtensionSupportedSignatureAlgorithms.Marshal()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(raw, rawExtensionSupportedSignatureAlgorithms) {
|
||||
t.Errorf("extensionSupportedSignatureAlgorithms marshal: got %#v, want %#v", raw, rawExtensionSupportedSignatureAlgorithms)
|
||||
}
|
||||
}
|
45
dtls-2.0.9/pkg/protocol/extension/use_master_secret.go
Normal file
45
dtls-2.0.9/pkg/protocol/extension/use_master_secret.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package extension
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
const (
|
||||
useExtendedMasterSecretHeaderSize = 4
|
||||
)
|
||||
|
||||
// UseExtendedMasterSecret defines a TLS extension that contextually binds the
|
||||
// master secret to a log of the full handshake that computes it, thus
|
||||
// preventing MITM attacks.
|
||||
type UseExtendedMasterSecret struct {
|
||||
Supported bool
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (u UseExtendedMasterSecret) TypeValue() TypeValue {
|
||||
return UseExtendedMasterSecretTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (u *UseExtendedMasterSecret) Marshal() ([]byte, error) {
|
||||
if !u.Supported {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
out := make([]byte, useExtendedMasterSecretHeaderSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(u.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(0)) // length
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (u *UseExtendedMasterSecret) Unmarshal(data []byte) error {
|
||||
if len(data) < useExtendedMasterSecretHeaderSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != u.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
u.Supported = true
|
||||
|
||||
return nil
|
||||
}
|
59
dtls-2.0.9/pkg/protocol/extension/use_srtp.go
Normal file
59
dtls-2.0.9/pkg/protocol/extension/use_srtp.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package extension
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
const (
|
||||
useSRTPHeaderSize = 6
|
||||
)
|
||||
|
||||
// UseSRTP allows a Client/Server to negotiate what SRTPProtectionProfiles
|
||||
// they both support
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc8422
|
||||
type UseSRTP struct {
|
||||
ProtectionProfiles []SRTPProtectionProfile
|
||||
}
|
||||
|
||||
// TypeValue returns the extension TypeValue
|
||||
func (u UseSRTP) TypeValue() TypeValue {
|
||||
return UseSRTPTypeValue
|
||||
}
|
||||
|
||||
// Marshal encodes the extension
|
||||
func (u *UseSRTP) Marshal() ([]byte, error) {
|
||||
out := make([]byte, useSRTPHeaderSize)
|
||||
|
||||
binary.BigEndian.PutUint16(out, uint16(u.TypeValue()))
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1))
|
||||
binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2))
|
||||
|
||||
for _, v := range u.ProtectionProfiles {
|
||||
out = append(out, []byte{0x00, 0x00}...)
|
||||
binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v))
|
||||
}
|
||||
|
||||
out = append(out, 0x00) /* MKI Length */
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the extension from encoded data
|
||||
func (u *UseSRTP) Unmarshal(data []byte) error {
|
||||
if len(data) <= useSRTPHeaderSize {
|
||||
return errBufferTooSmall
|
||||
} else if TypeValue(binary.BigEndian.Uint16(data)) != u.TypeValue() {
|
||||
return errInvalidExtensionType
|
||||
}
|
||||
|
||||
profileCount := int(binary.BigEndian.Uint16(data[4:]) / 2)
|
||||
if supportedGroupsHeaderSize+(profileCount*2) > len(data) {
|
||||
return errLengthMismatch
|
||||
}
|
||||
|
||||
for i := 0; i < profileCount; i++ {
|
||||
supportedProfile := SRTPProtectionProfile(binary.BigEndian.Uint16(data[(useSRTPHeaderSize + (i * 2)):]))
|
||||
if _, ok := srtpProtectionProfiles()[supportedProfile]; ok {
|
||||
u.ProtectionProfiles = append(u.ProtectionProfiles, supportedProfile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
20
dtls-2.0.9/pkg/protocol/extension/use_srtp_test.go
Normal file
20
dtls-2.0.9/pkg/protocol/extension/use_srtp_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExtensionUseSRTP(t *testing.T) {
|
||||
rawUseSRTP := []byte{0x00, 0x0e, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00}
|
||||
parsedUseSRTP := &UseSRTP{
|
||||
ProtectionProfiles: []SRTPProtectionProfile{SRTP_AES128_CM_HMAC_SHA1_80},
|
||||
}
|
||||
|
||||
raw, err := parsedUseSRTP.Marshal()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(raw, rawUseSRTP) {
|
||||
t.Errorf("extensionUseSRTP marshal: got %#v, want %#v", raw, rawUseSRTP)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user