Commit 170fba4c authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido/win: fix two bugs in attestation response handling

1) Pass the converted |dwTransportUsed| value into the response.
2) Require the attestation statement be a map, not just any CBOR value.

Also add unit tests.

Change-Id: Ifcf2c4936b08a45eed0be648be6307d71b48a9f1
Reviewed-on: https://chromium-review.googlesource.com/c/1429620
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarAdam Langley <agl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#625243}
parent c9aa6b0b
......@@ -100,6 +100,7 @@ test("device_unittests") {
"fido/u2f_command_constructor_unittest.cc",
"fido/u2f_register_operation_unittest.cc",
"fido/u2f_sign_operation_unittest.cc",
"fido/win/type_conversions_unittest.cc",
"gamepad/abstract_haptic_gamepad_unittest.cc",
"gamepad/gamepad_id_list_unittest.cc",
"gamepad/gamepad_provider_unittest.cc",
......
......@@ -35,7 +35,7 @@ ToAuthenticatorMakeCredentialResponse(
base::Optional<cbor::Value> cbor_attestation_statement = cbor::Reader::Read(
base::span<const uint8_t>(credential_attestation.pbAttestation,
credential_attestation.cbAttestation));
if (!cbor_attestation_statement) {
if (!cbor_attestation_statement || !cbor_attestation_statement->is_map()) {
DLOG(ERROR) << "CBOR decoding attestation statement failed: "
<< base::HexEncode(credential_attestation.pbAttestation,
credential_attestation.cbAttestation);
......@@ -67,7 +67,7 @@ ToAuthenticatorMakeCredentialResponse(
}
return AuthenticatorMakeCredentialResponse(
base::nullopt /* transport_used */,
transport_used,
AttestationObject(
std::move(*authenticator_data),
std::make_unique<OpaqueAttestationStatement>(
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/fido/win/type_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "device/fido/attestation_object.h"
#include "device/fido/attestation_statement.h"
#include "device/fido/fido_parsing_utils.h"
#include "device/fido/fido_test_data.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
namespace {
TEST(TypeConversionsTest, ToAuthenticatorMakeCredentialResponse) {
struct TestCase {
const wchar_t* format;
std::vector<uint8_t> authenticator_data;
std::vector<uint8_t> cbor_attestation_statement;
uint8_t used_transport; // WEBAUTHN_CTAP_TRANSPORT_* from <webauthn.h>
bool success;
base::Optional<FidoTransportProtocol> expected_transport;
} test_cases[] = {
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_USB, true,
FidoTransportProtocol::kUsbHumanInterfaceDevice},
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_NFC, true,
FidoTransportProtocol::kNearFieldCommunication},
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_INTERNAL, true,
FidoTransportProtocol::kInternal},
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_TEST, true, base::nullopt},
// Unknown attestation formats
{L"weird-unknown-format",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
{0xa0}, // Empty CBOR map.
WEBAUTHN_CTAP_TRANSPORT_USB,
true,
FidoTransportProtocol::kUsbHumanInterfaceDevice},
{L"weird-unknown-format",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
{0x60}, // Empty string. Not a valid attStmt.
WEBAUTHN_CTAP_TRANSPORT_USB,
false},
// Invalid authenticator data
{L"packed",
{},
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_USB,
false},
{L"packed",
{1, 2, 3},
fido_parsing_utils::Materialize(
test_data::kPackedAttestationStatementCBOR),
WEBAUTHN_CTAP_TRANSPORT_USB,
false},
// Invalid attestation statement
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
{},
WEBAUTHN_CTAP_TRANSPORT_USB,
false},
{L"packed",
fido_parsing_utils::Materialize(test_data::kTestSignAuthenticatorData),
{1, 2, 3},
WEBAUTHN_CTAP_TRANSPORT_USB,
false},
};
size_t i = 0;
for (const auto test : test_cases) {
SCOPED_TRACE(::testing::Message() << "Test case " << i++);
auto response =
ToAuthenticatorMakeCredentialResponse(WEBAUTHN_CREDENTIAL_ATTESTATION{
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3,
test.format,
test.authenticator_data.size(),
const_cast<unsigned char*>(test.authenticator_data.data()),
test.cbor_attestation_statement.size(),
const_cast<unsigned char*>(test.cbor_attestation_statement.data()),
// dwAttestationDecodeType and pvAttestationDecode are ignored.
WEBAUTHN_ATTESTATION_DECODE_NONE,
nullptr,
// cbAttestationObject and pbAttestationObject are ignored.
0,
nullptr,
// cbCredentialId and pbCredentialId are ignored.
0,
nullptr,
WEBAUTHN_EXTENSIONS{},
test.used_transport,
});
EXPECT_EQ(response.has_value(), test.success);
if (!response)
return;
EXPECT_EQ(response->attestation_object()
.authenticator_data()
.SerializeToByteArray(),
test.authenticator_data);
EXPECT_EQ(
response->attestation_object().attestation_statement().format_name(),
base::UTF16ToUTF8(test.format));
EXPECT_EQ(cbor::Writer::Write(cbor::Value(response->attestation_object()
.attestation_statement()
.GetAsCBORMap())),
test.cbor_attestation_statement);
EXPECT_EQ(response->transport_used(), test.expected_transport);
}
};
} // namespace
} // namespace device
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