diff options
author | Szczepan Zalega <szczepan@nitrokey.com> | 2017-03-11 17:18:59 +0100 |
---|---|---|
committer | Szczepan Zalega <szczepan@nitrokey.com> | 2017-03-11 17:18:59 +0100 |
commit | 22d05ce647281056d71fbd3c31df3bcd6396188d (patch) | |
tree | 90208930f54c47987bfd5ffcf0a0acaaad2510da /unittest | |
parent | ed5044da43172d86a1aa475473561a4818b7c69c (diff) | |
parent | ac6b9c18ef55f4cd36e85069cf0cf82c14e04404 (diff) | |
download | libnitrokey-22d05ce647281056d71fbd3c31df3bcd6396188d.tar.gz libnitrokey-22d05ce647281056d71fbd3c31df3bcd6396188d.tar.bz2 |
Merge branch 'libnitrokey_3'
Diffstat (limited to 'unittest')
-rw-r--r-- | unittest/Makefile | 33 | ||||
-rw-r--r-- | unittest/conftest.py | 22 | ||||
-rw-r--r-- | unittest/requirements.txt | 1 | ||||
-rw-r--r-- | unittest/setup_python_dependencies.sh | 3 | ||||
-rw-r--r-- | unittest/test.cc | 10 | ||||
-rw-r--r-- | unittest/test2.cc | 28 | ||||
-rw-r--r-- | unittest/test3.cc | 27 | ||||
-rw-r--r-- | unittest/test_C_API.cpp | 4 | ||||
-rw-r--r-- | unittest/test_HOTP.cc | 9 | ||||
-rw-r--r-- | unittest/test_pro.py | 83 | ||||
-rw-r--r-- | unittest/test_storage.py | 155 |
11 files changed, 288 insertions, 87 deletions
diff --git a/unittest/Makefile b/unittest/Makefile deleted file mode 100644 index dbd003e..0000000 --- a/unittest/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CC = $(PREFIX)-gcc -#CXX = $(PREFIX)-g++ -CXX = clang++-3.8 -LD = $(CXX) - -INCLUDE = -I../include -ICatch/single_include/ -LIB = -L../build -LDLIBS = -lnitrokey -BUILD = build - -CXXFLAGS = -std=c++14 -fPIC -Wno-gnu-variable-sized-type-not-at-end - -CXXSOURCES = $(wildcard *.cc) -TARGETS = $(CXXSOURCES:%.cc=$(BUILD)/%) -DEPENDS = $(CXXSOURCES:%.cc=$(BUILD)/%.d) - -$(BUILD)/%.d: %.cc - $(CXX) -M $< -o $@ $(INCLUDE) $(CXXFLAGS) - -$(BUILD)/%: %.cc $(DEPENDS) - $(CXX) $< -o $@ $(INCLUDE) $(LIB) $(CXXFLAGS) $(LDLIBS) - -all: $(TARGETS) - -clean: - rm -f $(TARGETS) - -mrproper: clean - rm -f $(BUILD)/*.d - -.PHONY: all clean mrproper - -include $(wildcard build/*.d) diff --git a/unittest/conftest.py b/unittest/conftest.py index 88bf7d0..67b45aa 100644 --- a/unittest/conftest.py +++ b/unittest/conftest.py @@ -22,14 +22,30 @@ def C(request): a = iter(declarations) for declaration in a: - if declaration.startswith('extern') and not '"C"' in declaration: - declaration = declaration.replace('extern', '').strip() + if declaration.startswith('NK_C_API'): + declaration = declaration.replace('NK_C_API', '').strip() while not ';' in declaration: declaration += (next(a)).strip() print(declaration) ffi.cdef(declaration, override=True) - C = ffi.dlopen("../build/libnitrokey.so") + C = None + import os, sys + path_build = os.path.join("..", "build") + paths = [ os.path.join(path_build,"libnitrokey-log.so"), + os.path.join(path_build,"libnitrokey.so")] + for p in paths: + print p + if os.path.exists(p): + C = ffi.dlopen(p) + break + else: + print("File does not exist: " + p) + print("Trying another") + if not C: + print("No library file found") + sys.exit(1) + C.NK_set_debug(False) nk_login = C.NK_login_auto() if nk_login != 1: diff --git a/unittest/requirements.txt b/unittest/requirements.txt index 7224741..2cb9c05 100644 --- a/unittest/requirements.txt +++ b/unittest/requirements.txt @@ -2,3 +2,4 @@ cffi pytest-repeat pytest-randomly enum +oath
\ No newline at end of file diff --git a/unittest/setup_python_dependencies.sh b/unittest/setup_python_dependencies.sh new file mode 100644 index 0000000..0f1a0f7 --- /dev/null +++ b/unittest/setup_python_dependencies.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pip install -r requirements.txt --user diff --git a/unittest/test.cc b/unittest/test.cc index 6744b45..15235bd 100644 --- a/unittest/test.cc +++ b/unittest/test.cc @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() #include "catch.hpp" #include <iostream> @@ -13,8 +12,9 @@ using namespace nitrokey::proto::stick10; using namespace nitrokey::log; using namespace nitrokey::misc; +using Dev10 = std::shared_ptr<Stick10>; -std::string getSlotName(Stick10 &stick, int slotNo) { +std::string getSlotName(Dev10 stick, int slotNo) { auto slot_req = get_payload<ReadSlot>(); slot_req.slot_number = slotNo; auto slot = ReadSlot::CommandTransaction::run(stick, slot_req); @@ -23,8 +23,8 @@ std::string getSlotName(Stick10 &stick, int slotNo) { } TEST_CASE("Slot names are correct", "[slotNames]") { - Stick10 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick10>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); @@ -79,5 +79,5 @@ TEST_CASE("Slot names are correct", "[slotNames]") { REQUIRE(sName == std::string("login1")); } - stick.disconnect(); + stick->disconnect(); } diff --git a/unittest/test2.cc b/unittest/test2.cc index 00e70e3..31dbce8 100644 --- a/unittest/test2.cc +++ b/unittest/test2.cc @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() static const char *const default_admin_pin = "12345678"; static const char *const default_user_pin = "123456"; @@ -20,9 +19,10 @@ using namespace nitrokey::proto::stick20; using namespace nitrokey::log; using namespace nitrokey::misc; +#include <memory> template<typename CMDTYPE> -void execute_password_command(Device &stick, const char *password, const char kind = 'P') { +void execute_password_command(std::shared_ptr<Device> stick, const char *password, const char kind = 'P') { auto p = get_payload<CMDTYPE>(); if (kind == 'P'){ p.set_kind_user(); @@ -47,8 +47,8 @@ void SKIP_TEST() { TEST_CASE("long operation test", "[test_long]") { SKIP_TEST(); - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); try{ @@ -123,8 +123,8 @@ TEST_CASE("test device commands ids", "[fast]") { } TEST_CASE("test device internal status with various commands", "[fast]") { - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); @@ -147,8 +147,8 @@ TEST_CASE("test device internal status with various commands", "[fast]") { } TEST_CASE("setup hidden volume test", "[hidden]") { - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); stick10::LockDevice::CommandTransaction::run(stick); @@ -170,8 +170,8 @@ TEST_CASE("setup hidden volume test", "[hidden]") { } TEST_CASE("setup multiple hidden volumes", "[hidden]") { - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); @@ -207,8 +207,8 @@ TEST_CASE("setup multiple hidden volumes", "[hidden]") { TEST_CASE("update password change", "[dangerous]") { SKIP_TEST(); - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); @@ -228,8 +228,8 @@ TEST_CASE("update password change", "[dangerous]") { } TEST_CASE("general test", "[test]") { - Stick20 stick; - bool connected = stick.connect(); + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); diff --git a/unittest/test3.cc b/unittest/test3.cc index 9049365..9e0ef11 100644 --- a/unittest/test3.cc +++ b/unittest/test3.cc @@ -1,8 +1,3 @@ -// -// Created by sz on 08.11.16. -// - -#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() static const char *const default_admin_pin = "12345678"; static const char *const default_user_pin = "123456"; @@ -26,13 +21,16 @@ using namespace nitrokey::proto::stick10_08; using namespace nitrokey::log; using namespace nitrokey::misc; -void connect_and_setup(Stick10 &stick) { - bool connected = stick.connect(); +using Dev = Stick10; +using Dev10 = std::shared_ptr<Dev>; + +void connect_and_setup(Dev10 stick) { + bool connected = stick->connect(); REQUIRE(connected == true); Log::instance().set_loglevel(Loglevel::DEBUG); } -void authorize(Stick10 &stick) { +void authorize(Dev10 stick) { auto authreq = get_payload<FirstAuthenticate>(); strcpy((char *) (authreq.card_password), default_admin_pin); strcpy((char *) (authreq.temporary_password), temporary_password); @@ -45,7 +43,8 @@ void authorize(Stick10 &stick) { } TEST_CASE("write slot", "[pronew]"){ - Stick10 stick; + auto stick = make_shared<Dev>(); + connect_and_setup(stick); authorize(stick); @@ -81,7 +80,7 @@ TEST_CASE("write slot", "[pronew]"){ TEST_CASE("erase slot", "[pronew]"){ - Stick10 stick; + auto stick = make_shared<Dev>(); connect_and_setup(stick); authorize(stick); @@ -107,7 +106,7 @@ TEST_CASE("erase slot", "[pronew]"){ } TEST_CASE("write general config", "[pronew]") { - Stick10 stick; + auto stick = make_shared<Dev>(); connect_and_setup(stick); authorize(stick); @@ -121,7 +120,7 @@ TEST_CASE("write general config", "[pronew]") { } TEST_CASE("authorize user HOTP", "[pronew]") { - Stick10 stick; + auto stick = make_shared<Dev>(); connect_and_setup(stick); authorize(stick); @@ -164,7 +163,7 @@ TEST_CASE("authorize user HOTP", "[pronew]") { } TEST_CASE("check firmware version", "[pronew]") { - Stick10 stick; + auto stick = make_shared<Dev>(); connect_and_setup(stick); auto p = GetStatus::CommandTransaction::run(stick); @@ -172,7 +171,7 @@ TEST_CASE("check firmware version", "[pronew]") { } TEST_CASE("authorize user TOTP", "[pronew]") { - Stick10 stick; + auto stick = make_shared<Dev>(); connect_and_setup(stick); authorize(stick); diff --git a/unittest/test_C_API.cpp b/unittest/test_C_API.cpp index 37d3c7f..160145b 100644 --- a/unittest/test_C_API.cpp +++ b/unittest/test_C_API.cpp @@ -24,8 +24,8 @@ TEST_CASE("Check retry count", "[BASIC]") { } TEST_CASE("Check long strings", "[STANDARD]") { - char* longPin = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - char *pin = "123123123"; + const char* longPin = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const char* pin = "123123123"; auto result = NK_change_user_PIN(longPin, pin); REQUIRE(result == TOO_LONG_STRING); result = NK_change_user_PIN(pin, longPin); diff --git a/unittest/test_HOTP.cc b/unittest/test_HOTP.cc index d31df55..e6f7d7c 100644 --- a/unittest/test_HOTP.cc +++ b/unittest/test_HOTP.cc @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() #include "catch.hpp" #include <iostream> #include "device_proto.h" @@ -14,7 +13,7 @@ using namespace nitrokey::log; using namespace nitrokey::misc; void hexStringToByte(uint8_t data[], const char* hexString){ - assert(strlen(hexString)%2==0); + REQUIRE(strlen(hexString)%2==0); char buf[2]; for(int i=0; i<strlen(hexString); i++){ buf[i%2] = hexString[i]; @@ -34,8 +33,8 @@ TEST_CASE("test secret", "[functions]") { } TEST_CASE("Test HOTP codes according to RFC", "[HOTP]") { - Stick10 stick; - bool connected = stick.connect(); + std::shared_ptr<Stick10> stick = make_shared<Stick10>(); + bool connected = stick->connect(); REQUIRE(connected == true); @@ -98,5 +97,5 @@ TEST_CASE("Test HOTP codes according to RFC", "[HOTP]") { } - stick.disconnect(); + stick->disconnect(); } diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 4a2a504..0140994 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -22,6 +22,72 @@ def test_write_password_safe_slot(C): assert C.NK_write_password_safe_slot(0, 'slotname1', 'login1', 'pass1') == DeviceErrorCode.STATUS_OK +@pytest.mark.slowtest +def test_write_all_password_safe_slots_and_read_10_times(C): + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890'*4 + s += numbers[:wid-len(s)] + assert len(s) == wid + return s + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + for i in range(0, PWS_slot_count): + iss = str(i) + assert C.NK_write_password_safe_slot(i, + get_slotname(iss), get_loginname(iss), + get_pass(iss)) == DeviceErrorCode.STATUS_OK + + for j in range(0, 10): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + +@pytest.mark.slowtest +@pytest.mark.xfail(reason="This test should be run directly after test_write_all_password_safe_slots_and_read_10_times") +def test_read_all_password_safe_slots_10_times(C): + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890'*4 + s += numbers[:wid-len(s)] + assert len(s) == wid + return s + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + + for j in range(0, 10): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + def test_get_password_safe_slot_name(C): assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK assert C.NK_write_password_safe_slot(0, 'slotname1', 'login1', 'pass1') == DeviceErrorCode.STATUS_OK @@ -82,6 +148,9 @@ def test_regenerate_aes_key(C): def test_enable_password_safe_after_factory_reset(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + if is_storage(C): + # for some reason storage likes to be authenticated before reset (to investigate) + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK wait(10) if is_storage(C): @@ -523,7 +592,7 @@ def test_OTP_secret_started_from_null(C, secret): skip_if_device_version_lower_than({'S': 43, 'P': 8}) if len(secret) > 40: # feature: 320 bit long secret handling - skip_if_device_version_lower_than({'S': 44, 'P': 8}) + skip_if_device_version_lower_than({'P': 8}) oath = pytest.importorskip("oath") lib_at = lambda t: oath.hotp(secret, t, format='dec6') @@ -617,8 +686,9 @@ def test_TOTP_secrets(C, secret): ''' skip_if_device_version_lower_than({'S': 44, 'P': 8}) - if is_pro_rtm_07(C) and len(secret)>20*2: #*2 since secret is in hex - pytest.skip("Secret lengths over 20 bytes are not supported by NK Pro 0.7 ") + if len(secret)>20*2: #*2 since secret is in hex + # pytest.skip("Secret lengths over 20 bytes are not supported by NK Pro 0.7 and NK Storage") + skip_if_device_version_lower_than({'P': 8}) slot_number = 0 time = 0 period = 30 @@ -645,10 +715,11 @@ def test_TOTP_secrets(C, secret): @pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) def test_HOTP_secrets(C, secret): """ - NK Pro 0.8+, NK Storage 0.44+ + NK Pro 0.8+ feature needed: support for 320bit secrets """ - skip_if_device_version_lower_than({'S': 44, 'P': 8}) + if len(secret)>40: + skip_if_device_version_lower_than({'P': 8}) slot_number = 0 counter = 0 @@ -695,7 +766,7 @@ def test_edit_OTP_slot(C): """ should change slots counter and name without changing its secret (using null secret for second update) """ - # counter does not reset under Storage v0.43 + # counter is not getting updated under Storage v0.43 - #TOREPORT skip_if_device_version_lower_than({'S': 44, 'P': 7}) secret = RFC_SECRET diff --git a/unittest/test_storage.py b/unittest/test_storage.py index a1c59aa..da7c9a3 100644 --- a/unittest/test_storage.py +++ b/unittest/test_storage.py @@ -57,10 +57,11 @@ def test_encrypted_volume_unlock_hidden(C): assert C.NK_create_hidden_volume(0, 20, 21, hidden_volume_password) == DeviceErrorCode.STATUS_OK assert C.NK_unlock_hidden_volume(hidden_volume_password) == DeviceErrorCode.STATUS_OK -@pytest.mark.skip(reason='hangs device, to report') -def test_encrypted_volume_setup_multiple_hidden(C): - skip_if_device_version_lower_than({'S': 43}) - hidden_volume_password = 'hiddenpassword' + +def test_encrypted_volume_setup_multiple_hidden_lock(C): + import random + skip_if_device_version_lower_than({'S': 45}) #hangs device on lower version + hidden_volume_password = 'hiddenpassword' + str(random.randint(0,100)) p = lambda i: hidden_volume_password + str(i) assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK @@ -72,6 +73,149 @@ def test_encrypted_volume_setup_multiple_hidden(C): assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK +@pytest.mark.parametrize("volumes_to_setup", range(1, 5)) +def test_encrypted_volume_setup_multiple_hidden_no_lock_device_volumes(C, volumes_to_setup): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = 'hiddenpassword' + p = lambda i: hidden_volume_password + str(i) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.parametrize("volumes_to_setup", range(1, 5)) +def test_encrypted_volume_setup_multiple_hidden_no_lock_device_volumes_unlock_at_once(C, volumes_to_setup): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = 'hiddenpassword' + p = lambda i: hidden_volume_password + str(i) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.parametrize("use_slot", range(4)) +def test_encrypted_volume_setup_one_hidden_no_lock_device_slot(C, use_slot): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = 'hiddenpassword' + p = lambda i: hidden_volume_password + str(i) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + i = use_slot + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for j in range(3): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +def test_password_safe_slot_name_corruption(C): + skip_if_device_version_lower_than({'S': 43}) + volumes_to_setup = 4 + # connected with encrypted volumes, possible also with hidden + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890' * 4 + s += numbers[:wid - len(s)] + assert len(s) == wid + return s + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + for i in range(0, PWS_slot_count): + iss = str(i) + assert C.NK_write_password_safe_slot(i, + get_slotname(iss), get_loginname(iss), + get_pass(iss)) == DeviceErrorCode.STATUS_OK + + def check_PWS_correctness(C): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + hidden_volume_password = 'hiddenpassword' + p = lambda i: hidden_volume_password + str(i) + def check_volumes_correctness(C): + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + check_PWS_correctness(C) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + check_volumes_correctness(C) + check_PWS_correctness(C) + check_volumes_correctness(C) + check_PWS_correctness(C) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + check_volumes_correctness(C) + check_PWS_correctness(C) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + check_volumes_correctness(C) + check_PWS_correctness(C) + +def test_hidden_volume_corruption(C): + # bug: this should return error without unlocking encrypted volume each hidden volume lock, but it does not + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + hidden_volume_password = 'hiddenpassword' + p = lambda i: hidden_volume_password + str(i) + for i in range(4): + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + wait(2) + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + def test_unencrypted_volume_set_read_only(C): skip_if_device_version_lower_than({'S': 43}) assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK @@ -94,7 +238,8 @@ def test_clear_new_sd_card_notification(C): assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK -@pytest.mark.skip +@pytest.mark.slowtest +@pytest.mark.skip(reason='long test (about 1h)') def test_fill_SD_card(C): skip_if_device_version_lower_than({'S': 43}) status = C.NK_fill_SD_card_with_random_data(DefaultPasswords.ADMIN) |