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 12namespace remoting { 13namespace protocol { 14 15// static 16AuthenticationMethod AuthenticationMethod::Invalid() { 17 return AuthenticationMethod(); 18} 19 20// static 21AuthenticationMethod AuthenticationMethod::Spake2(HashFunction hash_function) { 22 return AuthenticationMethod(SPAKE2, hash_function); 23} 24 25// static 26AuthenticationMethod AuthenticationMethod::Spake2Pair() { 27 return AuthenticationMethod(SPAKE2_PAIR, HMAC_SHA256); 28} 29 30// static 31AuthenticationMethod AuthenticationMethod::ThirdParty() { 32 return AuthenticationMethod(THIRD_PARTY, NONE); 33} 34 35// static 36AuthenticationMethod 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 52std::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 80AuthenticationMethod::AuthenticationMethod() 81 : type_(INVALID), 82 hash_function_(NONE) { 83} 84 85AuthenticationMethod::AuthenticationMethod(MethodType type, 86 HashFunction hash_function) 87 : type_(type), 88 hash_function_(hash_function) { 89 DCHECK_NE(type_, INVALID); 90} 91 92AuthenticationMethod::HashFunction AuthenticationMethod::hash_function() const { 93 DCHECK(is_valid()); 94 return hash_function_; 95} 96 97const 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 124bool AuthenticationMethod::operator ==( 125 const AuthenticationMethod& other) const { 126 return type_ == other.type_ && 127 hash_function_ == other.hash_function_; 128} 129 130bool 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