Nitrokey / nitrokey-pro-firmware

Firmware for the Nitrokey Pro device
GNU General Public License v3.0
118 stars 21 forks source link

maximum date of TOTP? #36

Closed jans23 closed 5 years ago

jans23 commented 7 years ago

In reference to this issue for Nitrokey Storage, the maximum TOTP date for NK Pro should be checked.

szszszsz commented 6 years ago

AFAIR Pro stores its date in 64 bit POSIX seconds (which covers next 1000 years). To confirm and check how the data is sent in protocol.

szszszsz commented 5 years ago

Nitrokey Pro passes the 64-bit tests for TOTP time setting and code generation. Related test: https://github.com/Nitrokey/libnitrokey/blob/3eb4856ed8c9a5a8179679f2432c01d382a9c07a/unittest/test_pro.py#L436-L458

Closing as question.

szszszsz commented 5 years ago

B. Pro v0.10+ (to be released as v0.11; current master): Code for TOTP looks almost the same as in Storage version. All time-related variables are 64 bit. Value is calculated in [5]. Before that it routed from [6].

Tests show that device response is same as with the Python library, but unexpectedly only until using time in 60 bits (with value 30 as a TOTP period). Doubling period allows to use 61 bit time value, which sounds, like the window counter would be the limiter (counter = time/period; 55 bits for a successful use -> log₂ ((2^60)÷30)). This variable is 64-bit, and as such is passed to the hmac-sha1 calculation. Perhaps not all bits are taken into account due to hmac-sha1 implementation, or algorithm itself. Even 55 bits will suffice though [7] (assuming period=1), so there is no need to pursue this in practice.

I need yet to see, whether the device is off with the calculations, or rather the library (used as a ground of truth), or both - in case both device and the Python OTP library would give wrong results.

[5] https://github.com/Nitrokey/nitrokey-pro-firmware/blob/master/src/hotp/hotp.c#L158 [6] https://github.com/Nitrokey/nitrokey-pro-firmware/blob/master/src/hotp/hotp.c#L686 [7] IPython3 session:

In [10]: datetime.datetime.fromtimestamp(2**31-1)
Out[10]: datetime.datetime(2038, 1, 19, 4, 14, 7)

In [11]: datetime.datetime.fromtimestamp(2**55-1)
ValueError: year 1141709097 is out of range

In [12]: datetime.datetime.fromtimestamp(2**32-1)
Out[12]: datetime.datetime(2106, 2, 7, 7, 28, 15)