package org.witness.informacam.crypto; import info.guardianproject.cacheword.CacheWordHandler; import info.guardianproject.cacheword.ICacheWordSubscriber; import info.guardianproject.cacheword.PassphraseSecrets; import info.guardianproject.cacheword.Wiper; import java.io.IOException; import java.security.GeneralSecurityException; import javax.crypto.SecretKey; import org.witness.informacam.InformaCam; import org.witness.informacam.R; import org.witness.informacam.utils.Constants.Actions; import org.witness.informacam.utils.Constants.App.Crypto; import org.witness.informacam.utils.Constants.App.Storage.Type; import org.witness.informacam.utils.Constants.Codes; import org.witness.informacam.utils.Constants.IManifest; import org.witness.informacam.utils.Constants.Logger; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.NotificationCompat; import android.util.Log; public class CredentialManager implements ICacheWordSubscriber { protected CacheWordHandler cacheWord; private int status; private boolean initIOCipher = true; private Context context; protected boolean firstUse = false; InformaCam informaCam = InformaCam.getInstance(); private final static String LOG = Crypto.LOG; public CredentialManager(Context context, boolean initIOCipher, boolean firstUse, boolean showNotification) { this.status = Codes.Status.UNKNOWN; this.initIOCipher = initIOCipher; this.context = context; this.firstUse = firstUse; cacheWord = new CacheWordHandler(this.context, this); if (showNotification) cacheWord.setNotification(buildNotification()); cacheWord.connectToService(); } private Notification buildNotification () { Intent intentLaunch = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); PendingIntent pendingIntent=PendingIntent.getActivity(context, 0, intentLaunch, Intent.FLAG_ACTIVITY_NEW_TASK); return new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_action_camera) .setContentTitle(context.getString(R.string.app_name)) .setContentText(context.getString(R.string.cacheword_unlocked)) .setContentIntent(pendingIntent) .setOngoing(true).build(); } public boolean login(char[] password) { try { cacheWord.setTimeout(0); cacheWord.setPassphrase(password); return true; } catch (GeneralSecurityException e) { Log.e(LOG, "invalid password or secrets has been tampered with"); e.printStackTrace(); } catch(NullPointerException e) { Logger.e(LOG, e); } return false; } public boolean logout() { cacheWord.lock(); return true; } public int getStatus() { if(status != Codes.Status.UNKNOWN) { return status; } else { if(!cacheWord.isLocked()) { status = Codes.Status.UNLOCKED; } else { if(cacheWord.getCachedSecrets() == null) { status = Codes.Status.UNINITIALIZED; } else { status = Codes.Status.LOCKED; } } return status; } } public void setMasterPassword(char[] password) throws GeneralSecurityException { // PassphraseSecrets secret = PassphraseSecrets.initializeSecrets(context, password); //cacheWord.setCachedSecrets(secret); cacheWord.setPassphrase(password); } public byte[] setAuthToken(String authToken) { SecretKey key = ((PassphraseSecrets) cacheWord.getCachedSecrets()).getSecretKey(); return AesUtility.EncryptToKey(key, authToken).getBytes(Wiper.Utf8CharSet); } private void update(int code) { Bundle data = new Bundle(); data.putInt(Codes.Extras.MESSAGE_CODE, code); Intent intent = new Intent(Actions.INFORMACAM_START) .putExtra(Codes.Keys.SERVICE, data) .putExtra(Codes.Extras.RESTRICT_TO_PROCESS, informaCam.getProcess()); informaCam.sendBroadcast(intent); } public void onPause() { cacheWord.detach(); } public void onResume() { cacheWord.reattach(); } @Override public void onCacheWordUninitialized() { Log.d(LOG, "onCacheWordUninitialized()"); this.status = Codes.Status.UNINITIALIZED; } @Override public void onCacheWordLocked() { Log.d(LOG, "onCacheWordLocked()"); informaCam.user.isLoggedIn = false; informaCam.user.lastLogOut = System.currentTimeMillis(); informaCam.saveState(informaCam.user); this.status = Codes.Status.LOCKED; } @Override public void onCacheWordOpened() { Log.d(LOG, "onCacheWordOpened()"); cacheWord.setTimeout(0); informaCam.initBroadcasters(); boolean hasIOCipher = !initIOCipher; if(initIOCipher) { try { /* * ICredentials credentials = new ICredentials(); credentials.inflate(informaCam.ioService.getBytes(Models.IUser.CREDENTIALS, Type.INTERNAL_STORAGE)); SecretKey key = ((PassphraseSecrets) cacheWord.getCachedSecrets()).getSecretKey(); byte[] authTokenBytes = AesUtility.DecryptWithKey(key, credentials.iv.getBytes(), credentials.passwordBlock.getBytes()); String authToken = new String(authTokenBytes, Wiper.Utf8CharSet);*/ if(informaCam.ioService.initIOCipher(cacheWord.getEncryptionKey())) { hasIOCipher = true; } else { Log.e(LOG, "COULD NOT FULLY OPEN IOCIPHER AND GET CREDENTIALS AND STUFF"); } } catch (Exception e) { Log.e(LOG, "COULD NOT FULLY OPEN IOCIPHER AND GET CREDENTIALS AND STUFF",e); } } if(hasIOCipher) { try { informaCam.initData(); } catch (Exception pge) { throw new RuntimeException("Could not initialize app data",pge); } try { informaCam.user.inflate(informaCam.ioService.getBytes(IManifest.USER, Type.INTERNAL_STORAGE)); } catch (Exception pge) { throw new RuntimeException("Could not initialize pgp secret key",pge); } this.status = Codes.Status.UNLOCKED; update(Codes.Messages.Home.INIT); informaCam.user.isLoggedIn = true; informaCam.user.lastLogIn = System.currentTimeMillis(); try { informaCam.ioService.saveBlob(informaCam.user.asJson().toString().getBytes(), new java.io.File(IManifest.USER)); this.status = Codes.Status.UNLOCKED; update(Codes.Messages.Home.INIT); } catch (IOException ioe) { Log.e(LOG,"iocipher saveState() error",ioe); } } } }