Skip to content

Commit b14d9d8

Browse files
committed
Fix for Android PRNG bug.
There is apparently an Android vulnerability with the PRNG it provides through the JCE. This uses their suggested code to patch the PRNG, and provides the option to regenerate identity keys. http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html
1 parent 8ecf972 commit b14d9d8

11 files changed

Lines changed: 533 additions & 6 deletions

File tree

AndroidManifest.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
android:protectionLevel="signature" />
3939
<uses-permission android:name="org.thoughtcrime.securesms.permission.C2D_MESSAGE" />
4040

41-
<application android:icon="@drawable/icon"
41+
<application android:name="org.thoughtcrime.securesms.ApplicationListener"
42+
android:icon="@drawable/icon"
4243
android:label="@string/app_name"
4344
android:theme="@style/TextSecure.LightTheme">
4445

@@ -124,6 +125,9 @@
124125
android:label="@string/AndroidManifest__public_identity_key"
125126
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
126127

128+
<activity android:name=".ViewLocalIdentityActivity"
129+
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
130+
127131
<activity android:name=".PassphraseChangeActivity"
128132
android:label="@string/AndroidManifest__change_passphrase"
129133
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>

res/drawable-hdpi/refresh.png

3.06 KB
Loading

res/drawable-mdpi/refresh.png

2.96 KB
Loading

res/drawable-xhdpi/refresh.png

3.14 KB
Loading

res/menu/local_identity.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<menu xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:title="@string/local_identity__regenerate_key"
5+
android:id="@+id/menu_regenerate_key"
6+
android:icon="@drawable/refresh"/>
7+
</menu>

res/values/strings.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,22 @@
257257
<string name="MessageNotifier_mark_all_as_read">Mark all as read</string>
258258
<string name="MessageNotifier_mark_as_read">Mark as read</string>
259259

260+
<!-- ViewLocalIdentityActivity -->
261+
<string name="ViewLocalIdentityActivity_regenerating">Regenerating...</string>
262+
<string name="ViewLocalIdentityActivity_regenerating_identity_key">Regenerating identity
263+
key...
264+
</string>
265+
<string name="ViewLocalIdentityActivity_regenerated">Regenerated!</string>
266+
<string name="ViewLocalIdentityActivity_reset_identity_key">Reset Identity Key?</string>
267+
<string name="ViewLocalIdentityActivity_by_regenerating_your_identity_key_your_existing_contacts_will_receive_warnings">
268+
Caution! By regenerating your identity key, your current identity key will be permanently lost,
269+
and your existing contacts will receive warnings when establishing new secure sessions with you.
270+
Are you sure you would like to continue?
271+
</string>
272+
<string name="ViewLocalIdentityActivity_cancel">Cancel</string>
273+
<string name="ViewLocalIdentityActivity_continue">Continue</string>
274+
275+
260276
<!-- SmsReceiver -->
261277
<string name="SmsReceiver_currently_unable_to_send_your_sms_message">Currently unable to send your SMS message. It will be sent once service becomes available.</string>
262278

@@ -332,6 +348,7 @@
332348
<string name="import_fragment__import_a_plaintext_backup_file">
333349
Import a plaintext backup file. Compatible with \'SMSBackup And Restore.\'</string>
334350

351+
<string name="local_identity__regenerate_key">Regenerate Key</string>
335352

336353
<!-- prompt_passphrase_activity -->
337354
<string name="prompt_passphrase_activity__textsecure_passphrase">TEXTSECURE PASSPHRASE</string>
@@ -455,6 +472,7 @@
455472
<string name="preferences__appearance">Appearance</string>
456473
<string name="preferences__theme">Theme</string>
457474
<string name="preferences__default">Default</string>
475+
<string name="preferences__language">Language</string>
458476

459477
<!-- **************************************** -->
460478
<!-- menus -->
@@ -521,7 +539,6 @@
521539

522540
<!-- verify_keys -->
523541
<string name="verify_keys__menu_verified">Verified</string>
524-
<string name="preferences__language">Language</string>
525542
<!-- EOF -->
526543

527544
</resources>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (C) 2013 Open Whisper Systems
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
package org.thoughtcrime.securesms;
18+
19+
import android.app.Application;
20+
21+
import org.thoughtcrime.securesms.crypto.PRNGFixes;
22+
23+
/**
24+
* Will be called once when the TextSecure process is created.
25+
*
26+
* We're using this as an insertion point to patch up the Android PRNG disaster.
27+
*
28+
* @author Moxie Marlinspike
29+
*/
30+
public class ApplicationListener extends Application {
31+
32+
@Override
33+
public void onCreate() {
34+
PRNGFixes.apply();
35+
}
36+
37+
}

