Menu

Certificate Enrollment Protocol

This topic explains how you can add support to provision digital certificates for use by apps in the Knox Workspace using the Certificate Enrollment Protocol (CEP) service.

About CEP service

Mobile apps such as email, Wi-Fi, browser, and so on, use digital certificates for authentication, digital signatures, and encryption. CEP enables MDMs and third-parties to perform certificate enrollment without the need of any manual intervention. 

You can enable certificate enrollment in the Knox platform using different protocols. Samsung Knox CEP service supports the following enrollment protocol standards:

  • Simple Certificate Enrollment Protocol (SCEP)
  • Certificate Management Protocol (CMP)
  • Certificate Management over Cryptographic Message Syntax (CMC)
  • Enrollment Over Secure Transport (EST)

SCEP, CMP, and CMC are widely used certificate enrollment protocols that enable provisioning of digital certificates. For more information on SCEP, CMP, and CMC, see Internet Engineering Task Force (IETF) Draft, RFC 4210, and RFC 7030.

CEP service acquires asymmetric keys

Apps use the CEP service to acquire the public part of an asymmetric key. Asymmetric keys have a public part and a private part. The private part never leaves the Keystore, but the public part is distributed freely. An app uses the Samsung Knox CEP service to acquire the public part of the key, encrypt a message, and send the encrypted message to whoever issued the public key. The owner of the key can then use the Keystore’s functionality to apply the private part of the asymmetric key to the encrypted message and decrypt it.

Certificate operations using CEP service

Using the Samsung Knox Certificate Enrollment Policy APIs, you can perform the following operations.

  • Enroll certificates
  • Renew certificates
  • Delete certificates
  • Check enrollment or renewal status

Install and access CEP service

The IT admin can download the required protocol-specific CEP service APK (SCEP, CMP and EST) from the Samsung Knox website and install the APK either inside the Knox Workspace or in the user space, depending on the requirement. 

For example, if the requirement is to provision and manage certificates for apps inside the Knox Workspace only, then you must install the CEP service(s) only inside the Workspace. If the requirement is to provision and manage certificates for apps at user space level, then install the CEP service in the user space to provision and manage certificates.

CEP service only operates within the scope of the Knox Workspace or user space, depending on where it is installed.

MDM agents can call the CEP service(s) present in its own user space or its own Workspace. MDM agents do not have access to the service created outside its scope.

Note: Starting with Knox v2.1, three CEP service APKs are available in Knox Marketplace: SCEP service, CMP service, and the CMC service. You can download and install the service(s) based on your requirements.

Certificate Enrollment Policy (CEP) APIs

To use the Certificate Enrollment Policy (CEP) APIs to provisions digital certificates, follows these steps: 

  1. Get instance of EnterpriseCertEnrollPolicy
  2. Listen to intents
  3. Perform certificate enrollment operations

Note: To use the CEP APIs, you must have the com.samsung.android.knox.permission.KNOX_CERTIFICATE_ENROLLMENT permission which has a protection level of signature.

Obtain an instance of EnterpriseCertEnrollmentPolicy

This call returns the instance of EnterpriseCertEnrollPolicy, which you can use to connect and perform certificate enrollment functionality with the CEP Service present in the same user space as the caller.

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance();
EnterpriseCertEnrollPolicy cep = ekm.getEnterpriseCertEnrollPolicy(Context, cepProtocol);

For CEP service installed in the Knox Workspace, obtain an instance of EnterpriseCertEnrollPolicy from KnoxContainerManager by providing the container ID explicitly. The caller (admin) must be the owner of that Workspace, otherwise the binding is not successful. If you specify an invalid container ID in the call, then it returns a null object.

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); 
KnoxContainerManager kcm = ekm.getKnoxContainerManager(Context, containerID); 

//When you create container successfully, containerID is returned using intent.  
EnterpriseCertEnrollPolicy cep = kcm.getEnterpriseCertEnrollPolicy(cepProtocol);

Note: The binding of the certificate enrollment service happens together with the initialization of EnterpriseCertEnrollPolicy object.

Listen to intents

The caller or agent must listen for the following intent to get the enrollment operation result or status.

CEP_ACTION_CERT_ENROLL_STATUS

The CEP_ACTION_SERVICE_DISCONNECTED intent received has the container ID value specified in the serviceuserid. If the serviceuserid value is 0, it indicates the UserID of the CEP Service in which binding or unbinding has happened to the CEP service present in the same user space as the caller.

Public class EnterpriseCEPpolicyReciever extends BroadcastReceiver {     
          public void onReceive(Context context, Intent intent) {
           if(intent.getAction().equalsIgnoreCase(
              CEPConstants.CEP_ACTION_SERVICE_DISCONNECTED)) {
              String serviceUserId =   
                intent.getExtra(CEPConstants.EXTRA_SERVICE_USERID);// User Id of the 
                                                     Certificate Enrollment Service.
              String servicePkgName = 
                intent.getExtra(CEPConstants.EXTRA_SERVICE_PROTOCOL);// Protocol 
                                        supported by Certificate Enrollment Service.
           }else if( 
intent.getAction().equalsIgnoreCase(CEPConstants.CEP_ACTION_CERT_ENROLL_STATUS)){
              int status = intent.getIntExtra(CEPConstants.EXTRA_ENROLL_STATUS, -1); // tells about the status of the request.
           }
          }
}

Perform certificate enrollment operations

Using the certificate enrollment APIs, you can perform the following operations.

  • Enroll certificate
  • Renew certificate
  • Delete certificate
  • Check enrollment or renewal status

Enroll a certificate

To enroll a user certificate, use the enrollUserCertificate API.  This API issues a public key X.509 certificate by sending a self-signed CSR to the CA server for enrolling in a PKI represented by the CA server.

The following sample code example illustrates enrolling a user certificate at user space level.

EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance();
 try {
     List  allowedPackages = new ArrayList();
     allowedPackages.add("com.android.email");
     String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP
     String refNum = ekm.getEnterpriseCertEnrollPolicy(Context, cepProtocol).enrollUserCertificate(enrollmentProfile,allowedPackages, hashCACert);
 } catch (SecurityException e) {
     Log.w(TAG, "Exception" + e);
 }

Note: The refNum is unique for each transaction. The corresponding request result is broadcast through broadcast intent CEP_ACTION_CERT_ENROLL_STATUS. Agents can map the refNum and know the status of the corresponding request.

The following sample code example illustrates how to enroll a user certificate in the Knox Workspace.

// When you create a container successfully, containerID is returned using intent. // Use this containerID in the following API. String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); KnoxContainerManager kcm = ekm.getKnoxContainerManager(Context, containerID); EnterpriseCertEnrollPolicy mEnterpriseCertEnrollPolicy = kcm.getEnterpriseCertEnrollPolicy(cepProtocol); try { List allowedPackages = new ArrayList(); allowedPackages.add("com.android.email"); String refNum = mEnterpriseCertEnrollPolicy.enrollUserCertificate(enrollmentProfile,allowedPackages, caCertHash); } catch (SecurityException e) { Log.w(TAG, "Exception" + e); }


If the certificate enrollment succeeds, it sends a broadcast with the hash or fingerprint of the received certificate. You must listen for the CEP_ACTION_CERT_ENROLL_STATUS broadcast intent to receive the hash value.

Renew a certificate

To renew an enrolled user certificate, use the renewUserCertificate API. This API renews an existing X.509 certificate and sends a new CSR to the CA server. The CSR is signed using the existing certificate.

If the certificate enrollment succeeds, it sends a broadcast with a hash or fingerprint of the received certificate. This API renews an existing X.509 certificate and sends a new CSR to the CA server. The CSR is signed using the existing certificate.

