This source file includes following definitions.
- is_server_
- GetMessage
- ProcessMessage
- CalculateHash
- error
- GetKey
#include <crypto/p224_spake.h>
#include <base/logging.h>
#include <crypto/p224.h>
#include <crypto/random.h>
#include <crypto/secure_util.h>
namespace {
const crypto::p224::Point kM = {
{174237515, 77186811, 235213682, 33849492,
33188520, 48266885, 177021753, 81038478},
{104523827, 245682244, 266509668, 236196369,
28372046, 145351378, 198520366, 113345994},
{1, 0, 0, 0, 0, 0, 0},
};
const crypto::p224::Point kN = {
{136176322, 263523628, 251628795, 229292285,
5034302, 185981975, 171998428, 11653062},
{197567436, 51226044, 60372156, 175772188,
42075930, 8083165, 160827401, 65097570},
{1, 0, 0, 0, 0, 0, 0},
};
}
namespace crypto {
P224EncryptedKeyExchange::P224EncryptedKeyExchange(
PeerType peer_type, const base::StringPiece& password)
: state_(kStateInitial),
is_server_(peer_type == kPeerTypeServer) {
memset(&x_, 0, sizeof(x_));
memset(&expected_authenticator_, 0, sizeof(expected_authenticator_));
RandBytes(x_, sizeof(x_));
p224::Point X;
p224::ScalarBaseMult(x_, &X);
SHA256HashString(std::string(password.data(), password.length()),
pw_, sizeof(pw_));
p224::Point MNpw;
p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw);
p224::Point Xstar;
p224::Add(X, MNpw, &Xstar);
next_message_ = Xstar.ToString();
}
const std::string& P224EncryptedKeyExchange::GetMessage() {
if (state_ == kStateInitial) {
state_ = kStateRecvDH;
return next_message_;
} else if (state_ == kStateSendHash) {
state_ = kStateRecvHash;
return next_message_;
}
LOG(FATAL) << "P224EncryptedKeyExchange::GetMessage called in"
" bad state " << state_;
next_message_ = "";
return next_message_;
}
P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage(
const base::StringPiece& message) {
if (state_ == kStateRecvHash) {
if (message.size() != sizeof(expected_authenticator_)) {
error_ = "peer's hash had an incorrect size";
return kResultFailed;
}
if (!SecureMemEqual(message.data(), expected_authenticator_,
message.size())) {
error_ = "peer's hash had incorrect value";
return kResultFailed;
}
state_ = kStateDone;
return kResultSuccess;
}
if (state_ != kStateRecvDH) {
LOG(FATAL) << "P224EncryptedKeyExchange::ProcessMessage called in"
" bad state " << state_;
error_ = "internal error";
return kResultFailed;
}
p224::Point Ystar;
if (!Ystar.SetFromString(message)) {
error_ = "failed to parse peer's masked Diffie-Hellman value";
return kResultFailed;
}
p224::Point MNpw, minus_MNpw, Y, k;
p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw);
p224::Negate(MNpw, &minus_MNpw);
p224::Add(Ystar, minus_MNpw, &Y);
p224::ScalarMult(Y, x_, &k);
key_ = k.ToString();
std::string client_masked_dh, server_masked_dh;
if (is_server_) {
client_masked_dh = message.as_string();
server_masked_dh = next_message_;
} else {
client_masked_dh = next_message_;
server_masked_dh = message.as_string();
}
uint8 client_hash[kSHA256Length], server_hash[kSHA256Length];
CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_,
client_hash);
CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_,
server_hash);
const uint8* my_hash = is_server_ ? server_hash : client_hash;
const uint8* their_hash = is_server_ ? client_hash : server_hash;
next_message_ =
std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length);
memcpy(expected_authenticator_, their_hash, kSHA256Length);
state_ = kStateSendHash;
return kResultPending;
}
void P224EncryptedKeyExchange::CalculateHash(
PeerType peer_type,
const std::string& client_masked_dh,
const std::string& server_masked_dh,
const std::string& k,
uint8* out_digest) {
std::string hash_contents;
if (peer_type == kPeerTypeServer) {
hash_contents = "server";
} else {
hash_contents = "client";
}
hash_contents += client_masked_dh;
hash_contents += server_masked_dh;
hash_contents +=
std::string(reinterpret_cast<const char *>(pw_), sizeof(pw_));
hash_contents += k;
SHA256HashString(hash_contents, out_digest, kSHA256Length);
}
const std::string& P224EncryptedKeyExchange::error() const {
return error_;
}
const std::string& P224EncryptedKeyExchange::GetKey() {
DCHECK_EQ(state_, kStateDone);
return key_;
}
}