blob: 74373c99ec3ff45e31c25b987f2fe87e1db7a029 [file] [log] [blame]
// Copyright 2019 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 U2FD_WEBAUTHN_HANDLER_H_
#define U2FD_WEBAUTHN_HANDLER_H_
#include <functional>
#include <memory>
#include <queue>
#include <vector>
#include <brillo/dbus/dbus_method_response.h>
#include <u2f/proto_bindings/u2f_interface.pb.h>
#include "u2fd/tpm_vendor_cmd.h"
#include "u2fd/user_state.h"
namespace u2f {
using MakeCredentialMethodResponse =
brillo::dbus_utils::DBusMethodResponse<MakeCredentialResponse>;
using GetAssertionMethodResponse =
brillo::dbus_utils::DBusMethodResponse<GetAssertionResponse>;
struct MakeCredentialSession {
bool empty() { return !response_; }
uint64_t session_id;
MakeCredentialRequest request_;
std::unique_ptr<MakeCredentialMethodResponse> response_;
};
struct GetAssertionSession {
bool empty() { return !response_; }
uint64_t session_id;
GetAssertionRequest request_;
std::unique_ptr<GetAssertionMethodResponse> response_;
};
enum class PresenceRequirement {
kPowerButton, // Requires a power button press as indication of presence.
kFingerprint, // Requires the GPIO line from fingerprint MCU to be active.
};
// Implementation of the WebAuthn DBus API.
// More detailed documentation is available in u2f_interface.proto
class WebAuthnHandler {
public:
WebAuthnHandler();
// Initializes WebAuthnHandler.
// |tpm_proxy| - proxy to send commands to TPM. Owned by U2fDaemon and should
// outlive WebAuthnHandler.
// |user_state| - pointer to a UserState instance, for requesting user secret.
// Owned by U2fDaemon and should outlive WebAuthnHandler.
// |request_presence| - callback for performing other platform tasks when
// expecting the user to press the power button.
void Initialize(TpmVendorCommandProxy* tpm_proxy,
UserState* user_state,
std::function<void()> request_presence);
// Generates a new credential.
void MakeCredential(
std::unique_ptr<MakeCredentialMethodResponse> method_response,
const MakeCredentialRequest& request);
// Signs a challenge from the relaying party.
void GetAssertion(std::unique_ptr<GetAssertionMethodResponse> method_response,
const GetAssertionRequest& request);
// Tests validity and/or presence of specified credentials.
HasCredentialsResponse HasCredentials(const HasCredentialsRequest& request);
private:
friend class WebAuthnHandlerTest;
bool Initialized();
// Proceeds to cr50 for the current MakeCredential request, and responds to
// the request with authenticator data.
// Called directly if the request is user-presence only.
// Called on user verification success if the request is user-verification.
void DoMakeCredential(struct MakeCredentialSession session,
PresenceRequirement presence_requirement);
// Proceeds to cr50 for the current GetAssertion request, and responds to
// the request with assertions.
// Called directly if the request is user-presence only.
// Called on user verification success if the request is user-verification.
void DoGetAssertion(struct GetAssertionSession session,
PresenceRequirement presence_requirement);
// Runs a U2F_GENERATE command to create a new key handle, and stores the key
// handle in |credential_id| and the public key in |credential_public_key|.
// The flag in the U2F_GENERATE command is set according to
// |presence_requirement|.
// |rp_id_hash| must be exactly 32 bytes.
MakeCredentialResponse::MakeCredentialStatus DoU2fGenerate(
const std::vector<uint8_t>& rp_id_hash,
PresenceRequirement presence_requirement,
std::vector<uint8_t>* credential_id,
std::vector<uint8_t>* credential_public_key);
// Runs a U2F_SIGN command to check that credential_id is valid, and if so,
// sign |hash_to_sign| and store the signature in |signature|.
// The flag in the U2F_SIGN command is set according to
// |presence_requirement|.
// |rp_id_hash| must be exactly 32 bytes.
GetAssertionResponse::GetAssertionStatus DoU2fSign(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& hash_to_sign,
const std::vector<uint8_t>& credential_id,
PresenceRequirement presence_requirement,
std::vector<uint8_t>* signature);
// Runs a U2F_SIGN command with "check only" flag to check whether
// |credential_id| is a key handle owned by this device tied to |rp_id_hash|.
HasCredentialsResponse::HasCredentialsStatus DoU2fSignCheckOnly(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& credential_id);
// Prompts the user for presence through |request_presence_| and calls |fn|
// repeatedly until success or timeout.
void CallAndWaitForPresence(std::function<uint32_t()> fn, uint32_t* status);
// Creates and returns authenticator data. |include_attested_credential_data|
// should be set to true for MakeCredential, false for GetAssertion.
std::vector<uint8_t> MakeAuthenticatorData(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& credential_id,
const std::vector<uint8_t>& credential_public_key,
bool user_verified,
bool include_attested_credential_data);
// Appends a none attestation to |response|. Only used in MakeCredential.
void AppendNoneAttestation(MakeCredentialResponse* response);
// Runs U2F_SIGN command with "check only" flag on each excluded credential
// id. Returns true if one of them belongs to this device.
HasCredentialsResponse::HasCredentialsStatus HasExcludedCredentials(
const MakeCredentialRequest& request);
TpmVendorCommandProxy* tpm_proxy_;
UserState* user_state_;
std::function<void()> request_presence_;
};
} // namespace u2f
#endif // U2FD_WEBAUTHN_HANDLER_H_