mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-02-21 02:01:24 +00:00
removed TPM_Utils
This commit is contained in:
parent
c929ee3bb3
commit
fd3bbd26a3
@ -1,45 +0,0 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'checkstyle'
|
||||
apply plugin: 'jacoco'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
dependencies {
|
||||
compile libs.log4j2
|
||||
compile libs.commons_codec
|
||||
compile libs.commons_io
|
||||
compile libs.commons_lang
|
||||
compile libs.spring_core
|
||||
|
||||
testCompile libs.testng
|
||||
}
|
||||
|
||||
ext.configDir = new File(projectDir, 'config')
|
||||
ext.checkstyleConfigDir = "$configDir/checkstyle"
|
||||
|
||||
checkstyle {
|
||||
toolVersion = '5.7'
|
||||
configFile = checkstyleConfigFile
|
||||
configProperties.put('basedir', checkstyleConfigDir)
|
||||
ignoreFailures = false
|
||||
showViolations = true
|
||||
}
|
||||
|
||||
jacocoTestReport {
|
||||
reports {
|
||||
xml.enabled true
|
||||
csv.enabled true
|
||||
html.enabled true
|
||||
html.destination "${buildDir}/reports/jacoco/html"
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
artifactId 'hirs-tpm-utils'
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
|
||||
<suppressions>
|
||||
|
||||
<suppress checks="MagicNumber" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
<suppress checks="FinalParameters" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
<suppress checks="JavadocPackage" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
|
||||
</suppressions>
|
@ -1,60 +0,0 @@
|
||||
package hirs.tpm.tss;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines the functionality of a Tpm as specified in the TCG TSS Specification.
|
||||
*/
|
||||
public interface Tpm {
|
||||
|
||||
/**
|
||||
* Takes ownership of an active but unowned Tpm.
|
||||
*/
|
||||
void takeOwnership();
|
||||
|
||||
/**
|
||||
* Obtain the public Endorsement Credential modulus.
|
||||
*
|
||||
* @return the endorsement credential modulus
|
||||
* @see #collateIdentityRequest(byte[], String)
|
||||
*/
|
||||
byte[] getEndorsementCredentialModulus();
|
||||
|
||||
/**
|
||||
* Obtains the full Endorsement Credential stored in the TPM.
|
||||
* @return the EC on the TPM, if present, otherwise null
|
||||
* @throws IOException if there's an error writing the EC to a temporary file for processing
|
||||
*/
|
||||
byte[] getEndorsementCredential() throws IOException;
|
||||
|
||||
/**
|
||||
* Instructs the Tpm to collate an identity request as stated in the TSS specification.
|
||||
*
|
||||
* @param acaPublicKey non null, ACA PK information.
|
||||
* @param uuid non null, non empty, UUID for the identity.
|
||||
* @return the identity request. to be later attested.
|
||||
*/
|
||||
byte[] collateIdentityRequest(byte[] acaPublicKey, String uuid);
|
||||
|
||||
/**
|
||||
* Activates the identity within the TPM given the label and ACA symmetric and asymmetric
|
||||
* identity response blobs. The return will be the identity credential that is activated within
|
||||
* the TPM.
|
||||
*
|
||||
* @param asymmetricBlob from ACA identity response
|
||||
* @param symmetricBlob from ACA identity response
|
||||
* @param uuid of the identity request
|
||||
* @return the activated identity credential
|
||||
*/
|
||||
byte[] activateIdentity(byte[] asymmetricBlob, byte[] symmetricBlob, String uuid);
|
||||
|
||||
/**
|
||||
* Queries the TPM for quote data given the specified pcrValues using the specified UUID.
|
||||
*
|
||||
* @param pcrValues cannot be null or empty
|
||||
* @param nonce cannot be null or empty
|
||||
* @param uuid cannot be null or empty
|
||||
* @return quote data
|
||||
*/
|
||||
byte[] getQuote(String pcrValues, String nonce, String uuid);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package hirs.tpm.tss.command;
|
||||
|
||||
/**
|
||||
* Exception that is thrown by the {@link CommandTpm} when executing operations.
|
||||
*/
|
||||
public class CommandException extends RuntimeException {
|
||||
|
||||
private CommandResult commandResult;
|
||||
|
||||
/**
|
||||
* Constructs this exception with the specified message and the command result.
|
||||
*
|
||||
* @param message as to why this exception occurred
|
||||
* @param commandResult the result of the command that caused this exception
|
||||
*/
|
||||
public CommandException(final String message, final CommandResult commandResult) {
|
||||
super(message);
|
||||
|
||||
this.commandResult = commandResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link CommandResult} of the command that caused this exception
|
||||
*/
|
||||
public CommandResult getCommandResult() {
|
||||
return this.commandResult;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package hirs.tpm.tss.command;
|
||||
|
||||
/**
|
||||
* Encapsulates the results of executing a command.
|
||||
*/
|
||||
public class CommandResult {
|
||||
|
||||
/**
|
||||
* The exit status when attempting to take ownership of an already owned TPM.
|
||||
*/
|
||||
public static final int TPM_PREVIOUSLY_OWNED_ERROR = 20;
|
||||
|
||||
private String output;
|
||||
|
||||
private int exitStatus;
|
||||
|
||||
/**
|
||||
* Creates the command result with the specified output and exist status.
|
||||
*
|
||||
* @param output of the command
|
||||
* @param exitStatus of the command
|
||||
*/
|
||||
public CommandResult(final String output, final int exitStatus) {
|
||||
this.output = output;
|
||||
this.exitStatus = exitStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return command output.
|
||||
*/
|
||||
public String getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return command exit status.
|
||||
*/
|
||||
public int getExitStatus() {
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
package hirs.tpm.tss.command;
|
||||
|
||||
import hirs.tpm.tss.Tpm;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Implementation of a {@link Tpm} that uses the TPM_MODULE command as the interface to the TPM.
|
||||
*/
|
||||
public class CommandTpm implements Tpm {
|
||||
|
||||
private static final String TPM_COMMAND = "/usr/bin/tpm_module";
|
||||
private static final String TPM_TOOLS_READ_COMMAND = "tpm_nvread";
|
||||
private static final String TPM_TOOLS_INFO_COMMAND = "tpm_nvinfo";
|
||||
|
||||
// The fixed location of the endorsement credential (TPM 1.2 only)
|
||||
private static final int EC_INDEX = 0xf000;
|
||||
private static final int EC_INDEX_MASK = 0x0000ffff;
|
||||
|
||||
private static final String IDENTITY_LABEL = "HISIdentityKey";
|
||||
|
||||
@Override
|
||||
public void takeOwnership() {
|
||||
// take ownership if the TPM is currently unowned
|
||||
try {
|
||||
sendTPMCommand("-nr -m 1 -z");
|
||||
} catch (CommandException ex) {
|
||||
|
||||
// if the error isn't that the TPM is already owned, bubble the exception up.
|
||||
if (ex.getCommandResult().getExitStatus() != CommandResult.TPM_PREVIOUSLY_OWNED_ERROR) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEndorsementCredentialModulus() {
|
||||
return sendTPMCommand("-m 17 -z -nr -t ek").getOutput().getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEndorsementCredential() throws IOException {
|
||||
File tempExtractFile = File.createTempFile("nvread-extract", ".tmp");
|
||||
|
||||
try {
|
||||
int ecIndex = findEndorsementCredentialIndex();
|
||||
int ecSize = getEndorsementCredentialSize(ecIndex);
|
||||
// don't care about the stdout from this command. If the command fails, an exception
|
||||
// is thrown, otherwise, read the temp file content
|
||||
String argList = "-i " + ecIndex
|
||||
+ " -s " + ecSize + " -z -f " + tempExtractFile.getAbsolutePath();
|
||||
|
||||
sendCommand(TPM_TOOLS_READ_COMMAND, argList);
|
||||
return FileUtils.readFileToByteArray(tempExtractFile);
|
||||
} finally {
|
||||
FileUtils.deleteQuietly(tempExtractFile);
|
||||
}
|
||||
}
|
||||
|
||||
private int findEndorsementCredentialIndex() {
|
||||
CommandResult command = sendCommand(TPM_TOOLS_INFO_COMMAND, "");
|
||||
return parseEcIndexFromNvInfoOutput(command.getOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the output from tpm_nvinfo to find the index for the endorsement credential.
|
||||
* @param commandOutput the output of the tpm_nvinfo command
|
||||
* @return the index of the EC
|
||||
*/
|
||||
static int parseEcIndexFromNvInfoOutput(final String commandOutput) {
|
||||
String[] lines = commandOutput.trim().split("\\r?\\n");
|
||||
|
||||
for (String line: lines) {
|
||||
if (line.startsWith("NVRAM index")) {
|
||||
String rawIndex = line.split(":")[1].trim();
|
||||
String hexIndexStr = rawIndex.split(" ")[0];
|
||||
int index = Integer.decode(hexIndexStr);
|
||||
if ((EC_INDEX_MASK & index) == EC_INDEX) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Failed to find index for EC");
|
||||
}
|
||||
|
||||
private int getEndorsementCredentialSize(final int index) {
|
||||
try {
|
||||
String args = "-i " + index;
|
||||
CommandResult command = sendCommand(TPM_TOOLS_INFO_COMMAND, args);
|
||||
return parseNvramSizeFromNvInfoOutput(command.getOutput());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Failed to get EC size: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the output from tpm_nvinfo for a particular address, returning the size of the
|
||||
* data at the queried address.
|
||||
* @param commandOutput the output of a tpm_nvinfo -i [address] command
|
||||
* @return the size at the address, as a decimal integer
|
||||
*/
|
||||
static int parseNvramSizeFromNvInfoOutput(final String commandOutput) {
|
||||
// trim the ends and split on lines.
|
||||
String[] lines = commandOutput.trim().split("\\r?\\n");
|
||||
|
||||
// search lines for the first "Size" line, which contains the # of bytes to
|
||||
// read at the location
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("Size")) {
|
||||
String rawSizeValue = line.split(":")[1].trim();
|
||||
// The value after the ":" contains the decimal and hex values.
|
||||
// Parse out the decimal portion
|
||||
String decimalSizeStr = rawSizeValue.split(" ")[0];
|
||||
return Integer.parseInt(decimalSizeStr);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Failed to find size from EC's NVRAM area");
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] collateIdentityRequest(final byte[] acaPublicKey, final String uuid) {
|
||||
Assert.notNull(acaPublicKey, "acaPublicKey is null");
|
||||
Assert.hasLength(uuid, "uuid must not be empty or null");
|
||||
|
||||
// encode the aca PK to a hex string.
|
||||
String hexAcaBlob = Hex.encodeHexString(acaPublicKey);
|
||||
|
||||
// send the collate identity request
|
||||
String request = sendTPMCommand(
|
||||
String.format("-nr -z -o -m 6 -p %s -u %s -l %s -nvram -debug",
|
||||
hexAcaBlob, uuid, IDENTITY_LABEL)).getOutput();
|
||||
|
||||
try {
|
||||
// attempt to decode the response
|
||||
return Hex.decodeHex(request.toCharArray());
|
||||
} catch (DecoderException e) {
|
||||
throw new RuntimeException(
|
||||
"Encountered error decoding response from tpm_module: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] activateIdentity(final byte[] asymmetricBlob, final byte[] symmetricBlob,
|
||||
final String uuid) {
|
||||
Assert.notNull(asymmetricBlob, "asymmetricBlob is null");
|
||||
Assert.notNull(symmetricBlob, "symmetricBlob is null");
|
||||
Assert.hasLength(uuid, "uuid must not be empty or null");
|
||||
|
||||
// encode the blobs into hex strings
|
||||
String hexAsymmetric = Hex.encodeHexString(asymmetricBlob);
|
||||
String hexSymmetric = Hex.encodeHexString(symmetricBlob);
|
||||
|
||||
// issue the activate identity command
|
||||
CommandResult result = sendTPMCommand(String.format("-asym %s -sym %s -u %s -m 7 -z - nr",
|
||||
hexAsymmetric, hexSymmetric, uuid));
|
||||
|
||||
try {
|
||||
return Hex.decodeHex(result.getOutput().toCharArray());
|
||||
} catch (DecoderException e) {
|
||||
throw new RuntimeException(
|
||||
"Encountered error decoding response from tpm_module: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getQuote(final String pcr, final String nonce, final String uuid) {
|
||||
Assert.hasLength(pcr, "pcr must not be empty or null");
|
||||
Assert.hasLength(nonce, "nonce must not be empty or null");
|
||||
Assert.hasLength(uuid, "uuid must not be empty or null");
|
||||
|
||||
// issues the quote 2 command (-m 9) to retrieve the quote for the selected PCR (-p #).
|
||||
CommandResult result =
|
||||
sendTPMCommand(String.format("-m 9 -z -n %s -c -u %s -p %s", nonce, uuid, pcr));
|
||||
|
||||
try {
|
||||
return Hex.decodeHex(result.getOutput().toCharArray());
|
||||
} catch (DecoderException e) {
|
||||
throw new RuntimeException(
|
||||
"Encountered error decoding response from tpm_module: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private CommandResult sendTPMCommand(final String arguments) {
|
||||
// always run the tpm_module with debug (-d).
|
||||
// otherwise the exit status and error messages are squelched.
|
||||
return sendCommand(TPM_COMMAND, "-d " + arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues the specified command to the tpm_module process.
|
||||
*/
|
||||
private CommandResult sendCommand(final String application, final String arguments) {
|
||||
String[] command = {application};
|
||||
|
||||
// add the specified arguments to the command
|
||||
command = ArrayUtils.addAll(command, arguments.split("\\s+"));
|
||||
|
||||
// build up the process
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
|
||||
// merge the error stream into the standard output
|
||||
processBuilder.redirectErrorStream(true);
|
||||
|
||||
try {
|
||||
// issue the command
|
||||
Process process = processBuilder.start();
|
||||
|
||||
// block and wait for the process to be complete
|
||||
int returnCode = process.waitFor();
|
||||
|
||||
try (InputStream processInputStream = process.getInputStream()) {
|
||||
// grab the command output
|
||||
String output = IOUtils.toString(processInputStream);
|
||||
|
||||
// construct the command result
|
||||
CommandResult result = new CommandResult(output, returnCode);
|
||||
|
||||
// if the command wasn't successful, generate an exception with command output
|
||||
if (returnCode != 0) {
|
||||
throw new CommandException(
|
||||
String.format("Encountered error: %s while executing command: %s",
|
||||
output, StringUtils.join(command, " ")), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Defines command line interface to the TPM/TSS.
|
||||
*/
|
||||
package hirs.tpm.tss.command;
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Defines high level interfaces for communicating and interacting with a TPM.
|
||||
*/
|
||||
package hirs.tpm.tss;
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration>
|
||||
<Appenders>
|
||||
<Console name="STDOUT" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t @ %C.%M] %-5p : %m%n"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="WARN">
|
||||
<AppenderRef ref="STDOUT"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -1,68 +0,0 @@
|
||||
package hirs.tpm.tss.command;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@see CommandTpm}.
|
||||
*/
|
||||
public class CommandTpmTest {
|
||||
|
||||
/**
|
||||
* Tests retrieving the size given a valid output from tpm_nvinfo.
|
||||
*/
|
||||
@Test
|
||||
public void parseSizeValid() {
|
||||
final int expectedSize = 1129;
|
||||
|
||||
String nvInfoOutput =
|
||||
"\n"
|
||||
+ "NVRAM index : 0x1000f000 (268496896)\n"
|
||||
+ "PCR read selection:\n"
|
||||
+ " Localities : ALL\n"
|
||||
+ "PCR write selection:\n"
|
||||
+ " Localities : ALL\n"
|
||||
+ "Permissions : 0x00020002 (OWNERREAD|OWNERWRITE)\n"
|
||||
+ "bReadSTClear : FALSE\n"
|
||||
+ "bWriteSTClear : FALSE\n"
|
||||
+ "bWriteDefine : FALSE\n"
|
||||
+ "Size : 1129 (0x469)\n"
|
||||
+ "\n";
|
||||
|
||||
|
||||
int readSize = CommandTpm.parseNvramSizeFromNvInfoOutput(nvInfoOutput);
|
||||
|
||||
Assert.assertEquals(readSize, expectedSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests failure to get the size given output from tpm_nvinfo with missing size value.
|
||||
*/
|
||||
@Test(expectedExceptions = RuntimeException.class)
|
||||
public void parseSizeMissingSizeValue() {
|
||||
String nvInfoOutput =
|
||||
"\n"
|
||||
+ "NVRAM index : 0x1000f000 (268496896)\n"
|
||||
+ "PCR read selection:\n"
|
||||
+ " Localities : ALL\n"
|
||||
+ "PCR write selection:\n"
|
||||
+ " Localities : ALL\n"
|
||||
+ "Permissions : 0x00020002 (OWNERREAD|OWNERWRITE)\n"
|
||||
+ "bReadSTClear : FALSE\n"
|
||||
+ "bWriteSTClear : FALSE\n"
|
||||
+ "bWriteDefine : FALSE\n"
|
||||
+ "Strength : 1129 (0x469)\n"
|
||||
+ "\n";
|
||||
|
||||
CommandTpm.parseNvramSizeFromNvInfoOutput(nvInfoOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests failure to get the EC size given a completely garbage tpm_nvifo output.
|
||||
*/
|
||||
@Test(expectedExceptions = RuntimeException.class)
|
||||
public void parseSizeBadOutput() {
|
||||
String nvInfoOutput = "bad data here. FAILURE TO READ SOMETHING!";
|
||||
CommandTpm.parseNvramSizeFromNvInfoOutput(nvInfoOutput);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Tests for the TPM command classes.
|
||||
*/
|
||||
package hirs.tpm.tss.command;
|
Loading…
x
Reference in New Issue
Block a user