| // Copyright 2017 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef HAMMERD_PAIR_UTILS_H_ |
| #define HAMMERD_PAIR_UTILS_H_ |
| |
| #include <base/macros.h> |
| #include <gtest/gtest_prod.h> |
| |
| #include "hammerd/curve25519.h" |
| #include "hammerd/dbus_wrapper.h" |
| #include "hammerd/update_fw.h" |
| |
| namespace hammerd { |
| |
| // The length of the HMAC nonce |
| constexpr size_t kHMACNonceLength = 16; |
| // The truncated length of the HMAC authenticator |
| constexpr size_t kHMACAuthenticatorLength = 16; |
| |
| // Pair challenge (from host), note that the packet, with header, must fit |
| // in a single USB packet (64 bytes), so its maximum length is 50 bytes. |
| struct PairChallengeRequest { |
| uint8_t public_key[X25519_PUBLIC_VALUE_LEN]; // X22519 public key from host |
| uint8_t nonce[kHMACNonceLength]; // nonce to be used for HMAC |
| }; |
| static_assert(sizeof(PairChallengeRequest) <= 50, |
| "size of PairChallengeRequest must be <= 50 bytes"); |
| |
| // Pair challenge response (from device). |
| struct PairChallengeResponse { |
| uint8_t status; // Returned status from EC |
| uint8_t public_key[X25519_PUBLIC_VALUE_LEN]; // X25519 public key from device |
| // Authentication output, the value should be: |
| // HMAC_SHA256(X25519(device_private, host_public), nonce) |
| uint8_t authenticator[kHMACAuthenticatorLength]; |
| } __attribute__((packed)); |
| |
| enum class ChallengeStatus { |
| kChallengePassed, |
| kChallengeFailed, |
| kNeedInjectEntropy, |
| kConnectionError, |
| kUnknownError, |
| }; |
| |
| // The interface of pairing manager. |
| class PairManagerInterface { |
| public: |
| virtual ~PairManagerInterface() = default; |
| // Generates the challange request and sends to the hammer. Then verifies the |
| // challenge. |
| virtual ChallengeStatus PairChallenge(FirmwareUpdaterInterface* fw_updater, |
| DBusWrapperInterface* dbus_wrapper) = 0; |
| }; |
| |
| // The host for generating and verifying the challenge. |
| // In order to prevent the challenge reuse, PairManager does not store the |
| // request as data members. |
| class PairManager : public PairManagerInterface { |
| public: |
| PairManager() = default; |
| PairManager(const PairManager&) = delete; |
| PairManager& operator=(const PairManager&) = delete; |
| |
| ~PairManager() override = default; |
| ChallengeStatus PairChallenge(FirmwareUpdaterInterface* fw_updater, |
| DBusWrapperInterface* dbus_wrapper) override; |
| |
| protected: |
| virtual void GenerateChallenge(PairChallengeRequest* request, |
| uint8_t* private_key); |
| bool VerifyChallenge(const PairChallengeRequest& request, |
| uint8_t* private_key, |
| const PairChallengeResponse& resp); |
| }; |
| |
| } // namespace hammerd |
| #endif // HAMMERD_PAIR_UTILS_H_ |