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