1 /*
2 * Copyright (c) 2015-2018 Nitrokey UG
3 *
4 * This file is part of libnitrokey.
5 *
6 * libnitrokey is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * libnitrokey is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with libnitrokey. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * SPDX-License-Identifier: LGPL-3.0
20 */
21
22
23 static const char *const default_admin_pin = "12345678";
24 static const char *const default_user_pin = "123456";
25 const char * temporary_password = "123456789012345678901234";
26 const char * RFC_SECRET = "12345678901234567890";
27
28 #include "catch2/catch.hpp"
29
30 #include <iostream>
31 #include <string.h>
32 #include <NitrokeyManager.h>
33 #include "device_proto.h"
34 #include "log.h"
35 #include "stick10_commands_0.8.h"
36 //#include "stick20_commands.h"
37
38 using namespace std;
39 using namespace nitrokey::device;
40 using namespace nitrokey::proto;
41 using namespace nitrokey::proto::stick10_08;
42 using namespace nitrokey::log;
43 using namespace nitrokey::misc;
44
45 using Dev = Stick10;
execute_password_command(std::shared_ptr<Device> stick,const char * password,const char kind='P')46 using Dev10 = std::shared_ptr<Dev>;
47
48 void connect_and_setup(Dev10 stick) {
49 bool connected = stick->connect();
50 REQUIRE(connected == true);
51 Log::instance().set_loglevel(Loglevel::DEBUG);
52 }
53
54 void authorize(Dev10 stick) {
55 auto authreq = get_payload<FirstAuthenticate>();
56 strcpy((char *) (authreq.card_password), default_admin_pin);
57 strcpy((char *) (authreq.temporary_password), temporary_password);
58 FirstAuthenticate::CommandTransaction::run(stick, authreq);
59
60 auto user_auth = get_payload<UserAuthenticate>();
61 strcpyT(user_auth.temporary_password, temporary_password);
SKIP_TEST()62 strcpyT(user_auth.card_password, default_user_pin);
63 UserAuthenticate::CommandTransaction::run(stick, user_auth);
64 }
65
66 TEST_CASE("write slot", "[pronew]"){
67 auto stick = make_shared<Dev>();
68
69 connect_and_setup(stick);
70 authorize(stick);
71
72 auto p2 = get_payload<SendOTPData>();
73 strcpyT(p2.temporary_admin_password, temporary_password);
74 p2.setTypeName();
75 strcpyT(p2.data, "test name aaa");
76 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
77
78 p2 = get_payload<SendOTPData>();
79 strcpyT(p2.temporary_admin_password, temporary_password);
80 strcpyT(p2.data, RFC_SECRET);
81 p2.setTypeSecret();
82 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
83
84 auto p = get_payload<WriteToOTPSlot>();
85 strcpyT(p.temporary_admin_password, temporary_password);
86 p.use_8_digits = true;
87 p.slot_number = 0 + 0x10;
88 p.slot_counter_or_interval = 0;
89 stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p);
90
91 auto pc = get_payload<WriteGeneralConfig>();
92 pc.enable_user_password = 0;
93 strcpyT(pc.temporary_admin_password, temporary_password);
94 WriteGeneralConfig::CommandTransaction::run(stick, pc);
95
96 auto p3 = get_payload<GetHOTP>();
97 p3.slot_number = 0 + 0x10;
98 GetHOTP::CommandTransaction::run(stick, p3);
99
100 }
101
102
103 TEST_CASE("erase slot", "[pronew]"){
104 auto stick = make_shared<Dev>();
105 connect_and_setup(stick);
106 authorize(stick);
107
108 auto p = get_payload<WriteGeneralConfig>();
109 p.enable_user_password = 0;
110 strcpyT(p.temporary_admin_password, temporary_password);
111 WriteGeneralConfig::CommandTransaction::run(stick, p);
112
113 auto p3 = get_payload<GetHOTP>();
114 p3.slot_number = 0 + 0x10;
115 GetHOTP::CommandTransaction::run(stick, p3);
116
117 auto erase_payload = get_payload<EraseSlot>();
118 erase_payload.slot_number = 0 + 0x10;
119 strcpyT(erase_payload.temporary_admin_password, temporary_password);
120 EraseSlot::CommandTransaction::run(stick, erase_payload);
121
122 auto p4 = get_payload<GetHOTP>();
123 p4.slot_number = 0 + 0x10;
124 REQUIRE_THROWS(
125 GetHOTP::CommandTransaction::run(stick, p4)
126 );
127 }
128
129 TEST_CASE("write general config", "[pronew]") {
130 auto stick = make_shared<Dev>();
131 connect_and_setup(stick);
132 authorize(stick);
133
134 auto p = get_payload<WriteGeneralConfig>();
135 p.enable_user_password = 1;
136 REQUIRE_THROWS(
137 WriteGeneralConfig::CommandTransaction::run(stick, p)
138 );
139 strcpyT(p.temporary_admin_password, temporary_password);
140 WriteGeneralConfig::CommandTransaction::run(stick, p);
141 }
142
143 TEST_CASE("authorize user HOTP", "[pronew]") {
144 auto stick = make_shared<Dev>();
145 connect_and_setup(stick);
146 authorize(stick);
147
148 {
149 auto p = get_payload<WriteGeneralConfig>();
150 p.enable_user_password = 1;
151 strcpyT(p.temporary_admin_password, temporary_password);
152 WriteGeneralConfig::CommandTransaction::run(stick, p);
153 }
154
155 auto p2 = get_payload<SendOTPData>();
156 strcpyT(p2.temporary_admin_password, temporary_password);
157 p2.setTypeName();
158 strcpyT(p2.data, "test name aaa");
159 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
160
161 p2 = get_payload<SendOTPData>();
162 strcpyT(p2.temporary_admin_password, temporary_password);
163 strcpyT(p2.data, RFC_SECRET);
164 p2.setTypeSecret();
165 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
166
167 auto p = get_payload<WriteToOTPSlot>();
168 strcpyT(p.temporary_admin_password, temporary_password);
169 p.use_8_digits = true;
170 p.slot_number = 0 + 0x10;
171 p.slot_counter_or_interval = 0;
172 stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p);
173
174
175 auto p3 = get_payload<GetHOTP>();
176 p3.slot_number = 0 + 0x10;
177 REQUIRE_THROWS(
178 GetHOTP::CommandTransaction::run(stick, p3)
179 );
180 strcpyT(p3.temporary_user_password, temporary_password);
181 auto code_response = GetHOTP::CommandTransaction::run(stick, p3);
182 REQUIRE(code_response.data().code == 84755224);
183
184 }
185
186 TEST_CASE("check firmware version", "[pronew]") {
187 auto stick = make_shared<Dev>();
188 connect_and_setup(stick);
189
190 auto p = GetStatus::CommandTransaction::run(stick);
191 REQUIRE(p.data().firmware_version == 8);
192 }
193
194 TEST_CASE("authorize user TOTP", "[pronew]") {
195 auto stick = make_shared<Dev>();
196 connect_and_setup(stick);
197 authorize(stick);
198
199 {
200 auto p = get_payload<WriteGeneralConfig>();
201 p.enable_user_password = 1;
202 strcpyT(p.temporary_admin_password, temporary_password);
203 WriteGeneralConfig::CommandTransaction::run(stick, p);
204 }
205
206 auto p2 = get_payload<SendOTPData>();
207 strcpyT(p2.temporary_admin_password, temporary_password);
208 p2.setTypeName();
209 strcpyT(p2.data, "test name TOTP");
210 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
211
212 p2 = get_payload<SendOTPData>();
213 strcpyT(p2.temporary_admin_password, temporary_password);
214 strcpyT(p2.data, RFC_SECRET);
215 p2.setTypeSecret();
216 stick10_08::SendOTPData::CommandTransaction::run(stick, p2);
217
218 auto p = get_payload<WriteToOTPSlot>();
219 strcpyT(p.temporary_admin_password, temporary_password);
220 p.use_8_digits = true;
221 p.slot_number = 0 + 0x20;
222 p.slot_counter_or_interval = 30;
223 stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p);
224
225 auto p_get_totp = get_payload<GetTOTP>();
226 p_get_totp.slot_number = 0 + 0x20;
227
228 REQUIRE_THROWS(
229 GetTOTP::CommandTransaction::run(stick, p_get_totp)
230 );
231 strcpyT(p_get_totp.temporary_user_password, temporary_password);
232
233 auto p_set_time = get_payload<SetTime>();
234 p_set_time.reset = 1;
235 p_set_time.time = 59;
236 SetTime::CommandTransaction::run(stick, p_set_time);
237 auto code = GetTOTP::CommandTransaction::run(stick, p_get_totp);
238 REQUIRE(code.data().code == 94287082);
239
240 }
241