diff options
| -rw-r--r-- | CHANGELOG.md | 24 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | build.rs | 34 | ||||
| -rw-r--r-- | libnitrokey-v3.4/DeviceCommunicationExceptions.cpp (renamed from libnitrokey-v3.3/DeviceCommunicationExceptions.cpp) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/LICENSE (renamed from libnitrokey-v3.3/LICENSE) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/NK_C_API.cc (renamed from libnitrokey-v3.3/NK_C_API.cc) | 199 | ||||
| -rw-r--r-- | libnitrokey-v3.4/NK_C_API.h (renamed from libnitrokey-v3.3/NK_C_API.h) | 268 | ||||
| -rw-r--r-- | libnitrokey-v3.4/NitrokeyManager.cc (renamed from libnitrokey-v3.3/NitrokeyManager.cc) | 34 | ||||
| -rw-r--r-- | libnitrokey-v3.4/README.md (renamed from libnitrokey-v3.3/README.md) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/command_id.cc (renamed from libnitrokey-v3.3/command_id.cc) | 4 | ||||
| -rw-r--r-- | libnitrokey-v3.4/device.cc (renamed from libnitrokey-v3.3/device.cc) | 6 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/CommandFailedException.h (renamed from libnitrokey-v3.3/libnitrokey/CommandFailedException.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/DeviceCommunicationExceptions.h (renamed from libnitrokey-v3.3/libnitrokey/DeviceCommunicationExceptions.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/LibraryException.h (renamed from libnitrokey-v3.3/libnitrokey/LibraryException.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/LongOperationInProgressException.h (renamed from libnitrokey-v3.3/libnitrokey/LongOperationInProgressException.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/NitrokeyManager.h (renamed from libnitrokey-v3.3/libnitrokey/NitrokeyManager.h) | 35 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/command.h (renamed from libnitrokey-v3.3/libnitrokey/command.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/command_id.h (renamed from libnitrokey-v3.3/libnitrokey/command_id.h) | 2 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/cxx_semantics.h (renamed from libnitrokey-v3.3/libnitrokey/cxx_semantics.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/deprecated.h | 35 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/device.h (renamed from libnitrokey-v3.3/libnitrokey/device.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/device_proto.h (renamed from libnitrokey-v3.3/libnitrokey/device_proto.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/dissect.h (renamed from libnitrokey-v3.3/libnitrokey/dissect.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/hidapi/hidapi.h (renamed from libnitrokey-v3.3/libnitrokey/hidapi/hidapi.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/log.h (renamed from libnitrokey-v3.3/libnitrokey/log.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/misc.h (renamed from libnitrokey-v3.3/libnitrokey/misc.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/stick10_commands.h (renamed from libnitrokey-v3.3/libnitrokey/stick10_commands.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/stick10_commands_0.8.h (renamed from libnitrokey-v3.3/libnitrokey/stick10_commands_0.8.h) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/stick20_commands.h (renamed from libnitrokey-v3.3/libnitrokey/stick20_commands.h) | 6 | ||||
| -rw-r--r-- | libnitrokey-v3.4/libnitrokey/version.h | 33 | ||||
| -rw-r--r-- | libnitrokey-v3.4/log.cc (renamed from libnitrokey-v3.3/log.cc) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/misc.cc (renamed from libnitrokey-v3.3/misc.cc) | 0 | ||||
| -rw-r--r-- | libnitrokey-v3.4/version.cc.in | 37 | ||||
| -rw-r--r-- | src/ffi.rs | 607 | 
35 files changed, 1149 insertions, 179 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a6f6fc..113b342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +# v3.4.0 (2018-12-10) + +- Update to libnitrokey 3.4, causing all following changes. +- New constant `NK_device_model_NK_DISCONNECTED` in the `NK_device_model` +  enumeration. +- New structures: +    - `NK_storage_ProductionTest` +    - `NK_storage_status` +- New functions: +    - `NK_get_device_model` +    - `NK_get_library_version` +    - `NK_get_major_library_version` +    - `NK_get_minor_libray_version` +    - `NK_get_status_storage` +    - `NK_get_storage_production_info` +    - `NK_totp_set_time_soft` +    - `NK_wink` +- The function `NK_totp_get_time` is now deprecated.  If applicable, +  `NK_totp_set_time_soft` should be used instead.  See the [upstream pull +  request #114][] for details. +- Strings are now returned as mutable instead of constant pointers. +  # v3.3.0 (2018-05-21)  - Change the crate license to LGPL 3.0. @@ -10,3 +32,5 @@  # v0.1.0 (2018-05-19)  - Initial release. + +[upstream pull request #114]: https://github.com/Nitrokey/libnitrokey/pull/114 @@ -1,6 +1,6 @@  [package]  name = "nitrokey-sys" -version = "3.3.0" +version = "3.4.0"  authors = ["Robin Krahl <robin.krahl@ireas.org>"]  homepage = "https://code.ireas.org/nitrokey-rs/"  repository = "https://git.ireas.org/nitrokey-sys-rs/" @@ -5,7 +5,7 @@ devices.  ```toml  [dependencies] -nitrokey-sys = "3.3.0" +nitrokey-sys = "3.4.0"  ```  The version of this crate corresponds to the wrapped `libnitrokey` version. @@ -1,6 +1,9 @@  extern crate cc;  use std::env; +use std::io; +use std::io::{Read, Write}; +use std::fs;  use std::path;  struct Version { @@ -41,7 +44,34 @@ fn get_version() -> Result<Version, String> {      })  } +fn prepare_version_source( +    version: &Version, +    out_path: &path::Path, +    library_path: &path::Path +) -> io::Result<path::PathBuf> { +    let out = out_path.join("version.cc"); +    let template = library_path.join("version.cc.in"); + +    let mut file = fs::File::open(template)?; +    let mut data = String::new(); +    file.read_to_string(&mut data)?; +    drop(file); + +    let data = data +        .replace("@PROJECT_VERSION_MAJOR@", &version.major) +        .replace("@PROJECT_VERSION_MINOR@", &version.minor) +        .replace("@PROJECT_VERSION_GIT@", &version.git); + +    let mut file = fs::File::create(&out)?; +    file.write_all(data.as_bytes())?; + +    Ok(out) +} +  fn main() { +    let out_dir = env::var("OUT_DIR").expect("Environment variable OUT_DIR is not set"); +    let out_path = path::PathBuf::from(out_dir); +      let version = get_version().expect("Could not extract library version");      let sources = [ @@ -56,10 +86,14 @@ fn main() {      let library_dir = format!("libnitrokey-{}", version.git);      let library_path = path::Path::new(&library_dir); +    let version_source = prepare_version_source(&version, &out_path, &library_path) +        .expect("Could not prepare the version source file"); +      cc::Build::new()          .cpp(true)          .include(library_path.join("libnitrokey"))          .files(sources.iter().map(|s| library_path.join(s))) +        .file(version_source)          .compile("libnitrokey.a");      println!("cargo:rustc-link-lib=hidapi-libusb"); diff --git a/libnitrokey-v3.3/DeviceCommunicationExceptions.cpp b/libnitrokey-v3.4/DeviceCommunicationExceptions.cpp index 4d62aad..4d62aad 100644 --- a/libnitrokey-v3.3/DeviceCommunicationExceptions.cpp +++ b/libnitrokey-v3.4/DeviceCommunicationExceptions.cpp diff --git a/libnitrokey-v3.3/LICENSE b/libnitrokey-v3.4/LICENSE index 341c30b..341c30b 100644 --- a/libnitrokey-v3.3/LICENSE +++ b/libnitrokey-v3.4/LICENSE diff --git a/libnitrokey-v3.3/NK_C_API.cc b/libnitrokey-v3.4/NK_C_API.cc index b245940..7d0a10e 100644 --- a/libnitrokey-v3.3/NK_C_API.cc +++ b/libnitrokey-v3.4/NK_C_API.cc @@ -21,10 +21,13 @@  #include "NK_C_API.h"  #include <iostream> +#include <tuple>  #include "libnitrokey/NitrokeyManager.h"  #include <cstring>  #include "libnitrokey/LibraryException.h"  #include "libnitrokey/cxx_semantics.h" +#include "libnitrokey/stick20_commands.h" +#include "version.h"  #ifdef _MSC_VER  #ifdef _WIN32 @@ -52,11 +55,11 @@ T* duplicate_vector_and_clear(std::vector<T> &v){      return d;  } -template <typename T> -uint8_t * get_with_array_result(T func){ +template <typename R, typename T> +std::tuple<int, R> get_with_status(T func, R fallback) {      NK_last_command_status = 0;      try { -        return func(); +        return std::make_tuple(0, func());      }      catch (CommandFailedException & commandFailedException){          NK_last_command_status = commandFailedException.last_command_status; @@ -67,43 +70,26 @@ uint8_t * get_with_array_result(T func){      catch (const DeviceCommunicationException &deviceException){        NK_last_command_status = 256-deviceException.getType();      } -    return nullptr; +    return std::make_tuple(NK_last_command_status, fallback);  }  template <typename T> -const char* get_with_string_result(T func){ -    NK_last_command_status = 0; -    try { -        return func(); -    } -    catch (CommandFailedException & commandFailedException){ -        NK_last_command_status = commandFailedException.last_command_status; -    } -    catch (LibraryException & libraryException){ -        NK_last_command_status = libraryException.exception_id(); -    } -    catch (const DeviceCommunicationException &deviceException){ -      NK_last_command_status = 256-deviceException.getType(); +uint8_t * get_with_array_result(T func){ +    return std::get<1>(get_with_status<uint8_t*>(func, nullptr)); +} + +template <typename T> +char* get_with_string_result(T func){ +    auto result = std::get<1>(get_with_status<char*>(func, nullptr)); +    if (result == nullptr) { +        return strndup("", MAXIMUM_STR_REPLY_LENGTH);      } -    return ""; +    return result;  }  template <typename T>  auto get_with_result(T func){ -    NK_last_command_status = 0; -    try { -        return func(); -    } -    catch (CommandFailedException & commandFailedException){ -        NK_last_command_status = commandFailedException.last_command_status; -    } -    catch (LibraryException & libraryException){ -        NK_last_command_status = libraryException.exception_id(); -    } -    catch (const DeviceCommunicationException &deviceException){ -      NK_last_command_status = 256-deviceException.getType(); -    } -    return static_cast<decltype(func())>(0); +    return std::get<1>(get_with_status(func, static_cast<decltype(func())>(0)));  }  template <typename T> @@ -170,6 +156,7 @@ extern "C" {                      case NK_STORAGE:                          model_string = "S";                          break; +                    case NK_DISCONNECTED:                      default:                          /* no such enum value -- return error code */                          return 0; @@ -238,22 +225,41 @@ extern "C" {  	} +	NK_C_API enum NK_device_model NK_get_device_model() { +		auto m = NitrokeyManager::instance(); +		try { +			auto model = m->get_connected_device_model(); +			switch (model) { +				case DeviceModel::PRO: +				    return NK_PRO; +				case DeviceModel::STORAGE: +				    return NK_STORAGE; +				default: +				    /* unknown or not connected device */ +				    return NK_device_model::NK_DISCONNECTED; +			} +		} catch (const DeviceNotConnected& e) { +			return NK_device_model::NK_DISCONNECTED; +		} +} + +  	void clear_string(std::string &s) {  		std::fill(s.begin(), s.end(), ' ');  	} -	NK_C_API const char * NK_status() { +	NK_C_API char * NK_status() {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			string && s = m->get_status_as_string(); -			char * rs = strndup(s.c_str(), max_string_field_length); +			char * rs = strndup(s.c_str(), MAXIMUM_STR_REPLY_LENGTH);  			clear_string(s);  			return rs;  		});  	} -	NK_C_API const char * NK_device_serial_number() { +	NK_C_API char * NK_device_serial_number() {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			string && s = m->get_serial_number(); @@ -263,11 +269,11 @@ extern "C" {  		});  	} -	NK_C_API const char * NK_get_hotp_code(uint8_t slot_number) { +	NK_C_API char * NK_get_hotp_code(uint8_t slot_number) {  		return NK_get_hotp_code_PIN(slot_number, "");  	} -	NK_C_API const char * NK_get_hotp_code_PIN(uint8_t slot_number, const char *user_temporary_password) { +	NK_C_API char * NK_get_hotp_code_PIN(uint8_t slot_number, const char *user_temporary_password) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			string && s = m->get_HOTP_code(slot_number, user_temporary_password); @@ -277,12 +283,12 @@ extern "C" {  		});  	} -	NK_C_API const char * NK_get_totp_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, +	NK_C_API char * NK_get_totp_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time,  		uint8_t last_interval) {  		return NK_get_totp_code_PIN(slot_number, challenge, last_totp_time, last_interval, "");  	} -	NK_C_API const char * NK_get_totp_code_PIN(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, +	NK_C_API char * NK_get_totp_code_PIN(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time,  		uint8_t last_interval, const char *user_temporary_password) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() { @@ -327,14 +333,14 @@ extern "C" {  		});  	} -	NK_C_API const char* NK_get_totp_slot_name(uint8_t slot_number) { +	NK_C_API char* NK_get_totp_slot_name(uint8_t slot_number) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			const auto slot_name = m->get_totp_slot_name(slot_number);  			return slot_name;  		});  	} -	NK_C_API const char* NK_get_hotp_slot_name(uint8_t slot_number) { +	NK_C_API char* NK_get_hotp_slot_name(uint8_t slot_number) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			const auto slot_name = m->get_hotp_slot_name(slot_number); @@ -353,6 +359,18 @@ extern "C" {  		m->set_loglevel(level);  	} +	NK_C_API unsigned int NK_get_major_library_version() { +		return get_major_library_version(); +	} + +	NK_C_API unsigned int NK_get_minor_library_version() { +		return get_minor_library_version(); +	} + +	NK_C_API const char* NK_get_library_version() { +		return get_library_version(); +	} +  	NK_C_API int NK_totp_set_time(uint64_t time) {  		auto m = NitrokeyManager::instance();  		return get_without_result([&]() { @@ -360,11 +378,15 @@ extern "C" {  		});  	} -	NK_C_API int NK_totp_get_time() { +	NK_C_API int NK_totp_set_time_soft(uint64_t time) {  		auto m = NitrokeyManager::instance();  		return get_without_result([&]() { -			m->get_time(0); // FIXME check how that should work +			m->set_time_soft(time);  		}); +        } + +	NK_C_API int NK_totp_get_time() { +	  return 0;  	}  	NK_C_API int NK_change_admin_PIN(const char *current_PIN, const char *new_PIN) { @@ -417,20 +439,20 @@ extern "C" {  		});  	} -	NK_C_API const char *NK_get_password_safe_slot_name(uint8_t slot_number) { +	NK_C_API char *NK_get_password_safe_slot_name(uint8_t slot_number) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			return m->get_password_safe_slot_name(slot_number);  		});  	} -	NK_C_API const char *NK_get_password_safe_slot_login(uint8_t slot_number) { +	NK_C_API char *NK_get_password_safe_slot_login(uint8_t slot_number) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			return m->get_password_safe_slot_login(slot_number);  		});  	} -	NK_C_API const char *NK_get_password_safe_slot_password(uint8_t slot_number) { +	NK_C_API char *NK_get_password_safe_slot_password(uint8_t slot_number) {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			return m->get_password_safe_slot_password(slot_number); @@ -589,14 +611,84 @@ extern "C" {  		});  	} -	NK_C_API const char* NK_get_status_storage_as_string() { +	NK_C_API char* NK_get_status_storage_as_string() {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			return m->get_status_storage_as_string();  		});  	} -	NK_C_API const char* NK_get_SD_usage_data_as_string() { +	NK_C_API int NK_get_status_storage(NK_storage_status* out) { +		if (out == nullptr) { +			return -1; +		} +		auto m = NitrokeyManager::instance(); +		auto result = get_with_status([&]() { +			return m->get_status_storage(); +		}, proto::stick20::DeviceConfigurationResponsePacket::ResponsePayload()); +		auto error_code = std::get<0>(result); +		if (error_code != 0) { +			return error_code; +		} + +		auto status = std::get<1>(result); +		out->unencrypted_volume_read_only = status.ReadWriteFlagUncryptedVolume_u8 != 0; +		out->unencrypted_volume_active = status.VolumeActiceFlag_st.unencrypted; +		out->encrypted_volume_read_only = status.ReadWriteFlagCryptedVolume_u8 != 0; +		out->encrypted_volume_active = status.VolumeActiceFlag_st.encrypted; +		out->hidden_volume_read_only = status.ReadWriteFlagHiddenVolume_u8 != 0; +		out->hidden_volume_active = status.VolumeActiceFlag_st.hidden; +		out->firmware_version_major = status.versionInfo.major; +		out->firmware_version_minor = status.versionInfo.minor; +		out->firmware_locked = status.FirmwareLocked_u8 != 0; +		out->serial_number_sd_card = status.ActiveSD_CardID_u32; +		out->serial_number_smart_card = status.ActiveSmartCardID_u32; +		out->user_retry_count = status.UserPwRetryCount; +		out->admin_retry_count = status.AdminPwRetryCount; +		out->new_sd_card_found = status.NewSDCardFound_st.NewCard; +		out->filled_with_random = (status.SDFillWithRandomChars_u8 & 0x01) != 0; +		out->stick_initialized = status.StickKeysNotInitiated == 0; +		return 0; +	} + +  NK_C_API int NK_get_storage_production_info(NK_storage_ProductionTest * out){ +    if (out == nullptr) { +      return -1; +    } +    auto m = NitrokeyManager::instance(); +    auto result = get_with_status([&]() { +      return m->production_info(); +    }, proto::stick20::ProductionTest::ResponsePayload()); + +		auto error_code = std::get<0>(result); +		if (error_code != 0) { +			return error_code; +		} + +		stick20::ProductionTest::ResponsePayload status = std::get<1>(result); +		// Cannot use memcpy without declaring C API struct packed +    // (which is not parsed by Python's CFFI apparently), hence the manual way. +#define a(x) out->x = status.x; +		 a(FirmwareVersion_au8[0]); +		 a(FirmwareVersion_au8[1]); +		 a(FirmwareVersionInternal_u8); +		 a(SD_Card_Size_u8); +		 a(CPU_CardID_u32); +		 a(SmartCardID_u32); +		 a(SD_CardID_u32); +		 a(SC_UserPwRetryCount); +		 a(SC_AdminPwRetryCount); +		 a(SD_Card_ManufacturingYear_u8); +		 a(SD_Card_ManufacturingMonth_u8); +		 a(SD_Card_OEM_u16); +		 a(SD_WriteSpeed_u16); +		 a(SD_Card_Manufacturer_u8); +#undef a +		return 0; +  } + + +NK_C_API char* NK_get_SD_usage_data_as_string() {  		auto m = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			return m->get_SD_usage_data_as_string(); @@ -631,7 +723,7 @@ extern "C" {  		});  	} -	NK_C_API const char* NK_list_devices_by_cpuID() { +	NK_C_API char* NK_list_devices_by_cpuID() {  		auto nm = NitrokeyManager::instance();  		return get_with_string_result([&]() {  			auto v = nm->list_devices_by_cpuID(); @@ -640,7 +732,7 @@ extern "C" {  				res += a+";";  			}  			if (res.size()>0) res.pop_back(); // remove last delimiter char -			return strndup(res.c_str(), 8192); //this buffer size sets limit to over 200 devices ID's +			return strndup(res.c_str(), MAXIMUM_STR_REPLY_LENGTH);  		});  	} @@ -651,7 +743,12 @@ extern "C" {  		});  	} - +	NK_C_API int NK_wink() { +		auto m = NitrokeyManager::instance(); +		return get_without_result([&]() { +			return m->wink(); +		}); +	}  #ifdef __cplusplus  } diff --git a/libnitrokey-v3.3/NK_C_API.h b/libnitrokey-v3.4/NK_C_API.h index 96a1950..b1bdf1e 100644 --- a/libnitrokey-v3.3/NK_C_API.h +++ b/libnitrokey-v3.4/NK_C_API.h @@ -25,41 +25,160 @@  #include <stdbool.h>  #include <stdint.h> +#include "deprecated.h" +  #ifdef _MSC_VER  #define NK_C_API __declspec(dllexport)  #else -#define NK_C_API  +#define NK_C_API  #endif  #ifdef __cplusplus  extern "C" {  #endif +  static const int MAXIMUM_STR_REPLY_LENGTH = 8192; +          /**           * The Nitrokey device models supported by the API.           */          enum NK_device_model { +						/** +						 * Use, if no supported device is connected +						 */ +        		NK_DISCONNECTED = 0,              /**               * Nitrokey Pro.               */ -            NK_PRO, +            NK_PRO = 1,              /**               * Nitrokey Storage.               */ -            NK_STORAGE +            NK_STORAGE = 2          };  	/** -	 * Set debug level of messages written on stderr -	 * @param state state=True - most messages, state=False - only errors level -	 */ +	 * Stores the status of a Storage device. +	 */ +        struct NK_storage_status { +		/** +		 * Indicates whether the unencrypted volume is read-only. +		 */ +		bool unencrypted_volume_read_only; +		/** +		 * Indicates whether the unencrypted volume is active. +		 */ +		bool unencrypted_volume_active; +		/** +		 * Indicates whether the encrypted volume is read-only. +		 */ +		bool encrypted_volume_read_only; +		/** +		 * Indicates whether the encrypted volume is active. +		 */ +		bool encrypted_volume_active; +		/** +		 * Indicates whether the hidden volume is read-only. +		 */ +		bool hidden_volume_read_only; +		/** +		 * Indicates whether the hidden volume is active. +		 */ +		bool hidden_volume_active; +		/** +		 * The major firmware version, e. g. 0 in v0.40. +		 */ +		uint8_t firmware_version_major; +		/** +		 * The minor firmware version, e. g. 40 in v0.40. +		 */ +		uint8_t firmware_version_minor; +		/** +		 * Indicates whether the firmware is locked. +		 */ +		bool firmware_locked; +		/** +		 * The serial number of the SD card in the Storage stick. +		 */ +		uint32_t serial_number_sd_card; +		/** +		 * The serial number of the smart card in the Storage stick. +		 */ +		uint32_t serial_number_smart_card; +		/** +		 * The number of remaining login attempts for the user PIN. +		 */ +		uint8_t user_retry_count; +		/** +		 * The number of remaining login attempts for the admin PIN. +		 */ +		uint8_t admin_retry_count; +		/** +		 * Indicates whether a new SD card was found. +		 */ +		bool new_sd_card_found; +		/** +		 * Indicates whether the SD card is filled with random characters. +		 */ +		bool filled_with_random; +		/** +		 * Indicates whether the stick has been initialized by generating +		 * the AES keys. +		 */ +		bool stick_initialized; +        }; + +   struct NK_storage_ProductionTest{ +    uint8_t FirmwareVersion_au8[2]; +    uint8_t FirmwareVersionInternal_u8; +    uint8_t SD_Card_Size_u8; +    uint32_t CPU_CardID_u32; +    uint32_t SmartCardID_u32; +    uint32_t SD_CardID_u32; +    uint8_t SC_UserPwRetryCount; +    uint8_t SC_AdminPwRetryCount; +    uint8_t SD_Card_ManufacturingYear_u8; +    uint8_t SD_Card_ManufacturingMonth_u8; +    uint16_t SD_Card_OEM_u16; +    uint16_t SD_WriteSpeed_u16; +    uint8_t SD_Card_Manufacturer_u8; +  }; + +  NK_C_API int NK_get_storage_production_info(struct NK_storage_ProductionTest * out); + + +/** + * Set debug level of messages written on stderr + * @param state state=True - most messages, state=False - only errors level + */  	NK_C_API void NK_set_debug(bool state);  	/**  	 * Set debug level of messages written on stderr  	 * @param level (int) 0-lowest verbosity, 5-highest verbosity  	 */ -  NK_C_API void NK_set_debug_level(const int level); +	NK_C_API void NK_set_debug_level(const int level); + +	/** +	 * Get the major library version, e. g. the 3 in v3.2. +	 * @return the major library version +	 */ +	NK_C_API unsigned int NK_get_major_library_version(); + +	/** +	 * Get the minor library version, e. g. the 2 in v3.2. +	 * @return the minor library version +	 */ +	NK_C_API unsigned int NK_get_minor_library_version(); + +	/** +	 * Get the library version as a string.  This is the output of +	 * `git describe --always` at compile time, for example "v3.3" or +	 * "v3.3-19-gaee920b". +	 * The return value is a string literal and must not be freed. +	 * @return the library version as a string +	 */ +	NK_C_API const char* NK_get_library_version();  	/**  	 * Connect to device of given model. Currently library can be connected only to one device at once. @@ -88,16 +207,24 @@ extern "C" {  	NK_C_API int NK_logout();  	/** +	 * Query the model of the connected device. +	 * Returns the model of the connected device or NK_DISCONNECTED. +	 * +	 * @return true if a device is connected and the out argument has been set +	 */ +	NK_C_API enum NK_device_model NK_get_device_model(); + +	/**  	 * Return the debug status string. Debug purposes.  	 * @return command processing error code  	 */ -	NK_C_API const char * NK_status(); +	NK_C_API char * NK_status();  	/**  	 * Return the device's serial number string in hex.  	 * @return string device's serial number in hex  	 */ -	NK_C_API const char * NK_device_serial_number(); +	NK_C_API char * NK_device_serial_number();  	/**  	 * Get last command processing status. Useful for commands which returns the results of their own and could not return @@ -114,37 +241,37 @@ extern "C" {  	/**  	 * Authenticates the user on USER privilages with user_password and sets user's temporary password on device to user_temporary_password. -	 * @param user_password char[25](Pro) current user password -	 * @param user_temporary_password char[25](Pro) user temporary password to be set on device for further communication (authentication command) +	 * @param user_password char[25] current user password +	 * @param user_temporary_password char[25] user temporary password to be set on device for further communication (authentication command)  	 * @return command processing error code  	 */  	NK_C_API int NK_user_authenticate(const char* user_password, const char* user_temporary_password);  	/**  	 * Authenticates the user on ADMIN privilages with admin_password and sets user's temporary password on device to admin_temporary_password. -	 * @param admin_password char[25](Pro) current administrator PIN -	 * @param admin_temporary_password char[25](Pro) admin temporary password to be set on device for further communication (authentication command) +	 * @param admin_password char[25] current administrator PIN +	 * @param admin_temporary_password char[25] admin temporary password to be set on device for further communication (authentication command)  	 * @return command processing error code  	 */  	NK_C_API int NK_first_authenticate(const char* admin_password, const char* admin_temporary_password);  	/**  	 * Execute a factory reset. -	 * @param admin_password char[20](Pro) current administrator PIN +	 * @param admin_password char[20] current administrator PIN  	 * @return command processing error code  	 */  	NK_C_API int NK_factory_reset(const char* admin_password);  	/**  	 * Generates AES key on the device -	 * @param admin_password char[20](Pro) current administrator PIN +	 * @param admin_password char[20] current administrator PIN  	 * @return command processing error code  	 */  	NK_C_API int NK_build_aes_key(const char* admin_password);  	/**  	 * Unlock user PIN locked after 3 incorrect codes tries. -	 * @param admin_password char[20](Pro) current administrator PIN +	 * @param admin_password char[20] current administrator PIN  	 * @return command processing error code  	 */  	NK_C_API int NK_unlock_user_password(const char *admin_password, const char *new_user_password); @@ -181,16 +308,16 @@ extern "C" {  	/**  	 * Get name of given TOTP slot  	 * @param slot_number TOTP slot number, slot_number<15 -	 * @return char[20](Pro) the name of the slot +	 * @return char[20] the name of the slot  	 */ -	NK_C_API const char * NK_get_totp_slot_name(uint8_t slot_number); +	NK_C_API char * NK_get_totp_slot_name(uint8_t slot_number);  	/**  	 *  	 * @param slot_number HOTP slot number, slot_number<3 -	 * @return char[20](Pro) the name of the slot +	 * @return char[20] the name of the slot  	 */ -	NK_C_API const char * NK_get_hotp_slot_name(uint8_t slot_number); +	NK_C_API char * NK_get_hotp_slot_name(uint8_t slot_number);  	/**  	 * Erase HOTP slot data from the device @@ -210,15 +337,16 @@ extern "C" {  	/**  	 * Write HOTP slot data to the device -	 * @param slot_number HOTP slot number, slot_number<3 -	 * @param slot_name char[15](Pro) desired slot name -	 * @param secret char[20](Pro) 160-bit secret +	 * @param slot_number HOTP slot number, slot_number<3, 0-numbered +	 * @param slot_name char[15] desired slot name. C string (requires ending '\0'; 16 bytes). +	 * @param secret char[40] 160-bit or 320-bit (currently Pro v0.8 only) secret as a hex string. C string (requires ending '\0'; 41 bytes). +	 * See NitrokeyManager::is_320_OTP_secret_supported.  	 * @param hotp_counter uint32_t starting value of HOTP counter  	 * @param use_8_digits should returned codes be 6 (false) or 8 digits (true)  	 * @param use_enter press ENTER key after sending OTP code using double-pressed scroll/num/capslock  	 * @param use_tokenID @see token_ID  	 * @param token_ID @see https://openauthentication.org/token-specs/, 'Class A' section -	 * @param temporary_password char[25](Pro) admin temporary password +	 * @param temporary_password char[25] admin temporary password  	 * @return command processing error code  	 */  	NK_C_API int NK_write_hotp_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter, @@ -227,15 +355,16 @@ extern "C" {  	/**  	 * Write TOTP slot data to the device -	 * @param slot_number TOTP slot number, slot_number<15 -	 * @param slot_name char[15](Pro) desired slot name -	 * @param secret char[20](Pro) 160-bit secret +	 * @param slot_number TOTP slot number, slot_number<15, 0-numbered +	 * @param slot_name char[15] desired slot name. C string (requires ending '\0'; 16 bytes). +	 * @param secret char[40] 160-bit or 320-bit (currently Pro v0.8 only) secret as a hex string. C string (requires ending '\0'; 41 bytes). +	 * See NitrokeyManager::is_320_OTP_secret_supported.  	 * @param time_window uint16_t time window for this TOTP  	 * @param use_8_digits should returned codes be 6 (false) or 8 digits (true)  	 * @param use_enter press ENTER key after sending OTP code using double-pressed scroll/num/capslock  	 * @param use_tokenID @see token_ID  	 * @param token_ID @see https://openauthentication.org/token-specs/, 'Class A' section -	 * @param temporary_password char[20](Pro) admin temporary password +	 * @param temporary_password char[20] admin temporary password  	 * @return command processing error code  	 */  	NK_C_API int NK_write_totp_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window, @@ -247,39 +376,39 @@ extern "C" {  	 * @param slot_number HOTP slot number, slot_number<3  	 * @return HOTP code  	 */ -	NK_C_API const char * NK_get_hotp_code(uint8_t slot_number); +	NK_C_API char * NK_get_hotp_code(uint8_t slot_number);  	/**  	 * Get HOTP code from the device (PIN protected)  	 * @param slot_number HOTP slot number, slot_number<3 -	 * @param user_temporary_password char[25](Pro) user temporary password if PIN protected OTP codes are enabled, +	 * @param user_temporary_password char[25] user temporary password if PIN protected OTP codes are enabled,  	 * otherwise should be set to empty string - ''  	 * @return HOTP code  	 */ -	NK_C_API const char * NK_get_hotp_code_PIN(uint8_t slot_number, const char *user_temporary_password); +	NK_C_API char * NK_get_hotp_code_PIN(uint8_t slot_number, const char *user_temporary_password);  	/**  	 * Get TOTP code from the device  	 * @param slot_number TOTP slot number, slot_number<15 -	 * @param challenge TOTP challenge -	 * @param last_totp_time last time -	 * @param last_interval last interval +	 * @param challenge TOTP challenge -- unused +	 * @param last_totp_time last time -- unused +	 * @param last_interval last interval --unused  	 * @return TOTP code  	 */ -	NK_C_API const char * NK_get_totp_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, +	NK_C_API char * NK_get_totp_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time,  		uint8_t last_interval);  	/**  	 * Get TOTP code from the device (PIN protected)  	 * @param slot_number TOTP slot number, slot_number<15 -	 * @param challenge TOTP challenge -	 * @param last_totp_time last time -	 * @param last_interval last interval -	 * @param user_temporary_password char[25](Pro) user temporary password if PIN protected OTP codes are enabled, +	 * @param challenge TOTP challenge -- unused +	 * @param last_totp_time last time -- unused +	 * @param last_interval last interval -- unused +	 * @param user_temporary_password char[25] user temporary password if PIN protected OTP codes are enabled,  	 * otherwise should be set to empty string - ''  	 * @return TOTP code  	 */ -	NK_C_API const char * NK_get_totp_code_PIN(uint8_t slot_number, uint64_t challenge, +	NK_C_API char * NK_get_totp_code_PIN(uint8_t slot_number, uint64_t challenge,  		uint64_t last_totp_time, uint8_t last_interval,  		const char *user_temporary_password); @@ -290,21 +419,35 @@ extern "C" {  	 */  	NK_C_API int NK_totp_set_time(uint64_t time); +	/** +	 * Set the device time used for TOTP to the given time.  Contrary to +	 * {@code set_time(uint64_t)}, this command fails if {@code old_time} +	 * > {@code time} or if {@code old_time} is zero (where {@code +	 * old_time} is the current time on the device). +	 * +	 * @param time new device time as Unix timestamp (seconds since +	 *        1970-01-01) +	 * @return command processing error code +	 */ +	NK_C_API int NK_totp_set_time_soft(uint64_t time); + +	// NK_totp_get_time is deprecated -- use NK_totp_set_time_soft instead +	DEPRECATED  	NK_C_API int NK_totp_get_time();  	//passwords  	/**  	 * Change administrator PIN -	 * @param current_PIN char[25](Pro) current PIN -	 * @param new_PIN char[25](Pro) new PIN +	 * @param current_PIN char[25] current PIN +	 * @param new_PIN char[25] new PIN  	 * @return command processing error code  	 */  	NK_C_API int NK_change_admin_PIN(const char *current_PIN, const char *new_PIN);  	/**  	 * Change user PIN -	 * @param current_PIN char[25](Pro) current PIN -	 * @param new_PIN char[25](Pro) new PIN +	 * @param current_PIN char[25] current PIN +	 * @param new_PIN char[25] new PIN  	 * @return command processing error code  	*/  	NK_C_API int NK_change_user_PIN(const char *current_PIN, const char *new_PIN); @@ -325,7 +468,7 @@ extern "C" {  	/**  	 * Enable password safe access -	 * @param user_pin char[30](Pro) current user PIN +	 * @param user_pin char[30] current user PIN  	 * @return command processing error code  	 */  	NK_C_API int NK_enable_password_safe(const char *user_pin); @@ -341,28 +484,28 @@ extern "C" {  	 * @param slot_number password safe slot number, slot_number<16  	 * @return slot name  	 */ -	NK_C_API const char *NK_get_password_safe_slot_name(uint8_t slot_number); +	NK_C_API char *NK_get_password_safe_slot_name(uint8_t slot_number);  	/**  	 * Get password safe slot login  	 * @param slot_number password safe slot number, slot_number<16  	 * @return login from the PWS slot  	 */ -	NK_C_API const char *NK_get_password_safe_slot_login(uint8_t slot_number); +	NK_C_API char *NK_get_password_safe_slot_login(uint8_t slot_number);  	/**  	 * Get the password safe slot password  	 * @param slot_number password safe slot number, slot_number<16  	 * @return password from the PWS slot  	 */ -	NK_C_API const char *NK_get_password_safe_slot_password(uint8_t slot_number); +	NK_C_API char *NK_get_password_safe_slot_password(uint8_t slot_number);  	/**  	 * Write password safe data to the slot  	 * @param slot_number password safe slot number, slot_number<16 -	 * @param slot_name char[11](Pro) name of the slot -	 * @param slot_login char[32](Pro) login string -	 * @param slot_password char[20](Pro) password string +	 * @param slot_name char[11] name of the slot +	 * @param slot_login char[32] login string +	 * @param slot_password char[20] password string  	 * @return command processing error code  	 */  	NK_C_API int NK_write_password_safe_slot(uint8_t slot_number, const char *slot_name, @@ -580,7 +723,18 @@ extern "C" {  	 * Storage only  	 * @return string with devices attributes  	 */ -	NK_C_API const char* NK_get_status_storage_as_string(); +	NK_C_API char* NK_get_status_storage_as_string(); + +	/** +	 * Get the Storage stick status and return the command processing +	 * error code.  If the code is zero, i. e. the command was successful, +	 * the storage status is written to the output pointer's target. +	 * The output pointer must not be null. +	 * +	 * @param out the output pointer for the storage status +	 * @return command processing error code +	 */ +	NK_C_API int NK_get_status_storage(struct NK_storage_status* out);  	/**  	 * Get SD card usage attributes as string. @@ -588,7 +742,7 @@ extern "C" {  	 * Storage only  	 * @return string with SD card usage attributes  	 */ -	NK_C_API const char* NK_get_SD_usage_data_as_string(); +	NK_C_API char* NK_get_SD_usage_data_as_string();  	/**  	 * Get progress value of current long operation. @@ -612,7 +766,7 @@ extern "C" {   * @example Example of returned data: '00005d19:dacc2cb4_p_0001:0010:02;000037c7:4cf12445_p_0001:000f:02;0001:000c:02'   * @return string delimited id's of connected devices   */ -	NK_C_API const char* NK_list_devices_by_cpuID(); +	NK_C_API char* NK_list_devices_by_cpuID();  /** @@ -625,7 +779,11 @@ extern "C" {   */  	NK_C_API int NK_connect_with_ID(const char* id); - +	/** +	 * Blink red and green LED alternatively and infinitely (until device is reconnected). +	 * @return command processing error code +	 */ +	NK_C_API int NK_wink();  #ifdef __cplusplus  } diff --git a/libnitrokey-v3.3/NitrokeyManager.cc b/libnitrokey-v3.4/NitrokeyManager.cc index 2ca183c..a950e4b 100644 --- a/libnitrokey-v3.3/NitrokeyManager.cc +++ b/libnitrokey-v3.4/NitrokeyManager.cc @@ -234,12 +234,14 @@ using nitrokey::misc::strcpyT;      bool NitrokeyManager::connect() {          std::lock_guard<std::mutex> lock(mex_dev_com_manager);          vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>() }; +        bool connected = false;          for( auto & d : devices ){              if (d->connect()){                  device = std::shared_ptr<Device>(d); +                connected = true;              }          } -        return device != nullptr; +        return connected;      } @@ -630,12 +632,12 @@ using nitrokey::misc::strcpyT;        auto resp = WriteToTOTPSlot::CommandTransaction::run(device, payload);      } -    const char * NitrokeyManager::get_totp_slot_name(uint8_t slot_number) { +    char * NitrokeyManager::get_totp_slot_name(uint8_t slot_number) {          if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number);          slot_number = get_internal_slot_number_for_totp(slot_number);          return get_slot_name(slot_number);      } -    const char * NitrokeyManager::get_hotp_slot_name(uint8_t slot_number) { +    char * NitrokeyManager::get_hotp_slot_name(uint8_t slot_number) {          if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number);          slot_number = get_internal_slot_number_for_hotp(slot_number);          return get_slot_name(slot_number); @@ -643,7 +645,7 @@ using nitrokey::misc::strcpyT;    static const int max_string_field_length = 2*1024; //storage's status string is ~1k -  const char * NitrokeyManager::get_slot_name(uint8_t slot_number)  { +  char * NitrokeyManager::get_slot_name(uint8_t slot_number)  {          auto payload = get_payload<GetSlotName>();          payload.slot_number = slot_number;          auto resp = GetSlotName::CommandTransaction::run(device, payload); @@ -666,11 +668,15 @@ using nitrokey::misc::strcpyT;          return false;      } -    bool NitrokeyManager::get_time(uint64_t time) { +    void NitrokeyManager::set_time_soft(uint64_t time) {          auto p = get_payload<SetTime>();          p.reset = 0;          p.time = time;          SetTime::CommandTransaction::run(device, p); +    } + +    bool NitrokeyManager::get_time(uint64_t time) { +        set_time_soft(time);          return true;      } @@ -749,7 +755,7 @@ using nitrokey::misc::strcpyT;          LockDevice::CommandTransaction::run(device);      } -    const char *NitrokeyManager::get_password_safe_slot_name(uint8_t slot_number) { +    char * NitrokeyManager::get_password_safe_slot_name(uint8_t slot_number) {          if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);          auto p = get_payload<GetPasswordSafeSlotName>();          p.slot_number = slot_number; @@ -759,7 +765,7 @@ using nitrokey::misc::strcpyT;      bool NitrokeyManager::is_valid_password_safe_slot_number(uint8_t slot_number) const { return slot_number < 16; } -    const char *NitrokeyManager::get_password_safe_slot_login(uint8_t slot_number) { +    char * NitrokeyManager::get_password_safe_slot_login(uint8_t slot_number) {          if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);          auto p = get_payload<GetPasswordSafeSlotLogin>();          p.slot_number = slot_number; @@ -767,7 +773,7 @@ using nitrokey::misc::strcpyT;          return strndup((const char *) response.data().slot_login, max_string_field_length);      } -    const char *NitrokeyManager::get_password_safe_slot_password(uint8_t slot_number) { +    char * NitrokeyManager::get_password_safe_slot_password(uint8_t slot_number) {          if (!is_valid_password_safe_slot_number(slot_number)) throw InvalidSlotException(slot_number);          auto p = get_payload<GetPasswordSafeSlotPassword>();          p.slot_number = slot_number; @@ -1059,7 +1065,7 @@ using nitrokey::misc::strcpyT;        stick20::ChangeUpdatePassword::CommandTransaction::run(device, p);      } -    const char * NitrokeyManager::get_status_storage_as_string(){ +    char * NitrokeyManager::get_status_storage_as_string(){        auto p = stick20::GetDeviceStatus::CommandTransaction::run(device);        return strndup(p.data().dissect().c_str(), max_string_field_length);      } @@ -1069,7 +1075,7 @@ using nitrokey::misc::strcpyT;        return p.data();      } -    const char * NitrokeyManager::get_SD_usage_data_as_string(){ +    char * NitrokeyManager::get_SD_usage_data_as_string(){        auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device);        return strndup(p.data().dissect().c_str(), max_string_field_length);      } @@ -1131,5 +1137,13 @@ using nitrokey::misc::strcpyT;          return current_device_id;      } +  void NitrokeyManager::wink(){ +    stick20::Wink::CommandTransaction::run(device); +  }; + +  stick20::ProductionTest::ResponsePayload NitrokeyManager::production_info(){ +    auto data = stick20::ProductionTest::CommandTransaction::run(device); +    return data.data(); +  };  } diff --git a/libnitrokey-v3.3/README.md b/libnitrokey-v3.4/README.md index 81b367a..81b367a 100644 --- a/libnitrokey-v3.3/README.md +++ b/libnitrokey-v3.4/README.md diff --git a/libnitrokey-v3.3/command_id.cc b/libnitrokey-v3.4/command_id.cc index d81d487..a6c2a28 100644 --- a/libnitrokey-v3.3/command_id.cc +++ b/libnitrokey-v3.4/command_id.cc @@ -173,10 +173,10 @@ const char *commandid_to_string(CommandID id) {        return "NEW_AES_KEY";      case CommandID::WRITE_TO_SLOT_2:        return "WRITE_TO_SLOT_2"; -      break;      case CommandID::SEND_OTP_DATA:        return "SEND_OTP_DATA"; -      break; +    case CommandID::WINK: +      return "WINK";    }    return "UNKNOWN";  } diff --git a/libnitrokey-v3.3/device.cc b/libnitrokey-v3.4/device.cc index da54e33..80e4b38 100644 --- a/libnitrokey-v3.3/device.cc +++ b/libnitrokey-v3.4/device.cc @@ -69,8 +69,10 @@ bool Device::_disconnect() {    LOG(std::string(__FUNCTION__) + std::string(m_model == DeviceModel::PRO ? "PRO" : "STORAGE"), Loglevel::DEBUG_L2);    LOG(std::string(__FUNCTION__) +  std::string(" *IN* "), Loglevel::DEBUG_L2); -  LOG(std::string("Disconnection: handle already freed: ") + std::to_string(mp_devhandle == nullptr) + " ("+m_path+")", Loglevel::DEBUG_L1); -  if(mp_devhandle == nullptr) return false; +  if(mp_devhandle == nullptr) { +    LOG(std::string("Disconnection: handle already freed: ") + std::to_string(mp_devhandle == nullptr) + " ("+m_path+")", Loglevel::DEBUG_L1); +    return false; +  }    hid_close(mp_devhandle);    mp_devhandle = nullptr; diff --git a/libnitrokey-v3.3/libnitrokey/CommandFailedException.h b/libnitrokey-v3.4/libnitrokey/CommandFailedException.h index 32bd6b7..32bd6b7 100644 --- a/libnitrokey-v3.3/libnitrokey/CommandFailedException.h +++ b/libnitrokey-v3.4/libnitrokey/CommandFailedException.h diff --git a/libnitrokey-v3.3/libnitrokey/DeviceCommunicationExceptions.h b/libnitrokey-v3.4/libnitrokey/DeviceCommunicationExceptions.h index f710d0b..f710d0b 100644 --- a/libnitrokey-v3.3/libnitrokey/DeviceCommunicationExceptions.h +++ b/libnitrokey-v3.4/libnitrokey/DeviceCommunicationExceptions.h diff --git a/libnitrokey-v3.3/libnitrokey/LibraryException.h b/libnitrokey-v3.4/libnitrokey/LibraryException.h index 3b9d177..3b9d177 100644 --- a/libnitrokey-v3.3/libnitrokey/LibraryException.h +++ b/libnitrokey-v3.4/libnitrokey/LibraryException.h diff --git a/libnitrokey-v3.3/libnitrokey/LongOperationInProgressException.h b/libnitrokey-v3.4/libnitrokey/LongOperationInProgressException.h index 865d6b5..865d6b5 100644 --- a/libnitrokey-v3.3/libnitrokey/LongOperationInProgressException.h +++ b/libnitrokey-v3.4/libnitrokey/LongOperationInProgressException.h diff --git a/libnitrokey-v3.3/libnitrokey/NitrokeyManager.h b/libnitrokey-v3.4/libnitrokey/NitrokeyManager.h index 1f4cec4..d6e5df4 100644 --- a/libnitrokey-v3.3/libnitrokey/NitrokeyManager.h +++ b/libnitrokey-v3.4/libnitrokey/NitrokeyManager.h @@ -65,6 +65,18 @@ char * strndup(const char* str, size_t maxlen);          stick10::ReadSlot::ResponsePayload get_HOTP_slot_data(const uint8_t slot_number);          bool set_time(uint64_t time); +        /** +         * Set the device time used for TOTP to the given time.  Contrary to +         * {@code set_time(uint64_t)}, this command fails if {@code old_time} +         * > {@code time} or if {@code old_time} is zero (where {@code +         * old_time} is the current time on the device). +         * +         * @param time new device time as Unix timestamp (seconds since +         *        1970-01-01) +         */ +        void set_time_soft(uint64_t time); + +        [[deprecated("get_time is deprecated -- use set_time_soft instead")]]          bool get_time(uint64_t time = 0);          bool erase_totp_slot(uint8_t slot_number, const char *temporary_password);          bool erase_hotp_slot(uint8_t slot_number, const char *temporary_password); @@ -93,8 +105,8 @@ char * strndup(const char* str, size_t maxlen);          string get_status_as_string();          string get_serial_number(); -        const char * get_totp_slot_name(uint8_t slot_number); -        const char * get_hotp_slot_name(uint8_t slot_number); +        char * get_totp_slot_name(uint8_t slot_number); +        char * get_hotp_slot_name(uint8_t slot_number);          void change_user_PIN(const char *current_PIN, const char *new_PIN);          void change_admin_PIN(const char *current_PIN, const char *new_PIN); @@ -108,9 +120,9 @@ char * strndup(const char* str, size_t maxlen);          void lock_device(); -        const char *get_password_safe_slot_name(uint8_t slot_number); -        const char *get_password_safe_slot_password(uint8_t slot_number); -        const char *get_password_safe_slot_login(uint8_t slot_number); +        char * get_password_safe_slot_name(uint8_t slot_number); +        char * get_password_safe_slot_password(uint8_t slot_number); +        char * get_password_safe_slot_login(uint8_t slot_number);          void      write_password_safe_slot(uint8_t slot_number, const char *slot_name, const char *slot_login, @@ -187,10 +199,10 @@ char * strndup(const char* str, size_t maxlen);          void send_startup(uint64_t seconds_from_epoch); -        const char * get_status_storage_as_string(); +        char * get_status_storage_as_string();          stick20::DeviceConfigurationResponsePacket::ResponsePayload get_status_storage(); -        const char *get_SD_usage_data_as_string(); +        char * get_SD_usage_data_as_string();          std::pair<uint8_t,uint8_t> get_SD_usage_data(); @@ -227,7 +239,7 @@ char * strndup(const char* str, size_t maxlen);          uint8_t get_internal_slot_number_for_hotp(uint8_t slot_number) const;          uint8_t get_internal_slot_number_for_totp(uint8_t slot_number) const;          bool erase_slot(uint8_t slot_number, const char *temporary_password); -        const char * get_slot_name(uint8_t slot_number); +        char * get_slot_name(uint8_t slot_number);          template <typename ProCommand, PasswordKind StoKind>          void change_PIN_general(const char *current_PIN, const char *new_PIN); @@ -276,6 +288,13 @@ char * strndup(const char* str, size_t maxlen);         * @return Returns true, if set unencrypted volume ro/rw pin type is User, false otherwise.         */        bool set_unencrypted_volume_rorw_pin_type_user(); + +      /** +       * Blink red and green LED alternatively and infinitely (until device is reconnected). +       */ +      void wink(); + +      stick20::ProductionTest::ResponsePayload production_info();      };  } diff --git a/libnitrokey-v3.3/libnitrokey/command.h b/libnitrokey-v3.4/libnitrokey/command.h index 6852bf0..6852bf0 100644 --- a/libnitrokey-v3.3/libnitrokey/command.h +++ b/libnitrokey-v3.4/libnitrokey/command.h diff --git a/libnitrokey-v3.3/libnitrokey/command_id.h b/libnitrokey-v3.4/libnitrokey/command_id.h index 1092ea9..eb0d450 100644 --- a/libnitrokey-v3.3/libnitrokey/command_id.h +++ b/libnitrokey-v3.4/libnitrokey/command_id.h @@ -130,6 +130,8 @@ enum class CommandID : uint8_t {    ENABLE_ADMIN_READONLY_ENCRYPTED_LUN = 0x20 + 30,    ENABLE_ADMIN_READWRITE_ENCRYPTED_LUN = 0x20 + 31,    CHECK_SMARTCARD_USAGE = 0x20 + 32, +  //v0.52+ +  WINK = 0x20 + 33,    GET_PW_SAFE_SLOT_STATUS = 0x60,    GET_PW_SAFE_SLOT_NAME = 0x61, diff --git a/libnitrokey-v3.3/libnitrokey/cxx_semantics.h b/libnitrokey-v3.4/libnitrokey/cxx_semantics.h index 36ed142..36ed142 100644 --- a/libnitrokey-v3.3/libnitrokey/cxx_semantics.h +++ b/libnitrokey-v3.4/libnitrokey/cxx_semantics.h diff --git a/libnitrokey-v3.4/libnitrokey/deprecated.h b/libnitrokey-v3.4/libnitrokey/deprecated.h new file mode 100644 index 0000000..5a83288 --- /dev/null +++ b/libnitrokey-v3.4/libnitrokey/deprecated.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Nitrokey UG + * + * This file is part of libnitrokey. + * + * libnitrokey is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * libnitrokey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnitrokey. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-3.0 + */ + + +#ifndef LIBNITROKEY_DEPRECATED_H +#define LIBNITROKEY_DEPRECATED_H + +#if defined(__GNUC__) || defined(__clang__) +#define DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define DEPRECATED __declspec(deprecated) +#else +#pragma message("WARNING: DEPRECATED macro is not defined for this compiler") +#define DEPRECATED +#endif + +#endif //LIBNITROKEY_DEPRECATED_H diff --git a/libnitrokey-v3.3/libnitrokey/device.h b/libnitrokey-v3.4/libnitrokey/device.h index f6d2380..f6d2380 100644 --- a/libnitrokey-v3.3/libnitrokey/device.h +++ b/libnitrokey-v3.4/libnitrokey/device.h diff --git a/libnitrokey-v3.3/libnitrokey/device_proto.h b/libnitrokey-v3.4/libnitrokey/device_proto.h index 45a6c16..45a6c16 100644 --- a/libnitrokey-v3.3/libnitrokey/device_proto.h +++ b/libnitrokey-v3.4/libnitrokey/device_proto.h diff --git a/libnitrokey-v3.3/libnitrokey/dissect.h b/libnitrokey-v3.4/libnitrokey/dissect.h index 690b5b7..690b5b7 100644 --- a/libnitrokey-v3.3/libnitrokey/dissect.h +++ b/libnitrokey-v3.4/libnitrokey/dissect.h diff --git a/libnitrokey-v3.3/libnitrokey/hidapi/hidapi.h b/libnitrokey-v3.4/libnitrokey/hidapi/hidapi.h index e5bc2dc..e5bc2dc 100644 --- a/libnitrokey-v3.3/libnitrokey/hidapi/hidapi.h +++ b/libnitrokey-v3.4/libnitrokey/hidapi/hidapi.h diff --git a/libnitrokey-v3.3/libnitrokey/log.h b/libnitrokey-v3.4/libnitrokey/log.h index 2a64bef..2a64bef 100644 --- a/libnitrokey-v3.3/libnitrokey/log.h +++ b/libnitrokey-v3.4/libnitrokey/log.h diff --git a/libnitrokey-v3.3/libnitrokey/misc.h b/libnitrokey-v3.4/libnitrokey/misc.h index 88254dd..88254dd 100644 --- a/libnitrokey-v3.3/libnitrokey/misc.h +++ b/libnitrokey-v3.4/libnitrokey/misc.h diff --git a/libnitrokey-v3.3/libnitrokey/stick10_commands.h b/libnitrokey-v3.4/libnitrokey/stick10_commands.h index f2ffba2..f2ffba2 100644 --- a/libnitrokey-v3.3/libnitrokey/stick10_commands.h +++ b/libnitrokey-v3.4/libnitrokey/stick10_commands.h diff --git a/libnitrokey-v3.3/libnitrokey/stick10_commands_0.8.h b/libnitrokey-v3.4/libnitrokey/stick10_commands_0.8.h index 9477890..9477890 100644 --- a/libnitrokey-v3.3/libnitrokey/stick10_commands_0.8.h +++ b/libnitrokey-v3.4/libnitrokey/stick10_commands_0.8.h diff --git a/libnitrokey-v3.3/libnitrokey/stick20_commands.h b/libnitrokey-v3.4/libnitrokey/stick20_commands.h index 4b75e6a..7efa1b6 100644 --- a/libnitrokey-v3.3/libnitrokey/stick20_commands.h +++ b/libnitrokey-v3.4/libnitrokey/stick20_commands.h @@ -275,6 +275,12 @@ namespace nitrokey {                      CommandTransaction;              }; +          class Wink : Command<CommandID::WINK> { +          public: +            typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload> +                CommandTransaction; +          }; +              class CheckSmartcardUsage : Command<CommandID::CHECK_SMARTCARD_USAGE> {              public:                  typedef Transaction<command_id(), struct EmptyPayload, EmptyPayload> diff --git a/libnitrokey-v3.4/libnitrokey/version.h b/libnitrokey-v3.4/libnitrokey/version.h new file mode 100644 index 0000000..6547af0 --- /dev/null +++ b/libnitrokey-v3.4/libnitrokey/version.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Nitrokey UG + * + * This file is part of libnitrokey. + * + * libnitrokey is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * libnitrokey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnitrokey. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-3.0 + */ + +#ifndef LIBNITROKEY_VERSION_H +#define LIBNITROKEY_VERSION_H + +namespace nitrokey { +    unsigned int get_major_library_version(); + +    unsigned int get_minor_library_version(); + +    const char* get_library_version(); +} + +#endif diff --git a/libnitrokey-v3.3/log.cc b/libnitrokey-v3.4/log.cc index 06acee7..06acee7 100644 --- a/libnitrokey-v3.3/log.cc +++ b/libnitrokey-v3.4/log.cc diff --git a/libnitrokey-v3.3/misc.cc b/libnitrokey-v3.4/misc.cc index 59185f3..59185f3 100644 --- a/libnitrokey-v3.3/misc.cc +++ b/libnitrokey-v3.4/misc.cc diff --git a/libnitrokey-v3.4/version.cc.in b/libnitrokey-v3.4/version.cc.in new file mode 100644 index 0000000..0eae647 --- /dev/null +++ b/libnitrokey-v3.4/version.cc.in @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Nitrokey UG + * + * This file is part of libnitrokey. + * + * libnitrokey is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * libnitrokey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnitrokey. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-3.0 + */ + +#include "version.h" + +namespace nitrokey { +    unsigned int get_major_library_version() { +        return @PROJECT_VERSION_MAJOR@; +    } + +    unsigned int get_minor_library_version() { +        return @PROJECT_VERSION_MINOR@; +    } + +    const char* get_library_version() { +        return "@PROJECT_VERSION_GIT@"; +    } +} + @@ -1,11 +1,467 @@  /* automatically generated by rust-bindgen, manually modified */ +/// Use, if no supported device is connected +pub const NK_device_model_NK_DISCONNECTED: NK_device_model = 0;  /// Nitrokey Pro. -pub const NK_device_model_NK_PRO: NK_device_model = 0; +pub const NK_device_model_NK_PRO: NK_device_model = 1;  /// Nitrokey Storage. -pub const NK_device_model_NK_STORAGE: NK_device_model = 1; +pub const NK_device_model_NK_STORAGE: NK_device_model = 2;  /// The Nitrokey device models supported by the API.  pub type NK_device_model = u32; +/// Stores the status of a Storage device. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NK_storage_status { +    /// Indicates whether the unencrypted volume is read-only. +    pub unencrypted_volume_read_only: bool, +    /// Indicates whether the unencrypted volume is active. +    pub unencrypted_volume_active: bool, +    /// Indicates whether the encrypted volume is read-only. +    pub encrypted_volume_read_only: bool, +    /// Indicates whether the encrypted volume is active. +    pub encrypted_volume_active: bool, +    /// Indicates whether the hidden volume is read-only. +    pub hidden_volume_read_only: bool, +    /// Indicates whether the hidden volume is active. +    pub hidden_volume_active: bool, +    /// The major firmware version, e. g. 0 in v0.40. +    pub firmware_version_major: u8, +    /// The minor firmware version, e. g. 40 in v0.40. +    pub firmware_version_minor: u8, +    /// Indicates whether the firmware is locked. +    pub firmware_locked: bool, +    /// The serial number of the SD card in the Storage stick. +    pub serial_number_sd_card: u32, +    /// The serial number of the smart card in the Storage stick. +    pub serial_number_smart_card: u32, +    /// The number of remaining login attempts for the user PIN. +    pub user_retry_count: u8, +    /// The number of remaining login attempts for the admin PIN. +    pub admin_retry_count: u8, +    /// Indicates whether a new SD card was found. +    pub new_sd_card_found: bool, +    /// Indicates whether the SD card is filled with random characters. +    pub filled_with_random: bool, +    /// Indicates whether the stick has been initialized by generating +    /// the AES keys. +    pub stick_initialized: bool, +} +#[test] +fn bindgen_test_layout_NK_storage_status() { +    assert_eq!( +        ::std::mem::size_of::<NK_storage_status>(), +        28usize, +        concat!("Size of: ", stringify!(NK_storage_status)) +    ); +    assert_eq!( +        ::std::mem::align_of::<NK_storage_status>(), +        4usize, +        concat!("Alignment of ", stringify!(NK_storage_status)) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).unencrypted_volume_read_only as *const _ +                as usize +        }, +        0usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(unencrypted_volume_read_only) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).unencrypted_volume_active as *const _ +                as usize +        }, +        1usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(unencrypted_volume_active) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).encrypted_volume_read_only as *const _ +                as usize +        }, +        2usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(encrypted_volume_read_only) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).encrypted_volume_active as *const _ +                as usize +        }, +        3usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(encrypted_volume_active) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).hidden_volume_read_only as *const _ +                as usize +        }, +        4usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(hidden_volume_read_only) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).hidden_volume_active as *const _ as usize +        }, +        5usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(hidden_volume_active) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).firmware_version_major as *const _ +                as usize +        }, +        6usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(firmware_version_major) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).firmware_version_minor as *const _ +                as usize +        }, +        7usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(firmware_version_minor) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).firmware_locked as *const _ as usize +        }, +        8usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(firmware_locked) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).serial_number_sd_card as *const _ as usize +        }, +        12usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(serial_number_sd_card) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).serial_number_smart_card as *const _ +                as usize +        }, +        16usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(serial_number_smart_card) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).user_retry_count as *const _ as usize +        }, +        20usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(user_retry_count) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).admin_retry_count as *const _ as usize +        }, +        21usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(admin_retry_count) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).new_sd_card_found as *const _ as usize +        }, +        22usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(new_sd_card_found) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).filled_with_random as *const _ as usize +        }, +        23usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(filled_with_random) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_status>())).stick_initialized as *const _ as usize +        }, +        24usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_status), +            "::", +            stringify!(stick_initialized) +        ) +    ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NK_storage_ProductionTest { +    pub FirmwareVersion_au8: [u8; 2usize], +    pub FirmwareVersionInternal_u8: u8, +    pub SD_Card_Size_u8: u8, +    pub CPU_CardID_u32: u32, +    pub SmartCardID_u32: u32, +    pub SD_CardID_u32: u32, +    pub SC_UserPwRetryCount: u8, +    pub SC_AdminPwRetryCount: u8, +    pub SD_Card_ManufacturingYear_u8: u8, +    pub SD_Card_ManufacturingMonth_u8: u8, +    pub SD_Card_OEM_u16: u16, +    pub SD_WriteSpeed_u16: u16, +    pub SD_Card_Manufacturer_u8: u8, +} +#[test] +fn bindgen_test_layout_NK_storage_ProductionTest() { +    assert_eq!( +        ::std::mem::size_of::<NK_storage_ProductionTest>(), +        28usize, +        concat!("Size of: ", stringify!(NK_storage_ProductionTest)) +    ); +    assert_eq!( +        ::std::mem::align_of::<NK_storage_ProductionTest>(), +        4usize, +        concat!("Alignment of ", stringify!(NK_storage_ProductionTest)) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).FirmwareVersion_au8 as *const _ +                as usize +        }, +        0usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(FirmwareVersion_au8) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).FirmwareVersionInternal_u8 +                as *const _ as usize +        }, +        2usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(FirmwareVersionInternal_u8) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_Card_Size_u8 as *const _ +                as usize +        }, +        3usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_Card_Size_u8) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).CPU_CardID_u32 as *const _ +                as usize +        }, +        4usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(CPU_CardID_u32) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SmartCardID_u32 as *const _ +                as usize +        }, +        8usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SmartCardID_u32) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_CardID_u32 as *const _ as usize +        }, +        12usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_CardID_u32) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SC_UserPwRetryCount as *const _ +                as usize +        }, +        16usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SC_UserPwRetryCount) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SC_AdminPwRetryCount as *const _ +                as usize +        }, +        17usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SC_AdminPwRetryCount) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_Card_ManufacturingYear_u8 +                as *const _ as usize +        }, +        18usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_Card_ManufacturingYear_u8) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_Card_ManufacturingMonth_u8 +                as *const _ as usize +        }, +        19usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_Card_ManufacturingMonth_u8) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_Card_OEM_u16 as *const _ +                as usize +        }, +        20usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_Card_OEM_u16) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_WriteSpeed_u16 as *const _ +                as usize +        }, +        22usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_WriteSpeed_u16) +        ) +    ); +    assert_eq!( +        unsafe { +            &(*(::std::ptr::null::<NK_storage_ProductionTest>())).SD_Card_Manufacturer_u8 +                as *const _ as usize +        }, +        24usize, +        concat!( +            "Offset of field: ", +            stringify!(NK_storage_ProductionTest), +            "::", +            stringify!(SD_Card_Manufacturer_u8) +        ) +    ); +} +extern "C" { +    pub fn NK_get_storage_production_info( +        out: *mut NK_storage_ProductionTest, +    ) -> ::std::os::raw::c_int; +}  extern "C" {      /// Set debug level of messages written on stderr      /// @param state state=True - most messages, state=False - only errors level @@ -17,6 +473,24 @@ extern "C" {      pub fn NK_set_debug_level(level: ::std::os::raw::c_int);  }  extern "C" { +    /// Get the major library version, e. g. the 3 in v3.2. +    /// @return the major library version +    pub fn NK_get_major_library_version() -> ::std::os::raw::c_uint; +} +extern "C" { +    /// Get the minor library version, e. g. the 2 in v3.2. +    /// @return the minor library version +    pub fn NK_get_minor_library_version() -> ::std::os::raw::c_uint; +} +extern "C" { +    /// Get the library version as a string.  This is the output of +    /// `git describe --always` at compile time, for example "v3.3" or +    /// "v3.3-19-gaee920b". +    /// The return value is a string literal and must not be freed. +    /// @return the library version as a string +    pub fn NK_get_library_version() -> *const ::std::os::raw::c_char; +} +extern "C" {      /// Connect to device of given model. Currently library can be connected only to one device at once.      /// @param device_model char 'S': Nitrokey Storage, 'P': Nitrokey Pro      /// @return 1 if connected, 0 if wrong model or cannot connect @@ -39,14 +513,21 @@ extern "C" {      pub fn NK_logout() -> ::std::os::raw::c_int;  }  extern "C" { +    /// Query the model of the connected device. +    /// Returns the model of the connected device or NK_DISCONNECTED. +    /// +    /// @return true if a device is connected and the out argument has been set +    pub fn NK_get_device_model() -> NK_device_model; +} +extern "C" {      /// Return the debug status string. Debug purposes.      /// @return command processing error code -    pub fn NK_status() -> *const ::std::os::raw::c_char; +    pub fn NK_status() -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Return the device's serial number string in hex.      /// @return string device's serial number in hex -    pub fn NK_device_serial_number() -> *const ::std::os::raw::c_char; +    pub fn NK_device_serial_number() -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get last command processing status. Useful for commands which returns the results of their own and could not return @@ -61,8 +542,8 @@ extern "C" {  }  extern "C" {      /// Authenticates the user on USER privilages with user_password and sets user's temporary password on device to user_temporary_password. -    /// @param user_password char[25](Pro) current user password -    /// @param user_temporary_password char[25](Pro) user temporary password to be set on device for further communication (authentication command) +    /// @param user_password char[25] current user password +    /// @param user_temporary_password char[25] user temporary password to be set on device for further communication (authentication command)      /// @return command processing error code      pub fn NK_user_authenticate(          user_password: *const ::std::os::raw::c_char, @@ -71,8 +552,8 @@ extern "C" {  }  extern "C" {      /// Authenticates the user on ADMIN privilages with admin_password and sets user's temporary password on device to admin_temporary_password. -    /// @param admin_password char[25](Pro) current administrator PIN -    /// @param admin_temporary_password char[25](Pro) admin temporary password to be set on device for further communication (authentication command) +    /// @param admin_password char[25] current administrator PIN +    /// @param admin_temporary_password char[25] admin temporary password to be set on device for further communication (authentication command)      /// @return command processing error code      pub fn NK_first_authenticate(          admin_password: *const ::std::os::raw::c_char, @@ -81,21 +562,21 @@ extern "C" {  }  extern "C" {      /// Execute a factory reset. -    /// @param admin_password char[20](Pro) current administrator PIN +    /// @param admin_password char[20] current administrator PIN      /// @return command processing error code      pub fn NK_factory_reset(admin_password: *const ::std::os::raw::c_char)          -> ::std::os::raw::c_int;  }  extern "C" {      /// Generates AES key on the device -    /// @param admin_password char[20](Pro) current administrator PIN +    /// @param admin_password char[20] current administrator PIN      /// @return command processing error code      pub fn NK_build_aes_key(admin_password: *const ::std::os::raw::c_char)          -> ::std::os::raw::c_int;  }  extern "C" {      /// Unlock user PIN locked after 3 incorrect codes tries. -    /// @param admin_password char[20](Pro) current administrator PIN +    /// @param admin_password char[20] current administrator PIN      /// @return command processing error code      pub fn NK_unlock_user_password(          admin_password: *const ::std::os::raw::c_char, @@ -135,13 +616,13 @@ extern "C" {  extern "C" {      /// Get name of given TOTP slot      /// @param slot_number TOTP slot number, slot_number<15 -    /// @return char[20](Pro) the name of the slot -    pub fn NK_get_totp_slot_name(slot_number: u8) -> *const ::std::os::raw::c_char; +    /// @return char[20] the name of the slot +    pub fn NK_get_totp_slot_name(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// @param slot_number HOTP slot number, slot_number<3 -    /// @return char[20](Pro) the name of the slot -    pub fn NK_get_hotp_slot_name(slot_number: u8) -> *const ::std::os::raw::c_char; +    /// @return char[20] the name of the slot +    pub fn NK_get_hotp_slot_name(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Erase HOTP slot data from the device @@ -165,15 +646,16 @@ extern "C" {  }  extern "C" {      /// Write HOTP slot data to the device -    /// @param slot_number HOTP slot number, slot_number<3 -    /// @param slot_name char[15](Pro) desired slot name -    /// @param secret char[20](Pro) 160-bit secret +    /// @param slot_number HOTP slot number, slot_number<3, 0-numbered +    /// @param slot_name char[15] desired slot name. C string (requires ending '\0'; 16 bytes). +    /// @param secret char[40] 160-bit or 320-bit (currently Pro v0.8 only) secret as a hex string. C string (requires ending '\0'; 41 bytes). +    /// See NitrokeyManager::is_320_OTP_secret_supported.      /// @param hotp_counter uint32_t starting value of HOTP counter      /// @param use_8_digits should returned codes be 6 (false) or 8 digits (true)      /// @param use_enter press ENTER key after sending OTP code using double-pressed scroll/num/capslock      /// @param use_tokenID @see token_ID      /// @param token_ID @see https://openauthentication.org/token-specs/, 'Class A' section -    /// @param temporary_password char[25](Pro) admin temporary password +    /// @param temporary_password char[25] admin temporary password      /// @return command processing error code      pub fn NK_write_hotp_slot(          slot_number: u8, @@ -189,15 +671,16 @@ extern "C" {  }  extern "C" {      /// Write TOTP slot data to the device -    /// @param slot_number TOTP slot number, slot_number<15 -    /// @param slot_name char[15](Pro) desired slot name -    /// @param secret char[20](Pro) 160-bit secret +    /// @param slot_number TOTP slot number, slot_number<15, 0-numbered +    /// @param slot_name char[15] desired slot name. C string (requires ending '\0'; 16 bytes). +    /// @param secret char[40] 160-bit or 320-bit (currently Pro v0.8 only) secret as a hex string. C string (requires ending '\0'; 41 bytes). +    /// See NitrokeyManager::is_320_OTP_secret_supported.      /// @param time_window uint16_t time window for this TOTP      /// @param use_8_digits should returned codes be 6 (false) or 8 digits (true)      /// @param use_enter press ENTER key after sending OTP code using double-pressed scroll/num/capslock      /// @param use_tokenID @see token_ID      /// @param token_ID @see https://openauthentication.org/token-specs/, 'Class A' section -    /// @param temporary_password char[20](Pro) admin temporary password +    /// @param temporary_password char[20] admin temporary password      /// @return command processing error code      pub fn NK_write_totp_slot(          slot_number: u8, @@ -215,40 +698,40 @@ extern "C" {      /// Get HOTP code from the device      /// @param slot_number HOTP slot number, slot_number<3      /// @return HOTP code -    pub fn NK_get_hotp_code(slot_number: u8) -> *const ::std::os::raw::c_char; +    pub fn NK_get_hotp_code(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get HOTP code from the device (PIN protected)      /// @param slot_number HOTP slot number, slot_number<3 -    /// @param user_temporary_password char[25](Pro) user temporary password if PIN protected OTP codes are enabled, +    /// @param user_temporary_password char[25] user temporary password if PIN protected OTP codes are enabled,      /// otherwise should be set to empty string - ''      /// @return HOTP code      pub fn NK_get_hotp_code_PIN(          slot_number: u8,          user_temporary_password: *const ::std::os::raw::c_char, -    ) -> *const ::std::os::raw::c_char; +    ) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get TOTP code from the device      /// @param slot_number TOTP slot number, slot_number<15 -    /// @param challenge TOTP challenge -    /// @param last_totp_time last time -    /// @param last_interval last interval +    /// @param challenge TOTP challenge -- unused +    /// @param last_totp_time last time -- unused +    /// @param last_interval last interval --unused      /// @return TOTP code      pub fn NK_get_totp_code(          slot_number: u8,          challenge: u64,          last_totp_time: u64,          last_interval: u8, -    ) -> *const ::std::os::raw::c_char; +    ) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get TOTP code from the device (PIN protected)      /// @param slot_number TOTP slot number, slot_number<15 -    /// @param challenge TOTP challenge -    /// @param last_totp_time last time -    /// @param last_interval last interval -    /// @param user_temporary_password char[25](Pro) user temporary password if PIN protected OTP codes are enabled, +    /// @param challenge TOTP challenge -- unused +    /// @param last_totp_time last time -- unused +    /// @param last_interval last interval -- unused +    /// @param user_temporary_password char[25] user temporary password if PIN protected OTP codes are enabled,      /// otherwise should be set to empty string - ''      /// @return TOTP code      pub fn NK_get_totp_code_PIN( @@ -257,7 +740,7 @@ extern "C" {          last_totp_time: u64,          last_interval: u8,          user_temporary_password: *const ::std::os::raw::c_char, -    ) -> *const ::std::os::raw::c_char; +    ) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Set time on the device (for TOTP requests) @@ -266,12 +749,23 @@ extern "C" {      pub fn NK_totp_set_time(time: u64) -> ::std::os::raw::c_int;  }  extern "C" { +    /// Set the device time used for TOTP to the given time.  Contrary to +    /// {@code set_time(uint64_t)}, this command fails if {@code old_time} +    /// > {@code time} or if {@code old_time} is zero (where {@code +    /// old_time} is the current time on the device). +    /// +    /// @param time new device time as Unix timestamp (seconds since +    /// 1970-01-01) +    /// @return command processing error code +    pub fn NK_totp_set_time_soft(time: u64) -> ::std::os::raw::c_int; +} +extern "C" {      pub fn NK_totp_get_time() -> ::std::os::raw::c_int;  }  extern "C" {      /// Change administrator PIN -    /// @param current_PIN char[25](Pro) current PIN -    /// @param new_PIN char[25](Pro) new PIN +    /// @param current_PIN char[25] current PIN +    /// @param new_PIN char[25] new PIN      /// @return command processing error code      pub fn NK_change_admin_PIN(          current_PIN: *const ::std::os::raw::c_char, @@ -280,8 +774,8 @@ extern "C" {  }  extern "C" {      /// Change user PIN -    /// @param current_PIN char[25](Pro) current PIN -    /// @param new_PIN char[25](Pro) new PIN +    /// @param current_PIN char[25] current PIN +    /// @param new_PIN char[25] new PIN      /// @return command processing error code      pub fn NK_change_user_PIN(          current_PIN: *const ::std::os::raw::c_char, @@ -300,7 +794,7 @@ extern "C" {  }  extern "C" {      /// Enable password safe access -    /// @param user_pin char[30](Pro) current user PIN +    /// @param user_pin char[30] current user PIN      /// @return command processing error code      pub fn NK_enable_password_safe(          user_pin: *const ::std::os::raw::c_char, @@ -315,26 +809,26 @@ extern "C" {      /// Get password safe slot name      /// @param slot_number password safe slot number, slot_number<16      /// @return slot name -    pub fn NK_get_password_safe_slot_name(slot_number: u8) -> *const ::std::os::raw::c_char; +    pub fn NK_get_password_safe_slot_name(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get password safe slot login      /// @param slot_number password safe slot number, slot_number<16      /// @return login from the PWS slot -    pub fn NK_get_password_safe_slot_login(slot_number: u8) -> *const ::std::os::raw::c_char; +    pub fn NK_get_password_safe_slot_login(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get the password safe slot password      /// @param slot_number password safe slot number, slot_number<16      /// @return password from the PWS slot -    pub fn NK_get_password_safe_slot_password(slot_number: u8) -> *const ::std::os::raw::c_char; +    pub fn NK_get_password_safe_slot_password(slot_number: u8) -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Write password safe data to the slot      /// @param slot_number password safe slot number, slot_number<16 -    /// @param slot_name char[11](Pro) name of the slot -    /// @param slot_login char[32](Pro) login string -    /// @param slot_password char[20](Pro) password string +    /// @param slot_name char[11] name of the slot +    /// @param slot_login char[32] login string +    /// @param slot_password char[20] password string      /// @return command processing error code      pub fn NK_write_password_safe_slot(          slot_number: u8, @@ -561,14 +1055,24 @@ extern "C" {      /// Get Storage stick status as string.      /// Storage only      /// @return string with devices attributes -    pub fn NK_get_status_storage_as_string() -> *const ::std::os::raw::c_char; +    pub fn NK_get_status_storage_as_string() -> *mut ::std::os::raw::c_char; +} +extern "C" { +    /// Get the Storage stick status and return the command processing +    /// error code.  If the code is zero, i. e. the command was successful, +    /// the storage status is written to the output pointer's target. +    /// The output pointer must not be null. +    /// +    /// @param out the output pointer for the storage status +    /// @return command processing error code +    pub fn NK_get_status_storage(out: *mut NK_storage_status) -> ::std::os::raw::c_int;  }  extern "C" {      /// Get SD card usage attributes as string.      /// Usable during hidden volumes creation.      /// Storage only      /// @return string with SD card usage attributes -    pub fn NK_get_SD_usage_data_as_string() -> *const ::std::os::raw::c_char; +    pub fn NK_get_SD_usage_data_as_string() -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Get progress value of current long operation. @@ -590,7 +1094,7 @@ extern "C" {      /// Storage only      /// @example Example of returned data: '00005d19:dacc2cb4_p_0001:0010:02;000037c7:4cf12445_p_0001:000f:02;0001:000c:02'      /// @return string delimited id's of connected devices -    pub fn NK_list_devices_by_cpuID() -> *const ::std::os::raw::c_char; +    pub fn NK_list_devices_by_cpuID() -> *mut ::std::os::raw::c_char;  }  extern "C" {      /// Connects to the device with given ID. ID's list could be created with NK_list_devices_by_cpuID. @@ -601,3 +1105,8 @@ extern "C" {      /// @return 1 on successful connection, 0 otherwise      pub fn NK_connect_with_ID(id: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;  } +extern "C" { +    /// Blink red and green LED alternatively and infinitely (until device is reconnected). +    /// @return command processing error code +    pub fn NK_wink() -> ::std::os::raw::c_int; +}  | 
