Monday, 16 June 2014

Lenovo S650 with android 4.4.2 and google authenticator (Part 2)

The first part of the series documents the process of upgrading Lenovo S650 from the original 4.2.2 ROM to the new VibeUI ROM which is based on KitKat 4.4.2 and MyUI. This post lists a few issues I ran into during the first days of using the new ROM.

Google Authenticator issues

I have been using Google Authenticator's time based one-time passwords as a second authentication factor a few very critical applications for a rather long time. After my recent update, I noticed that I was unable to log in to a critical service as the verification code was rejected. First I thought there must be some sort of time synchronisation issue, so I synchronised the clock from within Google Authenticator application but my authentication attempts were being rejected. I deleted the configuration and re-imported the secret key, however, this did not help.

Needless to say, after a few attempts I was rather nervous as I was under time pressure and worried about my stash... The same version of the application, 2.49, was working flawlessly before the upgrade so I was initially rather sure the error is somewhere on my side. Rather than falling into panic, I quickly searched and found my old Samsung Galaxy Y (android 2.3.6), where the same version, 2.49 was already installed, deleted the old configuration and carefully typed in the base32 representation of my secret key, making sure I do not mix up 0 with O and 1 with I respectively. (At this point I would like to draw attention to Base58 encoding which has an alphabet built with humans in mind, and does not contain characters which are easy to mix up...)

To my surprise I could log in using Google Authenticator on the Samsung device. After taking care of my time sensitive task and calming down, I continued searching for the root cause. The RFC6238 TOTP security token calculation used in Google Authenticator is very simple and publicly available, it only depends on the following two inputs:

  • The shared secret. First I double and triple checked the shared secret was the same on both devices. I gathered definitive evidence by peeking into the SQLite database located at /data/data/com.google.android.apps.authenticator2/databases/databases first via a hex editor, then via sqliteman on my thinkpad. Here is the catch, one can only do that on a rooted device. And definitely, from time to time, one might find himself in a situation where root access is needed for a legitimate purpose...
  • The number of 30 second periods elapsed since the Unix epoch which is based on system time. Although I have synced both devices and the timezone was also the same, I kept getting different tokens on the two devices. I experimented with the timezone settings, changing locale settings and manually setting different timezones but it did not help.

I decided to study the source code - the algorithm is rather simple and both inputs were known to be the same, yet the result were different. The source did not contain any magic, but at the same time I noticed the latest tag in the source repository was 2.21 whereas on both of my devices I had 2.49 - that was at least a bit suspicious. On the project page I found the following disclaimer: "This open source project allows you to download the code that powered version 2.21 of the application. Subsequent versions contain Google-specific workflows that are not part of the project."

I went on and found FreeOTP, a real open source implementation forked from Google Authenticator 2.21, maintained by RedHat. After taking a look at the source, I have installed it onto my S650 and imported my shared secret. Success. Open source rules. I uninstalled Google Authenticator.

Having found a working, very nice, true open source alternative, I have lost motivation to investigate further by decompiling Google Authenticator - unfortunately, I am rather busy these days with my primary duties. My hypothesis, without any proof, is the following: Version 2.49 of Google Authenticator might include some JNI based crypto-acceleration, or something else outside of the Java/Dalvik core libraries, that is not part of any standard, is not documented, therefore not included or works a bit differently in Lenovo ROM. Please leave a comment if you can prove or confute it.

Read on for other issues I encountered in the first few days. Of course, resolution or at least a workaround is provided where applicable.

3 comments:

  1. I have the same problem on my Lenovo S650. Thank you for link to FreeOTP.

    ReplyDelete
  2. https://code.google.com/p/google-authenticator/issues/detail?id=396

    ReplyDelete
    Replies
    1. Nice catch & code-around the issue. It might look like a shame that something as basic as java.lang.Math.pow() is not consistent across devices, however, I believe people should not use java.lang.Math.pow() in crypto code at all - nor any other code where precision matters. There is java.lang.StrictMath which by specification is required to provide "IEEE 754 core" compatible behavior for the following:

      sin, cos, tan, asin, acos, atan, exp, log, log10, cbrt, atan2, pow, sinh, cosh, tanh, hypot, expm1, and log1p

      Delete