| Commit message (Collapse) | Author | Age |
|
|
|
|
|
| |
Now that all vendored dependencies have been removed, this change moves
the program's source code from the nitrocli/ directory into the root of
the repository.
|
|
|
|
|
|
|
|
|
| |
This change updates the minimum required version of Rust to 1.35.0. The
motivation for doing so is at least two fold. First, next we want to
bump the nitrokey crate to version 0.4.0 and it requires Rust 1.34.0 as
a minimum. Second, and perhaps more importantly, though, in 1.34.0 a
clippy lint regressed, breaking our pipeline. That is the reason why we
are going to 1.35.0 instead.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change updates the version of the nitrokey crate that we use to
0.4.0-alpha.3. This version is the supposedly last pre-release before
0.4.0, with no further major anticipated changes.
In order to integrate with this new version we have to adjust the way we
connect to a Nitrokey device by funneling those connection requests
through a global manager object. The rationale behind that step being
that the underlying libnitrokey actually cannot handle access of
multiple devices at the same time, and so the manager object is used to
prevent accidental wrong concurrent usage.
Because a device object now effectively keeps a reference to the
manager, we need to provide an additional lifetime to that and derived
objects.
Lastly, the use of a manager is also the reason why the tests had to be
adjusted to no longer accept device objects in their signatures, but
only the respective model for which to invoke the test. That is required
because, as elaborated earlier on, having a device object implies having
taken a reference to a manager (in that case owned by nitrokey-test),
and that reference clashes with the nitrocli code itself attempting to
take the manager. We side step this problem by merely accepting a Model
object, which can be passed around independently of the manager itself,
meaning that nitrokey-test does not need to hold such a reference while
the test is run.
Import subrepo nitrokey/:nitrokey at f150d59410eefdec2ae69b2422906a3d1d88aa07
Import subrepo nitrokey-sys/:nitrokey-sys at 8695e2c762807e033a86c8d03974b686d20cdd72
Import subrepo lazy-static/:lazy-static at b4b2b16aaa79dd7548e288455a0dbe4065bf4e1a
|
|
|
|
|
|
|
|
|
|
| |
This change updates the dependency to nitrokey to version 0.4.0-alpha.2.
In addition to minor interface changes for the get_*_firmware_version
and get_*_retry_count functions, several functions that change the
device state now require a mutable handle to the nitrokey. Hence, this
patch a number of function signatures to accept mutable device objects.
Import subrepo nitrokey/:nitrokey at 34efcfadf1436102e42144f710edabaa2c4b55cd
|
|
|
|
|
|
| |
Since version 0.4.0, nitrokey provides the default admin and user PIN as
constants. This patch removes the constants from nitrocli and uses
nitrokey's constant instead.
|
|
|
|
|
|
|
|
|
|
|
| |
This is patch marks the first step in the process of updating the
nitrokey dependency to version 0.4. In particular, it integrates with
the first alpha version.
The main change on the nitrocli side accompanying the version bump is
that the nitrokey::CommandError got replaced by a more general
nitrokey::Error which includes the former variant.
Import subrepo nitrokey/:nitrokey at d433189caefe6bd6c88da7fbb1d6e9304353eb83
|
|
|
|
|
|
|
|
|
|
| |
The library ultimately taking care of communicating with the Nitrokey
device, libnitrokey, unconditionally expects hexadecimal strings
supplied as part of the configuration of an OTP slot to have an even
number of bytes.
Users should not be aware of this detail and so with this change we take
care of padding the supplied string with a leading zero to make such a
configuration go through without an error.
|
|
|
|
|
|
|
|
|
|
|
|
| |
When reading a secret in ascii or base32 format from the user, we
perform a conversion of the potentially decoded string into hexadecimal
bytes, because that is what libnitrokey expects.
The format string we used in the conversion, however, did not account
for padding with a leading zero for single digit results. E.g., the
newline/line feed symbol '\n', which has a decimal value of 10 would
result in the string 'a' being produced, whereas '0a' would be the
correct result.
This change corrects the format string to fix this problem.
|
|
|
|
|
|
|
|
|
|
| |
Similar to the with_*device functions introduced in a previous change,
this change introduces a with_password_safe function that is a short
hand for opening the Nitrokey, retrieving a handle to the password safe,
and invoking a user-supplied function on it.
This function will allow us to prevent life time inference problems
caused by passing around a PasswordSafe object, which will contain an
additional reference (and with that, lifetime) in nitrokey version 0.4.
|
|
|
|
|
|
|
| |
With an upcoming change we will require an ExecCtx in one of the
op functions passed to the with_* and try_with_* functionality. To
allow for such cases, this change adjusts the signature of those
functions to provide a reference to such a context.
|
|
|
|
|
|
|
|
|
|
|
| |
This change introduces a new trait, TryInto, to the crate. In the future
this trait will allow us to keep a flexible set of error result types
from the various try_with_* functions, which use a certain nitrokey
error variant to check for the entry of a wrong secret.
Note that while a TryInto trait exists in Rust's standard library, that
was not found to be helpful because we have no way to define it for
nitrkey crate's error type. Because of that, we will always have a
mismatch between our internal error and std::convert::Infallible.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The upcoming nitrokey 0.4 release changes the way a device handle can be
acquired, requiring a manager instance for doing so in an attempt to
prevent users from opening multiple sessions (which is not something
that libnitrokey supports).
A straight integration of the reworked API surface into our program
would severely complicate the architecture because of the additional
requirement of keeping a manager object around while a device is being
used.
To make the program more amenable to those changes in nitrokey, this
patch reworks the way we interact with a device handle: instead of
passing the device object around we pass in the functionality making use
of it in the form of a function. In more concrete terms, instead of
retrieving a device handle via get_device() we now have a with_device()
function that takes care of opening the device and then passing it to a
user-provided function.
|
|
|
|
|
|
|
|
|
| |
The try_with_* and authenticate functions accept a user-supplied
function to work with. Currently this function is declared as Fn. That,
however, is unnecessarily restrictive.
With this change we declare said function an FnMut instead, which allows
it to potentially capture variables from its environment in a mutable
manner.
|
|
|
|
|
|
|
|
| |
For functionality that explicitly works with the storage device we emit
an error message stating that a "Nitrokey Storage" device could not be
found. When the user chooses the model using the -m/--model argument
that is not the case.
With this patch we adjust the error message printed.
|
|
|
|
|
| |
This patch replaces two cases where we use Result::or_else over the more
idiomatic (and shorter) Result::map_err for converting errors.
|
|
|
|
|
|
|
| |
This change adds support for changing the read-write mode of the
unencrypted volume. To do so, we introduce a new top-level command,
unencrypted, with a new subcommand, set, that accepts the new mode of
the volume.
|
|
|
|
|
|
|
|
|
| |
This change rewords the error message that is emitted if the lock
command fails. The old message was incorrectly stating a problem with
the retrieval of the device's status.
While at it, also slightly rephrase the description for the hidden
command to be more in line with that of the other storage commands, and
replace lowercase 'nitrokey' with a capitalized one in a few comments.
|
|
|
|
|
|
|
|
| |
This change is the last step in the process of restructuring the storage
command. In particular, now that functionality pertaining hidden volumes
has been moved out into a dedicated top-level command, it renames said
command to encrypted, because dealing with the encrypted volume is the
only functionality it provides.
|
|
|
|
|
|
| |
This patch marks the next step in the process of restructuring the
storage command. Specifically, it promotes the storage hidden subcommand
to a top-level command, hidden.
|
|
|
|
|
|
|
|
| |
In an attempt to rework the structure of the storage command to better
accommodate future requirements for allowing to change the read-write
state of the unencrypted volume (as well as potentially the encrypted
one), this change removes the storage status subcommand and merges its
output into the storage command.
|
|
|
|
|
|
|
|
|
|
| |
When a PIN is changed using the pin set command, the last action is to
confirm the operation with the previously used PIN. This step will cause
this PIN, which is now stale and no longer valid, to be cached, which in
turn can cause follow up command using the same PIN type to use this
wrong cached entry for authentication.
To fix this problem, this change explicitly clear the PIN entry from the
cache after the PIN has been changed.
|
|
|
|
|
|
|
|
|
|
|
|
| |
So far we have cached secrets in gpg-agent(1) whenever that made sense
to do (i.e., for the two PINs in most contexts but not for passwords).
While there is reason to believe that such caching is desired by the
majority of users, not everybody has a use for it.
To give users an opportunity to opt out of such caching, this change
introduces a new environment variable, NITROCLI_NO_CACHE, that, when
present in the environment, instructs the program to bypass the cache
for all operations that require a secret and to instead inquire such
secrets each time they are needed.
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Nitrokey devices do not check whether a PWS slot is programmed
before accessing it (upstream issues [0] [1]). Until this is fixed in
the firmware, we have to manually check the slot status in pws get. This
could have been done in libnitrokey or the nitrokey crate, yet this
would lead to unnecessary commands if we check multiple fields of a slot
at the same time.
[0] https://github.com/Nitrokey/nitrokey-pro-firmware/issues/56
[1] https://github.com/Nitrokey/nitrokey-storage-firmware/issues/81
|
|
|
|
|
|
| |
After performing the factory reset, we also build the AES key so that
the device is fully usable. Due to timing issue, we have to add a delay
between the factory reset and building the AES key.
|
|
|
|
|
|
|
| |
This change adds a test for the creation, opening, and closing of a
hidden subvolume. In order to support that in a non-interactive fashion,
we introduce and honor the NITROCLI_PASSWORD environment variable, that
prevents an interactive password query.
|
|
|
|
|
|
|
|
|
| |
With this change we implement the storage hidden subcommand. We support
creation, opening, and closing of hidden volumes.
Note that the opening of a hidden volume automatically closes any opened
encrypted volumes and vice versa. To that end, we force file system
level caches to disk even from the storage open and storage hidden open
commands.
|
|
|
|
|
|
| |
Various functions in the pinentry module contain an arguably redundant
'_pin' suffix in their name. Examples include inquire_pin and clear_pin.
This change removes this part from their names.
|
|
|
|
|
|
|
|
|
| |
The functionality we have in place for choosing a PIN can arguably be
moved into the pinentry module: it can be considered logic directly
related to working with PINs or secrets and that has no dependencies to
unrelated modules of the program.
This patch moves the choose_pin and check_pin functions into the
pinentry module.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The application supports multiple devices both plugged in at the same
time as well as when used after the other. However, the GPG cache ID we
use for storing and retrieving the respective PIN is effectively a
constant. This constraint can cause problems when devices have different
PINs, as the PIN of a previously plugged in device may be reused for an
operation on a different one.
To resolve this problem this change adds the respective device's model
and serial number to the cache ID. As each serial number is supposed to
be different, this will ensure that the correct PIN is used for each
device. With this change we also show the model and serial number of the
currently used device in the pinentry dialog.
Note that because we do not store the serial numbers of all previously
plugged in devices, the pin clear command will only clear the PIN for
the currently plugged in device. If a user wants to make sure that a
cached PIN is cleared, the pin clear command should be invoked before
unplugging the device.
|
|
|
|
|
|
| |
This patch implements From<&str> for Error so that we can use
Error::from(s) as a shorthand for Error::Error(s.to_string()). It also
replaces Error::Error with Error::from where possible.
|
|
|
|
|
|
|
|
|
| |
nitrokey 0.3.1 introduced the connect_model function that connects to a
specific model given by an enum variant and returns a DeviceWrapper.
This new function allows us to remove the manual selection of a
connection method from the get_device function. We only have to
implement From<DeviceModel> for nitrokey::Model to be able to convert
our model enum to nitrokey's model enum.
|
|
|
|
|
|
|
|
|
|
|
|
| |
So far we have taken all nitrokey::CommandError objects and put them in
formatted form into the Error::Error variant. What we really should do,
though, is to preserve the original error, with the additional context
provided by the caller, and report that up the stack directly. Doing so
has at least the benefit that we are able to check for expected errors
without hard coding the textual representation as maintained by the
nitrokey create.
This change refactors the code accordingly and adds two tests for such
expected error codes.
|
|
|
|
|
|
|
|
|
|
|
| |
The second source of interactivity comes from the pin set and pin
unblock commands, which also inquire with the pinentry module to ask the
user for a PIN.
This change adjusts the two commands to honor the PINs as available in
the command execution context. It also updates the documentation
to reflect the availability of the newly introduced and honored
environment variables NITROCLI_ADMIN_PIN & NITROCLI_USER_PIN as well as
NITROCLI_NEW_ADMIN_PIN & NITROCLI_NEW_USER_PIN.
|
|
|
|
|
|
|
|
|
|
| |
The try_with_pin_and_data function is used by many commands to ask the
user for a PIN in an interactive manner. Because we do not want to have
any interactivity in our tests, we should honor the command execution's
admin & user PIN fields from this function, if set.
This change adjusts the function to honor the command execution
context's admin & user PIN, if set. In order to do so it also adjusts
the callers to hand through the context to begin with.
|
|
|
|
|
|
|
|
|
|
| |
The try_with_pin_and_data function is a fairly complex beast. Part of
that complexity stems from the returned Result value, whose error part
not only contains the error but also the previously passed in data. As
it turns out, though, this data as returned is never actually consumed
by any client.
Hence, this change simplifies the logic slightly by removing all the
additional complexity that this tuple return entailed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The inquire_pin function of the pinentry module used to return a vector
of bytes, as that is what is ultimately read from the gpg-agent process.
All clients of this function, however, work with a string and, hence,
convert this vector into a string.
As it turns out, for better or worse, the pinentry::parse_pinentry_pin
function (which produces the result of inquire_pin) internally already
works with a string but then converts it back. That is both not useful
and a waste of resources.
This change adjusts both functions of interest to simply return a String
object instead, removing the need for conversions at the clients. While
at it, the patch also removes the need for a bunch of unnecessary
allocations caused by sub-par parameter type choice.
|
|
|
|
|
|
|
|
|
|
|
|
| |
In the past we have used the term 'passphrase' to refer to the data
retrieved through the pinentry module and that terminology has permeated
the commands module as well.
However, on the Nitrokey side we talk about PINs most of the time
(despite a lack of an requirement for being actual numbers). In an
attempt to unify terminology a bit more, this change renames all
occurrences of the term 'passphrase' with PIN. This renaming has the
nice side effect of making the code more concise because the latter is
much shorter than the former.
|
|
|
|
|
|
|
|
|
| |
At some point in the past nitrokey::CommandError was lacking an
implementation of the fmt::Display trait. Hence, we fell back to
printing these errors in debug format.
Since version 0.2.0 of the crate fmt::Display is implemented for these
errors. With this change we use it to report more user-friendly error
messages.
|
|
|
|
|
|
|
|
|
|
|
| |
This change continues and concludes the effort of using customizable
stdio channels for output of data from the program. It does so by
replacing the standard println macro with a custom one that outputs the
data to the supplied context's stdout object.
Because this object is injected from the main function, it will be
possible for tests invoking this function to supply custom Write objects
that can buffer this data and make it available for verification
purposes.
|
|
|
|
|
|
|
|
|
|
| |
So far we have used a read-only reference to a command execution
context and passed that through to all consumers. However, with upcoming
changes we would will need to provide data that can be modified. This
change adjusts all function signatures accordingly. Also, because the
ExecCtx will contain references itself in the future, this change
already introduces a lifetime for the struct, as that also requires
signature adjustments.
|
|
|
|
|
|
|
| |
Many applications display OTP secrets in the base32 format (according to
RFC 4648).
This patch adds base32 as a possible value for the --format option to
the otp set subcommand.
|
|
|
|
|
|
|
| |
This patch refactors the prepare_secret function by renaming it to
prepare_ascii_secret and by moving the formatting of a bytes slice as a
hex string into the format_bytes function. This prepares for adding a
the base32 format in a future patch.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch introduces the -f/--format options for the otp set
subcommand to specify the format of the OTP secret. Previously, the
default format was hexadecimal and ASCII format could be selected using
the --ascii option. The new --format option takes the argument hex or
ascii, defaulting to hex, and replaces the --ascii option.
This patch does not remove the --ascii option but marks it as
deprecated. It may not be set together with --format, and a warning is
printed if it is set. It should be deleted with the next minor release.
This patch prepares the addition of a new format, base32.
|
|
|
|
|
|
| |
This change updates the nitrokey crate to version 0.3.0.
Import subrepo nitrokey/:nitrokey at 3593df8844b80741e2d33c8e5af80e65760dc058
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch adds the -m/--model option that can be used to restrict the
device model to connect to. Per default, nitrocli connects to any
available Nitrokey device. If this new option is set, it will instead
only connect to devices of the given Nitrokey model.
We introduce a new struct DeviceModel instead of using
nitrokey::DeviceModel to make sure that the command-line options are
parsed properly. On the long term, we should add a connect_model
function to the nitrokey crate to make the connection code easier.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change introduces a new option, -v/--verbose, that can be used to
increase the log level of libnitrokey. The option can be supplied
multiple times, with each occurrence increasing the verbosity of the
logging.
On the implementation side, the option is set as part of connecting the
device (piggy-backing on the previously introduced command execution
context), although it describes global state that strictly speaking could
be set anywhere. It is bad enough that libnitrokey just prints log
messages to stderr (and does not accept a file handle) and that it does
not track the log level on a per-device basis, but we don't want setting
of global state from arbitrary locations inside the program. Instead,
let's do that along with what pretty much is the first call into
libnitrokey anyway: the connection to the device.
|
|
|
|
|
|
|
|
|
| |
In the future we will need the ability to pass additional state that is
deduced from arguments or elsewhere into the commands module. To enable
such scenarios, this change introduces the concept of a command
execution context. Such a context can store more or less arbitrary data,
and the args module will take care of passing it through to the
individual commands.
|
|
|
|
|
|
|
|
|
|
|
|
| |
In order to flush file system level buffers to disk we use the sync
function. The way we made this function known to the crate was by
explicitly declaring it as extern "C" and linking against libc. However,
given that we already (indirectly) depend on libc through the nitrokey
crate (and that is unlikely to change) we may as well make libc a direct
dependency and invoke the function through the crate.
Given that the libc crate is available for a variety of platforms, it
seems likely that its approach to interfacing with the system libc
library is more portable than our hand rolled version.
|
|
|
|
|
|
|
|
| |
With the recent update of the nitrokey create the nitrokey::CommandError
enum has become trivially copyable. Hence, there is no more point in
passing a reference to it to the get_error function.
To that end, this change adjusts the signature to accept an owned value
instead.
|
|
|
|
|
|
| |
This patch implements the lock command that locks the password safe and,
on the Nitrokey Storage, the encrypted volume. See issue #18 for
details on the locking mechanism.
|