Manage device applications
Now that you have set up the device admin receiver and activated your license, you can use the APIs to manage certificates in TIMA CCM.
Create CCM Profile
This method initializes a CCMProfile object, sets its accessControlMethod to default and asks the user if they want to allow all the packages in the container.
private void createCCMProfile() { mCCMProfileObj = new CCMProfile(); // Initialize a CCMProfile object mCCMProfileObj.accessControlMethod = CCMProfile.AccessControlMethod.LOCK_STATE; // Set its accessControlMethod to the default method whitelistAllPackages(); // Proceed to ask the user if they want to allow all packages }
Add all packages to an allowlist
This method asks the user if they want to allow all packages in the container to access the token. Whitelisting allows them access to the token. If they do, skip asking user to allow specific package names and set the CCM profile. If they don't, ask the user to allow specific package names, then set the CCM profile.
private void whitelistAllPackages() { new AlertDialog.Builder(this) // Create a dialog box to show to the user .setTitle(getString(R.string.whitelist_all_packages)) // Set the dialog box's title .setMessage(getString(R.string.whitelist_all_packages_message)) // Set the dialog box's message // Set the action buttons .setPositiveButton(getString(R.string.opt_yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Whitelist all the packages, then set the CCM profile mCCMProfileObj.whiteListAllPackages = true; setCCMProfile(); } }).setNegativeButton(getString(R.string.opt_no), new DialogInterface.OnClickListener() { // Ask the user for specific package names to be allowed @Override public void onClick(DialogInterface dialog, int which) { mCCMProfileObj.whiteListAllPackages = false; whitelistPackagesToAccessToken(); } }).show(); // Show the dialog box to the user }
Whitelist specific packages
This method prompts the user to select certain packages in the container to be allowed to access the token.
private void whitelistPackagesToAccessToken() { final List<String> selectedPackages = new ArrayList<>(); // List to contain the user's selected packages final List<String> installedPackages = getInstalledPackages(); // List of installed packages on the device AlertDialog.Builder builder = new AlertDialog.Builder(this); // Create a dialog box to show to the user builder.setTitle(getString(R.string.whitelist_packages_list_title)); // Set the dialog box's title final String[] installedPackagesArr = installedPackages.toArray(new String[installedPackages.size()]); // Convert the list of installed packages to an array builder.setMultiChoiceItems(installedPackagesArr, null, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int indexSelected, boolean isChecked) { String selectedPackage = installedPackagesArr[indexSelected]; // If user selects a package in the list- if (isChecked) { // And the package is checked, then add it to the selected items selectedPackages.add(selectedPackage); } else if (selectedPackages.contains(selectedPackage)) { // If not, remove it from selected items selectedPackages.remove(selectedPackage); } } }) // Set the action buttons .setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { mCCMProfileObj.packageList = selectedPackages; // Set the CCM Profile's packageList to that of allowed packages by user setCCMProfile(); // Proceed to apply the CCM profile dialog.dismiss(); } }) .setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // Cancel CCM Profile creation mCCMProfileObj = null; mUtils.log(getString(R.string.cancel_ccm_profile)); dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.show(); // Show the dialog box to the user }
Set CCM Profile
This method applies the CCM Profile created by the user through the dialog boxes.
private void setCCMProfile () { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the setCCMProfile method lives mUtils.log(getString(R.string.about_to_apply_profile)); mUtils.log(getString(R.string.display_ccm_access, mCCMProfileObj.accessControlMethod)); // display the current CCM Profile Object's access method mUtils.log(getString(R.string.display_ccm_whitelist_all_packages, mCCMProfileObj.whiteListAllPackages)); // display whether the CCM profile allowed all packages if (!mCCMProfileObj.whiteListAllPackages) { // if not allowing all packages, display each allowed package mUtils.log(getString(R.string.display_ccm_packagelist)); for (String packageName : mCCMProfileObj.packageList) { // display the CCM profile's package list mUtils.log(getString(R.string.input_package_name, packageName)); } } try { boolean result = clientCertificateManager.setCCMProfile(mCCMProfileObj); // Apply the CCM Profile if (result) { // Display CCM profile set result mUtils.log(getString(R.string.ccm_profile_set_successfully)); } else { mUtils.log(getString(R.string.ccm_profile_failed)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Get CCM Profile
This method gets the current CCM Profile set through setCCMProfile and displays its details to the user.
private void getCCMProfile () { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the setCCMProfile method lives try { CCMProfile currentProfile = clientCertificateManager.getCCMProfile(); if (currentProfile != null) { mUtils.log(getString(R.string.display_current_profile)); mUtils.log(getString(R.string.display_ccm_access, currentProfile.accessControlMethod)); // display the current CCM Profile Object's access method mUtils.log(getString(R.string.display_ccm_whitelist_all_packages, currentProfile.whiteListAllPackages)); // display whether the CCM profile allowed all packages if (!currentProfile.whiteListAllPackages) { // if not allowing all packages, display each allowed package mUtils.log(getString(R.string.display_ccm_packagelist)); for (String packageName : currentProfile.packageList) { // display the CCM profile's package list mUtils.log(getString(R.string.input_package_name, packageName)); } } } else { mUtils.log(getString(R.string.no_profile_set)); } } catch (Exception e) { mUtils.processException(e, TAG); } }
Delete CCM Profile
This method deletes the current CCM Profile.
private void deleteCCMProfile () { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the setCCMProfile method lives try { boolean result = clientCertificateManager.deleteCCMProfile(); if (result) { // Delete CCM Profile result mUtils.log(getString(R.string.ccm_profile_delete_successfully)); } else { mUtils.log(getString(R.string.ccm_profile_delete_failed)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Get default Certificate Alias
This method returns the default certificate alias, if there is one for the device. The default certificate is a device unique certificate rooted at Samsung root certificate. It can be used to uniquely identify a Samsung device.
private void getDefaultCertificateAlias() { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the setCCMProfile method lives try { String defaultAlias = clientCertificateManager.getDefaultCertificateAlias(); if (defaultAlias != null) { mUtils.log(getString(R.string.get_default_certificate, defaultAlias)); // Display the default certificate alias } else { mUtils.log(getString(R.string.no_default_certificate)); // No default certificate alias is available } } catch (Exception e) { mUtils.processException(e, TAG); } }
Create Certificate
This method initializes a CertificateProfile object, and asks the user to set its' alias.
private void createCertificate() { mCertificateProfile = new CertificateProfile(); mUtils.log(getString(R.string.creating_new_certificate_profile)); configureCertificate(); }
Configure Certificate
This method asks the user to provide a certificate alias, whether or not to allow wi-fi, whether or not to allow all packages and whether or not to enable CSRResponse.
private void configureCertificate() { AlertDialog.Builder builder = new AlertDialog.Builder(this); // Build a dialog to show the user builder.setTitle(getString(R.string.configure_certificate)); // WIth the title "Configure Certificate" View viewInflated = LayoutInflater.from(this).inflate(R.layout.prompt_certificate_alias_wifi_packages_csrresponse, (ViewGroup) findViewById(R.id.configure_certificate_group), false); final EditText edTxtCertAlias = (EditText) viewInflated.findViewById(R.id.edtxtCertificateAlias); final CheckBox chkAllowAllPackages = (CheckBox) viewInflated.findViewById(R.id.chkAllowAllPackages); final CheckBox chkAllowWifi = (CheckBox) viewInflated.findViewById(R.id.chkAllowWifi); final CheckBox chkIsCSRResponse = (CheckBox) viewInflated.findViewById(R.id.chkIsCSRResponse); builder.setView(viewInflated); builder.setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mCertificateProfile.alias = edTxtCertAlias.getText().toString(); mCertificateProfile.allowAllPackages = chkAllowAllPackages.isChecked(); mCertificateProfile.allowWiFi = chkAllowWifi.isChecked(); mCertificateProfile.isCSRResponse = chkIsCSRResponse.isChecked(); mUtils.log(getString(R.string.configuring_certificate_with)); mUtils.log(getString(R.string.certificate_alias_is, mCertificateProfile.alias)); mUtils.log(getString(R.string.certificate_allow_all_packages_is, mCertificateProfile.allowAllPackages)); mUtils.log(getString(R.string.certificate_allow_wifi_is, mCertificateProfile.allowWiFi)); mUtils.log(getString(R.string.certificate_iscsrresponse_is, mCertificateProfile.isCSRResponse)); if (!(mCertificateProfile.alias).equals("")) { // If provided alias is not empty string if (mCertificateProfile.allowAllPackages) { // Check if allow all packages checked setCertificatePathAndPassword(); // If it is, skip choosing specific packages to choose } else { allowPackagesToAccessCertificate(); // If it isn't, prompt user for specific packages to choose } } else { mUtils.log(getString(R.string.provide_valid_alias)); // If provided alias is empty, prompt user for valid alias } } }); builder.setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mCertificateProfile = null; // Certificate creation cancelled. Reset the certificate profile. mUtils.log(getString(R.string.certificate_profile_cancelled)); dialog.cancel(); } }); builder.show(); }
Allow packages to access current Certificate
private void allowPackagesToAccessCertificate () { final List<String> selectedPackages = new ArrayList<>(); // List to contain the user's selected packages final List<String> installedPackages = getInstalledPackages(); // List of installed packages on the device AlertDialog.Builder builder = new AlertDialog.Builder(this); // Create a dialog box to show to the user builder.setTitle(getString(R.string.whitelist_packages_list_title)); // Set the dialog box's title final String[] installedPackagesArr = installedPackages.toArray(new String[installedPackages.size()]); // Convert the list of installed packages to an array builder.setMultiChoiceItems(installedPackagesArr, null, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int indexSelected, boolean isChecked) { String selectedPackage = installedPackagesArr[indexSelected]; // If user selects a package in the list- if (isChecked) { // And the package is checked, then add it to the selected items selectedPackages.add(selectedPackage); } else if (selectedPackages.contains(selectedPackage)) { // If not, remove it from selected items selectedPackages.remove(selectedPackage); } } }) // Set the action buttons .setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { mCertificateProfile.packageList = selectedPackages; // Set the CertificateProfile's packageList to that of allowed packages by user setCertificatePathAndPassword(); // Proceed to set CertificateProfile's path and password dialog.dismiss(); } }) .setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // Cancel CertificateProfile creation mCertificateProfile = null; // Certificate creation cancelled. Reset the certificate profile. mUtils.log(getString(R.string.certificate_profile_cancelled)); dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.show(); // Show the dialog box to the user }
Set Certificate path and password
This method sets the current certificate's path and password.
private void setCertificatePathAndPassword() { AlertDialog.Builder builder = new AlertDialog.Builder(this); // Build a dialog for the user builder.setTitle(getString(R.string.set_cert_path_and_pass)); // with the title "Set Certificate Path and Password" View viewInflated = LayoutInflater.from(this).inflate(R.layout.prompt_certificate_path_and_password, (ViewGroup) findViewById(R.id.certificate_pass_and_path_group), false); final EditText edTxtCertPath = (EditText) viewInflated.findViewById(R.id.edTxtCertificatePath); final EditText edTxtCertPassword = (EditText) viewInflated.findViewById(R.id.edTxtCertificatePassword); builder.setView(viewInflated); builder.setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String path = edTxtCertPath.getText().toString(); String password = edTxtCertPassword.getText().toString(); if (!path.equals(getString(R.string.path_hint))) { mUtils.log(getString(R.string.provided_cert_path_and_pass)); installCertificate(path, password); // Install the path and password } else { mCertificateProfile = null; // Certificate creation cancelled. Reset the certificate profile. mUtils.log(getString(R.string.invalid_path)); } } }); builder.setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mCertificateProfile = null; // Certificate creation cancelled. Reset the certificate profile. mUtils.log(getString(R.string.certificate_profile_cancelled)); dialog.cancel(); } }); builder.show(); }
Install Certificate
This method installs the current certificate with user-provided details.
private void installCertificate(String path, String password) { mUtils.log(getString(R.string.installing_certificate)); EnterpriseKnoxManager enterpriseKnoxManager = EnterpriseKnoxManager.getInstance(this); // Initialize the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = enterpriseKnoxManager.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the installCertificate method lives try { byte[] certificateBuffer = Utils.getByteArrayFromPath(path); // Get the byte array from the provided path boolean result = clientCertificateManager.installCertificate(mCertificateProfile, certificateBuffer, password); // Install the certificate with the profile config, byte array and password provided if (result) { mUtils.log(getString(R.string.certificate_profile_installed_successfully)); } else { mUtils.log(getString(R.string.certificate_profile_installation_failed)); } } catch (Exception e) { mUtils.processException(e, TAG); } }
Get installed packages
This method returns a list of installed packages' package names on the device.
private List<String> getInstalledPackages () { List<PackageInfo> packages = getPackageManager().getInstalledPackages(0); // Get list of installed packages ArrayList<String> packageList = new ArrayList<>(); // Initialize a list of package names for (PackageInfo pInfo : packages) { // For each installed package packageList.add(pInfo.packageName); // Add its package name to the return list } return packageList; }
Prompt user to delete Certificate
This method prompts the user for a certificate alias, then delete that certificate.
private void promptUserToDeleteCertificate () { AlertDialog.Builder builder = new AlertDialog.Builder(this); // Create a dialog box builder.setTitle(getString(R.string.delete_certificate)); // with the title "Delete Certificate." View viewInflated = LayoutInflater.from(this).inflate(R.layout.prompt_certificate_alias_to_delete, (ViewGroup) findViewById(R.id.delete_cert_group), false); final EditText edTxtCertAlias = (EditText) viewInflated.findViewById(R.id.edtxtCertificateAlias); builder.setView(viewInflated); builder.setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String alias = edTxtCertAlias.getText().toString(); // Get the user provided alias if (!alias.equals("")) { // If alias is valid deleteCertificate(alias); // Delete the certificate with an alias that matches provided alias. } else { mUtils.log(getString(R.string.no_alias_entered)); } } }); builder.setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mCertificateProfile = null; mUtils.log(getString(R.string.certificate_profile_deletion_cancelled)); dialog.cancel(); } }); builder.show(); }
Delete certificate
This method deletes Certificate with alias that matches provided alias.
private void deleteCertificate (String alias) { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the setCCMProfile method lives try { boolean result = clientCertificateManager.deleteCertificate(alias); // attempt to delete the certificate if (result) { mUtils.log(getString(R.string.certificate_profile_deleted_successfully)); } else { mUtils.log(getString(R.string.certificate_profile_deletion_failed)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Prompt user for a package name
This method prompts the user for a package name to either add it to exempt list, remove it from exempt list or check if it is affected by CCM Policy.
private void promptUserForPackage (final int type) { AlertDialog.Builder builder = new AlertDialog.Builder(this); // Create a dialog box switch (type) { // With a title depending on what button the user pressed case ADD_PACKAGE: // Title to add package to exempt list builder.setTitle(getString(R.string.add_package_to_exempt_list)); break; case REMOVE_PACKAGE: // Title to remove package from exempt list builder.setTitle(getString(R.string.remove_package_from_exempt_list)); break; case CHECK_PACKAGE: // Title to check if CCM policy is enabled for a package builder.setTitle(getString(R.string.check_ccm_policy_enabled_for_package)); break; default: return; } View viewInflated = LayoutInflater.from(this).inflate(R.layout.prompt_package_name, (ViewGroup) findViewById(R.id.package_name_input_group), false); final EditText edTxtPackageName = (EditText) viewInflated.findViewById(R.id.edTxtPackageName); builder.setView(viewInflated); builder.setPositiveButton(getString(R.string.option_confirm), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String packageName = edTxtPackageName.getText().toString(); // Get the user provided package name switch (type) { case ADD_PACKAGE: addPackageToExemptList(packageName); break; case REMOVE_PACKAGE: removePackageFromExemptList(packageName); break; case CHECK_PACKAGE: checkCCMEnabledForGivenPackage(packageName); break; default: break; } } }); builder.setNegativeButton(getString(R.string.option_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.show(); }
Add package to the exempt list
This method adds the given package name to the exempt list. This is required in case an app (running in background) needs access to certificates when the device/container is locked or user is not expected to enter password. An example package which needs exemption could be a third party VPN application which needs access to certificates without user interaction.
private void addPackageToExemptList (String packageName) { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the addPackageToExemptList method lives try { boolean result = clientCertificateManager.addPackageToExemptList(packageName); // attempt to add package name to exempt list if (result) { mUtils.log(getString(R.string.package_name_added_exempt_list_success)); } else { mUtils.log(getString(R.string.package_name_added_exempt_list_failed)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Remove package from the exempt list
This method removes the given package name from the exempt list.
private void removePackageFromExemptList (String packageName) { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the removePackageFromExemptList method lives try { boolean result = clientCertificateManager.removePackageFromExemptList(packageName); // attempt to add package name to exempt list if (result) { mUtils.log(getString(R.string.package_name_remove_exempt_list_success)); } else { mUtils.log(getString(R.string.package_name_remove_exempt_list_failed)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Check CCM Policy for a package
This method checks if CCM policy is enabled for a given package.
private void checkCCMEnabledForGivenPackage (String packageName) { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class ClientCertificateManager clientCertificateManager = ekm.getClientCertificateManagerPolicy(); // Get the ClientCertificateManager where the isCCMPolicyEnabledForPackage method lives try { boolean result = clientCertificateManager.isCCMPolicyEnabledForPackage(packageName); // attempt to add package name to exempt list if (result) { mUtils.log(getString(R.string.ccm_policy_enabled_for_package, packageName)); } else { mUtils.log(getString(R.string.ccm_policy_not_enabled_for_package, packageName)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Toggle TIMA Keystore
This method enables/disables the TIMA Keystore.
private void toggleTimaKeystore () { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class TimaKeystore timaKeystore = ekm.getTimaKeystorePolicy(); // Get the TimaKeystore object where the enableTimaKeystore method lives try { boolean isTimaKeystoreEnabled = timaKeystore.isTimaKeystoreEnabled(); // Check current status of the TimaKeystore boolean result = timaKeystore.enableTimaKeystore(!isTimaKeystoreEnabled); // Enable/disable the Tima Keystore if (result) { mUtils.log(getString(R.string.toggled_tima_keystore, !isTimaKeystoreEnabled)); } else { mUtils.log(getString(R.string.failed_to_toggle_tima_keystore)); } } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Display TIMA Keystore status
This method displays TIMA Keystore status (enabled/disabled).
private void isTimaKeystoreEnabled () { EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(this); // Instantiate the EnterpriseKnoxManager class TimaKeystore timaKeystore = ekm.getTimaKeystorePolicy(); // Get the TimaKeystore object where the enableTimaKeystore method lives try { boolean isTimaKeystoreEnabled = timaKeystore.isTimaKeystoreEnabled(); // Check current status of the TimaKeystore mUtils.log(getString(R.string.tima_keystore_status, isTimaKeystoreEnabled)); } catch (SecurityException e) { mUtils.processException(e, TAG); } }
Declare permissions in the manifest
Declare the following permissions in AndroidManifest.xml.
<uses-permission android:name="com.example.supportlibclient.SUPPORT_PERMISSION" /> <uses-permission android:name="com.samsung.android.knox.permission.KNOX_CCM"/> <uses-permission android:name="com.samsung.android.knox.permission.KNOX_CCM_KEYSTORE"/> <uses-permission android:name="com.samsung.android.knox.permission.KNOX_TIMA_KEYSTORE"/>
Tutorial Progress
You are 6/7 done! Go to the next step.