diff options
| -rw-r--r-- | NK_C_API.cc | 90 | ||||
| -rw-r--r-- | NK_C_API.h | 17 | ||||
| -rw-r--r-- | NitrokeyManager.cc | 79 | ||||
| -rw-r--r-- | include/NitrokeyManager.h | 25 | ||||
| -rw-r--r-- | unittest/constants.py | 2 | ||||
| -rw-r--r-- | unittest/test_storage.py | 91 | 
6 files changed, 302 insertions, 2 deletions
| diff --git a/NK_C_API.cc b/NK_C_API.cc index 7110fca..fc6d3c5 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -375,5 +375,95 @@ extern int NK_login_auto() {      });  } +// storage commands + +extern int NK_send_startup(uint64_t seconds_from_epoch){ +  auto m = NitrokeyManager::instance(); +  return get_without_result([&](){ +      m->send_startup(seconds_from_epoch); +  }); +} + +extern int NK_unlock_encrypted_volume(const char* user_pin){ +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->unlock_encrypted_volume(user_pin); +    }); +} + +extern int NK_unlock_hidden_volume(const char* hidden_volume_password){ +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->unlock_hidden_volume(hidden_volume_password); +    }); +} + +extern int NK_create_hidden_volume(int slot_nr, int start_percent, int end_percent, +                                   const char* hidden_volume_password){ +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->create_hidden_volume( slot_nr,  start_percent,  end_percent, +        hidden_volume_password); +    }); +} + +extern int NK_set_unencrypted_read_only(const char* user_pin){ +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->set_unencrypted_read_only(user_pin); +    }); +} + +extern int NK_set_unencrypted_read_write(const char* user_pin){ +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->set_unencrypted_read_write(user_pin); +    }); +} + +extern int NK_export_firmware(const char* admin_pin) { +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->export_firmware(admin_pin) ; +    }); +} + +extern int NK_clear_new_sd_card_warning(const char* admin_pin) { +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->clear_new_sd_card_warning(admin_pin); +    }); +} + +extern int NK_fill_SD_card_with_random_data(const char* admin_pin) { +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->fill_SD_card_with_random_data(admin_pin); +    }); +} + +extern int NK_change_update_password(const char* current_update_password, +                                     const char* new_update_password) { +    auto m = NitrokeyManager::instance(); +    return get_without_result([&](){ +        m->change_update_password(current_update_password, new_update_password); +    }); +} + +extern const char* NK_get_status_storage() { +  auto m = NitrokeyManager::instance(); +  return get_with_string_result([&](){ +      return m->get_status_storage(); +  }); +} + +extern const char* NK_get_SD_usage_data() { +  auto m = NitrokeyManager::instance(); +  return get_with_string_result([&](){ +      return m->get_SD_usage_data(); +  }); +} + +  } @@ -324,6 +324,23 @@ extern int NK_erase_password_safe_slot(uint8_t slot_number);   */  extern int NK_is_AES_supported(const char *user_password); + +extern int NK_send_startup(uint64_t seconds_from_epoch); +extern int NK_unlock_encrypted_volume(const char* user_pin); +extern int NK_unlock_hidden_volume(const char* hidden_volume_password); +extern int NK_create_hidden_volume(int slot_nr, int start_percent, int end_percent, +                                   const char* hidden_volume_password); +extern int NK_set_unencrypted_read_only(const char* user_pin); +extern int NK_set_unencrypted_read_write(const char* user_pin); +extern int NK_export_firmware(const char* admin_pin) ; +extern int NK_clear_new_sd_card_warning(const char* admin_pin) ; +extern int NK_fill_SD_card_with_random_data(const char* admin_pin) ; +extern int NK_change_update_password(const char* current_update_password, +                                     const char* new_update_password); +extern const char* NK_get_status_storage(); +extern const char* NK_get_SD_usage_data(); + +  } diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index 606c4fb..49b34c4 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -3,6 +3,7 @@  #include "include/NitrokeyManager.h"  #include "include/LibraryException.h"  #include <algorithm> +#include "include/misc.h"  namespace nitrokey{ @@ -486,4 +487,80 @@ namespace nitrokey{          return true;      } -} +    //storage commands + +    /** +     * TODO rename to set_time ? +     * TODO check what exactly this one is doing +     * @param seconds_from_epoch +     */ +    void NitrokeyManager::send_startup(uint64_t seconds_from_epoch){ +      auto p = get_payload<stick20::SendStartup>(); +//      p.set_defaults(); +      p.localtime = seconds_from_epoch; +      //auto device_status = +      stick20::SendStartup::CommandTransaction::run(*device, p); +    } + +    void NitrokeyManager::unlock_encrypted_volume(const char* user_pin){ +      misc::execute_password_command<stick20::EnableEncryptedPartition>(*device, user_pin); +    } + +    void NitrokeyManager::unlock_hidden_volume(const char* hidden_volume_password) { +      misc::execute_password_command<stick20::EnableHiddenEncryptedPartition>(*device, hidden_volume_password); +    } + +    //TODO check is encrypted volume unlocked before execution +    //if not return library exception +    void NitrokeyManager::create_hidden_volume(int slot_nr, int start_percent, int end_percent, +                                               const char* hidden_volume_password) { +      auto p = get_payload<stick20::SetupHiddenVolume>(); +      p.SlotNr_u8 = slot_nr; +      p.StartBlockPercent_u8 = start_percent; +      p.EndBlockPercent_u8 = end_percent; +      strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password); +      stick20::SetupHiddenVolume::CommandTransaction::run(*device, p); +    } + +    void NitrokeyManager::set_unencrypted_read_only(const char* user_pin) { +      misc::execute_password_command<stick20::SendSetReadonlyToUncryptedVolume>(*device, user_pin); +    } + +    void NitrokeyManager::set_unencrypted_read_write(const char* user_pin) { +      misc::execute_password_command<stick20::SendSetReadwriteToUncryptedVolume>(*device, user_pin); +    } + +    void NitrokeyManager::export_firmware(const char* admin_pin) { +      misc::execute_password_command<stick20::ExportFirmware>(*device, admin_pin); +    } + +    void NitrokeyManager::clear_new_sd_card_warning(const char* admin_pin) { +      misc::execute_password_command<stick20::SendClearNewSdCardFound>(*device, admin_pin); +    } + +    void NitrokeyManager::fill_SD_card_with_random_data(const char* admin_pin) { +      auto p = get_payload<stick20::FillSDCardWithRandomChars>(); +      p.set_defaults(); +      strcpyT(p.admin_pin, admin_pin); +      stick20::FillSDCardWithRandomChars::CommandTransaction::run(*device, p); +    } + +    void NitrokeyManager::change_update_password(const char* current_update_password, const char* new_update_password) { +      auto p = get_payload<stick20::ChangeUpdatePassword>(); +      strcpyT(p.current_update_password, current_update_password); +      strcpyT(p.new_update_password, new_update_password); +      stick20::ChangeUpdatePassword::CommandTransaction::run(*device, p); +    } + +    const char * NitrokeyManager::get_status_storage(){ +      auto p = stick20::GetDeviceStatus::CommandTransaction::run(*device); +      return strdup(p.data().dissect().c_str()); +    } + +    const char * NitrokeyManager::get_SD_usage_data(){ +      auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(*device); +      return strdup(p.data().dissect().c_str()); +    } + + +    } diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h index 52c18d7..7a3ffcc 100644 --- a/include/NitrokeyManager.h +++ b/include/NitrokeyManager.h @@ -82,6 +82,30 @@ namespace nitrokey {          bool is_AES_supported(const char *user_password); +        void unlock_encrypted_volume(const char *user_password); + +        void unlock_hidden_volume(const char *hidden_volume_password); + +        void set_unencrypted_read_only(const char *user_pin); + +        void set_unencrypted_read_write(const char *user_pin); + +        void export_firmware(const char *admin_pin); + +        void clear_new_sd_card_warning(const char *admin_pin); + +        void fill_SD_card_with_random_data(const char *admin_pin); + +        void change_update_password(const char *current_update_password, const char *new_update_password); + +        void create_hidden_volume(int slot_nr, int start_percent, int end_percent, const char *hidden_volume_password); + +        void send_startup(uint64_t seconds_from_epoch); + +        const char * get_status_storage(); + +        const char *get_SD_usage_data(); +          ~NitrokeyManager();      private:          NitrokeyManager(); @@ -101,7 +125,6 @@ namespace nitrokey {          template <typename ProCommand, PasswordKind StoKind>          void change_PIN_general(char *current_PIN, char *new_PIN); -      };  } diff --git a/unittest/constants.py b/unittest/constants.py index e3caae3..258619e 100644 --- a/unittest/constants.py +++ b/unittest/constants.py @@ -12,6 +12,8 @@ class DefaultPasswords(Enum):      USER = '123456'      ADMIN_TEMP = '123123123'      USER_TEMP = '234234234' +    UPDATE = '12345678' +    UPDATE_TEMP = '123update123'  class DeviceErrorCode(Enum): diff --git a/unittest/test_storage.py b/unittest/test_storage.py index d6cc558..b02b1eb 100644 --- a/unittest/test_storage.py +++ b/unittest/test_storage.py @@ -3,5 +3,96 @@ import pytest  from misc import ffi, gs, wait, cast_pointer_to_tuple  from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, LibraryErrors +import pprint +pprint = pprint.PrettyPrinter(indent=4).pprint +def get_dict_from_dissect(status): +    x = [] +    for s in status.split('\n'): +        try: +            if not ':' in s: continue +            ss = s.replace('\t', '').replace(' (int) ', '').split(':') +            if not len(ss) == 2: continue +            x.append(ss) +        except: +            pass +    d = {k.strip(): v.strip() for k, v in x} +    return d + + +def test_get_status_storage(C): +    status_pointer = C.NK_get_status_storage() +    status_string = gs(status_pointer) +    status_dict = get_dict_from_dissect(status_string) +    default_admin_password_retry_count = 3 +    assert int(status_dict['AdminPwRetryCount']) == default_admin_password_retry_count + + +def test_sd_card_usage(C): +    data_pointer = C.NK_get_SD_usage_data() +    data_string = gs(data_pointer) +    assert len(data_string) > 0 +    data_dict = get_dict_from_dissect(data_string) +    assert int(data_dict['WriteLevelMax']) <= 100 + + +def test_encrypted_volume_unlock(C): +    assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK +    assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +def test_encrypted_volume_unlock_hidden(C): +    hidden_volume_password = 'hiddenpassword' +    assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK +    assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK +    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 + + +def test_encrypted_volume_setup_multiple_hidden(C): +    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(4): +        assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i) ) == DeviceErrorCode.STATUS_OK +    for i in range(4): +        assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK +        assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK +        assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + + +def test_unencrypted_volume_set_read_only(C): +    assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK +    assert C.NK_set_unencrypted_read_only(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +def test_unencrypted_volume_set_read_write(C): +    assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK +    assert C.NK_set_unencrypted_read_write(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +def test_export_firmware(C): +    assert C.NK_export_firmware(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +def test_clear_new_sd_card_notification(C): +    assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.skip +def test_fill_SD_card(C): +    assert C.NK_fill_SD_card_with_random_data(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +def test_change_update_password(C): +    wrong_password = 'aaaaaaaaaaa' +    assert C.NK_change_update_password(wrong_password, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.WRONG_PASSWORD +    assert C.NK_change_update_password(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.STATUS_OK +    assert C.NK_change_update_password(DefaultPasswords.UPDATE_TEMP, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + + +def test_send_startup(C): +    time_seconds_from_epoch = 0 # FIXME set proper date +    assert C.NK_send_startup(time_seconds_from_epoch) == DeviceErrorCode.STATUS_OK | 