Note: If the Keystore type is CCM, then old keypair is used for generating the CSR.

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); try { List allowedPackages = new ArrayList(); allowedPackages.add("com.android.email"); String refNum = ekm.getEnterpriseCertEnrollPolicy(Context, cepProtocol).renewUserCertificate(certHash, allowedPackages); } catch (SecurityException e) { Log.w(TAG, "Exception" + e); }

Note: The CertHash of each alias is sent post-enrollment using the broadcast intent CEP_ACTION_CERT_ENROLL_STATUS. Alternatively, an agent can get the certificate directly from Android or CCM Keystore using the desired alias and then calculate the CertHash.

Delete a certificate

To delete a user certificate in the device, use the deleteUserCertificate API. This API deletes the local X.509 certificate specified by the certificate hash value.

Note: Deleting a certificate is not the same as certificate revocation. Certificate revocation in the CA server and MDM registry cleanup must be performed out-of-band.

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); try { int status = ekm.getEnterpriseCertEnrollPolicy(Context, cepProtocol).deleteUserCertificate(certHash); } catch (SecurityException e) { Log.w(TAG, "Exception" + e); }

Check enrollment or renewal status

To get the status of the certificate enrollment or renewal, use the getCertEnrollmentStatus API. This API returns the certificate enrollment status for the given request ID.  The agent or caller needs to provide the TxId of the request for the expected status. The transactionId of each request is sent through broadcast intent CEP_ACTION_CERT_ENROLL_STATUS.

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP //for SCEP EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); try { int status = ekm.getEnterpriseCertEnrollPolicy(Context, cepProtocol).getCertEnrollmentStatus(transactionId); } catch (SecurityException e) { Log.w(TAG, "Exception" + e); }

Enroll a certificate using SCEP

Following example illustrates how an enterprise IT admin provisions a certificate using Simple Certificate Enrollment Protocol (SCEP) on Samsung Knox devices.

About Simple Certificate Enrollment Protocol

SCEP has the following characteristics.

  • Only supports RSA-based cryptography, or asymmetric keys
  • Allows the secure issuance of certificates to large numbers of network devices using an automatic enrollment technique
  • Specifies how a device communicates with a CA, how it retrieves the CA’s public key, and how to enroll a device with the CA

Prequisites for enrolling a certificate

The following are the requirements for enrolling a certificate.

  • Knox Workspace is installed on a device.
  • The MDM has the com.samsung.android.knox.permission.KNOX_CERTIFICATE_ENROLLMENT permission.
  • SCEP service is installed in the Knox Workspace.
  • A CA server enabled with SCEP support is available. For example, a Windows server 2008 or later versions with NDES enabled, Symantec CA, and so on.

Tima Keystore(CCM) overview

Perform certificate enrollment

IT admins can trigger certificate enrollment from MDM/EMM/Admin console, passing SCEP profile to the SCEP service installed on the Knox device.

To trigger a certificate enrollment, perform the following steps.

  1. Get the challenge password from the SCEP server.

IT admins must get the challenge password from the enterprise SCEP/CA server, before triggering certificate enrollment request.

Note: Each SCEP/CA Server has a different means to retrieve this challenge password.

  1. Create the SCEP profile object.

Once the MDM agent receives the challenge password from the IT admin, the MDM agent must create the enrollment profile object.

EnrollmentProfile enrollmentProfile = new SCEPProfile();
  enrollmentProfile.scepUrl = "http://host:port/uri";
  enrollmentProfile.challengePassword = ""; // challenge password from CEP Server
  enrollmentProfile.scepProfileName = "emailprofile"; //SCEP Profile name
  enrollmentProfile.validitytimeForChallenge = 60; 
  
  //validaty time for the challenge in minutes.
  enrollmentProfile.challengeLength = 16; // Challenge byte length
  enrollmentProfile.setProfileType(CEPConstants.CERT_PROFILE_TYPE_SCEP); 
  
  // SCEP Protocol is used for Enrolment.
  enrollmentProfile.subjectName = "CN=admin";  // Subject name for the client 
                                                  certificate.
  enrollmentProfile.subjectAlterNativeName="user.name@samsung.com"; 
 
  // Client Account's email address.
  enrollmentProfile.setKeystoreType(CEPConstants.CEP_KEYSTORETYPE_CCM); 
 
