-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pin should be cleared if it is known to be wrong #85
Comments
Interesting point, thanks for the report! The problem is that we cannot be sure whether this error is caused by the PIN or by some other string. For example, when changing a PIN, this error could be caused by the original PIN or by the new PIN. I can think of three possible fixes:
|
I think there may be multiple bugs here.
So I checked what void NitrokeyManager::enable_password_safe(const char *user_pin) {
//The following command will cancel enabling PWS if it is not supported
auto a = get_payload<IsAESSupported>();
strcpyT(a.user_password, user_pin);
IsAESSupported::CommandTransaction::run(device, a);
auto p = get_payload<EnablePasswordSafe>();
strcpyT(p.user_password, user_pin);
EnablePasswordSafe::CommandTransaction::run(device, p);
} which notably does two things. So checking class IsAESSupported : Command<CommandID::DETECT_SC_AES> {
public:
struct CommandPayload {
uint8_t user_password[20]; <------------ spurious user_password buffer size
...
}; compare that to class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> {
public:
struct CommandPayload {
uint8_t user_password[30]; <-------------- ten bytes more buffer?!
...
}; And in fact its the template <typename T>
void strcpyT(T& dest, const char* src){
if (src == nullptr)
// throw EmptySourceStringException(slot_number);
return;
const size_t s_dest = sizeof dest;
LOG(std::string("strcpyT sizes dest src ")
+std::to_string(s_dest)+ " "
+std::to_string(strlen(src))+ " "
,nitrokey::log::Loglevel::DEBUG_L2);
if (strlen(src) > s_dest){
throw TooLongStringException(strlen(src), s_dest, src); <---- password does not fit into 20 byte buffer
}
strncpy((char*) &dest, src, s_dest);
} |
Ultimately I'd say that this does sound like the best approach. If all commands used in |
The IsAESSupported command struct has a 20 byte buffer size for storing the user password. That is in contrast to, say, the EnablePasswordSafe struct which uses a 30 byte buffer. Such a smaller buffer can cause string length errors to be emitted for a legitimate user PIN as has been found as part of the investigation for d-e-s-o/nitrocli#85. That is, the nitrokey allows for setting a user PIN of 21 characters. Retrieving an OTP using such a PIN works fine, whereas inquiring the PWS status does not, as it first tries to cram the supplied password into 20 characters, which fails. This change increases the buffer size in the IsAESSupported command struct to 30 bytes.
I doubled checked that this is indeed a problem and fixed it in |
Thinking about it again, this would not solve the underlying problem: If there is a library error before the command is sent to the device – in this case, an overlong password, but in other cases, it could also be an invalid OTP slot etc. –, we don’t know if the password is correct and should not cache it. It might be possible to solve this issue differently: In |
I am not sure I necessarily follow the conclusion you are drawing ("should not cache it"). The way I see it there are two main cases to consider:
With your proposal, on the other hand, we would ask the user again for the password had it not been cached so far; while not a correctness issue, I'd say that is at least somewhat annoying. So my take would be that we would need to verify that the retry counter would indeed be left unchanged if other inputs are invalid. If that is the case, I'd still be of the opinion that your original proposal is the most appealing. If that is not the case, I'd argue that's a firmware bug, but I'd be happy to be convinced otherwise. Did I overlook something in this assessment? |
Did I overlook something in this assessment?
What led me to a different conclusion is the fact that the next attempt
to use the passphrase does not necessarily happen directly after
entering the passphrase. (I actually had this case a few days ago.) So
you might get some library error, walk away and come back after 9:59
minutes, just to get a Wrong Password error without even entering a
passphrase.
In the best case, this is really confusing. In the worst case, this is
the first step to locking your Nitrokey device.
|
You are free to set a 9:58 minute TTL for the cache ;-) But more seriously, that just sounds like the nature of caching to me. In any case, given that we disagree, and this is a tiny issue with (in my opinion) no correctness issues on either side of the fence, let's just roll with either. I am happy to accept your proposed |
Hi!
I use 20 char pin and made a typo by entering 21 chars, so I get:
$ nitrocli pws status Could not access the password safe: The supplied string is too long
If I try to run this command again (or any other command requiring pin), I get this message again and no way to enter pin anew until I clear the cache manually using 'nitrocli pin clear'.
I think that in cases when pin is obviously wrong (like too long string) it should be purged from cache automatically.
The text was updated successfully, but these errors were encountered: