Skip to content

Commit

Permalink
[webauthn] Improve ctap code logging
Browse files Browse the repository at this point in the history
Print out CTAP status codes as a hex string with a description instead
of a decimal number. This matches how they are written in the spec.

Fixed: 1410329
Change-Id: I817e49fbe6553a88571f7ee6d5c91462da36395a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4973788
Commit-Queue: Nina Satragno <nsatragno@chromium.org>
Reviewed-by: Martin Kreichgauer <martinkr@google.com>
Auto-Submit: Nina Satragno <nsatragno@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1216252}
  • Loading branch information
nsatragno authored and Chromium LUCI CQ committed Oct 27, 2023
1 parent 1660cb9 commit 837c6ac
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 11 deletions.
13 changes: 8 additions & 5 deletions device/fido/ctap2_device_operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,14 @@ class Ctap2DeviceOperation : public DeviceOperation<Request, Response> {
// that breaks every mock test because they aren't expecting a call to
// GetId().
if (request.second) {
FIDO_LOG(DEBUG) << "<- " << static_cast<int>(request.first) << " "
FIDO_LOG(DEBUG) << "<- " << request.first << " "
<< cbor::DiagnosticWriter::Write(*request.second);
absl::optional<std::vector<uint8_t>> cbor_bytes =
cbor::Writer::Write(*request.second);
DCHECK(cbor_bytes);
request_bytes = std::move(*cbor_bytes);
} else {
FIDO_LOG(DEBUG) << "<- " << static_cast<int>(request.first)
<< " (no payload)";
FIDO_LOG(DEBUG) << "<- " << request.first << " (no payload)";
}

request_bytes.insert(request_bytes.begin(),
Expand Down Expand Up @@ -133,8 +132,12 @@ class Ctap2DeviceOperation : public DeviceOperation<Request, Response> {

auto response_code = GetResponseCode(*device_response);
if (response_code != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(DEBUG) << "-> (CTAP2 error code " << +device_response->at(0)
<< ")";
if (response_code == CtapDeviceResponseCode::kCtap2ErrInvalidCBOR) {
FIDO_LOG(DEBUG) << "-> (Unknown CTAP2 error code "
<< static_cast<int>(device_response->at(0)) << ")";
} else {
FIDO_LOG(DEBUG) << "-> (CTAP2 error code " << response_code << ")";
}
std::move(this->callback()).Run(response_code, absl::nullopt);
return;
}
Expand Down
159 changes: 159 additions & 0 deletions device/fido/fido_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,158 @@
#include "device/fido/fido_constants.h"

#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"

namespace device {

namespace {

std::string CtapRequestCommandName(CtapRequestCommand command) {
switch (command) {
case CtapRequestCommand::kAuthenticatorMakeCredential:
return "kAuthenticatorMakeCredential";
case CtapRequestCommand::kAuthenticatorGetAssertion:
return "kAuthenticatorGetAssertion";
case CtapRequestCommand::kAuthenticatorGetNextAssertion:
return "kAuthenticatorGetNextAssertion";
case CtapRequestCommand::kAuthenticatorGetInfo:
return "kAuthenticatorGetInfo";
case CtapRequestCommand::kAuthenticatorClientPin:
return "kAuthenticatorClientPin";
case CtapRequestCommand::kAuthenticatorReset:
return "kAuthenticatorReset";
case CtapRequestCommand::kAuthenticatorBioEnrollment:
return "kAuthenticatorBioEnrollment";
case CtapRequestCommand::kAuthenticatorSelection:
return "kAuthenticatorSelection";
case CtapRequestCommand::kAuthenticatorLargeBlobs:
return "kAuthenticatorLargeBlobs";
case CtapRequestCommand::kAuthenticatorBioEnrollmentPreview:
return "kAuthenticatorBioEnrollmentPreview";
case CtapRequestCommand::kAuthenticatorCredentialManagement:
return "kAuthenticatorCredentialManagement";
case CtapRequestCommand::kAuthenticatorCredentialManagementPreview:
return "kAuthenticatorCredentialManagementPreview";
}
}

std::string CtapDeviceResponseCodeName(CtapDeviceResponseCode code) {
switch (code) {
case CtapDeviceResponseCode::kSuccess:
return "kSuccess";
case CtapDeviceResponseCode::kCtap1ErrInvalidCommand:
return "kCtap1ErrInvalidCommand";
case CtapDeviceResponseCode::kCtap1ErrInvalidParameter:
return "kCtap1ErrInvalidParameter";
case CtapDeviceResponseCode::kCtap1ErrInvalidLength:
return "kCtap1ErrInvalidLength";
case CtapDeviceResponseCode::kCtap1ErrInvalidSeq:
return "kCtap1ErrInvalidSeq";
case CtapDeviceResponseCode::kCtap1ErrTimeout:
return "kCtap1ErrTimeout";
case CtapDeviceResponseCode::kCtap1ErrChannelBusy:
return "kCtap1ErrChannelBusy";
case CtapDeviceResponseCode::kCtap1ErrLockRequired:
return "kCtap1ErrLockRequired";
case CtapDeviceResponseCode::kCtap1ErrInvalidChannel:
return "kCtap1ErrInvalidChannel";
case CtapDeviceResponseCode::kCtap2ErrCBORUnexpectedType:
return "kCtap2ErrCBORUnexpectedType";
case CtapDeviceResponseCode::kCtap2ErrInvalidCBOR:
return "kCtap2ErrInvalidCBOR";
case CtapDeviceResponseCode::kCtap2ErrMissingParameter:
return "kCtap2ErrMissingParameter";
case CtapDeviceResponseCode::kCtap2ErrLimitExceeded:
return "kCtap2ErrLimitExceeded";
case CtapDeviceResponseCode::kCtap2ErrUnsupportedExtension:
return "kCtap2ErrUnsupportedExtension";
case CtapDeviceResponseCode::kCtap2ErrFpDatabaseFull:
return "kCtap2ErrFpDatabaseFull";
case CtapDeviceResponseCode::kCtap2ErrLargeBlobStorageFull:
return "kCtap2ErrLargeBlobStorageFull";
case CtapDeviceResponseCode::kCtap2ErrCredentialExcluded:
return "kCtap2ErrCredentialExcluded";
case CtapDeviceResponseCode::kCtap2ErrProcesssing:
return "kCtap2ErrProcesssing";
case CtapDeviceResponseCode::kCtap2ErrInvalidCredential:
return "kCtap2ErrInvalidCredential";
case CtapDeviceResponseCode::kCtap2ErrUserActionPending:
return "kCtap2ErrUserActionPending";
case CtapDeviceResponseCode::kCtap2ErrOperationPending:
return "kCtap2ErrOperationPending";
case CtapDeviceResponseCode::kCtap2ErrNoOperations:
return "kCtap2ErrNoOperations";
case CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm:
return "kCtap2ErrUnsupportedAlgorithm";
case CtapDeviceResponseCode::kCtap2ErrOperationDenied:
return "kCtap2ErrOperationDenied";
case CtapDeviceResponseCode::kCtap2ErrKeyStoreFull:
return "kCtap2ErrKeyStoreFull";
case CtapDeviceResponseCode::kCtap2ErrNotBusy:
return "kCtap2ErrNotBusy";
case CtapDeviceResponseCode::kCtap2ErrNoOperationPending:
return "kCtap2ErrNoOperationPending";
case CtapDeviceResponseCode::kCtap2ErrUnsupportedOption:
return "kCtap2ErrUnsupportedOption";
case CtapDeviceResponseCode::kCtap2ErrInvalidOption:
return "kCtap2ErrInvalidOption";
case CtapDeviceResponseCode::kCtap2ErrKeepAliveCancel:
return "kCtap2ErrKeepAliveCancel";
case CtapDeviceResponseCode::kCtap2ErrNoCredentials:
return "kCtap2ErrNoCredentials";
case CtapDeviceResponseCode::kCtap2ErrUserActionTimeout:
return "kCtap2ErrUserActionTimeout";
case CtapDeviceResponseCode::kCtap2ErrNotAllowed:
return "kCtap2ErrNotAllowed";
case CtapDeviceResponseCode::kCtap2ErrPinInvalid:
return "kCtap2ErrPinInvalid";
case CtapDeviceResponseCode::kCtap2ErrPinBlocked:
return "kCtap2ErrPinBlocked";
case CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid:
return "kCtap2ErrPinAuthInvalid";
case CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked:
return "kCtap2ErrPinAuthBlocked";
case CtapDeviceResponseCode::kCtap2ErrPinNotSet:
return "kCtap2ErrPinNotSet";
case CtapDeviceResponseCode::kCtap2ErrPinRequired:
return "kCtap2ErrPinRequired";
case CtapDeviceResponseCode::kCtap2ErrPinPolicyViolation:
return "kCtap2ErrPinPolicyViolation";
case CtapDeviceResponseCode::kCtap2ErrPinTokenExpired:
return "kCtap2ErrPinTokenExpired";
case CtapDeviceResponseCode::kCtap2ErrRequestTooLarge:
return "kCtap2ErrRequestTooLarge";
case CtapDeviceResponseCode::kCtap2ErrActionTimeout:
return "kCtap2ErrActionTimeout";
case CtapDeviceResponseCode::kCtap2ErrUpRequired:
return "kCtap2ErrUpRequired";
case CtapDeviceResponseCode::kCtap2ErrUvBlocked:
return "kCtap2ErrUvBlocked";
case CtapDeviceResponseCode::kCtap2ErrIntegrityFailure:
return "kCtap2ErrIntegrityFailure";
case CtapDeviceResponseCode::kCtap2ErrInvalidSubcommand:
return "kCtap2ErrInvalidSubcommand";
case CtapDeviceResponseCode::kCtap2ErrUvInvalid:
return "kCtap2ErrUvInvalid";
case CtapDeviceResponseCode::kCtap2ErrUnauthorizedPermission:
return "kCtap2ErrUnauthorizedPermission";
case CtapDeviceResponseCode::kCtap2ErrOther:
return "kCtap2ErrOther";
case CtapDeviceResponseCode::kCtap2ErrSpecLast:
return "kCtap2ErrSpecLast";
case CtapDeviceResponseCode::kCtap2ErrExtensionFirst:
return "kCtap2ErrExtensionFirst";
case CtapDeviceResponseCode::kCtap2ErrExtensionLast:
return "kCtap2ErrExtensionLast";
case CtapDeviceResponseCode::kCtap2ErrVendorFirst:
return "kCtap2ErrVendorFirst";
case CtapDeviceResponseCode::kCtap2ErrVendorLast:
return "kCtap2ErrVendorLast";
}
}

} // namespace

const std::array<uint8_t, 32> kBogusAppParam = {
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
Expand Down Expand Up @@ -106,4 +255,14 @@ const char kDevicePublicKeyEPKey[] = "epAtt";

const base::TimeDelta kBleDevicePairingModeWaitingInterval = base::Seconds(2);

std::ostream& operator<<(std::ostream& os, CtapRequestCommand command) {
return os << "0x" << std::hex << static_cast<int>(command) << " ("
<< CtapRequestCommandName(command) << ")";
}

std::ostream& operator<<(std::ostream& os, CtapDeviceResponseCode code) {
return os << "0x" << std::hex << static_cast<int>(code) << " ("
<< CtapDeviceResponseCodeName(code) << ")";
}

} // namespace device
7 changes: 6 additions & 1 deletion device/fido/fido_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <stdint.h>

#include <array>
#include <vector>

#include "base/component_export.h"
#include "base/containers/fixed_flat_set.h"
Expand Down Expand Up @@ -194,6 +193,9 @@ constexpr auto kCtapResponseCodeList = base::MakeFixedFlatSet<uint8_t>({
static_cast<uint8_t>(CtapDeviceResponseCode::kCtap2ErrVendorLast),
});

COMPONENT_EXPORT(DEVICE_FIDO)
std::ostream& operator<<(std::ostream& os, CtapDeviceResponseCode code);

// Commands supported by CTAPHID device as specified in
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid-commands
enum class FidoHidDeviceCommand : uint8_t {
Expand Down Expand Up @@ -257,6 +259,9 @@ enum class CtapRequestCommand : uint8_t {
kAuthenticatorCredentialManagementPreview = 0x41,
};

COMPONENT_EXPORT(DEVICE_FIDO)
std::ostream& operator<<(std::ostream& os, CtapRequestCommand command);

// Enumerates the keys in a COSE Key structure. See
// https://tools.ietf.org/html/rfc8152#section-7.1
enum class CoseKeyKey : int {
Expand Down
5 changes: 2 additions & 3 deletions device/fido/get_assertion_request_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -785,9 +785,8 @@ void GetAssertionRequestHandler::HandleResponse(
CancelActiveAuthenticators(authenticator->GetId());

if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "Failing assertion request due to status "
<< static_cast<int>(status) << " from "
<< authenticator->GetDisplayName();
FIDO_LOG(ERROR) << "Failing assertion request due to status " << status
<< " from " << authenticator->GetDisplayName();
std::move(completion_callback_)
.Run(*maybe_result, absl::nullopt, authenticator);
return;
Expand Down
3 changes: 1 addition & 2 deletions device/fido/make_credential_request_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -871,8 +871,7 @@ void MakeCredentialRequestHandler::HandleResponse(

if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "Failing make credential request due to status "
<< static_cast<int>(status) << " from "
<< authenticator->GetDisplayName();
<< status << " from " << authenticator->GetDisplayName();
std::move(completion_callback_)
.Run(*maybe_result, absl::nullopt, authenticator);
return;
Expand Down

0 comments on commit 837c6ac

Please sign in to comment.