Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: device/u2f/u2f_apdu_command.cc

Issue 2665493002: Add builders to APDU command class (Closed)
Patch Set: Add suffix for legacy version case and add additional unittests Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/u2f/u2f_apdu_command.h ('k') | device/u2f/u2f_apdu_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "u2f_apdu_command.h" 5 #include "u2f_apdu_command.h"
6 6
7 namespace device { 7 namespace device {
8 8
9 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateFromMessage( 9 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateFromMessage(
10 const std::vector<uint8_t>& message) { 10 const std::vector<uint8_t>& message) {
11 uint16_t data_length = 0; 11 uint16_t data_length = 0;
12 size_t index = 0, response_length = 0; 12 size_t index = 0;
13 size_t response_length = 0;
13 std::vector<uint8_t> data; 14 std::vector<uint8_t> data;
15 std::vector<uint8_t> suffix;
14 16
15 if (message.size() < kApduMinHeader || message.size() > kApduMaxLength) 17 if (message.size() < kApduMinHeader || message.size() > kApduMaxLength)
16 return nullptr; 18 return nullptr;
17 uint8_t cla = message[index++]; 19 uint8_t cla = message[index++];
18 uint8_t ins = message[index++]; 20 uint8_t ins = message[index++];
19 uint8_t p1 = message[index++]; 21 uint8_t p1 = message[index++];
20 uint8_t p2 = message[index++]; 22 uint8_t p2 = message[index++];
21 23
22 switch (message.size()) { 24 switch (message.size()) {
23 // No data present; no expected response 25 // No data present; no expected response
(...skipping 28 matching lines...) Expand all
52 } else if (message.size() == data_length + index + 2) { 54 } else if (message.size() == data_length + index + 2) {
53 // Maximum response size is stored in final 2 bytes 55 // Maximum response size is stored in final 2 bytes
54 data.insert(data.end(), message.begin() + index, message.end() - 2); 56 data.insert(data.end(), message.begin() + index, message.end() - 2);
55 index += data_length; 57 index += data_length;
56 response_length = message[index++] << 8; 58 response_length = message[index++] << 8;
57 response_length |= message[index++]; 59 response_length |= message[index++];
58 // Special case where response length of 0x0000 corresponds to 65536 60 // Special case where response length of 0x0000 corresponds to 65536
59 // Defined in ISO7816-4 61 // Defined in ISO7816-4
60 if (response_length == 0) 62 if (response_length == 0)
61 response_length = kApduMaxResponseLength; 63 response_length = kApduMaxResponseLength;
64 // Non-ISO7816-4 special legacy case where 2 suffix bytes are passed
65 // along with a version message
66 if (data_length == 0 && ins == kInsU2fVersion)
67 suffix = {0x0, 0x0};
62 } else { 68 } else {
63 return nullptr; 69 return nullptr;
64 } 70 }
65 break; 71 break;
66 } 72 }
67 73
68 return make_scoped_refptr( 74 return make_scoped_refptr(new U2fApduCommand(
69 new U2fApduCommand(cla, ins, p1, p2, response_length, std::move(data))); 75 cla, ins, p1, p2, response_length, std::move(data), std::move(suffix)));
70 } 76 }
71 77
72 // static 78 // static
73 scoped_refptr<U2fApduCommand> U2fApduCommand::Create() { 79 scoped_refptr<U2fApduCommand> U2fApduCommand::Create() {
74 return make_scoped_refptr(new U2fApduCommand()); 80 return make_scoped_refptr(new U2fApduCommand());
75 } 81 }
76 82
77 std::vector<uint8_t> U2fApduCommand::GetEncodedCommand() const { 83 std::vector<uint8_t> U2fApduCommand::GetEncodedCommand() const {
78 std::vector<uint8_t> encoded = {cla_, ins_, p1_, p2_}; 84 std::vector<uint8_t> encoded = {cla_, ins_, p1_, p2_};
79 85
(...skipping 11 matching lines...) Expand all
91 encoded.push_back(data_length & 0xff); 97 encoded.push_back(data_length & 0xff);
92 encoded.insert(encoded.end(), data_.begin(), data_.begin() + data_length); 98 encoded.insert(encoded.end(), data_.begin(), data_.begin() + data_length);
93 } else if (response_length_ > 0) { 99 } else if (response_length_ > 0) {
94 encoded.push_back(0x0); 100 encoded.push_back(0x0);
95 } 101 }
96 102
97 if (response_length_ > 0) { 103 if (response_length_ > 0) {
98 encoded.push_back((response_length_ >> 8) & 0xff); 104 encoded.push_back((response_length_ >> 8) & 0xff);
99 encoded.push_back(response_length_ & 0xff); 105 encoded.push_back(response_length_ & 0xff);
100 } 106 }
107 // Add suffix, if required, for legacy compatibility
108 encoded.insert(encoded.end(), suffix_.begin(), suffix_.end());
101 return encoded; 109 return encoded;
102 } 110 }
103 111
104 U2fApduCommand::U2fApduCommand() 112 U2fApduCommand::U2fApduCommand()
105 : cla_(0), ins_(0), p1_(0), p2_(0), response_length_(0) {} 113 : cla_(0), ins_(0), p1_(0), p2_(0), response_length_(0) {}
106 114
107 U2fApduCommand::U2fApduCommand(uint8_t cla, 115 U2fApduCommand::U2fApduCommand(uint8_t cla,
108 uint8_t ins, 116 uint8_t ins,
109 uint8_t p1, 117 uint8_t p1,
110 uint8_t p2, 118 uint8_t p2,
111 size_t response_length, 119 size_t response_length,
112 std::vector<uint8_t> data) 120 std::vector<uint8_t> data,
121 std::vector<uint8_t> suffix)
113 : cla_(cla), 122 : cla_(cla),
114 ins_(ins), 123 ins_(ins),
115 p1_(p1), 124 p1_(p1),
116 p2_(p2), 125 p2_(p2),
117 response_length_(response_length), 126 response_length_(response_length),
118 data_(std::move(data)) {} 127 data_(std::move(data)),
128 suffix_(std::move(suffix)) {}
119 129
120 U2fApduCommand::~U2fApduCommand() {} 130 U2fApduCommand::~U2fApduCommand() {}
121 131
132 // static
133 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateRegister(
134 const std::vector<uint8_t>& appid_digest,
135 const std::vector<uint8_t>& challenge_digest) {
136 if (appid_digest.size() != kAppIdDigestLen ||
137 challenge_digest.size() != kChallengeDigestLen) {
138 return nullptr;
139 }
140
141 scoped_refptr<U2fApduCommand> command = Create();
142 std::vector<uint8_t> data(challenge_digest.begin(), challenge_digest.end());
143 data.insert(data.end(), appid_digest.begin(), appid_digest.end());
144 command->set_ins(kInsU2fEnroll);
145 command->set_p1(kP1TupRequiredConsumed);
146 command->set_data(data);
147 return command;
148 }
149
150 // static
151 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateVersion() {
152 scoped_refptr<U2fApduCommand> command = Create();
153 command->set_ins(kInsU2fVersion);
154 command->set_response_length(kApduMaxResponseLength);
155 return command;
156 }
157
158 // static
159 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateLegacyVersion() {
160 scoped_refptr<U2fApduCommand> command = Create();
161 command->set_ins(kInsU2fVersion);
162 command->set_response_length(kApduMaxResponseLength);
163 // Early U2F drafts defined the U2F version command in extended
164 // length ISO 7816-4 format so 2 additional 0x0 bytes are necessary.
165 // https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-messa ge-formats-v1.1-id-20160915.html#implementation-considerations
166 command->set_suffix(std::vector<uint8_t>(2, 0));
167 return command;
168 }
169
170 // static
171 scoped_refptr<U2fApduCommand> U2fApduCommand::CreateSign(
172 const std::vector<uint8_t>& appid_digest,
173 const std::vector<uint8_t>& challenge_digest,
174 const std::vector<uint8_t>& key_handle) {
175 if (appid_digest.size() != kAppIdDigestLen ||
176 challenge_digest.size() != kChallengeDigestLen ||
177 key_handle.size() > kMaxKeyHandleLength) {
178 return nullptr;
179 }
180
181 scoped_refptr<U2fApduCommand> command = Create();
182 std::vector<uint8_t> data(challenge_digest.begin(), challenge_digest.end());
183 data.insert(data.end(), appid_digest.begin(), appid_digest.end());
184 data.push_back(static_cast<uint8_t>(key_handle.size()));
185 data.insert(data.end(), key_handle.begin(), key_handle.end());
186 command->set_ins(kInsU2fSign);
187 command->set_p1(kP1TupRequiredConsumed);
188 command->set_data(data);
189 return command;
190 }
191
122 } // namespace device 192 } // namespace device
OLDNEW
« no previous file with comments | « device/u2f/u2f_apdu_command.h ('k') | device/u2f/u2f_apdu_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698