Menu

Tutorial: Knox Attestation (v3)

Knox 3.4 introduced the latest version of Attestation (v3) running on flagship devices from the Note 10 onwards. Enhanced Attestation uses the EnhancedAttestationPolicy class and v3 REST API. For information about the previous version of Attestation, see Attestation (v2).

Get an Attestation REST API key

In the header of every REST API call to the Attestation server, identify yourself by encoding your own unique Attestation key.

To get this key:

  1. Sign in to the Knox Partner Portal.
  2. Go to: Get a License.
  3. Enter a unique alias to describe this Attestation key. This is mandatory.
  4. Click Get License Key.
  5. Under License Number, copy the key to use in your REST API calls.

Set up a server

In the following examples, we use an Apache server on a Linux operating system with PHP as the scripting language. You can set up such a web server from scratch quite simply. If you don’t have a web server, you can enroll in a free or trial cloud service to get quick access to one.

If you are new to web server setup, here are some basic Linux commands to set up the server:

install Ubuntu 14.0
sudo apt-get update
sudo apt-get install apache2
sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt php5-curl
sudo /etc/init.d/apache2 restart

Alternatively, you can use a pre-built environment, such as that provided by Apache Friends.

Once you have a web server with PHP support, copy your scripts into the folder /var/www/html. In the sample Attestation app, there are two PHP scripts, called nonces.php and measurements.php, which you can copy into this folder.

Through an app on the device, call the Knox API method RestrictionPolicy.setAllowedFOTAVersion to set the highest firmware version that the device is allowed to update to.

Get a nonce

A nonce is a random value that uniquely identifies each attestation request. To protect from replay attacks, each nonce is valid only for a short period of time. This ensures that the Attestation server can fail requests made using an invalid nonce once it expires, which prevents malicious attackers from accessing a past attestation result. A nonce also serves as a unique identifier for each attestation request.

Get a nonce from the Attestation server

In your web script, build the request to get a nonce from the Attestation Server. Our sample app does this using PHP, which you can find in the file nonces.php:

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, " https://attest.samsungknox.com/v3/nonces";
curl_setopt($curl, CURLOPT_POST, 1); 
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);

  $headers = array(
   'Accept: application/json',
   'Content-Type: application/json'',
   'Authorization: Bearer '.$api_key,
   'Ats-Request-Id: '.$ats_request_id
  ); 
					
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

  if(!curl_exec($curl)){
	die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
  }

Get a nonce from your web script

In your Android app, request a nonce from your web server. On the web server, you need a script to take the request and forward it to Samsung’s Attestation server.

In the sample Attestation app, there is a script called nonces.php that does this:

// identify the URL of your web server
private static final String URL_MDM_SERVER_NONCE = "http://attestation.example.com/nonces";

// through HTTP, send a nonce request to your web server
String response = HttpClient.getInstance().getNonce(URL_MDM_SERVER_NONCE, ”ATTESTATION_KEY”, “REQUEST_ID”));

In this example, we use a string variable called response to store the resulting nonce. Later, you will parse the response into a JSON object and pass it to the Attestation agent on the device.

For details about the syntax of the REST API calls to the Attestation Server, see the Attestation REST API Reference.

Start attestation

Start attestation using EnhancedAttestationPolicy

// import EnterpriseKnoxManager
// import EnhancedAttestationPolicy
// import EnhancedAttestationPolicyCallback

import com.samsung.android.knox.EnterpriseKnoxManager;
import com.samsung.android.knox.integrity.EnhancedAttestationPolicy;
import com.samsung.android.knox.integrity.EnhancedAttestationPolicyCallback;

// declare EnhancedAttestationPolicy to call api
private EnhancedAttestationPolicy mPolicy;
EnterpriseKnoxManager ekm = EnterpriseKnoxManager.getInstance(context);
mPolicy = ekm.getEnhancedAttestationPolicy();

//make callback to receive attestation result
EnhancedAttestationPolicyCallback cb = new EnhancedAttestationPolicyCallback() {
 @Override
 public void onAttestationFinished(final EnhancedAttestationResult result) {}
};
			
// call startAttestation (AUK is vendor Unique Key)
mPolicy.startAttestation(AUK, nonce, cb);

Handle attestation result

Your app handles the attestation result by passing it to the Callback method. This method handles the result sent by the EnhancedAttestationPolicy.

/// import package that defines constants for values returned by EnhancedAttestationResult
import com.samsung.android.knox.integrity.EnhancedAttestationResult

EnhancedAttestationPolicyCallback cb = new EnhancedAttestationPolicyCallback() {
 @Override
 public void onAttestationFinished(final EnhancedAttestationResult result) {
  if (result.getError() == EnhancedAttestationResult.ERROR_NONE) {
   Log.i(TAG, "attest: onSuccess");
   //should compare nonce to unique Id.
   if (nonce.equals(result.getUniqueId())) {
    //nonce verification success 
   }
   ...
  } else {
   Log.i(TAG, "attest: onFailure");
   if (nonce.equals(result.getUniqueId())) {
    //nonce verification success 
   }
   ...
  }
 }
};

Get verdict

Send a blob to your web server

Send the result (unique Id) to your web server using the HTTP protocol. On the web server, you need a script to take the unique id which should be same as nonce and forward it to Samsung’s Attestation server. In the sample Attestation app, there is a script called measurements.php that does the following:

// identify the URL of your web server
private static final String URL_MDM_SERVER_MEASUREMENTS = "http://attestation.example.com/attestations/";

String response = HttpClient.getInstance().getAttestationStatus(URL_MDM_SERVER_MEASUREMENTS + nonce, “ATTESTATION_KEY”, “REQUEST_ID”);
				

In this example, we use a string variable called response to store the resulting verdict. Later, you will parse the response into a JSON object and display the verdict details.

Get a verdict from the Attestation server

In the web script, build a request to get the attestation verdict from the Attestation server. Our sample code does this using PHP, which you can find in the source code file measurements.php:

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, "https://attest.samsungknox.com/v3/attestations/".$nonce);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);

$headers = array(
	'Accept: application/json',
	'Content-Type: application/json',
	'Authorization: Bearer '.$api_key,
	'Ats-Request-Id: '.$ats_request_id
);

curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
if(!curl_exec($curl)){
	die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
}				}
				

Display the verdict

You can process the verdict in either the web script or Android app.

Here, we use the Android app to convert the attestation response into a JSONObject to extract the results of the attestation, including the attestation verdict:

//Parsing result of attestation
JsonObject = new JSONObject(mAttestationStatus);
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
EAResultInfo eAResultInfo = gson.fromJson(mAttestationStatus.responseData, EAResultInfo.class);
eAResultInfo.toString();

public static class EAResultInfo {
 String nonce;
 String verdict;
 int warrantyFuseStatus;
 int verifiedBootState;
 int trustBootState;
 String idAttestationStatus;

 App app;
 long timestamp;

 public String toString() {
  return "Nonce: " + nonce +
   "\n\nVerdict: " + verdict +
   "\nWarranty bit: " + warrantyFuseStatus +
   "\nVerified boot: " + verifiedBootState +
   "\nTrust boot: " + trustBootState +
   "\nID Attestation: " + idAttestationStatus +
   "\n\nTimeStamp: " + timestamp +
   "\n\nApp package: " + app.pkg +
   "\n\nApp signature: " + app.signature;
 }

 static class App {
  String pkg;
  String signature;
 }
}

For details about the fields returned in the result, see the Attestation REST API Reference.

A verdict of:

  • Yes — indicates that the device passed the integrity checks
  • No — indicates that the device might have failed the integrity checks

The Warranty Bit indicates device has been rooted.

  • 0 — never rooted.
  • 1 — rooted.

The Trust boot indicates cross binary (or OEM unlock).

  • 0 — official binary.
  • 1 — Cross binary or OEM unlock.

Device ID Attestation

  • OK — device ID passed integrity checks.
  • Not OK — IMEI and S/N has been modified.