Carl Wallace
Oct 09, 2015
11:05 am

Silently installing certificates and PKCS12 objects

The following code works fine to silently install an X.509 certificate from an application running on the personal side of a Samsung device but when run from within a Knox container the installCertificateToKeystore call throws an exception that says: "Operation not supported, Device permission is not present". This code is executed after establishing the application as a device administrator and after activating both the Samsung enterprise and Knox licenses. The KeyChain install intent approach to installing works fine both inside and outside the container, but prompts the user for each item that gets installed, which is not desirable.

What additional steps or alternative approaches are required to silently install certificates or PKCS12 objects when running inside a Knox container?

byte[] data = Base64.decode(<base64 encoded certificate>, Base64.DEFAULT);

EnterpriseDeviceManager edm = (EnterpriseDeviceManager) getSystemService(
EnterpriseDeviceManager.ENTERPRISE_POLICY_SERVICE);

SecurityPolicy mSecurityPolicy = edm.getSecurityPolicy();

boolean retValue = mSecurityPolicy.installCertificateToKeystore(
SecurityPolicy.TYPE_CERTIFICATE, data, "nickname", null, 
SecurityPolicy.KEYSTORE_DEFAULT | 
SecurityPolicy.KEYSTORE_FOR_VPN_AND_APPS | 
SecurityPolicy.KEYSTORE_FOR_WIFI);

 

 

Kieran McCormick
Oct 09, 2015
8:24 pm

Hi Carl

If you are trying to implement standard policies on a container from inside a container then you will get this error, you need to use the premium APIs on the container. Additionally, if the container was not created by your device admin application then the application will have no authority over it.

It seems that in your code you have neither created a container nor used the premium SDKs installCertificateToKeystore method. If you are looking to do this please let me know and I will give you the steps to implement this policy on a container :-)

Carl Wallace
Oct 14, 2015
11:08 am

Thanks. I think two things contributed to not seeing the issue earlier. First, the term "device administrator" is an overloaded term. I noticed the APIs were available to "an administrator" but mistook this to mean an app that had been added as a "device administrator" via the DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN intent. It seems to mean "container creator" here. Second, given the app was working outside the container, the language in the developer guide stating "containerized apps will have the same functionality as their non-containerized versions" created a misimpression with regard to apps that use Samsung APIs. 

I don't think I will open a new thread on the license issue since Knox activation should become unnecessary if we cannot exercise the Knox APIs (since we did not create the container). Offhand, I think there are three possible ways forward:

1) Use the native Android APIs exclusively. These may feature suitable silent installation mechanisms starting with API level 23 anyway. The open question then becomes whether we can generate keys using Samsung APIs without being the container creator.

2) Look into re-signing both the MDM app and the key management app with a key controlled by the enterprise.

3) Submit an enhancement request to Samsung to allow key management to be performed by entities other than the container creator using Samsung APIs. Android API level 23 introduces a "delegated certificate installer" concept. I will be interested to see how Samsung implements support for that. That mechanism may suffice.

 

Comments

Hi Carl,

I have contacted R&D to double check that there is no API for 3rd party apps to create certificate in TZ without being owner of the container.

Kieran McCormickOct 15, 2015 at 4:33 pm
Kieran McCormick
Oct 09, 2015
5:07 pm

Hi Carl,

Please confirm that you have the following line in your AndroidManifext.xml, if you dont please let me know if adding it solves your issue:

<android:uses-permission android:name="android.permission.sec.MDM_SECURITY"/>

If having this line in your manifest does not solve your issue then please do the following:

1) Please provide me with the build number of the device you are testing on.

2) Please provide the full error code.

3) Are you able to set any other policies to your container?

Comments

That permission is present. I do not have the device handy but I can provide you a small test application that exhibits the problem. Do you have a means for accepting an attachment? Here is a link: https://downloads.redhoundsoftware.com/temp/OddBehaviorDemo.zip

Carl WallaceOct 09, 2015 at 5:37 pm

Post Deleted

Our content monitors have determined that this post violated our terms of service.

Please ensure your posts comply with our forum guidelines. We are committed to providing helpful and professional information in this space.