// Keystore Type SCEP or CCM.
  enrollmentProfile.setKeySize(2048);
  enrollmentProfile.setKeyPairAlgorithm(CEPConstants.CEP_KEYALGO_TYPE_RSA); 
 
//Only algorithm supported now.
  enrollmentProfile.setCertificateAlias("cert");
 
  1. Instantiate the CEP for the Knox Workspace.

Agent or caller has to initialize the EnterpriseCertEnrollPolicy

String cepProtocol = CEPConstants.CERT_PROFILE_TYPE_SCEP 
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(); 
KnoxContainerManager kcm = ekm.getKnoxContainerManager(Context, containerID); 
   
// When you create container successfully, containerID is returned using intent.
EnterpriseCertEnrollPolicy cep = kcm.getEnterpriseCertEnrollPolicy(cepProtocol);
 
  1. Trigger the enrollment operation and store the reference ID:
    • Trigger the enrollment request with the enrollment profile created in step 2
    • Agent must store the RefNum unique value returned for each transaction (with the alias)
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance();
 try {
     List  allowedPackages = new ArrayList();
     allowedPackages.add("com.android.email");
     String refNum = cep.enrollUserCertificate(enrollmentProfile,allowedPackages, hashCACert);
 } catch (SecurityException e) {
     Log.w(TAG, "Exception" + e);
 }
 
  1. Listen to the receiver and store the broadcast response:
    • Send the broadcast for each such enrollment/renew request with the corresponding refNum.
    • Store the values received in broadcast for the corresponding refNum/alias.
public class CertEnrolBindReciever extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
     	if (intent.getAction().equalsIgnoreCase(CEPConstants.CEP_ACTION_CERT_ENROLL_STATUS)) {
     		String certHash = intent.getStringExtra(CEPConstants.EXTRA_ENROLL_CERT_HASH);
    		String transactionId  =
intent.getStringExtra(CEPConstants.EXTRA_ENROLL_TRANSACTION_ID);
String alias = intent.getStringExtra(CEPConstants.EXTRA_ENROLL_ALIAS);
    		int status = intent.getIntExtra(CEPConstants.EXTRA_ENROLL_STATUS, -1);
String refNum = intent.getStringExtra(CEPConstants.EXTRA_ENROLL_REFERENCE_NUMBER);
//Store the values in DB against the Alias and RefNum, received in step 3.4
  }

Certificate enrollment flow

The following diagram illustrates the certificate enrollment flow.

Storing a CEP service certificate in UCM storage

Apps that acquire a security certificate through Simple Certificate Enrollment Protocol (SCEP) can provide Universal Credential Management (UCM) storage as a valid option for SCEP. Previously, SCEP could only store security certificates in the Android Keystore or Tima Keystore. For more information regarding UCM, refer to the Samsung Knox UCM Developer Guide.

The following steps show, at a high level, the procedure that you need to follow in order to store a SCEP certificate in UCM storage:

  1. Find the valid credential storage on the device by calling UniversalCredentialManager#getAvailableCredentialStorages().
  2. Manage the credential storage by calling UniversalCredentialManager#manageCredentialStorage().
  3. Include your app's own packages in the UCM whitelist by calling UniversalCredentialManager#addPackagesToWhitelist().
  4. Start certificate enrollment by calling EnterpriseCertEnrollPolicy#enrollUserCertificate(EnrollmentProfile enrollmentProfile, List<String> allowedPackages, String caCertHash). The UCM storage information is passed from the client in the enrollmentProfile.storageName parameter. The storageName value is in the SCEPProfile/CMCProfile class. CMCProfile/SCEPProfile is a subclass of the EnrollmentProfile object.