1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Copyright (C) 2018 Apple Inc. All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <WebCore/FidoConstants.h>
35 #include <WebCore/FidoHidMessage.h>
36 #include <WebCore/FidoHidPacket.h>
37 #include <wtf/Deque.h>
38 #include <wtf/Vector.h>
40 namespace TestWebKitAPI {
44 // Packets should be 64 bytes + 1 report ID byte.
45 TEST(FidoHidMessageTest, TestPacketSize)
47 uint32_t channelId = 0x05060708;
50 auto initPacket = std::make_unique<FidoHidInitPacket>(channelId, FidoHidDeviceCommand::kInit, Vector<uint8_t>(data), data.size());
51 EXPECT_EQ(64u, initPacket->getSerializedData().size());
53 auto continuationPacket = std::make_unique<FidoHidContinuationPacket>(channelId, 0, WTFMove(data));
54 EXPECT_EQ(64u, continuationPacket->getSerializedData().size());
58 * U2f Init Packets are of the format:
60 * Byte 1-4: Channel ID
61 * Byte 5: Command byte
62 * Byte 6-7: Big Endian size of data
63 * Byte 8-n: Data block
65 * Remaining buffer is padded with 0
67 TEST(FidoHidMessageTest, TestPacketData)
69 uint32_t channelId = 0xF5060708;
70 Vector<uint8_t> data {10, 11};
71 FidoHidDeviceCommand cmd = FidoHidDeviceCommand::kWink;
72 auto initPacket = std::make_unique<FidoHidInitPacket>(channelId, cmd, Vector<uint8_t>(data), data.size());
75 Vector<uint8_t> serialized = initPacket->getSerializedData();
76 EXPECT_EQ((channelId >> 24) & 0xff, serialized[index++]);
77 EXPECT_EQ((channelId >> 16) & 0xff, serialized[index++]);
78 EXPECT_EQ((channelId >> 8) & 0xff, serialized[index++]);
79 EXPECT_EQ(channelId & 0xff, serialized[index++]);
80 EXPECT_EQ(static_cast<uint8_t>(cmd), serialized[index++] & 0x7f);
82 EXPECT_EQ(data.size() >> 8, serialized[index++]);
83 EXPECT_EQ(data.size() & 0xff, serialized[index++]);
84 EXPECT_EQ(data[0], serialized[index++]);
85 EXPECT_EQ(data[1], serialized[index++]);
86 for (; index < serialized.size(); index++)
87 EXPECT_EQ(0, serialized[index]) << "mismatch at index " << index;
90 TEST(FidoHidMessageTest, TestPacketConstructors)
92 uint32_t channelId = 0x05060708;
93 Vector<uint8_t> data {10, 11};
94 FidoHidDeviceCommand cmd = FidoHidDeviceCommand::kWink;
95 size_t length = data.size();
96 auto origPacket = std::make_unique<FidoHidInitPacket>(channelId, cmd, WTFMove(data), length);
98 size_t payloadLength = static_cast<size_t>(origPacket->payloadLength());
99 Vector<uint8_t> origData = origPacket->getSerializedData();
101 auto reconstructedPacket = FidoHidInitPacket::createFromSerializedData(origData, &payloadLength);
102 EXPECT_EQ(origPacket->command(), reconstructedPacket->command());
103 EXPECT_EQ(origPacket->payloadLength(), reconstructedPacket->payloadLength());
104 EXPECT_EQ(origPacket->getPacketPayload(), reconstructedPacket->getPacketPayload());
106 EXPECT_EQ(channelId, reconstructedPacket->channelId());
108 ASSERT_EQ(origPacket->getSerializedData().size(), reconstructedPacket->getSerializedData().size());
109 for (size_t index = 0; index < origPacket->getSerializedData().size(); ++index)
110 EXPECT_EQ(origPacket->getSerializedData()[index], reconstructedPacket->getSerializedData()[index]) << "mismatch at index " << index;
113 TEST(FidoHidMessageTest, TestMaxLengthPacketConstructors)
115 uint32_t channelId = 0xAAABACAD;
116 Vector<uint8_t> data;
117 for (size_t i = 0; i < kHidMaxMessageSize; ++i)
118 data.append(static_cast<uint8_t>(i % 0xff));
120 auto origMsg = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kMsg, data);
121 ASSERT_TRUE(origMsg);
123 const auto& originalMsgPackets = origMsg->getPacketsForTesting();
124 auto it = originalMsgPackets.begin();
125 auto msgData = (*it)->getSerializedData();
126 auto newMsg = FidoHidMessage::createFromSerializedData(msgData);
129 for (; it != originalMsgPackets.end(); ++it) {
130 msgData = (*it)->getSerializedData();
131 EXPECT_TRUE(newMsg->addContinuationPacket(msgData));
134 auto origIt = originalMsgPackets.begin();
135 const auto& newMsgPackets = newMsg->getPacketsForTesting();
136 auto newMsgIt = newMsgPackets.begin();
138 EXPECT_EQ(origMsg->numPackets(), newMsg->numPackets());
139 for (; origIt != originalMsgPackets.end() || newMsgIt != newMsgPackets.end(); ++origIt, ++newMsgIt) {
140 EXPECT_EQ((*origIt)->getPacketPayload(), (*newMsgIt)->getPacketPayload());
142 EXPECT_EQ((*origIt)->channelId(), (*newMsgIt)->channelId());
144 ASSERT_EQ((*origIt)->getSerializedData().size(), (*newMsgIt)->getSerializedData().size());
145 for (size_t index = 0; index < (*origIt)->getSerializedData().size(); ++index)
146 EXPECT_EQ((*origIt)->getSerializedData()[index], (*newMsgIt)->getSerializedData()[index]) << "mismatch at index " << index;
150 TEST(FidoHidMessageTest, TestMessagePartitoning)
152 uint32_t channelId = 0x01010203;
153 Vector<uint8_t> data(kHidInitPacketDataSize + 1);
154 auto twoPacketMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
155 ASSERT_TRUE(twoPacketMessage);
156 EXPECT_EQ(2U, twoPacketMessage->numPackets());
158 data.resize(kHidInitPacketDataSize);
159 auto onePacketMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
160 ASSERT_TRUE(onePacketMessage);
161 EXPECT_EQ(1U, onePacketMessage->numPackets());
163 data.resize(kHidInitPacketDataSize + kHidContinuationPacketDataSize + 1);
164 auto threePacketMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
165 ASSERT_TRUE(threePacketMessage);
166 EXPECT_EQ(3U, threePacketMessage->numPackets());
169 TEST(FidoHidMessageTest, TestMaxSize)
171 uint32_t channelId = 0x00010203;
172 Vector<uint8_t> data(kHidMaxMessageSize + 1);
173 auto oversizeMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
174 EXPECT_FALSE(oversizeMessage);
177 TEST(FidoHidMessageTest, TestDeconstruct)
179 uint32_t channelId = 0x0A0B0C0D;
180 Vector<uint8_t> data(kHidMaxMessageSize, 0x7F);
181 auto filledMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
182 ASSERT_TRUE(filledMessage);
183 EXPECT_EQ(data, filledMessage->getMessagePayload());
186 TEST(FidoHidMessageTest, TestDeserialize)
188 uint32_t channelId = 0x0A0B0C0D;
189 Vector<uint8_t> data(kHidMaxMessageSize);
191 auto origMessage = FidoHidMessage::create(channelId, FidoHidDeviceCommand::kPing, data);
192 ASSERT_TRUE(origMessage);
194 Deque<Vector<uint8_t>> origList;
195 auto buf = origMessage->popNextPacket();
196 origList.append(buf);
198 auto newMessage = FidoHidMessage::createFromSerializedData(buf);
199 while (!newMessage->messageComplete()) {
200 buf = origMessage->popNextPacket();
201 origList.append(buf);
202 newMessage->addContinuationPacket(buf);
205 while (!(buf = newMessage->popNextPacket()).isEmpty()) {
206 EXPECT_EQ(buf, origList.first());
207 origList.removeFirst();
211 } // namespace TestWebKitAPI
213 #endif // ENABLE(WEB_AUTHN)