Thank you,

The SEAP team

Deleted Oct 09, 2015 8:24 pm

3
Carl Wallace
Oct 13, 2015
9:56 pm

Not quite (or at least not as I would describe it). We have an app. That app performs various key management functions. On the personal side of Samsung devices it uses the Samsung APIs to silently install certificates and PKCS12 files into the system key store. On non-Samsung devices, we use the Android Key Chain to install certificates and PKCS12 files into the system key store but with a user prompt. 

The environment the app will run in features a commercial MDM (including an MDM app installed on the personal side). The MDM software creates a Knox container and pushes apps into the container. When our app is pushed into the container, the Android Key Chain APIs work fine but the Samsung APIs do not. It looks like the installCertificateToKeystore is not going to work inside the container because the container was created by an app signed with a different key. If this is corrent, then it's likely that key generation is going to be a problem too, but we have not tried that yet. 

Separate but possibly related, we have noticed that KLM activation does not work with our KLM license string but does work with the KLM license string used by the MDM.

Comments

Hi Carl,

Thanks alot for explaining it to me!

I am not sure what keys you are referring to when you say:

"It looks like the installCertificateToKeystore is not going to work inside the container because the container was created by an app signed with a different key" 

The KNOX Standard and Premium keys are only used to allow the device administrator to use the KNOX APIs. A container has a specified owner who can apply policies to it, this owner is usually the creator of the container.

Just before I start in on my explanation I would like to make the following note: if your certificates are destined for the WiFi Keystore then you need only install them on the personal side as this keystore is device wide. By this I mean that if you install a WiFi certificate on the personal side you can access it in the container, however, you are not able to install a WiFi certificate inside the container with KNOX APIs.

Installing an application into a KNOX Container that is meant to apply any KNOX API, Premium or Standard, is beyond the scope of the KNOX APIs unless you use This method (createContainer(String, String)). This will make whatever MDM you specify the owner of the container space while being inside the container, it can then and only then call the Premium APIs, but not Standard APIs.

I do not know your exact use case of having a separate app inside the container to install certificates so it may be impossible to go any other route than to use the Android Key Chain APIs. If it is possible to do the following with your implementation than that would be the only other way to allow you to use the KNOX APIs. Do not call the certificate install APIs from inside the container but from the original MDM.

For the benifit of the community please create a new question on the forum for your KLM issue.

If you have any more question please let me know!

Kieran McCormickOct 13, 2015 at 11:18 pm
Carl Wallace
Oct 09, 2015
8:49 pm

If you can point me in that direction it would be most helpful. Where do I get the premium version of the installCertificateToKeystore method? I was under the impression I had obtained the premium SDKs. Any pointers to the right APIs or samples are welcome. Thanks.

Carl Wallace
Oct 13, 2015
8:27 pm

We have an MDM. Based on the developer guide description for your code sample, the MDM is creating a knox-b2b container. Independent of the sample code, I can click the Knox icon and run apps within that environment then click the Personal Space icon and return to the native side of the device and run apps there. The sample code I provided is pushed into the container by the MDM, where it exhibits the issues previously described (it works fine on the personal side).

Do the installCertificateToKeystore and getContainers calls only work in apps signed with the same key as used by the MDM's app (i.e., the entity that set up the container in which the apps are running in the first place)? If so, that would mean we cannot silently install certificates and keys using the Samsung APIs but must use the Android KeyChain API, which prompts the users.

Comments

Hi Carl,

I apologize that this is taking so long to resolve, I have had trouble understanding your implementation. 

From what you have just said I gather that your implementation is as follows:

  1. You have an MDM on your personal side to:
    1. Silently install certificates to the personal side of the device.
    2. Create a container.
  2. Your MDM will then install a second MDM inside the container it has created.
    1. This Second MDM inside the container installs certificates silently to the container.

Is this correct?

Kieran McCormickOct 13, 2015 at 9:13 pm
Carl Wallace
Oct 15, 2015
4:44 pm

Thanks, and just to finsh this off, the "owner of the container" is effectively the key that signed the app that created the container?

Comments

Hi Carl

