I am writing an application to generate OTP codes for two factor authentication where I need to securely store data locally. This data must be secure from both the owner/user as well as intruders. I have been thinking of encrypting the data, but the key to that data is also stored on the mobile device. The application will not access the internet. It just displays a code that changes over a given time interval, similar to an RSA SecurID token. The data to be stored is the token key and the key to decrypt it. I have read about possible solutions that it may be possible to store this information on the SIM card or other secure store on the device. What are industry best practices for such a scenario?
The important point is that you cannot hide secrets in software: if some software runs on the hardware owned by the attacker (here, the user and his smartphone), then the attacker can reverse-engineer the application code and extract the secret. If it was possible to protect software from that, then there would be no software or video piracy. Media industry would be very interested; they have looked high and low for a solution, and spent a lot of money on the subject, and did not find anything really robust.
So you need tamper-resistant hardware, i.e. hardware which will prevent reverse-engineering. In a smartphone, this indeed points at the SIM card: smart cards are, by design, tamper-resistant. In fact, the SIM card is the only tamper-resistant piece of hardware that can be found in a typical smartphone, so you have to use it. However, there will be additional challenges:
The clock issue might be avoided if you generate your codes not with a clock, but with a counter, like what is done with HOTP. A feature of RSA SecurID tokens is indeed that they include an internal battery powered clock that the user cannot tamper with; this is an expensive feature which explains both the size (substantially bigger than a smart card chip) and the price of these tokens.
Another way to avoid the clock issue is to use the network. The code in the smart card would generate a random challenge (say, 16 random bytes), send that to the phone; the phone would then talk to a Time Stamp Authority who would sign the challenge along with the current date and time, and send back the signature. The smart card would still have to verify that signature, and check that the response indeed contains the correct challenge value. This process ensures that the card obtains an untampered-with notion of the current time with decent accuracy. But the protocol has become quite complex, and involves network access (not necessarily easy, especially when the phone owner is in a foreign country) and a trusted server (which has to be maintained).