github.com/pion/dtls/v2@v2.2.12/pkg/protocol/handshake/message_server_key_exchange.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 "encoding/binary" 8 9 "github.com/pion/dtls/v2/internal/ciphersuite/types" 10 "github.com/pion/dtls/v2/pkg/crypto/elliptic" 11 "github.com/pion/dtls/v2/pkg/crypto/hash" 12 "github.com/pion/dtls/v2/pkg/crypto/signature" 13 ) 14 15 // MessageServerKeyExchange supports ECDH and PSK 16 type MessageServerKeyExchange struct { 17 IdentityHint []byte 18 19 EllipticCurveType elliptic.CurveType 20 NamedCurve elliptic.Curve 21 PublicKey []byte 22 HashAlgorithm hash.Algorithm 23 SignatureAlgorithm signature.Algorithm 24 Signature []byte 25 26 // for unmarshaling 27 KeyExchangeAlgorithm types.KeyExchangeAlgorithm 28 } 29 30 // Type returns the Handshake Type 31 func (m MessageServerKeyExchange) Type() Type { 32 return TypeServerKeyExchange 33 } 34 35 // Marshal encodes the Handshake 36 func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { 37 var out []byte 38 if m.IdentityHint != nil { 39 out = append([]byte{0x00, 0x00}, m.IdentityHint...) 40 binary.BigEndian.PutUint16(out, uint16(len(out)-2)) 41 } 42 43 if m.EllipticCurveType == 0 || len(m.PublicKey) == 0 { 44 return out, nil 45 } 46 out = append(out, byte(m.EllipticCurveType), 0x00, 0x00) 47 binary.BigEndian.PutUint16(out[len(out)-2:], uint16(m.NamedCurve)) 48 49 out = append(out, byte(len(m.PublicKey))) 50 out = append(out, m.PublicKey...) 51 switch { 52 case m.HashAlgorithm != hash.None && len(m.Signature) == 0: 53 return nil, errInvalidHashAlgorithm 54 case m.HashAlgorithm == hash.None && len(m.Signature) > 0: 55 return nil, errInvalidHashAlgorithm 56 case m.SignatureAlgorithm == signature.Anonymous && (m.HashAlgorithm != hash.None || len(m.Signature) > 0): 57 return nil, errInvalidSignatureAlgorithm 58 case m.SignatureAlgorithm == signature.Anonymous: 59 return out, nil 60 } 61 62 out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...) 63 binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) 64 out = append(out, m.Signature...) 65 66 return out, nil 67 } 68 69 // Unmarshal populates the message from encoded data 70 func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { 71 switch { 72 case len(data) < 2: 73 return errBufferTooSmall 74 case m.KeyExchangeAlgorithm == types.KeyExchangeAlgorithmNone: 75 return errCipherSuiteUnset 76 } 77 78 hintLength := binary.BigEndian.Uint16(data) 79 if int(hintLength) <= len(data)-2 && m.KeyExchangeAlgorithm.Has(types.KeyExchangeAlgorithmPsk) { 80 m.IdentityHint = append([]byte{}, data[2:2+hintLength]...) 81 data = data[2+hintLength:] 82 } 83 if m.KeyExchangeAlgorithm == types.KeyExchangeAlgorithmPsk { 84 if len(data) == 0 { 85 return nil 86 } 87 return errLengthMismatch 88 } 89 90 if !m.KeyExchangeAlgorithm.Has(types.KeyExchangeAlgorithmEcdhe) { 91 return errLengthMismatch 92 } 93 94 if _, ok := elliptic.CurveTypes()[elliptic.CurveType(data[0])]; ok { 95 m.EllipticCurveType = elliptic.CurveType(data[0]) 96 } else { 97 return errInvalidEllipticCurveType 98 } 99 100 if len(data[1:]) < 2 { 101 return errBufferTooSmall 102 } 103 m.NamedCurve = elliptic.Curve(binary.BigEndian.Uint16(data[1:3])) 104 if _, ok := elliptic.Curves()[m.NamedCurve]; !ok { 105 return errInvalidNamedCurve 106 } 107 if len(data) < 4 { 108 return errBufferTooSmall 109 } 110 111 publicKeyLength := int(data[3]) 112 offset := 4 + publicKeyLength 113 if len(data) < offset { 114 return errBufferTooSmall 115 } 116 m.PublicKey = append([]byte{}, data[4:offset]...) 117 118 // Anon connection doesn't contains hashAlgorithm, signatureAlgorithm, signature 119 if len(data) == offset { 120 return nil 121 } else if len(data) <= offset { 122 return errBufferTooSmall 123 } 124 125 m.HashAlgorithm = hash.Algorithm(data[offset]) 126 if _, ok := hash.Algorithms()[m.HashAlgorithm]; !ok { 127 return errInvalidHashAlgorithm 128 } 129 offset++ 130 if len(data) <= offset { 131 return errBufferTooSmall 132 } 133 m.SignatureAlgorithm = signature.Algorithm(data[offset]) 134 if _, ok := signature.Algorithms()[m.SignatureAlgorithm]; !ok { 135 return errInvalidSignatureAlgorithm 136 } 137 offset++ 138 if len(data) < offset+2 { 139 return errBufferTooSmall 140 } 141 signatureLength := int(binary.BigEndian.Uint16(data[offset:])) 142 offset += 2 143 if len(data) < offset+signatureLength { 144 return errBufferTooSmall 145 } 146 m.Signature = append([]byte{}, data[offset:offset+signatureLength]...) 147 return nil 148 }