1"""
2Copyright (c) 2015-2018 Nitrokey UG
3
4This file is part of libnitrokey.
5
6libnitrokey is free software: you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9any later version.
10
11libnitrokey is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License
17along with libnitrokey. If not, see <http://www.gnu.org/licenses/>.
18
19SPDX-License-Identifier: LGPL-3.0
20"""
21
22import pytest
23
24from misc import ffi, gs, to_hex, is_pro_rtm_07, is_long_OTP_secret_handled
25from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, LibraryErrors, bbRFC_SECRET
26
27
28def test_too_long_strings(C):
29    new_password = b'123123123'
30    long_string = b'a' * 100
31    assert C.NK_change_user_PIN(long_string, new_password) == LibraryErrors.TOO_LONG_STRING
32    assert C.NK_change_user_PIN(new_password, long_string) == LibraryErrors.TOO_LONG_STRING
33    assert C.NK_change_admin_PIN(long_string, new_password) == LibraryErrors.TOO_LONG_STRING
34    assert C.NK_change_admin_PIN(new_password, long_string) == LibraryErrors.TOO_LONG_STRING
35    assert C.NK_first_authenticate(long_string, DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TOO_LONG_STRING
36    assert C.NK_erase_totp_slot(0, long_string) == LibraryErrors.TOO_LONG_STRING
37    digits = False
38    assert C.NK_write_hotp_slot(1, long_string, bbRFC_SECRET, 0, digits, False, False, b"",
39                                DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TOO_LONG_STRING
40    assert C.NK_write_hotp_slot(1, b'long_test', bbRFC_SECRET, 0, digits, False, False, b"",
41                                long_string) == LibraryErrors.TOO_LONG_STRING
42    assert gs(C.NK_get_hotp_code_PIN(0, long_string)) == b""
43    assert C.NK_get_last_command_status() == LibraryErrors.TOO_LONG_STRING
44    assert C.NK_change_firmware_password_pro(long_string, long_string) == LibraryErrors.TOO_LONG_STRING
45    assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, long_string) == LibraryErrors.TOO_LONG_STRING
46
47
48def test_invalid_slot(C):
49    invalid_slot = 255
50    assert C.NK_erase_totp_slot(invalid_slot, b'some password') == LibraryErrors.INVALID_SLOT
51    assert C.NK_write_hotp_slot(invalid_slot, b'long_test', bbRFC_SECRET, 0, False, False, False, b"",
52                                b'aaa') == LibraryErrors.INVALID_SLOT
53    assert gs(C.NK_get_hotp_code_PIN(invalid_slot, b'some password')) == b""
54    assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT
55    assert C.NK_erase_password_safe_slot(invalid_slot) == LibraryErrors.INVALID_SLOT
56    assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK
57    assert gs(C.NK_get_password_safe_slot_name(invalid_slot)) == b''
58    assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT
59    assert gs(C.NK_get_password_safe_slot_login(invalid_slot)) == b''
60    assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT
61
62
63@pytest.mark.parametrize("invalid_hex_string",
64                         ['text', '00  ', '0xff', 'zzzzzzzzzzzz', 'fff', 'f' * 257, 'f' * 258])
65def test_invalid_secret_hex_string_for_OTP_write(C, invalid_hex_string):
66    """
67    Tests for invalid secret hex string during writing to OTP slot. Invalid strings are not hexadecimal number,
68    empty or longer than 255 characters.
69    """
70    invalid_hex_string = invalid_hex_string.encode('ascii')
71    assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
72    assert C.NK_write_hotp_slot(1, b'slot_name', invalid_hex_string, 0, True, False, False, b'',
73                                DefaultPasswords.ADMIN_TEMP) == LibraryErrors.INVALID_HEX_STRING
74    assert C.NK_write_totp_slot(1, b'python_test', invalid_hex_string, 30, True, False, False, b"",
75                                DefaultPasswords.ADMIN_TEMP) == LibraryErrors.INVALID_HEX_STRING
76
77def test_warning_binary_bigger_than_secret_buffer(C):
78    invalid_hex_string = to_hex('1234567890') * 3
79    invalid_hex_string = invalid_hex_string.encode('ascii')
80    if is_long_OTP_secret_handled(C):
81        invalid_hex_string *= 2
82    assert C.NK_write_hotp_slot(1, b'slot_name', invalid_hex_string, 0, True, False, False, b'',
83                                DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TARGET_BUFFER_SIZE_SMALLER_THAN_SOURCE
84
85
86@pytest.mark.skip(reason='Experimental')
87def test_clear(C):
88    d = 'asdasdasd'
89    print(d)
90    C.clear_password(d)
91    print(d)