src/org/thoughtcrime/securesms/ConversationListActivity.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,8 @@ public void onItemClick(AdapterView parent, View view, int position, long id) {
106106
intent = new Intent(this, ImportExportActivity.class);
107107
intent.putExtra("master_secret", masterSecret);
108108
} else if (selected.equals("my_identity_key")) {
109-
intent = new Intent(this, ViewIdentityActivity.class);
110-
intent.putExtra("identity_key", IdentityKeyUtil.getIdentityKey(this));
111-
intent.putExtra("title", getString(R.string.ApplicationPreferencesActivity_my) + " " +
112-
getString(R.string.ViewIdentityActivity_identity_fingerprint));
109+
intent = new Intent(this, ViewLocalIdentityActivity.class);
110+
intent.putExtra("master_secret", masterSecret);
113111
} else if (selected.equals("contact_identity_keys")) {
114112
intent = new Intent(this, ReviewIdentitiesActivity.class);
115113
intent.putExtra("master_secret", masterSecret);

src/org/thoughtcrime/securesms/ViewIdentityActivity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public void onCreate(Bundle state) {
3737
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
3838
setContentView(R.layout.view_identity_activity);
3939

40+
initialize();
41+
}
42+
43+
protected void initialize() {
4044
initializeResources();
4145
initializeFingerprint();
4246
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright (C) 2011 Whisper Systems
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
package org.thoughtcrime.securesms;
18+
19+
import android.app.AlertDialog;
20+
import android.app.ProgressDialog;
21+
import android.content.DialogInterface;
22+
import android.os.AsyncTask;
23+
import android.os.Bundle;
24+
import android.widget.Toast;
25+
26+
import com.actionbarsherlock.view.Menu;
27+
import com.actionbarsherlock.view.MenuInflater;
28+
import com.actionbarsherlock.view.MenuItem;
29+
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
30+
import org.thoughtcrime.securesms.crypto.MasterSecret;
31+
32+
/**
33+
* Activity that displays the local identity key and offers the option to regenerate it.
34+
*
35+
* @author Moxie Marlinspike
36+
*/
37+
public class ViewLocalIdentityActivity extends ViewIdentityActivity {
38+
39+
private MasterSecret masterSecret;
40+
41+
public void onCreate(Bundle bundle) {
42+
this.masterSecret = getIntent().getParcelableExtra("master_secret");
43+
44+
getIntent().putExtra("identity_key", IdentityKeyUtil.getIdentityKey(this));
45+
getIntent().putExtra("title", getString(R.string.ApplicationPreferencesActivity_my) + " " +
46+
getString(R.string.ViewIdentityActivity_identity_fingerprint));
47+
super.onCreate(bundle);
48+
}
49+
50+
@Override
51+
public boolean onPrepareOptionsMenu(Menu menu) {
52+
super.onPrepareOptionsMenu(menu);
53+
54+
MenuInflater inflater = this.getSupportMenuInflater();
55+
inflater.inflate(R.menu.local_identity, menu);
56+
57+
return true;
58+
}
59+
60+
@Override
61+
public boolean onOptionsItemSelected(MenuItem item) {
62+
super.onOptionsItemSelected(item);
63+
64+
switch (item.getItemId()) {
65+
case R.id.menu_regenerate_key: promptToRegenerateIdentityKey(); return true;
66+
case android.R.id.home: finish(); return true;
67+
}
68+
69+
return false;
70+
}
71+
72+
private void promptToRegenerateIdentityKey() {
73+
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
74+
dialog.setIcon(android.R.drawable.ic_dialog_alert);
75+
dialog.setTitle(getString(R.string.ViewLocalIdentityActivity_reset_identity_key));
76+
dialog.setMessage(getString(R.string.ViewLocalIdentityActivity_by_regenerating_your_identity_key_your_existing_contacts_will_receive_warnings));
77+
dialog.setNegativeButton(getString(R.string.ViewLocalIdentityActivity_cancel), null);
78+
dialog.setPositiveButton(getString(R.string.ViewLocalIdentityActivity_continue),
79+
new DialogInterface.OnClickListener() {
80+
@Override
81+
public void onClick(DialogInterface dialog, int which) {
82+
regenerateIdentityKey();
83+
}
84+
});
85+
dialog.show();
86+
}
87+
88+
private void regenerateIdentityKey() {
89+
new AsyncTask<Void, Void, Void>() {
90+
private ProgressDialog progressDialog;
91+
92+
@Override
93+
protected void onPreExecute() {
94+
progressDialog = ProgressDialog.show(ViewLocalIdentityActivity.this,
95+
getString(R.string.ViewLocalIdentityActivity_regenerating),
96+
getString(R.string.ViewLocalIdentityActivity_regenerating_identity_key),
97+
true, false);
98+
}
99+
100+
@Override
101+
public Void doInBackground(Void... params) {
102+
IdentityKeyUtil.generateIdentityKeys(ViewLocalIdentityActivity.this, masterSecret);
103+
return null;
104+
}
105+
106+
@Override
107+
protected void onPostExecute(Void result) {
108+
if (progressDialog != null)
109+
progressDialog.dismiss();
110+
111+
Toast.makeText(ViewLocalIdentityActivity.this,
112+
getString(R.string.ViewLocalIdentityActivity_regenerated),
113+
Toast.LENGTH_LONG).show();
114+
115+
getIntent().putExtra("identity_key",
116+
IdentityKeyUtil.getIdentityKey(ViewLocalIdentityActivity.this));
117+
initialize();
118+
}
119+
120+
}.execute();
121+
}
122+
123+
}

0 commit comments

Comments
 (0)