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 #include <cstring>
23 #include <iostream>
24 #include "libnitrokey/NitrokeyManager.h"
25 #include "libnitrokey/LibraryException.h"
26 #include <algorithm>
27 #include <unordered_map>
28 #include <stick20_commands.h>
29 #include "libnitrokey/misc.h"
30 #include <mutex>
31 #include "libnitrokey/cxx_semantics.h"
32 #include "libnitrokey/misc.h"
33 #include <functional>
34 #include <stick10_commands.h>
35
36 std::mutex nitrokey::proto::send_receive_mtx;
37
38 namespace nitrokey{
39
40 std::mutex mex_dev_com_manager;
41
42 #ifndef strndup
43 #ifdef _WIN32
44 #pragma message "Using own strndup"
strndup(const char * str,size_t maxlen)45 char * strndup(const char* str, size_t maxlen){
46 size_t len = strnlen(str, maxlen);
47 char* dup = (char *) malloc(len + 1);
48 memcpy(dup, str, len);
49 dup[len] = 0;
50 return dup;
51 }
52 #endif
53 #endif
54
55 using nitrokey::misc::strcpyT;
56
57 template <typename T>
get_payload()58 typename T::CommandPayload get_payload(){
59 //Create, initialize and return by value command payload
60 typename T::CommandPayload st;
61 bzero(&st, sizeof(st));
62 return st;
63 }
64
65
66 // package type to auth, auth type [Authorize,UserAuthorize]
67 template <typename S, typename A, typename T>
authorize_packet(T & package,const char * admin_temporary_password,shared_ptr<Device> device)68 void NitrokeyManager::authorize_packet(T &package, const char *admin_temporary_password, shared_ptr<Device> device){
69 if (!is_authorization_command_supported()){
70 LOG("Authorization command not supported, skipping", Loglevel::WARNING);
71 }
72 auto auth = get_payload<A>();
73 strcpyT(auth.temporary_password, admin_temporary_password);
74 auth.crc_to_authorize = S::CommandTransaction::getCRC(package);
75 A::CommandTransaction::run(device, auth);
76 }
77
78 shared_ptr <NitrokeyManager> NitrokeyManager::_instance = nullptr;
79
NitrokeyManager()80 NitrokeyManager::NitrokeyManager() : device(nullptr)
81 {
82 set_debug(false);
83 }
~NitrokeyManager()84 NitrokeyManager::~NitrokeyManager() {
85 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
86
87 for (auto d : connected_devices){
88 if (d.second == nullptr) continue;
89 d.second->disconnect();
90 connected_devices[d.first] = nullptr;
91 }
92 }
93
set_current_device_speed(int retry_delay,int send_receive_delay)94 bool NitrokeyManager::set_current_device_speed(int retry_delay, int send_receive_delay){
95 if (retry_delay < 20 || send_receive_delay < 20){
96 LOG("Delay set too low: " + to_string(retry_delay) +" "+ to_string(send_receive_delay), Loglevel::WARNING);
97 return false;
98 }
99
100 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
101 if(device == nullptr) {
102 return false;
103 }
104 device->set_receiving_delay(std::chrono::duration<int, std::milli>(send_receive_delay));
105 device->set_retry_delay(std::chrono::duration<int, std::milli>(retry_delay));
106 return true;
107 }
108
list_devices()109 std::vector<DeviceInfo> NitrokeyManager::list_devices(){
110 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
111
112 return Device::enumerate();
113 }
114
list_devices_by_cpuID()115 std::vector<std::string> NitrokeyManager::list_devices_by_cpuID(){
116 using misc::toHex;
117 //disconnect default device
118 disconnect();
119
120 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
121 LOGD1("Disconnecting registered devices");
122 for (auto & kv : connected_devices_byID){
123 if (kv.second != nullptr)
124 kv.second->disconnect();
125 }
126 connected_devices_byID.clear();
127
128 LOGD1("Enumerating devices");
129 std::vector<std::string> res;
130 const auto v = Device::enumerate();
131 LOGD1("Discovering IDs");
132 for (auto & i: v){
133 if (i.m_deviceModel != DeviceModel::STORAGE)
134 continue;
135 auto p = i.m_path;
136 auto d = make_shared<Stick20>();
137 LOGD1( std::string("Found: ") + p );
138 d->set_path(p);
139 try{
140 if (d->connect()){
141 device = d;
142 std::string id;
143 try {
144 const auto status = get_status_storage();
145 const auto sc_id = toHex(status.ActiveSmartCardID_u32);
146 const auto sd_id = toHex(status.ActiveSD_CardID_u32);
147 id += sc_id + ":" + sd_id;
148 id += "_p_" + p;
149 }
150 catch (const LongOperationInProgressException &e) {
151 LOGD1(std::string("Long operation in progress, setting ID to: ") + p);
152 id = p;
153 }
154
155 connected_devices_byID[id] = d;
156 res.push_back(id);
157 LOGD1( std::string("Found: ") + p + " => " + id);
158 } else{
159 LOGD1( std::string("Could not connect to: ") + p);
160 }
161 }
162 catch (const DeviceCommunicationException &e){
163 LOGD1( std::string("Exception encountered: ") + p);
164 }
165 }
166 return res;
167 }
168
connect_with_ID(const std::string id)169 bool NitrokeyManager::connect_with_ID(const std::string id) {
170 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
171
172 auto position = connected_devices_byID.find(id);
173 if (position == connected_devices_byID.end()) {
174 LOGD1(std::string("Could not find device ")+id + ". Refresh devices list with list_devices_by_cpuID().");
175 return false;
176 }
177
178 auto d = connected_devices_byID[id];
179 device = d;
180 current_device_id = id;
181
182 //validate connection
183 try{
184 get_status();
185 }
186 catch (const LongOperationInProgressException &){
187 //ignore
188 }
189 catch (const DeviceCommunicationException &){
190 d->disconnect();
191 current_device_id = "";
192 connected_devices_byID[id] = nullptr;
193 connected_devices_byID.erase(position);
194 return false;
195 }
196 nitrokey::log::Log::setPrefix(id);
197 LOGD1("Device successfully changed");
198 return true;
199 }
200
201 /**
202 * Connects device to path.
203 * Assumes devices are not being disconnected and caches connections (param cache_connections).
204 * @param path os-dependent device path
205 * @return false, when could not connect, true otherwise
206 */
connect_with_path(std::string path)207 bool NitrokeyManager::connect_with_path(std::string path) {
208 const bool cache_connections = false;
209
210 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
211
212 if (cache_connections){
213 if(connected_devices.find(path) != connected_devices.end()
214 && connected_devices[path] != nullptr) {
215 device = connected_devices[path];
216 return true;
217 }
218 }
219
220 auto vendor_id = NITROKEY_VID;
221 auto info_ptr = hid_enumerate(vendor_id, 0);
222 if (!info_ptr) {
223 vendor_id = PURISM_VID;
224 info_ptr = hid_enumerate(vendor_id, 0);
225 }
226 auto first_info_ptr = info_ptr;
227 if (!info_ptr)
228 return false;
229
230 misc::Option<DeviceModel> model;
231 while (info_ptr && !model.has_value()) {
232 if (path == std::string(info_ptr->path)) {
233 model = product_id_to_model(info_ptr->vendor_id, info_ptr->product_id);
234 }
235 info_ptr = info_ptr->next;
236 }
237 hid_free_enumeration(first_info_ptr);
238
239 if (!model.has_value())
240 return false;
241
242 auto p = Device::create(model.value());
243 if (!p)
244 return false;
245 p->set_path(path);
246
247 if(!p->connect()) return false;
248
249 if(cache_connections){
250 connected_devices [path] = p;
251 }
252
253 device = p; //previous device will be disconnected automatically
254 current_device_id = path;
255 nitrokey::log::Log::setPrefix(path);
256 LOGD1("Device successfully changed");
257 return true;
258 }
259
connect()260 bool NitrokeyManager::connect() {
261 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
262 vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>(),
263 make_shared<LibremKey>() };
264 bool connected = false;
265 for( auto & d : devices ){
266 if (d->connect()){
267 device = std::shared_ptr<Device>(d);
268 connected = true;
269 }
270 }
271 return connected;
272 }
273
274
set_log_function(std::function<void (std::string)> log_function)275 void NitrokeyManager::set_log_function(std::function<void(std::string)> log_function){
276 static nitrokey::log::FunctionalLogHandler handler(log_function);
277 nitrokey::log::Log::instance().set_handler(&handler);
278 }
279
set_default_commands_delay(int delay)280 bool NitrokeyManager::set_default_commands_delay(int delay){
281 if (delay < 20){
282 LOG("Delay set too low: " + to_string(delay), Loglevel::WARNING);
283 return false;
284 }
285 Device::set_default_device_speed(delay);
286 return true;
287 }
288
connect(const char * device_model)289 bool NitrokeyManager::connect(const char *device_model) {
290 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
291 LOG(__FUNCTION__, nitrokey::log::Loglevel::DEBUG_L2);
292 switch (device_model[0]){
293 case 'P':
294 device = make_shared<Stick10>();
295 break;
296 case 'S':
297 device = make_shared<Stick20>();
298 break;
299 case 'L':
300 device = make_shared<LibremKey>();
301 break;
302 default:
303 throw std::runtime_error("Unknown model");
304 }
305 return device->connect();
306 }
307
connect(device::DeviceModel device_model)308 bool NitrokeyManager::connect(device::DeviceModel device_model) {
309 const char *model_string;
310 switch (device_model) {
311 case device::DeviceModel::PRO:
312 model_string = "P";
313 break;
314 case device::DeviceModel::STORAGE:
315 model_string = "S";
316 break;
317 case device::DeviceModel::LIBREM:
318 model_string = "L";
319 break;
320 default:
321 throw std::runtime_error("Unknown model");
322 }
323 return connect(model_string);
324 }
325
instance()326 shared_ptr<NitrokeyManager> NitrokeyManager::instance() {
327 static std::mutex mutex;
328 std::lock_guard<std::mutex> lock(mutex);
329 if (_instance == nullptr){
330 _instance = make_shared<NitrokeyManager>();
331 }
332 return _instance;
333 }
334
335
336
disconnect()337 bool NitrokeyManager::disconnect() {
338 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
339 return _disconnect_no_lock();
340 }
341
_disconnect_no_lock()342 bool NitrokeyManager::_disconnect_no_lock() {
343 //do not use directly without locked mutex,
344 //used by could_be_enumerated, disconnect
345 if (device == nullptr){
346 return false;
347 }
348 const auto res = device->disconnect();
349 device = nullptr;
350 return res;
351 }
352
is_connected()353 bool NitrokeyManager::is_connected() throw(){
354 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
355 if(device != nullptr){
356 auto connected = device->could_be_enumerated();
357 if(connected){
358 return true;
359 } else {
360 _disconnect_no_lock();
361 return false;
362 }
363 }
364 return false;
365 }
366
could_current_device_be_enumerated()367 bool NitrokeyManager::could_current_device_be_enumerated() {
368 std::lock_guard<std::mutex> lock(mex_dev_com_manager);
369 if (device != nullptr) {
370 return device->could_be_enumerated();
371 }
372 return false;
373 }
374
set_loglevel(int loglevel)375 void NitrokeyManager::set_loglevel(int loglevel) {
376 loglevel = max(loglevel, static_cast<int>(Loglevel::ERROR));
377 loglevel = min(loglevel, static_cast<int>(Loglevel::DEBUG_L2));
378 Log::instance().set_loglevel(static_cast<Loglevel>(loglevel));
379 }
380
set_loglevel(Loglevel loglevel)381 void NitrokeyManager::set_loglevel(Loglevel loglevel) {
382 Log::instance().set_loglevel(loglevel);
383 }
384
set_debug(bool state)385 void NitrokeyManager::set_debug(bool state) {
386 if (state){
387 Log::instance().set_loglevel(Loglevel::DEBUG);
388 } else {
389 Log::instance().set_loglevel(Loglevel::ERROR);
390 }
391 }
392
393
get_serial_number()394 string NitrokeyManager::get_serial_number() {
395 try {
396 auto serial_number = this->get_serial_number_as_u32();
397 if (serial_number == 0) {
398 return "NA";
399 } else {
400 return nitrokey::misc::toHex(serial_number);
401 }
402 } catch (DeviceNotConnected& e) {
403 return "";
404 }
405 }
406
get_serial_number_as_u32()407 uint32_t NitrokeyManager::get_serial_number_as_u32() {
408 if (device == nullptr) { throw DeviceNotConnected("device not connected"); }
409 switch (device->get_device_model()) {
410 case DeviceModel::LIBREM:
411 case DeviceModel::PRO: {
412 auto response = GetStatus::CommandTransaction::run(device);
413 return response.data().card_serial_u32;
414 }
415 break;
416
417 case DeviceModel::STORAGE:
418 {
419 auto response = stick20::GetDeviceStatus::CommandTransaction::run(device);
420 return response.data().ActiveSmartCardID_u32;
421 }
422 break;
423 }
424 return 0;
425 }
426
get_status()427 stick10::GetStatus::ResponsePayload NitrokeyManager::get_status(){
428 try{
429 auto response = GetStatus::CommandTransaction::run(device);
430 return response.data();
431 }
432 catch (DeviceSendingFailure &e){
433 // disconnect();
434 throw;
435 }
436 }
437
get_status_as_string()438 string NitrokeyManager::get_status_as_string() {
439 auto response = GetStatus::CommandTransaction::run(device);
440 return response.data().dissect();
441 }
442
getFilledOTPCode(uint32_t code,bool use_8_digits)443 string getFilledOTPCode(uint32_t code, bool use_8_digits){
444 stringstream s;
445 s << std::right << std::setw(use_8_digits ? 8 : 6) << std::setfill('0') << code;
446 return s.str();
447 }
448
get_HOTP_code(uint8_t slot_number,const char * user_temporary_password)449 string NitrokeyManager::get_HOTP_code(uint8_t slot_number, const char *user_temporary_password) {
450 if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
451
452 if (is_authorization_command_supported()){
453 auto gh = get_payload<GetHOTP>();
454 gh.slot_number = get_internal_slot_number_for_hotp(slot_number);
455 if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0){ //FIXME use string instead of strlen
456 authorize_packet<GetHOTP, UserAuthorize>(gh, user_temporary_password, device);
457 }
458 auto resp = GetHOTP::CommandTransaction::run(device, gh);
459 return getFilledOTPCode(resp.data().code, resp.data().use_8_digits);
460 } else {
461 auto gh = get_payload<stick10_08::GetHOTP>();
462 gh.slot_number = get_internal_slot_number_for_hotp(slot_number);
463 if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0) {
464 strcpyT(gh.temporary_user_password, user_temporary_password);
465 }
466 auto resp = stick10_08::GetHOTP::CommandTransaction::run(device, gh);
467 return getFilledOTPCode(resp.data().code, resp.data().use_8_digits);
468 }
469 return "";
470 }
471
is_internal_hotp_slot_number(uint8_t slot_number) const472 bool NitrokeyManager::is_internal_hotp_slot_number(uint8_t slot_number) const { return slot_number < 0x20; }
is_valid_hotp_slot_number(uint8_t slot_number) const473 bool NitrokeyManager::is_valid_hotp_slot_number(uint8_t slot_number) const { return slot_number < 3; }
is_valid_totp_slot_number(uint8_t slot_number) const474 bool NitrokeyManager::is_valid_totp_slot_number(uint8_t slot_number) const { return slot_number < 0x10-1; } //15
get_internal_slot_number_for_totp(uint8_t slot_number) const475 uint8_t NitrokeyManager::get_internal_slot_number_for_totp(uint8_t slot_number) const { return (uint8_t) (0x20 + slot_number); }
get_internal_slot_number_for_hotp(uint8_t slot_number) const476 uint8_t NitrokeyManager::get_internal_slot_number_for_hotp(uint8_t slot_number) const { return (uint8_t) (0x10 + slot_number); }
477
478
479
get_TOTP_code(uint8_t slot_number,uint64_t challenge,uint64_t last_totp_time,uint8_t last_interval,const char * user_temporary_password)480 string NitrokeyManager::get_TOTP_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time,
481 uint8_t last_interval,
482 const char *user_temporary_password) {
483 if(!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
484 slot_number = get_internal_slot_number_for_totp(slot_number);
485
486 if (is_authorization_command_supported()){
487 auto gt = get_payload<GetTOTP>();
488 gt.slot_number = slot_number;
489 gt.challenge = challenge;
490 gt.last_interval = last_interval;
491 gt.last_totp_time = last_totp_time;
492
493 if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0){ //FIXME use string instead of strlen
494 authorize_packet<GetTOTP, UserAuthorize>(gt, user_temporary_password, device);
495 }
496 auto resp = GetTOTP::CommandTransaction::run(device, gt);
497 return getFilledOTPCode(resp.data().code, resp.data().use_8_digits);
498 } else {
499 auto gt = get_payload<stick10_08::GetTOTP>();
500 strcpyT(gt.temporary_user_password, user_temporary_password);
501 gt.slot_number = slot_number;
502 auto resp = stick10_08::GetTOTP::CommandTransaction::run(device, gt);
503 return getFilledOTPCode(resp.data().code, resp.data().use_8_digits);
504 }
505 return "";
506 }
507
erase_slot(uint8_t slot_number,const char * temporary_password)508 bool NitrokeyManager::erase_slot(uint8_t slot_number, const char *temporary_password) {
509 if (is_authorization_command_supported()){
510 auto p = get_payload<EraseSlot>();
511 p.slot_number = slot_number;
512 authorize_packet<EraseSlot, Authorize>(p, temporary_password, device);
513 auto resp = EraseSlot::CommandTransaction::run(device,p);
514 } else {
515 auto p = get_payload<stick10_08::EraseSlot>();
516 p.slot_number = slot_number;
517 strcpyT(p.temporary_admin_password, temporary_password);
518 auto resp = stick10_08::EraseSlot::CommandTransaction::run(device,p);
519 }
520 return true;
521 }
522
erase_hotp_slot(uint8_t slot_number,const char * temporary_password)523 bool NitrokeyManager::erase_hotp_slot(uint8_t slot_number, const char *temporary_password) {
524 if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
525 slot_number = get_internal_slot_number_for_hotp(slot_number);
526 return erase_slot(slot_number, temporary_password);
527 }
528
erase_totp_slot(uint8_t slot_number,const char * temporary_password)529 bool NitrokeyManager::erase_totp_slot(uint8_t slot_number, const char *temporary_password) {
530 if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
531 slot_number = get_internal_slot_number_for_totp(slot_number);
532 return erase_slot(slot_number, temporary_password);
533 }
534
535 template <typename T, typename U>
vector_copy_ranged(T & dest,std::vector<U> & vec,size_t begin,size_t elements_to_copy)536 void vector_copy_ranged(T& dest, std::vector<U> &vec, size_t begin, size_t elements_to_copy){
537 const size_t d_size = sizeof(dest);
538 if(d_size < elements_to_copy){
539 throw TargetBufferSmallerThanSource(elements_to_copy, d_size);
540 }
541 std::fill(dest, dest+d_size, 0);
542 std::copy(vec.begin() + begin, vec.begin() +begin + elements_to_copy, dest);
543 }
544
545 template <typename T, typename U>
vector_copy(T & dest,std::vector<U> & vec)546 void vector_copy(T& dest, std::vector<U> &vec){
547 const size_t d_size = sizeof(dest);
548 if(d_size < vec.size()){
549 throw TargetBufferSmallerThanSource(vec.size(), d_size);
550 }
551 std::fill(dest, dest+d_size, 0);
552 std::copy(vec.begin(), vec.end(), dest);
553 }
554
write_HOTP_slot(uint8_t slot_number,const char * slot_name,const char * secret,uint64_t hotp_counter,bool use_8_digits,bool use_enter,bool use_tokenID,const char * token_ID,const char * temporary_password)555 bool NitrokeyManager::write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter,
556 bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID,
557 const char *temporary_password) {
558 if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
559
560 int internal_slot_number = get_internal_slot_number_for_hotp(slot_number);
561 if (is_authorization_command_supported()){
562 write_HOTP_slot_authorize(internal_slot_number, slot_name, secret, hotp_counter, use_8_digits, use_enter, use_tokenID,
563 token_ID, temporary_password);
564 } else {
565 write_OTP_slot_no_authorize(internal_slot_number, slot_name, secret, hotp_counter, use_8_digits, use_enter, use_tokenID,
566 token_ID, temporary_password);
567 }
568 return true;
569 }
570
write_HOTP_slot_authorize(uint8_t slot_number,const char * slot_name,const char * secret,uint64_t hotp_counter,bool use_8_digits,bool use_enter,bool use_tokenID,const char * token_ID,const char * temporary_password)571 void NitrokeyManager::write_HOTP_slot_authorize(uint8_t slot_number, const char *slot_name, const char *secret,
572 uint64_t hotp_counter, bool use_8_digits, bool use_enter,
573 bool use_tokenID, const char *token_ID, const char *temporary_password) {
574 auto payload = get_payload<WriteToHOTPSlot>();
575 payload.slot_number = slot_number;
576 auto secret_bin = misc::hex_string_to_byte(secret);
577 vector_copy(payload.slot_secret, secret_bin);
578 strcpyT(payload.slot_name, slot_name);
579 strcpyT(payload.slot_token_id, token_ID);
580 switch (device->get_device_model() ){
581 case DeviceModel::LIBREM:
582 case DeviceModel::PRO: {
583 payload.slot_counter = hotp_counter;
584 break;
585 }
586 case DeviceModel::STORAGE: {
587 string counter = to_string(hotp_counter);
588 strcpyT(payload.slot_counter_s, counter.c_str());
589 break;
590 }
591 default:
592 LOG(string(__FILE__) + to_string(__LINE__) +
593 string(__FUNCTION__) + string(" Unhandled device model for HOTP")
594 , Loglevel::DEBUG);
595 break;
596 }
597 payload.use_8_digits = use_8_digits;
598 payload.use_enter = use_enter;
599 payload.use_tokenID = use_tokenID;
600
601 authorize_packet<WriteToHOTPSlot, Authorize>(payload, temporary_password, device);
602
603 auto resp = WriteToHOTPSlot::CommandTransaction::run(device, payload);
604 }
605
write_TOTP_slot(uint8_t slot_number,const char * slot_name,const char * secret,uint16_t time_window,bool use_8_digits,bool use_enter,bool use_tokenID,const char * token_ID,const char * temporary_password)606 bool NitrokeyManager::write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window,
607 bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID,
608 const char *temporary_password) {
609 if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
610 int internal_slot_number = get_internal_slot_number_for_totp(slot_number);
611
612 if (is_authorization_command_supported()){
613 write_TOTP_slot_authorize(internal_slot_number, slot_name, secret, time_window, use_8_digits, use_enter, use_tokenID,
614 token_ID, temporary_password);
615 } else {
616 write_OTP_slot_no_authorize(internal_slot_number, slot_name, secret, time_window, use_8_digits, use_enter, use_tokenID,
617 token_ID, temporary_password);
618 }
619
620 return true;
621 }
622
write_OTP_slot_no_authorize(uint8_t internal_slot_number,const char * slot_name,const char * secret,uint64_t counter_or_interval,bool use_8_digits,bool use_enter,bool use_tokenID,const char * token_ID,const char * temporary_password) const623 void NitrokeyManager::write_OTP_slot_no_authorize(uint8_t internal_slot_number, const char *slot_name,
624 const char *secret,
625 uint64_t counter_or_interval, bool use_8_digits, bool use_enter,
626 bool use_tokenID, const char *token_ID,
627 const char *temporary_password) const {
628
629 auto payload2 = get_payload<stick10_08::SendOTPData>();
630 strcpyT(payload2.temporary_admin_password, temporary_password);
631 strcpyT(payload2.data, slot_name);
632 payload2.setTypeName();
633 stick10_08::SendOTPData::CommandTransaction::run(device, payload2);
634
635 payload2.setTypeSecret();
636 payload2.id = 0;
637 auto secret_bin = misc::hex_string_to_byte(secret);
638 auto remaining_secret_length = secret_bin.size();
639 const auto maximum_OTP_secret_size = 40;
640 if(remaining_secret_length > maximum_OTP_secret_size){
641 throw TargetBufferSmallerThanSource(remaining_secret_length, maximum_OTP_secret_size);
642 }
643
644 while (remaining_secret_length>0){
645 const auto bytesToCopy = std::min(sizeof(payload2.data), remaining_secret_length);
646 const auto start = secret_bin.size() - remaining_secret_length;
647 memset(payload2.data, 0, sizeof(payload2.data));
648 vector_copy_ranged(payload2.data, secret_bin, start, bytesToCopy);
649 stick10_08::SendOTPData::CommandTransaction::run(device, payload2);
650 remaining_secret_length -= bytesToCopy;
651 payload2.id++;
652 }
653
654 auto payload = get_payload<stick10_08::WriteToOTPSlot>();
655 strcpyT(payload.temporary_admin_password, temporary_password);
656 strcpyT(payload.slot_token_id, token_ID);
657 payload.use_8_digits = use_8_digits;
658 payload.use_enter = use_enter;
659 payload.use_tokenID = use_tokenID;
660 payload.slot_counter_or_interval = counter_or_interval;
661 payload.slot_number = internal_slot_number;
662 stick10_08::WriteToOTPSlot::CommandTransaction::run(device, payload);
663 }
664
write_TOTP_slot_authorize(uint8_t slot_number,const char * slot_name,const char * secret,uint16_t time_window,bool use_8_digits,bool use_enter,bool use_tokenID,const char * token_ID,const char * temporary_password)665 void NitrokeyManager::write_TOTP_slot_authorize(uint8_t slot_number, const char *slot_name, const char *secret,
666 uint16_t time_window, bool use_8_digits, bool use_enter,
667 bool use_tokenID, const char *token_ID, const char *temporary_password) {
668 auto payload = get_payload<WriteToTOTPSlot>();
669 payload.slot_number = slot_number;
670 auto secret_bin = misc::hex_string_to_byte(secret);
671 vector_copy(payload.slot_secret, secret_bin);
672 strcpyT(payload.slot_name, slot_name);
673 strcpyT(payload.slot_token_id, token_ID);
674 payload.slot_interval = time_window; //FIXME naming
675 payload.use_8_digits = use_8_digits;
676 payload.use_enter = use_enter;
677 payload.use_tokenID = use_tokenID;
678
679 authorize_packet<WriteToTOTPSlot, Authorize>(payload, temporary_password, device);
680
681 auto resp = WriteToTOTPSlot::CommandTransaction::run(device, payload);
682 }
683
get_totp_slot_name(uint8_t slot_number)684 char * NitrokeyManager::get_totp_slot_name(uint8_t slot_number) {
685 if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
686 slot_number = get_internal_slot_number_for_totp(slot_number);
687 return get_slot_name(slot_number);
688 }
get_hotp_slot_name(uint8_t slot_number)689 char * NitrokeyManager::get_hotp_slot_name(uint8_t slot_number) {
690 if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number);
691 slot_number = get_internal_slot_number_for_hotp(slot_number);
692 return get_slot_name(slot_number);
693 }
694
695 static const int max_string_field_length = 2*1024; //storage's status string is ~1k
696
get_slot_name(uint8_t slot_number)697 char * NitrokeyManager::get_slot_name(uint8_t slot_number) {
698 auto payload = get_payload<GetSlotName>();
699 payload.slot_number = slot_number;
700 auto resp = GetSlotName::CommandTransaction::run(device, payload);
701 return strndup((const char *) resp.data().slot_name, max_string_field_length);
702 }
703
first_authenticate(const char * pin,const char * temporary_password)704 bool NitrokeyManager::first_authenticate(const char *pin, const char *temporary_password) {
705 auto authreq = get_payload<FirstAuthenticate>();
706 strcpyT(authreq.card_password, pin);
707 strcpyT(authreq.temporary_password, temporary_password);
708 FirstAuthenticate::CommandTransaction::run(device, authreq);
709 return true;
710 }
711
set_time(uint64_t time)712 bool NitrokeyManager::set_time(uint64_t time) {
713 auto p = get_payload<SetTime>();
714 p.reset = 1;
715 p.time = time;
716 SetTime::CommandTransaction::run(device, p);
717 return false;
718 }
719
set_time_soft(uint64_t time)720 void NitrokeyManager::set_time_soft(uint64_t time) {
721 auto p = get_payload<SetTime>();
722 p.reset = 0;
723 p.time = time;
724 SetTime::CommandTransaction::run(device, p);
725 }
726
get_time(uint64_t time)727 bool NitrokeyManager::get_time(uint64_t time) {
728 set_time_soft(time);
729 return true;
730 }
731
change_user_PIN(const char * current_PIN,const char * new_PIN)732 void NitrokeyManager::change_user_PIN(const char *current_PIN, const char *new_PIN) {
733 change_PIN_general<ChangeUserPin, PasswordKind::User>(current_PIN, new_PIN);
734 }
735
change_admin_PIN(const char * current_PIN,const char * new_PIN)736 void NitrokeyManager::change_admin_PIN(const char *current_PIN, const char *new_PIN) {
737 change_PIN_general<ChangeAdminPin, PasswordKind::Admin>(current_PIN, new_PIN);
738 }
739
740 template <typename ProCommand, PasswordKind StoKind>
change_PIN_general(const char * current_PIN,const char * new_PIN)741 void NitrokeyManager::change_PIN_general(const char *current_PIN, const char *new_PIN) {
742 switch (device->get_device_model()){
743 case DeviceModel::LIBREM:
744 case DeviceModel::PRO:
745 {
746 auto p = get_payload<ProCommand>();
747 strcpyT(p.old_pin, current_PIN);
748 strcpyT(p.new_pin, new_PIN);
749 ProCommand::CommandTransaction::run(device, p);
750 }
751 break;
752 //in Storage change admin/user pin is divided to two commands with 20 chars field len
753 case DeviceModel::STORAGE:
754 {
755 auto p = get_payload<ChangeAdminUserPin20Current>();
756 strcpyT(p.password, current_PIN);
757 p.set_kind(StoKind);
758 auto p2 = get_payload<ChangeAdminUserPin20New>();
759 strcpyT(p2.password, new_PIN);
760 p2.set_kind(StoKind);
761 ChangeAdminUserPin20Current::CommandTransaction::run(device, p);
762 ChangeAdminUserPin20New::CommandTransaction::run(device, p2);
763 }
764 break;
765 }
766
767 }
768
enable_password_safe(const char * user_pin)769 void NitrokeyManager::enable_password_safe(const char *user_pin) {
770 //The following command will cancel enabling PWS if it is not supported
771 auto a = get_payload<IsAESSupported>();
772 strcpyT(a.user_password, user_pin);
773 IsAESSupported::CommandTransaction::run(device, a);
774
775 auto p = get_payload<EnablePasswordSafe>();
776 strcpyT(p.user_password, user_pin);
777 EnablePasswordSafe::CommandTransaction::run(device, p);
778 }
779
get_password_safe_slot_status()780 vector <uint8_t> NitrokeyManager::get_password_safe_slot_status() {
781 auto responsePayload = GetPasswordSafeSlotStatus::CommandTransaction::run(device);
782 vector<uint8_t> v = vector<uint8_t>(responsePayload.data().password_safe_status,
783 responsePayload.data().password_safe_status
784 + sizeof(responsePayload.data().password_safe_status));
785 return v;
786 }
787
get_user_retry_count()788 uint8_t NitrokeyManager::get_user_retry_count() {
789 if(device->get_device_model() == DeviceModel::STORAGE){
790 stick20::GetDeviceStatus::CommandTransaction::run(device);
791 }
792 auto response = GetUserPasswordRetryCount::CommandTransaction::run(device);
793 return response.data().password_retry_count;
794 }
795
get_admin_retry_count()796 uint8_t NitrokeyManager::get_admin_retry_count() {
797 if(device->get_device_model() == DeviceModel::STORAGE){
798 stick20::GetDeviceStatus::CommandTransaction::run(device);
799 }
800 auto response = GetPasswordRetryCount::CommandTransaction::run(device);
801 return response.data().password_retry_count;
802 }
803
lock_device()804 void NitrokeyManager::lock_device() {
805 LockDevice::CommandTransaction::run(device);
806 }
807
get_password_safe_slot_name(uint8_t slot_number)808 char * NitrokeyManager::get_password_safe_slot_name(uint8_t slot_number) {
809 if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);
810 auto p = get_payload<GetPasswordSafeSlotName>();
811 p.slot_number = slot_number;
812 auto response = GetPasswordSafeSlotName::CommandTransaction::run(device, p);
813 return strndup((const char *) response.data().slot_name, max_string_field_length);
814 }
815
is_valid_password_safe_slot_number(uint8_t slot_number) const816 bool NitrokeyManager::is_valid_password_safe_slot_number(uint8_t slot_number) const { return slot_number < 16; }
817
get_password_safe_slot_login(uint8_t slot_number)818 char * NitrokeyManager::get_password_safe_slot_login(uint8_t slot_number) {
819 if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);
820 auto p = get_payload<GetPasswordSafeSlotLogin>();
821 p.slot_number = slot_number;
822 auto response = GetPasswordSafeSlotLogin::CommandTransaction::run(device, p);
823 return strndup((const char *) response.data().slot_login, max_string_field_length);
824 }
825
get_password_safe_slot_password(uint8_t slot_number)826 char * NitrokeyManager::get_password_safe_slot_password(uint8_t slot_number) {
827 if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);
828 auto p = get_payload<GetPasswordSafeSlotPassword>();
829 p.slot_number = slot_number;
830 auto response = GetPasswordSafeSlotPassword::CommandTransaction::run(device, p);
831 return strndup((const char *) response.data().slot_password, max_string_field_length); //FIXME use secure way
832 }
833
write_password_safe_slot(uint8_t slot_number,const char * slot_name,const char * slot_login,const char * slot_password)834 void NitrokeyManager::write_password_safe_slot(uint8_t slot_number, const char *slot_name, const char *slot_login,
835 const char *slot_password) {
836 if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);
837 auto p = get_payload<SetPasswordSafeSlotData>();
838 p.slot_number = slot_number;
839 strcpyT(p.slot_name, slot_name);
840 strcpyT(p.slot_password, slot_password);
841 SetPasswordSafeSlotData::CommandTransaction::run(device, p);
842
843 auto p2 = get_payload<SetPasswordSafeSlotData2>();
844 p2.slot_number = slot_number;
845 strcpyT(p2.slot_login_name, slot_login);
846 SetPasswordSafeSlotData2::CommandTransaction::run(device, p2);
847 }
848
erase_password_safe_slot(uint8_t slot_number)849 void NitrokeyManager::erase_password_safe_slot(uint8_t slot_number) {
850 if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);
851 auto p = get_payload<ErasePasswordSafeSlot>();
852 p.slot_number = slot_number;
853 ErasePasswordSafeSlot::CommandTransaction::run(device, p);
854 }
855
user_authenticate(const char * user_password,const char * temporary_password)856 void NitrokeyManager::user_authenticate(const char *user_password, const char *temporary_password) {
857 auto p = get_payload<UserAuthenticate>();
858 strcpyT(p.card_password, user_password);
859 strcpyT(p.temporary_password, temporary_password);
860 UserAuthenticate::CommandTransaction::run(device, p);
861 }
862
build_aes_key(const char * admin_password)863 void NitrokeyManager::build_aes_key(const char *admin_password) {
864 switch (device->get_device_model()) {
865 case DeviceModel::LIBREM:
866 case DeviceModel::PRO: {
867 auto p = get_payload<BuildAESKey>();
868 strcpyT(p.admin_password, admin_password);
869 BuildAESKey::CommandTransaction::run(device, p);
870 break;
871 }
872 case DeviceModel::STORAGE : {
873 auto p = get_payload<stick20::CreateNewKeys>();
874 strcpyT(p.password, admin_password);
875 p.set_defaults();
876 stick20::CreateNewKeys::CommandTransaction::run(device, p);
877 break;
878 }
879 }
880 }
881
factory_reset(const char * admin_password)882 void NitrokeyManager::factory_reset(const char *admin_password) {
883 auto p = get_payload<FactoryReset>();
884 strcpyT(p.admin_password, admin_password);
885 FactoryReset::CommandTransaction::run(device, p);
886 }
887
unlock_user_password(const char * admin_password,const char * new_user_password)888 void NitrokeyManager::unlock_user_password(const char *admin_password, const char *new_user_password) {
889 switch (device->get_device_model()){
890 case DeviceModel::LIBREM:
891 case DeviceModel::PRO: {
892 auto p = get_payload<stick10::UnlockUserPassword>();
893 strcpyT(p.admin_password, admin_password);
894 strcpyT(p.user_new_password, new_user_password);
895 stick10::UnlockUserPassword::CommandTransaction::run(device, p);
896 break;
897 }
898 case DeviceModel::STORAGE : {
899 auto p2 = get_payload<ChangeAdminUserPin20Current>();
900 p2.set_defaults();
901 strcpyT(p2.password, admin_password);
902 ChangeAdminUserPin20Current::CommandTransaction::run(device, p2);
903 auto p3 = get_payload<stick20::UnlockUserPin>();
904 p3.set_defaults();
905 strcpyT(p3.password, new_user_password);
906 stick20::UnlockUserPin::CommandTransaction::run(device, p3);
907 break;
908 }
909 }
910 }
911
912
write_config(uint8_t numlock,uint8_t capslock,uint8_t scrolllock,bool enable_user_password,bool delete_user_password,const char * admin_temporary_password)913 void NitrokeyManager::write_config(uint8_t numlock, uint8_t capslock, uint8_t scrolllock, bool enable_user_password,
914 bool delete_user_password, const char *admin_temporary_password) {
915 auto p = get_payload<stick10_08::WriteGeneralConfig>();
916 p.numlock = numlock;
917 p.capslock = capslock;
918 p.scrolllock = scrolllock;
919 p.enable_user_password = static_cast<uint8_t>(enable_user_password ? 1 : 0);
920 p.delete_user_password = static_cast<uint8_t>(delete_user_password ? 1 : 0);
921 if (is_authorization_command_supported()){
922 authorize_packet<stick10_08::WriteGeneralConfig, Authorize>(p, admin_temporary_password, device);
923 } else {
924 strcpyT(p.temporary_admin_password, admin_temporary_password);
925 }
926 stick10_08::WriteGeneralConfig::CommandTransaction::run(device, p);
927 }
928
read_config()929 vector<uint8_t> NitrokeyManager::read_config() {
930 auto responsePayload = GetStatus::CommandTransaction::run(device);
931 vector<uint8_t> v = vector<uint8_t>(responsePayload.data().general_config,
932 responsePayload.data().general_config+sizeof(responsePayload.data().general_config));
933 return v;
934 }
935
is_authorization_command_supported()936 bool NitrokeyManager::is_authorization_command_supported(){
937 //authorization command is supported for versions equal or below:
938 auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({
939 {DeviceModel::PRO, 7},
940 {DeviceModel::LIBREM, 7},
941 {DeviceModel::STORAGE, 53},
942 });
943 return get_minor_firmware_version() <= m[device->get_device_model()];
944 }
945
is_320_OTP_secret_supported()946 bool NitrokeyManager::is_320_OTP_secret_supported(){
947 // 320 bit OTP secret is supported by version bigger or equal to:
948 auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({
949 {DeviceModel::PRO, 8},
950 {DeviceModel::LIBREM, 8},
951 {DeviceModel::STORAGE, 54},
952 });
953 return get_minor_firmware_version() >= m[device->get_device_model()];
954 }
955
get_connected_device_model() const956 DeviceModel NitrokeyManager::get_connected_device_model() const{
957 if (device == nullptr){
958 throw DeviceNotConnected("device not connected");
959 }
960 return device->get_device_model();
961 }
962
is_smartcard_in_use()963 bool NitrokeyManager::is_smartcard_in_use(){
964 try{
965 stick20::CheckSmartcardUsage::CommandTransaction::run(device);
966 }
967 catch(const CommandFailedException & e){
968 return e.reason_smartcard_busy();
969 }
970 return false;
971 }
972
get_minor_firmware_version()973 uint8_t NitrokeyManager::get_minor_firmware_version(){
974 switch(device->get_device_model()){
975 case DeviceModel::LIBREM:
976 case DeviceModel::PRO:{
977 auto status_p = GetStatus::CommandTransaction::run(device);
978 return status_p.data().firmware_version_st.minor; //7 or 8
979 }
980 case DeviceModel::STORAGE:{
981 auto status = stick20::GetDeviceStatus::CommandTransaction::run(device);
982 auto test_firmware = status.data().versionInfo.build_iteration != 0;
983 if (test_firmware)
984 LOG("Development firmware detected. Increasing minor version number.", nitrokey::log::Loglevel::WARNING);
985 return status.data().versionInfo.minor + (test_firmware? 1 : 0);
986 }
987 }
988 return 0;
989 }
get_major_firmware_version()990 uint8_t NitrokeyManager::get_major_firmware_version(){
991 switch(device->get_device_model()){
992 case DeviceModel::LIBREM:
993 case DeviceModel::PRO:{
994 auto status_p = GetStatus::CommandTransaction::run(device);
995 return status_p.data().firmware_version_st.major; //0
996 }
997 case DeviceModel::STORAGE:{
998 auto status = stick20::GetDeviceStatus::CommandTransaction::run(device);
999 return status.data().versionInfo.major;
1000 }
1001 }
1002 return 0;
1003 }
1004
is_AES_supported(const char * user_password)1005 bool NitrokeyManager::is_AES_supported(const char *user_password) {
1006 auto a = get_payload<IsAESSupported>();
1007 strcpyT(a.user_password, user_password);
1008 IsAESSupported::CommandTransaction::run(device, a);
1009 return true;
1010 }
1011
1012 //storage commands
1013
send_startup(uint64_t seconds_from_epoch)1014 void NitrokeyManager::send_startup(uint64_t seconds_from_epoch){
1015 auto p = get_payload<stick20::SendStartup>();
1016 // p.set_defaults(); //set current time
1017 p.localtime = seconds_from_epoch;
1018 stick20::SendStartup::CommandTransaction::run(device, p);
1019 }
1020
unlock_encrypted_volume(const char * user_pin)1021 void NitrokeyManager::unlock_encrypted_volume(const char* user_pin){
1022 misc::execute_password_command<stick20::EnableEncryptedPartition>(device, user_pin);
1023 }
1024
unlock_hidden_volume(const char * hidden_volume_password)1025 void NitrokeyManager::unlock_hidden_volume(const char* hidden_volume_password) {
1026 misc::execute_password_command<stick20::EnableHiddenEncryptedPartition>(device, hidden_volume_password);
1027 }
1028
set_encrypted_volume_read_only(const char * admin_pin)1029 void NitrokeyManager::set_encrypted_volume_read_only(const char* admin_pin) {
1030 misc::execute_password_command<stick20::SetEncryptedVolumeReadOnly>(device, admin_pin);
1031 }
1032
set_encrypted_volume_read_write(const char * admin_pin)1033 void NitrokeyManager::set_encrypted_volume_read_write(const char* admin_pin) {
1034 misc::execute_password_command<stick20::SetEncryptedVolumeReadWrite>(device, admin_pin);
1035 }
1036
1037 //TODO check is encrypted volume unlocked before execution
1038 //if not return library exception
create_hidden_volume(uint8_t slot_nr,uint8_t start_percent,uint8_t end_percent,const char * hidden_volume_password)1039 void NitrokeyManager::create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent,
1040 const char *hidden_volume_password) {
1041 auto p = get_payload<stick20::SetupHiddenVolume>();
1042 p.SlotNr_u8 = slot_nr;
1043 p.StartBlockPercent_u8 = start_percent;
1044 p.EndBlockPercent_u8 = end_percent;
1045 strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password);
1046 stick20::SetupHiddenVolume::CommandTransaction::run(device, p);
1047 }
1048
set_unencrypted_read_only_admin(const char * admin_pin)1049 void NitrokeyManager::set_unencrypted_read_only_admin(const char* admin_pin) {
1050 //from v0.49, v0.52+ it needs Admin PIN
1051 if (set_unencrypted_volume_rorw_pin_type_user()){
1052 LOG("set_unencrypted_read_only_admin is not supported for this version of Storage device. "
1053 "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING);
1054 return;
1055 }
1056 misc::execute_password_command<stick20::SetUnencryptedVolumeReadOnlyAdmin>(device, admin_pin);
1057 }
1058
set_unencrypted_read_only(const char * user_pin)1059 void NitrokeyManager::set_unencrypted_read_only(const char *user_pin) {
1060 //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient
1061 LOG("set_unencrypted_read_only is deprecated. Use set_unencrypted_read_only_admin instead.",
1062 nitrokey::log::Loglevel::WARNING);
1063 if (!set_unencrypted_volume_rorw_pin_type_user()){
1064 LOG("set_unencrypted_read_only is not supported for this version of Storage device. Doing nothing.",
1065 nitrokey::log::Loglevel::WARNING);
1066 return;
1067 }
1068 misc::execute_password_command<stick20::SendSetReadonlyToUncryptedVolume>(device, user_pin);
1069 }
1070
set_unencrypted_read_write_admin(const char * admin_pin)1071 void NitrokeyManager::set_unencrypted_read_write_admin(const char* admin_pin) {
1072 //from v0.49, v0.52+ it needs Admin PIN
1073 if (set_unencrypted_volume_rorw_pin_type_user()){
1074 LOG("set_unencrypted_read_write_admin is not supported for this version of Storage device. "
1075 "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING);
1076 return;
1077 }
1078 misc::execute_password_command<stick20::SetUnencryptedVolumeReadWriteAdmin>(device, admin_pin);
1079 }
1080
set_unencrypted_read_write(const char * user_pin)1081 void NitrokeyManager::set_unencrypted_read_write(const char *user_pin) {
1082 //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient
1083 LOG("set_unencrypted_read_write is deprecated. Use set_unencrypted_read_write_admin instead.",
1084 nitrokey::log::Loglevel::WARNING);
1085 if (!set_unencrypted_volume_rorw_pin_type_user()){
1086 LOG("set_unencrypted_read_write is not supported for this version of Storage device. Doing nothing.",
1087 nitrokey::log::Loglevel::WARNING);
1088 return;
1089 }
1090 misc::execute_password_command<stick20::SendSetReadwriteToUncryptedVolume>(device, user_pin);
1091 }
1092
set_unencrypted_volume_rorw_pin_type_user()1093 bool NitrokeyManager::set_unencrypted_volume_rorw_pin_type_user(){
1094 auto minor_firmware_version = get_minor_firmware_version();
1095 return minor_firmware_version <= 48 || minor_firmware_version == 50 || minor_firmware_version == 51;
1096 }
1097
export_firmware(const char * admin_pin)1098 void NitrokeyManager::export_firmware(const char* admin_pin) {
1099 misc::execute_password_command<stick20::ExportFirmware>(device, admin_pin);
1100 }
1101
enable_firmware_update(const char * firmware_pin)1102 void NitrokeyManager::enable_firmware_update(const char* firmware_pin) {
1103 misc::execute_password_command<stick20::EnableFirmwareUpdate>(device, firmware_pin);
1104 }
1105
clear_new_sd_card_warning(const char * admin_pin)1106 void NitrokeyManager::clear_new_sd_card_warning(const char* admin_pin) {
1107 misc::execute_password_command<stick20::SendClearNewSdCardFound>(device, admin_pin);
1108 }
1109
fill_SD_card_with_random_data(const char * admin_pin)1110 void NitrokeyManager::fill_SD_card_with_random_data(const char* admin_pin) {
1111 auto p = get_payload<stick20::FillSDCardWithRandomChars>();
1112 p.set_defaults();
1113 strcpyT(p.admin_pin, admin_pin);
1114 stick20::FillSDCardWithRandomChars::CommandTransaction::run(device, p);
1115 }
1116
change_update_password(const char * current_update_password,const char * new_update_password)1117 void NitrokeyManager::change_update_password(const char* current_update_password, const char* new_update_password) {
1118 auto p = get_payload<stick20::ChangeUpdatePassword>();
1119 strcpyT(p.current_update_password, current_update_password);
1120 strcpyT(p.new_update_password, new_update_password);
1121 stick20::ChangeUpdatePassword::CommandTransaction::run(device, p);
1122 }
1123
get_status_storage_as_string()1124 char * NitrokeyManager::get_status_storage_as_string(){
1125 auto p = stick20::GetDeviceStatus::CommandTransaction::run(device);
1126 return strndup(p.data().dissect().c_str(), max_string_field_length);
1127 }
1128
get_status_storage()1129 stick20::DeviceConfigurationResponsePacket::ResponsePayload NitrokeyManager::get_status_storage(){
1130 auto p = stick20::GetDeviceStatus::CommandTransaction::run(device);
1131 return p.data();
1132 }
1133
get_SD_usage_data_as_string()1134 char * NitrokeyManager::get_SD_usage_data_as_string(){
1135 auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device);
1136 return strndup(p.data().dissect().c_str(), max_string_field_length);
1137 }
1138
get_SD_usage_data()1139 std::pair<uint8_t,uint8_t> NitrokeyManager::get_SD_usage_data(){
1140 auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device);
1141 return std::make_pair(p.data().WriteLevelMin, p.data().WriteLevelMax);
1142 }
1143
get_progress_bar_value()1144 int NitrokeyManager::get_progress_bar_value(){
1145 try{
1146 stick20::GetDeviceStatus::CommandTransaction::run(device);
1147 return -1;
1148 }
1149 catch (LongOperationInProgressException &e){
1150 return e.progress_bar_value;
1151 }
1152 }
1153
get_TOTP_code(uint8_t slot_number,const char * user_temporary_password)1154 string NitrokeyManager::get_TOTP_code(uint8_t slot_number, const char *user_temporary_password) {
1155 return get_TOTP_code(slot_number, 0, 0, 0, user_temporary_password);
1156 }
1157
1158 /**
1159 * Returns ReadSlot structure, describing OTP slot configuration. Always return binary counter -
1160 * does the necessary conversion, if needed, to unify the behavior across Pro and Storage.
1161 * @private For internal use only
1162 * @param slot_number which OTP slot to use (usual format)
1163 * @return ReadSlot structure
1164 */
get_OTP_slot_data(const uint8_t slot_number)1165 stick10::ReadSlot::ResponsePayload NitrokeyManager::get_OTP_slot_data(const uint8_t slot_number) {
1166 auto p = get_payload<stick10::ReadSlot>();
1167 p.slot_number = slot_number;
1168 p.data_format = stick10::ReadSlot::CounterFormat::BINARY; // ignored for devices other than Storage v0.54+
1169 auto data = stick10::ReadSlot::CommandTransaction::run(device, p);
1170
1171 auto &payload = data.data();
1172
1173 // if fw <=v0.53 and asked binary - do the conversion from ASCII
1174 if (device->get_device_model() == DeviceModel::STORAGE && get_minor_firmware_version() <= 53
1175 && is_internal_hotp_slot_number(slot_number))
1176 {
1177 //convert counter from string to ull
1178 auto counter_s = std::string(payload.slot_counter_s, payload.slot_counter_s + sizeof(payload.slot_counter_s));
1179 payload.slot_counter = std::stoull(counter_s);
1180 }
1181
1182 return payload;
1183 }
1184
get_TOTP_slot_data(const uint8_t slot_number)1185 stick10::ReadSlot::ResponsePayload NitrokeyManager::get_TOTP_slot_data(const uint8_t slot_number) {
1186 return get_OTP_slot_data(get_internal_slot_number_for_totp(slot_number));
1187 }
1188
get_HOTP_slot_data(const uint8_t slot_number)1189 stick10::ReadSlot::ResponsePayload NitrokeyManager::get_HOTP_slot_data(const uint8_t slot_number) {
1190 return get_OTP_slot_data(get_internal_slot_number_for_hotp(slot_number));
1191 }
1192
lock_encrypted_volume()1193 void NitrokeyManager::lock_encrypted_volume() {
1194 misc::execute_password_command<stick20::DisableEncryptedPartition>(device, "");
1195 }
1196
lock_hidden_volume()1197 void NitrokeyManager::lock_hidden_volume() {
1198 misc::execute_password_command<stick20::DisableHiddenEncryptedPartition>(device, "");
1199 }
1200
get_SD_card_size()1201 uint8_t NitrokeyManager::get_SD_card_size() {
1202 auto data = stick20::ProductionTest::CommandTransaction::run(device);
1203 return data.data().SD_Card_Size_u8;
1204 }
1205
get_current_device_id() const1206 const string NitrokeyManager::get_current_device_id() const {
1207 return current_device_id;
1208 }
1209
wink()1210 void NitrokeyManager::wink(){
1211 stick20::Wink::CommandTransaction::run(device);
1212 };
1213
production_info()1214 stick20::ProductionTest::ResponsePayload NitrokeyManager::production_info(){
1215 auto data = stick20::ProductionTest::CommandTransaction::run(device);
1216 return data.data();
1217 };
1218
enable_firmware_update_pro(const char * firmware_pin)1219 void NitrokeyManager::enable_firmware_update_pro(const char *firmware_pin) {
1220 auto p = get_payload<FirmwareUpdate>();
1221 strcpyT(p.firmware_password, firmware_pin);
1222 FirmwareUpdate::CommandTransaction::run(device, p);
1223 }
1224
1225 void
change_firmware_update_password_pro(const char * firmware_pin_current,const char * firmware_pin_new)1226 NitrokeyManager::change_firmware_update_password_pro(const char *firmware_pin_current, const char *firmware_pin_new) {
1227 auto p = get_payload<FirmwarePasswordChange>();
1228 strcpyT(p.firmware_password_current, firmware_pin_current);
1229 strcpyT(p.firmware_password_new, firmware_pin_new);
1230 FirmwarePasswordChange::CommandTransaction::run(device, p);
1231 }
1232
1233 }
1234