Disable spongycastle before verifying jar files.

Fixes issue #111. This is a workaround rather than a full solution,
but it solves the problem. There is a bug in Lollipop, whereby including
spongycastle as a security provider causes problems verifying .jar files.
As a result, it is now disabled when actually performing verification,
so that the libraries provided by Android do the work, and then re-enabled
afterwards.

There is an ever so slight chance that the period when this is disabled
may align with the period when spongycastle may actually be required
(i.e. for signing a local repo index). This is a risk which I cnanot
see how to avoid, and will likel7 cause either the signing to fail
due to the unavailability of the relevant security classes. However
this is very minimal, hard to reproduce (I couldn't get it to happen)
and also has the effect of the local repo failing, rather than the updating
of apps failing (which is arguably more important) and so is worth it in
my opinion.

See comments at https://gitlab.com/fdroid/fdroidclient/issues/111
for much greater detail.
This commit is contained in:
Peter Serwylo 2014-11-17 22:21:18 +11:00
parent 2d78fa802f
commit 0a4725b962
4 changed files with 62 additions and 28 deletions

View File

@ -55,10 +55,8 @@ import org.fdroid.fdroid.localrepo.LocalRepoService;
import org.fdroid.fdroid.net.IconDownloader;
import org.fdroid.fdroid.net.WifiStateChangeService;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.File;
import java.security.Security;
import java.util.Set;
public class FDroidApp extends Application {
@ -71,6 +69,8 @@ public class FDroidApp extends Application {
public static Repo repo = new Repo();
public static Set<String> selectedApps = null; // init in SelectLocalAppsFragment
// Leaving the fully qualified class name here to help clarify the difference between spongy/bouncy castle.
private static org.spongycastle.jce.provider.BouncyCastleProvider spongyCastleProvider;
private static Messenger localRepoServiceMessenger = null;
private static boolean localRepoServiceIsBound = false;
@ -78,6 +78,11 @@ public class FDroidApp extends Application {
BluetoothAdapter bluetoothAdapter = null;
static {
spongyCastleProvider = new org.spongycastle.jce.provider.BouncyCastleProvider();
enableSpongyCastle();
}
public static enum Theme {
dark, light, lightWithDarkActionBar
}
@ -108,6 +113,22 @@ public class FDroidApp extends Application {
return curTheme;
}
public static void enableSpongyCastle() {
Security.addProvider(spongyCastleProvider);
}
public static void enableSpongyCastleOnLollipop() {
if (Build.VERSION.SDK_INT == 21) {
Security.addProvider(spongyCastleProvider);
}
}
public static void disableSpongyCastleOnLollipop() {
if (Build.VERSION.SDK_INT == 21) {
Security.removeProvider(spongyCastleProvider.getName());
}
}
@Override
public void onCreate() {
super.onCreate();

View File

@ -11,6 +11,7 @@ import android.text.TextUtils;
import android.util.Log;
import org.fdroid.fdroid.AppFilter;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Utils;
import java.io.File;
@ -263,6 +264,11 @@ public class App extends ValueObject implements Comparable<App> {
throw new CertificateEncodingException("null signed entry!");
}
// Due to a bug in android 5.0 lollipop, the inclusion of BouncyCastle causes
// breakage when verifying the signature of most .jars. For more
// details, check out https://gitlab.com/fdroid/fdroidclient/issues/111.
try {
FDroidApp.disableSpongyCastleOnLollipop();
InputStream tmpIn = apkJar.getInputStream(aSignedEntry);
byte[] buff = new byte[2048];
while (tmpIn.read(buff, 0, buff.length) != -1) {
@ -281,7 +287,9 @@ public class App extends ValueObject implements Comparable<App> {
Certificate signer = aSignedEntry.getCertificates()[0];
rawCertBytes = signer.getEncoded();
} finally {
FDroidApp.enableSpongyCastleOnLollipop();
}
apkJar.close();
/*

View File

@ -35,12 +35,6 @@ import kellinwood.security.zipsigner.ZipSigner;
public class LocalRepoKeyStore {
private static final String TAG = "KerplappKeyStore";
static {
Security.insertProviderAt(
new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}
public static final String INDEX_CERT_ALIAS = "fdroid";
public static final String HTTP_CERT_ALIAS = "https";

View File

@ -2,6 +2,7 @@ package org.fdroid.fdroid.updater;
import android.content.Context;
import android.util.Log;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Hasher;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
@ -123,7 +124,17 @@ public class SignedRepoUpdater extends RepoUpdater {
// Don't worry about checking the status code for 200. If it was a
// successful download, then we will have a file ready to use:
if (indexJar != null && indexJar.exists()) {
// Due to a bug in android 5.0 lollipop, the inclusion of BouncyCastle causes
// breakage when verifying the signature of the downloaded .jar. For more
// details, check out https://gitlab.com/fdroid/fdroidclient/issues/111.
try {
FDroidApp.disableSpongyCastleOnLollipop();
indexXml = extractIndexFromJar(indexJar);
} finally {
FDroidApp.enableSpongyCastleOnLollipop();
}
}
return indexXml;
}