Quantcast
Channel: Certified Security Solutions » in-app certs
Viewing all articles
Browse latest Browse all 4

In-App Mobile Certificates Made Easy with mCMS (Part 2)

$
0
0

In Part I, we took a look at how easy it is to integrate in-app certificates with your iOS applications with mCMS 1.2.  In Part II, I’ll show you how Android integrates with mCMS 1.2 to leverage in-app certificates.   While the documentation and SDK source code are demonstrating this capability on Android, it would be trivial to use this client library on any Java-based platform, such as J2ME.

 

Figure 1:  Shows the new API components shipping with mCMS 1.2.

App developers are free to use either the REST-based API or their platform-specific API as appropriate.  The remainder of this blog post will focus on building an Android app using the Java API.

Obtain a certificate with mCMS in 4 easy steps

  1. Create an instance of the certificate enrollment class, which implements the interface MCMSCertEnrollApi
  2. (Optionally) Read the Status of the mCMS Server
  3. (Optionally) Read the available Certificate Templates
  4. Request a certificate based on an available template on behalf of the user

Let’s break these steps down a bit further.

Step 1

The MCMSCertEnrollApi interface exposes methods that allow your app to perform those actions.  By initializing it with properties (through a factory method), the class will handle most of the details for obtaining certificates.  Most likely, all but the userName and password field values will be compiled into your application. The app should provide a UI for users to enter their Windows AD credentials, thereby making the credentials available to the app.

Here’s an example of how an instance is created:


MCMSCertEnrollApi certEnrollApi =
    MCMSApiFactory.createCertEnrollApi(appKey, appSecret, serverUrl, userName, password, virtualFolderName);

To make this instance available across multiple activities, the sample app keeps a reference to this instance in a custom Application class.

Step 2

Read the status of the mCMS Server.  This is an optional, but recommended, step to make sure that the version of the mCMS Server matches the version that the app is expecting.

certEnrollApi.readServerStatus(new MCMSCertEnrollApiCallback() {

    @Override
    public void onFailure(final ApiException error) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(LoginActivity.this,
                    String.format("Failed to read server status.  Error: %s",
                    error.getMessage()), Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onSuccess(ApiVersion version) {
         runOnUiThread(new Runnable() {
             public void run() {
                 Toast.makeText(LoginActivity.this,
                     "Successful response from the server.",
                     Toast.LENGTH_SHORT).show();
             }
        });
    }
});

The MCMSCertEnrollApiCallback interface is implemented by the caller of the API.  In the example above, we’ve implemented it as an anonymous class, but it could be implemented in a declared class as well.

The interface looks like this, and is used across all of the methods through the use of templates:


public interface MCMSCertEnrollApiCallback
{
    /**
    * Method used to indicate the asynchronous request was successful.
    * @param result A reference to class of type T.
    */
    public void onSuccess(T result);

    /**
    * Method used to indicate the asynchronous request failed.
    * @param error Reference to the ApiException class containing the details
    * of why a particular request failed.
    */
    public void onFailure(ApiException error);
}

The onSuccess method will be called if the response from the mCMS server is successful.  The ApiVersion class instance will contain the versioning and license status of your mCMS server.  At this point, your software application is ready to read templates and/or request a certificate.

The onFailure method will be called if the response from the mCMS server is an error.  A single ApiException exception will be returned to the caller.  In addition to the usual Exception methods, it contains two methods for retrieving the error code and message for this specific failure.  This rich error information should give your app enough context to know exactly why it failed to read the server status.

Step 3

Read the certificate templates that the mCMS Server has been configured to offer to your app.  The certificate template will contain several pieces of information, including the size of the key that the template requires.


certEnrollApi.readAvailableTemplates(new MCMSCertEnrollApiCallback<List>() {

    @Override
    public void onSuccess(final List result) {
        runOnUiThread(new Runnable() {
            public void run() {
                certificateTemplateList.addAll(result);
                for(Template t : result) {
                    certificateTemplateAdapter.add(t.getCommonName() + " (" +
                        String.valueOf(t.getKeySize()) + ")");
                }

                Toast.makeText(CertEnrollActivity.this,
                    "Successful response from the server.", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onFailure(final ApiException error) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(CertEnrollActivity.this,
                    String.format("Failed to read Certificate templates.  Error: %s",
                    error.getMessage()), Toast.LENGTH_SHORT).show();
            }
        });
    }
});

In the onSuccess method, the list of Template objects received from the server is passed in.  In the code above, the array adapter (corresponding to a Spinner control) is populated with the list of template names, along with the key length.  In the onFailure method, the error information is available to the caller.

It’s likely that certificate templates would not be exposed to the user, so this method can be used to verify that the expected template is available to this particular app.

Step 4

Enroll the certificate itself.  Only two parameters are required for this final step.  The app must supply:

  • Template Name:  Name of the template to enroll for the certificate
  • Identity Name:  Friendly name to store the certificate/key in the Android KeyChain
  • Pkcs12 Path:  Absolute path to store the PKCS12 to.  It is strongly recommended that this path be in the application’s sandbox directory, which can be discovered with the getFilesDir method.
  • PKCS12 Password:  Password to secure the contents of the PKCS12 file.
certEnrollApi.enrollForCertificateWithPkcs10(new MCMSCertEnrollApiCallback(){
        @Override
        public void onSuccess(final EnrollmentResponse result) {
            runOnUiThread(new Runnable() {
                public void run() {
                    dialog.dismiss();
                    importPkcs12(result.getPkcs12Path());
                }
            });
        }
        @Override
        public void onFailure(ApiException error) {
            runOnUiThread(new Runnable() {
                public void run() {
                     dialog.dismiss();
                }
            });
        }
    },
    “ClientAuth”, //Template Name
    certEnrollApi.getUserName(),  //Identity
    getFilesDir().getAbsolutePath(),  //PKCS12 Temporary Storage location
    "ypGwgqMgQldZ"  //PKCS12 Password
);

Several things happen on the Android device when this method is called.

  1. A Public/Private keypair is generated on the device based on the Certificate Template properties
  2. A PKCS#10 is generated on the device
  3. The PKCS#10 is sent as an enrollment request to the mCMS Server
  4. The mCMS Server enrolls with the Microsoft CA to request a certificate for the user
  5. The new certificate is returned from the mCMS Server and into the client library
  6. Client library writes the Key/Certificate details to the location specified in PKCS12 format, protected with the supplied password
  7. The onSuccess or onFailure method is called with the results

In the onSuccess method, the EnrollmentResponse class contains two fields:


public class EnrollmentResponse
{
    List certificates;
    String pkcs12Path;
}

The certificates field is a list of X509Certificate class instances containing the certificate received, as well as any trust chain certificates.  The pkcs12path is the absolute path to the PKCS12 file, as requested in the call.  At this point, your application has two choices based on the version of Android.

Android 4.0+

Android 4.0 adds a new KeyChain API that allows applications across the system to use certificates and keys, with user permission.  Our 4.0-based sample application takes the PKCS12 path, and installs it into the device’s KeyChain.  This is a very simple step to do:

byte[] keystore = readPkcs12(pkcs12Path);
Intent installIntent = KeyChain.createInstallIntent();
installIntent.putExtra(KeyChain.EXTRA_PKCS12, keystore);
startActivityForResult(installIntent, INSTALL_KEYSTORE_CODE);

A standard Activity will be launched to import the key and certificates into the KeyChain.  The user will be prompted to enter the PKCS12 password.  If the password matches, the key and certificates are available for any number of uses:

  • Wifi connections
  • VPN connections
  • Client-side SSL (in the standard browser)
  • ActiveSync/Exchange (support varies by Email clients, however)
  • In-App key/certificate usage (with user permission)

Android applications that wish to use one of these key/certificates  can easily do so through the KeyChain API.  Android will prompt the user to acknowledge and permit the application to use the requested certificate.

Earlier Versions of Android

In-App certificates can be used by earlier versions of Android.  However without KeyChain API support, the application will need to use the PKCS12 file directly.  On non-rooted devices, storing the PKCS12 file in the Application’s sandbox directory will prevent other applications from accessing this data.  On rooted devices, all bets are off, as sandboxes are potentially vulnerable to access by unauthorized application.

Summary

The CertEnroll API for mCMS 1.2 lowers the bar significantly for obtaining in-app certificates on both the iOS and Android platforms.  It is now easy and secure to enroll for certificates from your mobile devices using your Microsoft-based PKI, and with on device key generation.

Notes:

http://android-developers.blogspot.com/2012/03/unifying-key-store-access-in-ics.html

The post In-App Mobile Certificates Made Easy with mCMS (Part 2) appeared first on Certified Security Solutions.


Viewing all articles
Browse latest Browse all 4

Latest Images

Trending Articles





Latest Images