DualDAR ISV integration

Samsung Knox DualDAR allows enterprises to ensure their work data is secured with two layers of encryption. For details please see the DualDAR architecture.

Knox DualDAR architecture allows ISVs to build and provide their own custom encryption library for the second layer of encryption. ISV developers can provide second layer of encryption via a native library and an Android application. Once provided, Knox DualDAR ensures work data is also protected by the ISV provided custom encryption implementation.

Supported Devices

DualDAR is supported on Galaxy S10, N10, S20, and future flagship models.


Samsung Knox DualDAR consists of the following components:

Knox Workspace

DualDAR Framework and SDK

DualDAR Client

Knox Workspace

Knox Workspace is a secure container designed to separate, isolate, encrypt, and protect enterprise apps and data. This container enables a mobile phone that provides both work and play environments. Enterprises can remotely manage the work environment, but not access personal information like photos and messages. For additional details, read more about the Knox Workspace.

DualDAR Framework and SDK

DualDAR framework provides classes and APIs that allow:

  1. UEM solutions to enable creation and configuration of a workspace container with DualDAR protection.
  2. ISVs to enable third party applications to provide an implementation for an independent second layer of encryption.

For additional details, see the DualDAR API reference and the UEM integration guide.

DualDAR Client

The DualDAR client is the implementation of the second layer of encryption provided by the ISV. The DualDAR client APK is installed on the end user’s device prior to creation of DualDAR Workspace.

It consists of two components:

  • File Encryption Component – Native Library
  • Key Management and Authentication Component – Android Application

Native Library

The native library is the file encryption component responsible for encryption and decryption of data. ISVs will need to build and include this native library(.so file) in their android application. The native library runs inside the DualDAR daemon of the android framework and the daemon gives the native library access to the file system. We will refer to this library as DualDAR client library.

Android Application

The Android application is responsible for key management, authentication, installing the native library and other bookkeeping functions. We will refer to this application as DualDAR client application.

Implement the DualDAR client

Create Android Application

As a first step you'll need to create an Android application, targeting Android SDK version 28 and above, that will invoke DualDAR platform APIs and receive platform callbacks. You'll need to mention the target DualDAR SDK version in the manifest file.

Sample DualDAR client AndroidManifest.xml:

<?xml version="1.0"?>
<manifest xmlns:android="" package="">
    <meta-data android:name="supportedDualDarSdkVersion" android:value="1.0"/>
    <service android:name="">
	 <action android:name=""/>

Extend DualDARClient class

Next, you'll need to extend abstract DualDARClient class and implement the callbacks to handle authentication, key management and other tasks. Figure 1 below highlights the various events, callbacks and states. The sections after the diagram provides information on how to extend the abstract class and provide implementation for the client callbacks.

Figure 1: Represents the platform states, user events and the callback client app receives

Client Bringup

During DualDAR workspace creation and user restart (after device restart and data lock state), the client app receives the onClientBringup() callback. The client app should perform all the DualDAR client initialization related activities in this callback.

The client should also install libraries and other supporting files using the installLibrary() API:

  • The getInstalledClientLibraryVersion() API can be used to check the current version of the DualDAR library, and get the newest version of the DualDAR library. This will return null if no library is installed.
