java.lang.Object | ||||
↳ | android.content.Context | |||
↳ | android.content.ContextWrapper | |||
↳ | android.app.Service | |||
↳ | com.samsung.android.knox.ddar.DualDARClient |
This class is used by privileged application to invoke Dual DAR platform apis and receive platform callbacks.
Dual DAR Client application extends this class and overrides the abstract callback methods.
NOTE: All the cryptographic key usages and operations are to be done using Android Key Store (AKS)
as the keys are bound to the secure hardware and is never exposed to the outside world even in case
of Android OS compromise.
This class is a Service that helps platform discover and bind to the client. Once the class has been extended in client application, declare the class as a service with the following intent filter in AndroidManifest.xml - com.samsung.android.knox.ddar.BIND_DUAL_DAR_CLIENTThe client application also needs to specify the supported DUAL DAR SDK version in the meta-data tag of the AndroidManifest.xml with name as supportedDualDarSdkVersion and value being the valid DUAL DAR SDK version as String literal.
Refer to DualDARPolicy.DUAL_DAR_VERSION_CODES for DUAL DAR SDK version information.
Sample Dual DAR Client AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.samsung.android.knox.test"> <application> <meta-data android:name="supportedDualDarSdkVersion" android:value="1.1" /> <service android:name="com.samsung.android.knox.test.MyDualDARClient"> <intent-filter> <action android:name="com.samsung.android.knox.ddar.BIND_DUAL_DAR_CLIENT" /> </intent-filter> </service> </application> </manifest> Sample Dual DAR Client implementation: |
public class MyDualDARClient extends DualDARClient { public boolean isSupported(int feature) { if(feature == FEATURE_RESET_PASSWORD) { return true; } return false; } public boolean onClientBringup() { // Install new version of dual dar client library and other files if version mismatch if(!getInstalledClientLibraryVersion().equals(CLIENT_VERSION)){ List<String> secondaryLibs = new ArrayList<>(); secondaryLibs.add(PROP_FILE); if (installLibrary(CLIENT_LIB_FILE_NAME, secondaryLibs, true) != ERROR_NONE) { Log.e(TAG, "Error installing Dual DAR client lib" + RELAY_FILE_NAME); return false; } } if(!getInstalledClientLibraryVersion().equals(CLIENT_VERSION)){ Log.e(TAG, "Version mismatch for Dual DAR client lib. Expected " + CLIENT_VERSION + " but installed " + getInstalledClientLibraryVersion()); return false; } return true; } public boolean onDualDARSetupForUser(int userId) { // Generate Secret (Master Key) and set it to platform for (de)encrypting filesystem byte[] masterKey = generateSecretKey(); Map<String, Byte[]> secrets = new HashMap<>(); Byte[] secretData = new Byte[masterKey.length]; for(int i=0;i<masterKey.length;i++) { secretData[i] = masterKey[i]; } secrets.put(MASTER_KEY_ALIAS, secretData); setSecret(userId, secrets); // Generate and save salt byte[] salt = generateAndSaveSalt(); // Generate and save default auth token byte[] defAuthToken = generateAndSaveDefAuthToken(); // Encrypt master key and save saveEncryptedMasterKey(encryptMasterKeyWithPassword(masterKey, defAuthToken, salt)); return true; } public boolean onPasswordAuth(int userId, byte[] password) { byte[] salt = getSalt(); if (password == null) { //get default password password = getDefaultAuthToken(); } // Generate KEK using given auth token SecretKey kek = generateKek(password, salt); // Decrypt the encrypted master key on disk with KEK and set to platform byte[] masterKey = getSecret(kek, getEncryptedMasterKey()); // Decrypt the encrypted master key on disk with KEK and set to platform Map<String, Byte[]> secrets = new HashMap<>(); Byte[] secretData = new Byte[masterKey.length]; for(int i=0;i<masterKey.length;i++) { secretData[i] = masterKey[i]; } secrets.put(MASTER_KEY_ALIAS, secretData); setSecret(userId, secrets); return true; } public boolean onPasswordChange(int userId, byte[] oldPassword, byte[] newPassword) { byte[] salt = getSalt(); if(oldPassword == null) { oldPassword = getDefaultAuthToken(); } saveEncryptedMasterKey(reEncryptMasterKeyWithNewPassword( getEncryptedMasterKey(), derivedOldSystemToken, derivedNewSystemToken, salt)); return true; } public void onDataLockStateChange(int userId, boolean locked) { Log.d(TAG, " onDataLockStateChange " + userId + " locked: " + locked); } public boolean onDualDARDestroyForUser(int userId) { destroyKeysAndTokens(userId); return true; } public boolean onSetResetPasswordToken(int userId, byte[] password, long tokenHandle, byte[] token) { // Decrypt Master Key using password and re-encrypt with token EncryptedMasterKey reEncryptedMasterKey = null; byte[] salt = getSalt(); if(password == null) { password = getDefaultAuthToken(); } reEncryptedMasterKey = reEncryptMasterKeyWithNewPassword( getEncryptedMasterKey(), password, token, salt); // Save token encrypted Master Key saveTokenEncryptedMasterKey(reEncryptedMasterKey, userId, tokenHandle); // Save token handle addTokenHandleAndSave(userId, tokenHandle); return true; } public void onClearResetPasswordToken(int userId, long tokenHandle) { // Clear token encrypted Master Key removeTokenEncryptedMasterKey(userId, tokenHandle); // Clear token handle removeTokenHandleAndSave(userId, tokenHandle); } public boolean onResetPasswordWithToken(int userId, byte[] newPassword, long tokenHandle, byte[] token) { // Decrypt Master Key using token and re-encrypt with new password EncryptedMasterKey reEncryptedMasterKey = null; byte[] salt = getSalt(); if(newPassword == null) { newPassword = getDefaultAuthToken(); } reEncryptedMasterKey = reEncryptMasterKeyWithNewPassword( getTokenEncryptedMasterKey(userId, tokenHandle), token, newPassword, salt); saveEncryptedMasterKey(reEncryptedMasterKey); return true; } } |
API level 28 |
KNOX 3.3 |
Constants | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
int | ERROR_FAILURE | Signifies FAILURE | |||||||||
int | ERROR_NONE | Signifies SUCCESS | |||||||||
int | FEATURE_RESET_PASSWORD | Signifies feature Reset Password |
[Expand]
Inherited Constants | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
From class
android.app.Service
| |||||||||||
From class
android.content.Context
| |||||||||||
From interface
android.content.ComponentCallbacks2
|
Public Constructors | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Public Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
API to get the list of Dual DAR enabled users
| |||||||||||
API to get the installed client crypto library version
| |||||||||||
API to install Dual DAR Client's crypto library and supporting files to Dual DAR Client Daemon.
| |||||||||||
API callback from DualDAR platform to check if DualDAR Client App supports a certain feature.
| |||||||||||
API callback to Dual DAR client to clear the reset password token
which was provisioned earlier using
onSetResetPasswordToken(int, byte[], long, byte[]) . | |||||||||||
API callback for Dual DAR bring up event to inform DualDAR Client App to initiate Dual DAR related activities.
| |||||||||||
API callback for Dual DAR workspace(container) Data Lock State change event to inform Dual DAR Client App.
| |||||||||||
API callback for Dual DAR workspace(container) destroy event to inform Dual DAR Client App.
| |||||||||||
API callback for Dual DAR workspace(container) creation event to inform Dual DAR Client App.
| |||||||||||
API callback for Dual DAR workspace(container) authentication event to inform Dual DAR Client App.
| |||||||||||
API callback for Dual DAR workspace(container) password change event to inform Dual DAR Client App.
| |||||||||||
API callback to Dual DAR client to reset password using the token
which was provisioned earlier using
onSetResetPasswordToken(int, byte[], long, byte[]) . | |||||||||||
API callback to Dual DAR client to provision the reset password token
which can later be used to reset the workspace(container)
password via
onResetPasswordWithToken(int, byte[], long, byte[]) . | |||||||||||
API to set secrets for client lib
The secret that is set is passed to the native client library for (en)decrypt operation of filesystem. |
[Expand]
Inherited Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
From class
android.app.Service
| |||||||||||
From class
android.content.ContextWrapper
| |||||||||||
From class
android.content.Context
| |||||||||||
From class
java.lang.Object
| |||||||||||
From interface
android.content.ComponentCallbacks
| |||||||||||
From interface
android.content.ComponentCallbacks2
|
Signifies FAILURE
API level 28 |
Signifies SUCCESS
API level 28 |
Signifies feature Reset Password
API level 28 |
API to get the list of Dual DAR enabled users
This API will return the list of DualDAR users available in device. |
API level 28 |
KNOX 3.3 |
API to get the installed client crypto library version
API level 28 |
KNOX 3.3 |
API to install Dual DAR Client's crypto library and supporting files to Dual DAR Client Daemon. Client App's crypto library and supporting files are copied to the the /data/misc/knoxcore/dualdar/ system directory.
clientLibPath | Path to the client crypto library that is to be installed |
---|---|
secondaryFilePaths | Paths to the secondary files that are to be installed. Can be null. |
isAsset | true if client lib and secondary files reside in assets directory, else false |
ERROR_NONE
on success else ERROR_FAILURE
If the secondary file is a shared object library, then compile the client crypto library by setting
the RPATH variable to the /data/misc/knoxcore/dualdar/ system directory.
If client lib and files are not in assets directory, then paths are relative to the application's base directory.
Else, paths are relative paths to assets directory
If library and secondary files are in assets directory
List<String> secondaryLibs = new ArrayList<>(); secondaryLibs.add("libsecondary.so"); if (installLibrary("libclient.so", secondaryLibs, true) != ERROR_NONE) { Log.e(TAG, "Error installing Dual DAR client lib" + RELAY_FILE_NAME); return false; }If library and secondary files are in a non-assets directory. Below example demonstrates when library and secondary files are part of lib folder in the compiled apk. String filePrefix = getApplicationInfo().nativeLibraryDir + "/"; List<String> secondaryLibs = new ArrayList<>(); secondaryLibs.add(filePrefix + "libsecondary.so"); if (installLibrary(filePrefix + "libclient.so", secondaryLibs, false) != ERROR_NONE) { Log.e(TAG, "Error installing Dual DAR client lib" + RELAY_FILE_NAME); return false; }Note: This API is to be used in onClientBringup() callback only. |
API level 28 |
KNOX 3.3 |
API callback from DualDAR platform to check if DualDAR Client App supports a certain feature.
Refer to features: FEATURE_RESET_PASSWORD
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback to Dual DAR client to clear the reset password token
which was provisioned earlier using onSetResetPasswordToken(int, byte[], long, byte[])
.
userId | User ID of the workspace |
---|---|
tokenHandle | handle to the reset password token to be cleared |
This API will be invoked when workspace(container) admin is trying to clear an earlier
provisioned reset password token. Applicable only if Client supports FEATURE_RESET_PASSWORD . |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR bring up event to inform DualDAR Client App to initiate Dual DAR related activities. Note: This is not related to Android App lifecycle events.
This method is invoked when -
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR workspace(container) Data Lock State change event to inform Dual DAR Client App.
userId | User ID of the workspace |
---|---|
locked | true for locked and false for unlocked |
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR workspace(container) destroy event to inform Dual DAR Client App.
userId | User ID of the workspace |
---|
Typical client activities include cleaning the secret and other data structures
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR workspace(container) creation event to inform Dual DAR Client App.
userId | User ID of the workspace |
---|
Typical client activities include creating a secret and setting up client library
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR workspace(container) authentication event to inform Dual DAR Client App.
userId | User ID of the workspace |
---|---|
password | user password for dualDAR profile |
Typical client activities include verify password and set
secret to platform by invoking setSecret(int, Map .
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback for Dual DAR workspace(container) password change event to inform Dual DAR Client App.
userId | User ID of the workspace |
---|---|
oldPassword | old user password for dualDAR profile |
newPassword | new user password for dualDAR profile |
Typical client activities include updating to new password.
Note: Incoming callbacks are not guaranteed to be executed on the main thread or any one thread, so you need to think about multithreading from the start and properly build your service to be thread-safe. |
API level 28 |
KNOX 3.3 |
API callback to Dual DAR client to reset password using the token
which was provisioned earlier using onSetResetPasswordToken(int, byte[], long, byte[])
.
userId | User ID of the workspace |
---|---|
newPassword | new user password to be set for the dualDAR profile |
tokenHandle | handle to the reset password token passed |
token | token to be used to reset the password |
true
on success, false
otherwise This API will be invoked when workspace(container) admin is trying to reset password using
earlier provisioned token. Applicable only if Client supports FEATURE_RESET_PASSWORD . |
API level 28 |
KNOX 3.3 |
API callback to Dual DAR client to provision the reset password token
which can later be used to reset the workspace(container)
password via onResetPasswordWithToken(int, byte[], long, byte[])
.
userId | User ID of the workspace |
---|---|
password | current user password for dualDAR profile |
tokenHandle | handle to the reset password token passed |
token | reset password token to be provisioned |
true
on success, false
otherwise This API will be invoked when workspace(container) admin is trying to setup a reset password token.
Applicable only if Client supports FEATURE_RESET_PASSWORD . |
API level 28 |
KNOX 3.3 |
API to set secrets for client lib
The secret that is set is passed to the native client library for (en)decrypt operation of filesystem.
userId | User ID of the workspace |
---|---|
secrets | secret data for client library |
Note: This API is generally used in onDualDARSetupForUser(int) and
onPasswordAuth(int, byte[]) callbacks. |
API level 28 |
KNOX 3.3 |