Android
Required software
- Android SDK >= 19
Project Configuration
- Add the MPS.aar to your project libs folder and in build.gradle
- Add useLegacyPackaging to the packagingOptions and include the dependencies
android {
...
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
...
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
...
}
Initialize
While MPS can be initialized at any point during the application lifecycle, it is recommended to do so during application startup. This ensures that environment integrity validation is in place from the beginning, providing protection throughout the app's runtime.
The Hardening.getInstance(ctx)
method can be called multiple times and does not require retaining the Hardening instance in memory.
However, be aware that Hardening.getInstance(ctx)
is a relatively expensive and blocking operation. To avoid performance issues, it should be used sparingly and only when necessary.
MPS can then be used to detect a rooted device, if the app is running in an emulator, and retrieve an endpoint securely stored within the library:
import com.securityside.mobileprotection.Hardening;
import com.securityside.mobileprotection.Secrets;
import android.content.Context;
...
try {
Context ctx; // getApplicationContext() / getActivity()
Hardening mps = Hardening.getInstance(ctx); // Load the library
} catch (Exception e) {
...
}
Environment verifications
Since MPS does not collect or retain any environment data, you must handle all logging yourself. If Hardening.getInstance(ctx)
does not throw an exception, it indicates that, based on the MPS specified security parameters, the app is running in a secure environment and the secrets vault is accessible.
After calling Hardening.getInstance(ctx)
, you can also check each individual threat flag. However, if an exception is thrown during getInstance(), it signifies that a critical threat was detected, the app is not secure, and the secrets vault will remain locked.
private static void hardeningInit() {
try {
hardeningCheck();
} catch (Exception exception) {
Log.e("MPS", "MPS critical threats: "+exception.getMessage(), exception);
}
}
private static void hardeningCheck() throws Exception {
Hardening mps = Hardening.getInstance(instance);
List<String> threats = new ArrayList<>();
if (mps.isDebugger()) threats.add("Debugger");
if (mps.isEmulator()) threats.add("Emulator");
if (mps.isFrida()) threats.add("Frida");
if (mps.isMagisk()) threats.add("Magisk");
if (mps.isRooted()) threats.add("Root");
if (!threats.isEmpty()) {
String logMessage = String.join(", ", threats) + " detected";
Log.d("MPS","MPS threats: "+logMessage);
}
}
MPS allows your application to verify the integrity of its runtime environment by returning specific flags that indicate the results of various validation checks. These validation checks only work if no exception is thrown during Hardening.getInstance(ctx)
boolean isDebugger = mps.isDebugger();
boolean isEmulator = mps.isEmulator();
boolean isFrida = mps.isFrida();
boolean isMagisk = mps.isMagisk();
boolean isRooted = mps.isRooted();
Secrets
MPS securely stores sensitive information, which can only be retrieved if the environment passes integrity checks based on your specified security requirements. The retrieval method is thread-safe and can be invoked at any point in the app lifecycle, from any thread.
MPS allows your application to verify the integrity of its runtime environment by returning specific flags that indicate the results of various validation checks. These validation checks only work if no exception is thrown during Hardening.getInstance(ctx).
If the environment integrity check fails due to a compromise, the secretValue returned by MPS will differ from the expected one, signaling potential tampering or an untrusted runtime environment.
String secret = Secrets.<Secret Name>();