github.com/pion/dtls/v2@v2.2.12/pkg/protocol/handshake/handshake.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package handshake provides the DTLS wire protocol for handshakes 5 package handshake 6 7 import ( 8 "github.com/pion/dtls/v2/internal/ciphersuite/types" 9 "github.com/pion/dtls/v2/internal/util" 10 "github.com/pion/dtls/v2/pkg/protocol" 11 ) 12 13 // Type is the unique identifier for each handshake message 14 // https://tools.ietf.org/html/rfc5246#section-7.4 15 type Type uint8 16 17 // Types of DTLS Handshake messages we know about 18 const ( 19 TypeHelloRequest Type = 0 20 TypeClientHello Type = 1 21 TypeServerHello Type = 2 22 TypeHelloVerifyRequest Type = 3 23 TypeCertificate Type = 11 24 TypeServerKeyExchange Type = 12 25 TypeCertificateRequest Type = 13 26 TypeServerHelloDone Type = 14 27 TypeCertificateVerify Type = 15 28 TypeClientKeyExchange Type = 16 29 TypeFinished Type = 20 30 ) 31 32 // String returns the string representation of this type 33 func (t Type) String() string { 34 switch t { 35 case TypeHelloRequest: 36 return "HelloRequest" 37 case TypeClientHello: 38 return "ClientHello" 39 case TypeServerHello: 40 return "ServerHello" 41 case TypeHelloVerifyRequest: 42 return "HelloVerifyRequest" 43 case TypeCertificate: 44 return "TypeCertificate" 45 case TypeServerKeyExchange: 46 return "ServerKeyExchange" 47 case TypeCertificateRequest: 48 return "CertificateRequest" 49 case TypeServerHelloDone: 50 return "ServerHelloDone" 51 case TypeCertificateVerify: 52 return "CertificateVerify" 53 case TypeClientKeyExchange: 54 return "ClientKeyExchange" 55 case TypeFinished: 56 return "Finished" 57 } 58 return "" 59 } 60 61 // Message is the body of a Handshake datagram 62 type Message interface { 63 Marshal() ([]byte, error) 64 Unmarshal(data []byte) error 65 Type() Type 66 } 67 68 // Handshake protocol is responsible for selecting a cipher spec and 69 // generating a master secret, which together comprise the primary 70 // cryptographic parameters associated with a secure session. The 71 // handshake protocol can also optionally authenticate parties who have 72 // certificates signed by a trusted certificate authority. 73 // https://tools.ietf.org/html/rfc5246#section-7.3 74 type Handshake struct { 75 Header Header 76 Message Message 77 78 KeyExchangeAlgorithm types.KeyExchangeAlgorithm 79 } 80 81 // ContentType returns what kind of content this message is carying 82 func (h Handshake) ContentType() protocol.ContentType { 83 return protocol.ContentTypeHandshake 84 } 85 86 // Marshal encodes a handshake into a binary message 87 func (h *Handshake) Marshal() ([]byte, error) { 88 if h.Message == nil { 89 return nil, errHandshakeMessageUnset 90 } else if h.Header.FragmentOffset != 0 { 91 return nil, errUnableToMarshalFragmented 92 } 93 94 msg, err := h.Message.Marshal() 95 if err != nil { 96 return nil, err 97 } 98 99 h.Header.Length = uint32(len(msg)) 100 h.Header.FragmentLength = h.Header.Length 101 h.Header.Type = h.Message.Type() 102 header, err := h.Header.Marshal() 103 if err != nil { 104 return nil, err 105 } 106 107 return append(header, msg...), nil 108 } 109 110 // Unmarshal decodes a handshake from a binary message 111 func (h *Handshake) Unmarshal(data []byte) error { 112 if err := h.Header.Unmarshal(data); err != nil { 113 return err 114 } 115 116 reportedLen := util.BigEndianUint24(data[1:]) 117 if uint32(len(data)-HeaderLength) != reportedLen { 118 return errLengthMismatch 119 } else if reportedLen != h.Header.FragmentLength { 120 return errLengthMismatch 121 } 122 123 switch Type(data[0]) { 124 case TypeHelloRequest: 125 return errNotImplemented 126 case TypeClientHello: 127 h.Message = &MessageClientHello{} 128 case TypeHelloVerifyRequest: 129 h.Message = &MessageHelloVerifyRequest{} 130 case TypeServerHello: 131 h.Message = &MessageServerHello{} 132 case TypeCertificate: 133 h.Message = &MessageCertificate{} 134 case TypeServerKeyExchange: 135 h.Message = &MessageServerKeyExchange{KeyExchangeAlgorithm: h.KeyExchangeAlgorithm} 136 case TypeCertificateRequest: 137 h.Message = &MessageCertificateRequest{} 138 case TypeServerHelloDone: 139 h.Message = &MessageServerHelloDone{} 140 case TypeClientKeyExchange: 141 h.Message = &MessageClientKeyExchange{KeyExchangeAlgorithm: h.KeyExchangeAlgorithm} 142 case TypeFinished: 143 h.Message = &MessageFinished{} 144 case TypeCertificateVerify: 145 h.Message = &MessageCertificateVerify{} 146 default: 147 return errNotImplemented 148 } 149 return h.Message.Unmarshal(data[HeaderLength:]) 150 }