1 /*
2  *  Copyright 2009 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef PC_SRTP_FILTER_H_
12 #define PC_SRTP_FILTER_H_
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <list>
18 #include <map>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/types/optional.h"
24 #include "api/array_view.h"
25 #include "api/crypto_params.h"
26 #include "api/jsep.h"
27 #include "api/sequence_checker.h"
28 #include "pc/session_description.h"
29 #include "rtc_base/buffer.h"
30 #include "rtc_base/constructor_magic.h"
31 #include "rtc_base/ssl_stream_adapter.h"
32 
33 // Forward declaration to avoid pulling in libsrtp headers here
34 struct srtp_event_data_t;
35 struct srtp_ctx_t_;
36 
37 namespace cricket {
38 
39 // A helper class used to negotiate SDES crypto params.
40 // TODO(zhihuang): Find a better name for this class, like "SdesNegotiator".
41 class SrtpFilter {
42  public:
43   enum Mode { PROTECT, UNPROTECT };
44   enum Error {
45     ERROR_NONE,
46     ERROR_FAIL,
47     ERROR_AUTH,
48     ERROR_REPLAY,
49   };
50 
51   SrtpFilter();
52   ~SrtpFilter();
53 
54   // Whether the filter is active (i.e. crypto has been properly negotiated).
55   bool IsActive() const;
56 
57   // Handle the offer/answer negotiation of the crypto parameters internally.
58   // TODO(zhihuang): Make SetOffer/ProvisionalAnswer/Answer private as helper
59   // methods once start using Process.
60   bool Process(const std::vector<CryptoParams>& cryptos,
61                webrtc::SdpType type,
62                ContentSource source);
63 
64   // Indicates which crypto algorithms and keys were contained in the offer.
65   // offer_params should contain a list of available parameters to use, or none,
66   // if crypto is not desired. This must be called before SetAnswer.
67   bool SetOffer(const std::vector<CryptoParams>& offer_params,
68                 ContentSource source);
69   // Same as SetAnwer. But multiple calls are allowed to SetProvisionalAnswer
70   // after a call to SetOffer.
71   bool SetProvisionalAnswer(const std::vector<CryptoParams>& answer_params,
72                             ContentSource source);
73   // Indicates which crypto algorithms and keys were contained in the answer.
74   // answer_params should contain the negotiated parameters, which may be none,
75   // if crypto was not desired or could not be negotiated (and not required).
76   // This must be called after SetOffer. If crypto negotiation completes
77   // successfully, this will advance the filter to the active state.
78   bool SetAnswer(const std::vector<CryptoParams>& answer_params,
79                  ContentSource source);
80 
81   bool ResetParams();
82 
83   static bool ParseKeyParams(const std::string& params,
84                              uint8_t* key,
85                              size_t len);
86 
send_cipher_suite()87   absl::optional<int> send_cipher_suite() { return send_cipher_suite_; }
recv_cipher_suite()88   absl::optional<int> recv_cipher_suite() { return recv_cipher_suite_; }
89 
send_key()90   rtc::ArrayView<const uint8_t> send_key() { return send_key_; }
recv_key()91   rtc::ArrayView<const uint8_t> recv_key() { return recv_key_; }
92 
93  protected:
94   bool ExpectOffer(ContentSource source);
95 
96   bool StoreParams(const std::vector<CryptoParams>& params,
97                    ContentSource source);
98 
99   bool ExpectAnswer(ContentSource source);
100 
101   bool DoSetAnswer(const std::vector<CryptoParams>& answer_params,
102                    ContentSource source,
103                    bool final);
104 
105   bool NegotiateParams(const std::vector<CryptoParams>& answer_params,
106                        CryptoParams* selected_params);
107 
108  private:
109   bool ApplySendParams(const CryptoParams& send_params);
110 
111   bool ApplyRecvParams(const CryptoParams& recv_params);
112 
113   enum State {
114     ST_INIT,                    // SRTP filter unused.
115     ST_SENTOFFER,               // Offer with SRTP parameters sent.
116     ST_RECEIVEDOFFER,           // Offer with SRTP parameters received.
117     ST_SENTPRANSWER_NO_CRYPTO,  // Sent provisional answer without crypto.
118     // Received provisional answer without crypto.
119     ST_RECEIVEDPRANSWER_NO_CRYPTO,
120     ST_ACTIVE,  // Offer and answer set.
121     // SRTP filter is active but new parameters are offered.
122     // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT.
123     ST_SENTUPDATEDOFFER,
124     // SRTP filter is active but new parameters are received.
125     // When the answer is set, the state transitions back to ST_ACTIVE.
126     ST_RECEIVEDUPDATEDOFFER,
127     // SRTP filter is active but the sent answer is only provisional.
128     // When the final answer is set, the state transitions to ST_ACTIVE or
129     // ST_INIT.
130     ST_SENTPRANSWER,
131     // SRTP filter is active but the received answer is only provisional.
132     // When the final answer is set, the state transitions to ST_ACTIVE or
133     // ST_INIT.
134     ST_RECEIVEDPRANSWER
135   };
136   State state_ = ST_INIT;
137   std::vector<CryptoParams> offer_params_;
138   CryptoParams applied_send_params_;
139   CryptoParams applied_recv_params_;
140   absl::optional<int> send_cipher_suite_;
141   absl::optional<int> recv_cipher_suite_;
142   rtc::ZeroOnFreeBuffer<uint8_t> send_key_;
143   rtc::ZeroOnFreeBuffer<uint8_t> recv_key_;
144 };
145 
146 }  // namespace cricket
147 
148 #endif  // PC_SRTP_FILTER_H_
149