aboutsummaryrefslogtreecommitdiff
path: root/pc/srtpfilter.h
blob: a4dd54fa8bdebca68e19c0fddd0839b6910e69d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 *  Copyright 2009 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef PC_SRTPFILTER_H_
#define PC_SRTPFILTER_H_

#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/cryptoparams.h"
#include "api/jsep.h"
#include "pc/sessiondescription.h"
#include "rtc_base/buffer.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/sslstreamadapter.h"
#include "rtc_base/thread_checker.h"

// Forward declaration to avoid pulling in libsrtp headers here
struct srtp_event_data_t;
struct srtp_ctx_t_;

namespace cricket {

// A helper class used to negotiate SDES crypto params.
// TODO(zhihuang): Find a better name for this class, like "SdesNegotiator".
class SrtpFilter {
 public:
  enum Mode { PROTECT, UNPROTECT };
  enum Error {
    ERROR_NONE,
    ERROR_FAIL,
    ERROR_AUTH,
    ERROR_REPLAY,
  };

  SrtpFilter();
  ~SrtpFilter();

  // Whether the filter is active (i.e. crypto has been properly negotiated).
  bool IsActive() const;

  // Handle the offer/answer negotiation of the crypto parameters internally.
  // TODO(zhihuang): Make SetOffer/ProvisionalAnswer/Answer private as helper
  // methods once start using Process.
  bool Process(const std::vector<CryptoParams>& cryptos,
               webrtc::SdpType type,
               ContentSource source);

  // Indicates which crypto algorithms and keys were contained in the offer.
  // offer_params should contain a list of available parameters to use, or none,
  // if crypto is not desired. This must be called before SetAnswer.
  bool SetOffer(const std::vector<CryptoParams>& offer_params,
                ContentSource source);
  // Same as SetAnwer. But multiple calls are allowed to SetProvisionalAnswer
  // after a call to SetOffer.
  bool SetProvisionalAnswer(const std::vector<CryptoParams>& answer_params,
                            ContentSource source);
  // Indicates which crypto algorithms and keys were contained in the answer.
  // answer_params should contain the negotiated parameters, which may be none,
  // if crypto was not desired or could not be negotiated (and not required).
  // This must be called after SetOffer. If crypto negotiation completes
  // successfully, this will advance the filter to the active state.
  bool SetAnswer(const std::vector<CryptoParams>& answer_params,
                 ContentSource source);

  bool ResetParams();

  absl::optional<int> send_cipher_suite() { return send_cipher_suite_; }
  absl::optional<int> recv_cipher_suite() { return recv_cipher_suite_; }

  rtc::ArrayView<const uint8_t> send_key() { return send_key_; }
  rtc::ArrayView<const uint8_t> recv_key() { return recv_key_; }

 protected:
  bool ExpectOffer(ContentSource source);

  bool StoreParams(const std::vector<CryptoParams>& params,
                   ContentSource source);

  bool ExpectAnswer(ContentSource source);

  bool DoSetAnswer(const std::vector<CryptoParams>& answer_params,
                   ContentSource source,
                   bool final);

  bool NegotiateParams(const std::vector<CryptoParams>& answer_params,
                       CryptoParams* selected_params);

 private:
  bool ApplySendParams(const CryptoParams& send_params);

  bool ApplyRecvParams(const CryptoParams& recv_params);

  static bool ParseKeyParams(const std::string& params,
                             uint8_t* key,
                             size_t len);

  enum State {
    ST_INIT,                    // SRTP filter unused.
    ST_SENTOFFER,               // Offer with SRTP parameters sent.
    ST_RECEIVEDOFFER,           // Offer with SRTP parameters received.
    ST_SENTPRANSWER_NO_CRYPTO,  // Sent provisional answer without crypto.
    // Received provisional answer without crypto.
    ST_RECEIVEDPRANSWER_NO_CRYPTO,
    ST_ACTIVE,  // Offer and answer set.
    // SRTP filter is active but new parameters are offered.
    // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT.
    ST_SENTUPDATEDOFFER,
    // SRTP filter is active but new parameters are received.
    // When the answer is set, the state transitions back to ST_ACTIVE.
    ST_RECEIVEDUPDATEDOFFER,
    // SRTP filter is active but the sent answer is only provisional.
    // When the final answer is set, the state transitions to ST_ACTIVE or
    // ST_INIT.
    ST_SENTPRANSWER,
    // SRTP filter is active but the received answer is only provisional.
    // When the final answer is set, the state transitions to ST_ACTIVE or
    // ST_INIT.
    ST_RECEIVEDPRANSWER
  };
  State state_ = ST_INIT;
  std::vector<CryptoParams> offer_params_;
  CryptoParams applied_send_params_;
  CryptoParams applied_recv_params_;
  absl::optional<int> send_cipher_suite_;
  absl::optional<int> recv_cipher_suite_;
  rtc::ZeroOnFreeBuffer<uint8_t> send_key_;
  rtc::ZeroOnFreeBuffer<uint8_t> recv_key_;
};

}  // namespace cricket

#endif  // PC_SRTPFILTER_H_