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