• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Invalid()16 AuthenticationMethod AuthenticationMethod::Invalid() {
17   return AuthenticationMethod();
18 }
19 
20 // static
Spake2(HashFunction hash_function)21 AuthenticationMethod AuthenticationMethod::Spake2(HashFunction hash_function) {
22   return AuthenticationMethod(SPAKE2, hash_function);
23 }
24 
25 // static
Spake2Pair()26 AuthenticationMethod AuthenticationMethod::Spake2Pair() {
27   return AuthenticationMethod(SPAKE2_PAIR, HMAC_SHA256);
28 }
29 
30 // static
ThirdParty()31 AuthenticationMethod AuthenticationMethod::ThirdParty() {
32   return AuthenticationMethod(THIRD_PARTY, NONE);
33 }
34 
35 // static
FromString(const std::string & value)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
ApplyHashFunction(HashFunction hash_function,const std::string & tag,const std::string & shared_secret)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 
AuthenticationMethod()80 AuthenticationMethod::AuthenticationMethod()
81     : type_(INVALID),
82       hash_function_(NONE) {
83 }
84 
AuthenticationMethod(MethodType type,HashFunction hash_function)85 AuthenticationMethod::AuthenticationMethod(MethodType type,
86                                            HashFunction hash_function)
87     : type_(type),
88       hash_function_(hash_function) {
89   DCHECK_NE(type_, INVALID);
90 }
91 
hash_function() const92 AuthenticationMethod::HashFunction AuthenticationMethod::hash_function() const {
93   DCHECK(is_valid());
94   return hash_function_;
95 }
96 
ToString() const97 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 
operator ==(const AuthenticationMethod & other) const124 bool AuthenticationMethod::operator ==(
125     const AuthenticationMethod& other) const {
126   return type_ == other.type_ &&
127       hash_function_ == other.hash_function_;
128 }
129 
Parse(const std::string & as_string)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