From b94d61b2f3c446c46ac2f660d954841d740782f5 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Wed, 9 Nov 2016 19:20:51 +0100 Subject: Detect Pro 0.8 Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 6ab2af9..c7772d6 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -2,7 +2,7 @@ import pytest from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET from misc import ffi, gs, wait, cast_pointer_to_tuple -from misc import is_pro_rtm_07, is_storage +from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage def test_enable_password_safe(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK @@ -61,7 +61,7 @@ def test_password_safe_slot_status(C): def test_issue_device_locks_on_second_key_generation_in_sequence(C): - if is_pro_rtm_07(C): + if is_pro_rtm_07(C) or is_pro_rtm_08(C): pytest.skip("issue to register: device locks up " "after below commands sequence (reinsertion fixes), skipping for now") assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK -- cgit v1.2.1 From d28794ef7d6d6fa7e8d6478fb912302691fe75e7 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 12 Nov 2016 18:34:23 +0100 Subject: Add test for STATUS_AES_DEC_FAILED error Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index c7772d6..5c8ecb4 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -74,6 +74,14 @@ def test_regenerate_aes_key(C): assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK +def test_enable_password_safe_after_factory_reset(C): + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + wait(10) + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_AES_DEC_FAILED + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + @pytest.mark.xfail(reason="NK Pro firmware bug: regenerating AES key command not always results in cleared slot data") def test_destroy_password_safe(C): @@ -96,6 +104,7 @@ def test_destroy_password_safe(C): assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK assert gs(C.NK_get_password_safe_slot_name(0)) != 'slotname1' -- cgit v1.2.1 From 411921354998d01229ba1cd10424df05441825be Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Tue, 15 Nov 2016 20:17:02 +0100 Subject: Tests: secret started with null byte Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 5c8ecb4..8c99f81 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -74,6 +74,7 @@ def test_regenerate_aes_key(C): assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + def test_enable_password_safe_after_factory_reset(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK @@ -294,6 +295,7 @@ def test_HOTP_64bit_counter(C): assert C.NK_write_hotp_slot(slot_number, 'python_test', RFC_SECRET, t, use_8_digits, False, False, "", DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK code_device = str(C.NK_get_hotp_code(slot_number)) + code_device = '0'+code_device if len(code_device) < 6 else code_device dev_res += (t, code_device) lib_res += (t, lib_at(t)) assert dev_res == lib_res @@ -319,6 +321,7 @@ def test_TOTP_64bit_time(C): assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_totp_set_time(t) == DeviceErrorCode.STATUS_OK code_device = str((C.NK_get_totp_code(slot_number, T, 0, 30))) + code_device = '0'+code_device if len(code_device) < 6 else code_device dev_res += (t, code_device) lib_res += (t, lib_at(t)) assert dev_res == lib_res @@ -495,3 +498,25 @@ def test_get_serial_number(C): sn = gs(sn) assert len(sn) > 0 print(('Serial number of the device: ', sn)) + +@pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) +def test_OTP_secret_started_from_null(C, secret): + oath = pytest.importorskip("oath") + lib_at = lambda t: oath.hotp(secret, t, format='dec6') + PIN_protection = False + use_8_digits = False + slot_number = 1 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for t in range(1,5): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, 'null_secret', secret, t, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_hotp_code(slot_number)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + dev_res += (t, code_device) + lib_res += (t, lib_at(t)) + assert dev_res == lib_res -- cgit v1.2.1 From 54d3b649b4c6d51120c16c64b7f824c81123a807 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Wed, 16 Nov 2016 11:25:17 +0100 Subject: Tests: more OTP, test all slots for read/write Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 8c99f81..a9e9fa4 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -520,3 +520,57 @@ def test_OTP_secret_started_from_null(C, secret): dev_res += (t, code_device) lib_res += (t, lib_at(t)) assert dev_res == lib_res + + +@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff] ) +def test_HOTP_slots_read_write_counter(C, counter): + secret = RFC_SECRET + oath = pytest.importorskip("oath") + lib_at = lambda t: oath.hotp(secret, t, format='dec6') + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for slot_number in range(3): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, 'null_secret', secret, counter, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_hotp_code(slot_number)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + dev_res += (counter, code_device) + lib_res += (counter, lib_at(counter)) + assert dev_res == lib_res + + +@pytest.mark.parametrize("period", [30,60] ) +@pytest.mark.parametrize("time", range(20,70,20) ) +def test_TOTP_slots_read_write_at_time_period(C, time, period): + secret = RFC_SECRET + oath = pytest.importorskip("oath") + lib_at = lambda t: oath.totp(RFC_SECRET, t=t, period=period) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for slot_number in range(15): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(slot_number, 'null_secret', secret, period, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_totp_code(slot_number, T, 0, period)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + dev_res += (time, code_device) + lib_res += (time, lib_at(time)) + assert dev_res == lib_res + + + + -- cgit v1.2.1 From cbccc871329c5522449010ae5007278123508820 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Wed, 16 Nov 2016 18:32:38 +0100 Subject: Use another OTP writing protocol and test it Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index a9e9fa4..3632ecd 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -536,7 +536,7 @@ def test_HOTP_slots_read_write_counter(C, counter): lib_res = [] for slot_number in range(3): assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK - assert C.NK_write_hotp_slot(slot_number, 'null_secret', secret, counter, use_8_digits, False, False, "", + assert C.NK_write_hotp_slot(slot_number, 'HOTP rw' + str(slot_number), secret, counter, use_8_digits, False, False, "", DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK code_device = str(C.NK_get_hotp_code(slot_number)) code_device = '0'+code_device if len(code_device) < 6 else code_device @@ -546,7 +546,7 @@ def test_HOTP_slots_read_write_counter(C, counter): @pytest.mark.parametrize("period", [30,60] ) -@pytest.mark.parametrize("time", range(20,70,20) ) +@pytest.mark.parametrize("time", range(21,70,20) ) def test_TOTP_slots_read_write_at_time_period(C, time, period): secret = RFC_SECRET oath = pytest.importorskip("oath") @@ -561,7 +561,7 @@ def test_TOTP_slots_read_write_at_time_period(C, time, period): lib_res = [] for slot_number in range(15): assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK - assert C.NK_write_totp_slot(slot_number, 'null_secret', secret, period, use_8_digits, False, False, "", + assert C.NK_write_totp_slot(slot_number, 'TOTP rw' + str(slot_number), secret, period, use_8_digits, False, False, "", DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK @@ -572,5 +572,32 @@ def test_TOTP_slots_read_write_at_time_period(C, time, period): assert dev_res == lib_res +@pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET] ) +def test_TOTP_secrets(C, secret): + slot_number = 0 + time = 0 + period = 30 + oath = pytest.importorskip("oath") + lib_at = lambda t: oath.totp(secret, t=t, period=period) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(slot_number, 'TOTP secret' + str(slot_number), secret, period, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_totp_code(slot_number, T, 0, period)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + dev_res += (time, code_device) + lib_res += (time, lib_at(time)) + assert dev_res == lib_res + + -- cgit v1.2.1 From 9c2feef240e396648dfb2378f7d2428b0593c9f2 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 18 Nov 2016 12:52:50 +0100 Subject: Support longer secrets (40 bytes) for NK Pro 0.8 Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 3632ecd..71abfba 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -501,6 +501,9 @@ def test_get_serial_number(C): @pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) def test_OTP_secret_started_from_null(C, secret): + ''' + NK Pro 0.8+, NK Storage 0.43+ + ''' oath = pytest.importorskip("oath") lib_at = lambda t: oath.hotp(secret, t, format='dec6') PIN_protection = False @@ -522,7 +525,7 @@ def test_OTP_secret_started_from_null(C, secret): assert dev_res == lib_res -@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff] ) +@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff, 0xffffffff, 0xffffffffffffffff] ) def test_HOTP_slots_read_write_counter(C, counter): secret = RFC_SECRET oath = pytest.importorskip("oath") @@ -571,9 +574,13 @@ def test_TOTP_slots_read_write_at_time_period(C, time, period): lib_res += (time, lib_at(time)) assert dev_res == lib_res - -@pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET] ) +@pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) def test_TOTP_secrets(C, secret): + ''' + NK Pro 0.8+, NK Storage 0.44+ + ''' + 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 ") slot_number = 0 time = 0 period = 30 @@ -587,10 +594,8 @@ def test_TOTP_secrets(C, secret): DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK dev_res = [] lib_res = [] - assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK - assert C.NK_write_totp_slot(slot_number, 'TOTP secret' + str(slot_number), secret, period, use_8_digits, False, False, "", + assert C.NK_write_totp_slot(slot_number, 'secret' + str(len(secret)), secret, period, use_8_digits, False, False, "", DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK - assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK code_device = str(C.NK_get_totp_code(slot_number, T, 0, period)) code_device = '0'+code_device if len(code_device) < 6 else code_device @@ -598,6 +603,30 @@ def test_TOTP_secrets(C, secret): lib_res += (time, lib_at(time)) assert dev_res == lib_res - - +@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+ + ''' + 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 ") + slot_number = 0 + counter = 0 + oath = pytest.importorskip("oath") + lib_at = lambda t: oath.hotp(secret, counter=t) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + assert C.NK_write_hotp_slot(slot_number, 'secret' + str(len(secret)), secret, counter, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_hotp_code(slot_number)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + dev_res += (counter, code_device) + lib_res += (counter, lib_at(counter)) + assert dev_res == lib_res -- cgit v1.2.1 From b33681083348588caa3db3885c811a3c42d5b094 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 19 Nov 2016 14:14:43 +0100 Subject: Support sending empty OTP secrets for slot edit (+test) Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 71abfba..b8109f2 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -630,3 +630,34 @@ def test_HOTP_secrets(C, secret): lib_res += (counter, lib_at(counter)) assert dev_res == lib_res + +def test_edit_OTP_slot(C): + """ + should change slots counter and name without changing its secret (using null secret for second update) + """ + secret = RFC_SECRET + counter = 0 + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + slot_number = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + first_name = 'edit slot' + assert C.NK_write_hotp_slot(slot_number, first_name, secret, counter, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_hotp_slot_name(slot_number)) == first_name + + + first_code = C.NK_get_hotp_code(slot_number) + changed_name = 'changedname' + empty_secret = '' + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, changed_name, empty_secret, counter, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + second_code = C.NK_get_hotp_code(slot_number) + assert first_code == second_code + assert gs(C.NK_get_hotp_slot_name(slot_number)) == changed_name + + -- cgit v1.2.1 From fbe8f668eb3ceb02a23f943d5db5070b0cafc401 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 19 Nov 2016 14:16:44 +0100 Subject: Test to configure getting HOTP codes through special key double press Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index b8109f2..aaf884f 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -631,6 +631,25 @@ def test_HOTP_secrets(C, secret): assert dev_res == lib_res +def test_special_double_press(C): + """ + requires manual check after function run + double press each of num-, scroll-, caps-lock and check inserted OTP codes (each 1st should be 755224) + on nkpro 0.7 scrolllock should do nothing, on nkpro 0.8+ should return OTP code + """ + secret = RFC_SECRET + counter = 0 + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(0, 1, 2, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + for slot_number in range(3): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, 'double' + str(slot_number), secret, counter, use_8_digits, False, False, "", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # requires manual check + def test_edit_OTP_slot(C): """ should change slots counter and name without changing its secret (using null secret for second update) -- cgit v1.2.1 From 5adc4b754de0a55f8c92dfbcd868630e65b4781f Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 19 Nov 2016 14:36:02 +0100 Subject: Update description for TOTP_RFC_usepin test Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index aaf884f..c8be0e8 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -327,9 +327,12 @@ def test_TOTP_64bit_time(C): assert dev_res == lib_res -@pytest.mark.xfail(reason="NK Pro: possible firmware bug or communication issue: set time command not always changes the time on stick thus failing this test, " - "this does not influence normal use since setting time is not done every TOTP code request" - "Rarely fail occurs on NK Storage") +@pytest.mark.xfail(reason="NK Pro: Test fails in 50% of cases due to test vectors set 1 second before interval count change" + "Here time is changed on seconds side only and miliseconds part is not being reset apparently" + "This results in available time to test of half a second on average, thus 50% failed cases" + "With disabled two first test vectors test passess 10/10 times" + "Fail may also occurs on NK Storage with lower occurrency since it needs less time to execute " + "commands") @pytest.mark.parametrize("PIN_protection", [False, True, ]) def test_TOTP_RFC_usepin(C, PIN_protection): slot_number = 1 @@ -350,8 +353,8 @@ def test_TOTP_RFC_usepin(C, PIN_protection): # Mode: Sha1, time step X=30 test_data = [ #Time T (hex) TOTP - (59, 0x1, 94287082), - (1111111109, 0x00000000023523EC, 7081804), + (59, 0x1, 94287082), # Warning - test vector time 1 second before interval count changes + (1111111109, 0x00000000023523EC, 7081804), # Warning - test vector time 1 second before interval count changes (1111111111, 0x00000000023523ED, 14050471), (1234567890, 0x000000000273EF07, 89005924), (2000000000, 0x0000000003F940AA, 69279037), -- cgit v1.2.1 From b9f7d118ecdef61764c3256a203010831e0c5d7d Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 26 Nov 2016 15:41:34 +0100 Subject: Test for manual checking of TOTP slot written by Nitrokey App Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index c8be0e8..89a6ccf 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -683,3 +683,23 @@ def test_edit_OTP_slot(C): assert gs(C.NK_get_hotp_slot_name(slot_number)) == changed_name +@pytest.mark.skip +@pytest.mark.parametrize("secret", ['31323334353637383930'*2,'31323334353637383930'*4] ) +def test_TOTP_codes_from_nitrokeyapp(secret, C): + """ + Helper test for manual TOTP check of written secret by Nitrokey App + Destined to run by hand + """ + slot_number = 0 + PIN_protection = False + period = 30 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = str(C.NK_get_totp_code(slot_number, 0, 0, period)) + code_device = '0'+code_device if len(code_device) < 6 else code_device + + oath = pytest.importorskip("oath") + lib_at = lambda : oath.totp(secret, period=period) + print (lib_at()) + assert lib_at() == code_device -- cgit v1.2.1 From f4b1f29058f55a716cb6e4e8a4f9bf0e6c7332fe Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Sat, 26 Nov 2016 15:42:48 +0100 Subject: Add missing newlines to make code format consistent Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 89a6ccf..5b39c34 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -4,6 +4,7 @@ from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET from misc import ffi, gs, wait, cast_pointer_to_tuple from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage + def test_enable_password_safe(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe('wrong_password') == DeviceErrorCode.WRONG_PASSWORD @@ -252,6 +253,7 @@ def test_HOTP_token(C): assert hotp_code != 0 assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + def test_HOTP_counters(C): """ # https://tools.ietf.org/html/rfc4226#page-32 @@ -374,6 +376,7 @@ def test_TOTP_RFC_usepin(C, PIN_protection): correct += expected_code == code_from_device assert data == responses or correct == len(test_data) + def test_get_slot_names(C): C.NK_set_debug(True) assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK @@ -502,6 +505,7 @@ def test_get_serial_number(C): assert len(sn) > 0 print(('Serial number of the device: ', sn)) + @pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) def test_OTP_secret_started_from_null(C, secret): ''' @@ -577,6 +581,7 @@ def test_TOTP_slots_read_write_at_time_period(C, time, period): lib_res += (time, lib_at(time)) assert dev_res == lib_res + @pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) def test_TOTP_secrets(C, secret): ''' @@ -606,6 +611,7 @@ def test_TOTP_secrets(C, secret): lib_res += (time, lib_at(time)) assert dev_res == lib_res + @pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) def test_HOTP_secrets(C, secret): ''' @@ -653,6 +659,7 @@ def test_special_double_press(C): DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK # requires manual check + def test_edit_OTP_slot(C): """ should change slots counter and name without changing its secret (using null secret for second update) -- cgit v1.2.1 From 8e1499871dda0559b0d7164e23d9e146f10409ec Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 11:10:35 +0100 Subject: Apply firmware versions limits to tests Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 5b39c34..7f567c7 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -1,5 +1,6 @@ import pytest +from conftest import skip_if_device_version_lower_than from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET from misc import ffi, gs, wait, cast_pointer_to_tuple from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage @@ -511,6 +512,8 @@ def test_OTP_secret_started_from_null(C, secret): ''' NK Pro 0.8+, NK Storage 0.43+ ''' + skip_if_device_version_lower_than({'S': 43, 'P': 8}) + oath = pytest.importorskip("oath") lib_at = lambda t: oath.hotp(secret, t, format='dec6') PIN_protection = False @@ -532,8 +535,18 @@ def test_OTP_secret_started_from_null(C, secret): assert dev_res == lib_res -@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff, 0xffffffff, 0xffffffffffffffff] ) +@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff, + 0xffffffff, + 0xffffffffffffffff] ) def test_HOTP_slots_read_write_counter(C, counter): + """ + Write different counters to all HOTP slots, read code and compare with 3rd party + :param counter: + """ + if counter >= 1e7: + # Storage does not handle counters longer than 7 digits + skip_if_device_version_lower_than({'P': 7}) + secret = RFC_SECRET oath = pytest.importorskip("oath") lib_at = lambda t: oath.hotp(secret, t, format='dec6') @@ -587,6 +600,8 @@ def test_TOTP_secrets(C, secret): ''' NK Pro 0.8+, NK Storage 0.44+ ''' + 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 ") slot_number = 0 @@ -617,6 +632,8 @@ def test_HOTP_secrets(C, secret): ''' NK Pro 0.8+, NK Storage 0.44+ ''' + 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 ") slot_number = 0 -- cgit v1.2.1 From 7c432494269144fa9777266834fd5b88b4fe1b90 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 11:12:24 +0100 Subject: Add NK Storage specific reply on running not initialized Password Safe Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 7f567c7..6b47c9f 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -81,7 +81,9 @@ def test_enable_password_safe_after_factory_reset(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK wait(10) - assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_AES_DEC_FAILED + enable_password_safe_result = C.NK_enable_password_safe(DefaultPasswords.USER) + assert enable_password_safe_result == DeviceErrorCode.STATUS_AES_DEC_FAILED \ + or is_storage(C) and enable_password_safe_result == DeviceErrorCode.WRONG_PASSWORD assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK -- cgit v1.2.1 From b78c28cb133bd00024416d8ad69740040c91d589 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 11:13:20 +0100 Subject: Enable factory reset test for Nitrokey Storage. Comments. Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 6b47c9f..3282436 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -476,8 +476,6 @@ def test_read_write_config(C): def test_factory_reset(C): - if is_storage(C): - pytest.skip('Recovery not implemented for NK Storage') C.NK_set_debug(True) assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK @@ -494,6 +492,8 @@ def test_factory_reset(C): assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + if is_storage(C): + C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) def test_get_status(C): @@ -573,6 +573,10 @@ def test_HOTP_slots_read_write_counter(C, counter): @pytest.mark.parametrize("period", [30,60] ) @pytest.mark.parametrize("time", range(21,70,20) ) def test_TOTP_slots_read_write_at_time_period(C, time, period): + """ + Write to all TOTP slots with specified period, read code at specified time + and compare with 3rd party + """ secret = RFC_SECRET oath = pytest.importorskip("oath") lib_at = lambda t: oath.totp(RFC_SECRET, t=t, period=period) -- cgit v1.2.1 From 87eaf78c7c7290764ccaebe67726b77a44f21240 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 12:44:33 +0100 Subject: Remove old skipping code. Feature comment. Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 3282436..ab30e04 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -635,13 +635,12 @@ 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+ - ''' + feature needed: support for 320bit secrets + """ 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 ") slot_number = 0 counter = 0 oath = pytest.importorskip("oath") -- cgit v1.2.1 From 1d493a5daba996e31615154b28688de3637529c7 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 13:46:54 +0100 Subject: Test null started OTP secrets also for 320bit case Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index ab30e04..d2ed48b 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -509,12 +509,16 @@ def test_get_serial_number(C): print(('Serial number of the device: ', sn)) -@pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) +@pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', + '00'*29+'ff', '00'*39+'ff', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) def test_OTP_secret_started_from_null(C, secret): - ''' + """ NK Pro 0.8+, NK Storage 0.43+ - ''' + """ 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}) oath = pytest.importorskip("oath") lib_at = lambda t: oath.hotp(secret, t, format='dec6') -- cgit v1.2.1 From e414840ab19ce022d5354fad13bcbcbe41925eea Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Fri, 9 Dec 2016 13:49:33 +0100 Subject: Add a note regarding Password Safe tests Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index d2ed48b..2a4a1a7 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -7,6 +7,9 @@ from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage def test_enable_password_safe(C): + """ + All Password Safe tests depend on AES keys being initialized. They will fail otherwise. + """ assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe('wrong_password') == DeviceErrorCode.WRONG_PASSWORD assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK -- cgit v1.2.1 From 925d75007161aa845e8c29ac412ac875cf45f337 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Mon, 12 Dec 2016 15:10:09 +0100 Subject: Tests: clear new SD card warning on factory reset Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 2a4a1a7..a6f7094 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -84,6 +84,8 @@ def test_enable_password_safe_after_factory_reset(C): assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK wait(10) + if is_storage(C): + assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK enable_password_safe_result = C.NK_enable_password_safe(DefaultPasswords.USER) assert enable_password_safe_result == DeviceErrorCode.STATUS_AES_DEC_FAILED \ or is_storage(C) and enable_password_safe_result == DeviceErrorCode.WRONG_PASSWORD @@ -496,7 +498,7 @@ def test_factory_reset(C): assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK if is_storage(C): - C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) + assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK def test_get_status(C): -- cgit v1.2.1 From 5e02e1e198c1c4051f15c45dfeb67b9be2cd5aa1 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Mon, 12 Dec 2016 15:10:55 +0100 Subject: Tests: skip edit OTP slot test for NK Storage 0.44 Signed-off-by: Szczepan Zalega --- unittest/test_pro.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'unittest/test_pro.py') diff --git a/unittest/test_pro.py b/unittest/test_pro.py index a6f7094..4a2a504 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -695,6 +695,9 @@ 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 + skip_if_device_version_lower_than({'S': 44, 'P': 7}) + secret = RFC_SECRET counter = 0 PIN_protection = False -- cgit v1.2.1