github.com/pion/dtls/v2@v2.2.12/flight0handler.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package dtls 5 6 import ( 7 "context" 8 "crypto/rand" 9 10 "github.com/pion/dtls/v2/pkg/crypto/elliptic" 11 "github.com/pion/dtls/v2/pkg/protocol" 12 "github.com/pion/dtls/v2/pkg/protocol/alert" 13 "github.com/pion/dtls/v2/pkg/protocol/extension" 14 "github.com/pion/dtls/v2/pkg/protocol/handshake" 15 ) 16 17 func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { 18 seq, msgs, ok := cache.fullPullMap(0, state.cipherSuite, 19 handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, 20 ) 21 if !ok { 22 // No valid message received. Keep reading 23 return 0, nil, nil 24 } 25 state.handshakeRecvSequence = seq 26 27 var clientHello *handshake.MessageClientHello 28 29 // Validate type 30 if clientHello, ok = msgs[handshake.TypeClientHello].(*handshake.MessageClientHello); !ok { 31 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil 32 } 33 34 if !clientHello.Version.Equal(protocol.Version1_2) { 35 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.ProtocolVersion}, errUnsupportedProtocolVersion 36 } 37 38 state.remoteRandom = clientHello.Random 39 40 cipherSuites := []CipherSuite{} 41 for _, id := range clientHello.CipherSuiteIDs { 42 if c := cipherSuiteForID(CipherSuiteID(id), cfg.customCipherSuites); c != nil { 43 cipherSuites = append(cipherSuites, c) 44 } 45 } 46 47 if state.cipherSuite, ok = findMatchingCipherSuite(cipherSuites, cfg.localCipherSuites); !ok { 48 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errCipherSuiteNoIntersection 49 } 50 51 for _, val := range clientHello.Extensions { 52 switch e := val.(type) { 53 case *extension.SupportedEllipticCurves: 54 if len(e.EllipticCurves) == 0 { 55 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoSupportedEllipticCurves 56 } 57 state.namedCurve = e.EllipticCurves[0] 58 case *extension.UseSRTP: 59 profile, ok := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles) 60 if !ok { 61 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile 62 } 63 state.setSRTPProtectionProfile(profile) 64 case *extension.UseExtendedMasterSecret: 65 if cfg.extendedMasterSecret != DisableExtendedMasterSecret { 66 state.extendedMasterSecret = true 67 } 68 case *extension.ServerName: 69 state.serverName = e.ServerName // remote server name 70 case *extension.ALPN: 71 state.peerSupportedProtocols = e.ProtocolNameList 72 } 73 } 74 75 if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { 76 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerRequiredButNoClientEMS 77 } 78 79 if state.localKeypair == nil { 80 var err error 81 state.localKeypair, err = elliptic.GenerateKeypair(state.namedCurve) 82 if err != nil { 83 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err 84 } 85 } 86 87 nextFlight := flight2 88 89 if cfg.insecureSkipHelloVerify { 90 nextFlight = flight4 91 } 92 93 return handleHelloResume(clientHello.SessionID, state, cfg, nextFlight) 94 } 95 96 func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, next flightVal) (flightVal, *alert.Alert, error) { 97 if len(sessionID) > 0 && cfg.sessionStore != nil { 98 if s, err := cfg.sessionStore.Get(sessionID); err != nil { 99 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err 100 } else if s.ID != nil { 101 cfg.log.Tracef("[handshake] resume session: %x", sessionID) 102 103 state.SessionID = sessionID 104 state.masterSecret = s.Secret 105 106 if err := state.initCipherSuite(); err != nil { 107 return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err 108 } 109 110 clientRandom := state.localRandom.MarshalFixed() 111 cfg.writeKeyLog(keyLogLabelTLS12, clientRandom[:], state.masterSecret) 112 113 return flight4b, nil, nil 114 } 115 } 116 return next, nil, nil 117 } 118 119 func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { 120 // Initialize 121 if !cfg.insecureSkipHelloVerify { 122 state.cookie = make([]byte, cookieLength) 123 if _, err := rand.Read(state.cookie); err != nil { 124 return nil, nil, err 125 } 126 } 127 128 var zeroEpoch uint16 129 state.localEpoch.Store(zeroEpoch) 130 state.remoteEpoch.Store(zeroEpoch) 131 state.namedCurve = defaultNamedCurve 132 133 if err := state.localRandom.Populate(); err != nil { 134 return nil, nil, err 135 } 136 137 return nil, nil, nil 138 }