OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This code implements SPAKE2, a varient of EKE: | 5 // This code implements SPAKE2, a variant of EKE: |
6 // http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04 | 6 // http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04 |
7 | 7 |
8 #include <crypto/p224_spake.h> | 8 #include <crypto/p224_spake.h> |
9 | 9 |
10 #include <base/logging.h> | 10 #include <base/logging.h> |
11 #include <base/rand_util.h> | 11 #include <base/rand_util.h> |
12 #include <crypto/p224.h> | 12 #include <crypto/p224.h> |
13 #include <crypto/secure_util.h> | 13 #include <crypto/secure_util.h> |
14 | 14 |
15 namespace { | 15 namespace { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 {197567436, 51226044, 60372156, 175772188, | 89 {197567436, 51226044, 60372156, 175772188, |
90 42075930, 8083165, 160827401, 65097570}, | 90 42075930, 8083165, 160827401, 65097570}, |
91 {1, 0, 0, 0, 0, 0, 0}, | 91 {1, 0, 0, 0, 0, 0, 0}, |
92 }; | 92 }; |
93 | 93 |
94 } // anonymous namespace | 94 } // anonymous namespace |
95 | 95 |
96 namespace crypto { | 96 namespace crypto { |
97 | 97 |
98 P224EncryptedKeyExchange::P224EncryptedKeyExchange( | 98 P224EncryptedKeyExchange::P224EncryptedKeyExchange( |
99 PeerType peer_type, | 99 PeerType peer_type, const base::StringPiece& password) |
100 const base::StringPiece& password, | |
101 const base::StringPiece& session) | |
102 : state_(kStateInitial), | 100 : state_(kStateInitial), |
103 is_server_(peer_type == kPeerTypeServer) { | 101 is_server_(peer_type == kPeerTypeServer) { |
104 // x_ is a random scalar. | 102 // x_ is a random scalar. |
105 base::RandBytes(x_, sizeof(x_)); | 103 base::RandBytes(x_, sizeof(x_)); |
106 | 104 |
107 // X = g**x_ | 105 // X = g**x_ |
108 p224::Point X; | 106 p224::Point X; |
109 p224::ScalarBaseMult(x_, &X); | 107 p224::ScalarBaseMult(x_, &X); |
110 | 108 |
111 // The "password" in the SPAKE2 protocol is | 109 // Calculate |password| hash to get SPAKE password value. |
112 // SHA256(P(password) + P(session)) where P is function that prepends a | 110 SHA256HashString(std::string(password.data(), password.length()), |
113 // uint32, big-endian length prefix. | 111 pw_, sizeof(pw_)); |
114 uint8 password_length[4], session_length[4]; | |
115 password_length[0] = password.size() >> 24; | |
116 password_length[1] = password.size() >> 16; | |
117 password_length[2] = password.size() >> 8; | |
118 password_length[3] = password.size(); | |
119 session_length[0] = session.size() >> 24; | |
120 session_length[1] = session.size() >> 16; | |
121 session_length[2] = session.size() >> 8; | |
122 session_length[3] = session.size(); | |
123 SHA256HashString(std::string(reinterpret_cast<const char *>(password_length), | |
124 sizeof(password_length)) + | |
125 password.as_string() + | |
126 std::string(reinterpret_cast<const char *>(session_length), | |
127 sizeof(session_length)) + | |
128 session.as_string(), | |
129 pw_, | |
130 sizeof(pw_)); | |
131 | 112 |
132 // The client masks the Diffie-Hellman value, X, by adding M**pw and the | 113 // The client masks the Diffie-Hellman value, X, by adding M**pw and the |
133 // server uses N**pw. | 114 // server uses N**pw. |
134 p224::Point MNpw; | 115 p224::Point MNpw; |
135 p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw); | 116 p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw); |
136 | 117 |
137 // X* = X + (N|M)**pw | 118 // X* = X + (N|M)**pw |
138 p224::Point Xstar; | 119 p224::Point Xstar; |
139 p224::Add(X, MNpw, &Xstar); | 120 p224::Add(X, MNpw, &Xstar); |
140 | 121 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw); | 174 p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw); |
194 p224::Negate(MNpw, &minus_MNpw); | 175 p224::Negate(MNpw, &minus_MNpw); |
195 | 176 |
196 // Y = Y* - (N|M)**pw | 177 // Y = Y* - (N|M)**pw |
197 p224::Add(Ystar, minus_MNpw, &Y); | 178 p224::Add(Ystar, minus_MNpw, &Y); |
198 | 179 |
199 // K = Y**x_ | 180 // K = Y**x_ |
200 p224::ScalarMult(Y, x_, &k); | 181 p224::ScalarMult(Y, x_, &k); |
201 | 182 |
202 // If everything worked out, then K is the same for both parties. | 183 // If everything worked out, then K is the same for both parties. |
203 std::string k_str = k.ToString(); | 184 key_ = k.ToString(); |
204 | 185 |
205 std::string client_masked_dh, server_masked_dh; | 186 std::string client_masked_dh, server_masked_dh; |
206 if (is_server_) { | 187 if (is_server_) { |
207 client_masked_dh = message.as_string(); | 188 client_masked_dh = message.as_string(); |
208 server_masked_dh = next_message_; | 189 server_masked_dh = next_message_; |
209 } else { | 190 } else { |
210 client_masked_dh = next_message_; | 191 client_masked_dh = next_message_; |
211 server_masked_dh = message.as_string(); | 192 server_masked_dh = message.as_string(); |
212 } | 193 } |
213 | 194 |
214 // Now we calculate the hashes that each side will use to prove to the other | 195 // Now we calculate the hashes that each side will use to prove to the other |
215 // that they derived the correct value for K. | 196 // that they derived the correct value for K. |
216 uint8 client_hash[kSHA256Length], server_hash[kSHA256Length]; | 197 uint8 client_hash[kSHA256Length], server_hash[kSHA256Length]; |
217 CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, k_str, | 198 CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_, |
218 client_hash); | 199 client_hash); |
219 CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, k_str, | 200 CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_, |
220 server_hash); | 201 server_hash); |
221 | 202 |
222 const uint8* my_hash = is_server_ ? server_hash : client_hash; | 203 const uint8* my_hash = is_server_ ? server_hash : client_hash; |
223 const uint8* their_hash = is_server_ ? client_hash : server_hash; | 204 const uint8* their_hash = is_server_ ? client_hash : server_hash; |
224 | 205 |
225 next_message_ = | 206 next_message_ = |
226 std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length); | 207 std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length); |
227 memcpy(expected_authenticator_, their_hash, kSHA256Length); | 208 memcpy(expected_authenticator_, their_hash, kSHA256Length); |
228 state_ = kStateSendHash; | 209 state_ = kStateSendHash; |
229 return kResultPending; | 210 return kResultPending; |
(...skipping 19 matching lines...) Expand all Loading... |
249 std::string(reinterpret_cast<const char *>(pw_), sizeof(pw_)); | 230 std::string(reinterpret_cast<const char *>(pw_), sizeof(pw_)); |
250 hash_contents += k; | 231 hash_contents += k; |
251 | 232 |
252 SHA256HashString(hash_contents, out_digest, kSHA256Length); | 233 SHA256HashString(hash_contents, out_digest, kSHA256Length); |
253 } | 234 } |
254 | 235 |
255 const std::string& P224EncryptedKeyExchange::error() const { | 236 const std::string& P224EncryptedKeyExchange::error() const { |
256 return error_; | 237 return error_; |
257 } | 238 } |
258 | 239 |
| 240 const std::string& P224EncryptedKeyExchange::GetKey() { |
| 241 DCHECK_EQ(state_, kStateDone); |
| 242 return key_; |
| 243 } |
| 244 |
259 } // namespace crypto | 245 } // namespace crypto |
OLD | NEW |