Commit 3545f505 authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Migrate device/u2f/apdu to src/components

U2fApduCommand and U2fApduResponse objects in device/u2f are transport
and protocol agnostic. Migrate all APDU related objects and tests to
src/components.

Bug: 807836
Change-Id: I96e71128eb0fcf13b8c38fc7e9a4d0b31203c99f
Reviewed-on: https://chromium-review.googlesource.com/896965
Commit-Queue: Jun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542979}
parent a276a89f
......@@ -62,6 +62,7 @@ test("components_unittests") {
deps = [
"//base",
"//components/apdu:unit_tests",
"//components/assist_ranker:unit_tests",
"//components/autofill/core/browser:unit_tests",
"//components/autofill/core/common:unit_tests",
......
# Copyright 2018 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.
import("//testing/libfuzzer/fuzzer_test.gni")
component("apdu") {
sources = [
"apdu_command.cc",
"apdu_command.h",
"apdu_response.cc",
"apdu_response.h",
]
defines = [ "IS_APDU_IMPL" ]
deps = [
"//base",
]
}
source_set("unit_tests") {
testonly = true
sources = [
"apdu_unittest.cc",
]
deps = [
":apdu",
"//base",
"//testing/gmock",
"//testing/gtest",
]
}
fuzzer_test("apdu_fuzzer") {
sources = [
"apdu_fuzzer.cc",
]
deps = [
":apdu",
"//base",
]
libfuzzer_options = [ "max_len=65535" ]
}
jdoerrie@chromium.org
reillyg@chromium.org
// Copyright 2017 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/u2f_apdu_command.h"
#include <utility>
#include "components/apdu/apdu_command.h"
#include "base/memory/ptr_util.h"
namespace apdu {
namespace device {
namespace {
// static
std::unique_ptr<U2fApduCommand> U2fApduCommand::CreateFromMessageForTesting(
const std::vector<uint8_t>& message) {
uint16_t data_length = 0;
size_t index = 0;
size_t response_length = 0;
std::vector<uint8_t> data;
// APDU command data length is 2 bytes encoded in big endian order.
uint16_t ParseMessageLength(base::span<const uint8_t> message, size_t offset) {
DCHECK_GE(message.size(), offset + 2);
return (message[offset] << 8) | message[offset + 1];
}
} // namespace
base::Optional<ApduCommand> ApduCommand::CreateFromMessage(
base::span<const uint8_t> message) {
if (message.size() < kApduMinHeader || message.size() > kApduMaxLength)
return nullptr;
uint8_t cla = message[index++];
uint8_t ins = message[index++];
uint8_t p1 = message[index++];
uint8_t p2 = message[index++];
return base::nullopt;
uint8_t cla = message[0];
uint8_t ins = message[1];
uint8_t p1 = message[2];
uint8_t p2 = message[3];
size_t response_length = 0;
std::vector<uint8_t> data;
switch (message.size()) {
// No data present; no expected response
// No data present; no expected response.
case kApduMinHeader:
break;
// Invalid encoding sizes
// Invalid encoding sizes.
case kApduMinHeader + 1:
case kApduMinHeader + 2:
return nullptr;
// No data present; response expected
return base::nullopt;
// No data present; response expected.
case kApduMinHeader + 3:
// Fifth byte must be 0
if (message[index++] != 0)
return nullptr;
response_length = message[index++] << 8;
response_length |= message[index++];
// Fifth byte must be 0.
if (message[4] != 0)
return base::nullopt;
response_length = ParseMessageLength(message, kApduCommandLengthOffset);
// Special case where response length of 0x0000 corresponds to 65536
// Defined in ISO7816-4
// as defined in ISO7816-4.
if (response_length == 0)
response_length = kApduMaxResponseLength;
break;
default:
// Fifth byte must be 0
if (message[index++] != 0)
return nullptr;
data_length = message[index++] << 8;
data_length |= message[index++];
if (message.size() == data_length + index) {
// No response expected
data.insert(data.end(), message.begin() + index, message.end());
} else if (message.size() == data_length + index + 2) {
// Maximum response size is stored in final 2 bytes
data.insert(data.end(), message.begin() + index, message.end() - 2);
index += data_length;
response_length = message[index++] << 8;
response_length |= message[index++];
// Fifth byte must be 0.
if (message[4] != 0)
return base::nullopt;
auto data_length = ParseMessageLength(message, kApduCommandLengthOffset);
if (message.size() == data_length + kApduCommandDataOffset) {
// No response expected.
data.insert(data.end(), message.begin() + kApduCommandDataOffset,
message.end());
} else if (message.size() == data_length + kApduCommandDataOffset + 2) {
// Maximum response size is stored in final 2 bytes.
data.insert(data.end(), message.begin() + kApduCommandDataOffset,
message.end() - 2);
auto response_length_offset = kApduCommandDataOffset + data_length;
response_length = ParseMessageLength(message, response_length_offset);
// Special case where response length of 0x0000 corresponds to 65536
// Defined in ISO7816-4
// as defined in ISO7816-4.
if (response_length == 0)
response_length = kApduMaxResponseLength;
} else {
return nullptr;
return base::nullopt;
}
break;
}
return std::make_unique<U2fApduCommand>(cla, ins, p1, p2, response_length,
std::move(data));
return ApduCommand(cla, ins, p1, p2, response_length, std::move(data));
}
U2fApduCommand::U2fApduCommand()
: cla_(0), ins_(0), p1_(0), p2_(0), response_length_(0) {}
ApduCommand::ApduCommand() = default;
U2fApduCommand::U2fApduCommand(uint8_t cla,
uint8_t ins,
uint8_t p1,
uint8_t p2,
size_t response_length,
std::vector<uint8_t> data)
ApduCommand::ApduCommand(uint8_t cla,
uint8_t ins,
uint8_t p1,
uint8_t p2,
size_t response_length,
std::vector<uint8_t> data)
: cla_(cla),
ins_(ins),
p1_(p1),
......@@ -90,16 +92,20 @@ U2fApduCommand::U2fApduCommand(uint8_t cla,
response_length_(response_length),
data_(std::move(data)) {}
U2fApduCommand::~U2fApduCommand() = default;
ApduCommand::ApduCommand(ApduCommand&& that) = default;
ApduCommand& ApduCommand::operator=(ApduCommand&& that) = default;
ApduCommand::~ApduCommand() = default;
std::vector<uint8_t> U2fApduCommand::GetEncodedCommand() const {
std::vector<uint8_t> ApduCommand::GetEncodedCommand() const {
std::vector<uint8_t> encoded = {cla_, ins_, p1_, p2_};
// If data exists, request size (Lc) is encoded in 3 bytes, with the first
// byte always being null, and the other two bytes being a big-endian
// representation of the request size. If data length is 0, response size (Le)
// will be prepended with a null byte.
if (data_.size() > 0) {
if (!data_.empty()) {
size_t data_length = data_.size();
encoded.push_back(0x0);
......@@ -119,4 +125,4 @@ std::vector<uint8_t> U2fApduCommand::GetEncodedCommand() const {
return encoded;
}
} // namespace device
} // namespace apdu
......@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_FIDO_U2F_APDU_COMMAND_H_
#define DEVICE_FIDO_U2F_APDU_COMMAND_H_
#ifndef COMPONENTS_APDU_APDU_COMMAND_H_
#define COMPONENTS_APDU_APDU_COMMAND_H_
#include <cinttypes>
#include <memory>
#include <utility>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/optional.h"
namespace device {
namespace apdu {
// APDU commands are defined as part of ISO 7816-4. Commands can be serialized
// into either short length encodings, where the maximum data length is 256
......@@ -23,20 +25,22 @@ namespace device {
// byte, denoting the instruction code, P1 and P2, each one byte denoting
// instruction parameters, a length field (Lc), a data field of length Lc, and
// a maximum expected response length (Le).
class COMPONENT_EXPORT(DEVICE_FIDO) U2fApduCommand {
class COMPONENT_EXPORT(APDU) ApduCommand {
public:
// Constructs an APDU command from the serialized message data.
static std::unique_ptr<U2fApduCommand> CreateFromMessageForTesting(
const std::vector<uint8_t>& data);
U2fApduCommand();
U2fApduCommand(uint8_t cla,
uint8_t ins,
uint8_t p1,
uint8_t p2,
size_t response_length,
std::vector<uint8_t> data);
~U2fApduCommand();
static base::Optional<ApduCommand> CreateFromMessage(
base::span<const uint8_t> message);
ApduCommand();
ApduCommand(uint8_t cla,
uint8_t ins,
uint8_t p1,
uint8_t p2,
size_t response_length,
std::vector<uint8_t> data);
ApduCommand(ApduCommand&& that);
ApduCommand& operator=(ApduCommand&& that);
~ApduCommand();
// Returns serialized message data.
std::vector<uint8_t> GetEncodedCommand() const;
......@@ -58,12 +62,15 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fApduCommand {
const std::vector<uint8_t>& data() const { return data_; }
private:
FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestDeserializeBasic);
FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestDeserializeComplex);
FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestSerializeEdgeCases);
FRIEND_TEST_ALL_PREFIXES(ApduTest, TestDeserializeBasic);
FRIEND_TEST_ALL_PREFIXES(ApduTest, TestDeserializeComplex);
FRIEND_TEST_ALL_PREFIXES(ApduTest, TestSerializeEdgeCases);
static constexpr size_t kApduMinHeader = 4;
static constexpr size_t kApduMaxHeader = 7;
static constexpr size_t kApduCommandDataOffset = 7;
static constexpr size_t kApduCommandLengthOffset = 5;
// As defined in ISO7816-4, extended length APDU request data is limited to
// 16 bits in length with a maximum value of 65535. Response data length is
// also limited to 16 bits in length with a value of 0x0000 corresponding to
......@@ -73,14 +80,16 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fApduCommand {
static constexpr size_t kApduMaxLength =
kApduMaxDataLength + kApduMaxHeader + 2;
uint8_t cla_;
uint8_t ins_;
uint8_t p1_;
uint8_t p2_;
size_t response_length_;
uint8_t cla_ = 0;
uint8_t ins_ = 0;
uint8_t p1_ = 0;
uint8_t p2_ = 0;
size_t response_length_ = 0;
std::vector<uint8_t> data_;
DISALLOW_COPY_AND_ASSIGN(ApduCommand);
};
} // namespace device
} // namespace apdu
#endif // DEVICE_FIDO_U2F_APDU_COMMAND_H_
#endif // COMPONENTS_APDU_APDU_COMMAND_H_
......@@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include "components/apdu/apdu_command.h"
#include "components/apdu/apdu_response.h"
#include "device/fido/u2f_apdu_command.h"
#include "device/fido/u2f_apdu_response.h"
namespace apdu {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::vector<uint8_t> input(data, data + size);
std::unique_ptr<device::U2fApduCommand> cmd =
device::U2fApduCommand::CreateFromMessageForTesting(input);
std::unique_ptr<device::U2fApduResponse> rsp =
device::U2fApduResponse::CreateFromMessage(input);
ApduCommand::CreateFromMessage(base::make_span(data, size));
ApduResponse::CreateFromMessage(base::make_span(data, size));
return 0;
}
} // namespace apdu
// Copyright 2017 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 "components/apdu/apdu_response.h"
#include <utility>
#include "base/numerics/safe_conversions.h"
namespace apdu {
// static
base::Optional<ApduResponse> ApduResponse::CreateFromMessage(
base::span<const uint8_t> data) {
// Invalid message size, data is appended by status byte.
if (data.size() < 2)
return base::nullopt;
uint16_t status_bytes = data[data.size() - 2] << 8;
status_bytes |= data[data.size() - 1];
return ApduResponse(std::vector<uint8_t>(data.begin(), data.end() - 2),
static_cast<Status>(status_bytes));
}
ApduResponse::ApduResponse(std::vector<uint8_t> data, Status response_status)
: data_(std::move(data)), response_status_(response_status) {}
ApduResponse::ApduResponse(ApduResponse&& that) = default;
ApduResponse& ApduResponse::operator=(ApduResponse&& that) = default;
ApduResponse::~ApduResponse() = default;
std::vector<uint8_t> ApduResponse::GetEncodedResponse() const {
std::vector<uint8_t> encoded_response = data_;
encoded_response.push_back(
base::strict_cast<uint16_t>(response_status_) >> 8 & 0xff);
encoded_response.push_back(base::strict_cast<uint16_t>(response_status_) &
0xff);
return encoded_response;
}
} // namespace apdu
......@@ -2,49 +2,58 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_FIDO_U2F_APDU_RESPONSE_H_
#define DEVICE_FIDO_U2F_APDU_RESPONSE_H_
#ifndef COMPONENTS_APDU_APDU_RESPONSE_H_
#define COMPONENTS_APDU_APDU_RESPONSE_H_
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/macros.h"
#include "base/optional.h"
namespace device {
namespace apdu {
// APDU responses are defined as part of ISO 7816-4. Serialized responses
// consist of a data field of varying length, up to a maximum 65536, and a
// two byte status field.
class COMPONENT_EXPORT(DEVICE_FIDO) U2fApduResponse {
class COMPONENT_EXPORT(APDU) ApduResponse {
public:
// Status bytes are specified in ISO 7816-4
// Status bytes are specified in ISO 7816-4.
enum class Status : uint16_t {
SW_NO_ERROR = 0x9000,
SW_CONDITIONS_NOT_SATISFIED = 0x6985,
SW_WRONG_DATA = 0x6A80,
SW_WRONG_LENGTH = 0x6700,
SW_INS_NOT_SUPPORTED = 0x6d00,
SW_INS_NOT_SUPPORTED = 0x6D00,
};
U2fApduResponse(std::vector<uint8_t> message, Status response_status);
~U2fApduResponse();
// Create a APDU response from the serialized message.
static base::Optional<ApduResponse> CreateFromMessage(
base::span<const uint8_t> data);
ApduResponse(std::vector<uint8_t> data, Status response_status);
ApduResponse(ApduResponse&& that);
ApduResponse& operator=(ApduResponse&& that);
~ApduResponse();
// Create a APDU response from the serialized message
static std::unique_ptr<U2fApduResponse> CreateFromMessage(
const std::vector<uint8_t>& data);
std::vector<uint8_t> GetEncodedResponse() const;
const std::vector<uint8_t> data() const { return data_; }
const std::vector<uint8_t>& data() const { return data_; }
Status status() const { return response_status_; }
private:
FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestDeserializeResponse);
FRIEND_TEST_ALL_PREFIXES(ApduTest, TestDeserializeResponse);
Status response_status_;
std::vector<uint8_t> data_;
Status response_status_;
DISALLOW_COPY_AND_ASSIGN(ApduResponse);
};
} // namespace device
} // namespace apdu
#endif // DEVICE_FIDO_U2F_APDU_RESPONSE_H_
#endif // COMPONENTS_APDU_APDU_RESPONSE_H_
......@@ -69,7 +69,6 @@ test("device_unittests") {
"fido/fake_u2f_discovery_unittest.cc",
"fido/fido_hid_message_unittest.cc",
"fido/test_callback_receiver_unittest.cc",
"fido/u2f_apdu_unittest.cc",
"fido/u2f_ble_connection_unittest.cc",
"fido/u2f_ble_device_unittest.cc",
"fido/u2f_ble_frames_unittest.cc",
......@@ -87,6 +86,7 @@ test("device_unittests") {
deps = [
"//base/test:test_support",
"//base/third_party/dynamic_annotations:dynamic_annotations",
"//components/apdu",
"//components/cbor",
"//device/base/synchronization",
"//device/bluetooth",
......
......@@ -57,10 +57,6 @@ component("fido") {
"response_data.h",
"sign_response_data.cc",
"sign_response_data.h",
"u2f_apdu_command.cc",
"u2f_apdu_command.h",
"u2f_apdu_response.cc",
"u2f_apdu_response.h",
"u2f_ble_connection.cc",
"u2f_ble_connection.h",
"u2f_ble_device.cc",
......@@ -95,6 +91,7 @@ component("fido") {
defines = [ "IS_DEVICE_FIDO_IMPL" ]
deps = [
"//components/apdu",
"//components/cbor",
"//crypto",
"//device/base",
......@@ -140,20 +137,11 @@ source_set("mocks") {
deps = [
":fido",
"//base",
"//components/apdu",
"//testing/gmock",
]
}
fuzzer_test("u2f_apdu_fuzzer") {
sources = [
"u2f_apdu_fuzzer.cc",
]
deps = [
":fido",
]
libfuzzer_options = [ "max_len=65537" ]
}
fuzzer_test("fido_hid_message_fuzzer") {
sources = [
"fido_hid_message_fuzzer.cc",
......@@ -223,6 +211,7 @@ source_set("test_support") {
]
deps = [
"//base",
"//components/apdu",
"//device/fido",
"//mojo/public/cpp/bindings",
"//services/device/public/mojom",
......
include_rules = [
"+components/apdu",
"+components/cbor",
"+crypto",
"+net/base",
......
......@@ -6,6 +6,7 @@
#include <utility>
#include "components/apdu/apdu_response.h"
#include "device/fido/u2f_response_test_data.h"
namespace device {
......@@ -26,28 +27,28 @@ void MockU2fDevice::DeviceTransact(std::vector<uint8_t> command,
// static
void MockU2fDevice::NotSatisfied(const std::vector<uint8_t>& cmd,
DeviceCallback& cb) {
std::move(cb).Run(true,
std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED));
std::move(cb).Run(
true, apdu::ApduResponse(
std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED));
}
// static
void MockU2fDevice::WrongData(const std::vector<uint8_t>& cmd,
DeviceCallback& cb) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_DATA));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_DATA));
}
// static
void MockU2fDevice::NoErrorSign(const std::vector<uint8_t>& cmd,
DeviceCallback& cb) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(
std::begin(test_data::kTestU2fSignResponse),
std::end(test_data::kTestU2fSignResponse)),
U2fApduResponse::Status::SW_NO_ERROR));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(
std::begin(test_data::kTestU2fSignResponse),
std::end(test_data::kTestU2fSignResponse)),
apdu::ApduResponse::Status::SW_NO_ERROR));
}
// static
......@@ -55,21 +56,21 @@ void MockU2fDevice::NoErrorRegister(const std::vector<uint8_t>& cmd,
DeviceCallback& cb) {
std::move(cb).Run(
true,
std::make_unique<U2fApduResponse>(
apdu::ApduResponse(
std::vector<uint8_t>(std::begin(test_data::kTestU2fRegisterResponse),
std::end(test_data::kTestU2fRegisterResponse)),
U2fApduResponse::Status::SW_NO_ERROR));
apdu::ApduResponse::Status::SW_NO_ERROR));
}
// static
void MockU2fDevice::SignWithCorruptedResponse(const std::vector<uint8_t>& cmd,
DeviceCallback& cb) {
std::move(cb).Run(
true, std::make_unique<U2fApduResponse>(
true, apdu::ApduResponse(
std::vector<uint8_t>(
std::begin(test_data::kTestCorruptedU2fSignResponse),
std::end(test_data::kTestCorruptedU2fSignResponse)),
U2fApduResponse::Status::SW_NO_ERROR));
apdu::ApduResponse::Status::SW_NO_ERROR));
}
// static
......
......@@ -7,7 +7,6 @@
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
......
// Copyright 2017 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 "base/memory/ptr_util.h"
#include "device/fido/u2f_apdu_response.h"
namespace device {
std::unique_ptr<U2fApduResponse> U2fApduResponse::CreateFromMessage(
const std::vector<uint8_t>& message) {
uint16_t status_bytes;
Status response_status;
// Invalid message size, data is appended by status byte
if (message.size() < 2)
return nullptr;
status_bytes = message[message.size() - 2] << 8;
status_bytes |= message[message.size() - 1];
response_status = static_cast<Status>(status_bytes);
std::vector<uint8_t> data(message.begin(), message.end() - 2);
return std::make_unique<U2fApduResponse>(std::move(data), response_status);
}
U2fApduResponse::U2fApduResponse(std::vector<uint8_t> message,
Status response_status)
: response_status_(response_status), data_(std::move(message)) {}
U2fApduResponse::~U2fApduResponse() = default;
} // namespace device
......@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/strings/string_piece.h"
#include "device/fido/u2f_apdu_response.h"
#include "components/apdu/apdu_response.h"
#include "device/fido/u2f_ble_frames.h"
#include "device/fido/u2f_ble_transaction.h"
......@@ -82,8 +82,8 @@ void U2fBleDevice::DeviceTransact(std::vector<uint8_t> command,
[](DeviceCallback callback, base::Optional<U2fBleFrame> frame) {
std::move(callback).Run(
frame.has_value(),
frame ? U2fApduResponse::CreateFromMessage(frame->data())
: nullptr);
frame ? apdu::ApduResponse::CreateFromMessage(frame->data())
: base::nullopt);
},
std::move(callback)));
Transition();
......
......@@ -15,7 +15,6 @@
#include "device/bluetooth/bluetooth_discovery_filter.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "device/fido/u2f_apdu_command.h"
#include "device/fido/u2f_ble_device.h"
#include "device/fido/u2f_ble_uuids.h"
......
......@@ -7,8 +7,7 @@
#include <utility>
#include "base/bind.h"
#include "device/fido/u2f_apdu_command.h"
#include "device/fido/u2f_apdu_response.h"
#include "components/apdu/apdu_command.h"
#include "device/fido/u2f_request.h"
namespace device {
......@@ -52,21 +51,21 @@ void U2fDevice::Version(VersionCallback callback) {
void U2fDevice::OnRegisterComplete(
MessageCallback callback,
bool success,
std::unique_ptr<U2fApduResponse> register_response) {
base::Optional<apdu::ApduResponse> register_response) {
if (!success || !register_response) {
std::move(callback).Run(U2fReturnCode::FAILURE, std::vector<uint8_t>());
return;
}
switch (register_response->status()) {
case U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
std::move(callback).Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
std::vector<uint8_t>());
break;
case U2fApduResponse::Status::SW_NO_ERROR:
case apdu::ApduResponse::Status::SW_NO_ERROR:
std::move(callback).Run(U2fReturnCode::SUCCESS,
register_response->data());
break;
case U2fApduResponse::Status::SW_WRONG_DATA:
case apdu::ApduResponse::Status::SW_WRONG_DATA:
std::move(callback).Run(U2fReturnCode::INVALID_PARAMS,
std::vector<uint8_t>());
break;
......@@ -76,23 +75,24 @@ void U2fDevice::OnRegisterComplete(
}
}
void U2fDevice::OnSignComplete(MessageCallback callback,
bool success,
std::unique_ptr<U2fApduResponse> sign_response) {
void U2fDevice::OnSignComplete(
MessageCallback callback,
bool success,
base::Optional<apdu::ApduResponse> sign_response) {
if (!success || !sign_response) {
std::move(callback).Run(U2fReturnCode::FAILURE, std::vector<uint8_t>());
return;
}
switch (sign_response->status()) {
case U2fApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
std::move(callback).Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
std::vector<uint8_t>());
break;
case U2fApduResponse::Status::SW_NO_ERROR:
case apdu::ApduResponse::Status::SW_NO_ERROR:
std::move(callback).Run(U2fReturnCode::SUCCESS, sign_response->data());
break;
case U2fApduResponse::Status::SW_WRONG_DATA:
case U2fApduResponse::Status::SW_WRONG_LENGTH:
case apdu::ApduResponse::Status::SW_WRONG_DATA:
case apdu::ApduResponse::Status::SW_WRONG_LENGTH:
default:
std::move(callback).Run(U2fReturnCode::INVALID_PARAMS,
std::vector<uint8_t>());
......@@ -104,9 +104,9 @@ void U2fDevice::OnVersionComplete(
VersionCallback callback,
bool legacy,
bool success,
std::unique_ptr<U2fApduResponse> version_response) {
base::Optional<apdu::ApduResponse> version_response) {
if (success && version_response &&
version_response->status() == U2fApduResponse::Status::SW_NO_ERROR &&
version_response->status() == apdu::ApduResponse::Status::SW_NO_ERROR &&
version_response->data() ==
std::vector<uint8_t>({'U', '2', 'F', '_', 'V', '2'})) {
std::move(callback).Run(success, ProtocolVersion::U2F_V2);
......
......@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "device/fido/u2f_apdu_response.h"
#include "components/apdu/apdu_response.h"
#include "device/fido/u2f_return_code.h"
namespace device {
......@@ -34,7 +34,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fDevice {
base::OnceCallback<void(bool success, ProtocolVersion version)>;
using DeviceCallback =
base::OnceCallback<void(bool success,
std::unique_ptr<U2fApduResponse> response)>;
base::Optional<apdu::ApduResponse> response)>;
using WinkCallback = base::OnceCallback<void()>;
static constexpr auto kDeviceTimeout = base::TimeDelta::FromSeconds(3);
......@@ -65,14 +65,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fDevice {
private:
void OnRegisterComplete(MessageCallback callback,
bool success,
std::unique_ptr<U2fApduResponse> register_response);
base::Optional<apdu::ApduResponse> register_response);
void OnSignComplete(MessageCallback callback,
bool success,
std::unique_ptr<U2fApduResponse> sign_response);
base::Optional<apdu::ApduResponse> sign_response);
void OnVersionComplete(VersionCallback callback,
bool legacy,
bool success,
std::unique_ptr<U2fApduResponse> version_response);
base::Optional<apdu::ApduResponse> version_response);
DISALLOW_COPY_AND_ASSIGN(U2fDevice);
};
......
......@@ -75,7 +75,7 @@ void U2fHidDevice::Transition(std::vector<uint8_t> command,
case State::DEVICE_ERROR:
default:
base::WeakPtr<U2fHidDevice> self = weak_factory_.GetWeakPtr();
repeating_callback.Run(false, nullptr);
repeating_callback.Run(false, base::nullopt);
// Executing callbacks may free |this|. Check |self| first.
while (self && !pending_transactions_.empty()) {
......@@ -83,7 +83,7 @@ void U2fHidDevice::Transition(std::vector<uint8_t> command,
DeviceCallback pending_cb =
std::move(pending_transactions_.front().second);
pending_transactions_.pop();
std::move(pending_cb).Run(false, nullptr);
std::move(pending_cb).Run(false, base::nullopt);
}
break;
}
......@@ -280,9 +280,11 @@ void U2fHidDevice::MessageReceived(DeviceCallback callback,
Transition(std::vector<uint8_t>(), std::move(callback));
return;
}
std::unique_ptr<U2fApduResponse> response = nullptr;
if (message)
response = U2fApduResponse::CreateFromMessage(message->GetMessagePayload());
auto response =
message
? apdu::ApduResponse::CreateFromMessage(message->GetMessagePayload())
: base::nullopt;
state_ = State::IDLE;
base::WeakPtr<U2fHidDevice> self = weak_factory_.GetWeakPtr();
......
......@@ -96,7 +96,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fHidDevice : public U2fDevice {
void ArmTimeout(DeviceCallback callback);
void OnTimeout(DeviceCallback callback);
void OnDeviceTransact(bool success,
std::unique_ptr<U2fApduResponse> response);
base::Optional<apdu::ApduResponse> response);
base::WeakPtr<U2fDevice> GetWeakPtr() override;
uint32_t channel_id_ = kBroadcastChannel;
......
......@@ -11,10 +11,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_mock_time_message_loop_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "components/apdu/apdu_command.h"
#include "components/apdu/apdu_response.h"
#include "device/fido/fake_hid_impl_for_testing.h"
#include "device/fido/test_callback_receiver.h"
#include "device/fido/u2f_apdu_command.h"
#include "device/fido/u2f_apdu_response.h"
#include "device/fido/u2f_command_type.h"
#include "device/fido/u2f_hid_device.h"
#include "device/fido/u2f_request.h"
......@@ -96,7 +96,8 @@ device::mojom::HidDeviceInfoPtr TestHidDevice() {
class U2fDeviceEnumerateCallbackReceiver
: public test::TestCallbackReceiver<std::vector<mojom::HidDeviceInfoPtr>> {
public:
U2fDeviceEnumerateCallbackReceiver(device::mojom::HidManager* hid_manager)
explicit U2fDeviceEnumerateCallbackReceiver(
device::mojom::HidManager* hid_manager)
: hid_manager_(hid_manager) {}
~U2fDeviceEnumerateCallbackReceiver() = default;
......@@ -124,7 +125,7 @@ class U2fDeviceEnumerateCallbackReceiver
using TestVersionCallbackReceiver =
test::StatusAndValueCallbackReceiver<bool, U2fDevice::ProtocolVersion>;
using TestDeviceCallbackReceiver = ::device::test::
StatusAndValueCallbackReceiver<bool, std::unique_ptr<U2fApduResponse>>;
StatusAndValueCallbackReceiver<bool, base::Optional<apdu::ApduResponse>>;
} // namespace
......@@ -201,7 +202,7 @@ TEST_F(U2fHidDeviceTest, TestConnectionFailure) {
// Manually delete connection.
device->connection_ = nullptr;
// Add pending transactions manually and ensure they are processed
// Add pending transactions manually and ensure they are processed.
TestDeviceCallbackReceiver receiver_1;
device->pending_transactions_.emplace(U2fRequest::GetU2fVersionApduCommand(),
receiver_1.callback());
......@@ -211,10 +212,11 @@ TEST_F(U2fHidDeviceTest, TestConnectionFailure) {
TestDeviceCallbackReceiver receiver_3;
device->DeviceTransact(U2fRequest::GetU2fVersionApduCommand(),
receiver_3.callback());
EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
EXPECT_EQ(nullptr, receiver_1.value());
EXPECT_EQ(nullptr, receiver_2.value());
EXPECT_EQ(nullptr, receiver_3.value());
EXPECT_EQ(base::nullopt, receiver_1.value());
EXPECT_EQ(base::nullopt, receiver_2.value());
EXPECT_EQ(base::nullopt, receiver_3.value());
}
TEST_F(U2fHidDeviceTest, TestDeviceError) {
......@@ -235,14 +237,14 @@ TEST_F(U2fHidDeviceTest, TestDeviceError) {
// Mock connection where writes always fail.
FakeHidConnection::mock_connection_error_ = true;
device->state_ = U2fHidDevice::State::IDLE;
TestDeviceCallbackReceiver receiver_0;
std::unique_ptr<U2fApduResponse> response_0(
U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
device->DeviceTransact(U2fRequest::GetU2fVersionApduCommand(),
receiver_0.callback());
EXPECT_EQ(nullptr, receiver_0.value());
EXPECT_EQ(base::nullopt, receiver_0.value());
EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
// Add pending transactions manually and ensure they are processed.
// Add pending transactions manually and ensure they are processed.
TestDeviceCallbackReceiver receiver_1;
device->pending_transactions_.emplace(U2fRequest::GetU2fVersionApduCommand(),
......@@ -256,9 +258,9 @@ TEST_F(U2fHidDeviceTest, TestDeviceError) {
FakeHidConnection::mock_connection_error_ = false;
EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
EXPECT_EQ(nullptr, receiver_1.value());
EXPECT_EQ(nullptr, receiver_2.value());
EXPECT_EQ(nullptr, receiver_3.value());
EXPECT_EQ(base::nullopt, receiver_1.value());
EXPECT_EQ(base::nullopt, receiver_2.value());
EXPECT_EQ(base::nullopt, receiver_3.value());
}
TEST_F(U2fHidDeviceTest, TestLegacyVersion) {
......@@ -350,7 +352,7 @@ TEST_F(U2fHidDeviceTest, TestRetryChannelAllocation) {
MockHidConnection mock_connection(
hid_device.Clone(), mojo::MakeRequest(&connection_client), kChannelId);
// Delegate custom functions to be invoked for mock hid connection
// Delegate custom functions to be invoked for mock hid connection.
EXPECT_CALL(mock_connection, WritePtr(_, _, _))
// HID_INIT request to authenticator for channel allocation.
.WillOnce(WithArgs<1, 2>(
......@@ -392,7 +394,7 @@ TEST_F(U2fHidDeviceTest, TestRetryChannelAllocation) {
mock_connection.connection_channel_id()));
})));
// Add device and set mock connection to fake hid manager
// Add device and set mock connection to fake hid manager.
fake_hid_manager_->AddDeviceAndSetConnection(std::move(hid_device),
std::move(connection_client));
......
......@@ -12,7 +12,7 @@
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "device/fido/u2f_apdu_command.h"
#include "components/apdu/apdu_command.h"
#include "services/service_manager/public/cpp/connector.h"
namespace device {
......@@ -49,7 +49,7 @@ void U2fRequest::Start() {
// static
std::vector<uint8_t> U2fRequest::GetBogusRegisterCommand() {
U2fApduCommand command;
apdu::ApduCommand command;
std::vector<uint8_t> data(kBogusChallenge.cbegin(), kBogusChallenge.cend());
data.insert(data.end(), kBogusAppParam.cbegin(), kBogusAppParam.cend());
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kRegister));
......@@ -61,7 +61,7 @@ std::vector<uint8_t> U2fRequest::GetBogusRegisterCommand() {
// static
std::vector<uint8_t> U2fRequest::GetU2fVersionApduCommand(
bool is_legacy_version) {
U2fApduCommand command;
apdu::ApduCommand command;
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kVersion));
// Set maximum expected response length to maximum length possible.
command.set_response_length(kU2fMaxResponseSize);
......@@ -85,7 +85,7 @@ base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fSignApduCommand(
key_handle.size() > kMaxKeyHandleLength) {
return base::nullopt;
}
U2fApduCommand command;
apdu::ApduCommand command;
std::vector<uint8_t> data(challenge_digest_.begin(), challenge_digest_.end());
data.insert(data.end(), application_parameter.begin(),
application_parameter.end());
......@@ -103,7 +103,7 @@ base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fRegisterApduCommand(
challenge_digest_.size() != kU2fParameterLength) {
return base::nullopt;
}
U2fApduCommand command;
apdu::ApduCommand command;
std::vector<uint8_t> data(challenge_digest_.begin(), challenge_digest_.end());
data.insert(data.end(), application_parameter_.begin(),
application_parameter_.end());
......
......@@ -16,7 +16,6 @@
#include "base/macros.h"
#include "base/optional.h"
#include "device/fido/fido_constants.h"
#include "device/fido/u2f_apdu_command.h"
#include "device/fido/u2f_device.h"
#include "device/fido/u2f_discovery.h"
#include "device/fido/u2f_transport_protocol.h"
......
......@@ -7,11 +7,12 @@
#include <utility>
#include "base/numerics/safe_conversions.h"
#include "components/apdu/apdu_command.h"
#include "components/apdu/apdu_response.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "crypto/sha2.h"
#include "device/fido/fido_constants.h"
#include "device/fido/u2f_apdu_command.h"
namespace device {
......@@ -130,7 +131,7 @@ void VirtualU2fDevice::AddRegistration(
void VirtualU2fDevice::DeviceTransact(std::vector<uint8_t> command,
DeviceCallback cb) {
// Note, here we are using the code-under-test in this fake.
auto parsed_command = U2fApduCommand::CreateFromMessageForTesting(command);
auto parsed_command = apdu::ApduCommand::CreateFromMessage(command);
switch (parsed_command->ins()) {
case base::strict_cast<uint8_t>(U2fApduInstruction::kVersion):
break;
......@@ -143,10 +144,10 @@ void VirtualU2fDevice::DeviceTransact(std::vector<uint8_t> command,
parsed_command->data(), std::move(cb));
break;
default:
std::move(cb).Run(true,
std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_INS_NOT_SUPPORTED));
std::move(cb).Run(
true,
apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED));
}
}
......@@ -160,9 +161,9 @@ void VirtualU2fDevice::DoRegister(uint8_t ins,
base::span<const uint8_t> data,
DeviceCallback cb) {
if (data.size() != 64) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_LENGTH));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_LENGTH));
return;
}
......@@ -223,8 +224,8 @@ void VirtualU2fDevice::DoRegister(uint8_t ins,
1);
std::move(cb).Run(
true, std::make_unique<U2fApduResponse>(
std::move(response), U2fApduResponse::Status::SW_NO_ERROR));
true, apdu::ApduResponse(std::move(response),
apdu::ApduResponse::Status::SW_NO_ERROR));
}
void VirtualU2fDevice::DoSign(uint8_t ins,
......@@ -235,9 +236,9 @@ void VirtualU2fDevice::DoSign(uint8_t ins,
if (!(p1 == kP1CheckOnly || p1 == kP1TupRequiredConsumed ||
p1 == kP1IndividualAttestation) ||
p2 != 0) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_DATA));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_DATA));
return;
}
......@@ -247,15 +248,15 @@ void VirtualU2fDevice::DoSign(uint8_t ins,
if (key_handle_length != 32) {
// Our own keyhandles are always 32 bytes long, if the request has something
// else then we already know it is not ours.
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_DATA));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_DATA));
return;
}
if (data.size() != 32 + 32 + 1 + key_handle_length) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_LENGTH));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_LENGTH));
return;
}
auto key_handle = data.last(key_handle_length);
......@@ -265,9 +266,9 @@ void VirtualU2fDevice::DoSign(uint8_t ins,
std::vector<uint8_t>(key_handle.cbegin(), key_handle.cend()));
if (it == registrations_.end()) {
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_DATA));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_DATA));
return;
}
......@@ -276,9 +277,9 @@ void VirtualU2fDevice::DoSign(uint8_t ins,
if (app_id_hash != registered_app_id_hash) {
// It's important this error looks identical to the previous one, as
// tokens should not reveal the existence of keyHandles to unrelated appIds.
std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
std::vector<uint8_t>(),
U2fApduResponse::Status::SW_WRONG_DATA));
std::move(cb).Run(
true, apdu::ApduResponse(std::vector<uint8_t>(),
apdu::ApduResponse::Status::SW_WRONG_DATA));
return;
}
......@@ -311,8 +312,8 @@ void VirtualU2fDevice::DoSign(uint8_t ins,
AppendTo(&response, sig);
std::move(cb).Run(
true, std::make_unique<U2fApduResponse>(
std::move(response), U2fApduResponse::Status::SW_NO_ERROR));
true, apdu::ApduResponse(std::move(response),
apdu::ApduResponse::Status::SW_NO_ERROR));
}
} // 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