github.com/pion/dtls/v2@v2.2.12/flight6handler.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  
     9  	"github.com/pion/dtls/v2/pkg/crypto/prf"
    10  	"github.com/pion/dtls/v2/pkg/protocol"
    11  	"github.com/pion/dtls/v2/pkg/protocol/alert"
    12  	"github.com/pion/dtls/v2/pkg/protocol/handshake"
    13  	"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
    14  )
    15  
    16  func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
    17  	_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite,
    18  		handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false},
    19  	)
    20  	if !ok {
    21  		// No valid message received. Keep reading
    22  		return 0, nil, nil
    23  	}
    24  
    25  	if _, ok = msgs[handshake.TypeFinished].(*handshake.MessageFinished); !ok {
    26  		return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil
    27  	}
    28  
    29  	// Other party may re-transmit the last flight. Keep state to be flight6.
    30  	return flight6, nil, nil
    31  }
    32  
    33  func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
    34  	var pkts []*packet
    35  
    36  	pkts = append(pkts,
    37  		&packet{
    38  			record: &recordlayer.RecordLayer{
    39  				Header: recordlayer.Header{
    40  					Version: protocol.Version1_2,
    41  				},
    42  				Content: &protocol.ChangeCipherSpec{},
    43  			},
    44  		})
    45  
    46  	if len(state.localVerifyData) == 0 {
    47  		plainText := cache.pullAndMerge(
    48  			handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false},
    49  			handshakeCachePullRule{handshake.TypeServerHello, cfg.initialEpoch, false, false},
    50  			handshakeCachePullRule{handshake.TypeCertificate, cfg.initialEpoch, false, false},
    51  			handshakeCachePullRule{handshake.TypeServerKeyExchange, cfg.initialEpoch, false, false},
    52  			handshakeCachePullRule{handshake.TypeCertificateRequest, cfg.initialEpoch, false, false},
    53  			handshakeCachePullRule{handshake.TypeServerHelloDone, cfg.initialEpoch, false, false},
    54  			handshakeCachePullRule{handshake.TypeCertificate, cfg.initialEpoch, true, false},
    55  			handshakeCachePullRule{handshake.TypeClientKeyExchange, cfg.initialEpoch, true, false},
    56  			handshakeCachePullRule{handshake.TypeCertificateVerify, cfg.initialEpoch, true, false},
    57  			handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false},
    58  		)
    59  
    60  		var err error
    61  		state.localVerifyData, err = prf.VerifyDataServer(state.masterSecret, plainText, state.cipherSuite.HashFunc())
    62  		if err != nil {
    63  			return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
    64  		}
    65  	}
    66  
    67  	pkts = append(pkts,
    68  		&packet{
    69  			record: &recordlayer.RecordLayer{
    70  				Header: recordlayer.Header{
    71  					Version: protocol.Version1_2,
    72  					Epoch:   1,
    73  				},
    74  				Content: &handshake.Handshake{
    75  					Message: &handshake.MessageFinished{
    76  						VerifyData: state.localVerifyData,
    77  					},
    78  				},
    79  			},
    80  			shouldEncrypt:            true,
    81  			resetLocalSequenceNumber: true,
    82  		},
    83  	)
    84  	return pkts, nil, nil
    85  }