// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

// Package handshake provides the DTLS wire protocol for handshakes
package handshake import ( ) // Type is the unique identifier for each handshake message // https://tools.ietf.org/html/rfc5246#section-7.4 type Type uint8 // Types of DTLS Handshake messages we know about. const ( TypeHelloRequest Type = 0 TypeClientHello Type = 1 TypeServerHello Type = 2 TypeHelloVerifyRequest Type = 3 TypeCertificate Type = 11 TypeServerKeyExchange Type = 12 TypeCertificateRequest Type = 13 TypeServerHelloDone Type = 14 TypeCertificateVerify Type = 15 TypeClientKeyExchange Type = 16 TypeFinished Type = 20 ) // String returns the string representation of this type. func ( Type) () string { //nolint:cyclop switch { case TypeHelloRequest: return "HelloRequest" case TypeClientHello: return "ClientHello" case TypeServerHello: return "ServerHello" case TypeHelloVerifyRequest: return "HelloVerifyRequest" case TypeCertificate: return "TypeCertificate" case TypeServerKeyExchange: return "ServerKeyExchange" case TypeCertificateRequest: return "CertificateRequest" case TypeServerHelloDone: return "ServerHelloDone" case TypeCertificateVerify: return "CertificateVerify" case TypeClientKeyExchange: return "ClientKeyExchange" case TypeFinished: return "Finished" } return "" } // Message is the body of a Handshake datagram. type Message interface { Marshal() ([]byte, error) Unmarshal(data []byte) error Type() Type } // Handshake protocol is responsible for selecting a cipher spec and // generating a master secret, which together comprise the primary // cryptographic parameters associated with a secure session. The // handshake protocol can also optionally authenticate parties who have // certificates signed by a trusted certificate authority. // https://tools.ietf.org/html/rfc5246#section-7.3 type Handshake struct { Header Header Message Message KeyExchangeAlgorithm types.KeyExchangeAlgorithm } // ContentType returns what kind of content this message is carying. func ( Handshake) () protocol.ContentType { return protocol.ContentTypeHandshake } // Marshal encodes a handshake into a binary message. func ( *Handshake) () ([]byte, error) { if .Message == nil { return nil, errHandshakeMessageUnset } else if .Header.FragmentOffset != 0 { return nil, errUnableToMarshalFragmented } , := .Message.Marshal() if != nil { return nil, } .Header.Length = uint32(len()) //nolint:gosec // G115 .Header.FragmentLength = .Header.Length .Header.Type = .Message.Type() , := .Header.Marshal() if != nil { return nil, } return append(, ...), nil } // Unmarshal decodes a handshake from a binary message. func ( *Handshake) ( []byte) error { //nolint:cyclop if := .Header.Unmarshal(); != nil { return } := util.BigEndianUint24([1:]) if uint32(len()-HeaderLength) != { //nolint:gosec // G115 return errLengthMismatch } else if != .Header.FragmentLength { return errLengthMismatch } switch Type([0]) { case TypeHelloRequest: return errNotImplemented case TypeClientHello: .Message = &MessageClientHello{} case TypeHelloVerifyRequest: .Message = &MessageHelloVerifyRequest{} case TypeServerHello: .Message = &MessageServerHello{} case TypeCertificate: .Message = &MessageCertificate{} case TypeServerKeyExchange: .Message = &MessageServerKeyExchange{KeyExchangeAlgorithm: .KeyExchangeAlgorithm} case TypeCertificateRequest: .Message = &MessageCertificateRequest{} case TypeServerHelloDone: .Message = &MessageServerHelloDone{} case TypeClientKeyExchange: .Message = &MessageClientKeyExchange{KeyExchangeAlgorithm: .KeyExchangeAlgorithm} case TypeFinished: .Message = &MessageFinished{} case TypeCertificateVerify: .Message = &MessageCertificateVerify{} default: return errNotImplemented } return .Message.Unmarshal([HeaderLength:]) }