aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzczepan Zalega <szczepan@nitrokey.com>2019-06-22 17:31:45 +0200
committerSzczepan Zalega <szczepan@nitrokey.com>2019-06-22 17:31:45 +0200
commit3ede630625cdc83cde2753897bee260595a5137a (patch)
tree578e349f9e5b44acabf106e3f8f8f2073a80ad02
parent3fc4193776b4ea29354838df024a72d7c8349ea9 (diff)
parent1fed3fd903da061a58d846f92161b60b711d8df5 (diff)
downloadlibnitrokey-3ede630625cdc83cde2753897bee260595a5137a.tar.gz
libnitrokey-3ede630625cdc83cde2753897bee260595a5137a.tar.bz2
Merge branch 'otp_tests'
Add OTP tests: - complete writing and reading codes - test edge slots of TOTP and HOTP
-rw-r--r--unittest/constants.py3
-rw-r--r--unittest/test_pro.py91
2 files changed, 92 insertions, 2 deletions
diff --git a/unittest/constants.py b/unittest/constants.py
index 714c8c6..645ef6a 100644
--- a/unittest/constants.py
+++ b/unittest/constants.py
@@ -57,3 +57,6 @@ class LibraryErrors:
INVALID_HEX_STRING = 202
TARGET_BUFFER_SIZE_SMALLER_THAN_SOURCE = 203
+
+HOTP_slot_count = 3
+TOTP_slot_count = 15 \ No newline at end of file
diff --git a/unittest/test_pro.py b/unittest/test_pro.py
index b8ae290..29eabff 100644
--- a/unittest/test_pro.py
+++ b/unittest/test_pro.py
@@ -22,9 +22,10 @@ SPDX-License-Identifier: LGPL-3.0
import pytest
from conftest import skip_if_device_version_lower_than
-from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, bb, bbRFC_SECRET, LibraryErrors
+from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, bb, bbRFC_SECRET, LibraryErrors, HOTP_slot_count, \
+ TOTP_slot_count
from misc import ffi, gs, wait, cast_pointer_to_tuple, has_binary_counter
-from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage
+from misc import is_storage
@pytest.mark.lock_device
@pytest.mark.PWS
@@ -431,6 +432,10 @@ def test_HOTP_64bit_counter(C):
lib_res += (t, lib_at(t))
assert dev_res == lib_res
+def helper_set_HOTP_test_slot(C, slot_number):
+ assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
+ assert C.NK_write_hotp_slot(slot_number, b'python_test', bbRFC_SECRET, 0, False, False, True, b'', DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
+
def helper_set_TOTP_test_slot(C, slot_number):
PIN_protection = False
@@ -593,6 +598,20 @@ def test_get_code_user_authorize(C):
assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK
+def helper_get_TOTP_code(C,i):
+ code = gs(C.NK_get_totp_code(i, 0, 0, 30))
+ assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK
+ assert code != b''
+ return code
+
+
+def helper_get_HOTP_code(C,i):
+ code = gs(C.NK_get_hotp_code(i))
+ assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK
+ assert code != b''
+ return code
+
+
@pytest.mark.otp
def test_authorize_issue_admin(C):
skip_if_device_version_lower_than({'S': 43, 'P': 9})
@@ -1003,3 +1022,71 @@ def test_HOTP_counter_getter(C, counter_mid: int):
assert read_slot_st.slot_counter == counter
+def test_edge_OTP_slots(C):
+ # -> shows TOTP15 is not written
+ # -> assuming HOTP1 is written
+ # (optional) Write slot HOTP1
+ # Write slot TOTP15
+ # Wait
+ # Read slot TOTP15 details
+ # Read HOTP1 details
+ # returns SLOT_NOT_PROGRAMMED
+ # (next nkapp execution)
+ # -> shows HOTP1 is not written
+ # briefly writing TOTP15 clears HOTP1, and vice versa
+
+ read_slot_st = ffi.new('struct ReadSlot_t *')
+ if not read_slot_st:
+ raise Exception("Could not allocate status")
+ use_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, use_pin_protection, not use_pin_protection,
+ DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
+ counter = 0
+ HOTP_slot_number = 1 -1
+ TOTP_slot_number = 15 -1 # 0 based
+ assert C.NK_write_totp_slot(TOTP_slot_number, b'python_test', bbRFC_SECRET, 30, False, False, False, b'',
+ DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
+ assert C.NK_write_hotp_slot(HOTP_slot_number, b'python_test', bbRFC_SECRET, counter, use_8_digits, False, False, b'', DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
+ for i in range(5):
+ code_hotp = gs(C.NK_get_hotp_code(HOTP_slot_number))
+ assert code_hotp
+ assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK
+ assert C.NK_read_HOTP_slot(HOTP_slot_number, read_slot_st) == DeviceErrorCode.STATUS_OK
+ assert read_slot_st.slot_counter == (i+1)
+ helper_set_time_on_device(C, 1)
+ code_totp = gs((C.NK_get_totp_code(TOTP_slot_number, 0, 0, 30)))
+ assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK
+
+
+def test_OTP_all_rw(C):
+ """
+ Write all OTP slots and read codes from them two times.
+ All generated codes should be the same, which is checked as well.
+ """
+ for i in range(TOTP_slot_count):
+ helper_set_TOTP_test_slot(C, i)
+ for i in range(HOTP_slot_count):
+ helper_set_HOTP_test_slot(C, i)
+ all_codes = []
+ for i in range(5):
+ this_loop_codes = []
+ code_old = b''
+ helper_set_time_on_device(C, 30*i)
+ for i in range(TOTP_slot_count):
+ code = helper_get_TOTP_code(C, i)
+ if code_old:
+ assert code == code_old
+ code_old = code
+ this_loop_codes.append(('T', i, code))
+ code_old = b''
+ for i in range(HOTP_slot_count):
+ code = helper_get_HOTP_code(C, i)
+ if code_old:
+ assert code == code_old
+ code_old = code
+ this_loop_codes.append(('H', i, code))
+ all_codes.append(this_loop_codes)
+ from pprint import pprint
+ pprint(all_codes) \ No newline at end of file