1 // Copyright 2012 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef POLO_PAIRING_PAIRINGSESSION_H_ 16 #define POLO_PAIRING_PAIRINGSESSION_H_ 17 18 #include <string> 19 20 #include "polo/encoding/secretencoder.h" 21 #include "polo/pairing/pairingcontext.h" 22 #include "polo/pairing/pairinglistener.h" 23 #include "polo/pairing/message/messagelistener.h" 24 #include "polo/wire/polowireadapter.h" 25 26 namespace polo { 27 namespace pairing { 28 29 class PairingSession : public message::MessageListener { 30 public: 31 // The state of the Polo pairing session. 32 enum ProtocolState { 33 // The Polo session has not yet been initialized. 34 kUninitialized, 35 36 // The session is initializing. 37 kInitializing, 38 39 // The configuration options are being negotiated with the peer. 40 kConfiguring, 41 42 // The local device is being paired with the peer. 43 kPairing, 44 45 // Waiting for the secret challenge messsage or response from the peer. 46 kWaitingForSecret, 47 48 // The pairing completely successfully. 49 kSuccess, 50 51 // There was an error pairing. 52 kFailure, 53 }; 54 55 // Creates a new pairing session. The given wire adapter will be used for 56 // sending and receiving protocol messages. The given context contains the 57 // local and peer SSL certificates from the establishment of the SSL 58 // connection. No ownership is taken of the given pointers. 59 PairingSession(wire::PoloWireAdapter* wire, 60 PairingContext* context, 61 PoloChallengeResponse* challenge); 62 63 virtual ~PairingSession(); 64 65 // Adds a supported input encoding. This must be called before the session is 66 // started. 67 void AddInputEncoding(const encoding::EncodingOption& encoding); 68 69 // Adds a supported output encoding. This must be called before the session is 70 // started. 71 void AddOutputEncoding(const encoding::EncodingOption& encoding); 72 73 // Starts the pairing session. The given listener will be invoked during the 74 // pairing session. 75 void DoPair(PairingListener* listener); 76 77 // Sets the secret entered by the user. This must be invoked when, and only 78 // when, OnPerformInputDeviceRole has been called on the listener. 79 // @return Whether the secret was successfully set. If the given secret is 80 // invalid or fails the local check, this will return false. 81 bool SetSecret(const Gamma& secret); 82 83 // Gets the encoder used for encoding and decoding the secret challenge. This 84 // should only be invoked after OnPerformInputDeviceRole or 85 // OnPerformOutputDeviceRole has been called on the listener. encoder()86 const encoding::SecretEncoder* encoder() const { return encoder_; } 87 88 protected: 89 // Starts the pairing process. 90 void DoPairingPhase(); 91 92 // Performs the initialization phase of the pairing process. 93 virtual void DoInitializationPhase() = 0; 94 95 // Performs the configuration phase of the pairing process. 96 virtual void DoConfigurationPhase() = 0; 97 98 // Sets the configuration once it has been negotiated. This must be called 99 // by implementations during the configuration phase. Returns true if the 100 // configuration was valid and false otherwise. If the configuration was 101 // invalid the pairing process can not continue. 102 bool SetConfiguration(const message::ConfigurationMessage& message); 103 configuration()104 const message::ConfigurationMessage* configuration() const { 105 return configuration_; 106 } 107 108 // @override 109 virtual void OnSecretMessage(const message::SecretMessage& message); 110 111 // @override 112 virtual void OnSecretAckMessage(const message::SecretAckMessage& message); 113 114 // @override 115 virtual void OnError(pairing::PoloError error); 116 117 // Determines whether this device is acting as the input device. 118 bool IsInputDevice() const; 119 120 // Gets the local device role or kUnknown if the configuration has not been 121 // established yet. 122 message::OptionsMessage::ProtocolRole GetLocalRole() const; 123 124 // Set the current protocol state. 125 void set_state(ProtocolState state); 126 127 // Gets the current state of the pairing process. state()128 ProtocolState state() const { return state_; } 129 130 // Sets the service name. set_service_name(const std::string & service_name)131 void set_service_name(const std::string& service_name) { 132 service_name_.assign(service_name); 133 } 134 135 // Sets the peer name. set_peer_name(const std::string & peer_name)136 void set_peer_name(const std::string& peer_name) { 137 peer_name_.assign(peer_name); 138 } 139 140 // Gets the service name. service_name()141 std::string service_name() const { return service_name_; } 142 143 // Gets the peer name. peer_name()144 std::string peer_name() const { return peer_name_; } 145 146 // Gets the local options. local_options()147 const message::OptionsMessage& local_options() const { 148 return local_options_; 149 } 150 151 // Gets the wire adapter used to send and receive Polo messages. wire()152 wire::PoloWireAdapter* wire() const { return wire_; } 153 154 // Gets the listener that will be notified of pairing events. listener()155 PairingListener* listener() const { return listener_; } 156 157 // Gets the challenge response. challenge()158 const PoloChallengeResponse& challenge() const { return *challenge_; } 159 160 // Gets the nonce value. nonce()161 const Nonce* nonce() const { return nonce_; } 162 163 private: 164 // Performs pairing as the input device. 165 void DoInputPairing(); 166 167 // Performs pairing as the output device. 168 void DoOutputPairing(); 169 170 // Determines whether the given encoding option is valid. 171 bool IsValidEncodingOption(const encoding::EncodingOption& option) const; 172 173 // Verifies that the given secret is correct. 174 bool VerifySecret(const Alpha& secret) const; 175 176 enum { 177 // Whether to verify the secret ack. This is not currently required since 178 // the ack means the peer already verified the secret. 179 kVerifySecretAck = false, 180 181 // The time to wait for a secret. 182 kSecretPollTimeoutMs = 500 183 }; 184 185 ProtocolState state_; 186 wire::PoloWireAdapter* wire_; 187 PairingContext* context_; 188 message::OptionsMessage local_options_; 189 PoloChallengeResponse* challenge_; 190 PairingListener* listener_; 191 message::ConfigurationMessage* configuration_; 192 encoding::SecretEncoder* encoder_; 193 Nonce* nonce_; 194 Gamma* secret_; 195 std::string service_name_; 196 std::string peer_name_; 197 }; 198 199 } // namespace pairing 200 } // namespace polo 201 202 #endif // POLO_PAIRING_PAIRINGSESSION_H_ 203