aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzczepan Zalega <szczepan@nitrokey.com>2016-11-02 21:52:40 +0100
committerSzczepan Zalega <szczepan@nitrokey.com>2016-11-26 18:56:28 +0100
commit7d943d3e8717ba47af4b53787cc4c29ad6ee2f90 (patch)
tree40b42184ef943539c472459e6f8533c600cb3808
parent0a15620115f4f6d56ec99777e1996497d7175bc2 (diff)
downloadlibnitrokey-7d943d3e8717ba47af4b53787cc4c29ad6ee2f90.tar.gz
libnitrokey-7d943d3e8717ba47af4b53787cc4c29ad6ee2f90.tar.bz2
Python bindings and tests for most of Storage functionality
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
-rw-r--r--NK_C_API.cc90
-rw-r--r--NK_C_API.h17
-rw-r--r--NitrokeyManager.cc79
-rw-r--r--include/NitrokeyManager.h25
-rw-r--r--unittest/constants.py2
-rw-r--r--unittest/test_storage.py91
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();
+ });
+}
+
+
}
diff --git a/NK_C_API.h b/NK_C_API.h
index 728824d..e5b414c 100644
--- a/NK_C_API.h
+++ b/NK_C_API.h
@@ -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