Skip to content

Instantly share code, notes, and snippets.

@kmansoft
Created August 2, 2014 17:06
Show Gist options
  • Save kmansoft/f4de66b422de7e93655d to your computer and use it in GitHub Desktop.
Save kmansoft/f4de66b422de7e93655d to your computer and use it in GitHub Desktop.
public class SSLHardening {
private static final String TAG = "SSLHardening";
public static boolean isSupported() {
return Build.VERSION.SDK_INT >= 14;
}
public static boolean isHardeningEnabled(Context context) {
if (isSupported()) {
synchronized (SSLHardening.class) {
final SharedPreferences prefs = getSharedPrefsLocked(context);
return prefs.getBoolean(Prefs.PREF_NETWORK_SSL_HARDNENING_KEY,
Prefs.PREF_NETWORK_SSL_HARDNENING_DEFAULT);
}
}
return false;
}
public static void hardenSocket(Socket socket) {
if (socket instanceof SSLSocket) {
hardenSocketImpl((SSLSocket) socket);
}
}
private static void hardenSocketImpl(SSLSocket socket) {
synchronized (SSLHardening.class) {
if (!ENABLED_DONE) {
ENABLED_DONE = true;
final String[] listCiphers = socket.getEnabledCipherSuites();
ENABLED_CIPHERS = reorder(listCiphers, ORDERED_KNOWN_CIPHERS, BLACKLISTED_CIPHERS);
final String[] listProtos = socket.getEnabledProtocols();
ENABLED_PROTOCOLS = reorder(listProtos, ORDERED_KNOWN_PROTOCOLS, null);
}
}
if (ENABLED_CIPHERS != null) {
if (MyLog.isEnabled()) {
MyLog.i(TAG, "Setting hardened ciphers: %s", Arrays.toString(ENABLED_CIPHERS));
}
socket.setEnabledCipherSuites(ENABLED_CIPHERS);
}
if (ENABLED_PROTOCOLS != null) {
if (MyLog.isEnabled()) {
MyLog.i(TAG, "Setting hardened protocols: %s", Arrays.toString(ENABLED_PROTOCOLS));
}
socket.setEnabledProtocols(ENABLED_PROTOCOLS);
}
}
private static boolean ENABLED_DONE;
private static String[] ENABLED_CIPHERS;
private static String[] ENABLED_PROTOCOLS;
//@formatter:off
// Order taken from OpenSSL 1.0.1c
private static final String[] ORDERED_KNOWN_CIPHERS = {
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDH_RSA_WITH_RC4_128_SHA",
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_RC4_128_SHA",
"SSL_RSA_WITH_RC4_128_MD5",
};
private static final String[] BLACKLISTED_CIPHERS = {
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
};
private static final String[] ORDERED_KNOWN_PROTOCOLS = {
"TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3"
};
//@formatter:on
private static String[] reorder(String[] def, String[] ordered, String[] black) {
if (def == null) {
return null;
}
final List<String> result = CollectionUtil.newArrayList(def.length);
final Set<String> defSet = listToSet(def);
for (String s : ordered) {
if (defSet.contains(s)) {
result.add(s);
}
}
final Set<String> orderedSet = listToSet(ordered);
final Set<String> blackSet = black != null ? listToSet(black) : null;
for (String s : def) {
if (!orderedSet.contains(s)) {
if (blackSet == null || !blackSet.contains(s)) {
result.add(s);
}
}
}
if (MyLog.isEnabled()) {
MyLog.i(TAG, "Hardening reorder: %s, %s, %s -> %s", Arrays.toString(def), Arrays.toString(ordered),
Arrays.toString(black), result);
}
return result.toArray(new String[result.size()]);
}
private static Set<String> listToSet(String[] list) {
final Set<String> set = CollectionUtil.newHashSet();
for (String s : list) {
set.add(s);
}
return set;
}
private static SharedPreferences gSharedPrefs;
private static SharedPreferences getSharedPrefsLocked(Context context) {
if (gSharedPrefs == null) {
gSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
}
return gSharedPrefs;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment