| 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 |