Back to top

Deprecation of TIMA/CCM Keystore support

When the Samsung Knox platform was first released, Samsung introduced the TrustZone-based Integrity Measurement Architecture (TIMA) Keystore and Client Certificate Manager (CCM) to ensure that highly sensitive data, such as user credentials, were protected. Cryptographic keys and certificates were locked down using this tamper-proof, detection-based system.

In the spring of 2021, Google introduced the Android Keystore2 as a replacement for the current Keystore in Android 12 (S) OS.

The deprecation timeline is as follows:

  • October 2020 — Deprecated TIMA/CCM Keystore APIs in Knox 3.7 (API level 33)
  • March 2021 — Google introduced Android Keystore2 for Android 12 (S) OS
  • 3Q 2021 — Keystore APIs no longer work on devices running Android 12 (S) OS and Knox 3.8

What’s being deprecated in Android 12 (S)?

The following table provides an overview of all classes that are no longer supported in Android 12 (S), along with a brief description of each.

Package: com.samsung.android.knox.keystore
Unsupported classes Description
CCMProfile This class defines the profile used to set up the Client Certificate Manager token.
ClientCertificateManager This class provides APIs to manage certificates in TIMA Client Certificate Manager (CCM).
TimaKeystore This class provides APIs to enable and disable the TIMA Keystore.
CEPConstants This class contains all required constant values used inside the Certificate Enrollment service.
CMCProfile The Certificate Management over CMS (CMC) profile to enroll the certificate.
CMPProfile The Certificate Management Protocol (CMP) profile to enroll the certificate.
CSRProfile This class defines the profile used to set up the Certificate Signing Request (CSR) template.
EnrollmentProfile This abstract class defines a basic profile for certificate enrollment.
SCEPProfile This class provides a concrete implementation of SCEP EnrollmentProfile.

How does the deprecation impact my apps?

If you installed keys on any OS version prior to Android 12 (S), they will automatically be migrated to Keystore2 when the device is upgraded to Android 12 (S).

As per Android’s design, usage keys are blocked across different user domains. With the exception of Knox legacy containers, devices managed through profile owner (PO) or work profile on company-owned (WP-C) modes have both the workspace and UEM client installed in the work profile. Corporate owned managed profile (COMP) devices, however, can have both the workspace and UEM client installed on either the personal side or the work profile. These permissions allow the UEM to install keys within either of the device’s profile domains.

To grant permission for apps to use installed keys, use the Knox API addPermissionApplicationPrivateKey. Refer to the following Java code snippet for an example:

example)
String pkgName = "com.example.app";
String host = "myserver.com";
int port = 80;
String alias = "mykey";
PermissionApplicationPrivateKey pkey = new PermissionApplicationPrivateKey(pkgName, host, port, alias);
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(context);
CertificatePolicy certificatePolicy = ekm.getCertificatePolicy();
try {
    boolean result = certificatePolicy.addPermissionApplicationPrivateKey(pkey);
    if (true == result) {
        // application will receive permission to access private key, when it
        // ask for it.
    } else {
        // failure to set policy
    }
   } catch (SecurityException e) {
     Log.w(TAG, "SecurityException: " + e);
   }
      

To ensure you do not encounter issues with your stored credentials, you need to modify any Keystore-related APIs using the guidance provided by the Android Developer documentation. Refer to the following Java code snippets for examples on how to generate new keys, work with Keystore entries, and sign and verify data.

example) Generate a new private key
/*
 * Use a PrivateKey in the KeyStore to create a signature over
 * some data.
 */
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof PrivateKeyEntry)) {
    Log.w(TAG, "Not an instance of a PrivateKeyEntry");
    return null;
}
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(((PrivateKeyEntry) entry).getPrivateKey());
s.update(data);
byte[] signature = s.sign();

Additional information

Is this page helpful?