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