Commit 9abd46f6 authored by Yicheng Li's avatar Yicheng Li Committed by Commit Bot

fido: Add GetAssertion operation for ChromeOS authenticator

This change implements the GetAssertion operation in ChromeOS
authenticator. It uses the first assertion returned by ChromeOS
platform daemons. Resident credentials are not supported yet.

Bug: b:144861739
Change-Id: Icc9ae86568d42a4f15f95e6fdc5cc8fd367353cb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2040064
Commit-Queue: Yicheng Li <yichengli@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#746099}
parent 2e71e7af
......@@ -41,7 +41,8 @@ namespace {
AuthenticatorSupportedOptions ChromeOSAuthenticatorOptions() {
AuthenticatorSupportedOptions options;
options.is_platform_device = true;
options.supports_resident_key = true;
// TODO(yichengli): change supports_resident_key to true once it's supported.
options.supports_resident_key = false;
// Even if the user has no fingerprints enrolled, we will have password
// as fallback.
options.user_verification_availability = AuthenticatorSupportedOptions::
......@@ -162,6 +163,96 @@ void ChromeOSAuthenticator::OnMakeCredentialResp(
std::move(response));
}
void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request,
GetAssertionCallback callback) {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
dbus::ObjectProxy* u2f_proxy = bus->GetObjectProxy(
u2f::kU2FServiceName, dbus::ObjectPath(u2f::kU2FServicePath));
if (!u2f_proxy) {
FIDO_LOG(ERROR) << "Couldn't get u2f proxy";
std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOther,
base::nullopt);
return;
}
u2f::GetAssertionRequest req;
// Requests with UserPresence get upgraded to UserVerification.
req.set_verification_type(u2f::VERIFICATION_USER_VERIFICATION);
req.set_rp_id(request.rp_id);
req.set_client_data_hash(std::string(request.client_data_hash.begin(),
request.client_data_hash.end()));
for (const PublicKeyCredentialDescriptor& descriptor : request.allow_list) {
const std::vector<uint8_t>& id = descriptor.id();
req.add_allowed_credential_id(std::string(id.begin(), id.end()));
}
dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FGetAssertion);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(req);
u2f_proxy->CallMethodWithErrorResponse(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&ChromeOSAuthenticator::OnGetAssertionResp,
weak_factory_.GetWeakPtr(), std::move(request),
std::move(callback)));
}
void ChromeOSAuthenticator::OnGetAssertionResp(CtapGetAssertionRequest request,
GetAssertionCallback callback,
dbus::Response* dbus_response,
dbus::ErrorResponse* error) {
if (error) {
FIDO_LOG(ERROR) << "GetAssertion dbus call failed with error: "
<< error->ToString();
std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOther,
base::nullopt);
return;
}
dbus::MessageReader reader(dbus_response);
u2f::GetAssertionResponse resp;
if (!reader.PopArrayOfBytesAsProto(&resp)) {
FIDO_LOG(ERROR) << "Failed to parse reply for call to GetAssertion";
std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOther,
base::nullopt);
return;
}
FIDO_LOG(DEBUG) << "GetAssertion status: " << resp.status();
if (resp.status() != u2f::GetAssertionResponse_GetAssertionStatus_SUCCESS ||
resp.assertion_size() < 1) {
std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOperationDenied,
base::nullopt);
return;
}
u2f::Assertion assertion = resp.assertion(0);
base::Optional<AuthenticatorData> authenticator_data =
AuthenticatorData::DecodeAuthenticatorData(
base::as_bytes(base::make_span(assertion.authenticator_data())));
if (!authenticator_data) {
FIDO_LOG(ERROR) << "Authenticator data corrupted.";
std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOther,
base::nullopt);
return;
}
std::vector<uint8_t> signature(assertion.signature().begin(),
assertion.signature().end());
AuthenticatorGetAssertionResponse response(std::move(*authenticator_data),
std::move(signature));
const std::string& credential_id = assertion.credential_id();
response.SetCredential(PublicKeyCredentialDescriptor(
CredentialType::kPublicKey,
std::vector<uint8_t>(credential_id.begin(), credential_id.end())));
std::move(callback).Run(CtapDeviceResponseCode::kSuccess,
std::move(response));
}
bool ChromeOSAuthenticator::IsInPairingMode() const {
return false;
}
......
......@@ -34,7 +34,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
void MakeCredential(CtapMakeCredentialRequest request,
MakeCredentialCallback callback) override;
void GetAssertion(CtapGetAssertionRequest request,
GetAssertionCallback callback) override {}
GetAssertionCallback callback) override;
void GetNextAssertion(GetAssertionCallback callback) override {}
void Cancel() override {}
std::string GetId() const override;
......@@ -56,6 +56,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
dbus::Response* dbus_response,
dbus::ErrorResponse* error);
void OnGetAssertionResp(CtapGetAssertionRequest request,
GetAssertionCallback callback,
dbus::Response* dbus_response,
dbus::ErrorResponse* error);
base::WeakPtrFactory<ChromeOSAuthenticator> weak_factory_;
};
......
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