| Commit message (Collapse) | Author | Age |
|
|
|
|
|
|
|
|
|
| |
With Rust 1.35 we get compile errors due to doc comments that are added
to macro invocations but not actually included in the expanded output.
The rustc wrongly assumes that we want to document the resulting code
and not just provide details about the invocation itself.
This change explicitly allows for those cases. Alternatively we could
have "downgraded" the doc comments to normal comments or removed them
altogether. There is little difference between those alternatives.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
With the required interface for secrets well defined, this change
introduces a second secret type in addition to PINs: passwords. Similar
to a PIN, a password can contain pretty arbitrary characters but
passwords can be retried repeatedly, whereas PINs cause a lockout after
a certain number of failed attempts.
Our first use case for passwords will be for hidden volumes. For those,
we do not want to gpg-agent to cache entries and so a password entry
indicates that it is not to be cached through the previously introduced
mechanism for optional caching.
|
|
|
|
|
|
|
|
| |
Another commonality between a password and a PIN is that they typically
both have a minimum length.
To accommodate for this requirement, this change introduces another
method to the SecretEntry trait that represents the secret's minimum
character length.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, when we enter a secret (i.e., a PIN) through the pinentry
module, this PIN will automatically be cached and not asked from the
user again on subsequent inquiries. However, caching may not always be
desired. For the upcoming support of passwords used in conjunction with
hidden volumes, we do not want any caching because different passwords
can be entered for different volumes and the user's intention is not
clear until a password has actually been entered.
To accommodate this use case, this change modifies the signature of the
SecretEntry trait's cache_id method to return an optional cache ID. If
none is returned, caching of the entered secret is disabled.
|
|
|
|
|
|
|
|
|
| |
We do not know what kind of data future implementers of the SecretEntry
trait may want to return. For all we know these could just be static
strings, in which case the forced conversion into a String by virtue of
the return type is wasteful.
To be more flexible in the future while gaining some consistency, this
change makes all those trait's methods return a Cow object instead.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now that we have introduced the notion of a secret abstracting over
whether something is a PIN or a password in terms of terminology, we
need to define what makes a secret in code. From the pinentry module's
perspective, the commonality between the two is that they both can be
entered through a dialog containing a prompt and a description, and they
can be cached.
This change introduces a trait, SecretEntry, that defines methods
representing those properties. Right now only the existing PinEntry
struct implements this trait.
|
|
|
|
|
|
|
|
|
|
|
|
| |
In the past we have worked solely with PINs. PINs in our (or rather, the
Nitrokey's) sense are not necessarily numbers but they can be reasonably
short in length, because they can only be retried a limited number of
times.
In the future, however, we will introduce the notion of a password,
which does not carry such a restriction.
The commonality between the two is that they are secrets and so with
this change we refer to secrets -- rather than PINs -- in places where
both passwords and PINs can conceptually be used.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
This change continues the effort of auto-generating more of the help
text content by extending the logic to optional arguments. We make use
of the fmt_enum macro to format the description of the argument with the
available variants (as well as the default, if any) interpolated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
The implementation of the fmt::Display trait for the PinType is
seemingly unused. Remove it.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
This change implements the pin set command which can be used to change
a Nitrokey's user or admin PIN.
|
|
|
|
|
|
|
| |
This patch implements the pin unblock command that unblocks and resets
the user PIN. The name unblock is chosen over libnitrokey's unlock to
be consistent with the GnuPG terminology and to avoid confusion with the
unrelated lock command.
|
|
|
|
|
|
|
| |
The mode argument is used to specify the context of the pinentry dialog:
querying an existing passphrase or prompting the user to choose a new
PIN. It is used to choose a description and to decide whether to show a
quality bar that measures the password strength.
|
|
|
|
|
|
| |
Currently, we only clear the user PIN if clear is called. This patch
changes the clear command to also clear the admin PIN as we will start
to use the admin PIN in upcoming patches.
|
|
|
|
|
|
|
| |
Spaces in the arguments for gpg-connect-agent’s `GET_PASSPHRASE` command
have to be esaced using a plus sign. Somehow this was missing for the
prompt argument. This patch adds escaping for the prompt so that the
pinentry dialog is displayed correctly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An automated code formatter can help tremendously in reducing the amount
of cognitive energy wasted on thinking about the "best" formatting of
code as well as the number of nitpicks reviews typically get -- the
format is machine checked (and enforced) and there is usually little to
no discussion about the validity.
To reach the goal of having such automated enforcement, we want to run
the rustfmt tool as part of the CI pipeline. With rustfmt having reached
1.0 recently, the believe is that by now the formatting is reasonably
stable and usable for this purpose.
In that light, this change formats the code using rustfmt and prepares
for such an automated style check.
|
|
|
|
|
|
|
| |
After the switch to using the nitrokey crate for communication with the
device, we have to warnings standing in the way of enabling clippy
unconditionally for the nitrocli crate. This change fixes those two
warnings.
|
|
|
|
|
|
|
|
| |
Given that development is picking up speed again we should accept all
the help we get from the compiler to catch issues as early as possible.
To that end, this change enables more lints for the program. As "usual",
lints that are suspected to potentially change in future versions of
Rust are reported as warnings and not errors.
|
|
|
|
|
|
|
|
| |
In preparation for the switch to using Rust 2018, this change enables
the rust_2018_compatibility lint. Along with that enablement we fix the
warnings emitted by it, which evolve around the module system changes
Rust has gone through and that require us to prefix initial uses of
crate local modules with "crate".
|
| |
|
|
|
|
|
|
|
|
| |
Currently, the pinentry module only supports querying the user PIN. The
Nitrokey devices also have an admin PIN. This patch adds support for
querying multiple PIN types to the pinentry module. While this is
currently not used, it will be needed to add support for administrative
commands like unlocking the device or changeing the user PIN.
|
|
|
|
|
|
|
|
|
| |
Currently, the error message for a wrong password is printed to the
standard output. Yet the standard output might not be visible to the
user if they are using the curses frontend for pinentry. Pinentry
already supports displaying an error message in the passphrase prompt.
This patch moves the error message from the standard output to the
pinentry prompt.
|
|
|
|
|
|
|
|
| |
The GnuPG documentation [0] refers to the GET_PASSPHRASE arguments as
“error message”, “prompt” and “description”. This patch changes the
names of the constants for these arguments to match the documented names.
[0] https://www.gnupg.org/documentation/manuals/gnupg/Agent-GET_005fPASSPHRASE.html#Agent-GET_005fPASSPHRASE
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch adds the application name (nitrocli) and the type of the
requested PIN (user PIN) to the cache ID user with pinentry to conform
with the GnuPG documentation [0]:
> By convention either the hexified fingerprint of the key shall be used
> for cache_id or an arbitrary string prefixed with the name of the
> calling application and a colon: Like gpg:somestring.
[0] https://www.gnupg.org/documentation/manuals/gnupg/Agent-GET_005fPASSPHRASE.html#Agent-GET_005fPASSPHRASE
|
|
|
|
|
| |
The clippy tool has a couple of suggestions on how to improve the code.
This change applies them to the project's code base.
|
|
|
|
|
|
|
|
|
|
| |
When a wrong password is entered when attempting to open the encrypted
volume the nitrokey will report that in the form of an error. In such a
case we should retry the operation after asking the user for the
corrected password.
This change implements this logic. Note that because we use gpg-agent
for the PIN inquiry and because it caches passwords by default we must
make sure to clear the cache before retrying.
|
|
|
|
|
|
|
| |
With this change we assemble a HID feature report and send it to the
nitrokey device. Feature reports are the objects used for sending
commands to the nitrokey. We create two different reports for
opening and closing of the encrypted volume.
|
|
We do not want to roll our own infrastructure for entering a password
(or PIN) securely, as there are existing providers of such
functionality. gpg-agent, which uses pinentry for this very purpose, is
such a program and we can safely assume to be present because we use it
with the smartcard part of the nitrokey.
This change introduces a new module, pinentry.rs, that provides the
means to invoke gpg-agent to ask the user for a PIN and to parse the
result. Using gpg-agent like this has two advantages that other
solutions do not necessarily provide: first, because we use gpg-agent
anyway it's pinentry configuration is as the user desires it and, hence,
the integration appears seamless. And second, the agent caches
pass phrases which alleviates the need for repeated entry should the
credential be required again.
|