15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/authentication_method.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/hmac.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/auth_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protocol {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthenticationMethod AuthenticationMethod::Invalid() {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AuthenticationMethod();
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthenticationMethod AuthenticationMethod::Spake2(HashFunction hash_function) {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AuthenticationMethod(SPAKE2, hash_function);
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)AuthenticationMethod AuthenticationMethod::Spake2Pair() {
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return AuthenticationMethod(SPAKE2_PAIR, HMAC_SHA256);
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AuthenticationMethod AuthenticationMethod::ThirdParty() {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AuthenticationMethod(THIRD_PARTY, NONE);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthenticationMethod AuthenticationMethod::FromString(
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& value) {
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value == "spake2_pair") {
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Spake2Pair();
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (value == "spake2_plain") {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Spake2(NONE);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (value == "spake2_hmac") {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Spake2(HMAC_SHA256);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (value == "third_party") {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ThirdParty();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AuthenticationMethod::Invalid();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AuthenticationMethod::ApplyHashFunction(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HashFunction hash_function,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& tag,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& shared_secret) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (hash_function) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NONE:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return shared_secret;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HMAC_SHA256: {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crypto::HMAC response(crypto::HMAC::SHA256);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!response.Init(tag)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(FATAL) << "HMAC::Init failed";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char out_bytes[kSharedSecretHashLength];
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!response.Sign(shared_secret, out_bytes, sizeof(out_bytes))) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(FATAL) << "HMAC::Sign failed";
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::string(out_bytes, out_bytes + sizeof(out_bytes));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shared_secret;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthenticationMethod::AuthenticationMethod()
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : type_(INVALID),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hash_function_(NONE) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AuthenticationMethod::AuthenticationMethod(MethodType type,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           HashFunction hash_function)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : type_(type),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hash_function_(hash_function) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(type_, INVALID);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthenticationMethod::HashFunction AuthenticationMethod::hash_function() const {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_valid());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hash_function_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string AuthenticationMethod::ToString() const {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_valid());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (type_) {
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case INVALID:
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case SPAKE2_PAIR:
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return "spake2_pair";
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case SPAKE2:
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switch (hash_function_) {
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case NONE:
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return "spake2_plain";
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case HMAC_SHA256:
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return "spake2_hmac";
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case THIRD_PARTY:
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return "third_party";
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return "invalid";
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AuthenticationMethod::operator ==(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AuthenticationMethod& other) const {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return type_ == other.type_ &&
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hash_function_ == other.hash_function_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SharedSecretHash::Parse(const std::string& as_string) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t separator = as_string.find(':');
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (separator == std::string::npos)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string function_name = as_string.substr(0, separator);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (function_name == "plain") {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash_function = AuthenticationMethod::NONE;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (function_name == "hmac") {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash_function = AuthenticationMethod::HMAC_SHA256;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::Base64Decode(as_string.substr(separator + 1), &value)) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protocol
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
153