1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/apdu/apdu_command.h"
6 #include "components/apdu/apdu_response.h"
7 #include "testing/gmock/include/gmock/gmock.h"
8 #include "testing/gtest/include/gtest/gtest.h"
12 TEST(ApduTest, TestDeserializeBasic) {
17 std::vector<uint8_t> message({cla, ins, p1, p2});
18 const auto cmd = ApduCommand::CreateFromMessage(message);
20 EXPECT_EQ(0u, cmd->response_length_);
21 EXPECT_TRUE(cmd->data_.empty());
22 EXPECT_EQ(cla, cmd->cla_);
23 EXPECT_EQ(ins, cmd->ins_);
24 EXPECT_EQ(p1, cmd->p1_);
25 EXPECT_EQ(p2, cmd->p2_);
27 message = {cla, ins, p1};
28 EXPECT_FALSE(ApduCommand::CreateFromMessage(message));
29 message.push_back(p2);
31 // Set APDU command data size as maximum.
32 message.push_back(0xFF);
33 message.push_back(0xFF);
34 message.resize(message.size() + ApduCommand::kApduMaxDataLength);
35 // Set maximum response size.
38 // |message| is APDU encoded byte array with maximum data length.
39 EXPECT_TRUE(ApduCommand::CreateFromMessage(message));
41 // |message| encoding containing data of size maximum data length + 1.
42 EXPECT_FALSE(ApduCommand::CreateFromMessage(message));
45 TEST(ApduTest, TestDeserializeComplex) {
50 std::vector<uint8_t> data(
51 ApduCommand::kApduMaxDataLength - ApduCommand::kApduMaxHeader - 2, 0x7F);
52 std::vector<uint8_t> message = {cla, ins, p1, p2, 0};
53 message.push_back((data.size() >> 8) & 0xff);
54 message.push_back(data.size() & 0xff);
55 message.insert(message.end(), data.begin(), data.end());
57 // Create a message with no response expected.
58 const auto cmd_no_response = ApduCommand::CreateFromMessage(message);
59 ASSERT_TRUE(cmd_no_response);
60 EXPECT_EQ(0u, cmd_no_response->response_length_);
61 EXPECT_THAT(data, ::testing::ContainerEq(cmd_no_response->data_));
62 EXPECT_EQ(cla, cmd_no_response->cla_);
63 EXPECT_EQ(ins, cmd_no_response->ins_);
64 EXPECT_EQ(p1, cmd_no_response->p1_);
65 EXPECT_EQ(p2, cmd_no_response->p2_);
67 // Add response length to message.
68 message.push_back(0xF1);
69 message.push_back(0xD0);
70 const auto cmd = ApduCommand::CreateFromMessage(message);
72 EXPECT_THAT(data, ::testing::ContainerEq(cmd->data_));
73 EXPECT_EQ(cla, cmd->cla_);
74 EXPECT_EQ(ins, cmd->ins_);
75 EXPECT_EQ(p1, cmd->p1_);
76 EXPECT_EQ(p2, cmd->p2_);
77 EXPECT_EQ(static_cast<size_t>(0xF1D0), cmd->response_length_);
80 TEST(ApduTest, TestDeserializeResponse) {
81 ApduResponse::Status status;
82 std::vector<uint8_t> test_vector;
84 std::vector<uint8_t> message({0xAA});
85 EXPECT_FALSE(ApduResponse::CreateFromMessage(message));
86 // Valid length and status.
87 status = ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED;
88 message = {static_cast<uint8_t>(static_cast<uint16_t>(status) >> 8),
89 static_cast<uint8_t>(status)};
90 auto response = ApduResponse::CreateFromMessage(message);
91 ASSERT_TRUE(response);
92 EXPECT_EQ(ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED,
93 response->response_status_);
94 EXPECT_THAT(response->data_, ::testing::ContainerEq(std::vector<uint8_t>()));
95 // Valid length and status.
96 status = ApduResponse::Status::SW_NO_ERROR;
97 message = {static_cast<uint8_t>(static_cast<uint16_t>(status) >> 8),
98 static_cast<uint8_t>(status)};
99 test_vector = {0x01, 0x02, 0xEF, 0xFF};
100 message.insert(message.begin(), test_vector.begin(), test_vector.end());
101 response = ApduResponse::CreateFromMessage(message);
102 ASSERT_TRUE(response);
103 EXPECT_EQ(ApduResponse::Status::SW_NO_ERROR, response->response_status_);
104 EXPECT_THAT(response->data_, ::testing::ContainerEq(test_vector));
106 TEST(ApduTest, TestSerializeCommand) {
112 // No data, no response expected.
113 std::vector<uint8_t> expected({0xA, 0xB, 0xC, 0xD});
114 ASSERT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
115 auto deserialized_cmd = ApduCommand::CreateFromMessage(expected);
116 ASSERT_TRUE(deserialized_cmd);
117 EXPECT_THAT(expected,
118 ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
119 // No data, response expected.
120 cmd.set_response_length(0xCAFE);
121 expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0xCA, 0xFE};
122 EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
123 deserialized_cmd = ApduCommand::CreateFromMessage(expected);
124 ASSERT_TRUE(deserialized_cmd);
125 EXPECT_THAT(expected,
126 ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
127 // Data exists, response expected.
128 std::vector<uint8_t> data({0x1, 0x2, 0x3, 0x4});
130 expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x4,
131 0x1, 0x2, 0x3, 0x4, 0xCA, 0xFE};
132 EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
133 deserialized_cmd = ApduCommand::CreateFromMessage(expected);
134 ASSERT_TRUE(deserialized_cmd);
135 EXPECT_THAT(expected,
136 ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
137 // Data exists, no response expected.
138 cmd.set_response_length(0);
139 expected = {0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4};
140 EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
143 ::testing::ContainerEq(
144 ApduCommand::CreateFromMessage(expected)->GetEncodedCommand()));
146 TEST(ApduTest, TestSerializeEdgeCases) {
152 // Set response length to maximum, which should serialize to 0x0000.
153 cmd.set_response_length(ApduCommand::kApduMaxResponseLength);
154 std::vector<uint8_t> expected({0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x0});
155 EXPECT_THAT(expected, ::testing::ContainerEq(cmd.GetEncodedCommand()));
156 auto deserialized_cmd = ApduCommand::CreateFromMessage(expected);
157 ASSERT_TRUE(deserialized_cmd);
158 EXPECT_THAT(expected,
159 ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));
160 // Maximum data size.
161 std::vector<uint8_t> oversized(ApduCommand::kApduMaxDataLength);
162 cmd.set_data(oversized);
163 deserialized_cmd = ApduCommand::CreateFromMessage(cmd.GetEncodedCommand());
164 ASSERT_TRUE(deserialized_cmd);
165 EXPECT_THAT(cmd.GetEncodedCommand(),
166 ::testing::ContainerEq(deserialized_cmd->GetEncodedCommand()));