Skip to content
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

fix off-by-one in update_client_pin_if_verified() #559

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

DanielCohenHillel
Copy link

The code that validated new PIN length checks if the new PIN is between 4 and 63
bytes long, instead of between 4 and 64 as it should. This could allow an
attacker to decrypt the 64-th byte of an encrypted message without knowing
the shared secret key, assuming he can bypass the HMAC memcmp check (which is
not too likely).

Reasoning:
The authenticator decrypts the given PIN, and a user/attacker can tell if the
given decrypted PIN length is correct or not from the returned error, this is
a padding oracle.
If the check were if the new pin is between was between 4 and 64 this wouln't
be a problem, since 64 is a multiple of the block size (16), and since the
message is padded to block multiples, all 64-byte long new PINs would be
accepted. The next possible length is 80 bytes, and the only way an 80-bytes
new PIN message would be accepted is if the last 16 bytes are zero, which is
impossibly unlikely (2 ^ -16 random chance), so the padding oracle won't give
an attacker anything.
Since the actual check is if the PIN is between 4 and 63, if you send a 64
byte new PIN message, it would be accepted only if the last byte was
decrypted to zero, and fail otherwise.
Since the authenticator uses CBC mode of operation, it is possible the brute-
force the last byte of the previous block (i.e. the 48-th byte) until the
last byte is zero, then you know the last byte is zero, so the decrypted last
byte is the encrypted 48-th byte.

The code that validated new PIN length checks if new PIN is between 4 and 63
bytes long, instead of between 4 and 64 as it should. This could allow an
attacker to decrypt the 64-th byte of an encrypted message without knowing
the shared secret key, assuming he can bypass the HMAC memcmp check (which is
not too likely).

Reasoning:
  The authenticator decrypts the given PIN, and a user/attacker can tell if the
  given decrypted PIN length is correct or not from the returned error, this is
  a padding oracle.
  If the check were if the new pin is between was between 4 and 64 this wouln't
  be a problem, since 64 is a multiple of the block size (16), and since the
  message is padded to block multiples, all 64-byte long new PINs would be
  accepted. The next possible length is 80 bytes, and the only way an 80-bytes
  new PIN message would be accepted is if the last 16 bytes are zero, which is
  impossibly unlikely (2 ^ -16 random chance), so the padding oracle won't give
  an attacker anything.
  Since the actual check is if the PIN is between 4 and 63, if you send a 64
  byte new PIN message, it would be accepted only if the last byte was
  decrypted to zero, and fail otherwise.
  Since the authenticator uses CBC mode of operation, it is possible the brute-
  force the last byte of the previous block (i.e. the 48-th byte) until the
  last byte is zero, then you know the last byte is zero, so the decrypted last
  byte is the encrypted 48-th byte.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant