123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // 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_command.h"
- #include "components/apdu/apdu_response.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace apdu {
- TEST(ApduTest, TestDeserializeBasic) {
- uint8_t cla = 0xAA;
- uint8_t ins = 0xAB;
- uint8_t p1 = 0xAC;
- uint8_t p2 = 0xAD;
- std::vector<uint8_t> message({cla, ins, p1, p2});
- const auto cmd = ApduCommand::CreateFromMessage(message);
- ASSERT_TRUE(cmd);
- EXPECT_EQ(0u, cmd->response_length_);
- EXPECT_TRUE(cmd->data_.empty());
- EXPECT_EQ(cla, cmd->cla_);
- EXPECT_EQ(ins, cmd->ins_);
- EXPECT_EQ(p1, cmd->p1_);
- EXPECT_EQ(p2, cmd->p2_);
- // Invalid length.
- message = {cla, ins, p1};
- EXPECT_FALSE(ApduCommand::CreateFromMessage(message));
- message.push_back(p2);
- message.push_back(0);
- // Set APDU command data size as maximum.
- message.push_back(0xFF);
- message.push_back(0xFF);
- message.resize(message.size() + ApduCommand::kApduMaxDataLength);
- // Set maximum response size.
- message.push_back(0);
- message.push_back(0);
- // |message| is APDU encoded byte array with maximum data length.
- EXPECT_TRUE(ApduCommand::CreateFromMessage(message));
- message.push_back(0);
- // |message| encoding containing data of size maximum data length + 1.
- EXPECT_FALSE(ApduCommand::CreateFromMessage(message));
- }
- TEST(ApduTest, TestDeserializeComplex) {
- uint8_t cla = 0xAA;
- uint8_t ins = 0xAB;
- uint8_t p1 = 0xAC;
- uint8_t p2 = 0xAD;
- std::vector<uint8_t> data(
- ApduCommand::kApduMaxDataLength - ApduCommand::kApduMaxHeader - 2, 0x7F);
- std::vector<uint8_t> message = {cla, ins, p1, p2, 0};
- message.push_back((data.size() >> 8) & 0xff);
- message.push_back(data.size() & 0xff);
- message.insert(message.end(), data.begin(), data.end());
- // Create a message with no response expected.
- const auto cmd_no_response = ApduCommand::CreateFromMessage(message);
- ASSERT_TRUE(cmd_no_response);
- EXPECT_EQ(0u, cmd_no_response->response_length_);
- EXPECT_THAT(data, ::testing::ContainerEq(cmd_no_response->data_));
- EXPECT_EQ(cla, cmd_no_response->cla_);
- EXPECT_EQ(ins, cmd_no_response->ins_);
- EXPECT_EQ(p1, cmd_no_response->p1_);
- EXPECT_EQ(p2, cmd_no_response->p2_);
- // Add response length to message.
- message.push_back(0xF1);
- message.push_back(0xD0);
- const auto cmd = ApduCommand::CreateFromMessage(message);
- ASSERT_TRUE(cmd);
- EXPECT_THAT(data, ::testing::ContainerEq(cmd->data_));
- EXPECT_EQ(cla, cmd->cla_);
- EXPECT_EQ(ins, cmd->ins_);
- EXPECT_EQ(p1, cmd->p1_);
- EXPECT_EQ(p2, cmd->p2_);
- EXPECT_EQ(static_cast<size_t>(0xF1D0), cmd->response_length_);
- }
- TEST(ApduTest, TestDeserializeResponse) {
- ApduResponse::Status status;
- std::vector<uint8_t> test_vector;
- // Invalid length.
- std::vector<uint8_t> message({0xAA});
- EXPECT_FALSE(ApduResponse::CreateFromMessage(message));
- // Valid length and status.
- status = ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED;
- message = {static_cast<uint8_t>(static_cast<uint16_t>(status) >> 8),
- static_cast<uint8_t>(status)};
- auto response = ApduResponse::CreateFromMessage(message);
- ASSERT_TRUE(response);
- EXPECT_EQ(ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED,
- response->response_status_);
- EXPECT_THAT(response->data_, ::testing::ContainerEq(std::vector<uint8_t>()));
- // Valid length and status.
- status = ApduResponse::Status::SW_NO_ERROR;
- message = {static_cast<uint8_t>(static_cast<uint16_t>(status) >> 8),
- static_cast<uint8_t>(status)};
- test_vector = {0x01, 0x02, 0xEF, 0xFF};
- message.insert(message.begin(), test_vector.begin(), test_vector.end());
- response = ApduResponse::CreateFromMessage(message);
- ASSERT_TRUE(response);
- EXPECT_EQ(ApduResponse::Status::SW_NO_ERROR, response->response_status_);
- EXPECT_THAT(response->data_, ::testing::ContainerEq(test_vector));
- }
- TEST(ApduTest, TestSerializeCommand) {
- ApduCommand cmd;
- cmd.set_cla(0xA);
- cmd.set_ins(0xB);
- cmd.set_p1(0xC);
- cmd.set_p2(0xD);
- // No data, no response expected.
- std::vector<uint8_t> expected({0xA, 0xB, 0xC, 0xD});
- ASSERT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
- auto deserialized_cmd = ApduCommand::CreateFromMessage(expected);
- ASSERT_TRUE(deserialized_cmd);
- EXPECT_THAT(expected,
- ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
- // No data, response expected.
- cmd.set_response_length(0xCAFE);
- expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0xCA, 0xFE};
- EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
- deserialized_cmd = ApduCommand::CreateFromMessage(expected);
- ASSERT_TRUE(deserialized_cmd);
- EXPECT_THAT(expected,
- ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
- // Data exists, response expected.
- std::vector<uint8_t> data({0x1, 0x2, 0x3, 0x4});
- cmd.set_data(data);
- expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x4,
- 0x1, 0x2, 0x3, 0x4, 0xCA, 0xFE};
- EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
- deserialized_cmd = ApduCommand::CreateFromMessage(expected);
- ASSERT_TRUE(deserialized_cmd);
- EXPECT_THAT(expected,
- ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
- // Data exists, no response expected.
- cmd.set_response_length(0);
- expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4};
- EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
- EXPECT_THAT(
- expected,
- ::testing::ContainerEq(
- ApduCommand::CreateFromMessage(expected)->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 apdu
|