No, the owner of the container is more dependent on the API call "createContainer" itself.

It may be easiest if we look at the owner as just being assinged via the following API calls

The owner of the container would be the application that calls This method

The owner of the container could be almost any MDM app if This API is called. (The description of this method should hopefully explain what you are asking)

 

If that doesnt make sense, or you have any more questions please let me know!

I will update you asoon as I hear back from R&D.

Kieran McCormickOct 15, 2015 at 4:59 pm
Kieran McCormick
Oct 09, 2015
10:25 pm

Hi Carl,

It is my understanding that you are looking to implement the following use case:

  • Have an MDM client on a device to silently install certificates to both the personal side and the container.

Your current implementation will work on the personal side as you are using standard APIs. In order to do this for the container, however, you will need in implement Premium APIs.

First, you will need to create a container with your MDM, if you try and set policies on a container that is not managed by your MDM you will get the security exception you have been seeing.

Below is a quick and simple implementation to get you started on container management. please note that this implementation is only meant to manage one container, management of multiple containers would require a different method:

  • A way of doing this would be to do the following:
    • Use the KnoxContainerManager.createContainer(type); method to create your container. (Here)
    • Use the following code snippit to obtain the container ID.
      • public static int getContainerId() {
            int containerID = 0;
        
            try {
                List containerIDList = KnoxContainerManager.getContainers();
        
                //Using a value of zero as all container values are >= 100.
                //If List returned from getContainers is populated.
                if (!containerIDList.isEmpty()) {
                    //Get container ID from list, 
                    for (int i : containerIDList) {
                        containerID = i;
                    }
                }
            }
    • Then use this container ID to create a KnoxContainerManager object, then use this object to create the SecurityPolicy object. (Here)
      • EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance();
        KnoxContainerManager kmcm = ekm.getKnoxContainerManager(getBaseContext(), getContainerId());
        SecurityPolicy securityPolicy = kmcm.getSecurityPolicy();
    • You can now use this premium SecurityPolicy object to enforce any of the policies in the SecurityPolicy Class.
      • EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance();
        KnoxContainerManager kmcm = ekm.getKnoxContainerManager(getBaseContext(), getContainerId());
        SecurityPolicy securityPolicy = kmcm.getSecurityPolicy();
        
        ​boolean result = securityPolicy.installCertificateToKeystore
                (SecurityPolicy.TYPE_CERTIFICATE, certByteArray, "cert" + mCertCounter, password,
                        SecurityPolicy.KEYSTORE_FOR_VPN_AND_APPS);

If the above does not resolve your issue then please let me know. You can always look at the implementation of the test apps Here for further examples.

Comments

The call to KnoxContainerManager.getContainers(); returns an empty list. This is confusing because a call to android.os.Process.myUid() returns an 8 digit value. Per other documentation on the Samsung site, the first three digits indicate the container ID, which is 100 in this case. Why would the container ID list be empty when the myUid is 8 digits and indicates execution inside of a container? Independent of that, using 100 as the container ID does not work. I get a null KnoxContainerManager from ekm.getKnoxContainerManager(getBaseContext(), getContainerId());

Now that I have the device handy and per your earlier request, the build number is KTU84P.N910AUCU1ANIE.

Carl WallaceOct 12, 2015 at 2:31 pm

Hi Carl,

Sorry if I was not clear before.

If KnoxContainerManager.getContainers(); is returning an empty list this usually means that you have not created a container under your MDM solution. Can you please confirm that you have the following lines in your code and execute them before calling KnoxContainerManager.getContainers(); 

KnoxContainerManager.createContainer("knox-b2b");

The main reason I think this is the issue is because when I looked through your code earlier I did not see that you were implementing container creation. As I stated earlier "First, you will need to create a container with your MDM, if you try and set policies on a container that is not managed by your MDM you will get the security exception you have been seeing" ... and in this case you will not have any containers under your management to set policies on.

If you have implemented the above then please disregard the following and provide me with your new code so I can look into it for you.

Please read This developer guide for more information on container creation/management.

Kieran McCormickMar 17, 2016 at 10:04 pm