17c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Copyright 2012 Google Inc. All Rights Reserved.
27c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
37c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Licensed under the Apache License, Version 2.0 (the "License");
47c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// you may not use this file except in compliance with the License.
57c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// You may obtain a copy of the License at
67c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
77c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//     http://www.apache.org/licenses/LICENSE-2.0
87c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
97c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Unless required by applicable law or agreed to in writing, software
107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// distributed under the License is distributed on an "AS IS" BASIS,
117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// See the License for the specific language governing permissions and
137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// limitations under the License.
147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include "polo/pairing/pairingsession.h"
167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include <glog/logging.h>
187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include "polo/encoding/hexadecimalencoder.h"
197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include "polo/util/poloutil.h"
207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetnamespace polo {
227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetnamespace pairing {
237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
247c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetPairingSession::PairingSession(wire::PoloWireAdapter* wire,
257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                               PairingContext* context,
267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                               PoloChallengeResponse* challenge)
277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    : state_(kUninitialized),
287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      wire_(wire),
297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      context_(context),
307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      challenge_(challenge),
317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      configuration_(NULL),
327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      encoder_(NULL),
337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      nonce_(NULL),
347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      secret_(NULL) {
357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  wire_->set_listener(this);
367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  local_options_.set_protocol_role_preference(context->is_server() ?
387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      message::OptionsMessage::kDisplayDevice
397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      : message::OptionsMessage::kInputDevice);
407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
427c9978567a202d6aa98beac5da5e1b3b34792862Jerome PoichetPairingSession::~PairingSession() {
437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (configuration_) {
447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete configuration_;
457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (encoder_) {
487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete encoder_;
497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (nonce_) {
527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete nonce_;
537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (secret_) {
567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete secret_;
577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::AddInputEncoding(
617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const encoding::EncodingOption& encoding) {
627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (state_ != kUninitialized) {
637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Attempt to add input encoding to active session";
647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!IsValidEncodingOption(encoding)) {
687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Invalid input encoding: " << encoding.ToString();
697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  local_options_.AddInputEncoding(encoding);
737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::AddOutputEncoding(
767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const encoding::EncodingOption& encoding) {
777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (state_ != kUninitialized) {
787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Attempt to add output encoding to active session";
797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!IsValidEncodingOption(encoding)) {
837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Invalid output encoding: " << encoding.ToString();
847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  local_options_.AddOutputEncoding(encoding);
887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetbool PairingSession::SetSecret(const Gamma& secret) {
917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  secret_ = new Gamma(secret);
927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!IsInputDevice() || state_ != kWaitingForSecret) {
947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Invalid state: unexpected secret";
957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!challenge().CheckGamma(secret)) {
997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Secret failed local check";
1007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
1017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  nonce_ = challenge().ExtractNonce(secret);
1047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!nonce_) {
1057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Failed to extract nonce";
1067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
1077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  const Alpha* gen_alpha = challenge().GetAlpha(*nonce_);
1107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!gen_alpha) {
1117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Failed to get alpha";
1127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
1137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  message::SecretMessage secret_message(*gen_alpha);
1167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  delete gen_alpha;
1177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  wire_->SendSecretMessage(secret_message);
1197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  LOG(INFO) << "Waiting for SecretAck...";
1217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  wire_->GetNextMessage();
1227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return true;
1247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::DoPair(PairingListener *listener) {
1277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_ = listener;
1287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnSessionCreated();
1297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (context_->is_server()) {
1317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(INFO) << "Pairing started (SERVER mode)";
1327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  } else {
1337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(INFO) << "Pairing started (CLIENT mode)";
1347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  LOG(INFO) << "Local options: " << local_options_.ToString();
1367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  set_state(kInitializing);
1387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  DoInitializationPhase();
1397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::DoPairingPhase() {
1427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (IsInputDevice()) {
1437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    DoInputPairing();
1447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  } else {
1457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    DoOutputPairing();
1467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::DoInputPairing() {
1507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  set_state(kWaitingForSecret);
1517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnPerformInputDeviceRole();
1527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::DoOutputPairing() {
1557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  size_t nonce_length = configuration_->encoding().symbol_length() / 2;
1567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  size_t bytes_needed = nonce_length / encoder_->symbols_per_byte();
1577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  uint8_t* random = util::PoloUtil::GenerateRandomBytes(bytes_needed);
1597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  nonce_ = new Nonce(random, random + bytes_needed);
1607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  delete[] random;
1617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  const Gamma* gamma = challenge().GetGamma(*nonce_);
1637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!gamma) {
1647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Failed to get gamma";
1657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    wire()->SendErrorMessage(kErrorProtocol);
1667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    listener()->OnError(kErrorProtocol);
1677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
1687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnPerformOutputDeviceRole(*gamma);
1717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  delete gamma;
1727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  set_state(kWaitingForSecret);
1747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  LOG(INFO) << "Waiting for Secret...";
1767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  wire_->GetNextMessage();
1777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::set_state(ProtocolState state) {
1807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  LOG(INFO) << "New state: " << state;
1817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  state_ = state;
1827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
1837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetbool PairingSession::SetConfiguration(
1857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const message::ConfigurationMessage& message) {
1867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  const encoding::EncodingOption& encoding = message.encoding();
1877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!IsValidEncodingOption(encoding)) {
1897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Invalid configuration: " << encoding.ToString();
1907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
1917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (encoder_) {
1947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete encoder_;
1957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    encoder_ = NULL;
1967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
1977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
1987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  switch (encoding.encoding_type()) {
1997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    case encoding::EncodingOption::kHexadecimal:
2007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      encoder_ = new encoding::HexadecimalEncoder();
2017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      break;
2027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    default:
2037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      LOG(ERROR) << "Unsupported encoding type: "
2047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet          << encoding.encoding_type();
2057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      return false;
2067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (configuration_) {
2097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete configuration_;
2107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  configuration_ = new message::ConfigurationMessage(message.encoding(),
2127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                                                     message.client_role());
2137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return true;
2147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
2157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::OnSecretMessage(const message::SecretMessage& message) {
2177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (state() != kWaitingForSecret) {
2187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Invalid state: unexpected secret message";
2197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    wire()->SendErrorMessage(kErrorProtocol);
2207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    listener()->OnError(kErrorProtocol);
2217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
2227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!VerifySecret(message.secret())) {
2257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    wire()->SendErrorMessage(kErrorInvalidChallengeResponse);
2267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    listener_->OnError(kErrorInvalidChallengeResponse);
2277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
2287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  const Alpha* alpha = challenge().GetAlpha(*nonce_);
2317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!alpha) {
2327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Failed to get alpha";
2337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    wire()->SendErrorMessage(kErrorProtocol);
2347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    listener()->OnError(kErrorProtocol);
2357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
2367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  message::SecretAckMessage ack(*alpha);
2397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  delete alpha;
2407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  wire_->SendSecretAckMessage(ack);
2427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnPairingSuccess();
2447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
2457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::OnSecretAckMessage(
2477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const message::SecretAckMessage& message) {
2487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (kVerifySecretAck && !VerifySecret(message.secret())) {
2497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    wire()->SendErrorMessage(kErrorInvalidChallengeResponse);
2507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    listener_->OnError(kErrorInvalidChallengeResponse);
2517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return;
2527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnPairingSuccess();
2557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
2567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetvoid PairingSession::OnError(pairing::PoloError error) {
2587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  listener_->OnError(error);
2597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
2607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetbool PairingSession::VerifySecret(const Alpha& secret) const {
2627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!nonce_) {
2637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Nonce not set";
2647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
2657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  const Alpha* gen_alpha = challenge().GetAlpha(*nonce_);
2687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!gen_alpha) {
2697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Failed to get alpha";
2707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return false;
2717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  bool valid = (secret == *gen_alpha);
2747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!valid) {
2767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    LOG(ERROR) << "Inband secret did not match. Expected ["
2777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet        << util::PoloUtil::BytesToHexString(&(*gen_alpha)[0], gen_alpha->size())
2787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet        << "], got ["
2797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet        << util::PoloUtil::BytesToHexString(&secret[0], secret.size())
2807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet        << "]";
2817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  delete gen_alpha;
2847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return valid;
2857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
2867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetmessage::OptionsMessage::ProtocolRole PairingSession::GetLocalRole() const {
2887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (!configuration_) {
2897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return message::OptionsMessage::kUnknown;
2907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
2917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
2927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (context_->is_client()) {
2937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return configuration_->client_role();
2947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  } else {
2957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return configuration_->client_role() ==
2967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet        message::OptionsMessage::kDisplayDevice ?
2977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet            message::OptionsMessage::kInputDevice
2987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet            : message::OptionsMessage::kDisplayDevice;
2997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
3007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
3017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
3027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetbool PairingSession::IsInputDevice() const {
3037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return GetLocalRole() == message::OptionsMessage::kInputDevice;
3047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
3057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
3067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetbool PairingSession::IsValidEncodingOption(
3077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const encoding::EncodingOption& option) const {
3087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Legal values of GAMMALEN must be an even number of at least 2 bytes.
3097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return option.encoding_type() != encoding::EncodingOption::kUnknown
3107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      && (option.symbol_length() % 2 == 0)
3117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet      && (option.symbol_length() >= 2);
3127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
3137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
3147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}  // namespace pairing
3157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}  // namespace polo
316