Home | History | Annotate | Download | only in protocol
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/protocol/authentication_method.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/logging.h"
      9 #include "crypto/hmac.h"
     10 #include "remoting/protocol/auth_util.h"
     11 
     12 namespace remoting {
     13 namespace protocol {
     14 
     15 // static
     16 AuthenticationMethod AuthenticationMethod::Invalid() {
     17   return AuthenticationMethod();
     18 }
     19 
     20 // static
     21 AuthenticationMethod AuthenticationMethod::Spake2(HashFunction hash_function) {
     22   return AuthenticationMethod(SPAKE2, hash_function);
     23 }
     24 
     25 // static
     26 AuthenticationMethod AuthenticationMethod::Spake2Pair() {
     27   return AuthenticationMethod(SPAKE2_PAIR, HMAC_SHA256);
     28 }
     29 
     30 // static
     31 AuthenticationMethod AuthenticationMethod::ThirdParty() {
     32   return AuthenticationMethod(THIRD_PARTY, NONE);
     33 }
     34 
     35 // static
     36 AuthenticationMethod AuthenticationMethod::FromString(
     37     const std::string& value) {
     38   if (value == "spake2_pair") {
     39     return Spake2Pair();
     40   } else if (value == "spake2_plain") {
     41     return Spake2(NONE);
     42   } else if (value == "spake2_hmac") {
     43     return Spake2(HMAC_SHA256);
     44   } else if (value == "third_party") {
     45     return ThirdParty();
     46   } else {
     47     return AuthenticationMethod::Invalid();
     48   }
     49 }
     50 
     51 // static
     52 std::string AuthenticationMethod::ApplyHashFunction(
     53     HashFunction hash_function,
     54     const std::string& tag,
     55     const std::string& shared_secret) {
     56   switch (hash_function) {
     57     case NONE:
     58       return shared_secret;
     59       break;
     60 
     61     case HMAC_SHA256: {
     62       crypto::HMAC response(crypto::HMAC::SHA256);
     63       if (!response.Init(tag)) {
     64         LOG(FATAL) << "HMAC::Init failed";
     65       }
     66 
     67       unsigned char out_bytes[kSharedSecretHashLength];
     68       if (!response.Sign(shared_secret, out_bytes, sizeof(out_bytes))) {
     69         LOG(FATAL) << "HMAC::Sign failed";
     70       }
     71 
     72       return std::string(out_bytes, out_bytes + sizeof(out_bytes));
     73     }
     74   }
     75 
     76   NOTREACHED();
     77   return shared_secret;
     78 }
     79 
     80 AuthenticationMethod::AuthenticationMethod()
     81     : type_(INVALID),
     82       hash_function_(NONE) {
     83 }
     84 
     85 AuthenticationMethod::AuthenticationMethod(MethodType type,
     86                                            HashFunction hash_function)
     87     : type_(type),
     88       hash_function_(hash_function) {
     89   DCHECK_NE(type_, INVALID);
     90 }
     91 
     92 AuthenticationMethod::HashFunction AuthenticationMethod::hash_function() const {
     93   DCHECK(is_valid());
     94   return hash_function_;
     95 }
     96 
     97 const std::string AuthenticationMethod::ToString() const {
     98   DCHECK(is_valid());
     99 
    100   switch (type_) {
    101     case INVALID:
    102       NOTREACHED();
    103       break;
    104 
    105     case SPAKE2_PAIR:
    106       return "spake2_pair";
    107 
    108     case SPAKE2:
    109       switch (hash_function_) {
    110         case NONE:
    111           return "spake2_plain";
    112         case HMAC_SHA256:
    113           return "spake2_hmac";
    114       }
    115       break;
    116 
    117     case THIRD_PARTY:
    118       return "third_party";
    119   }
    120 
    121   return "invalid";
    122 }
    123 
    124 bool AuthenticationMethod::operator ==(
    125     const AuthenticationMethod& other) const {
    126   return type_ == other.type_ &&
    127       hash_function_ == other.hash_function_;
    128 }
    129 
    130 bool SharedSecretHash::Parse(const std::string& as_string) {
    131   size_t separator = as_string.find(':');
    132   if (separator == std::string::npos)
    133     return false;
    134 
    135   std::string function_name = as_string.substr(0, separator);
    136   if (function_name == "plain") {
    137     hash_function = AuthenticationMethod::NONE;
    138   } else if (function_name == "hmac") {
    139     hash_function = AuthenticationMethod::HMAC_SHA256;
    140   } else {
    141     return false;
    142   }
    143 
    144   if (!base::Base64Decode(as_string.substr(separator + 1), &value)) {
    145     return false;
    146   }
    147 
    148   return true;
    149 }
    150 
    151 }  // namespace protocol
    152 }  // namespace remoting
    153