public boolean onClientBringup() {
  // Install new version of dual dar client library and other files if version mismatch
  if (!getInstalledClientLibraryVersion().equals(“ < Your client version > ”)) {
    List < String > secondaryLibs = new ArrayList < > ();
    secondaryLibs.add(“ < Your secondary file > ”);
    if (installLibrary(“ < your client library path > ”, secondaryLibs, true) != ERROR_NONE) {
      Log.e(TAG, "Error installing Dual DAR client lib");
      return false;
  return true;

DualDAR setup

During DualDAR Workspace creation, the DualDAR client app also receives the onDualDARSetupForUser() callback. As part of the setup process, the DualDAR client should generate the necessary keys and secrets as shown by the following sample code:

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 primary key and save
  saveEncryptedMasterKey(encryptMasterKeyWithPassword(masterKey, defAuthToken, salt));
  return true;

Set secret

During workspace creation and authentication, the client app should pass their secret/keys to the native client library. The native client library uses these secret/keys to encrypt and decrypt file encryption key. The file encryption keys are used to encrypt and decrypt files. The secret should be set when the platform invokes the onDualDARSetupForUser() and onPasswordAuth() callbacks.

Handle Authentication

When the user is authenticated to the DualDAR Workspace, the DualDAR client app receives onPasswordAuth() callback. In this callback, the DualDAR client app should verify the second layer password and set appropriate secret as shown by the following sample code:

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 primary key on disk with KEK and set to platform
    byte[] masterKey = getSecret(kek, getEncryptedMasterKey());

    // Decrypt the encrypted primary 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;

Handle change password

When the user changes the password for the DualDAR Workspace, the DualDAR client app receives onPasswordChange() callback. DualDAR client app will need to unwrap the existing encrypted primary key and re-wrap the primary key with the new password as shown by the sample code below:

public boolean onPasswordChange(int userId, byte[] oldPassword, byte[] newPassword) {
    byte[] salt = getSalt();
    if(oldPassword == null) {
        oldPassword = getDefaultAuthToken();
        getEncryptedMasterKey(), derivedOldSystemToken, derivedNewSystemToken, salt));
    return true;

Handle reset password

The IT admin can reset the user’s password in case the user has forgotten their password. In order to reset password, the IT admin would need to first setup and activate a token. When the reset password token is set, cleared or reset for DualDAR Workspace, the DualDAR client app is informed via onSetResetPasswordToken(), onClearResetPasswordToken() and onResetPasswordWithToken() callbacks respectively. The DualDAR client app will then need to provision, manage the token and reset password when requested as shown by the following sample code:

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);

    return true;

Implement the native interface

You'll need to build the native library for file encryption and decryption. The native library is installed by the DualDAR client application and loaded in the DualDAR daemon, which provides access to the file system. Details for the native library can be found in the Samsung Mobile Device Management: Native SDK.

Declare entry point

The native interface must have an entry symbol DDAR_ABSTRACT_CRYPTO_SYM with a type of abstract_crypto, so that the system daemon can dynamically load the derived class at the time of device boot up. Crypto library must also declare library version by defining a symbol DDAR_ABSTRACT_CRYPTO_VERSION. This version can be retrieved in the java side by calling getInstalledClientLibraryVersion() API in DualDARClient.

const char * DDAR_ABSTRACT_CRYPTO_VERSION = "1.0";

Native library should perform the following tasks:


The prepare callback is used to initialize crypto materials prior to encryption and decryption, while the platform provides metadata object to access persistent and ephemeral storage. It's called for each file after the data locked state or during file creation.

For example, an implementation of prepare would be to derive the file encryption key (FEK) from the primary key in secret object and store the FEK in the ephemeral cache to be used with encypt/decrypt callbacks:

bool MyTestCrypto::prepare(ddar::context *context, ddar::metadata *md) {
  ddar::secret *sec = context->get_secret("my_master_key_alias");  # vendor client app defined
  struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
  char *iv = NULL;
  char efek[FEK_KEYLEN];
  int rc = md->persistent_get(ALIAS_EFEK, efek);
  if (rc <= 0) {
      // No FEK associate with the file, create new
      mSSL.rand_bytes(my_md->fek, FEK_KEYLEN);
      rc = mSSL.encrypt((unsigned char *)my_md->fek, FEK_KEYLEN,
              (unsigned char *)sec->data, (unsigned char *)iv, (unsigned char *)efek);
      if (rc < 0)
          return false;  // failed to encrypt efek
      md->persistent_set(ALIAS_EFEK, efek, FEK_KEYLEN);  // store efek
  } else {
      mSSL.decrypt((unsigned char *)efek, rc,
          (unsigned char *)sec->data, (unsigned char *)iv, (unsigned char *)my_md->fek);


The encrypt callback is called when a file is currently being written to disk. The native interface will encrypt the data prior to being written to the disk:

bool MyTestCrypto::encrypt(ddar::metadata *md, void *pt, void *ct, unsigned long page_offset, int page_len) {
 struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
 if(mSSL.encrypt((unsigned char *)pt, page_len,
         (unsigned char *)my_md->fek, NULL,
         (unsigned char *)ct) > 0)
     return true;
 return false;


The decrypt callback is called when a file is currently being read from disk. The native interface will need to decrypt the data in-place:

bool MyTestCrypto::decrypt(ddar::metadata *md, void *ct, unsigned long page_offset, int page_len) {
  struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
  if(mSSL.decrypt((unsigned char *)ct, page_len,
          (unsigned char *)my_md->fek, NULL,
          (unsigned char *)ct) > 0)  // implement crypto inplace
      return true;
  return false;


The DualDAR native framework provides the following APIs in the context class to capture logs:

  • logd(const char *fmt) – writes debug log to both adb, logcat and dumpstate
  • loge(const char *fmt) – writes debug log to both adb, logcat and dumpstate

The Android application can use Log class to write logs or use its own logging mechanism to write logs.

Logging and Debugging

To get the log files for debugging, contact Samsung support team to get the issue tracker light tool. The tool enables to extract log files. The following list important log files related to DualDAR workspace:

  1. act_dumpstate.txt – entire framework and app logs are saved here.
  2. ddar_fw.txt – dualdar framework logs are saved here
  3. ddar_log.txt – native library logging is saved here.

Deploy the DualDAR client

DualDAR client APK needs to be installed on end user’s device prior to creation of DualDAR Workspace. DualDAR client can either be installed by UEM or be uploaded to a public or private app store.

Need more help?

For more information, see the: