Tutorial
Installation
Installation instructions can be found in the Usage document.
Your first Application sha1sum
We will start by writing a sha1sum replacement. This will just compute the sha1sum of a single file and write it to the console.
Computing sha1sums is nothing you need a tpm for, but the tpm chip provides this functionality, and you can quickly verify if your tpm chip works.
package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * A little example, which shows how to use the tpm chip to compute * a sha1 checksum of a file. * * @author Erik Tews */ public class Sha1Sum { /** * Does nearly the same as the command line utility sha1sum. * * @param args A filename of a file to hash */ public static void main(String[] args) { /* * Fetch a high level interface to the tpm. */ TssHighLevel highLevel = TssFactory.getHighLevel(); try { // Open the file. FileInputStream fis = new FileInputStream(args[0]); // This computes the sha1-Hash over the file using the tpm. byte[] hash = highLevel.computeSha1(fis); // Close the file fis.close(); // Output the hash to the console. System.out.println(toHex(hash) + " " + args[0]); } catch (Exception e) { /* * Something must have gone wrong. This usually happens, if the * file does not exist. */ e.printStackTrace(); } } /** * Converts a byte-array to a hexString. * @param data The array to convert. * @return A String with the content of the array in hexadecimal representation. */ public static String toHex(byte[] data) { StringBuffer buf = new StringBuffer(data.length * 2); for (int i = 0; i < data.length; i++) { buf.append(Integer.toHexString((data[i]>>>4)&0xf)); buf.append(Integer.toHexString((data[i]&0xf))); } return new String(buf); } }
We do now compute the sha1sum of /bin/ls by running java de.datenzone.tpm4java.examples.Sha1Sum /bin/ls. On my system, the output is:
1146fe1deb6c9f83738780eb6a635b7c9d2599e0 /bin/ls
We can verify the output by computing this result using the usual sha1sum by running sha1sum /bin/ls. The output is here
erik@tp:~$ sha1sum /bin/ls 1146fe1deb6c9f83738780eb6a635b7c9d2599e0 /bin/ls
A more usefull example, generating random numbers
Random numbers are very important for cryptographic applications. Java provides a random number generator in java.util.Random which is not so suiteable for cryptographic applications. A better one is provided in java.security.SecureRandom. This generator is still based on determinic functions, but is quite well useable in cryptographic applications.
We will show you how to use your tpm as a source for random numbers which are perhaps generated hardware based and should provide a higher level of security than software based generators.
We will simulate a dice which has 6 numbers on its surface. Each one shows up with equal probabilty and if you roll the dice more than once, all results will be independend of each other.
package de.datenzone.tpm4java.examples; import java.util.Random; import de.datenzone.tpm4java.TssFactory; /** * This is a simulator of an ordinary dice, with numbers from 1 to 6 inclusive * printed on the surface. * * @author Erik Tews */ public class Dice { /** * Simulate the dice one time. * * @param args Will be ignored. */ public static void main(String[] args) { /* * Get a new tpm enabled random number generator. */ Random tpmRandom = TssFactory.getHighLevel().getTpmRandom(); /* * Get a number between 1 inclusive and 6 inclusive. */ int result = ((int)((tpmRandom.nextFloat()*6)))+1; System.out.println("The dice says " + result); } }
Take the ownership of your TPM
If you are new to trusted computing, the first thing you wanna do is, take the ownership of your TPM.
Every TPM has an owner. In a company environment, this is usually the id department of the company. In some other environments, it is the owner of the physical device the TPM is connected to.
The owner and the TPM share a secret, called the ownerAuth, a simple password.
The TPM has a secure storage for RSA-Keys. This is a tree of RSA-Keys, where the key of a node is protected by the key of the parent of the node. The key in the root of the tree is called the storage root key, in short words srk. This srk is protected by a shared secret between the owner and the TPM, called the srkAuth.
When taking ownership, you specify the ownerAuth and the srkAuth as String. These Strings will be converted to byte-Arrays using UTF16 encoding, and then hashed using the SHA1-Algorithm. The result will then be used as ownerAuth and srkAuth.
This example shows how to take Ownership from the command line.
package de.datenzone.tpm4java.examples; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * This is for taking the ownership of an TPM. * * @author Erik Tews */ public class TakeOwnership { /** * Take the ownership of an TPM. * * @param args the ownerAuth and optional the srk. */ public static void main(String[] args) { String authKey = args[0]; String srkKey = null; /* * If a srk password is provided, we use it. */ if (args.length >= 2) { srkKey = args[1]; } TssHighLevel highLevel = TssFactory.getHighLevel(); highLevel.takeOwnership(authKey, srkKey); System.out.println("Take Ownership successfull!"); } }
If it was successfull, you should see a message like:
Take Ownership successfull!
If it fails with:
Exception in thread "main" java.lang.RuntimeException: de.datenzone.tpm4java.TPMException: Bad return code 20 There is already an Owner
at de.datenzone.tpm4java.TssHighLevelImpl.takeOwnership(TssHighLevelImpl.java:76)
at de.datenzone.tpm4java.examples.TakeOwnership.main(TakeOwnership.java:30)
Caused by: de.datenzone.tpm4java.TPMException: Bad return code 20 There is already an Owner
at de.datenzone.tpm4java.TSSCoreService.SendCommand(TSSCoreService.java:1919)
at de.datenzone.tpm4java.TSSCoreService.SendCommand(TSSCoreService.java:1905)
at de.datenzone.tpm4java.TSSCoreService.TPM_TakeOwnership(TSSCoreService.java:221)
at de.datenzone.tpm4java.TssHighLevelImpl.takeOwnership(TssHighLevelImpl.java:74)
... 1 more
Somebody has taken ownership before. You should reboot and clear the tpm from the bios. Then you can try to take ownership again.
Changing ownerAuth or srkAuth
You can change these passwords later. For example, this application will change the ownerAuth to a new value.
package de.datenzone.tpm4java.examples; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * This demonstrates how to change the ownerAuth of an tpm. * @author Erik Tews */ public class ChangeAuth { /** * Change the ownerAuth of your tpm. * * @param args The old password and the new pasword. */ public static void main(String[] args) { TssHighLevel highLevel = TssFactory.getHighLevel(); String oldpass = args[0]; String newpass = args[1]; /* * If you change 1 to 2, the srkAuth will be changed. */ highLevel.changeAuth(oldpass, 1, newpass); System.out.println("changed ownerAuth from '" + oldpass + "' to '" + newpass + "'"); } }
The output should look like:
changed ownerAuth from 'foo' to 'foobar'
If you specified the wrong password, you will see a message like:
Exception in thread "main" java.lang.RuntimeException: de.datenzone.tpm4java.TPMException: Bad return code 1 Authentication failed
at de.datenzone.tpm4java.TssHighLevelImpl.changeAuth(TssHighLevelImpl.java:99)
at de.datenzone.tpm4java.examples.ChangeAuth.main(ChangeAuth.java:25)
Caused by: de.datenzone.tpm4java.TPMException: Bad return code 1 Authentication failed
at de.datenzone.tpm4java.TSSCoreService.SendCommand(TSSCoreService.java:1919)
at de.datenzone.tpm4java.TSSCoreService.SendCommand(TSSCoreService.java:1905)
at de.datenzone.tpm4java.TSSCoreService.TPM_ChangeAuthOwner(TSSCoreService.java:263)
at de.datenzone.tpm4java.TssHighLevelImpl.changeAuth(TssHighLevelImpl.java:97)
... 1 more
If you have really forgotten the ownerAuth, you are really screwed. You have to clear your TPM to set a new one.
Encrypt a file
Now, lets put some real trust in your TPM We will now use the TPM to protect a file on your harddisk. In detail, the following things will happen:
- an AES256 Key will be generated
- a new RSA-Key in the TPM will be generated
- The AES256 Key will be encrypted with the RSA-Key
- The Wrapped RSA-Key and the encrypted AES256-Key will be written to a file
- The actual content of the file will be encrypted with the AES256-Key and be appended
The code for this is pretty short. Here it is:
package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * This example shows how to encrypt a file, and protect the file key with * your TPM. * * The format of the file is not specified in the TPM specifications. * * @author Erik Tews */ public class EcryptFile { /** * Encrypt a file. * * If you are going to use the SRK as a parent, the handle is 1073741824. * * @param args InputFile, OuputFile, parentKeyHandle, parentKeyAuth, KeyAuth. */ public static void main(String[] args) { try { /* * Put together all paraemters. */ String filein = args[0]; String fileout = args[1]; int keyhandle = Integer.parseInt(args[2]); String parentAuth = args[3]; String keyAuth = args[4]; TssHighLevel highLevel = TssFactory.getHighLevel(); /* * Encrypt the file. */ highLevel.encryptFile(keyhandle, parentAuth, keyAuth, new FileInputStream(filein), new FileOutputStream(fileout)); } catch (Exception e) { throw new RuntimeException(e); } } }
This can be called with java de.datenzone.tpm4java.examples.EncryptFile /etc/resolv.conf /tmp/out.encrypted 1073741824 bar topSecret, if bar is the srkAuth value of your storage root key.
The decryption part looks quiet similar:
/* * Erstellt am 18.06.2006. * * Erik Tews <erik@debian.franken.de> */ package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * This is an example how to decrypt a file which was previously encrypted * with the EncryptFile example. * * @author Erik Tews */ public class DecryptFile { /** * Decrypt a file. * * If you are going to use the SRK as a parent, the handle is 1073741824. * * @param args InputFile, OuputFile, parentKeyHandle, parentKeyAuth, KeyAuth. */ public static void main(String[] args) { try { /* * Put together all paraemters. */ String filein = args[0]; String fileout = args[1]; int keyhandle = Integer.parseInt(args[2]); String parentAuth = args[3]; String keyAuth = args[4]; TssHighLevel highLevel = TssFactory.getHighLevel(); /* * Decrypt the file. */ highLevel.decryptFile(keyhandle, parentAuth, keyAuth, new FileInputStream(filein), new FileOutputStream(fileout)); } catch (Exception e) { throw new RuntimeException(e); } } }
You can run it with java de.datenzone.tpm4java.examples.EncryptFile /tmp/out.encrypted /tmp/out.decrypted 1073741824 bar topSecret, the result will be written to /tmp/out.encrypted.
Using the PCRs, write data to them
Your TPM has several plattform configuration registers. These registers store hash-values of configurations of your plattform. One exampel for such a configuration could be the output of lsmod on a linux system.
To fill a pcr with a configuration, you can use the following example:
package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * This example shows how to calculate the sha1sum of a file, and write it * to a pcr register. * * @author Erik Tews */ public class SetPCR { /** * Read a file and write its sha1sum to a pcr. * * @param args id of the pcr, name of the file. */ public static void main(String[] args) { int pcrId = Integer.parseInt(args[0]); String filename = args[1]; TssHighLevel highLevel = TssFactory.getHighLevel(); try { // Open the file. FileInputStream fis = new FileInputStream(filename); // This computes the sha1-Hash over the file using the tpm. highLevel.computeSha1ToPcr(pcrId, fis); } catch (Exception e) { e.printStackTrace(); } } }
This is not much different from the sha1sum example.
Accessing the pcr registers
It is easy to read the content of a pcr register. It is so easy, that we will use the low level interface to the TPM for the first time here in our tutorial.
package de.datenzone.tpm4java.examples; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssLowlevel; /** * This example shows how to access pcr registers. * * It will print their content on the console. * * @author Erik Tews */ public class PcrDump { /** * Dumps the content of all pcrs to the screen. */ public static void main(String[] args) { /* * We use a low level interface to the TPM. * * Accessing the pcrs is so easy, you don't need any * high-level functions to do that. */ TssLowlevel lowLevel = TssFactory.getLowlevel(); for (int i = 0; i < 25; i++) { try { byte[] content = lowLevel.TPM_PCRRead(i); System.out.println("pcr " + i + ":\t" + toHex(content)); } catch (Exception e) { } } } /** * Converts a byte-array to a hexString. * @param data The array to convert. * @return A String with the content of the array in hexadecimal representation. */ public static String toHex(byte[] data) { StringBuffer buf = new StringBuffer(data.length * 2); for (int i = 0; i < data.length; i++) { buf.append(Integer.toHexString((data[i]>>>4)&0xf)); buf.append(Integer.toHexString((data[i]&0xf))); } return new String(buf); } }
The output on my system is quite boring:
pcr 0: ff00000000000000000000000000000000000000 pcr 1: ff00000000000000000000000000000000000000 pcr 2: ff00000000000000000000000000000000000000 pcr 3: ff00000000000000000000000000000000000000 pcr 4: ff00000000000000000000000000000000000000 pcr 5: ff00000000000000000000000000000000000000 pcr 6: ff00000000000000000000000000000000000000 pcr 7: ff00000000000000000000000000000000000000 pcr 8: ff00000000000000000000000000000000000000 pcr 9: ff00000000000000000000000000000000000000 pcr 10: ff00000000000000000000000000000000000000 pcr 11: ff00000000000000000000000000000000000000 pcr 12: ff00000000000000000000000000000000000000 pcr 13: ff00000000000000000000000000000000000000 pcr 14: ff00000000000000000000000000000000000000 pcr 15: ff00000000000000000000000000000000000000 pcr 16: 0000000000000000000000000000000000000000 pcr 17: 0000000000000000000000000000000000000000 pcr 18: 0000000000000000000000000000000000000000 pcr 19: 0000000000000000000000000000000000000000 pcr 20: 0000000000000000000000000000000000000000 pcr 21: 0000000000000000000000000000000000000000 pcr 22: 0000000000000000000000000000000000000000 pcr 23: 0000000000000000000000000000000000000000 pcr 24: 0000000000000000000000000000000000000000
Attesting your plattform configuration
Remote Attestion is one of the most intresting things in trusted computing. It is one of the most complex operations the tpm can do too. So we will split this example in multiple parts.
Step 1: The privacy ca
At the moment this document is written, there is no operational ca out there which acts as a privacy ca. So we have to set up our owne one.
tpm4java includes a very basic ca which is sufficient for this tutorial. To generate a ca, you can use this utility:
package de.datenzone.tpm4java.examples; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import de.datenzone.tpm4java.SimplePrivacyCA; /** * Little example, which shows how to generate a Privacy CA. * * @author Erik Tews */ public class GenerateCa { /** * Generate a new Simple Privacy CA and write it to a file. * * @param args label and filename. */ public static void main(String[] args) { KeyPairGenerator kpg; /* * The label of your ca we are about to create. */ String label = args[0]; /* * Where to store the ca. */ String filename = args[1]; try { /* * We use a 2048 bit rsa key. */ kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); KeyPair caKey = kpg.generateKeyPair(); /* * Create the new ca and write it to a file. */ SimplePrivacyCA ca = new SimplePrivacyCA(caKey, label.getBytes()); ca.writeToFile(filename); System.out.println("Created CA with label \"" + label + "\" and wrote it to " + filename + "."); /* * Write the id to an extra file. */ FileOutputStream idStream = new FileOutputStream(filename + ".id"); idStream.write(ca.getChosenID()); idStream.close(); System.out.println("Wrote id to " + filename + ".id."); /* * Write the public key to an extra file. */ ObjectOutputStream kous = new ObjectOutputStream( new FileOutputStream(filename + ".pub")); kous.writeObject(caKey.getPublic()); kous.close(); System.out.println("Wrote public key to " + filename + ".pub."); } catch (Exception e) { e.printStackTrace(); } } }
You run it with java de.datenzone.tpm4java.examples.GenerateCa myTinyCa ca.dump ant it will generate a privacy ca and write it to ca.dump. The output should look like this:
Created CA with label "myTinyCa" and wrote it to ca.dump. Wrote id to ca.dump.id. Wrote public key to ca.dump.pub.
You can find the id of your ca in the file ca.dump.id which is important later.
Step 2: Generate an AIK and pack everything for the request
Now, we will generate the AIK. We use the following code to do that:
package de.datenzone.tpm4java.examples; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.PublicKey; import de.datenzone.tpm4java.TPMPubKeyWrapper; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; import de.datenzone.tpm4java.TssLowlevel; /** * Example which shows how to generate an AIK and send it as an request to an * privacy ca. * * @author Erik Tews */ public class GenerateAikRequest { /** * @param args * label of the ca, filename of the id-file, filename of the * public key of the ca, ownerpass, srkpass, newkeypass, filename * to write request to. */ public static void main(String[] args) { try { /* * The label of the ca. */ String label = args[0]; /* * File, containting the id of the ca. */ String idfile = args[1]; /* * The file containing the public key of the ca. */ String pubkeyfile = args[2]; /* * Your ownerpass. */ String ownerpass = args[3]; /* * Your srkpass. */ String srkpass = args[4]; /* * The new password to protect the AIK. */ String newkeypass = args[5]; /* * Where to write the request to the ca to. */ String outfile = args[6]; TssHighLevel highLevel = TssFactory.getHighLevel(); /* * We first need the public key of the privacy ca. * * We deserialize it from a file. */ ObjectInputStream ois = new ObjectInputStream(new FileInputStream( pubkeyfile)); PublicKey pubkey = (PublicKey) ois.readObject(); ois.close(); /* * Every privacy ca has an id. Read it from a file. */ DataInputStream fis = new DataInputStream(new FileInputStream( idfile)); byte[] id = new byte[20]; fis.readFully(id); fis.close(); /* * Now, we genereate the aik. * * We don't got any credentials, so we just use empty byte arrays * here. */ int keyId = highLevel.generateAIK(id, label, ownerpass, srkpass, newkeypass, pubkey, new FileOutputStream(outfile), new byte[0], new byte[0], new byte[0]); System.out.println("Generated new aik request with keyid " + keyId); System.out.println("Request was written to: " + outfile); /* * The privacy ca will need our public EK too. * * Serialize it to a file. */ TssLowlevel lowLevel = TssFactory.getLowlevel(); TPMPubKeyWrapper pubEk = lowLevel.TPM_ReadPubek(); ObjectOutputStream ekous = new ObjectOutputStream( new FileOutputStream(outfile + ".pubEK")); ekous.writeObject(pubEk); ekous.close(); System.out.println("Wrote public EK to: " + outfile + ".pubEK"); } catch (Exception e) { e.printStackTrace(); } } }
We use the command java de.datenzone.tpm4java.examples.GenerateAikRequest myTinyCa ca.dump.id ca.dump.pub foo bar foobar request.dump. This assumes that your ownerPass is foo, the srkPass is bar and the new AIK will be protected with the password foobar. The output should look like:
Generated new aik request with keyid 5335300 Request was written to: request.dump Wrote public EK to: request.dump.pubEK
The keyid is important. Plese remember it for later.
Step 3: Responding to that request
We will now use our ca to respond to this request:
package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import de.datenzone.tpm4java.SimplePrivacyCA; import de.datenzone.tpm4java.TCPAIdentityCredential; import de.datenzone.tpm4java.TCPAIdentityRequest; import de.datenzone.tpm4java.TPMPubKeyWrapper; /** * This example shows how to sign an aik request with your ca. * * @author Erik Tews */ public class SignAikRequest { /** * Generate an response to an request. * * @param args filename where the ca is stored, filename where the request * is stored, filename with the public ek from the request, filename * to write the request to. */ public static void main(String[] args) { String caFile = args[0]; String requestInput = args[1]; String requestEK = args[2]; String requestOutput = args[3]; try { /* * Load the ca from the disk. */ SimplePrivacyCA ca = SimplePrivacyCA.loadCa(caFile); /* * Load the request. */ ObjectInputStream ois = new ObjectInputStream(new FileInputStream( requestInput)); TCPAIdentityRequest request = (TCPAIdentityRequest) ois .readObject(); ois.close(); /* * Load the public part of the EK from the request. */ ois = new ObjectInputStream(new FileInputStream(requestEK)); TPMPubKeyWrapper pubEK = (TPMPubKeyWrapper) ois.readObject(); ois.close(); /* * Generate the response to the request. */ TCPAIdentityCredential response = ca.processIdentityRequest( request, pubEK); /* * Write the response to the disk. */ ObjectOutputStream ous = new ObjectOutputStream( new FileOutputStream(requestOutput)); ous.writeObject(response); ous.close(); System.out.println("wrote response to: " + requestOutput); } catch (Exception e) { e.printStackTrace(); } } }
The command line we use is java de.datenzone.tpm4java.examples.SignAikRequest ca.dump request.dump request.dump.pubEK request.out. The output should look similar to:
wrote response to: request.out
Step 4: Activating the AIK
We will now activate the AIK. The follwing code will do that for us:
package de.datenzone.tpm4java.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import de.datenzone.tpm4java.TCPAIdentityCredential; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; /** * Example, which shows how to process an response from a ca. * * @author Erik Tews */ public class ActivateAik { /** * @param args keyhandle, keypass, onwerpass, filename of ca response, * filename to decrypt response to. */ public static void main(String[] args) { int keyhandle = Integer.parseInt(args[0]); String keypass = args[1]; String ownerpass = args[2]; String responsefile = args[3]; String outputfile = args[4]; try { TssHighLevel highLevel = TssFactory.getHighLevel(); /* * Read the response from the ca into memory. */ ObjectInputStream ois = new ObjectInputStream(new FileInputStream( responsefile)); TCPAIdentityCredential cred = (TCPAIdentityCredential) ois .readObject(); ois.close(); /* * Now, decrypt it, using the TPM. */ byte[] response = highLevel.activateAik(cred, keyhandle, keypass, ownerpass); /* * Write the decrypted informations to the disk. */ FileOutputStream fos = new FileOutputStream(outputfile); fos.write(response); fos.close(); System.out.println("Wrote response to: " + outputfile); } catch (Exception e) { e.printStackTrace(); } } }
We run it with java de.datenzone.tpm4java.examples.ActivateAik 5335300 foobar foo request.out ca.txt. This will use the keyhandle 5335300 which is the keyhandle of our aik. The response will be written to ca.txt.<
The output should look like:
!#text Wrote response to: ca.txt
The contents of ca.txt are now:
You have been officially certified!
Step 4: The attestion
Now, we will attest our configuration.
First, we need a nounce for that. We just use 20 bytes of random. We can generate it on a linux system like that:
dd if=/dev/zero of=nounce.dat bs=20 count=1
Now, we will use the following code to attest the state of registers 0,1,2 and 3 with our just genereated aik.
package de.datenzone.tpm4java.examples; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import de.datenzone.tpm4java.TssFactory; import de.datenzone.tpm4java.TssHighLevel; public class AttestConfiguration { /** * @param args * keyhandle of aik, password for this key, nouncefile, * outputfile. */ public static void main(String[] args) { int keyhanle = Integer.parseInt(args[0]); String password = args[1]; String nouncefile = args[2]; String outputfile = args[3]; int[] pcrs = new int[] { 0, 1, 2, 3 }; try { /* * Read the nounce. */ byte[] nounce = new byte[20]; DataInputStream dis = new DataInputStream(new FileInputStream( nouncefile)); dis.readFully(nounce); dis.close(); TssHighLevel highLevel = TssFactory.getHighLevel(); /* * Compute the result. */ byte[] result = highLevel.attestPcr(pcrs, nounce, keyhanle, password); /* * Write the result to a file. */ FileOutputStream fos = new FileOutputStream(outputfile); fos.write(result); fos.close(); System.out.println("Wrote signed pcrs to file: " + outputfile); } catch (Exception e) { e.printStackTrace(); } } /** * Converts a byte-array to a hexString. * * @param data * The array to convert. * @return A String with the content of the array in hexadecimal * representation. */ public static String toHex(byte[] data) { StringBuffer buf = new StringBuffer(data.length * 2); for (int i = 0; i < data.length; i++) { buf.append(Integer.toHexString((data[i] >>> 4) & 0xf)); buf.append(Integer.toHexString((data[i] & 0xf))); } return new String(buf); } }
We start it using java de.datenzone.tpm4java.examples.AttestConfiguration 5335300 foobar nounce.dat attest.dat. 5335300 is our aik keyhandle, foobar is the password for our aik, nounce.dat contains a nounce from a remote side, and attest.dat will then contain the answer of our TPM.
The output should look like:
Wrote signed pcrs to file: attest.dat
You should now send the attest.dat to the remote side, which requested the attestation.
Summary
Gratulation, you have now done your first remote plattform attestation.
Because there are currently no CAs out there, the format for the requests will be most likely something different from our serialized java objects. You will perhaps not store your keys in the tpm, more likely on the harddisk. And you will need real credentials.
Further reading
After you read this tutorial, you should have a look at the sourcecode of TssHighLevelImpl? which containts a lot of useful examples how to use the low level api.
There is also an junit-test called TSSCoreServiceTest which shows much more examples to nearly every low level command. This is definitly worth reading.
If you still got questions, you can read the other parts of the sourcecode, or ask on our MailingList.
