Commit f3ec3b67 authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

Advertise and pair with long-term keys.

With this change, the caBLE authenticator will advertise with it's
long-term keys and (always) exchange pairing information when doing QR
handshakes. This removes the need to do a QR pairing for every
operation.

BUG=1002262

Change-Id: I1999e3de347f278a460f126c491d185d1cb18e95
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2101288
Commit-Queue: Adam Langley <agl@chromium.org>
Auto-Submit: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#750613}
parent 714facf4
......@@ -19,7 +19,6 @@ CRYPTO_EXPORT void RandBytes(void *bytes, size_t length);
// Fills |bytes| with cryptographically-secure random bits.
CRYPTO_EXPORT void RandBytes(base::span<uint8_t> bytes);
}
#endif // CRYPTO_RANDOM_H_
......@@ -320,8 +320,7 @@ HandshakeInitiator::ProcessResponse(base::span<const uint8_t> response) {
base::Optional<std::unique_ptr<Crypter>> RespondToHandshake(
base::span<const uint8_t, 32> psk_gen_key,
base::span<const uint8_t, 8> nonce,
base::span<const uint8_t, kCableEphemeralIdSize> expected_eid,
const NonceAndEID& nonce_and_eid,
const EC_KEY* identity,
const CableDiscoveryData* pairing_data,
base::span<const uint8_t> in,
......@@ -339,8 +338,8 @@ base::Optional<std::unique_ptr<Crypter>> RespondToHandshake(
return base::nullopt;
}
if (eid.size() != expected_eid.size() ||
memcmp(eid.data(), expected_eid.data(), eid.size()) != 0) {
if (eid.size() != nonce_and_eid.second.size() ||
memcmp(eid.data(), nonce_and_eid.second.data(), eid.size()) != 0) {
return base::nullopt;
}
......@@ -356,7 +355,7 @@ base::Optional<std::unique_ptr<Crypter>> RespondToHandshake(
std::array<uint8_t, 32> psk;
HKDF(psk.data(), psk.size(), EVP_sha256(), psk_gen_key.data(),
psk_gen_key.size(),
/*salt=*/nonce.data(), nonce.size(),
/*salt=*/nonce_and_eid.first.data(), nonce_and_eid.first.size(),
/*info=*/nullptr, 0);
noise.MixKeyAndHash(psk);
......
......@@ -21,6 +21,12 @@
namespace device {
namespace cablev2 {
// NonceAndEID contains both the random nonce chosen for an advert, as well as
// the EID that was generated from it.
typedef std::pair<std::array<uint8_t, device::kCableNonceSize>,
std::array<uint8_t, device::kCableEphemeralIdSize>>
NonceAndEID;
// kP256PointSize is the number of bytes in an X9.62 encoding of a P-256 point.
constexpr size_t kP256PointSize = 65;
......@@ -102,8 +108,7 @@ COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::unique_ptr<Crypter>> RespondToHandshake(
// See |HandshakeInitiator| comments about these first three arguments.
base::span<const uint8_t, 32> psk_gen_key,
base::span<const uint8_t, 8> nonce,
base::span<const uint8_t, kCableEphemeralIdSize> expected_eid,
const NonceAndEID& nonce_and_eid,
// identity, if not nullptr, specifies that this is a paired handshake and
// contains the long-term identity key for this authenticator.
const EC_KEY* identity,
......
......@@ -17,8 +17,8 @@ class CableV2HandshakeTest : public ::testing::Test {
public:
CableV2HandshakeTest() {
std::fill(psk_gen_key_.begin(), psk_gen_key_.end(), 0);
std::fill(nonce_.begin(), nonce_.end(), 1);
std::fill(eid_.begin(), eid_.end(), 2);
std::fill(nonce_and_eid_.first.begin(), nonce_and_eid_.first.end(), 1);
std::fill(nonce_and_eid_.second.begin(), nonce_and_eid_.second.end(), 2);
p256_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
const EC_GROUP* group = EC_KEY_get0_group(p256_key_.get());
......@@ -32,8 +32,7 @@ class CableV2HandshakeTest : public ::testing::Test {
protected:
std::array<uint8_t, 32> psk_gen_key_;
std::array<uint8_t, 8> nonce_;
std::array<uint8_t, kCableEphemeralIdSize> eid_;
NonceAndEID nonce_and_eid_;
bssl::UniquePtr<EC_KEY> p256_key_;
std::array<uint8_t, kP256PointSize> p256_public_key_;
};
......@@ -72,12 +71,13 @@ TEST_F(CableV2HandshakeTest, OneTimeQRHandshake) {
for (const bool use_correct_key : {false, true}) {
HandshakeInitiator initiator(
use_correct_key ? psk_gen_key_ : wrong_psk_gen_key, nonce_, eid_,
use_correct_key ? psk_gen_key_ : wrong_psk_gen_key,
nonce_and_eid_.first, nonce_and_eid_.second,
/*peer_identity=*/base::nullopt);
std::vector<uint8_t> message = initiator.BuildInitialMessage();
std::vector<uint8_t> response;
base::Optional<std::unique_ptr<Crypter>> response_crypter(
RespondToHandshake(psk_gen_key_, nonce_, eid_, /*identity=*/nullptr,
RespondToHandshake(psk_gen_key_, nonce_and_eid_, /*identity=*/nullptr,
/*pairing_data=*/nullptr, message, &response));
ASSERT_EQ(response_crypter.has_value(), use_correct_key);
if (!use_correct_key) {
......@@ -103,12 +103,13 @@ TEST_F(CableV2HandshakeTest, PairingQRHandshake) {
pairing.v2->peer_identity = p256_public_key_;
pairing.v2->peer_name = "Unittest";
HandshakeInitiator initiator(psk_gen_key_, nonce_, eid_,
HandshakeInitiator initiator(psk_gen_key_, nonce_and_eid_.first,
nonce_and_eid_.second,
/*peer_identity=*/base::nullopt);
std::vector<uint8_t> message = initiator.BuildInitialMessage();
std::vector<uint8_t> response;
base::Optional<std::unique_ptr<Crypter>> response_crypter(
RespondToHandshake(psk_gen_key_, nonce_, eid_, /*identity=*/nullptr,
RespondToHandshake(psk_gen_key_, nonce_and_eid_, /*identity=*/nullptr,
&pairing, message, &response));
ASSERT_TRUE(response_crypter.has_value());
base::Optional<std::pair<std::unique_ptr<Crypter>,
......@@ -136,11 +137,12 @@ TEST_F(CableV2HandshakeTest, PairedHandshake) {
for (const bool use_correct_key : {false, true}) {
SCOPED_TRACE(use_correct_key);
HandshakeInitiator initiator(psk_gen_key_, nonce_, eid_, p256_public_key_);
HandshakeInitiator initiator(psk_gen_key_, nonce_and_eid_.first,
nonce_and_eid_.second, p256_public_key_);
std::vector<uint8_t> message = initiator.BuildInitialMessage();
std::vector<uint8_t> response;
base::Optional<std::unique_ptr<Crypter>> response_crypter(
RespondToHandshake(psk_gen_key_, nonce_, eid_,
RespondToHandshake(psk_gen_key_, nonce_and_eid_,
use_correct_key ? p256_key_.get() : wrong_key.get(),
/*pairing=*/nullptr, message, &response));
ASSERT_EQ(response_crypter.has_value(), use_correct_key);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment