Monday, August 22, 2011

Master password in Fennec

Last week we finally fixed the master password bug 592772. It had one of the longest history: 130+ comments, and 12 versions of the patch! A funny thing about it is that the final patch is actually almost the same as the very first version, except for some minor tweaks.

OK, some background. The need for this functionality had arisen when we implemented support for SD card, specifically - moving the user profile to an SD card when application is moved there. It was a wanted feature, because the user profile may grow to tens of megabytes (37MB was mentioned), which is quite a lot for many phones. Mike Beltzner formulated this pretty well in his comment:
While I understand that instinct, and further understand that the newer generations of Android phones are not as limited as the Nexus One and its contemporaries in terms of the internal/SD memory split, I can also tell you that as a Nexus One owner, this really does prevent me from using Fennec as intended. My choices are:
- Fennec + Sync and a limited number of other applications
- Fennec w/o Sync and my applications
- No Fennec and my applications
The feature, while helping the users to free some internal phone memory, had a big drawback - it made all the user data fully exposed and easily accessible, as the SD card uses FAT file system and doesn't have any protection. So if the card is lost or stolen, someone could get access to all personal information in the Firefox user profile, most importantly - all the stored passwords for the web sites.

To avoid that the important data had to be encrypted. Desktop Firefox already has such a feature called "master password". The key*.db file in the user profile could be encrypted with the password, so when a web site login data needs to be saved, or Firefox detects it can auto-fill the login information on a site, the user is prompted to enter "the master password for the Software Security Device".

The original goal of the master password bug 592772 was just to implement the same functionality - basically just have a preference, and prompt the user for a password similar way how it's done on desktop. But a simple prompt had some UX issues. It could come up several times in a row when more than one site requiring access to the password database was open, or in some specific cases, like in the bugs 624552 and 624570. So there came up an idea to implement a new feature, later called "auto-password". The idea was pretty simple: use the same internal master password functionality, but do not ask the user to enter the password, but rather generate it automatically, and store in the system, so the data would be protected the same way as on desktop, but without the "UX hell".

I did some research on the ways how to store the generated password, and implemented a prototype, which used AuthenticationService and an Authenticator - similar way how it is done for all Android applications logging the user in like Gmail, Facebook, etc, but unlike those, stored the password locally rather than on the server. But it wasn't the best way. Apparently the current version of Android does not have any system-wide secured storage, which could be used for our purpose, so the only place to store the password was the internal application data directory. It revealed one more important issue. Our application was marked as debuggable in Android manifest file, to make debugging easier, obviously. But that flag made all application data readable, and accessible by other applications, and through USB connection. This bit was fixed in a separate bug, turning off the debuggable flag in the official builds.

The unnecessary complexity of the authenticator approach implementation, where all its functionality was not really used, and some minor issues related to it (for example, our authentication service that was used only internally, was visible in the system settings, which we didn't really want) lead to a simplified approach to store the generated password in the application's SharedSettings, which, despite the name, are private to the application, and with debuggable option off, are not accessible by the others. Then there was another modification, with the password stored in a simple file inside the Firefox data directory. This was done to avoid an extra call to Java layer through Android bridge, as the latest implementation was all in the platform code.

The last approach to the auto-generated master password feature combined the auto-password service and the original UI preference, to allow the security-conscious users still have their own master passwords, which were not stored anywhere on the device. The feature passed the security review, with the comments that it might be useful not only on Android, but on other systems as well, where the generated password could be securely stored in a system key ring. But later during the last code review more concerns were raised by Brian Smith, with an alternative suggestion: instead of implementing a whole new auto-password feature, which would encrypt the passwords database and store the key in internal memory, just keep that passwords database itself in the same internal memory, by splitting the user profile. This was actually discussed before, but it wasn't clear how difficult it would be to implement the profile splitting.

During another security review, for the whole approach to store user profile data on the SD card, those concerns and possible ways to resolve them were discussed, and the final decision was to drop the auto-password feature, look into the profile splitting possibility, and implement the master password UI, as it was originally planned.

That was the final implementation submitted, which will be included in the next release: just a master password preference, similar to the one on desktop. The auto-password feature was moved to a separate bug 678412, with a "work-in-progress" patch attached.

No comments: