diff options
Diffstat (limited to 'vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go')
-rw-r--r-- | vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go b/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go new file mode 100644 index 0000000..4148fe0 --- /dev/null +++ b/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go @@ -0,0 +1,119 @@ +package handshake + +import ( + "encoding/binary" + + "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v2/pkg/crypto/hash" + "github.com/pion/dtls/v2/pkg/crypto/signature" +) + +// MessageServerKeyExchange supports ECDH and PSK +type MessageServerKeyExchange struct { + IdentityHint []byte + + EllipticCurveType elliptic.CurveType + NamedCurve elliptic.Curve + PublicKey []byte + HashAlgorithm hash.Algorithm + SignatureAlgorithm signature.Algorithm + Signature []byte +} + +// Type returns the Handshake Type +func (m MessageServerKeyExchange) Type() Type { + return TypeServerKeyExchange +} + +// Marshal encodes the Handshake +func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { + if m.IdentityHint != nil { + out := append([]byte{0x00, 0x00}, m.IdentityHint...) + binary.BigEndian.PutUint16(out, uint16(len(out)-2)) + return out, nil + } + + out := []byte{byte(m.EllipticCurveType), 0x00, 0x00} + binary.BigEndian.PutUint16(out[1:], uint16(m.NamedCurve)) + + out = append(out, byte(len(m.PublicKey))) + out = append(out, m.PublicKey...) + + if m.HashAlgorithm == hash.None && m.SignatureAlgorithm == signature.Anonymous && len(m.Signature) == 0 { + return out, nil + } + + out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) + out = append(out, m.Signature...) + + return out, nil +} + +// Unmarshal populates the message from encoded data +func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { + if len(data) < 2 { + return errBufferTooSmall + } + + // If parsed as PSK return early and only populate PSK Identity Hint + if pskLength := binary.BigEndian.Uint16(data); len(data) == int(pskLength+2) { + m.IdentityHint = append([]byte{}, data[2:]...) + return nil + } + + if _, ok := elliptic.CurveTypes()[elliptic.CurveType(data[0])]; ok { + m.EllipticCurveType = elliptic.CurveType(data[0]) + } else { + return errInvalidEllipticCurveType + } + + if len(data[1:]) < 2 { + return errBufferTooSmall + } + m.NamedCurve = elliptic.Curve(binary.BigEndian.Uint16(data[1:3])) + if _, ok := elliptic.Curves()[m.NamedCurve]; !ok { + return errInvalidNamedCurve + } + if len(data) < 4 { + return errBufferTooSmall + } + + publicKeyLength := int(data[3]) + offset := 4 + publicKeyLength + if len(data) < offset { + return errBufferTooSmall + } + m.PublicKey = append([]byte{}, data[4:offset]...) + + // Anon connection doesn't contains hashAlgorithm, signatureAlgorithm, signature + if len(data) == offset { + return nil + } else if len(data) <= offset { + return errBufferTooSmall + } + + m.HashAlgorithm = hash.Algorithm(data[offset]) + if _, ok := hash.Algorithms()[m.HashAlgorithm]; !ok { + return errInvalidHashAlgorithm + } + offset++ + if len(data) <= offset { + return errBufferTooSmall + } + m.SignatureAlgorithm = signature.Algorithm(data[offset]) + if _, ok := signature.Algorithms()[m.SignatureAlgorithm]; !ok { + return errInvalidSignatureAlgorithm + } + offset++ + if len(data) < offset+2 { + return errBufferTooSmall + } + signatureLength := int(binary.BigEndian.Uint16(data[offset:])) + offset += 2 + if len(data) < offset+signatureLength { + return errBufferTooSmall + } + m.Signature = append([]byte{}, data[offset:offset+signatureLength]...) + return nil +} |